Esempio n. 1
0
def _obfuscate(args):
    '''Obfuscate scripts without project'''
    if args.src is None and args.entry is None and not args.scripts:
        raise RuntimeError('No entry script')

    entry = args.entry or args.scripts[0]
    path = os.path.abspath(
        os.path.dirname(entry) if args.src is None else args.src)
    logging.info('Obfuscate scripts in path "%s" ...', path)

    capsule = args.capsule if args.capsule else DEFAULT_CAPSULE
    if os.path.exists(capsule) and check_capsule(capsule):
        logging.info('Use cached capsule %s', capsule)
    else:
        logging.info('Generate capsule %s', capsule)
        make_capsule(capsule)

    output = args.output
    if args.recursive:
        pats = ['global-include *.py', 'prune build', 'prune dist']
        if hasattr('', 'decode'):
            pats = [p.decode() for p in pats]
        files = Project.build_manifest(pats, path)
    else:
        files = Project.build_globfiles(['*.py'], path)
    filepairs = [(os.path.join(path, x), os.path.join(output, x))
                 for x in files]

    if args.restrict:
        logging.info('Restrict mode is eanbled')
        mode = Project.map_obfuscate_mode(default_obf_module_mode,
                                          default_obf_code_mode)
    else:
        logging.info('Restrict mode is disabled')
        mode = Project.map_obfuscate_mode(default_obf_module_mode, 'wrap')

    logging.info('Obfuscate scripts with mode %s', mode)
    logging.info('Save obfuscated scripts to "%s"', output)
    for a, b in filepairs:
        logging.info('\t%s -> %s', a, b)
    obfuscate_scripts(filepairs, mode, capsule, output)

    logging.info('Make runtime files')
    make_runtime(capsule, output)
    if not args.restrict:
        licode = '*FLAGS:%c*CODE:Pyarmor-Project' % chr(1)
        licfile = os.path.join(output, license_filename)
        logging.info('Generate no restrict mode license file: %s', licfile)
        make_project_license(capsule, licode, licfile)

    make_entry(os.path.basename(entry), path, output)
    for script in args.scripts[1:]:
        make_entry(os.path.basename(script), path, output)

    logging.info('Obfuscate %d scripts OK.', len(files))
Esempio n. 2
0
def main_entry():
    logging.basicConfig(
        level=logging.INFO,
        format='%(levelname)-8s %(message)s',
    )
    try:
        if 'download' not in sys.argv[1:2]:
            pytransform_bootstrap()
            capsule = DEFAULT_CAPSULE
            if not (os.path.exists(capsule) and check_capsule(capsule)):
                logging.info('Generate global capsule %s', capsule)
                make_capsule(capsule)
        main(sys.argv[1:])
    except Exception as e:
        if sys.flags.debug:
            raise
        logging.error('%s', e)
        sys.exit(1)
Esempio n. 3
0
def _obfuscate(args):
    '''Obfuscate scripts without project.'''
    for x in ('src', 'entry', 'cross-protection'):
        if getattr(args, x.replace('-', '_')) is not None:
            logging.warning('Option --%s has been deprecated', x)

    if args.src is None and not args.scripts:
        args.src = '.'

    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:
        path = os.path.abspath(args.src)
    if not os.path.exists(path):
        raise RuntimeError('Not found source path: %s' % path)
    logging.info('Source path is "%s"', path)

    entry = args.entry or (args.scripts and args.scripts[0])
    logging.info('Entry script is %s', entry)

    capsule = args.capsule if args.capsule else DEFAULT_CAPSULE
    if os.path.exists(capsule) and check_capsule(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')

    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(','):
                    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
    if args.platform:
        logging.info('Target platform is %s', args.platform)
        if cross_protection == 1:
            cross_protection = args.platform
        elif isinstance(cross_protection, str):
            cross_protection = ','.join([cross_protection, args.platform])

    advanced = 1 if args.advanced else 0
    logging.info('Advanced mode is %d', advanced)

    restrict = args.restrict
    logging.info('Restrict mode is %d', restrict)

    for x in 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, b)
        protection = entry and (os.path.abspath(a) == os.path.abspath(entry)) \
            and cross_protection
        plugins = protection and args.plugins

        d = os.path.dirname(b)
        if not os.path.exists(d):
            os.makedirs(d)

        encrypt_script(prokey,
                       a,
                       b,
                       adv_mode=advanced,
                       rest_mode=restrict,
                       protection=protection,
                       plugins=plugins)
    logging.info('%d scripts have been obfuscated', len(files))

    make_runtime(capsule, output, platform=args.platform)

    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)
        licfile = os.path.join(output, license_filename)
        logging.info('Generate no restrict mode license file: %s', licfile)
        make_project_license(capsule, licode, licfile)

    if (not args.no_bootstrap) and entry and os.path.exists(entry):
        entryname = entry if args.src else os.path.basename(entry)
        if os.path.exists(os.path.join(output, entryname)):
            make_entry(entryname, path, output)
        else:
            logging.info('Use outer entry script "%s"', entry)
            make_entry(entry, path, output)

    logging.info('Obfuscate %d scripts OK.', len(files))
