Spaces:
Sleeping
Sleeping
| # 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*', 'isilon onefs')), | |
| ('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 | |
| def version_info(): | |
| prototype = PYFUNCTYPE(py_object) | |
| dlfunc = prototype(('version_info', _pytransform)) | |
| return dlfunc() | |
| 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 | |
| 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) | |
| 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) | |
| 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()) | |
| def get_registration_code(): | |
| prototype = PYFUNCTYPE(py_object) | |
| dlfunc = prototype(('get_registration_code', _pytransform)) | |
| return dlfunc() | |
| def get_expired_days(): | |
| prototype = PYFUNCTYPE(py_object) | |
| dlfunc = prototype(('get_expired_days', _pytransform)) | |
| return dlfunc() | |
| 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() | |
| for alias, platlist in plat_table: | |
| if _match_features(platlist, plat): | |
| plat = alias | |
| break | |
| name = '_pytransform' + suffix | |
| if plat == 'linux': | |
| filename = os.path.abspath(os.path.join(path, name + '.so')) | |
| elif plat in ('darwin', 'ios'): | |
| filename = os.path.join(path, name + '.dylib') | |
| elif plat == 'windows': | |
| filename = os.path.join(path, name + '.dll') | |
| elif plat in ('freebsd', 'poky'): | |
| filename = os.path.join(path, name + '.so') | |
| else: | |
| filename = None | |
| 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 filename is None: | |
| raise PytransformError('Platform %s not supported' % plat) | |
| 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) | |
| elif (not is_runtime) and sys.platform.startswith('cygwin'): | |
| path = os.environ['PYARMOR_CYGHOME'] | |
| 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 | |
| # ---------------------------------------------------------- | |
| # | |
| # Unused | |
| # | |
| 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) | |
| # | |
| # 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 | |
| def _generate_project_capsule(): | |
| prototype = PYFUNCTYPE(py_object) | |
| dlfunc = prototype(('generate_project_capsule', _pytransform)) | |
| return dlfunc() | |
| 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 | |
| # | |
| 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 | |
| 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) | |
| 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) | |
| 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 | |
| # | |
| 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) | |
| 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()) | |
| 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()) | |