mirror of
				https://github.com/kovidgoyal/calibre.git
				synced 2025-11-04 03:27:00 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			106 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
#!/usr/bin/env python
 | 
						|
# vim:fileencoding=utf-8
 | 
						|
# License: GPLv3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
 | 
						|
 | 
						|
import os
 | 
						|
import plistlib
 | 
						|
from glob import glob
 | 
						|
 | 
						|
from bypy.macos_sign import codesign, create_entitlements_file, make_certificate_useable, notarize_app, verify_signature
 | 
						|
from bypy.utils import current_dir
 | 
						|
 | 
						|
entitlements = {
 | 
						|
    # MAP_JIT is used by libpcre which is bundled with Qt
 | 
						|
    'com.apple.security.cs.allow-jit': True,
 | 
						|
 | 
						|
    # v8 and therefore WebEngine need this as they don't use MAP_JIT
 | 
						|
    'com.apple.security.cs.allow-unsigned-executable-memory': True,
 | 
						|
 | 
						|
    # calibre itself does not use DYLD env vars, but don't know about its
 | 
						|
    # dependencies.
 | 
						|
    'com.apple.security.cs.allow-dyld-environment-variables': True,
 | 
						|
 | 
						|
    # Allow loading of unsigned plugins or frameworks
 | 
						|
    # 'com.apple.security.cs.disable-library-validation': True,
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
def files_in(folder):
 | 
						|
    for record in os.walk(folder):
 | 
						|
        for f in record[-1]:
 | 
						|
            yield os.path.join(record[0], f)
 | 
						|
 | 
						|
 | 
						|
def expand_dirs(items, exclude=lambda x: x.endswith('.so')):
 | 
						|
    items = set(items)
 | 
						|
    dirs = set(x for x in items if os.path.isdir(x))
 | 
						|
    items.difference_update(dirs)
 | 
						|
    for x in dirs:
 | 
						|
        items.update({y for y in files_in(x) if not exclude(y)})
 | 
						|
    return items
 | 
						|
 | 
						|
 | 
						|
def get_executable(info_path):
 | 
						|
    with open(info_path, 'rb') as f:
 | 
						|
        return plistlib.load(f)['CFBundleExecutable']
 | 
						|
 | 
						|
 | 
						|
def find_sub_apps(contents_dir='.'):
 | 
						|
    for app in glob(os.path.join(contents_dir, '*.app')):
 | 
						|
        cdir = os.path.join(app, 'Contents')
 | 
						|
        for sapp in find_sub_apps(cdir):
 | 
						|
            yield sapp
 | 
						|
        yield app
 | 
						|
 | 
						|
 | 
						|
def sign_MacOS(contents_dir='.'):
 | 
						|
    # Sign everything in MacOS except the main executable
 | 
						|
    # which will be signed automatically by codesign when
 | 
						|
    # signing the app bundles
 | 
						|
    with current_dir(os.path.join(contents_dir, 'MacOS')):
 | 
						|
        exe = get_executable('../Info.plist')
 | 
						|
        items = {x for x in os.listdir('.') if x != exe and not os.path.islink(x)}
 | 
						|
        if items:
 | 
						|
            codesign(items)
 | 
						|
 | 
						|
 | 
						|
def do_sign_app(appdir):
 | 
						|
    appdir = os.path.abspath(appdir)
 | 
						|
    with current_dir(os.path.join(appdir, 'Contents')):
 | 
						|
        sign_MacOS()
 | 
						|
        # Sign the sub application bundles
 | 
						|
        sub_apps = list(find_sub_apps())
 | 
						|
        sub_apps.append('Frameworks/QtWebEngineCore.framework/Versions/Current/Helpers/QtWebEngineProcess.app')
 | 
						|
        for sa in sub_apps:
 | 
						|
            sign_MacOS(os.path.join(sa, 'Contents'))
 | 
						|
        codesign(sub_apps)
 | 
						|
 | 
						|
        # Sign all .so files
 | 
						|
        so_files = {x for x in files_in('.') if x.endswith('.so')}
 | 
						|
        codesign(so_files)
 | 
						|
 | 
						|
        # Sign everything in PlugIns
 | 
						|
        with current_dir('PlugIns'):
 | 
						|
            items = set(os.listdir('.'))
 | 
						|
            codesign(expand_dirs(items))
 | 
						|
 | 
						|
        # Sign everything else in Frameworks
 | 
						|
        with current_dir('Frameworks'):
 | 
						|
            fw = set(glob('*.framework'))
 | 
						|
            codesign(fw)
 | 
						|
            items = set(os.listdir('.')) - fw
 | 
						|
            codesign(expand_dirs(items))
 | 
						|
 | 
						|
    # Now sign the main app
 | 
						|
    codesign(appdir)
 | 
						|
    verify_signature(appdir)
 | 
						|
    return 0
 | 
						|
 | 
						|
 | 
						|
def sign_app(appdir, notarize):
 | 
						|
    create_entitlements_file(entitlements)
 | 
						|
    with make_certificate_useable():
 | 
						|
        do_sign_app(appdir)
 | 
						|
        if notarize:
 | 
						|
            notarize_app(appdir, 'calibre')
 |