Esempio n. 4
0
def _licenses(args):
    '''Generate licenses for obfuscated scripts.'''
    for x in ('bind-file', ):
        if getattr(args, x.replace('-', '_')) is not None:
            logging.warning('Option --%s has been deprecated', x)

    if os.path.exists(os.path.join(args.project, config_filename)):
        logging.info('Generate licenses for project %s ...', args.project)
        project = Project()
        project.open(args.project)
        capsule = build_path(project.capsule, args.project) \
            if args.capsule is None else args.capsule
        restrict_mode = project.get(
            'restrict_mode', 0 if project.get('disable_restrict_mode') else 1)
    else:
        if args.project != '':
            logging.warning('Ignore option --project, there is no project')
        capsule = DEFAULT_CAPSULE if args.capsule is None else args.capsule
        if not (os.path.exists(capsule) and check_capsule(capsule)):
            logging.info('Generate capsule %s', capsule)
            make_capsule(capsule)
        logging.info('Generate licenses with capsule %s ...', capsule)
        project = dict(restrict_mode=args.restrict)
        restrict_mode = args.restrict

    licpath = os.path.join(
        args.project if args.output is None else args.output, 'licenses')
    if os.path.exists(licpath):
        logging.info('Output path of licenses: %s', licpath)
    else:
        logging.info('Make output path of licenses: %s', licpath)
        os.mkdir(licpath)

    if args.expired is None:
        fmt = ''
    else:
        fmt = '*TIME:%.0f\n' % \
              time.mktime(time.strptime(args.expired, '%Y-%m-%d'))

    if not restrict_mode:
        logging.info('The license file generated is in disable restrict mode')
        fmt = '%s*FLAGS:%c' % (fmt, 1)
    else:
        logging.info('The license file generated is in restrict mode')

    if args.bind_disk:
        fmt = '%s*HARDDISK:%s' % (fmt, args.bind_disk)

    if args.bind_mac:
        fmt = '%s*IFMAC:%s' % (fmt, args.bind_mac)

    if args.bind_ipv4:
        fmt = '%s*IFIPV4:%s' % (fmt, args.bind_ipv4)

    # if args.bind_ipv6:
    #     fmt = '%s*IFIPV6:%s' % (fmt, args.bind_ipv6)

    if args.bind_domain:
        fmt = '%s*DOMAIN:%s' % (fmt, args.bind_domain)

    if args.bind_file:
        bind_file, bind_key = args.bind_file.split(';', 2)
        if os.path.exists(bind_file):
            f = open(bind_file, 'rb')
            s = f.read()
            f.close()
            if sys.version_info[0] == 3:
                fmt = '%s*FIXKEY:%s;%s' % (fmt, bind_key, s.decode())
            else:
                fmt = '%s*FIXKEY:%s;%s' % (fmt, bind_key, s)
        else:
            raise RuntimeError('Bind file %s not found' % bind_file)

    # Prefix of registration code
    fmt = fmt + '*CODE:'

    for rcode in args.codes:
        output = os.path.join(licpath, re.sub('[^-_0-9a-zA-Z]', '',
                                              rcode[:32]))
        if not os.path.exists(output):
            logging.info('Make path: %s', output)
            os.mkdir(output)

        licfile = os.path.join(output, license_filename)
        licode = fmt + rcode
        txtinfo = licode.replace('\n', r'\n')
        if args.expired:
            txtinfo = '"Expired:%s%s"' % (args.expired,
                                          txtinfo[txtinfo.find(r'\n') + 2:])
        logging.info('Generate license: %s', txtinfo)
        make_project_license(capsule, licode, licfile)
        logging.info('Write license file: %s', licfile)

        logging.info('Write information to %s.txt', licfile)
        with open(os.path.join(licfile + '.txt'), 'w') as f:
            f.write(txtinfo)

    logging.info('Generate %d licenses OK.', len(args.codes))
