| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464 |
- # These module alos are used by protection code, so that protection
- # code needn't import anything
- import os
- import platform
- import sys
- import struct
- # Because ctypes is new from Python 2.5, so pytransform doesn't work
- # before Python 2.5
- #
- from ctypes import cdll, c_char, c_char_p, c_int, c_void_p, \
- pythonapi, py_object, PYFUNCTYPE, CFUNCTYPE
- from fnmatch import fnmatch
- #
- # Support Platforms
- #
- plat_path = 'platforms'
- plat_table = (
- ('windows', ('windows', 'cygwin-*')),
- ('darwin', ('darwin',)),
- ('ios', ('ios',)),
- ('linux', ('linux*',)),
- ('freebsd', ('freebsd*', 'openbsd*')),
- ('poky', ('poky',)),
- )
- arch_table = (
- ('x86', ('i?86', )),
- ('x86_64', ('x64', 'x86_64', 'amd64', 'intel')),
- ('arm', ('armv5',)),
- ('armv6', ('armv6l',)),
- ('armv7', ('armv7l',)),
- ('ppc64', ('ppc64le',)),
- ('mips32', ('mips',)),
- ('aarch32', ('aarch32',)),
- ('aarch64', ('aarch64', 'arm64'))
- )
- #
- # Hardware type
- #
- HT_HARDDISK, HT_IFMAC, HT_IPV4, HT_IPV6, HT_DOMAIN = range(5)
- #
- # Global
- #
- _pytransform = None
- class PytransformError(Exception):
- pass
- def dllmethod(func):
- def wrap(*args, **kwargs):
- return func(*args, **kwargs)
- return wrap
- @dllmethod
- def version_info():
- prototype = PYFUNCTYPE(py_object)
- dlfunc = prototype(('version_info', _pytransform))
- return dlfunc()
- @dllmethod
- def init_pytransform():
- major, minor = sys.version_info[0:2]
- # Python2.5 no sys.maxsize but sys.maxint
- # bitness = 64 if sys.maxsize > 2**32 else 32
- prototype = PYFUNCTYPE(c_int, c_int, c_int, c_void_p)
- init_module = prototype(('init_module', _pytransform))
- ret = init_module(major, minor, pythonapi._handle)
- if (ret & 0xF000) == 0x1000:
- raise PytransformError('Initialize python wrapper failed (%d)'
- % (ret & 0xFFF))
- return ret
- @dllmethod
- def init_runtime():
- prototype = PYFUNCTYPE(c_int, c_int, c_int, c_int, c_int)
- _init_runtime = prototype(('init_runtime', _pytransform))
- return _init_runtime(0, 0, 0, 0)
- @dllmethod
- def encrypt_code_object(pubkey, co, flags, suffix=''):
- _pytransform.set_option(6, suffix.encode())
- prototype = PYFUNCTYPE(py_object, py_object, py_object, c_int)
- dlfunc = prototype(('encrypt_code_object', _pytransform))
- return dlfunc(pubkey, co, flags)
- @dllmethod
- def generate_license_file(filename, priname, rcode, start=-1, count=1):
- prototype = PYFUNCTYPE(c_int, c_char_p, c_char_p, c_char_p, c_int, c_int)
- dlfunc = prototype(('generate_project_license_files', _pytransform))
- return dlfunc(filename.encode(), priname.encode(), rcode.encode(),
- start, count) if sys.version_info[0] == 3 \
- else dlfunc(filename, priname, rcode, start, count)
- @dllmethod
- def generate_license_key(prikey, keysize, rcode):
- prototype = PYFUNCTYPE(py_object, c_char_p, c_int, c_char_p)
- dlfunc = prototype(('generate_license_key', _pytransform))
- return dlfunc(prikey, keysize, rcode) if sys.version_info[0] == 2 \
- else dlfunc(prikey, keysize, rcode.encode())
- @dllmethod
- def get_registration_code():
- prototype = PYFUNCTYPE(py_object)
- dlfunc = prototype(('get_registration_code', _pytransform))
- return dlfunc()
- @dllmethod
- def get_expired_days():
- prototype = PYFUNCTYPE(py_object)
- dlfunc = prototype(('get_expired_days', _pytransform))
- return dlfunc()
- @dllmethod
- def clean_obj(obj, kind):
- prototype = PYFUNCTYPE(c_int, py_object, c_int)
- dlfunc = prototype(('clean_obj', _pytransform))
- return dlfunc(obj, kind)
- def clean_str(*args):
- tdict = {
- 'str': 0,
- 'bytearray': 1,
- 'unicode': 2
- }
- for obj in args:
- k = tdict.get(type(obj).__name__)
- if k is None:
- raise RuntimeError('Can not clean object: %s' % obj)
- clean_obj(obj, k)
- def get_hd_info(hdtype, name=None):
- if hdtype not in range(HT_DOMAIN + 1):
- raise RuntimeError('Invalid parameter hdtype: %s' % hdtype)
- size = 256
- t_buf = c_char * size
- buf = t_buf()
- cname = c_char_p(0 if name is None
- else name.encode('utf-8') if hasattr('name', 'encode')
- else name)
- if (_pytransform.get_hd_info(hdtype, buf, size, cname) == -1):
- raise PytransformError('Get hardware information failed')
- return buf.value.decode()
- def show_hd_info():
- return _pytransform.show_hd_info()
- def assert_armored(*names):
- prototype = PYFUNCTYPE(py_object, py_object)
- dlfunc = prototype(('assert_armored', _pytransform))
- def wrapper(func):
- def wrap_execute(*args, **kwargs):
- dlfunc(names)
- return func(*args, **kwargs)
- return wrap_execute
- return wrapper
- def check_armored(*names):
- try:
- prototype = PYFUNCTYPE(py_object, py_object)
- prototype(('assert_armored', _pytransform))(names)
- return True
- except RuntimeError:
- return False
- def get_license_info():
- info = {
- 'ISSUER': None,
- 'EXPIRED': None,
- 'HARDDISK': None,
- 'IFMAC': None,
- 'IFIPV4': None,
- 'DOMAIN': None,
- 'DATA': None,
- 'CODE': None,
- }
- rcode = get_registration_code().decode()
- if rcode.startswith('*VERSION:'):
- index = rcode.find('\n')
- info['ISSUER'] = rcode[9:index].split('.')[0].replace('-sn-1.txt', '')
- rcode = rcode[index+1:]
- index = 0
- if rcode.startswith('*TIME:'):
- from time import ctime
- index = rcode.find('\n')
- info['EXPIRED'] = ctime(float(rcode[6:index]))
- index += 1
- if rcode[index:].startswith('*FLAGS:'):
- index += len('*FLAGS:') + 1
- info['FLAGS'] = ord(rcode[index - 1])
- prev = None
- start = index
- for k in ['HARDDISK', 'IFMAC', 'IFIPV4', 'DOMAIN', 'FIXKEY', 'CODE']:
- index = rcode.find('*%s:' % k)
- if index > -1:
- if prev is not None:
- info[prev] = rcode[start:index]
- prev = k
- start = index + len(k) + 2
- info['CODE'] = rcode[start:]
- i = info['CODE'].find(';')
- if i > 0:
- info['DATA'] = info['CODE'][i+1:]
- info['CODE'] = info['CODE'][:i]
- return info
- def get_license_code():
- return get_license_info()['CODE']
- def get_user_data():
- return get_license_info()['DATA']
- def _match_features(patterns, s):
- for pat in patterns:
- if fnmatch(s, pat):
- return True
- def _gnu_get_libc_version():
- try:
- prototype = CFUNCTYPE(c_char_p)
- ver = prototype(('gnu_get_libc_version', cdll.LoadLibrary('')))()
- return ver.decode().split('.')
- except Exception:
- pass
- def format_platform(platid=None):
- if platid:
- return os.path.normpath(platid)
- plat = platform.system().lower()
- mach = platform.machine().lower()
- for alias, platlist in plat_table:
- if _match_features(platlist, plat):
- plat = alias
- break
- if plat == 'linux':
- cname, cver = platform.libc_ver()
- if cname == 'musl':
- plat = 'musl'
- elif cname == 'libc':
- plat = 'android'
- elif cname == 'glibc':
- v = _gnu_get_libc_version()
- if v and len(v) >= 2 and (int(v[0]) * 100 + int(v[1])) < 214:
- plat = 'centos6'
- for alias, archlist in arch_table:
- if _match_features(archlist, mach):
- mach = alias
- break
- if plat == 'windows' and mach == 'x86_64':
- bitness = struct.calcsize('P'.encode()) * 8
- if bitness == 32:
- mach = 'x86'
- return os.path.join(plat, mach)
- # Load _pytransform library
- def _load_library(path=None, is_runtime=0, platid=None, suffix='', advanced=0):
- path = os.path.dirname(__file__) if path is None \
- else os.path.normpath(path)
- plat = platform.system().lower()
- name = '_pytransform' + suffix
- if plat == 'linux':
- filename = os.path.abspath(os.path.join(path, name + '.so'))
- elif plat == 'darwin':
- filename = os.path.join(path, name + '.dylib')
- elif plat == 'windows':
- filename = os.path.join(path, name + '.dll')
- elif plat == 'freebsd':
- filename = os.path.join(path, name + '.so')
- else:
- raise PytransformError('Platform %s not supported' % plat)
- if platid is not None and os.path.isfile(platid):
- filename = platid
- elif platid is not None or not os.path.exists(filename) or not is_runtime:
- libpath = platid if platid is not None and os.path.isabs(platid) else \
- os.path.join(path, plat_path, format_platform(platid))
- filename = os.path.join(libpath, os.path.basename(filename))
- if not os.path.exists(filename):
- raise PytransformError('Could not find "%s"' % filename)
- try:
- m = cdll.LoadLibrary(filename)
- except Exception as e:
- if sys.flags.debug:
- print('Load %s failed:\n%s' % (filename, e))
- raise
- # Removed from v4.6.1
- # if plat == 'linux':
- # m.set_option(-1, find_library('c').encode())
- if not os.path.abspath('.') == os.path.abspath(path):
- m.set_option(1, path.encode() if sys.version_info[0] == 3 else path)
- # Required from Python3.6
- m.set_option(2, sys.byteorder.encode())
- if sys.flags.debug:
- m.set_option(3, c_char_p(1))
- m.set_option(4, c_char_p(not is_runtime))
- # Disable advanced mode by default
- m.set_option(5, c_char_p(not advanced))
- # Set suffix for private package
- if suffix:
- m.set_option(6, suffix.encode())
- return m
- def pyarmor_init(path=None, is_runtime=0, platid=None, suffix='', advanced=0):
- global _pytransform
- _pytransform = _load_library(path, is_runtime, platid, suffix, advanced)
- return init_pytransform()
- def pyarmor_runtime(path=None, suffix='', advanced=0):
- if _pytransform is not None:
- return
- try:
- pyarmor_init(path, is_runtime=1, suffix=suffix, advanced=advanced)
- init_runtime()
- except Exception as e:
- if sys.flags.debug or hasattr(sys, '_catch_pyarmor'):
- raise
- sys.stderr.write("%s\n" % str(e))
- sys.exit(1)
- # ----------------------------------------------------------
- # End of pytransform
- # ----------------------------------------------------------
- #
- # Not available from v5.6
- #
- def generate_capsule(licfile):
- prikey, pubkey, prolic = _generate_project_capsule()
- capkey, newkey = _generate_pytransform_key(licfile, pubkey)
- return prikey, pubkey, capkey, newkey, prolic
- @dllmethod
- def _generate_project_capsule():
- prototype = PYFUNCTYPE(py_object)
- dlfunc = prototype(('generate_project_capsule', _pytransform))
- return dlfunc()
- @dllmethod
- def _generate_pytransform_key(licfile, pubkey):
- prototype = PYFUNCTYPE(py_object, c_char_p, py_object)
- dlfunc = prototype(('generate_pytransform_key', _pytransform))
- return dlfunc(licfile.encode() if sys.version_info[0] == 3 else licfile,
- pubkey)
- #
- # Deprecated functions from v5.1
- #
- @dllmethod
- def encrypt_project_files(proname, filelist, mode=0):
- prototype = PYFUNCTYPE(c_int, c_char_p, py_object, c_int)
- dlfunc = prototype(('encrypt_project_files', _pytransform))
- return dlfunc(proname.encode(), filelist, mode)
- def generate_project_capsule(licfile):
- prikey, pubkey, prolic = _generate_project_capsule()
- capkey = _encode_capsule_key_file(licfile)
- return prikey, pubkey, capkey, prolic
- @dllmethod
- def _encode_capsule_key_file(licfile):
- prototype = PYFUNCTYPE(py_object, c_char_p, c_char_p)
- dlfunc = prototype(('encode_capsule_key_file', _pytransform))
- return dlfunc(licfile.encode(), None)
- @dllmethod
- def encrypt_files(key, filelist, mode=0):
- t_key = c_char * 32
- prototype = PYFUNCTYPE(c_int, t_key, py_object, c_int)
- dlfunc = prototype(('encrypt_files', _pytransform))
- return dlfunc(t_key(*key), filelist, mode)
- @dllmethod
- def generate_module_key(pubname, key):
- t_key = c_char * 32
- prototype = PYFUNCTYPE(py_object, c_char_p, t_key, c_char_p)
- dlfunc = prototype(('generate_module_key', _pytransform))
- return dlfunc(pubname.encode(), t_key(*key), None)
- #
- # Compatible for PyArmor v3.0
- #
- @dllmethod
- def old_init_runtime(systrace=0, sysprofile=1, threadtrace=0, threadprofile=1):
- '''Only for old version, before PyArmor 3'''
- pyarmor_init(is_runtime=1)
- prototype = PYFUNCTYPE(c_int, c_int, c_int, c_int, c_int)
- _init_runtime = prototype(('init_runtime', _pytransform))
- return _init_runtime(systrace, sysprofile, threadtrace, threadprofile)
- @dllmethod
- def import_module(modname, filename):
- '''Only for old version, before PyArmor 3'''
- prototype = PYFUNCTYPE(py_object, c_char_p, c_char_p)
- _import_module = prototype(('import_module', _pytransform))
- return _import_module(modname.encode(), filename.encode())
- @dllmethod
- def exec_file(filename):
- '''Only for old version, before PyArmor 3'''
- prototype = PYFUNCTYPE(c_int, c_char_p)
- _exec_file = prototype(('exec_file', _pytransform))
- return _exec_file(filename.encode())
|