Example #1
0
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)
Example #2
0
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))
Example #3
0
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.')