Esempio n. 5
0
def _licenses(args):
    '''Generate licenses for obfuscated scripts.

Examples,

* Expired license for global capsule

    pyarmor licenses --expired=2018-05-12 Customer-Jordan

* Bind license to fixed harddisk and expired someday for project

    cd projects/myproject
    ./pyarmor licenses -e 2018-05-12 \\
              --bind-disk '100304PBN2081SF3NJ5T' Customer-Tom
    '''
    if os.path.exists(os.path.join(args.project, config_filename)):
        logging.info('Generate licenses for project %s ...', args.project)
        project = Project()
        project.open(args.project)
        capsule = build_path(project.capsule, args.project) \
            if args.capsule is None else args.capsule
    else:
        if args.project != '':
            logging.warning('Ignore option --project, no project in %s',
                            args.project)
        capsule = DEFAULT_CAPSULE if args.capsule is None else args.capsule
        if not (os.path.exists(capsule) and check_capsule(capsule)):
            logging.info('Generate capsule %s', capsule)
            make_capsule(capsule)
        logging.info('Generate licenses with capsule %s ...', capsule)
        project = {
            'disable_restrict_mode': 0 if args.restrict else 1,
        }

    licpath = os.path.join(
        args.project if args.output is None else args.output, 'licenses')
    if os.path.exists(licpath):
        logging.info('Output path of licenses: %s', licpath)
    else:
        logging.info('Make output path of licenses: %s', licpath)
        os.mkdir(licpath)

    if args.expired is None:
        fmt = ''
    else:
        fmt = '*TIME:%.0f\n' % \
              time.mktime(time.strptime(args.expired, '%Y-%m-%d'))

    if project.get('disable_restrict_mode'):
        logging.info('The license files generated is in disable restrict mode')
        fmt = '%s*FLAGS:%c' % (fmt, 1)
    else:
        logging.info('The license files generated is in restrict mode')

    if args.bind_disk:
        fmt = '%s*HARDDISK:%s' % (fmt, args.bind_disk)

    if args.bind_mac:
        fmt = '%s*IFMAC:%s' % (fmt, args.bind_mac)

    if args.bind_ipv4:
        fmt = '%s*IFIPV4:%s' % (fmt, args.bind_ipv4)

    # if args.bind_ipv6:
    #     fmt = '%s*IFIPV6:%s' % (fmt, args.bind_ipv6)

    if args.bind_domain:
        fmt = '%s*DOMAIN:%s' % (fmt, args.bind_domain)

    if args.bind_file:
        bind_file, bind_key = args.bind_file.split(';', 2)
        if os.path.exists(bind_file):
            f = open(bind_file, 'rb')
            s = f.read()
            f.close()
            if sys.version_info[0] == 3:
                fmt = '%s*FIXKEY:%s;%s' % (fmt, bind_key, s.decode())
            else:
                fmt = '%s*FIXKEY:%s;%s' % (fmt, bind_key, s)
        else:
            raise RuntimeError('Bind file %s not found' % bindfile)

    # Prefix of registration code
    fmt = fmt + '*CODE:'

    for rcode in args.codes:
        output = os.path.join(licpath, rcode)
        if not os.path.exists(output):
            logging.info('Make path: %s', output)
            os.mkdir(output)

        licfile = os.path.join(output, license_filename)
        licode = fmt + rcode
        txtinfo = licode.replace('\n', r'\n')
        if args.expired:
            txtinfo = '"Expired:%s%s"' % (args.expired,
                                          txtinfo[txtinfo.find(r'\n') + 2:])
        logging.info('Generate license: %s', txtinfo)
        make_project_license(capsule, licode, licfile)
        logging.info('Write license file: %s', licfile)

        logging.info('Write information to %s.txt', licfile)
        with open(os.path.join(licfile + '.txt'), 'w') as f:
            f.write(txtinfo)

    logging.info('Generate %d licenses OK.', len(args.codes))
