| Index: packagerSafari.py |
| =================================================================== |
| --- a/packagerSafari.py |
| +++ b/packagerSafari.py |
| @@ -1,16 +1,14 @@ |
| # This Source Code Form is subject to the terms of the Mozilla Public |
| # License, v. 2.0. If a copy of the MPL was not distributed with this |
| # file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| -import base64 |
| import ConfigParser |
| import json |
| -import math |
| import os |
| import re |
| from urlparse import urlparse |
| from packager import readMetadata, getDefaultFileName, getBuildVersion, getTemplate, Files |
| from packagerChrome import convertJS, importGeckoLocales, getIgnoredFiles, getPackageFiles, defaultLocale, createScriptPage |
| @@ -106,31 +104,16 @@ def fixAbsoluteUrls(files): |
| if os.path.splitext(filename)[1].lower() == '.html': |
| files[filename] = re.sub( |
| r'(<[^<>]*?\b(?:href|src)\s*=\s*["\']?)\/+', |
| r'\1' + '/'.join(['..'] * filename.count('/') + ['']), |
| content, re.S | re.I |
| ) |
| -def get_certificates_and_key(keyfile): |
| - from Crypto.PublicKey import RSA |
| - |
| - certs = [] |
| - with open(keyfile, 'r') as file: |
| - data = file.read() |
| - keydata = re.sub(r'(-+END PRIVATE KEY-+).*', r'\1', data, flags=re.S) |
| - key = RSA.importKey(keydata) |
| - |
| - for match in re.finditer(r'-+BEGIN CERTIFICATE-+(.*?)-+END CERTIFICATE-+', data, re.S): |
| - certs.append(base64.b64decode(match.group(1))) |
| - |
| - return certs, key |
| - |
| - |
| def get_developer_identifier(certs): |
| from Crypto.Util import asn1 |
| def get_sequence(data): |
| sequence = asn1.DerSequence() |
| sequence.decode(data) |
| return sequence |
| for cert in certs: |
| @@ -142,102 +125,16 @@ def get_developer_identifier(certs): |
| # expression on CN entry anyway we can just skip that. |
| m = re.search(r'Safari Developer: \((\S*?)\)', subject) |
| if m: |
| return m.group(1) |
| raise Exception('No Safari developer certificate found in chain') |
| -def sign_digest(key, digest): |
| - from Crypto.Hash import SHA |
| - from Crypto.Signature import PKCS1_v1_5 |
| - |
| - # xar already calculated the SHA1 digest so we have to fake hashing here. |
| - class FakeHash(SHA.SHA1Hash): |
| - def digest(self): |
| - return digest |
| - |
| - return PKCS1_v1_5.new(key).sign(FakeHash()) |
| - |
| - |
| -def createSignedXarArchive(outFile, files, certs, key): |
| - import subprocess |
| - import tempfile |
| - import shutil |
| - |
| - # write files to temporary directory and create a xar archive |
| - dirname = tempfile.mkdtemp() |
| - try: |
| - for filename, contents in files.iteritems(): |
| - path = os.path.join(dirname, filename) |
| - |
| - try: |
| - os.makedirs(os.path.dirname(path)) |
| - except OSError: |
| - pass |
| - |
| - with open(path, 'wb') as file: |
| - file.write(contents) |
| - |
| - subprocess.check_output( |
| - ['xar', '-czf', os.path.abspath(outFile), '--distribution'] + os.listdir(dirname), |
| - cwd=dirname |
| - ) |
| - finally: |
| - shutil.rmtree(dirname) |
| - |
| - certificate_filenames = [] |
| - try: |
| - # write each certificate in DER format to a separate |
| - # temporary file, that they can be passed to xar |
| - for cert in certs: |
| - fd, filename = tempfile.mkstemp() |
| - try: |
| - certificate_filenames.append(filename) |
| - os.write(fd, cert) |
| - finally: |
| - os.close(fd) |
| - |
| - # add certificates and placeholder signature |
| - # to the xar archive, and get data to sign |
| - fd, digest_filename = tempfile.mkstemp() |
| - os.close(fd) |
| - try: |
| - subprocess.check_call( |
| - [ |
| - 'xar', '--sign', '-f', outFile, |
| - '--data-to-sign', digest_filename, |
| - '--sig-size', str(len(sign_digest(key, ''))) |
| - ] + [ |
| - arg for cert in certificate_filenames for arg in ('--cert-loc', cert) |
| - ] |
| - ) |
| - |
| - with open(digest_filename, 'rb') as file: |
| - digest = file.read() |
| - finally: |
| - os.unlink(digest_filename) |
| - finally: |
| - for filename in certificate_filenames: |
| - os.unlink(filename) |
| - |
| - # sign data and inject signature into xar archive |
| - fd, signature_filename = tempfile.mkstemp() |
| - try: |
| - try: |
| - os.write(fd, sign_digest(key, digest)) |
| - finally: |
| - os.close(fd) |
| - |
| - subprocess.check_call(['xar', '--inject-sig', signature_filename, '-f', outFile]) |
| - finally: |
| - os.unlink(signature_filename) |
| - |
| - |
| def createBuild(baseDir, type, outFile=None, buildNum=None, releaseBuild=False, keyFile=None, devenv=False): |
| metadata = readMetadata(baseDir, type) |
| version = getBuildVersion(baseDir, metadata, releaseBuild, buildNum) |
| if not outFile: |
| outFile = getDefaultFileName(metadata, version, 'safariextz' if keyFile else 'zip') |
| params = { |
| @@ -267,26 +164,28 @@ def createBuild(baseDir, type, outFile=N |
| if metadata.has_section('import_locales'): |
| importGeckoLocales(params, files) |
| if metadata.has_option('general', 'testScripts'): |
| files['qunit/index.html'] = createScriptPage(params, 'testIndex.html.tmpl', |
| ('general', 'testScripts')) |
| if keyFile: |
| - certs, key = get_certificates_and_key(keyFile) |
| + from buildtools import xarfile |
| + certs = xarfile.read_certificates(keyFile) |
| params['developerIdentifier'] = get_developer_identifier(certs) |
| files['lib/info.js'] = createInfoModule(params) |
| files['background.html'] = createScriptPage(params, 'background.html.tmpl', |
| ('general', 'backgroundScripts')) |
| files['Info.plist'] = createManifest(params, files) |
| fixAbsoluteUrls(files) |
| dirname = metadata.get('general', 'basename') + '.safariextension' |
| for filename in files.keys(): |
| files[os.path.join(dirname, filename)] = files.pop(filename) |
| if not devenv and keyFile: |
| - createSignedXarArchive(outFile, files, certs, key) |
| + from buildtools import xarfile |
| + xarfile.create(outFile, files, keyFile) |
| else: |
| files.zip(outFile) |