InPanel 1.2.1__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.
- inpanel/__init__.py +29 -0
- inpanel/acme.py +289 -0
- inpanel/aliyuncs.py +269 -0
- inpanel/app.py +514 -0
- inpanel/apt.py +223 -0
- inpanel/base.py +200 -0
- inpanel/config.py +139 -0
- inpanel/data/config.ini +29 -0
- inpanel/data/history +5 -0
- inpanel/data/runlogs.ini +12 -0
- inpanel/data/update_info.ini +4 -0
- inpanel/dnf.py +225 -0
- inpanel/lib/__init__.py +9 -0
- inpanel/lib/async_process.py +98 -0
- inpanel/lib/filelock.py +82 -0
- inpanel/lib/magic.py +233 -0
- inpanel/lib/pxssh.py +310 -0
- inpanel/lib/pyDes.py +867 -0
- inpanel/mod/__init__.py +0 -0
- inpanel/mod/apt.py +316 -0
- inpanel/mod/certificate.py +268 -0
- inpanel/mod/config.py +372 -0
- inpanel/mod/cron.py +315 -0
- inpanel/mod/disk.py +322 -0
- inpanel/mod/dnf.py +239 -0
- inpanel/mod/file.py +722 -0
- inpanel/mod/firewall.py +199 -0
- inpanel/mod/firewall_base.py +137 -0
- inpanel/mod/firewall_firewalld.py +170 -0
- inpanel/mod/firewall_iptables.py +176 -0
- inpanel/mod/firewall_macos.py +213 -0
- inpanel/mod/firewall_ufw.py +128 -0
- inpanel/mod/ftp.py +231 -0
- inpanel/mod/httpd.py +1205 -0
- inpanel/mod/lighttpd.py +26 -0
- inpanel/mod/login.py +98 -0
- inpanel/mod/mysql.py +577 -0
- inpanel/mod/named.py +26 -0
- inpanel/mod/nginx.py +2327 -0
- inpanel/mod/package.py +33 -0
- inpanel/mod/package_apt.py +62 -0
- inpanel/mod/package_base.py +77 -0
- inpanel/mod/package_dnf.py +62 -0
- inpanel/mod/package_map.py +366 -0
- inpanel/mod/package_yum.py +64 -0
- inpanel/mod/php.py +289 -0
- inpanel/mod/process.py +291 -0
- inpanel/mod/proftpd.py +26 -0
- inpanel/mod/pureftpd.py +26 -0
- inpanel/mod/query.py +108 -0
- inpanel/mod/server.py +1319 -0
- inpanel/mod/service.py +262 -0
- inpanel/mod/setting.py +228 -0
- inpanel/mod/shell.py +78 -0
- inpanel/mod/ssh.py +280 -0
- inpanel/mod/system.py +220 -0
- inpanel/mod/task.py +1337 -0
- inpanel/mod/ufw.py +14 -0
- inpanel/mod/user.py +306 -0
- inpanel/mod/vsftpd.py +67 -0
- inpanel/mod/yum.py +243 -0
- inpanel/plugins/__init__.py +10 -0
- inpanel/plugins/__pycache__/__init__.cpython-313.pyc +0 -0
- inpanel/plugins/acme/static/index.html +10 -0
- inpanel/plugins/acme/static/index.js +13 -0
- inpanel/plugins/shadowsocks-libev/__pycache__/info.cpython-313.pyc +0 -0
- inpanel/plugins/shadowsocks-libev/info.py +73 -0
- inpanel/plugins/shadowsocks-libev/static/index.html +70 -0
- inpanel/plugins/shadowsocks-libev/static/index.js +18 -0
- inpanel/public/css/global.css +138 -0
- inpanel/public/favicon.ico +0 -0
- inpanel/public/images/alipay.jpg +0 -0
- inpanel/public/images/loading.gif +0 -0
- inpanel/public/images/weixin.jpg +0 -0
- inpanel/public/index.html +94 -0
- inpanel/public/js/controllers/controllers.js +566 -0
- inpanel/public/js/controllers/database.js +590 -0
- inpanel/public/js/controllers/ecs.js +624 -0
- inpanel/public/js/controllers/file.js +940 -0
- inpanel/public/js/controllers/plugins.js +105 -0
- inpanel/public/js/controllers/service.js +1460 -0
- inpanel/public/js/controllers/site.js +1241 -0
- inpanel/public/js/controllers/utils.js +2319 -0
- inpanel/public/js/core.js +221 -0
- inpanel/public/js/directives.js +784 -0
- inpanel/public/js/filters.js +395 -0
- inpanel/public/js/services.js +257 -0
- inpanel/public/lib/angular/1.0.2/angular-resource.min.js +10 -0
- inpanel/public/lib/angular/1.0.2/angular.min.js +158 -0
- inpanel/public/lib/bootstrap/css/bootstrap-theme.css +587 -0
- inpanel/public/lib/bootstrap/css/bootstrap-theme.css.map +1 -0
- inpanel/public/lib/bootstrap/css/bootstrap-theme.min.css +6 -0
- inpanel/public/lib/bootstrap/css/bootstrap-theme.min.css.map +1 -0
- inpanel/public/lib/bootstrap/css/bootstrap.css +6757 -0
- inpanel/public/lib/bootstrap/css/bootstrap.css.map +1 -0
- inpanel/public/lib/bootstrap/css/bootstrap.min.css +6 -0
- inpanel/public/lib/bootstrap/css/bootstrap.min.css.map +1 -0
- inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.eot +0 -0
- inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.svg +288 -0
- inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf +0 -0
- inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.woff +0 -0
- inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.woff2 +0 -0
- inpanel/public/lib/bootstrap/img/glyphicons-halflings-white.png +0 -0
- inpanel/public/lib/bootstrap/img/glyphicons-halflings.png +0 -0
- inpanel/public/lib/bootstrap/js/bootstrap.js +2377 -0
- inpanel/public/lib/bootstrap/js/bootstrap.min.js +7 -0
- inpanel/public/lib/bootstrap/js/npm.js +13 -0
- inpanel/public/lib/codemirror/codemirror-compressed.js +1 -0
- inpanel/public/lib/codemirror/codemirror.css +173 -0
- inpanel/public/lib/jquery/jquery-1.12.4.min.js +5 -0
- inpanel/public/lib/md5/md5.js +379 -0
- inpanel/public/lib/md5/md5.min.js +1 -0
- inpanel/public/partials/database/index.html +172 -0
- inpanel/public/partials/database/mysql/dbedit.html +462 -0
- inpanel/public/partials/database/mysql/dbnew.html +348 -0
- inpanel/public/partials/database/mysql/useredit.html +310 -0
- inpanel/public/partials/database/mysql/usernew.html +97 -0
- inpanel/public/partials/directives/message.html +20 -0
- inpanel/public/partials/directives/navbar.html +25 -0
- inpanel/public/partials/directives/selector.html +57 -0
- inpanel/public/partials/directives/srvbase.html +72 -0
- inpanel/public/partials/directives/srvext.html +34 -0
- inpanel/public/partials/directives/srvfile.html +23 -0
- inpanel/public/partials/directives/srvinstall.html +34 -0
- inpanel/public/partials/directives/srvlog.html +23 -0
- inpanel/public/partials/directives/srvminiop.html +28 -0
- inpanel/public/partials/directives/srvuninstall.html +38 -0
- inpanel/public/partials/directives/srvupdate.html +30 -0
- inpanel/public/partials/ecs/account.html +156 -0
- inpanel/public/partials/ecs/ecs.html +198 -0
- inpanel/public/partials/ecs/index.html +40 -0
- inpanel/public/partials/ecs/setings.html +459 -0
- inpanel/public/partials/file/file.html +501 -0
- inpanel/public/partials/file/trash.html +95 -0
- inpanel/public/partials/ftp.html +36 -0
- inpanel/public/partials/log.html +83 -0
- inpanel/public/partials/login.html +79 -0
- inpanel/public/partials/logout.html +22 -0
- inpanel/public/partials/main.html +534 -0
- inpanel/public/partials/plugins/index.html +55 -0
- inpanel/public/partials/plugins/plugins.html +13 -0
- inpanel/public/partials/secure.html +13 -0
- inpanel/public/partials/service/apache.html +147 -0
- inpanel/public/partials/service/cron.html +71 -0
- inpanel/public/partials/service/index.html +293 -0
- inpanel/public/partials/service/iptables.html +40 -0
- inpanel/public/partials/service/lighttpd.html +63 -0
- inpanel/public/partials/service/mariadb.html +113 -0
- inpanel/public/partials/service/memcache.html +36 -0
- inpanel/public/partials/service/minio.html +44 -0
- inpanel/public/partials/service/mongodb.html +44 -0
- inpanel/public/partials/service/mysql.html +113 -0
- inpanel/public/partials/service/named.html +61 -0
- inpanel/public/partials/service/nginx.html +296 -0
- inpanel/public/partials/service/ntp.html +40 -0
- inpanel/public/partials/service/php.html +250 -0
- inpanel/public/partials/service/proftpd.html +59 -0
- inpanel/public/partials/service/pureftpd.html +59 -0
- inpanel/public/partials/service/redis.html +40 -0
- inpanel/public/partials/service/samba.html +58 -0
- inpanel/public/partials/service/sendmail.html +40 -0
- inpanel/public/partials/service/ssh.html +186 -0
- inpanel/public/partials/service/tomcat.html +65 -0
- inpanel/public/partials/service/vsftpd.html +195 -0
- inpanel/public/partials/setting.html +299 -0
- inpanel/public/partials/site/apache/site.html +277 -0
- inpanel/public/partials/site/index.html +344 -0
- inpanel/public/partials/site/nginx/site.html +558 -0
- inpanel/public/partials/sorry.html +19 -0
- inpanel/public/partials/storage/autofm.html +103 -0
- inpanel/public/partials/storage/backup.html +42 -0
- inpanel/public/partials/storage/index.html +360 -0
- inpanel/public/partials/storage/migrate.html +93 -0
- inpanel/public/partials/storage/movedata.html +98 -0
- inpanel/public/partials/storage/remote.html +77 -0
- inpanel/public/partials/utils/cron.html +486 -0
- inpanel/public/partials/utils/firewall.html +266 -0
- inpanel/public/partials/utils/index.html +193 -0
- inpanel/public/partials/utils/network.html +118 -0
- inpanel/public/partials/utils/process.html +239 -0
- inpanel/public/partials/utils/repository.html +373 -0
- inpanel/public/partials/utils/shell.html +28 -0
- inpanel/public/partials/utils/ssl.html +319 -0
- inpanel/public/partials/utils/time.html +109 -0
- inpanel/public/partials/utils/user.html +359 -0
- inpanel/public/robots.txt +2 -0
- inpanel/remote.py +109 -0
- inpanel/templates/file/preview.html +34 -0
- inpanel/templates/index.html +93 -0
- inpanel/utils.py +282 -0
- inpanel/web.py +1811 -0
- inpanel/yum.py +756 -0
- inpanel-1.2.1.dist-info/METADATA +399 -0
- inpanel-1.2.1.dist-info/RECORD +198 -0
- inpanel-1.2.1.dist-info/WHEEL +5 -0
- inpanel-1.2.1.dist-info/entry_points.txt +2 -0
- inpanel-1.2.1.dist-info/licenses/LICENSE +30 -0
- inpanel-1.2.1.dist-info/top_level.txt +1 -0
inpanel/utils.py
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2017-2026 Jackson Dou
|
|
4
|
+
# All rights reserved.
|
|
5
|
+
#
|
|
6
|
+
# InPanel is distributed under the terms of the (new) BSD License.
|
|
7
|
+
# The full license can be found in 'LICENSE'.
|
|
8
|
+
|
|
9
|
+
'''Package for Utils.'''
|
|
10
|
+
|
|
11
|
+
import base64
|
|
12
|
+
import random
|
|
13
|
+
import re
|
|
14
|
+
import socket
|
|
15
|
+
import string
|
|
16
|
+
import time
|
|
17
|
+
import uuid
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def randstr(length=32):
|
|
21
|
+
"""Generate a fixed-length random string.
|
|
22
|
+
"""
|
|
23
|
+
# table = range(0x30, 0x3a) + range(0x41, 0x5b) + range(0x61, 0x7b)
|
|
24
|
+
# pop = [chr(i) for i in table]
|
|
25
|
+
return ''.join(random.sample('abcdefghijklmnopqrstuvwxyz!@#$%^&*()', length))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def make_cookie_secret():
|
|
29
|
+
return base64.b64encode(uuid.uuid4().bytes + uuid.uuid4().bytes).decode('utf-8')
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def is_valid_ip(ip):
|
|
33
|
+
'''Validates IP addresses.'''
|
|
34
|
+
return is_valid_ipv4(ip) or is_valid_ipv6(ip)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def is_valid_ipv4(ip):
|
|
38
|
+
'''Validates IPv4 addresses.'''
|
|
39
|
+
if not ip or ip == '':
|
|
40
|
+
return False
|
|
41
|
+
try:
|
|
42
|
+
socket.inet_pton(socket.AF_INET, ip)
|
|
43
|
+
return True
|
|
44
|
+
except socket.error:
|
|
45
|
+
return False
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def is_valid_ipv6(ip):
|
|
49
|
+
'''Validates IPv6 addresses.'''
|
|
50
|
+
if not ip or ip == '':
|
|
51
|
+
return False
|
|
52
|
+
try:
|
|
53
|
+
socket.inet_pton(socket.AF_INET6, ip)
|
|
54
|
+
return True
|
|
55
|
+
except socket.error:
|
|
56
|
+
return False
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def is_valid_netmask(mask):
|
|
60
|
+
"""Validates IPv4 sub-network mask.
|
|
61
|
+
"""
|
|
62
|
+
return mask in map(lambda x: ipv4_cidr_to_netmask(x), range(0, 33))
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def ipv4_cidr_to_netmask(bits):
|
|
66
|
+
"""Convert CIDR bits to netmask """
|
|
67
|
+
netmask = ''
|
|
68
|
+
for i in range(4):
|
|
69
|
+
if i:
|
|
70
|
+
netmask += '.'
|
|
71
|
+
if bits >= 8:
|
|
72
|
+
netmask += '%d' % (2**8-1)
|
|
73
|
+
bits -= 8
|
|
74
|
+
else:
|
|
75
|
+
netmask += '%d' % (256-2**(8-bits))
|
|
76
|
+
bits = 0
|
|
77
|
+
return netmask
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def b2h(n):
|
|
81
|
+
# bypes to human
|
|
82
|
+
# http://code.activestate.com/recipes/578019
|
|
83
|
+
# >>> b2h(10000)
|
|
84
|
+
# '9.8K'
|
|
85
|
+
# >>> b2h(100001221)
|
|
86
|
+
# '95.4M'
|
|
87
|
+
symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
|
|
88
|
+
prefix = {}
|
|
89
|
+
for i, s in enumerate(symbols):
|
|
90
|
+
prefix[s] = 1 << (i+1)*10
|
|
91
|
+
for s in reversed(symbols):
|
|
92
|
+
if n >= prefix[s]:
|
|
93
|
+
value = float(n) / prefix[s]
|
|
94
|
+
return '%.1f%s' % (value, s)
|
|
95
|
+
return "%sB" % n
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def ftime(secs):
|
|
99
|
+
return time.strftime('%Y-%m-%d %X', time.localtime(secs))
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def is_valid_domain(name, allow_localname=True):
|
|
103
|
+
'''Validates domain name.'''
|
|
104
|
+
if not name or name == '':
|
|
105
|
+
return False
|
|
106
|
+
name = name.lower()
|
|
107
|
+
if allow_localname:
|
|
108
|
+
pt = r'^(?:(?:(?:[a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z0-9])\.)*(?:(?:[a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z0-9])$'
|
|
109
|
+
else:
|
|
110
|
+
pt = r'^(?:(?:(?:[a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z0-9])\.)+[a-z]{2,6}$'
|
|
111
|
+
return re.match(pt, name.decode('utf-8')) and True or False
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def is_url(url):
|
|
115
|
+
'''Check that the URL is in the correct format'''
|
|
116
|
+
return re.match('[a-z]+://.+', url) and True or False
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def version_get(v1, v2):
|
|
120
|
+
"""Check if version v1 is great or equal then version v2.
|
|
121
|
+
"""
|
|
122
|
+
return [int(i) for i in v1.split('.') if i.isdigit()] > [int(i) for i in v2.split('.') if i.isdigit()]
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def valid_filename(filename):
|
|
126
|
+
"""Check if a filename is validate.
|
|
127
|
+
"""
|
|
128
|
+
valid_chars = "-_.() %s%s" % (string.ascii_letters, string.digits)
|
|
129
|
+
return not any([c for c in filename if c not in valid_chars])
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def callbackable(func):
|
|
133
|
+
"""Make a function callbackable.
|
|
134
|
+
"""
|
|
135
|
+
def wrapper(*args, **kwds):
|
|
136
|
+
callback = kwds['callback']
|
|
137
|
+
if callback:
|
|
138
|
+
del kwds['callback']
|
|
139
|
+
result = func(*args, **kwds)
|
|
140
|
+
if callback:
|
|
141
|
+
return callback(result)
|
|
142
|
+
else:
|
|
143
|
+
return result
|
|
144
|
+
return wrapper
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def loadconfig(cfgfile, delimiter, detail=False):
|
|
148
|
+
"""Read config file and parse config item to dict.
|
|
149
|
+
"""
|
|
150
|
+
#if not cfgfile: cfgfile = SSHCFG
|
|
151
|
+
|
|
152
|
+
settings = {}
|
|
153
|
+
with open(cfgfile, encoding='utf-8') as f:
|
|
154
|
+
for line_i, line in enumerate(f):
|
|
155
|
+
line = line.strip()
|
|
156
|
+
if not line or line.startswith('# '):
|
|
157
|
+
continue
|
|
158
|
+
|
|
159
|
+
# detect if it's commented
|
|
160
|
+
if line.startswith('#'):
|
|
161
|
+
line = line.strip('#')
|
|
162
|
+
commented = True
|
|
163
|
+
if not detail:
|
|
164
|
+
continue
|
|
165
|
+
else:
|
|
166
|
+
commented = False
|
|
167
|
+
|
|
168
|
+
fs = re.split(delimiter, line, 1)
|
|
169
|
+
if len(fs) != 2:
|
|
170
|
+
continue
|
|
171
|
+
|
|
172
|
+
item = fs[0].strip()
|
|
173
|
+
value = fs[1].strip()
|
|
174
|
+
|
|
175
|
+
if item in settings:
|
|
176
|
+
if detail:
|
|
177
|
+
count = settings[item]['count'] + 1
|
|
178
|
+
if not commented:
|
|
179
|
+
settings[item] = detail and {
|
|
180
|
+
'file': cfgfile,
|
|
181
|
+
'line': line_i,
|
|
182
|
+
'value': value,
|
|
183
|
+
'commented': commented,
|
|
184
|
+
} or value
|
|
185
|
+
else:
|
|
186
|
+
count = 1
|
|
187
|
+
settings[item] = detail and {
|
|
188
|
+
'file': cfgfile,
|
|
189
|
+
'line': line_i,
|
|
190
|
+
'value': fs[1].strip(),
|
|
191
|
+
'commented': commented,
|
|
192
|
+
} or value
|
|
193
|
+
if detail:
|
|
194
|
+
settings[item]['count'] = count
|
|
195
|
+
|
|
196
|
+
return settings
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def cfg_get(cfgfile, item, delimiter, detail=False, config=None):
|
|
200
|
+
"""Get value of a config item.
|
|
201
|
+
"""
|
|
202
|
+
if not config:
|
|
203
|
+
config = loadconfig(cfgfile, delimiter, detail=detail)
|
|
204
|
+
if item in config:
|
|
205
|
+
return config[item]
|
|
206
|
+
else:
|
|
207
|
+
return None
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def cfg_set(cfgfile, item, value, delimiter, commented=False, config=None):
|
|
211
|
+
"""Set value of a config item.
|
|
212
|
+
"""
|
|
213
|
+
#cfgfile = SSHCFG
|
|
214
|
+
v = cfg_get(cfgfile, item, delimiter, detail=True, config=config)
|
|
215
|
+
if delimiter == r'\s+':
|
|
216
|
+
delimiter = ' '
|
|
217
|
+
if v:
|
|
218
|
+
# detect if value change
|
|
219
|
+
if v['commented'] == commented and v['value'] == value:
|
|
220
|
+
return True
|
|
221
|
+
|
|
222
|
+
# empty value should be commented
|
|
223
|
+
if value == '':
|
|
224
|
+
commented = True
|
|
225
|
+
|
|
226
|
+
# replace item in line
|
|
227
|
+
lines = []
|
|
228
|
+
with open(v['file'], encoding='utf-8') as f:
|
|
229
|
+
for line_i, line in enumerate(f):
|
|
230
|
+
if line_i == v['line']:
|
|
231
|
+
if not v['commented']:
|
|
232
|
+
if commented:
|
|
233
|
+
if v['count'] > 1:
|
|
234
|
+
# delete this line, just ignore it
|
|
235
|
+
pass
|
|
236
|
+
else:
|
|
237
|
+
# comment this line
|
|
238
|
+
lines.append('#%s%s%s\n' %
|
|
239
|
+
(item, delimiter, value))
|
|
240
|
+
else:
|
|
241
|
+
lines.append('%s%s%s\n' % (item, delimiter, value))
|
|
242
|
+
else:
|
|
243
|
+
if commented:
|
|
244
|
+
# do not allow change comment value
|
|
245
|
+
lines.append(line)
|
|
246
|
+
pass
|
|
247
|
+
else:
|
|
248
|
+
# append a new line after comment line
|
|
249
|
+
lines.append(line)
|
|
250
|
+
lines.append('%s%s%s\n' % (item, delimiter, value))
|
|
251
|
+
else:
|
|
252
|
+
lines.append(line)
|
|
253
|
+
with open(v['file'], 'w', encoding='utf-8') as f:
|
|
254
|
+
f.write(''.join(lines))
|
|
255
|
+
else:
|
|
256
|
+
# append to the end of file
|
|
257
|
+
with open(cfgfile, 'a', encoding='utf-8') as f:
|
|
258
|
+
f.write('\n%s%s%s\n' % (item, delimiter, value))
|
|
259
|
+
|
|
260
|
+
return True
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def cfg_get_array(cfgfile, configs_array, delimiter):
|
|
264
|
+
for key in configs_array:
|
|
265
|
+
q_value = cfg_get(cfgfile, key, delimiter)
|
|
266
|
+
configs_array[key] = q_value
|
|
267
|
+
return configs_array
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def cfg_set_array(cfgfile, configs_array, delimiter):
|
|
271
|
+
for key in configs_array:
|
|
272
|
+
q_value = cfg_get(cfgfile, key, delimiter)
|
|
273
|
+
if q_value:
|
|
274
|
+
cfg_set(cfgfile, key, q_value, delimiter)
|
|
275
|
+
return True
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def gen_accesskey():
|
|
279
|
+
"""Generate a access key.
|
|
280
|
+
"""
|
|
281
|
+
keys = [chr(int(random.random()*256)) for i in range(0, 32)]
|
|
282
|
+
return base64.b64encode(''.join(keys))
|