pyarmor 8.5.11__zip → 9.0.0__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyarmor-8.5.11 → pyarmor-9.0.0}/PKG-INFO +1 -1
- {pyarmor-8.5.11 → pyarmor-9.0.0}/README.md +8 -55
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/cli/__init__.py +1 -1
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/cli/__main__.py +20 -5
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/cli/bug.py +3 -3
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/cli/context.py +1 -0
- pyarmor-9.0.0/pyarmor/cli/core.data.1 +0 -0
- pyarmor-9.0.0/pyarmor/cli/core.data.2 +0 -0
- pyarmor-9.0.0/pyarmor/cli/core.data.3 +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/cli/default.cfg +6 -5
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/cli/register.py +337 -102
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/config.py +2 -2
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor.egg-info/PKG-INFO +1 -1
- pyarmor-9.0.0/pyarmor.egg-info/requires.txt +1 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/setup.py +1 -1
- pyarmor-8.5.11/pyarmor/cli/core.data.1 +0 -0
- pyarmor-8.5.11/pyarmor/cli/core.data.2 +0 -0
- pyarmor-8.5.11/pyarmor/cli/core.data.3 +0 -0
- pyarmor-8.5.11/pyarmor.egg-info/requires.txt +0 -1
- {pyarmor-8.5.11 → pyarmor-9.0.0}/MANIFEST.in +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/README.rst +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/__init__.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/benchmark.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/build_meta.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/cli/bootstrap.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/cli/config.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/cli/docker.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/cli/generate.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/cli/hdinfo.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/cli/merge.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/cli/mixer.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/cli/plugin.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/cli/public_capsule.zip +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/cli/repack.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/cli/resource.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/cli/shell.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/cobuilder.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/README-ZH.md +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/README.md +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/build-for-exe.bat +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/build-for-freeze.bat +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/build-with-project.bat +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/build-with-project.sh +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/cx_Freeze/hello.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/cx_Freeze/queens.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/cx_Freeze/setup.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/helloworld/foo.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/obfuscate-app.bat +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/obfuscate-app.sh +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/obfuscate-pkg.bat +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/obfuscate-pkg.sh +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pack-obfuscated-scripts.bat +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pack-obfuscated-scripts.sh +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/py2exe/hello.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/py2exe/queens.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/py2exe/setup.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/Arithmetic.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/Calls.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/CommandLine.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/Constructs.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/Dict.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/Exceptions.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/Imports.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/Instances.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/Lists.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/Lookups.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/NewInstances.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/Numbers.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/Setup.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/Strings.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/Tuples.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/With.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/clockres.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/package/__init__.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/package/submodule.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/pybench.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/pybench/systimes.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/simple/queens.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/testmod/hello.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/testmod/queens.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/testpkg/main.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/testpkg/mypkg/__init__.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/examples/testpkg/mypkg/foo.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/helper/__init__.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/helper/build_data_module.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/helper/buildext.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/helper/get_bind_key.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/helper/get_license_info.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/helper/get_platform_name.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/helper/merge.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/helper/repack.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/helper/superuntime.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/license.tri +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/packer.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/platforms/darwin/x86_64/_pytransform.dylib +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/platforms/linux/x86/_pytransform.so +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/platforms/linux/x86_64/_pytransform.so +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/platforms/windows/x86/_pytransform.dll +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/platforms/windows/x86_64/_pytransform.dll +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/plugins/README.md +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/plugins/check_ntp_time.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/polyfills/__init__.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/polyfills/argparse.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/product.key +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/project.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/protect_code.pt +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/protect_code2.pt +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/public.key +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/public_capsule.zip +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/pyarmor-deprecated.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/pyarmor-webui.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/pyarmor.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/pyimcore.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/pyshield.key +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/pyshield.lic +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/pytransform.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/reform.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/register.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/sppmode.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor/utils.py +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor.egg-info/SOURCES.txt +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor.egg-info/dependency_links.txt +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor.egg-info/entry_points.txt +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/pyarmor.egg-info/top_level.txt +0 -0
- {pyarmor-8.5.11 → pyarmor-9.0.0}/setup.cfg +0 -0
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
#
|
|
22
22
|
import os
|
|
23
23
|
|
|
24
|
-
from base64 import b64decode, urlsafe_b64encode
|
|
24
|
+
from base64 import b64decode, b64encode, urlsafe_b64encode
|
|
25
25
|
from json import loads as json_loads
|
|
26
26
|
from string import Template
|
|
27
27
|
|
|
@@ -31,11 +31,51 @@ from . import logger, CliError
|
|
|
31
31
|
# All supported machine flags for group license: [11, 26)
|
|
32
32
|
MACHFLAGS = 22, 21, 18, 20, 16, 11
|
|
33
33
|
|
|
34
|
+
# Upgrade notes for Pyarmor 9
|
|
35
|
+
URL_UPGRADE_V9 = 'https://github.com/dashingsoft/pyarmor/issues/1958'
|
|
36
|
+
|
|
37
|
+
# Template for license info
|
|
38
|
+
LICENSE_INFO_TEMPLATE = '''$advanced
|
|
39
|
+
|
|
40
|
+
$notes
|
|
41
|
+
'''
|
|
42
|
+
|
|
34
43
|
|
|
35
44
|
def parse_token(data):
|
|
36
45
|
from struct import unpack
|
|
37
46
|
|
|
38
|
-
if
|
|
47
|
+
if data and data.find(b' ') > 0:
|
|
48
|
+
try:
|
|
49
|
+
buf = b64decode(data.split()[0])
|
|
50
|
+
|
|
51
|
+
token, value = unpack('II', buf[:8])
|
|
52
|
+
rev, features = value & 0xff, value >> 8
|
|
53
|
+
licno = buf[16:34].decode('utf-8')
|
|
54
|
+
|
|
55
|
+
pstr = []
|
|
56
|
+
i = 64
|
|
57
|
+
for k in range(4):
|
|
58
|
+
n = buf[i]
|
|
59
|
+
i += 1
|
|
60
|
+
pstr.append(buf[i:i+n].decode('utf-8') if n
|
|
61
|
+
else '')
|
|
62
|
+
i += n
|
|
63
|
+
|
|
64
|
+
product = ('non-profits(TBD)' if pstr[2] in ('', 'TBD')
|
|
65
|
+
else pstr[2])
|
|
66
|
+
return {
|
|
67
|
+
'token': token,
|
|
68
|
+
'rev': rev,
|
|
69
|
+
'features': features,
|
|
70
|
+
'licno': licno,
|
|
71
|
+
'machine': pstr[0],
|
|
72
|
+
'regname': pstr[1],
|
|
73
|
+
'product': product,
|
|
74
|
+
'note': pstr[3],
|
|
75
|
+
}
|
|
76
|
+
except Exception as e:
|
|
77
|
+
logger.warning('bad token: %s', str(e))
|
|
78
|
+
|
|
39
79
|
return {
|
|
40
80
|
'token': 0,
|
|
41
81
|
'rev': 0,
|
|
@@ -46,31 +86,50 @@ def parse_token(data):
|
|
|
46
86
|
'note': 'This is trial license'
|
|
47
87
|
}
|
|
48
88
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
89
|
+
|
|
90
|
+
def show_help_page(prompt, url):
|
|
91
|
+
choice = input('\n'.join(prompt)).lower()[:1]
|
|
92
|
+
if choice == 'h':
|
|
93
|
+
import webbrowser
|
|
94
|
+
webbrowser.open(url)
|
|
95
|
+
return choice
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def check_license_version(ctx, silent=False):
|
|
99
|
+
licinfo = ctx.license_info
|
|
100
|
+
rev = licinfo.get('rev', 0)
|
|
101
|
+
token = licinfo.get('token', 0)
|
|
102
|
+
features = licinfo.get('features', 0)
|
|
103
|
+
if rev == 1 and features > 0 and token > 0:
|
|
104
|
+
logger.warning('this license is not ready for Pyarmor 9')
|
|
105
|
+
if silent:
|
|
106
|
+
return False
|
|
107
|
+
|
|
108
|
+
# Group License
|
|
109
|
+
if features == 15:
|
|
110
|
+
prompt = (
|
|
111
|
+
'',
|
|
112
|
+
'Pyarmor 9 has some changes on license policy',
|
|
113
|
+
'This group license is still available',
|
|
114
|
+
'But it need request new device regfile as before',
|
|
115
|
+
'Press "h" to check Pyarmor 9 Upgrade Notes',
|
|
116
|
+
'',
|
|
117
|
+
'Help (h), Quit (q): '
|
|
118
|
+
)
|
|
119
|
+
show_help_page(prompt, URL_UPGRADE_V9)
|
|
120
|
+
raise SystemExit('Quit')
|
|
121
|
+
|
|
122
|
+
prompt = (
|
|
123
|
+
'',
|
|
124
|
+
'Pyarmor 9 has big change on CI/CD pipeline',
|
|
125
|
+
'If not using Pyarmor License in CI/CD pipeline',
|
|
126
|
+
'Press "c" to continue',
|
|
127
|
+
'Otherwise press "h" to check Pyarmor 9.0 Upgrade Notes',
|
|
128
|
+
'',
|
|
129
|
+
'Continue (c), Help (h), Quit (q): '
|
|
130
|
+
)
|
|
131
|
+
if not show_help_page(prompt, URL_UPGRADE_V9) == 'c':
|
|
132
|
+
raise SystemExit('Quit')
|
|
74
133
|
|
|
75
134
|
|
|
76
135
|
class Register(object):
|
|
@@ -124,6 +183,7 @@ class Register(object):
|
|
|
124
183
|
return 'basic' if info['features'] == 1 else \
|
|
125
184
|
'pro' if info['features'] == 7 else \
|
|
126
185
|
'group' if info['features'] == 15 else \
|
|
186
|
+
'ci' if info['features'] == 23 else \
|
|
127
187
|
'trial' if info['token'] == 0 else 'unknown'
|
|
128
188
|
|
|
129
189
|
def _license_to(self, info):
|
|
@@ -148,13 +208,89 @@ class Register(object):
|
|
|
148
208
|
|
|
149
209
|
raise CliError('no registration code found in %s' % filename)
|
|
150
210
|
|
|
211
|
+
def _register_offline_license(self, fzip, namelist):
|
|
212
|
+
logger.info('machine id in group license: %s', ', '.join(
|
|
213
|
+
[x[7:] for x in namelist if x.startswith('tokens')]))
|
|
214
|
+
for idver in MACHFLAGS:
|
|
215
|
+
machid = self._get_machine_id(idver).decode('utf-8')
|
|
216
|
+
logger.debug('got machine id: %s', machid)
|
|
217
|
+
name = '/'.join(['tokens', machid])
|
|
218
|
+
if name in namelist:
|
|
219
|
+
logger.info('this machine id matchs group license')
|
|
220
|
+
break
|
|
221
|
+
else:
|
|
222
|
+
logger.info('no machine id matchs this group license')
|
|
223
|
+
logger.info('take this machine as docker container, and '
|
|
224
|
+
'connect to docker host for authentication...')
|
|
225
|
+
mlist = self._get_docker_hostname()
|
|
226
|
+
if not mlist:
|
|
227
|
+
logger.info(
|
|
228
|
+
'could not get docker host machine id\n%s',
|
|
229
|
+
'\n'.join([
|
|
230
|
+
'',
|
|
231
|
+
'if this machine is docker container, please '
|
|
232
|
+
'run command `pyarmor-auth` in docker host, '
|
|
233
|
+
'and try it again', '',
|
|
234
|
+
'otherwise please generate new group '
|
|
235
|
+
'device license for this machine', '',
|
|
236
|
+
'more information please check section '
|
|
237
|
+
'"using group license" in documentation '
|
|
238
|
+
'"how-to register" guide', ''
|
|
239
|
+
]))
|
|
240
|
+
raise CliError('this group device license is not for '
|
|
241
|
+
'this machine')
|
|
242
|
+
for machid in mlist:
|
|
243
|
+
hostname = '/'.join(['tokens', machid])
|
|
244
|
+
if hostname in namelist:
|
|
245
|
+
name = hostname
|
|
246
|
+
break
|
|
247
|
+
else:
|
|
248
|
+
logger.debug('docker host machine ids: %s', mlist)
|
|
249
|
+
raise CliError('this group device license is not for '
|
|
250
|
+
'this docker host')
|
|
251
|
+
|
|
252
|
+
logger.debug('extracting %s', name)
|
|
253
|
+
self.ctx.save_group_token(fzip.read(name))
|
|
254
|
+
|
|
255
|
+
def _init_token(self, reginfo):
|
|
256
|
+
from struct import pack
|
|
257
|
+
rev, licno, lictp, regname, product = (
|
|
258
|
+
reginfo['rev'], reginfo['rcode'], reginfo['type'],
|
|
259
|
+
reginfo['name'], reginfo['product']
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
token = 0
|
|
263
|
+
old_license = self.license_info
|
|
264
|
+
if old_license['licno'] == licno:
|
|
265
|
+
token = old_license['token']
|
|
266
|
+
|
|
267
|
+
features = (1 if lictp == 'J' else 7 if lictp == 'Z' else
|
|
268
|
+
15 if lictp == 'G' else 23 if lictp == 'C' else
|
|
269
|
+
0)
|
|
270
|
+
notes = (
|
|
271
|
+
'* Do not use this file in CI/CD pipeline directly\n'
|
|
272
|
+
'* Only use it to request CI regfile '
|
|
273
|
+
'"pyarmor-ci-%s.zip"' % licno[:6].lstrip('0')
|
|
274
|
+
if lictp == 'C' else ''
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
regname = regname.encode('utf-8')
|
|
278
|
+
product = product.encode('utf-8')
|
|
279
|
+
notes = notes.encode('utf-8')
|
|
280
|
+
data = pack('<II8x20s28xBB2sB2sB2s', token,
|
|
281
|
+
rev | features << 8,
|
|
282
|
+
licno.encode('utf-8'),
|
|
283
|
+
0,
|
|
284
|
+
len(regname), b'%s',
|
|
285
|
+
len(product), b'%s',
|
|
286
|
+
len(notes), b'%s') % (regname, product, notes)
|
|
287
|
+
return b64encode(data) + b' *=='
|
|
288
|
+
|
|
151
289
|
def register_regfile(self, regfile, clean=True):
|
|
152
290
|
from zipfile import ZipFile
|
|
153
291
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
logger.info('remove old token "%s"', x)
|
|
157
|
-
os.remove(x)
|
|
292
|
+
if os.path.exists(self.ctx.license_group_token):
|
|
293
|
+
os.remove(self.ctx.license_group_token)
|
|
158
294
|
|
|
159
295
|
path = self.ctx.reg_path
|
|
160
296
|
with ZipFile(regfile, 'r') as f:
|
|
@@ -163,56 +299,36 @@ class Register(object):
|
|
|
163
299
|
f.extract(item, path=path)
|
|
164
300
|
namelist = f.namelist()
|
|
165
301
|
if 'group.tokens' in namelist:
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
for idver in MACHFLAGS:
|
|
170
|
-
machid = self._get_machine_id(idver).decode('utf-8')
|
|
171
|
-
logger.info('got machine id: %s', machid)
|
|
172
|
-
name = '/'.join(['tokens', machid])
|
|
173
|
-
if name in namelist:
|
|
174
|
-
logger.info('this machine id matchs group license')
|
|
175
|
-
break
|
|
176
|
-
else:
|
|
177
|
-
logger.info('no machine id matchs this group license')
|
|
178
|
-
logger.info('take this machine as docker container, and '
|
|
179
|
-
'connect to docker host for authentication...')
|
|
180
|
-
mlist = self._get_docker_hostname()
|
|
181
|
-
if not mlist:
|
|
182
|
-
logger.info(
|
|
183
|
-
'could not get docker host machine id\n%s',
|
|
184
|
-
'\n'.join([
|
|
185
|
-
'',
|
|
186
|
-
'if this machine is docker container, please '
|
|
187
|
-
'run command `pyarmor-auth` in docker host, '
|
|
188
|
-
'and try it again', '',
|
|
189
|
-
'otherwise please generate new group '
|
|
190
|
-
'device license for this machine', '',
|
|
191
|
-
'more information please check section '
|
|
192
|
-
'"using group license" in documentation '
|
|
193
|
-
'"how-to register" guide', ''
|
|
194
|
-
]))
|
|
195
|
-
raise CliError('this group device license is not for '
|
|
196
|
-
'this machine')
|
|
197
|
-
for machid in mlist:
|
|
198
|
-
hostname = '/'.join(['tokens', machid])
|
|
199
|
-
if hostname in namelist:
|
|
200
|
-
name = hostname
|
|
201
|
-
break
|
|
202
|
-
else:
|
|
203
|
-
logger.debug('docker host machine ids: %s', mlist)
|
|
204
|
-
raise CliError('this group device license is not for '
|
|
205
|
-
'this docker host')
|
|
302
|
+
self._register_offline_license(f, namelist)
|
|
303
|
+
elif 'ci.token' in namelist:
|
|
304
|
+
name = 'ci.token'
|
|
206
305
|
logger.debug('extracting %s', name)
|
|
207
|
-
self.ctx.
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
'
|
|
212
|
-
raise CliError('wrong usage for
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
306
|
+
self.ctx.save_token(f.read(name))
|
|
307
|
+
elif 'group.info' in namelist:
|
|
308
|
+
logger.info('this file is only used to '
|
|
309
|
+
'request device regfile:\n\n'
|
|
310
|
+
'\tpyarmor reg -g 1 %s\n', regfile)
|
|
311
|
+
raise CliError('wrong usage for Group License')
|
|
312
|
+
elif 'reg.info' in namelist:
|
|
313
|
+
data = f.read('reg.info')
|
|
314
|
+
info = json_loads(data, encoding='utf-8')
|
|
315
|
+
if info.get('type', '') == 'C':
|
|
316
|
+
logger.info('this file is only used to '
|
|
317
|
+
'request ci regfile:\n\n'
|
|
318
|
+
'\tpyarmor reg -C %s\n', regfile)
|
|
319
|
+
raise CliError('wrong usage for CI License')
|
|
320
|
+
self.ctx.save_token(self._init_token(info))
|
|
321
|
+
else:
|
|
322
|
+
logger.error('this license is not ready for Pyarmor 9')
|
|
323
|
+
prompt = (
|
|
324
|
+
'',
|
|
325
|
+
'Pyarmor 9 has big change on CI/CD pipeline',
|
|
326
|
+
'Press "h" to check Pyarmor 9.0 Upgrade Notes',
|
|
327
|
+
'',
|
|
328
|
+
'Help (h), Quit (q): '
|
|
329
|
+
)
|
|
330
|
+
show_help_page(prompt, URL_UPGRADE_V9)
|
|
331
|
+
raise SystemExit()
|
|
216
332
|
|
|
217
333
|
def _get_docker_hostname(self):
|
|
218
334
|
try:
|
|
@@ -270,7 +386,7 @@ class Register(object):
|
|
|
270
386
|
return path
|
|
271
387
|
|
|
272
388
|
def check_group_license(self, silent=False):
|
|
273
|
-
licinfo = self.
|
|
389
|
+
licinfo = self.license_info
|
|
274
390
|
if licinfo['features'] & 8:
|
|
275
391
|
licmach = licinfo.get('machine', '')
|
|
276
392
|
if not licmach:
|
|
@@ -299,12 +415,6 @@ class Register(object):
|
|
|
299
415
|
'this group license is not for this machine')
|
|
300
416
|
|
|
301
417
|
def __str__(self):
|
|
302
|
-
'''$advanced
|
|
303
|
-
|
|
304
|
-
Notes
|
|
305
|
-
$notes
|
|
306
|
-
'''
|
|
307
|
-
|
|
308
418
|
info = self.license_info
|
|
309
419
|
lictype = self._license_type(info)
|
|
310
420
|
|
|
@@ -319,9 +429,11 @@ $notes
|
|
|
319
429
|
|
|
320
430
|
bccmode = info['features'] & 2
|
|
321
431
|
rftmode = info['features'] & 4
|
|
432
|
+
cidmode = info.get('machine', '').startswith('CITK')
|
|
322
433
|
advanced = [
|
|
323
434
|
fmt % ('BCC Mode', 'Yes' if bccmode else 'No'),
|
|
324
435
|
fmt % ('RFT Mode', 'Yes' if rftmode else 'No'),
|
|
436
|
+
fmt % ('CI/CD Mode', 'Yes' if cidmode else 'No'),
|
|
325
437
|
]
|
|
326
438
|
if lictype == 'trial':
|
|
327
439
|
self.notes.append('* Can\'t obfuscate big script and mix str')
|
|
@@ -331,7 +443,13 @@ $notes
|
|
|
331
443
|
elif lictype == 'group':
|
|
332
444
|
self.notes.append('* Offline obfuscation')
|
|
333
445
|
|
|
334
|
-
|
|
446
|
+
if info['note']:
|
|
447
|
+
self.notes.extend(info['note'].splitlines())
|
|
448
|
+
|
|
449
|
+
if self.notes:
|
|
450
|
+
self.notes.insert(0, 'Notes')
|
|
451
|
+
|
|
452
|
+
lines.append(Template(LICENSE_INFO_TEMPLATE).substitute(
|
|
335
453
|
advanced='\n'.join(advanced),
|
|
336
454
|
notes='\n'.join(self.notes),
|
|
337
455
|
))
|
|
@@ -362,6 +480,24 @@ class WebRegister(Register):
|
|
|
362
480
|
conn.request("GET", url[k:])
|
|
363
481
|
return conn.getresponse()
|
|
364
482
|
|
|
483
|
+
def check_request_interval(self, delta=30.0):
|
|
484
|
+
"""Make sure no more than 2 requests in 1 minute"""
|
|
485
|
+
tspath = os.path.join(self.ctx.reg_path, 'last_register')
|
|
486
|
+
try:
|
|
487
|
+
st = os.stat(tspath)
|
|
488
|
+
except FileNotFoundError:
|
|
489
|
+
os.makedirs(tspath)
|
|
490
|
+
else:
|
|
491
|
+
from time import sleep, time
|
|
492
|
+
d = delta - (time() - st.st_mtime)
|
|
493
|
+
if d > 0:
|
|
494
|
+
logger.info('last register was within %d seconds, '
|
|
495
|
+
'waiting for %d seconds', delta, d)
|
|
496
|
+
while time() - st.st_mtime < delta:
|
|
497
|
+
logger.info('waiting ...')
|
|
498
|
+
sleep(3.0)
|
|
499
|
+
os.utime(tspath)
|
|
500
|
+
|
|
365
501
|
def _send_request(self, url, timeout=6.0):
|
|
366
502
|
try:
|
|
367
503
|
return self._request(url)
|
|
@@ -418,16 +554,13 @@ class WebRegister(Register):
|
|
|
418
554
|
lines = []
|
|
419
555
|
if upgrade:
|
|
420
556
|
if rcode and not rcode.startswith('pyarmor-vax-'):
|
|
421
|
-
logger.error('please check Pyarmor 8 EULA')
|
|
422
557
|
raise CliError('old license "%s" can not be upgraded' % rcode)
|
|
423
558
|
if info['upgrade']:
|
|
424
559
|
lines.append(upgrade_to_pro_info.substitute(rcode=rcode))
|
|
425
560
|
else:
|
|
426
561
|
lines.append(upgrade_to_basic_info.substitute())
|
|
427
562
|
else:
|
|
428
|
-
if info['lictype'] not in ('BASIC', 'PRO', 'GROUP'):
|
|
429
|
-
logger.error('this license does not work in Pyarmor 8')
|
|
430
|
-
logger.error('please check Pyarmor 8.0 EULA')
|
|
563
|
+
if info['lictype'] not in ('BASIC', 'PRO', 'GROUP', 'CI'):
|
|
431
564
|
raise CliError('unknown license type %s' % info['lictype'])
|
|
432
565
|
lines.append('This license registration information will be')
|
|
433
566
|
|
|
@@ -492,6 +625,8 @@ class WebRegister(Register):
|
|
|
492
625
|
reginfo = self.parse_keyfile(keyfile)
|
|
493
626
|
|
|
494
627
|
url = self.regurl(reginfo[1], product=product)
|
|
628
|
+
# Request license file with extra info by rev 2
|
|
629
|
+
url += '&rev=2'
|
|
495
630
|
if upgrade:
|
|
496
631
|
url += '&upgrade_to_basic=1'
|
|
497
632
|
logger.debug('url: %s', url)
|
|
@@ -500,23 +635,37 @@ class WebRegister(Register):
|
|
|
500
635
|
res = self._send_request(url)
|
|
501
636
|
regfile = self._handle_response(res)
|
|
502
637
|
|
|
638
|
+
logger.info('')
|
|
639
|
+
logger.info('the registration file "%s" has been generated', regfile)
|
|
640
|
+
logger.info('this license has been activated sucessfully')
|
|
641
|
+
|
|
503
642
|
notes = [
|
|
504
|
-
'* Please backup
|
|
505
|
-
'
|
|
506
|
-
'*
|
|
643
|
+
'* Please backup "%s", but do not use it to '
|
|
644
|
+
'register Pyarmor' % os.path.basename(keyfile),
|
|
645
|
+
'* Please backup regfile "%s", and '
|
|
646
|
+
'use this file for next any registration' % regfile,
|
|
647
|
+
'* Do not use this file in docker and CI/CD pipeline',
|
|
507
648
|
]
|
|
508
649
|
|
|
509
650
|
if group:
|
|
510
|
-
logger.info('This group license has been activated sucessfully')
|
|
511
651
|
notes.append('* Please check `pyarmor reg` in Man page for '
|
|
512
652
|
'how to register Pyarmor on offline device')
|
|
513
|
-
|
|
653
|
+
logger.info('\n\nImport Notes:\n%s\n', '\n'.join(notes))
|
|
654
|
+
return
|
|
655
|
+
|
|
656
|
+
notes.append('')
|
|
657
|
+
notes.append('Next register Pyarmor in build device by this command:')
|
|
658
|
+
|
|
659
|
+
notes.append('\tpyarmor reg %s' % regfile)
|
|
660
|
+
notes.append('')
|
|
661
|
+
logger.info('\n\nImport Notes:\n%s\n', '\n'.join(notes))
|
|
662
|
+
|
|
663
|
+
prompt = 'Do you want register Pyarmor in this machine? (Y/n) '
|
|
664
|
+
choice = input(prompt).lower()[:1]
|
|
665
|
+
if choice == 'y':
|
|
514
666
|
logger.info('register "%s"', regfile)
|
|
515
667
|
self.register_regfile(regfile)
|
|
516
|
-
logger.info('This license
|
|
517
|
-
'upgraded' if upgrade else 'activated')
|
|
518
|
-
|
|
519
|
-
logger.info('Import Notes:\n\n%s\n', '\n'.join(notes))
|
|
668
|
+
logger.info('This license registration information:\n\n%s', self)
|
|
520
669
|
|
|
521
670
|
def _handle_response(self, res):
|
|
522
671
|
if res and res.code == 200:
|
|
@@ -529,16 +678,39 @@ class WebRegister(Register):
|
|
|
529
678
|
with open(filename, 'wb') as f:
|
|
530
679
|
f.write(data[n:])
|
|
531
680
|
self._write_group_info(filename, data[:n])
|
|
681
|
+
elif data.startswith(b'REGINFO:'):
|
|
682
|
+
i = len(b'REGINFO:')
|
|
683
|
+
n = data[i] + (data[i+1] << 8)
|
|
684
|
+
i += 2
|
|
685
|
+
n += i
|
|
686
|
+
with open(filename, 'wb') as f:
|
|
687
|
+
f.write(data[n:])
|
|
688
|
+
self._write_reg_info(filename, data[i:n])
|
|
532
689
|
else:
|
|
690
|
+
# TBD: it should not happened
|
|
691
|
+
logger.warning('no REGINFO found')
|
|
533
692
|
with open(filename, 'wb') as f:
|
|
534
693
|
f.write(data)
|
|
535
694
|
return filename
|
|
536
695
|
|
|
537
696
|
elif res:
|
|
538
|
-
|
|
697
|
+
data = res.read()
|
|
698
|
+
logger.debug('server return(%d): %s', res.code, data)
|
|
699
|
+
try:
|
|
700
|
+
msg = data.decode('utf-8')
|
|
701
|
+
except Exception as e:
|
|
702
|
+
logger.debug('decode server data error "%s"', e)
|
|
703
|
+
msg = data
|
|
704
|
+
raise CliError(msg)
|
|
539
705
|
|
|
540
706
|
raise CliError('no response from license server')
|
|
541
707
|
|
|
708
|
+
def _write_reg_info(self, filename, data):
|
|
709
|
+
from zipfile import ZipFile
|
|
710
|
+
logger.info('write reg information')
|
|
711
|
+
with ZipFile(filename, 'a') as f:
|
|
712
|
+
f.writestr('reg.info', data)
|
|
713
|
+
|
|
542
714
|
def _write_group_info(self, filename, data):
|
|
543
715
|
from zipfile import ZipFile
|
|
544
716
|
logger.info('write group information')
|
|
@@ -607,3 +779,66 @@ class WebRegister(Register):
|
|
|
607
779
|
|
|
608
780
|
logger.info('please copy deivce regfile to offline device and run')
|
|
609
781
|
logger.info(' pyarmor reg %s', filename)
|
|
782
|
+
|
|
783
|
+
def _write_ci_info(self, filename, data):
|
|
784
|
+
from zipfile import ZipFile
|
|
785
|
+
logger.info('write ci information')
|
|
786
|
+
with ZipFile(filename, 'a') as f:
|
|
787
|
+
f.writestr('ci.token', data)
|
|
788
|
+
|
|
789
|
+
def request_ci_regfile(self, regfile, rev=2):
|
|
790
|
+
logger.info('request ci regfile by "%s"', regfile)
|
|
791
|
+
from zipfile import ZipFile
|
|
792
|
+
|
|
793
|
+
with ZipFile(regfile, 'r') as f:
|
|
794
|
+
if 'reg.info' not in f.namelist():
|
|
795
|
+
logger.error('missing reg.info in regfile')
|
|
796
|
+
raise CliError('can not request CI license')
|
|
797
|
+
reginfo = json_loads(f.read('reg.info'))
|
|
798
|
+
|
|
799
|
+
ucode = reginfo['ucode']
|
|
800
|
+
rcode = reginfo['rcode']
|
|
801
|
+
if len(ucode) != 192:
|
|
802
|
+
raise CliError('invalid registration file "%s"', regfile)
|
|
803
|
+
|
|
804
|
+
url = self.regurl('ci/%s' % ucode)
|
|
805
|
+
paras = (('rev', str(rev)),)
|
|
806
|
+
url += '&'.join(['='.join(x) for x in paras])
|
|
807
|
+
logger.debug('url: %s', url)
|
|
808
|
+
|
|
809
|
+
logger.info('send request to server')
|
|
810
|
+
res = self._send_request(url)
|
|
811
|
+
|
|
812
|
+
logger.info('handle response')
|
|
813
|
+
if res is None:
|
|
814
|
+
raise CliError('no response from license server')
|
|
815
|
+
|
|
816
|
+
elif res.code != 200:
|
|
817
|
+
raise CliError(res.read().decode('utf-8'))
|
|
818
|
+
|
|
819
|
+
data = res.read()
|
|
820
|
+
if not data.startswith(b'CITOKEN:'):
|
|
821
|
+
raise CliError('wrong server data: "%s"' % data)
|
|
822
|
+
|
|
823
|
+
i = len(b'CITOKEN:') + 2
|
|
824
|
+
n = data[i-2] + (data[i-1] << 8)
|
|
825
|
+
token = data[i:i+n]
|
|
826
|
+
|
|
827
|
+
rn = rcode[-6:].lstrip('0')
|
|
828
|
+
cifile = 'pyarmor-ci-%s.zip' % rn
|
|
829
|
+
|
|
830
|
+
with ZipFile(regfile, 'r') as src:
|
|
831
|
+
with ZipFile(cifile, 'w') as dst:
|
|
832
|
+
for x in src.namelist():
|
|
833
|
+
dst.writestr(x, src.read(x))
|
|
834
|
+
dst.writestr('ci.token', token)
|
|
835
|
+
|
|
836
|
+
logger.info('generate CI regfile "%s" successfully', cifile)
|
|
837
|
+
|
|
838
|
+
ver = '.'.join([str(x) for x in self.ctx.version])
|
|
839
|
+
logger.info('\n\nCheck CI license in local machine by:\n'
|
|
840
|
+
'\n\tpyarmor reg %s\n\n'
|
|
841
|
+
'Register Pyarmor in CI/CD pipeline by:\n'
|
|
842
|
+
'\n\tpip install pyarmor==%s\n'
|
|
843
|
+
'\tpyarmor reg %s\n',
|
|
844
|
+
cifile, ver, cifile)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from sys import platform
|
|
2
2
|
|
|
3
|
-
version = '
|
|
3
|
+
version = '9.0.0'
|
|
4
4
|
|
|
5
5
|
# The corresponding version of pytransform.so
|
|
6
6
|
core_version = 'r52.6'
|
|
@@ -43,7 +43,7 @@ platform_url = 'https://pyarmor.dashingsoft.com/files/{version}'
|
|
|
43
43
|
|
|
44
44
|
key_url = 'https://api.dashingsoft.com/product/key/%s/query'
|
|
45
45
|
reg_url = 'https://api.dashingsoft.com/product/key/activate/%s/'
|
|
46
|
-
buy_url = 'https://
|
|
46
|
+
buy_url = 'https://jondy.github.io/paypal/index.html'
|
|
47
47
|
help_url = 'https://pyarmor.readthedocs.io/{lang}/v%s/{page}' % version
|
|
48
48
|
|
|
49
49
|
sppmode_info = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 1.1
|
|
2
2
|
Name: pyarmor
|
|
3
|
-
Version:
|
|
3
|
+
Version: 9.0.0
|
|
4
4
|
Summary: A tool used to obfuscate python scripts, bind obfuscated scripts to fixed machine or expire obfuscated scripts.
|
|
5
5
|
Home-page: https://github.com/dashingsoft/pyarmor
|
|
6
6
|
Author: Jondy Zhao
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pyarmor.cli.core~=7.6.0
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
pyarmor.cli.core~=6.5.3
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|