pyarmor.cli 9.2.6__3-py3-none-any.whl
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/cli/__init__.py +46 -0
- pyarmor/cli/__main__.py +812 -0
- pyarmor/cli/batch.py +62 -0
- pyarmor/cli/bootstrap.py +207 -0
- pyarmor/cli/bug.py +137 -0
- pyarmor/cli/command.py +563 -0
- pyarmor/cli/config.py +306 -0
- pyarmor/cli/context.py +790 -0
- pyarmor/cli/core.data.1 +0 -0
- pyarmor/cli/core.data.2 +0 -0
- pyarmor/cli/core.data.3 +0 -0
- pyarmor/cli/default.cfg +564 -0
- pyarmor/cli/docker.py +192 -0
- pyarmor/cli/generate.py +256 -0
- pyarmor/cli/hdinfo.py +81 -0
- pyarmor/cli/merge.py +232 -0
- pyarmor/cli/mixer.py +109 -0
- pyarmor/cli/model.py +460 -0
- pyarmor/cli/plugin.py +292 -0
- pyarmor/cli/project.py +1281 -0
- pyarmor/cli/public_capsule.zip +0 -0
- pyarmor/cli/register.py +1093 -0
- pyarmor/cli/repack.py +793 -0
- pyarmor/cli/resource.py +265 -0
- pyarmor/cli/shell.py +481 -0
- pyarmor_cli-9.2.6.dist-info/METADATA +74 -0
- pyarmor_cli-9.2.6.dist-info/RECORD +30 -0
- pyarmor_cli-9.2.6.dist-info/WHEEL +6 -0
- pyarmor_cli-9.2.6.dist-info/entry_points.txt +3 -0
- pyarmor_cli-9.2.6.dist-info/top_level.txt +1 -0
pyarmor/cli/docker.py
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#! /usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#
|
|
4
|
+
#############################################################
|
|
5
|
+
# #
|
|
6
|
+
# Copyright @ 2023 - Dashingsoft corp. #
|
|
7
|
+
# All rights reserved. #
|
|
8
|
+
# #
|
|
9
|
+
# Pyarmor #
|
|
10
|
+
# #
|
|
11
|
+
# Version: 8.3.0 - #
|
|
12
|
+
# #
|
|
13
|
+
#############################################################
|
|
14
|
+
#
|
|
15
|
+
#
|
|
16
|
+
# @File: cli/docker.py
|
|
17
|
+
#
|
|
18
|
+
# @Author: Jondy Zhao (pyarmor@163.com)
|
|
19
|
+
#
|
|
20
|
+
# @Create Date: Tue Aug 1 09:18:12 CST 2023
|
|
21
|
+
#
|
|
22
|
+
import argparse
|
|
23
|
+
import logging
|
|
24
|
+
import os
|
|
25
|
+
import socketserver
|
|
26
|
+
import struct
|
|
27
|
+
import sys
|
|
28
|
+
|
|
29
|
+
from .context import Context
|
|
30
|
+
from .generate import Pytransform3
|
|
31
|
+
from .register import Register, MACHFLAGS
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
CONFIG = {
|
|
35
|
+
'host': '0.0.0.0',
|
|
36
|
+
'port': 29092,
|
|
37
|
+
'home': os.path.expanduser(os.path.join('~', '.pyarmor', 'docker')),
|
|
38
|
+
'machid': None,
|
|
39
|
+
'ctx': None,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class DockerAuthHandler(socketserver.BaseRequestHandler):
|
|
44
|
+
|
|
45
|
+
def handle(self):
|
|
46
|
+
data = self.request.recv(64)
|
|
47
|
+
logging.info('receive request from %s', self.client_address)
|
|
48
|
+
try:
|
|
49
|
+
logging.debug('request data (%d): %s', len(data), data)
|
|
50
|
+
response = self.process(data)
|
|
51
|
+
logging.info('send auth result to %s', self.client_address)
|
|
52
|
+
logging.debug('response data (%d): %s', len(response), response)
|
|
53
|
+
except Exception as e:
|
|
54
|
+
logging.error('%s', str(e))
|
|
55
|
+
msg = 'verification failed, please check host console'.encode()
|
|
56
|
+
msg += b'\00'
|
|
57
|
+
self.request.send(struct.pack('!HH', 1, len(msg)) + msg)
|
|
58
|
+
|
|
59
|
+
def process(self, packet):
|
|
60
|
+
cmd = packet[:4]
|
|
61
|
+
if cmd == b'PADH':
|
|
62
|
+
response = b'\n'.join(CONFIG['machid']) + b'\x00'
|
|
63
|
+
self.request.send(response)
|
|
64
|
+
elif cmd == b'PADI':
|
|
65
|
+
userdata = packet[4:].decode('utf-8')
|
|
66
|
+
rtkey = self.generate_outer_key(userdata, outer=False)
|
|
67
|
+
magic = b'DockerRuntimeKey'
|
|
68
|
+
response = magic + struct.pack('!HH', 0, len(rtkey)) + rtkey
|
|
69
|
+
self.request.send(response)
|
|
70
|
+
elif cmd == b'PADK':
|
|
71
|
+
userdata = self.parse_packet(packet).decode('utf-8')
|
|
72
|
+
rtkey = self.generate_runtime_key(userdata)
|
|
73
|
+
response = struct.pack('!HH', 0, len(rtkey)) + rtkey
|
|
74
|
+
self.request.send(response)
|
|
75
|
+
else:
|
|
76
|
+
raise RuntimeError('unknown packet %r' % packet)
|
|
77
|
+
return response
|
|
78
|
+
|
|
79
|
+
def parse_packet(self, packet):
|
|
80
|
+
if len(packet) == 32 and packet[:4] == b'PADK':
|
|
81
|
+
return packet[12:]
|
|
82
|
+
raise RuntimeError('invalid auth request: %r' % packet)
|
|
83
|
+
|
|
84
|
+
def generate_runtime_key(self, userdata):
|
|
85
|
+
ctx = CONFIG['ctx']
|
|
86
|
+
ctx.cmd_options['user_data'] = userdata
|
|
87
|
+
ctx.cmd_options['expired'] = '.3'
|
|
88
|
+
ctx.cmd_options['outer'] = 0
|
|
89
|
+
Pytransform3._pytransform3.init_ctx(ctx)
|
|
90
|
+
return Pytransform3.generate_runtime_key(ctx)
|
|
91
|
+
|
|
92
|
+
def generate_outer_key(self, userdata, outer=True):
|
|
93
|
+
ctx = CONFIG['ctx']
|
|
94
|
+
ctx.cmd_options['user_data'] = userdata
|
|
95
|
+
ctx.cmd_options['expired'] = '.3'
|
|
96
|
+
ctx.cmd_options['outer'] = 1
|
|
97
|
+
Pytransform3._pytransform3.init_ctx(ctx)
|
|
98
|
+
return Pytransform3.generate_runtime_key(ctx, outer=outer)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def register_pyarmor(ctx, regfile):
|
|
102
|
+
reg = Register(ctx)
|
|
103
|
+
logging.info('register "%s"', regfile)
|
|
104
|
+
reg.register_regfile(regfile)
|
|
105
|
+
if reg.license_info['features'] < 15:
|
|
106
|
+
raise RuntimeError('this feature is only for group license')
|
|
107
|
+
Pytransform3.init(ctx)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def main_entry():
|
|
111
|
+
parser = argparse.ArgumentParser()
|
|
112
|
+
parser.add_argument('-d', '--debug', action='store_true',
|
|
113
|
+
help='Enable debug mode')
|
|
114
|
+
parser.add_argument('--host', type=str, default=CONFIG['host'])
|
|
115
|
+
parser.add_argument('-p', '--port', type=int, default=CONFIG['port'],
|
|
116
|
+
help=argparse.SUPPRESS)
|
|
117
|
+
parser.add_argument('-s', '--sock', default='/var/run/docker.sock',
|
|
118
|
+
help=argparse.SUPPRESS)
|
|
119
|
+
parser.add_argument('--home', help=argparse.SUPPRESS)
|
|
120
|
+
parser.add_argument('regfile', nargs=1,
|
|
121
|
+
help='group device registration file for this machine')
|
|
122
|
+
args = parser.parse_args(sys.argv[1:])
|
|
123
|
+
|
|
124
|
+
if args.debug:
|
|
125
|
+
logging.getLogger().setLevel(logging.DEBUG)
|
|
126
|
+
|
|
127
|
+
if args.home:
|
|
128
|
+
CONFIG['home'] = os.path.expandvars(os.path.expanduser(args.home))
|
|
129
|
+
home = CONFIG['home']
|
|
130
|
+
logging.info('work path: %s', home)
|
|
131
|
+
|
|
132
|
+
# lpath should be non-existent or empty
|
|
133
|
+
ctx = Context(home=home, lpath=os.path.join(home, 'non-existent'))
|
|
134
|
+
register_pyarmor(ctx, args.regfile[0])
|
|
135
|
+
CONFIG['ctx'] = ctx
|
|
136
|
+
|
|
137
|
+
CONFIG['machid'] = [Pytransform3.get_hd_info(x) for x in MACHFLAGS]
|
|
138
|
+
logging.debug('machine id: %s', CONFIG['machid'])
|
|
139
|
+
|
|
140
|
+
host, port = args.host, args.port
|
|
141
|
+
with socketserver.TCPServer((host, port), DockerAuthHandler) as server:
|
|
142
|
+
logging.info('listen container auth request on %s:%s', host, port)
|
|
143
|
+
server.serve_forever()
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def main():
|
|
147
|
+
logging.basicConfig(
|
|
148
|
+
level=logging.INFO,
|
|
149
|
+
format='%(asctime)s: %(message)s',
|
|
150
|
+
)
|
|
151
|
+
main_entry()
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
#
|
|
155
|
+
# Deprecrated functions
|
|
156
|
+
#
|
|
157
|
+
def get_docker_gateway(client):
|
|
158
|
+
filters = {
|
|
159
|
+
'driver': 'bridge',
|
|
160
|
+
'type': 'builtin'
|
|
161
|
+
}
|
|
162
|
+
networks = client.networks.list(filters=filters)
|
|
163
|
+
return networks[0].attrs['IPAM']['Config'][0]['Gateway']
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def get_container(client, ipaddr):
|
|
167
|
+
filters = {
|
|
168
|
+
'driver': 'bridge',
|
|
169
|
+
'type': 'builtin'
|
|
170
|
+
}
|
|
171
|
+
networks = client.networks.list(filters=filters, greedy=True)
|
|
172
|
+
containers = networks[0].attrs.get('Containers')
|
|
173
|
+
if containers:
|
|
174
|
+
marker = ipaddr + '/'
|
|
175
|
+
for dockid, netattr in containers.items():
|
|
176
|
+
if netattr.get('IPv4Address').startswith(marker):
|
|
177
|
+
return client.containers.get(dockid)
|
|
178
|
+
raise RuntimeError('no found countainer with IPv4 %s' % ipaddr)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def copy_file_into_docker(containerid, filename):
|
|
182
|
+
from subprocess import check_call
|
|
183
|
+
check_call(['docker', 'cp', filename, '%s:/' % containerid])
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def get_container_info(client, shortid):
|
|
187
|
+
container = client.container.get(shortid)
|
|
188
|
+
return container.attrs
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
if __name__ == '__main__':
|
|
192
|
+
main()
|
pyarmor/cli/generate.py
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
#! /usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#
|
|
4
|
+
#############################################################
|
|
5
|
+
# #
|
|
6
|
+
# Copyright @ 2023 - Dashingsoft corp. #
|
|
7
|
+
# All rights reserved. #
|
|
8
|
+
# #
|
|
9
|
+
# Pyarmor #
|
|
10
|
+
# #
|
|
11
|
+
# Version: 8.0.1 - #
|
|
12
|
+
# #
|
|
13
|
+
#############################################################
|
|
14
|
+
#
|
|
15
|
+
#
|
|
16
|
+
# @File: cli/generate.py
|
|
17
|
+
#
|
|
18
|
+
# @Author: Jondy Zhao (pyarmor@163.com)
|
|
19
|
+
#
|
|
20
|
+
# @Create Date: 2022-12-06
|
|
21
|
+
#
|
|
22
|
+
import os
|
|
23
|
+
import shutil
|
|
24
|
+
|
|
25
|
+
from pyarmor.cli.core import Pytransform3
|
|
26
|
+
|
|
27
|
+
from . import logger, CliError
|
|
28
|
+
from .resource import FileResource, PathResource
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class Finder(object):
|
|
32
|
+
|
|
33
|
+
def __init__(self, ctx):
|
|
34
|
+
self.ctx = ctx
|
|
35
|
+
|
|
36
|
+
def _build_resource(self, pathlist):
|
|
37
|
+
resources = []
|
|
38
|
+
for path in pathlist:
|
|
39
|
+
if not os.path.exists(path):
|
|
40
|
+
raise CliError('argument "%s" doesn\'t exists' % path)
|
|
41
|
+
if os.path.isfile(path):
|
|
42
|
+
logger.info('find script %s', path)
|
|
43
|
+
res = FileResource(path)
|
|
44
|
+
resources.append(res)
|
|
45
|
+
else:
|
|
46
|
+
logger.info('find package at %s', path)
|
|
47
|
+
res = PathResource(path)
|
|
48
|
+
resources.append(res)
|
|
49
|
+
options = self.ctx.get_res_options(res.fullname)
|
|
50
|
+
res.rebuild(**options)
|
|
51
|
+
return resources
|
|
52
|
+
|
|
53
|
+
def prepare(self, input_paths):
|
|
54
|
+
self.ctx.resources = self._build_resource(input_paths)
|
|
55
|
+
|
|
56
|
+
def process_extra(self, contents):
|
|
57
|
+
extra_paths = [x for x in contents if x.endswith('.pyc')]
|
|
58
|
+
for pyz in [x for x in contents if x.endswith('.pyz_extracted')]:
|
|
59
|
+
extra_paths.extend([os.path.join(pyz, x) for x in os.listdir(pyz)])
|
|
60
|
+
resnames = [x.pkgname for x in self.ctx.resources]
|
|
61
|
+
for res in self._build_resource(extra_paths):
|
|
62
|
+
if res.pkgname not in resnames:
|
|
63
|
+
self.ctx.obfuscated_modules.add(res.pkgname)
|
|
64
|
+
self.ctx.extra_resources.append(res)
|
|
65
|
+
|
|
66
|
+
def append(self, resources):
|
|
67
|
+
resnames = [x.pkgname for x in self.ctx.resources]
|
|
68
|
+
for res in self._build_resource(resources):
|
|
69
|
+
if res.pkgname not in resnames:
|
|
70
|
+
self.ctx.obfuscated_modules.add(res.pkgname)
|
|
71
|
+
self.ctx.resources.append(res)
|
|
72
|
+
|
|
73
|
+
def process(self):
|
|
74
|
+
logger.info('search inputs ...')
|
|
75
|
+
self.prepare(self.ctx.input_paths)
|
|
76
|
+
logger.info('find %d top resources', len(self.ctx.resources))
|
|
77
|
+
|
|
78
|
+
modules = [x.fullname for res in self.ctx.resources for x in res
|
|
79
|
+
if x.is_script()]
|
|
80
|
+
self.ctx.obfuscated_modules.update(modules)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class Builder(object):
|
|
84
|
+
|
|
85
|
+
def __init__(self, ctx):
|
|
86
|
+
self.ctx = ctx
|
|
87
|
+
|
|
88
|
+
def format_output(self, outputs, count=0):
|
|
89
|
+
try:
|
|
90
|
+
output = outputs[count]
|
|
91
|
+
except IndexError:
|
|
92
|
+
output = self.ctx.alias_suffix.format(outputs[0], count)
|
|
93
|
+
return output
|
|
94
|
+
|
|
95
|
+
def generate_runtime_key(self, outer=None):
|
|
96
|
+
return Pytransform3.generate_runtime_key(self.ctx, outer)
|
|
97
|
+
|
|
98
|
+
def generate_runtime_package(self, output):
|
|
99
|
+
if self.ctx.runtime_key is None:
|
|
100
|
+
self.ctx.runtime_key = self.generate_runtime_key()
|
|
101
|
+
Pytransform3.generate_runtime_package(self.ctx, output)
|
|
102
|
+
|
|
103
|
+
def _generate_obfuscated_script(self, res):
|
|
104
|
+
try:
|
|
105
|
+
return Pytransform3.generate_obfuscated_script(self.ctx, res)
|
|
106
|
+
except RuntimeError as e:
|
|
107
|
+
if str(e) != 'out of license':
|
|
108
|
+
raise
|
|
109
|
+
|
|
110
|
+
def _copy_script(self, path, res):
|
|
111
|
+
logger.warning('%s is not obfuscated because out of license', res)
|
|
112
|
+
fullpath = os.path.join(path, res.output_filename)
|
|
113
|
+
output = os.path.dirname(fullpath)
|
|
114
|
+
os.makedirs(output, exist_ok=True)
|
|
115
|
+
logger.info('write %s (not obfuscated)', fullpath)
|
|
116
|
+
shutil.copy2(res.fullpath, output)
|
|
117
|
+
|
|
118
|
+
def _obfuscate_scripts(self):
|
|
119
|
+
rev = self.ctx.version_info()
|
|
120
|
+
template = self.ctx.bootstrap_template
|
|
121
|
+
relative = self.ctx.import_prefix
|
|
122
|
+
pkgname = self.ctx.runtime_package_name
|
|
123
|
+
bootpath = self.ctx.cfg.get('builder', 'bootstrap_file')
|
|
124
|
+
encoding = self.ctx.cfg.get('builder', 'encoding')
|
|
125
|
+
|
|
126
|
+
plugins = [x for x in self.ctx.plugins if hasattr(x, 'post_script')]
|
|
127
|
+
|
|
128
|
+
namelist = []
|
|
129
|
+
for res in self.ctx.resources + self.ctx.extra_resources:
|
|
130
|
+
logger.info('process resource "%s"', res.fullname)
|
|
131
|
+
name = res.name
|
|
132
|
+
path = self.format_output(self.ctx.outputs, namelist.count(name))
|
|
133
|
+
namelist.append(name)
|
|
134
|
+
os.makedirs(path, exist_ok=True)
|
|
135
|
+
|
|
136
|
+
for r in res:
|
|
137
|
+
if not r.is_script():
|
|
138
|
+
logger.info('copy data file %s', r.fullpath)
|
|
139
|
+
data_path = os.path.join(path, r.output_path)
|
|
140
|
+
os.makedirs(data_path, exist_ok=True)
|
|
141
|
+
shutil.copy2(r.fullpath, data_path)
|
|
142
|
+
continue
|
|
143
|
+
|
|
144
|
+
logger.info('obfuscating %s', r)
|
|
145
|
+
code = Pytransform3.generate_obfuscated_script(self.ctx, r)
|
|
146
|
+
source = r.generate_output(
|
|
147
|
+
template, code, relative=relative, pkgname=pkgname,
|
|
148
|
+
bootpath=bootpath, rev=rev
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
fullpath = os.path.join(path, r.output_filename)
|
|
152
|
+
os.makedirs(os.path.dirname(fullpath), exist_ok=True)
|
|
153
|
+
|
|
154
|
+
for plugin in plugins:
|
|
155
|
+
patched_source = plugin.post_script(self.ctx, r, source)
|
|
156
|
+
if patched_source:
|
|
157
|
+
source = patched_source
|
|
158
|
+
|
|
159
|
+
logger.info('write %s', fullpath)
|
|
160
|
+
with open(fullpath, 'w', encoding=encoding) as f:
|
|
161
|
+
f.write(source)
|
|
162
|
+
|
|
163
|
+
def process(self, options, packer=None):
|
|
164
|
+
for opt in options['inputs']:
|
|
165
|
+
if not os.path.exists(opt):
|
|
166
|
+
raise CliError('no found input "%s"' % opt)
|
|
167
|
+
self.ctx.input_paths = options['inputs']
|
|
168
|
+
|
|
169
|
+
output = options.get('output', 'dist')
|
|
170
|
+
self.ctx.outputs = output.split(',')
|
|
171
|
+
|
|
172
|
+
finder = Finder(self.ctx)
|
|
173
|
+
finder.process()
|
|
174
|
+
|
|
175
|
+
if packer and hasattr(packer, 'analysis'):
|
|
176
|
+
auto_resources = packer.analysis()
|
|
177
|
+
logger.info('find extra resources: %s', auto_resources)
|
|
178
|
+
finder.append(auto_resources)
|
|
179
|
+
|
|
180
|
+
Pytransform3.pre_build(self.ctx)
|
|
181
|
+
|
|
182
|
+
self.ctx.runtime_key = self.generate_runtime_key()
|
|
183
|
+
if not options.get('no_runtime'):
|
|
184
|
+
logger.info('start to generate runtime files')
|
|
185
|
+
self.generate_runtime_package(self.ctx.outputs[0])
|
|
186
|
+
logger.info('generate runtime files OK')
|
|
187
|
+
|
|
188
|
+
logger.info('start to obfuscate scripts')
|
|
189
|
+
n = self.ctx.cfg.getint('builder', 'max_workers')
|
|
190
|
+
async_obfuscate_scripts(self, n) if n else self._obfuscate_scripts()
|
|
191
|
+
logger.info('obfuscate scripts OK')
|
|
192
|
+
|
|
193
|
+
Pytransform3.post_build(self.ctx)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def async_obfuscate_scripts(builder, max_workers):
|
|
197
|
+
from concurrent.futures import ProcessPoolExecutor, wait
|
|
198
|
+
|
|
199
|
+
ctx = builder.ctx
|
|
200
|
+
rev = ctx.version_info()
|
|
201
|
+
template = ctx.bootstrap_template
|
|
202
|
+
relative = ctx.import_prefix
|
|
203
|
+
pkgname = ctx.runtime_package_name
|
|
204
|
+
bootpath = ctx.cfg.get('builder', 'bootstrap_file')
|
|
205
|
+
encoding = ctx.cfg.get('builder', 'encoding')
|
|
206
|
+
max_workers = None if max_workers < 2 else max_workers
|
|
207
|
+
|
|
208
|
+
plugins = [x for x in ctx.plugins if hasattr(x, 'post_script')]
|
|
209
|
+
|
|
210
|
+
namelist = []
|
|
211
|
+
futures = []
|
|
212
|
+
|
|
213
|
+
with ProcessPoolExecutor(max_workers=max_workers) as executor:
|
|
214
|
+
for res in ctx.resources + ctx.extra_resources:
|
|
215
|
+
logger.info('process resource "%s"', res.fullname)
|
|
216
|
+
name = res.name
|
|
217
|
+
path = builder.format_output(ctx.outputs, namelist.count(name))
|
|
218
|
+
namelist.append(name)
|
|
219
|
+
os.makedirs(path, exist_ok=True)
|
|
220
|
+
|
|
221
|
+
for r in res:
|
|
222
|
+
if not r.is_script():
|
|
223
|
+
logger.info('copy data file %s', r.fullpath)
|
|
224
|
+
data_path = os.path.join(path, r.output_path)
|
|
225
|
+
os.makedirs(data_path, exist_ok=True)
|
|
226
|
+
shutil.copy2(r.fullpath, data_path)
|
|
227
|
+
continue
|
|
228
|
+
|
|
229
|
+
logger.info('obfuscating %s', r)
|
|
230
|
+
futures.append(executor.submit(aysnc_generate_script, *(
|
|
231
|
+
r, path, ctx, template, relative, pkgname, bootpath,
|
|
232
|
+
rev, plugins, encoding)))
|
|
233
|
+
|
|
234
|
+
wait(futures)
|
|
235
|
+
for x in futures:
|
|
236
|
+
x.result()
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def aysnc_generate_script(r, path, ctx, template, relative,
|
|
240
|
+
pkgname, bootpath, rev, plugins, encoding):
|
|
241
|
+
code = Pytransform3.generate_obfuscated_script(ctx, r)
|
|
242
|
+
source = r.generate_output(
|
|
243
|
+
template, code, relative=relative, pkgname=pkgname,
|
|
244
|
+
bootpath=bootpath, rev=rev
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
fullpath = os.path.join(path, r.output_filename)
|
|
248
|
+
os.makedirs(os.path.dirname(fullpath), exist_ok=True)
|
|
249
|
+
|
|
250
|
+
for plugin in plugins:
|
|
251
|
+
patched_source = plugin.post_script(ctx, r, source)
|
|
252
|
+
if patched_source:
|
|
253
|
+
source = patched_source
|
|
254
|
+
|
|
255
|
+
with open(fullpath, 'w', encoding=encoding) as f:
|
|
256
|
+
f.write(source)
|
pyarmor/cli/hdinfo.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#! /usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#
|
|
4
|
+
#############################################################
|
|
5
|
+
# #
|
|
6
|
+
# Copyright @ 2023 - Dashingsoft corp. #
|
|
7
|
+
# All rights reserved. #
|
|
8
|
+
# #
|
|
9
|
+
# Pyarmor #
|
|
10
|
+
# #
|
|
11
|
+
# Version: 8.4.6 - #
|
|
12
|
+
# #
|
|
13
|
+
#############################################################
|
|
14
|
+
#
|
|
15
|
+
#
|
|
16
|
+
# @File: cli/hdinfo.py
|
|
17
|
+
#
|
|
18
|
+
# @Author: Jondy Zhao (pyarmor@163.com)
|
|
19
|
+
#
|
|
20
|
+
# @Create Date: Fri Dec 15 09:27:30 CST 2023
|
|
21
|
+
#
|
|
22
|
+
import argparse
|
|
23
|
+
import sys
|
|
24
|
+
|
|
25
|
+
from pyarmor.cli.core import Pytransform3
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
GROUP_LICENSE_MACHINE_FLAG = 22
|
|
29
|
+
HT_HARDDISK, HT_IFMAC, HT_IPV4, HT_IPV6, HT_DOMAIN = range(5)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_hd_info(hdtype, name=None):
|
|
33
|
+
try:
|
|
34
|
+
return repr(Pytransform3.get_hd_info(hdtype, name))
|
|
35
|
+
except Exception as e:
|
|
36
|
+
return str(e)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def get_all_ifmac():
|
|
40
|
+
try:
|
|
41
|
+
buf = Pytransform3.get_hd_info(HT_IFMAC, name='*')
|
|
42
|
+
i = 0
|
|
43
|
+
n = len(buf)
|
|
44
|
+
rlist = []
|
|
45
|
+
while i < n and buf[i]:
|
|
46
|
+
j = i + 1 + buf[i]
|
|
47
|
+
rlist.append(':'.join(['%02x' % x for x in buf[i+1:j]]))
|
|
48
|
+
i = j
|
|
49
|
+
except Exception as e:
|
|
50
|
+
return str(e)
|
|
51
|
+
|
|
52
|
+
return '<%s>' % ','.join(set(rlist))
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def main(argv):
|
|
56
|
+
parser = argparse.ArgumentParser()
|
|
57
|
+
parser.add_argument('devname', nargs='*', help=(
|
|
58
|
+
'In Linux get netcard name like "eth0" '
|
|
59
|
+
'or harddisk name like "/dev/sda"'))
|
|
60
|
+
args = parser.parse_args(argv)
|
|
61
|
+
|
|
62
|
+
print('Machine ID: %s' % get_hd_info(GROUP_LICENSE_MACHINE_FLAG)[1:])
|
|
63
|
+
|
|
64
|
+
if not args.devname:
|
|
65
|
+
print('Default Harddisk Serial Number: %s' % get_hd_info(HT_HARDDISK))
|
|
66
|
+
print('Default Mac address: %s' % get_hd_info(HT_IFMAC))
|
|
67
|
+
print('Default IPv4 address: %s' % get_hd_info(HT_IPV4))
|
|
68
|
+
print('Multiple Mac addresses: %s' % get_all_ifmac())
|
|
69
|
+
print('Domain: %s' % get_hd_info(HT_DOMAIN))
|
|
70
|
+
|
|
71
|
+
for name in args.devname:
|
|
72
|
+
if name.startswith('/'):
|
|
73
|
+
print('Query Harddisk "%s" Serial Number: %s' %
|
|
74
|
+
(name, get_hd_info(HT_HARDDISK, name=name)))
|
|
75
|
+
else:
|
|
76
|
+
print('Query Netcard "/dev/%s" Mac Address: %s' %
|
|
77
|
+
(name, get_hd_info(HT_IFMAC, name=name)))
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
if __name__ == '__main__':
|
|
81
|
+
main(sys.argv[1:])
|