Esempio n. 6
0
def main(args):
    parser = argparse.ArgumentParser(
        prog='pyarmor',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        description='PyArmor is a command line tool used to obfuscate '
        'python scripts, bind obfuscated scripts to fixed '
        'machine or expire obfuscated scripts.',
        epilog=__doc__,
    )
    parser.add_argument('-v',
                        '--version',
                        action='version',
                        version=_version_info())
    parser.add_argument('-q',
                        '--silent',
                        action='store_true',
                        help='Suppress all normal output')

    subparsers = parser.add_subparsers(
        title='The most commonly used pyarmor commands are',
        metavar='<command>')

    #
    # Command: capsule
    #
    cparser = subparsers.add_parser(
        'capsule',
        epilog=_capsule.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Generate or upgrade the capsule explicitly ')
    cparser.add_argument('--upgrade',
                         action='store_true',
                         help='Upgrade the capsule to latest version')
    cparser.add_argument('path',
                         nargs='?',
                         default=os.path.expanduser('~'),
                         help='Path to save capsule, default is home path')
    cparser.set_defaults(func=_capsule)

    #
    # Command: obfuscate
    #
    cparser = subparsers.add_parser(
        'obfuscate',
        epilog=_obfuscate.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Obfuscate python scripts')
    cparser.add_argument('-O', '--output', default='dist', metavar='PATH')
    cparser.add_argument('-e',
                         '--entry',
                         metavar='SCRIPT',
                         help='Entry script [DEPRECATED]')
    cparser.add_argument('-r',
                         '--recursive',
                         action='store_true',
                         help='Match files recursively')
    cparser.add_argument('-s',
                         '--src',
                         metavar='PATH',
                         help='Base path for search python scripts')
    cparser.add_argument('--restrict',
                         type=int,
                         choices=(0, 1),
                         help='Set restrict mode')
    cparser.add_argument('--cross-protection',
                         type=int,
                         choices=(0, 1),
                         default=1,
                         help='Enable/disable to insert protection code')
    cparser.add_argument('--capsule',
                         help='Use this capsule other than global capsule')
    cparser.add_argument('scripts',
                         metavar='SCRIPT',
                         nargs='*',
                         help='Scripts to obfuscted')
    cparser.set_defaults(func=_obfuscate)

    #
    # Command: init
    #
    cparser = subparsers.add_parser(
        'init',
        epilog=_init.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Create a project to manage obfuscated scripts')
    cparser.add_argument('-t',
                         '--type',
                         default='auto',
                         choices=('auto', 'app', 'pkg'))
    cparser.add_argument('-e', '--entry', help='Entry script of this project')
    cparser.add_argument('-s',
                         '--src',
                         required=True,
                         help='Base path of python scripts')
    cparser.add_argument('--capsule',
                         help='Use this capsule other than global capsule')
    cparser.add_argument('project', nargs='?', help='Project path')
    cparser.set_defaults(func=_init)

    #
    # Command: config
    #
    cparser = subparsers.add_parser(
        'config',
        epilog=_update.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Update project settings')
    cparser.add_argument('project',
                         nargs='?',
                         metavar='PATH',
                         default='',
                         help='Project path')
    cparser.add_argument('--name')
    cparser.add_argument('--title')
    cparser.add_argument('--src')
    cparser.add_argument('--output')
    cparser.add_argument('--capsule', help='Project capsule')
    cparser.add_argument('--manifest',
                         metavar='TEMPLATE',
                         help='Manifest template string')
    cparser.add_argument('--entry',
                         metavar='SCRIPT',
                         help='Entry script of this project')
    cparser.add_argument('--is-package', type=int, choices=(0, 1))
    cparser.add_argument('--disable-restrict-mode', type=int, choices=(0, 1))
    cparser.add_argument('--obf-module-mode',
                         choices=Project.OBF_MODULE_MODE,
                         help='[DEPRECATED] Use --obf-mod instead')
    cparser.add_argument('--obf-code-mode',
                         choices=Project.OBF_CODE_MODE,
                         help='[DEPRECATED] Use --obf-code and --wrap-mode'
                         ' instead')
    cparser.add_argument('--obf-mod', type=int, choices=(0, 1))
    cparser.add_argument('--obf-code', type=int, choices=(0, 1))
    cparser.add_argument('--wrap-mode', type=int, choices=(0, 1))
    cparser.add_argument('--cross-protection', type=int, choices=(0, 1))
    cparser.add_argument('--runtime-path', metavar="RPATH")
    cparser.set_defaults(func=_update)

    #
    # Command: info
    #
    cparser = subparsers.add_parser(
        'info',
        epilog=_info.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Show project information')
    cparser.add_argument('project',
                         nargs='?',
                         metavar='PATH',
                         default='',
                         help='Project path')
    cparser.set_defaults(func=_info)

    #
    # Command: check
    #
    cparser = subparsers.add_parser(
        'check',
        epilog=_check.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Check consistency of project')
    cparser.add_argument('project',
                         nargs='?',
                         metavar='PATH',
                         default='',
                         help='Project path')
    cparser.set_defaults(func=_check)

    #
    # Command: build
    #
    cparser = subparsers.add_parser(
        'build',
        epilog=_build.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Obfuscate all the scripts in the project')
    cparser.add_argument('project',
                         nargs='?',
                         metavar='PATH',
                         default='',
                         help='Project path')
    cparser.add_argument(
        '-B',
        '--force',
        action='store_true',
        help='Obfuscate all scripts even if it\'s not updated')
    cparser.add_argument('-r',
                         '--only-runtime',
                         action='store_true',
                         help='Generate extra runtime files only')
    cparser.add_argument('-n',
                         '--no-runtime',
                         action='store_true',
                         help='DO NOT generate extra runtime files')
    cparser.add_argument('-O',
                         '--output',
                         help='Output path, override project configuration')
    cparser.set_defaults(func=_build)

    #
    # Command: target
    #
    # cparser = subparsers.add_parser('target', help='Manage target for project')
    # cparser.add_argument('name', metavar='NAME', nargs=1,
    #                      help='Target name')
    # group = cparser.add_argument_group('Target definition')
    # group.add_argument('-p', '--platform', metavar='PLATFORM',
    #                    help='Target platform to run obfuscated scripts')
    # group.add_argument('-c', '--license', metavar='CODE',
    #                    help='License code for this target')
    # cparser.add_argument('--remove', action='store_true',
    #                      help='Remove target from project')
    # cparser.add_argument('-P', '--project', required=True, default='',
    #                      help='Project path or configure file')
    # cparser.set_defaults(func=_target)

    #
    # Command: license
    #
    cparser = subparsers.add_parser(
        'licenses',
        epilog=_licenses.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Generate new licenses for obfuscated scripts')
    cparser.add_argument('codes',
                         nargs='+',
                         metavar='CODE',
                         help='Registration code for this license')
    group = cparser.add_argument_group('Bind license to hardware')
    group.add_argument('-e',
                       '--expired',
                       metavar='YYYY-MM-DD',
                       help='Expired date for this license')
    group.add_argument('-d',
                       '--bind-disk',
                       metavar='SN',
                       help='Bind license to serial number of harddisk')
    group.add_argument('-4',
                       '--bind-ipv4',
                       metavar='a.b.c.d',
                       help='Bind license to ipv4 addr')
    # group.add_argument('-6', '--bind-ipv6', metavar='a:b:c:d',
    #                    help='Bind license to ipv6 addr')
    group.add_argument('-m',
                       '--bind-mac',
                       metavar='x:x:x:x',
                       help='Bind license to mac addr')
    group.add_argument('--bind-domain',
                       metavar='DOMAIN',
                       help='Bind license to domain name')
    group.add_argument('--bind-file',
                       metavar='filename;target_filename',
                       help='Bind license to fixed file')
    cparser.add_argument('-P', '--project', default='', help='Project path')
    cparser.add_argument('-C', '--capsule', help='Project capsule')
    cparser.add_argument('-O', '--output', help='Output path')
    cparser.add_argument('--restrict',
                         type=int,
                         default=1,
                         choices=(0, 1),
                         help='Generate license for restrict mode')

    cparser.set_defaults(func=_licenses)

    #
    # Command: hdinfo
    #
    cparser = subparsers.add_parser(
        'hdinfo',
        epilog=_hdinfo.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Show hardware information')
    cparser.set_defaults(func=_hdinfo)

    #
    # Command: benchmark
    #
    cparser = subparsers.add_parser(
        'benchmark',
        epilog=_benchmark.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Run benchmark test in current machine')
    cparser.add_argument('-m',
                         '--obf-mod',
                         choices=(0, 1),
                         default=1,
                         type=int)
    cparser.add_argument('-c',
                         '--obf-code',
                         choices=(0, 1),
                         default=1,
                         type=int)
    cparser.add_argument('-w',
                         '--wrap-mode',
                         choices=(0, 1),
                         default=1,
                         type=int)
    cparser.set_defaults(func=_benchmark)

    #
    # Command: pack
    #
    cparser = subparsers.add_parser(
        'pack',
        epilog=packer.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Pack obfuscated scripts to one bundle')
    packer.add_arguments(cparser)
    cparser.set_defaults(func=packer.packer)

    args = parser.parse_args(args)
    if args.silent:
        logging.getLogger().setLevel(100)

    if not hasattr(args, 'func'):
        parser.print_help()
        return

    logging.info(_version_info(short=True))
    logging.debug('PyArmor install path: %s', PYARMOR_PATH)

    capsule = DEFAULT_CAPSULE
    if not (os.path.exists(capsule) and check_capsule(capsule)):
        logging.info('Generate global capsule %s', capsule)
        make_capsule(capsule)

    args.func(args)
Esempio n. 7
0
def _obfuscate(args):
    '''Obfuscate scripts without project'''
    if args.src is None and args.entry is None and not args.scripts:
        raise RuntimeError('No entry script')

    entry = args.entry or (args.scripts and args.scripts[0])
    path = os.path.abspath(
        os.path.dirname(entry) if args.src is None else args.src)
    logging.info('Obfuscate scripts in path "%s"', path)

    capsule = args.capsule if args.capsule else DEFAULT_CAPSULE
    if os.path.exists(capsule) and check_capsule(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')
    if args.recursive:
        pats = ['global-include *.py', 'prune build', 'prune dist']
        if os.path.abspath(output).startswith(path):
            x = os.path.abspath(output)[len(path):].strip('/\\')
            pats.append('prune %s' % x)
        if hasattr('', 'decode'):
            pats = [p.decode() for p in pats]
        files = Project.build_manifest(pats, path)
    else:
        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')
    for x in files:
        a, b = os.path.join(path, x), os.path.join(output, x)
        logging.info('\t%s -> %s', x, b)
        protection = args.cross_protection and entry \
            and (os.path.abspath(a) == os.path.abspath(entry))

        d = os.path.dirname(b)
        if not os.path.exists(d):
            os.makedirs(d)

        encrypt_script(prokey, a, b, protection=protection)
    logging.info('%d scripts have been obfuscated', len(files))

    make_runtime(capsule, output)

    if entry and entry.endswith('__init__.py') and args.restrict is None:
        logging.info('Disable restrict mode for package by default')
        restrict = 0
    else:
        restrict = 1 if args.restrict is None else args.restrict
        logging.info('Obfuscate scripts with restrict mode %s',
                     'on' if restrict else 'off')
    if not restrict:
        licode = '*FLAGS:%c*CODE:PyArmor-Project' % chr(1)
        licfile = os.path.join(output, license_filename)
        logging.info('Generate no restrict mode license file: %s', licfile)
        make_project_license(capsule, licode, licfile)

    if entry:
        make_entry(os.path.basename(entry), path, output)
    for script in args.scripts[1:]:
        make_entry(os.path.basename(script), path, output)

    logging.info('Obfuscate %d scripts OK.', len(files))