| OLD | NEW |
| 1 # This Source Code Form is subject to the terms of the Mozilla Public | 1 # This Source Code Form is subject to the terms of the Mozilla Public |
| 2 # License, v. 2.0. If a copy of the MPL was not distributed with this | 2 # License, v. 2.0. If a copy of the MPL was not distributed with this |
| 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. | 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 4 | 4 |
| 5 import base64 | 5 import base64 |
| 6 import hashlib | 6 import hashlib |
| 7 import json | 7 import json |
| 8 import mimetypes | 8 import mimetypes |
| 9 import os | 9 import os |
| 10 import zipfile | 10 import zipfile |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 | 40 |
| 41 def _make_blockmap_entry(filename, data): | 41 def _make_blockmap_entry(filename, data): |
| 42 blocks = [data[i:i + BLOCKSIZE] for i in range(0, len(data), BLOCKSIZE)] | 42 blocks = [data[i:i + BLOCKSIZE] for i in range(0, len(data), BLOCKSIZE)] |
| 43 return { | 43 return { |
| 44 'name': filename.replace('/', '\\'), | 44 'name': filename.replace('/', '\\'), |
| 45 'size': len(data), | 45 'size': len(data), |
| 46 'lfh_size': _lfh_size(filename), | 46 'lfh_size': _lfh_size(filename), |
| 47 'blocks': [ | 47 'blocks': [ |
| 48 {'hash': base64.b64encode(hashlib.sha256(block).digest())} | 48 {'hash': base64.b64encode(hashlib.sha256(block).digest())} |
| 49 for block in blocks | 49 for block in blocks |
| 50 ] | 50 ], |
| 51 } | 51 } |
| 52 | 52 |
| 53 | 53 |
| 54 def create_appx_blockmap(files): | 54 def create_appx_blockmap(files): |
| 55 """Create APPX blockmap for the list of files.""" | 55 """Create APPX blockmap for the list of files.""" |
| 56 # We don't support AppxBlockmap.xml generation for compressed zip files at | 56 # We don't support AppxBlockmap.xml generation for compressed zip files at |
| 57 # the moment. The only way to reliably calculate the compressed size of | 57 # the moment. The only way to reliably calculate the compressed size of |
| 58 # each 64k chunk in the zip file is to override the relevant parts of | 58 # each 64k chunk in the zip file is to override the relevant parts of |
| 59 # `zipfile` library. We have chosen to not do it so we produce an | 59 # `zipfile` library. We have chosen to not do it so we produce an |
| 60 # uncompressed zip file that is later repackaged by Windows Store with | 60 # uncompressed zip file that is later repackaged by Windows Store with |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 names = sorted(files.keys(), key=len, reverse=True) | 124 names = sorted(files.keys(), key=len, reverse=True) |
| 125 for filename in names: | 125 for filename in names: |
| 126 files['{}/{}'.format(EXTENSION_DIR, filename)] = files.pop(filename) | 126 files['{}/{}'.format(EXTENSION_DIR, filename)] = files.pop(filename) |
| 127 | 127 |
| 128 | 128 |
| 129 def create_content_types_map(filenames): | 129 def create_content_types_map(filenames): |
| 130 """Create [Content_Types].xml -- a mime type map.""" | 130 """Create [Content_Types].xml -- a mime type map.""" |
| 131 params = {'defaults': {}, 'overrides': {}} | 131 params = {'defaults': {}, 'overrides': {}} |
| 132 overrides = { | 132 overrides = { |
| 133 BLOCKMAP: 'application/vnd.ms-appx.blockmap+xml', | 133 BLOCKMAP: 'application/vnd.ms-appx.blockmap+xml', |
| 134 MANIFEST: 'application/vnd.ms-appx.manifest+xml' | 134 MANIFEST: 'application/vnd.ms-appx.manifest+xml', |
| 135 } | 135 } |
| 136 types = mimetypes.MimeTypes() | 136 types = mimetypes.MimeTypes() |
| 137 types.add_type('application/octet-stream', '.otf') | 137 types.add_type('application/octet-stream', '.otf') |
| 138 for filename in filenames: | 138 for filename in filenames: |
| 139 ext = os.path.splitext(filename)[1] | 139 ext = os.path.splitext(filename)[1] |
| 140 if ext: | 140 if ext: |
| 141 content_type = types.guess_type(filename, strict=False)[0] | 141 content_type = types.guess_type(filename, strict=False)[0] |
| 142 if content_type is not None: | 142 if content_type is not None: |
| 143 params['defaults'][ext[1:]] = content_type | 143 params['defaults'][ext[1:]] = content_type |
| 144 if filename in overrides: | 144 if filename in overrides: |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 for name, path in metadata.items('appx_assets'): | 197 for name, path in metadata.items('appx_assets'): |
| 198 path = os.path.join(baseDir, path) | 198 path = os.path.join(baseDir, path) |
| 199 files.read(path, '{}/{}'.format(ASSETS_DIR, name)) | 199 files.read(path, '{}/{}'.format(ASSETS_DIR, name)) |
| 200 | 200 |
| 201 files[MANIFEST] = create_appx_manifest(params, files, | 201 files[MANIFEST] = create_appx_manifest(params, files, |
| 202 buildNum, releaseBuild) | 202 buildNum, releaseBuild) |
| 203 files[BLOCKMAP] = create_appx_blockmap(files) | 203 files[BLOCKMAP] = create_appx_blockmap(files) |
| 204 files[CONTENT_TYPES] = create_content_types_map(files.keys() + [BLOCKMAP]) | 204 files[CONTENT_TYPES] = create_content_types_map(files.keys() + [BLOCKMAP]) |
| 205 | 205 |
| 206 files.zip(outfile, compression=zipfile.ZIP_STORED) | 206 files.zip(outfile, compression=zipfile.ZIP_STORED) |
| OLD | NEW |