def _runtime(args): '''Generate runtime package separately.''' capsule = DEFAULT_CAPSULE name = 'pytransform_bootstrap' output = os.path.join(args.output, name) if args.inside else args.output package = not args.no_package platforms = compatible_platform_names(args.platforms) suffix = get_name_suffix() if args.enable_suffix else '' make_runtime(capsule, output, licfile=args.with_license, platforms=platforms, package=package, suffix=suffix, restrict=False) filename = os.path.join(output, '__init__.py') if args.inside else \ os.path.join(args.output, name + '.py') logging.info('Generating bootstrap script ...') make_bootstrap_script(filename, capsule=capsule, suffix=suffix) logging.info('Generating bootstrap script %s OK', filename)
def _obfuscate(args): '''Obfuscate scripts without project.''' platforms = compatible_platform_names(args.platforms) if platforms: logging.info('Target platforms: %s', platforms) if check_cross_platform(platforms) is not False: return for x in ('entry', 'cross-protection'): if getattr(args, x.replace('-', '_')) is not None: logging.warning('Option --%s has been deprecated', x) if args.src is None: if args.scripts[0].lower().endswith('.py'): path = os.path.abspath(os.path.dirname(args.scripts[0])) else: path = os.path.abspath(args.scripts[0]) args.src = path if len(args.scripts) > 1: raise RuntimeError('Only one path is allowed') args.scripts = [] else: for s in args.scripts: if not s.lower().endswith('.py'): raise RuntimeError('Only one path is allowed') path = os.path.abspath(args.src) if not args.exact and len(args.scripts) > 1: raise RuntimeError('Two many entry scripts, only one is allowed') if not os.path.exists(path): raise RuntimeError('Not found source path: %s' % path) logging.info('Source path is "%s"', path) entries = [args.entry] if args.entry else args.scripts logging.info('Entry scripts are %s', entries) capsule = args.capsule if args.capsule else DEFAULT_CAPSULE if os.path.exists(capsule): logging.info('Use cached capsule %s', capsule) else: logging.info('Generate capsule %s', capsule) make_capsule(capsule) output = args.output if os.path.abspath(output) == path: raise RuntimeError('Output path can not be same as src') suffix = get_name_suffix() if args.enable_suffix else '' if args.recursive: logging.info('Recursive mode is on') pats = ['global-include *.py'] if args.exclude: for item in args.exclude: for x in item.split(','): if x.endswith('.py'): logging.info('Exclude pattern "%s"', x) pats.append('exclude %s' % x) else: logging.info('Exclude path "%s"', x) pats.append('prune %s' % x) if os.path.abspath(output).startswith(path): x = os.path.abspath(output)[len(path):].strip('/\\') pats.append('prune %s' % x) logging.info('Auto exclude output path "%s"', x) if hasattr('', 'decode'): pats = [p.decode() for p in pats] files = Project.build_manifest(pats, path) elif args.exact: logging.info('Exact mode is on') files = [os.path.abspath(x) for x in args.scripts] else: logging.info('Normal mode is on') files = Project.build_globfiles(['*.py'], path) logging.info('Save obfuscated scripts to "%s"', output) if not os.path.exists(output): os.makedirs(output) logging.info('Read public key from capsule') prokey = get_product_key(capsule) logging.info('Obfuscate scripts with default mode') cross_protection = 0 if args.no_cross_protection else \ 1 if args.cross_protection is None else args.cross_protection advanced = 1 if args.advanced else 0 logging.info('Advanced mode is %d', advanced) restrict = args.restrict logging.info('Restrict mode is %d', restrict) n = args.bootstrap_code relative = True if n == 3 else False if n == 2 else None bootstrap = (not args.no_bootstrap) and n elist = [os.path.abspath(x) for x in entries] for x in sorted(files): if os.path.isabs(x): a, b = x, os.path.join(output, os.path.basename(x)) else: a, b = os.path.join(path, x), os.path.join(output, x) logging.info('\t%s -> %s', x, relpath(b)) is_entry = os.path.abspath(a) in elist protection = is_entry and cross_protection plugins = search_plugins(args.plugins) d = os.path.dirname(b) if not os.path.exists(d): os.makedirs(d) vmode = advanced | (8 if is_entry else 0) encrypt_script(prokey, a, b, adv_mode=vmode, rest_mode=restrict, protection=protection, platforms=platforms, plugins=plugins, suffix=suffix) if is_entry and bootstrap: name = os.path.abspath(a)[len(path)+1:] make_entry(name, path, output, relative=relative, suffix=suffix) logging.info('%d scripts have been obfuscated', len(files)) if args.no_runtime: logging.info('Obfuscate %d scripts OK.', len(files)) return package = args.package_runtime make_runtime(capsule, output, platforms=platforms, package=package, suffix=suffix) logging.info('Obfuscate scripts with restrict mode %s', 'on' if args.restrict else 'off') if not args.restrict: licode = '*FLAGS:%c*CODE:PyArmor-Project' % chr(1) licpath = (os.path.join(output, 'pytransform' + suffix) if package else output) licfile = os.path.join(licpath, license_filename) logging.info('Generate no restrict mode license file: %s', licfile) make_license_key(capsule, licode, licfile) logging.info('Obfuscate %d scripts OK.', len(files))
def _build(args): '''Build project, obfuscate all scripts in the project.''' project = Project() project.open(args.project) logging.info('Build project %s ...', args.project) logging.info('Check project') project.check() suffix = get_name_suffix() if project.get('enable_suffix', 0) else '' capsule = project.get('capsule', DEFAULT_CAPSULE) logging.info('Use capsule: %s', capsule) output = project.output if args.output is None \ else os.path.normpath(args.output) logging.info('Output path is: %s', output) if args.platforms: platforms = [] if '' in args.platforms else args.platforms elif project.get('platform'): platforms = project.get('platform').split(',') else: platforms = [] if platforms: platforms = compatible_platform_names(platforms) logging.info('Taget platforms: %s', platforms) if check_cross_platform(platforms) is not False: return restrict = project.get('restrict_mode', 0 if project.get('disable_restrict_mode') else 1) if not args.only_runtime: src = project.src if os.path.abspath(output).startswith(src): excludes = ['prune %s' % os.path.abspath(output)[len(src)+1:]] else: excludes = [] files = project.get_build_files(args.force, excludes=excludes) soutput = os.path.join(output, os.path.basename(src)) \ if project.get('is_package') else output logging.info('Save obfuscated scripts to "%s"', soutput) if not os.path.exists(soutput): os.makedirs(soutput) logging.info('Read public key from capsule') prokey = get_product_key(capsule) logging.info('%s increment build', 'Disable' if args.force else 'Enable') logging.info('Search scripts from %s', src) logging.info('Obfuscate scripts with mode:') if hasattr(project, 'obf_mod'): obf_mod = project.obf_mod else: obf_mod = project.obf_module_mode == 'des' if hasattr(project, 'wrap_mode'): wrap_mode = project.wrap_mode obf_code = project.obf_code elif project.obf_code_mode == 'wrap': wrap_mode = 1 obf_code = 1 else: wrap_mode = 0 obf_code = 0 if project.obf_code_mode == 'none' else 1 adv_mode = (1 if project.advanced_mode else 0) \ if hasattr(project, 'advanced_mode') else 0 def v(t): return 'on' if t else 'off' logging.info('Obfuscating the whole module is %s', v(obf_mod)) logging.info('Obfuscating each function is %s', v(obf_code)) logging.info('Autowrap each code object mode is %s', v(wrap_mode)) logging.info('Advanced mode is %s', v(adv_mode)) logging.info('Restrict mode is %s', restrict) entries = [build_path(s.strip(), project.src) for s in project.entry.split(',')] if project.entry else [] protection = project.cross_protection \ if hasattr(project, 'cross_protection') else 1 for x in sorted(files): a, b = os.path.join(src, x), os.path.join(soutput, x) logging.info('\t%s -> %s', x, relpath(b)) d = os.path.dirname(b) if not os.path.exists(d): os.makedirs(d) if hasattr(project, 'plugins'): plugins = search_plugins(project.plugins) else: plugins = None if entries and (os.path.abspath(a) in entries): vmode = adv_mode | 8 pcode = protection else: vmode = adv_mode pcode = 0 encrypt_script(prokey, a, b, obf_code=obf_code, obf_mod=obf_mod, wrap_mode=wrap_mode, adv_mode=vmode, rest_mode=restrict, protection=pcode, platforms=platforms, plugins=plugins, rpath=project.runtime_path, suffix=suffix) logging.info('%d scripts has been obfuscated', len(files)) project['build_time'] = time.time() project.save(args.project) if project.entry and project.get('bootstrap_code', 1): soutput = os.path.join(output, os.path.basename(project.src)) \ if project.get('is_package') else output n = project.get('bootstrap_code', 1) relative = True if n == 3 else \ False if (n == 2 or (args.no_runtime and n == 1)) else None make_entry(project.entry, project.src, soutput, rpath=project.runtime_path, relative=relative, suffix=suffix) if not args.no_runtime: routput = output if args.output is not None and args.only_runtime \ else os.path.join(output, os.path.basename(project.src)) \ if project.get('is_package') else output if not os.path.exists(routput): logging.info('Make path: %s', routput) os.mkdir(routput) package = project.get('package_runtime', 0) \ if args.package_runtime is None else args.package_runtime make_runtime(capsule, routput, platforms=platforms, package=package, suffix=suffix) licfile = project.license_file if licfile: logging.info('Project has customized license file: %s', licfile) licpath = os.path.join(routput, 'pytransform' + suffix) \ if package else routput logging.info('Copy project license file to %s', licpath) shutil.copy(licfile, licpath) elif not restrict: licode = '*FLAGS:%c*CODE:PyArmor-Project' % chr(1) licpath = os.path.join(routput, 'pytransform' + suffix) \ if package else routput licfile = os.path.join(licpath, license_filename) logging.info('Generate no restrict mode license file: %s', licfile) make_license_key(capsule, licode, licfile) logging.info('Build project OK.')