| LEFT | RIGHT |
| 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 sys | 5 import errno |
| 6 import io |
| 7 import json |
| 6 import os | 8 import os |
| 7 import re | 9 import re |
| 8 import json | 10 from StringIO import StringIO |
| 9 import struct | 11 import struct |
| 10 import io | 12 import sys |
| 11 from StringIO import StringIO | 13 import collections |
| 12 | 14 |
| 13 from packager import (readMetadata, getDefaultFileName, getBuildVersion, | 15 from packager import (readMetadata, getDefaultFileName, getBuildVersion, |
| 14 getTemplate, Files) | 16 getTemplate, Files) |
| 15 | 17 |
| 16 defaultLocale = 'en_US' | 18 defaultLocale = 'en_US' |
| 17 | 19 |
| 18 | 20 |
| 19 def getIgnoredFiles(params): | 21 def getIgnoredFiles(params): |
| 20 return {'store.description'} | 22 return {'store.description'} |
| 21 | 23 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 | 137 |
| 136 return manifest.encode('utf-8') | 138 return manifest.encode('utf-8') |
| 137 | 139 |
| 138 | 140 |
| 139 def createInfoModule(params): | 141 def createInfoModule(params): |
| 140 template = getTemplate('chromeInfo.js.tmpl') | 142 template = getTemplate('chromeInfo.js.tmpl') |
| 141 return template.render(params).encode('utf-8') | 143 return template.render(params).encode('utf-8') |
| 142 | 144 |
| 143 | 145 |
| 144 def convertJS(params, files): | 146 def convertJS(params, files): |
| 145 from jshydra.abp_rewrite import doRewrite | 147 from jshydra.abp_rewrite import rewrite_js |
| 148 |
| 149 output_files = collections.OrderedDict() |
| 150 args = collections.defaultdict(list) |
| 146 | 151 |
| 147 for item in params['metadata'].items('convert_js'): | 152 for item in params['metadata'].items('convert_js'): |
| 148 file, sources = item | 153 filename, arg = re.search(r'^(.*?)(?:\[(.*)\])?$', item[0]).groups() |
| 149 baseDir = os.path.dirname(item.source) | 154 if arg is None: |
| 150 | 155 output_files[filename] = (item[1].split(), item.source) |
| 151 # Make sure the file is inside an included directory | 156 else: |
| 152 if '/' in file and not files.isIncluded(file): | 157 args[filename].append('{}={}'.format(arg, item[1])) |
| 153 continue | 158 |
| 154 | 159 for filename, (input_files, origin) in output_files.iteritems(): |
| 155 sourceFiles = sources.split() | 160 if '/' in filename and not files.isIncluded(filename): |
| 156 args = [] | 161 continue |
| 157 try: | 162 |
| 158 argsStart = sourceFiles.index('--arg') | 163 base_dir = os.path.dirname(origin) |
| 159 args = sourceFiles[argsStart + 1:] | 164 jshydra_args = ['--arg', ' '.join(args[filename])] |
| 160 sourceFiles = sourceFiles[0:argsStart] | 165 |
| 161 except ValueError: | 166 for input_filename in input_files: |
| 162 pass | 167 jshydra_args.append(os.path.join(base_dir, input_filename)) |
| 163 | 168 files.pop(input_filename, None) |
| 164 # Source files of the conversion shouldn't be part of the build | 169 |
| 165 for sourceFile in sourceFiles: | 170 files[filename] = rewrite_js(jshydra_args) |
| 166 if sourceFile in files: | |
| 167 del files[sourceFile] | |
| 168 | |
| 169 sourceFiles = map(lambda f: os.path.abspath(os.path.join(baseDir, f)), s
ourceFiles) | |
| 170 files[file] = doRewrite(sourceFiles, args) | |
| 171 | 171 |
| 172 | 172 |
| 173 def toJson(data): | 173 def toJson(data): |
| 174 return json.dumps( | 174 return json.dumps( |
| 175 data, ensure_ascii=False, sort_keys=True, | 175 data, ensure_ascii=False, sort_keys=True, |
| 176 indent=2, separators=(',', ': ') | 176 indent=2, separators=(',', ': ') |
| 177 ).encode('utf-8') + '\n' | 177 ).encode('utf-8') + '\n' |
| 178 | 178 |
| 179 | 179 |
| 180 def importGeckoLocales(params, files): | 180 def importGeckoLocales(params, files): |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 # Remove access keys | 245 # Remove access keys |
| 246 value = sourceData[stringID] | 246 value = sourceData[stringID] |
| 247 match = re.search(r'^(.*?)\s*\(&.\)$', value) | 247 match = re.search(r'^(.*?)\s*\(&.\)$', value) |
| 248 if match: | 248 if match: |
| 249 value = match.group(1) | 249 value = match.group(1) |
| 250 else: | 250 else: |
| 251 index = value.find('&') | 251 index = value.find('&') |
| 252 if index >= 0: | 252 if index >= 0: |
| 253 value = value[0:index] + value[index + 1:] | 253 value = value[0:index] + value[index + 1:] |
| 254 data[key] = {'message': value} | 254 data[key] = {'message': value} |
| 255 except Exception, e: | 255 except Exception as e: |
| 256 print 'Warning: error importing locale data from %s: %s' % (sour
ceFile, e) | 256 print 'Warning: error importing locale data from %s: %s' % (sour
ceFile, e) |
| 257 | 257 |
| 258 files[targetFile] = toJson(data) | 258 files[targetFile] = toJson(data) |
| 259 | 259 |
| 260 | 260 |
| 261 def truncate(text, length_limit): | 261 def truncate(text, length_limit): |
| 262 if len(text) <= length_limit: | 262 if len(text) <= length_limit: |
| 263 return text | 263 return text |
| 264 return text[:length_limit - 1].rstrip() + u'\u2026' | 264 return text[:length_limit - 1].rstrip() + u'\u2026' |
| 265 | 265 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 288 data = json.loads(files[filename]) | 288 data = json.loads(files[filename]) |
| 289 for name, info in defaults.iteritems(): | 289 for name, info in defaults.iteritems(): |
| 290 data.setdefault(name, info) | 290 data.setdefault(name, info) |
| 291 for name, limit in limits.iteritems(): | 291 for name, limit in limits.iteritems(): |
| 292 if name in data: | 292 if name in data: |
| 293 data[name]['message'] = truncate(data[name]['message'], limit) | 293 data[name]['message'] = truncate(data[name]['message'], limit) |
| 294 files[filename] = toJson(data) | 294 files[filename] = toJson(data) |
| 295 | 295 |
| 296 | 296 |
| 297 def signBinary(zipdata, keyFile): | 297 def signBinary(zipdata, keyFile): |
| 298 import M2Crypto | 298 from Crypto.Hash import SHA |
| 299 if not os.path.exists(keyFile): | 299 from Crypto.PublicKey import RSA |
| 300 M2Crypto.RSA.gen_key(1024, 65537, callback=lambda x: None).save_key(keyF
ile, cipher=None) | 300 from Crypto.Signature import PKCS1_v1_5 |
| 301 key = M2Crypto.EVP.load_key(keyFile) | 301 |
| 302 key.sign_init() | 302 try: |
| 303 key.sign_update(zipdata) | 303 with open(keyFile, 'rb') as file: |
| 304 return key.final() | 304 key = RSA.importKey(file.read()) |
| 305 except IOError as e: |
| 306 if e.errno != errno.ENOENT: |
| 307 raise |
| 308 key = RSA.generate(2048) |
| 309 with open(keyFile, 'wb') as file: |
| 310 file.write(key.exportKey('PEM')) |
| 311 |
| 312 return PKCS1_v1_5.new(key).sign(SHA.new(zipdata)) |
| 305 | 313 |
| 306 | 314 |
| 307 def getPublicKey(keyFile): | 315 def getPublicKey(keyFile): |
| 308 import M2Crypto | 316 from Crypto.PublicKey import RSA |
| 309 return M2Crypto.EVP.load_key(keyFile).as_der() | 317 with open(keyFile, 'rb') as file: |
| 318 return RSA.importKey(file.read()).publickey().exportKey('DER') |
| 310 | 319 |
| 311 | 320 |
| 312 def writePackage(outputFile, pubkey, signature, zipdata): | 321 def writePackage(outputFile, pubkey, signature, zipdata): |
| 313 if isinstance(outputFile, basestring): | 322 if isinstance(outputFile, basestring): |
| 314 file = open(outputFile, 'wb') | 323 file = open(outputFile, 'wb') |
| 315 else: | 324 else: |
| 316 file = outputFile | 325 file = outputFile |
| 317 if pubkey != None and signature != None: | 326 if pubkey != None and signature != None: |
| 318 file.write(struct.pack('<4sIII', 'Cr24', 2, len(pubkey), len(signature))
) | 327 file.write(struct.pack('<4sIII', 'Cr24', 2, len(pubkey), len(signature))
) |
| 319 file.write(pubkey) | 328 file.write(pubkey) |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 files['qunit/index.html'] = createScriptPage(params, 'testIndex.html.tmp
l', | 384 files['qunit/index.html'] = createScriptPage(params, 'testIndex.html.tmp
l', |
| 376 ('general', 'testScripts')) | 385 ('general', 'testScripts')) |
| 377 | 386 |
| 378 zipdata = files.zipToString() | 387 zipdata = files.zipToString() |
| 379 signature = None | 388 signature = None |
| 380 pubkey = None | 389 pubkey = None |
| 381 if keyFile != None: | 390 if keyFile != None: |
| 382 signature = signBinary(zipdata, keyFile) | 391 signature = signBinary(zipdata, keyFile) |
| 383 pubkey = getPublicKey(keyFile) | 392 pubkey = getPublicKey(keyFile) |
| 384 writePackage(outFile, pubkey, signature, zipdata) | 393 writePackage(outFile, pubkey, signature, zipdata) |
| LEFT | RIGHT |