mirror of
https://github.com/aaPanel/aaPanel.git
synced 2026-09-28 20:34:52 +02:00
Update to 7.7.0
Since version 7.7.0, we recommend yours update python to 3.12. [+] Using nginx technology to load static files improves access speed [+] Refactor homepage, website, FTP, and database using vue3 [+] Table loading changed to skeleton screen [+] Add Website statistics-v2 professional plug-in [+] Add Home page - top 5 resource occupancy [+] Add protection for Files management (requires Tamper-proof for Enterprise 3.7) [+] Website, FTP, Databases page add program status [+] Add FTP log analysis (only supports Centos) [+] Add password-free login to phpMyAdmin [+] Add Proxy Project in Website (Supported when web service uses Nginx) [+] Add WP Toolkit (Pro version only) [+] Redesigned Docker module [+] Add WP Toolkit Protection [+] Add WP Toolkit Backup and Restore [+] Add WP Toolkit Migrated [+] Add WP Toolkit Clone site (supports new domain and subdomain) [+] Add WP Toolkit Create site from backup of other panel [+] Add WP Toolkit support for Cron automatic backup (only save Local disk) [+] Add WP Toolkit operation log [+] Add Integrity check for WP Toolkit [+] Add WP Toolkit plug-in management and themes management [*] Optimize phpMyAdmin formula access method [*] Optimize Home page PHP display problem [*] Optimize jump to the login interface after the login expires [*] Optimize automatic renewal of SSL at some times [*] Optimize Let's Encrypt to increase application success rate [-] Fix Logs Audit cannot be opened [-] Fix apache URL rewrite issue [-] Fix phpmyadmin installation problem [-] Fix the problem that some servers cannot install software [-] Fix upload file error [-] Fix left menu hiding problem [-] Fix aaPanel Mobile QR code display problem [-] Fix problem that third-party plug-ins are not displayed in the App Store [-] Fix issue where the menu bar is blank when opening new tabs [-] Fixed panel not being accessible in some cases [-] Fix the issue where Curl warning caused the inability to apply for SSL [-] Fix Quota issues for Website, FTP, Databases [-] Fix file interface display problem on mobile terminal
This commit is contained in:
Binary file not shown.
Binary file not shown.
+621
-416
File diff suppressed because it is too large
Load Diff
+26
-123
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2016 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2016 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# | Author: hwliang <hwl@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
from flask import session,request
|
||||
|
||||
@@ -794,19 +794,19 @@ class ajax:
|
||||
if not os.path.exists(filename): return public.return_msg_gettext(False,'Requested PHP version does NOT exist!')
|
||||
phpini = public.readFile(filename)
|
||||
data = {}
|
||||
rep = "disable_functions\s*=\s{0,1}(.*)\n"
|
||||
rep = "disable_functions\\s*=\\s{0,1}(.*)\n"
|
||||
|
||||
tmp = re.search(rep,phpini)
|
||||
if tmp:
|
||||
data['disable_functions'] = tmp.groups()[0]
|
||||
|
||||
rep = "upload_max_filesize\s*=\s*([0-9]+)(M|m|K|k)"
|
||||
rep = r"upload_max_filesize\s*=\s*([0-9]+)(M|m|K|k)"
|
||||
|
||||
tmp = re.search(rep,phpini)
|
||||
if tmp:
|
||||
data['max'] = tmp.groups()[0]
|
||||
|
||||
rep = u"\n;*\s*cgi\.fix_pathinfo\s*=\s*([0-9]+)\s*\n"
|
||||
rep = u"\n;*\\s*cgi\\.fix_pathinfo\\s*=\\s*([0-9]+)\\s*\n"
|
||||
tmp = re.search(rep,phpini)
|
||||
if tmp:
|
||||
if tmp.groups()[0] == '0':
|
||||
@@ -1048,7 +1048,7 @@ class ajax:
|
||||
#AUTH_END
|
||||
"""
|
||||
# nginx配置文件
|
||||
ssl_conf = """server
|
||||
ssl_conf = r"""server
|
||||
{
|
||||
listen 887 ssl;
|
||||
server_name phpmyadmin;
|
||||
@@ -1095,7 +1095,7 @@ class ajax:
|
||||
#AUTH_END
|
||||
"""
|
||||
# apache配置
|
||||
ssl_conf = '''Listen 887
|
||||
ssl_conf = r'''Listen 887
|
||||
<VirtualHost *:887>
|
||||
ServerAdmin webmaster@example.com
|
||||
DocumentRoot "/www/server/phpmyadmin"
|
||||
@@ -1134,6 +1134,13 @@ class ajax:
|
||||
</Directory>
|
||||
</VirtualHost>'''.format(public.get_php_proxy(v["ext"]["phpversion"],'apache'),auth)
|
||||
public.writeFile("/www/server/panel/vhost/apache/phpmyadmin.conf", ssl_conf)
|
||||
|
||||
import firewalls
|
||||
fw = firewalls.firewalls()
|
||||
fw.AddAcceptPort(public.to_dict_obj({
|
||||
'port': '887',
|
||||
'ps': public.get_msg_gettext('New phpMyAdmin SSL Port'),
|
||||
}))
|
||||
else:
|
||||
if os.path.exists("/www/server/panel/vhost/nginx/phpmyadmin.conf"):
|
||||
os.remove("/www/server/panel/vhost/nginx/phpmyadmin.conf")
|
||||
@@ -1331,9 +1338,9 @@ class ajax:
|
||||
conf = public.readFile('/etc/init.d/memcached')
|
||||
result = {}
|
||||
result['bind'] = re.search('IP=(.+)',conf).groups()[0]
|
||||
result['port'] = int(re.search('PORT=(\d+)',conf).groups()[0])
|
||||
result['maxconn'] = int(re.search('MAXCONN=(\d+)',conf).groups()[0])
|
||||
result['cachesize'] = int(re.search('CACHESIZE=(\d+)',conf).groups()[0])
|
||||
result['port'] = int(re.search(r'PORT=(\d+)',conf).groups()[0])
|
||||
result['maxconn'] = int(re.search(r'MAXCONN=(\d+)',conf).groups()[0])
|
||||
result['cachesize'] = int(re.search(r'CACHESIZE=(\d+)',conf).groups()[0])
|
||||
tn = telnetlib.Telnet(result['bind'],result['port'])
|
||||
tn.write(b"stats\n")
|
||||
tn.write(b"quit\n")
|
||||
@@ -1358,9 +1365,9 @@ class ajax:
|
||||
confFile = '/etc/init.d/memcached'
|
||||
conf = public.readFile(confFile)
|
||||
conf = re.sub('IP=.+','IP='+get.ip,conf)
|
||||
conf = re.sub('PORT=\d+','PORT='+get.port,conf)
|
||||
conf = re.sub('MAXCONN=\d+','MAXCONN='+get.maxconn,conf)
|
||||
conf = re.sub('CACHESIZE=\d+','CACHESIZE='+get.cachesize,conf)
|
||||
conf = re.sub(r'PORT=\d+','PORT='+get.port,conf)
|
||||
conf = re.sub(r'MAXCONN=\d+','MAXCONN='+get.maxconn,conf)
|
||||
conf = re.sub(r'CACHESIZE=\d+','CACHESIZE='+get.cachesize,conf)
|
||||
public.writeFile(confFile,conf)
|
||||
public.ExecShell(confFile + ' reload')
|
||||
return public.return_msg_gettext(True,'Setup successfully!')
|
||||
@@ -1369,8 +1376,8 @@ class ajax:
|
||||
def GetRedisStatus(self,get):
|
||||
import re
|
||||
c = public.readFile('/www/server/redis/redis.conf')
|
||||
port = re.findall('\n\s*port\s+(\d+)',c)[0]
|
||||
password = re.findall('\n\s*requirepass\s+(.+)',c)
|
||||
port = re.findall('\n\\s*port\\s+(\\d+)',c)[0]
|
||||
password = re.findall('\n\\s*requirepass\\s+(.+)',c)
|
||||
if password:
|
||||
password = ' -a ' + password[0]
|
||||
else:
|
||||
@@ -1431,113 +1438,9 @@ class ajax:
|
||||
if not os.path.exists(get.path): return public.return_msg_gettext(False,'Log file does NOT exist!')
|
||||
return public.returnMsg(True,public.xsssec(public.GetNumLines(get.path,1000)))
|
||||
|
||||
def get_pd(self,get):
|
||||
from BTPanel import cache
|
||||
tmp = -1
|
||||
try:
|
||||
import panelPlugin
|
||||
# get = public.dict_obj()
|
||||
# get.init = 1
|
||||
tmp1 = panelPlugin.panelPlugin().get_cloud_list(get)
|
||||
except:
|
||||
tmp1 = None
|
||||
if tmp1:
|
||||
tmp = tmp1[public.to_string([112, 114, 111])]
|
||||
ltd = tmp1.get('ltd', -1)
|
||||
else:
|
||||
ltd = -1
|
||||
tmp4 = cache.get(public.to_string([112, 95, 116, 111, 107, 101, 110]))
|
||||
if tmp4:
|
||||
tmp_f = public.to_string([47, 116, 109, 112, 47]) + tmp4
|
||||
if not os.path.exists(tmp_f): public.writeFile(tmp_f, '-1')
|
||||
tmp = public.readFile(tmp_f)
|
||||
if tmp: tmp = int(tmp)
|
||||
if not ltd: ltd = -1
|
||||
if tmp == None: tmp = -1
|
||||
if ltd < 1:
|
||||
if ltd == -2:
|
||||
tmp3 = public.to_string(
|
||||
[60, 115, 112, 97, 110, 32, 99, 108, 97, 115, 115, 61, 34, 98, 116, 108, 116, 100,
|
||||
45, 103, 114, 97, 121, 34, 62, 60, 115, 112, 97, 110, 32, 115, 116, 121, 108, 101,
|
||||
61, 34, 99, 111, 108, 111, 114, 58, 32, 35, 102, 99, 54, 100, 50, 54, 59, 102, 111,
|
||||
110, 116, 45, 119, 101, 105, 103, 104, 116, 58, 32, 98, 111, 108, 100, 59, 109, 97,
|
||||
114, 103, 105, 110, 45, 114, 105, 103, 104, 116, 58, 53, 112, 120, 34, 62, 24050, 36807,
|
||||
26399, 60, 47, 115, 112, 97, 110, 62, 60, 97, 32, 99, 108, 97, 115, 115, 61, 34, 98, 116,
|
||||
108, 105, 110, 107, 34, 32, 111, 110, 99, 108, 105, 99, 107, 61, 34, 98, 116, 46, 115, 111,
|
||||
102, 116, 46, 117, 112, 100, 97, 116, 97, 95, 108, 116, 100, 40, 41, 34, 62, 82, 69, 78, 69, 87,
|
||||
60, 47, 97,
|
||||
62, 60, 47, 115, 112, 97, 110, 62])
|
||||
elif tmp == -1:
|
||||
tmp3 = public.to_string([60, 115, 112, 97, 110, 32, 99, 108, 97, 115, 115, 61, 34, 98,
|
||||
116, 112, 114, 111, 45, 102, 114, 101, 101, 34, 32, 111, 110, 99, 108, 105, 99,
|
||||
107,
|
||||
61, 34, 98, 116, 46, 115, 111, 102, 116, 46, 114, 101, 110, 101, 119, 95, 112,
|
||||
114,
|
||||
111, 40, 41, 34, 32, 116, 105, 116, 108, 101, 61, 34, 67, 108, 105, 99, 107,
|
||||
32, 116, 111, 32,
|
||||
103, 101, 116, 32, 80, 82, 79, 34, 62, 20813, 36153, 29256, 60, 47, 115, 112,
|
||||
97, 110, 62])
|
||||
elif tmp == -2:
|
||||
tmp3 = public.to_string([60, 115, 112, 97, 110, 32, 99, 108, 97, 115, 115, 61, 34, 98, 116,
|
||||
112, 114, 111, 45, 103, 114, 97, 121, 34, 62, 60, 115, 112, 97, 110, 32,
|
||||
115, 116, 121, 108, 101, 61, 34, 99, 111, 108, 111, 114, 58, 32, 35,
|
||||
102, 99, 54, 100, 50, 54, 59, 102, 111, 110, 116, 45, 119, 101, 105, 103,
|
||||
104, 116, 58, 32, 98, 111, 108, 100, 59, 109, 97, 114, 103, 105, 110, 45,
|
||||
114, 105, 103, 104, 116, 58, 53, 112, 120, 34, 62, 24050, 36807, 26399,
|
||||
60, 47, 115, 112, 97, 110, 62, 60, 97, 32, 99, 108, 97, 115, 115, 61, 34,
|
||||
98, 116, 108, 105, 110, 107, 34, 32, 111, 110, 99, 108, 105, 99, 107, 61,
|
||||
34, 98, 116, 46, 115, 111, 102, 116, 46, 114, 101, 110, 101, 119, 95, 112, 114,
|
||||
111, 40, 41, 34, 62, 82, 69, 78, 69, 87, 60, 47, 97, 62, 60, 47, 115, 112, 97,
|
||||
110, 62])
|
||||
if tmp >= 0 and ltd in [-1, -2]:
|
||||
if tmp == 0:
|
||||
|
||||
tmp2 = public.to_string([76, 105, 102, 101, 116, 105, 109, 101])
|
||||
tmp3 = public.to_string(
|
||||
[60, 115, 112, 97, 110, 32, 99, 108, 97, 115, 115, 61, 34, 98, 116, 112, 114,
|
||||
111, 34, 62, 69, 120, 112, 105, 114, 101, 58, 60, 115, 112, 97, 110, 32, 115,
|
||||
116, 121, 108, 101, 61, 34, 99, 111, 108, 111, 114, 58, 32, 35, 102, 99, 54,
|
||||
100, 50, 54, 59, 102, 111, 110, 116, 45, 119, 101, 105, 103, 104, 116, 58, 32,
|
||||
98, 111, 108, 100, 59, 34, 62, 123, 48, 125, 60, 47, 115, 112, 97, 110, 62, 60,
|
||||
47, 115, 112, 97, 110, 62]).format(tmp2)
|
||||
else:
|
||||
tmp2 = time.strftime(public.to_string([37, 89, 45, 37, 109, 45, 37, 100]), time.localtime(tmp))
|
||||
tmp3 = public.to_string([60, 115, 112, 97, 110, 32, 99, 108, 97, 115, 115, 61, 34, 98, 116,
|
||||
112, 114, 111, 34, 62, 69, 120, 112, 105, 114, 101, 58, 32, 60, 115, 112,
|
||||
97, 110, 32, 115, 116, 121, 108, 101, 61, 34, 99, 111, 108, 111, 114,
|
||||
58, 32, 35, 102, 99, 54, 100, 50, 54, 59, 102, 111, 110, 116, 45, 119,
|
||||
101, 105, 103, 104, 116, 58, 32, 98, 111, 108, 100, 59, 109, 97, 114,
|
||||
103, 105, 110, 45, 114, 105, 103, 104, 116, 58, 53, 112, 120, 34, 62, 123,
|
||||
48, 125, 60, 47, 115, 112, 97, 110, 62, 60, 97, 32, 99, 108, 97, 115,
|
||||
115, 61, 34, 98, 116, 108, 105, 110, 107, 34, 32, 111, 110, 99, 108, 105,
|
||||
99,
|
||||
107, 61, 34, 98, 116, 46, 115, 111, 102, 116, 46, 114, 101, 110, 101, 119,
|
||||
95,
|
||||
112, 114, 111, 40, 41, 34, 62, 82, 69, 78, 69, 87, 60, 47, 97, 62, 60,
|
||||
47, 115, 112, 97, 110, 62]).format(tmp2)
|
||||
else:
|
||||
tmp3 = public.to_string([60, 115, 112, 97, 110, 32, 99, 108, 97, 115, 115, 61, 34, 98, 116, 112,
|
||||
114, 111, 45, 103, 114, 97, 121, 34, 32, 111, 110, 99, 108, 105, 99, 107,
|
||||
61, 34, 98, 116, 46, 115, 111, 102, 116, 46, 117, 112, 100, 97, 116, 97, 95, 112,
|
||||
114, 111, 40, 41, 34, 32, 116, 105, 116, 108, 101, 61, 34, 67, 108, 105, 99,
|
||||
107, 32, 116,
|
||||
111, 32, 103, 101, 116, 32, 80, 82, 79, 34, 62, 70, 82,
|
||||
69, 69, 60, 47, 115, 112, 97, 110, 62])
|
||||
else:
|
||||
tmp3 = public.to_string([60, 115, 112, 97, 110, 32, 99, 108, 97, 115, 115, 61, 34, 98, 116, 108, 116,
|
||||
100, 34, 62, 69, 120, 112, 105, 114, 101, 58, 32, 60, 115, 112, 97, 110, 32, 115,
|
||||
116,
|
||||
121, 108, 101, 61, 34, 99, 111, 108, 111, 114, 58, 32, 35, 102, 99, 54, 100, 50,
|
||||
54, 59, 102, 111, 110, 116, 45, 119, 101, 105, 103, 104, 116, 58, 32, 98, 111,
|
||||
108, 100, 59, 109, 97, 114, 103, 105, 110, 45, 114, 105, 103, 104, 116, 58, 53,
|
||||
112, 120, 34, 62, 123, 125, 60, 47, 115, 112, 97, 110, 62, 60, 97, 32, 99, 108,
|
||||
97, 115, 115, 61, 34, 98, 116, 108, 105, 110, 107, 34, 32, 111, 110, 99, 108, 105,
|
||||
99, 107, 61, 34, 98, 116, 46, 115, 111, 102, 116, 46, 114, 101, 110, 101, 119, 95,
|
||||
112, 114, 111, 40, 41, 34, 62, 82, 69, 78, 69, 87, 60, 47, 97, 62, 60, 47, 115,
|
||||
112, 97, 110, 62]).format(
|
||||
time.strftime(public.to_string([37, 89, 45, 37, 109, 45, 37, 100]), time.localtime(ltd)))
|
||||
|
||||
return tmp3, tmp, ltd
|
||||
# 获取授权信息
|
||||
def get_pd(self, get):
|
||||
return public.get_pd(get)
|
||||
|
||||
#检查用户绑定是否正确
|
||||
def check_user_auth(self,get):
|
||||
|
||||
+26
-26
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2018 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2018 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
@@ -52,7 +52,7 @@ class apache:
|
||||
data = {}
|
||||
|
||||
# 计算启动时间
|
||||
Uptime = re.search("ServerUptimeSeconds:\s+(.*)",result)
|
||||
Uptime = re.search(r"ServerUptimeSeconds:\s+(.*)",result)
|
||||
if not Uptime:
|
||||
return public.return_msg_gettext(False, "Get worker Uptime False")
|
||||
Uptime = int(Uptime.group(1))
|
||||
@@ -63,11 +63,11 @@ class apache:
|
||||
min = math.floor(min - (days * 60 * 24) - (hours * 60))
|
||||
|
||||
#格式化重启时间
|
||||
restarttime = re.search("RestartTime:\s+(.*)",result)
|
||||
restarttime = re.search(r"RestartTime:\s+(.*)",result)
|
||||
if not restarttime:
|
||||
return public.return_msg_gettext(False, "Get worker Restart Time False")
|
||||
restarttime = restarttime.group(1)
|
||||
rep = "\w+,\s([\w-]+)\s([\d\:]+)\s\w+"
|
||||
rep = r"\w+,\s([\w-]+)\s([\d\:]+)\s\w+"
|
||||
date = re.search(rep,restarttime)
|
||||
if not date:
|
||||
return public.return_msg_gettext(False, "Get worker date False")
|
||||
@@ -85,28 +85,28 @@ class apache:
|
||||
date = date.split("-")
|
||||
date = "%s-%s-%s" % (date[2],date[1],date[0])
|
||||
|
||||
reqpersec = re.search("ReqPerSec:\s+(.*)", result)
|
||||
reqpersec = re.search(r"ReqPerSec:\s+(.*)", result)
|
||||
if not reqpersec:
|
||||
return public.return_msg_gettext(False, "Get worker reqpersec False")
|
||||
reqpersec = reqpersec.group(1)
|
||||
if re.match("^\.", reqpersec):
|
||||
if re.match(r"^\.", reqpersec):
|
||||
reqpersec = "%s%s" % (0,reqpersec)
|
||||
data["RestartTime"] = "%s %s" % (date,timedetail)
|
||||
data["UpTime"] = "%s day %s hour %s minute" % (str(int(days)),str(int(hours)),str(int(min)))
|
||||
total_acc = re.search("Total Accesses:\s+(\d+)",result)
|
||||
total_acc = re.search(r"Total Accesses:\s+(\d+)",result)
|
||||
if not total_acc:
|
||||
return public.return_msg_gettext(False, "Get worker TotalAccesses False")
|
||||
data["TotalAccesses"] = total_acc.group(1)
|
||||
total_kb = re.search("Total kBytes:\s+(\d+)",result)
|
||||
total_kb = re.search(r"Total kBytes:\s+(\d+)",result)
|
||||
if not total_kb:
|
||||
return public.return_msg_gettext(False, "Get worker TotalKBytes False")
|
||||
data["TotalKBytes"] = total_kb.group(1)
|
||||
data["ReqPerSec"] = round(float(reqpersec), 2)
|
||||
busywork = re.search("BusyWorkers:\s+(\d+)",result)
|
||||
busywork = re.search(r"BusyWorkers:\s+(\d+)",result)
|
||||
if not busywork:
|
||||
return public.return_msg_gettext(False, "Get worker BusyWorkers False")
|
||||
data["BusyWorkers"] = busywork.group(1)
|
||||
idlework = re.search("IdleWorkers:\s+(\d+)",result)
|
||||
idlework = re.search(r"IdleWorkers:\s+(\d+)",result)
|
||||
if not idlework:
|
||||
return public.return_msg_gettext(False, "Get worker IdleWorkers False")
|
||||
data["IdleWorkers"] = idlework.group(1)
|
||||
@@ -119,7 +119,7 @@ class apache:
|
||||
apachempmcontent = public.readFile(self.apachempmfile)
|
||||
if not "mpm_event_module" in apachempmcontent:
|
||||
return public.returnMsg(False,"mpm_event_module conf not found or /www/server/apache/conf/extra/httpd-mpm.conf is empty")
|
||||
apachempmcontent = re.search("\<IfModule mpm_event_module\>(\n|.)+?\</IfModule\>",apachempmcontent).group()
|
||||
apachempmcontent = re.search(r"\<IfModule mpm_event_module\>(\n|.)+?\</IfModule\>",apachempmcontent).group()
|
||||
ps = ["%s,%s" % (public.get_msg_gettext('Second'),public.get_msg_gettext('Request timeout')),
|
||||
public.get_msg_gettext('Keep alive'),
|
||||
"%s,%s" % (public.get_msg_gettext('Second'),public.get_msg_gettext('Connection timeout')),
|
||||
@@ -131,7 +131,7 @@ class apache:
|
||||
conflist = []
|
||||
n = 0
|
||||
for i in gets:
|
||||
rep = "(%s)\s+(\w+)" % i
|
||||
rep = r"(%s)\s+(\w+)" % i
|
||||
k = re.search(rep, apachedefaultcontent)
|
||||
if not k:
|
||||
return public.return_msg_gettext(False, "Get Key {} False",(i,))
|
||||
@@ -154,7 +154,7 @@ class apache:
|
||||
gets = ["StartServers","MaxSpareThreads","MinSpareThreads","ThreadsPerChild","MaxRequestWorkers","MaxConnectionsPerChild"]
|
||||
n = 0
|
||||
for i in gets:
|
||||
rep = "(%s)\s+(\w+)" % i
|
||||
rep = r"(%s)\s+(\w+)" % i
|
||||
k = re.search(rep, apachempmcontent)
|
||||
if not k:
|
||||
return public.return_msg_gettext(False, "Get Key {} False",(i,))
|
||||
@@ -175,7 +175,7 @@ class apache:
|
||||
if not "mpm_event_module" in apachempmcontent:
|
||||
return public.return_msg_gettext(False,"mpm_event_module conf not found or /www/server/apache/conf/extra/httpd-mpm.conf is empty")
|
||||
conflist = []
|
||||
getdict = get.__dict__
|
||||
getdict = get.get_items()
|
||||
for i in getdict.keys():
|
||||
if i != "__module__" and i != "__doc__" and i != "data" and i != "args" and i != "action":
|
||||
getpost = {
|
||||
@@ -189,11 +189,11 @@ class apache:
|
||||
return public.return_msg_gettext(False, 'Parameter ERROR!')
|
||||
else:
|
||||
print(c["value"])
|
||||
if not re.search("\d+", c["value"]):
|
||||
if not re.search(r"\d+", c["value"]):
|
||||
print(c["name"],c["value"])
|
||||
return public.return_msg_gettext(False, 'Parameter ERROR!')
|
||||
|
||||
rep = "%s\s+\w+" % c["name"]
|
||||
rep = r"%s\s+\w+" % c["name"]
|
||||
if re.search(rep,apachedefaultcontent):
|
||||
newconf = "%s %s" % (c["name"],c["value"])
|
||||
apachedefaultcontent = re.sub(rep,newconf,apachedefaultcontent)
|
||||
@@ -214,7 +214,7 @@ class apache:
|
||||
def add_httpd_access_log_format(self,args):
|
||||
'''
|
||||
@name 添加httpd日志格式
|
||||
@author zhwen<zhw@bt.cn>
|
||||
@author zhwen<zhw@aapanel.com>
|
||||
@param log_format 需要设置的日志格式["$server_name","$remote_addr","-"....]
|
||||
@param log_format_name
|
||||
@param act 操作方式 add/edit
|
||||
@@ -244,13 +244,13 @@ class apache:
|
||||
def del_httpd_access_log_format(self,args):
|
||||
'''
|
||||
@name 删除日志格式
|
||||
@author zhwen<zhw@bt.cn>
|
||||
@author zhwen<zhw@aapanel.com>
|
||||
@param log_format_name
|
||||
'''
|
||||
conf = public.readFile(self.httpdconf)
|
||||
if not conf:
|
||||
return public.return_msg_gettext(False, 'Configuration file not exist')
|
||||
reg = '\s*#LOG_FORMAT_BEGIN_{n}(\n|.)+#LOG_FORMAT_END_{n}\n?'.format(n=args.log_format_name)
|
||||
reg = r'\s*#LOG_FORMAT_BEGIN_{n}(\n|.)+#LOG_FORMAT_END_{n}\n?'.format(n=args.log_format_name)
|
||||
conf = re.sub(reg,'',conf)
|
||||
self._del_format_log_of_website(args.log_format_name)
|
||||
public.writeFile(self.httpdconf,conf)
|
||||
@@ -270,7 +270,7 @@ class apache:
|
||||
if not site_format_log_status[s]:
|
||||
continue
|
||||
website_conf_file = '/www/server/panel/vhost/apache/{}.conf'.format(s)
|
||||
format_exist_reg = 'CustomLog\s+"/www.*"\s+{}'.format(log_format_name)
|
||||
format_exist_reg = r'CustomLog\s+"/www.*"\s+{}'.format(log_format_name)
|
||||
conf = public.readFile(website_conf_file)
|
||||
if not conf:continue
|
||||
if not re.search(format_exist_reg,conf):continue
|
||||
@@ -323,7 +323,7 @@ class apache:
|
||||
format_name = [i.split('LOG_FORMAT_BEGIN_')[-1] for i in data]
|
||||
format_log = {}
|
||||
for i in format_name:
|
||||
format_reg = "#LOG_FORMAT_BEGIN_{n}(\n|.)+LogFormat\s+\'(.*)\'\s+{n}".format(n=i)
|
||||
format_reg = r"#LOG_FORMAT_BEGIN_{n}(\n|.)+LogFormat\s+\'(.*)\'\s+{n}".format(n=i)
|
||||
tmp = re.search(format_reg,conf)
|
||||
if not tmp:
|
||||
continue
|
||||
@@ -336,7 +336,7 @@ class apache:
|
||||
def set_httpd_format_log_to_website(self,args):
|
||||
'''
|
||||
@name 设置网站日志格式
|
||||
@author zhwen<zhw@bt.cn>
|
||||
@author zhwen<zhw@aapanel.com>
|
||||
@param sites aaa.com,bbb.com
|
||||
@param log_format_name
|
||||
'''
|
||||
@@ -344,13 +344,13 @@ class apache:
|
||||
sites = loads(args.sites)
|
||||
try:
|
||||
all_site = public.M('sites').field('name').select()
|
||||
reg = 'CustomLog\s+"/www.*{}\s*'.format(args.log_format_name)
|
||||
reg = r'CustomLog\s+"/www.*{}\s*'.format(args.log_format_name)
|
||||
for site in all_site:
|
||||
website_conf_file = '/www/server/panel/vhost/apache/{}.conf'.format(site['name'])
|
||||
conf = public.readFile(website_conf_file)
|
||||
if not conf:
|
||||
return public.return_msg_gettext(False, 'Configuration file not exist')
|
||||
format_exist_reg = '(CustomLog\s+"/www.*\_log).*'
|
||||
format_exist_reg = r'(CustomLog\s+"/www.*\_log).*'
|
||||
access_log = re.search(format_exist_reg, conf).groups()[0] + '" ' + args.log_format_name
|
||||
if site['name'] not in sites and re.search(format_exist_reg,conf):
|
||||
access_log = ' '.join(access_log.split()[:-1])
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
# coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 1249648969@qq.com
|
||||
# | 主控 备份
|
||||
@@ -283,7 +283,7 @@ class backup_bak:
|
||||
public.ExecShell("sed -i '/password=/d' /etc/my.cnf")
|
||||
if act:
|
||||
mycnf = public.readFile('/etc/my.cnf');
|
||||
rep = "\[mysqldump\]\nuser=root"
|
||||
rep = "\\[mysqldump\\]\nuser=root"
|
||||
sea = "[mysqldump]\n"
|
||||
subStr = sea + "user=root\npassword=\"" + root + "\"\n";
|
||||
mycnf = mycnf.replace(sea,subStr)
|
||||
|
||||
+152
-1
@@ -47,6 +47,9 @@ class SimpleCache(BaseCache):
|
||||
__session_key = 'BT_:'
|
||||
__session_basedir = '/www/server/panel/data/session'
|
||||
|
||||
__SHM_PREFIX = 'SHM_:'
|
||||
__SHM_BASEDIR = '/dev/shm/aap-shm'
|
||||
|
||||
def __init__(self, threshold=500, default_timeout=300):
|
||||
BaseCache.__init__(self, default_timeout)
|
||||
self._cache = {}
|
||||
@@ -109,6 +112,15 @@ class SimpleCache(BaseCache):
|
||||
|
||||
def get(self, key):
|
||||
if not isinstance(key,str): return None
|
||||
|
||||
try:
|
||||
# 优先从shm中查找
|
||||
_shm_val = self.__get_shm(key)
|
||||
|
||||
if _shm_val is not None:
|
||||
return _shm_val
|
||||
except: pass
|
||||
|
||||
try:
|
||||
expires, value = self._cache[key]
|
||||
if expires == 0 or expires > time():
|
||||
@@ -125,6 +137,12 @@ class SimpleCache(BaseCache):
|
||||
if value_type not in type_list:
|
||||
return False
|
||||
|
||||
try:
|
||||
# 优先写入shm
|
||||
if self.__set_shm(key, value, timeout):
|
||||
return True
|
||||
except: pass
|
||||
|
||||
# 过期清理
|
||||
expires = self._normalize_timeout(timeout)
|
||||
self._prune()
|
||||
@@ -148,6 +166,12 @@ class SimpleCache(BaseCache):
|
||||
if value_type not in type_list:
|
||||
return False
|
||||
|
||||
try:
|
||||
# 优先写入shm
|
||||
if self.__add_shm(key, value, timeout):
|
||||
return True
|
||||
except: pass
|
||||
|
||||
expires = self._normalize_timeout(timeout)
|
||||
self._prune()
|
||||
try:
|
||||
@@ -162,11 +186,23 @@ class SimpleCache(BaseCache):
|
||||
return True
|
||||
|
||||
def delete(self, key):
|
||||
try:
|
||||
# 优先删除shm
|
||||
if self.__del_shm(key):
|
||||
return True
|
||||
except: pass
|
||||
|
||||
result = self._cache.pop(key, None) is not None
|
||||
self.del_session_by_file(key)
|
||||
return result
|
||||
|
||||
def has(self, key):
|
||||
try:
|
||||
# 优先shm
|
||||
if self.__has_shm(key):
|
||||
return True
|
||||
except: pass
|
||||
|
||||
try:
|
||||
expires, value = self._cache[key]
|
||||
return expires == 0 or expires > time()
|
||||
@@ -174,7 +210,6 @@ class SimpleCache(BaseCache):
|
||||
if self.get_session_by_file(key): return True
|
||||
return False
|
||||
|
||||
|
||||
def get_expire_time(self, key):
|
||||
try:
|
||||
expires, value = self._cache[key]
|
||||
@@ -194,3 +229,119 @@ class SimpleCache(BaseCache):
|
||||
m.update(strings.encode('utf-8'))
|
||||
return m.hexdigest()
|
||||
|
||||
def __set_shm(self, key, value, timeout=None):
|
||||
'''
|
||||
@name 尝试将缓存写入shm目录
|
||||
@author Zhj<2022-10-08>
|
||||
@param key<string> 键名
|
||||
@param value<mixed> 值
|
||||
@param timeout<int> 存活时间/秒
|
||||
@return bool
|
||||
'''
|
||||
if key[:5] != self.__SHM_PREFIX:
|
||||
return False
|
||||
|
||||
self.__makesure_shm_basedir()
|
||||
|
||||
expires = struct.pack('f', self._normalize_timeout(timeout))
|
||||
filename = '/'.join((self.__SHM_BASEDIR, self.md5(key)))
|
||||
with open(filename, 'wb') as fp:
|
||||
fp.write(expires + pickle.dumps(value, pickle.HIGHEST_PROTOCOL))
|
||||
os.chmod(filename, 384)
|
||||
|
||||
return True
|
||||
|
||||
def __get_shm(self, key):
|
||||
'''
|
||||
@name 尝试从shm目录下读取缓存
|
||||
@author Zhj<2022-10-08>
|
||||
@param key<string> 键名
|
||||
@return mixed|None
|
||||
'''
|
||||
if key[:5] != self.__SHM_PREFIX:
|
||||
return None
|
||||
|
||||
self.__makesure_shm_basedir()
|
||||
|
||||
filename = '/'.join((self.__SHM_BASEDIR, self.md5(key)))
|
||||
if not os.path.exists(filename): return None
|
||||
|
||||
with open(filename, 'rb') as fp:
|
||||
_val = fp.read()
|
||||
|
||||
expires = struct.unpack('f', _val[:4])[0]
|
||||
|
||||
# 过期 删除缓存文件
|
||||
if expires > 0 and expires <= time():
|
||||
os.remove(filename)
|
||||
return None
|
||||
|
||||
return pickle.loads(_val[4:])
|
||||
|
||||
def __del_shm(self, key):
|
||||
'''
|
||||
@name 删除shm目录下的缓存
|
||||
@author Zhj<2022-10-08>
|
||||
@param key<string> 键名
|
||||
@return bool
|
||||
'''
|
||||
if key[:5] != self.__SHM_PREFIX:
|
||||
return False
|
||||
|
||||
self.__makesure_shm_basedir()
|
||||
|
||||
filename = '/'.join((self.__SHM_BASEDIR, self.md5(key)))
|
||||
if os.path.exists(filename):
|
||||
os.remove(filename)
|
||||
|
||||
return True
|
||||
|
||||
def __has_shm(self, key):
|
||||
'''
|
||||
@name 检查shm目录下的缓存是否存在
|
||||
@author Zhj<2022-10-08>
|
||||
@param key<string> 键名
|
||||
@return bool
|
||||
'''
|
||||
if key[:5] != self.__SHM_PREFIX:
|
||||
return False
|
||||
|
||||
self.__makesure_shm_basedir()
|
||||
|
||||
filename = '/'.join((self.__SHM_BASEDIR, self.md5(key)))
|
||||
if not os.path.exists(filename): return False
|
||||
|
||||
# 获取缓存过期时间
|
||||
with open(filename, 'rb') as fp:
|
||||
expires = struct.unpack('f', fp.read(4))[0]
|
||||
|
||||
# 过期 删除缓存文件
|
||||
if expires > 0 and expires <= time():
|
||||
os.remove(filename)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def __add_shm(self, key, value, timeout=None):
|
||||
'''
|
||||
@name 尝试添加缓存到shm目录下
|
||||
@author Zhj<2022-10-08>
|
||||
@param key<string> 键名
|
||||
@param value<mixed> 值
|
||||
@param timeout<int> 缓存存活时间/秒
|
||||
@return bool
|
||||
'''
|
||||
if self.__has_shm(key):
|
||||
return False
|
||||
|
||||
return self.__set_shm(key, value, timeout)
|
||||
|
||||
def __makesure_shm_basedir(self):
|
||||
'''
|
||||
@name 确保shm下的缓存目录存在
|
||||
@author Zhj<2022-10-08>
|
||||
@return void
|
||||
'''
|
||||
if not os.path.exists(self.__SHM_BASEDIR):
|
||||
os.makedirs(self.__SHM_BASEDIR, 384)
|
||||
|
||||
|
||||
+135
-37
@@ -1,12 +1,12 @@
|
||||
#coding: utf-8
|
||||
# coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# | Author: hwliang <hwl@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
from BTPanel import session, cache , request, redirect, g,abort
|
||||
from BTPanel import session, cache , request, redirect, g,abort, Response
|
||||
from datetime import datetime
|
||||
from public import dict_obj
|
||||
import os
|
||||
@@ -21,13 +21,13 @@ class panelSetup:
|
||||
panel_path = public.get_panel_path()
|
||||
if os.getcwd() != panel_path: os.chdir(panel_path)
|
||||
|
||||
g.ua = request.headers.get('User-Agent','')
|
||||
g.ua = request.headers.get('User-Agent', '')
|
||||
if g.ua:
|
||||
ua = g.ua.lower()
|
||||
if ua.find('spider') != -1 or g.ua.find('bot') != -1:
|
||||
return abort(403)
|
||||
|
||||
g.version = '6.8.37'
|
||||
g.version = '7.0.6'
|
||||
g.title = public.GetConfigValue('title')
|
||||
g.uri = request.path
|
||||
g.debug = os.path.exists('data/debug.pl')
|
||||
@@ -55,7 +55,6 @@ class panelSetup:
|
||||
self.other_import()
|
||||
return None
|
||||
|
||||
|
||||
def other_import(self):
|
||||
g.o = public.readFile('data/o.pl')
|
||||
g.other_css = []
|
||||
@@ -71,7 +70,6 @@ class panelSetup:
|
||||
if os.path.exists(js_file): g.other_js.append('/static/other/{}'.format(js_name))
|
||||
|
||||
|
||||
|
||||
class panelAdmin(panelSetup):
|
||||
setupPath = '/www/server'
|
||||
|
||||
@@ -82,6 +80,7 @@ class panelAdmin(panelSetup):
|
||||
return result
|
||||
result = self.check_login()
|
||||
if result:
|
||||
# public.print_log("local 2登录检查返回 {}".format(result))
|
||||
return result
|
||||
result = self.setSession()
|
||||
if result:
|
||||
@@ -100,7 +99,8 @@ class panelAdmin(panelSetup):
|
||||
if request.method == 'GET':
|
||||
g.menus = public.get_menus()
|
||||
g.yaer = datetime.now().year
|
||||
session["top_tips"] = public.get_msg_gettext("The current IE browser version is too low to display some features, please use another browser. Or if you use a browser developed by a Chinese company, please switch to Extreme Mode!")
|
||||
session["top_tips"] = public.get_msg_gettext(
|
||||
"The current IE browser version is too low to display some features, please use another browser. Or if you use a browser developed by a Chinese company, please switch to Extreme Mode!")
|
||||
session["bt_help"] = public.get_msg_gettext("For Support|Suggestions, please visit the aaPanel Forum")
|
||||
session["download"] = public.get_msg_gettext("Downloading:")
|
||||
if not 'brand' in session:
|
||||
@@ -121,7 +121,7 @@ class panelAdmin(panelSetup):
|
||||
|
||||
# 检查Web服务器类型
|
||||
def checkWebType(self):
|
||||
#if request.method == 'GET':
|
||||
# if request.method == 'GET':
|
||||
if not 'webserver' in session:
|
||||
if os.path.exists('/usr/local/lsws/bin/lswsctrl'):
|
||||
session['webserver'] = 'openlitespeed'
|
||||
@@ -130,11 +130,12 @@ class panelAdmin(panelSetup):
|
||||
else:
|
||||
session['webserver'] = 'nginx'
|
||||
if not 'webversion' in session:
|
||||
if os.path.exists(self.setupPath+'/'+session['webserver']+'/version.pl'):
|
||||
session['webversion'] = public.ReadFile(self.setupPath+'/'+session['webserver']+'/version.pl').strip()
|
||||
if os.path.exists(self.setupPath + '/' + session['webserver'] + '/version.pl'):
|
||||
session['webversion'] = public.ReadFile(
|
||||
self.setupPath + '/' + session['webserver'] + '/version.pl').strip()
|
||||
|
||||
if not 'phpmyadminDir' in session:
|
||||
filename = self.setupPath+'/data/phpmyadminDirName.pl'
|
||||
filename = self.setupPath + '/data/phpmyadminDirName.pl'
|
||||
if os.path.exists(filename):
|
||||
session['phpmyadminDir'] = public.ReadFile(filename).strip()
|
||||
return False
|
||||
@@ -144,15 +145,38 @@ class panelAdmin(panelSetup):
|
||||
if os.path.exists('data/close.pl'):
|
||||
return redirect('/close')
|
||||
|
||||
# 跳转到登录页面
|
||||
def to_login(self, url, msg=" Login has expired, please log in again"):
|
||||
x_http_token = request.headers.get('X-Http-Token', '')
|
||||
if x_http_token:
|
||||
# 如果是ajax请求
|
||||
# res = {"status": False, "msg": msg, "redirect": url}
|
||||
# 修改为通用返回方式
|
||||
res = {
|
||||
"status": -1,
|
||||
"timestamp": int(time.time()),
|
||||
"message": {
|
||||
# "result": "successfully added!",
|
||||
"msg": msg,
|
||||
"redirect": url
|
||||
}
|
||||
}
|
||||
|
||||
# public.print_log("有x_http_token res --{}".format(res))
|
||||
return Response(json.dumps(res), content_type='application/json')
|
||||
|
||||
# public.print_log("无x_http_token 跳转 --{}".format(url))
|
||||
return redirect(url)
|
||||
|
||||
# 检查登录
|
||||
def check_login(self):
|
||||
def check_login1(self):
|
||||
try:
|
||||
api_check = True
|
||||
g.api_request = False
|
||||
if not 'login' in session:
|
||||
api_check = self.get_sk()
|
||||
if api_check:
|
||||
if not isinstance(api_check,dict):
|
||||
if not isinstance(api_check, dict):
|
||||
if public.get_admin_path() == '/login':
|
||||
return redirect('/login?err=1')
|
||||
return api_check
|
||||
@@ -178,12 +202,12 @@ class panelAdmin(panelSetup):
|
||||
|
||||
if api_check:
|
||||
now_time = time.time()
|
||||
session_timeout = session.get('session_timeout',0)
|
||||
session_timeout = session.get('session_timeout', 0)
|
||||
if session_timeout < now_time and session_timeout != 0:
|
||||
session.clear()
|
||||
return redirect(public.get_admin_path())
|
||||
|
||||
login_token = session.get('login_token','')
|
||||
login_token = session.get('login_token', '')
|
||||
if login_token:
|
||||
if login_token != public.get_login_token_auth():
|
||||
session.clear()
|
||||
@@ -201,51 +225,120 @@ class panelAdmin(panelSetup):
|
||||
self.check_session()
|
||||
|
||||
except:
|
||||
# public.print_log(public.get_error_info())
|
||||
public.print_log(public.get_error_info())
|
||||
session.clear()
|
||||
public.print_error()
|
||||
|
||||
return redirect('/login?id=2')
|
||||
|
||||
# 检查登录
|
||||
def check_login(self):
|
||||
try:
|
||||
api_check = True
|
||||
g.api_request = False
|
||||
if not 'login' in session:
|
||||
api_check = self.get_sk()
|
||||
if api_check:
|
||||
# if not isinstance(api_check, dict):
|
||||
# if public.get_admin_path() == '/login':
|
||||
# return redirect('/login?err=1')
|
||||
return api_check
|
||||
g.api_request = True
|
||||
else:
|
||||
if session['login'] == False:
|
||||
session.clear()
|
||||
return self.to_login(public.get_admin_path())
|
||||
|
||||
if 'tmp_login_expire' in session:
|
||||
s_file = 'data/session/{}'.format(session['tmp_login_id'])
|
||||
if session['tmp_login_expire'] < time.time():
|
||||
session.clear()
|
||||
if os.path.exists(s_file): os.remove(s_file)
|
||||
return self.to_login(public.get_admin_path(), 'The temporary login has expired, please log in again')
|
||||
if not os.path.exists(s_file):
|
||||
session.clear()
|
||||
return self.to_login(public.get_admin_path(),'The temporary login has expired, please log in again')
|
||||
|
||||
# 检查客户端hash -- 不要删除
|
||||
if not public.check_client_hash():
|
||||
session.clear()
|
||||
return self.to_login(public.get_admin_path(),'Client verification failed, please log in again')
|
||||
|
||||
if api_check:
|
||||
now_time = time.time()
|
||||
session_timeout = session.get('session_timeout', 0)
|
||||
if session_timeout < now_time and session_timeout != 0:
|
||||
session.clear()
|
||||
return self.to_login(public.get_admin_path(),"Login session has expired, please log in again")
|
||||
|
||||
login_token = session.get('login_token', '')
|
||||
if login_token:
|
||||
if login_token != public.get_login_token_auth():
|
||||
session.clear()
|
||||
return self.to_login(public.get_admin_path(),'Login verification failed, please log in again')
|
||||
|
||||
# if api_check:
|
||||
# filename = 'data/sess_files/' + public.get_sess_key()
|
||||
# if not os.path.exists(filename):
|
||||
# session.clear()
|
||||
# return redirect(public.get_admin_path())
|
||||
|
||||
# 标记新的会话过期时间
|
||||
self.check_session()
|
||||
|
||||
except:
|
||||
public.print_log(public.get_error_info())
|
||||
session.clear()
|
||||
public.print_error()
|
||||
public.print_log("except Login has expired, please log in again")
|
||||
return self.to_login('/login',' Login has expired, please log in again')
|
||||
|
||||
|
||||
def check_session(self):
|
||||
white_list = ['/favicon.ico', '/system?action=GetNetWork']
|
||||
if g.uri in white_list:
|
||||
return
|
||||
session['session_timeout'] = time.time() + public.get_session_timeout()
|
||||
|
||||
|
||||
|
||||
# 获取sk
|
||||
def get_sk(self):
|
||||
save_path = '/www/server/panel/config/api.json'
|
||||
if not os.path.exists(save_path):
|
||||
return public.redirect_to_login()
|
||||
return public.redirect_to_login(None)
|
||||
# return self.to_login(public.get_admin_path(), "Login session has expired, please log in again")
|
||||
|
||||
try:
|
||||
api_config = json.loads(public.ReadFile(save_path))
|
||||
except:
|
||||
os.remove(save_path)
|
||||
return public.redirect_to_login()
|
||||
return public.redirect_to_login(None)
|
||||
# return self.to_login(public.get_admin_path(), "Login session has expired, please log in again")
|
||||
|
||||
if not api_config['open']:
|
||||
return public.redirect_to_login()
|
||||
return public.redirect_to_login(None)
|
||||
# return self.to_login(public.get_admin_path(), "Login session has expired, please log in again")
|
||||
from BTPanel import get_input
|
||||
get = get_input()
|
||||
client_ip = public.GetClientIp()
|
||||
|
||||
if not 'client_bind_token' in get:
|
||||
if not 'request_token' in get or not 'request_time' in get:
|
||||
return public.redirect_to_login()
|
||||
return public.redirect_to_login(None)
|
||||
# return self.to_login(public.get_admin_path(), "Login session has expired, please log in again")
|
||||
|
||||
num_key = client_ip + '_api'
|
||||
if not public.get_error_num(num_key, 20):
|
||||
return public.returnJson(False,'20 consecutive verification failures, prohibited for 1 hour')
|
||||
return public.returnJson(False, '20 consecutive verification failures, prohibited for 1 hour')
|
||||
|
||||
if not public.is_api_limit_ip(api_config['limit_addr'], client_ip): # client_ip in api_config['limit_addr']:
|
||||
if not public.is_api_limit_ip(api_config['limit_addr'],
|
||||
client_ip): # client_ip in api_config['limit_addr']:
|
||||
public.set_error_num(num_key)
|
||||
return public.returnJson(False,'%s[' % public.get_msg_gettext("20 consecutive verification failures, prohibited for 1 hour")+client_ip+']')
|
||||
return public.returnJson(False, '%s[' % public.get_msg_gettext(
|
||||
"IP validation failed, your access IP is") + client_ip + ']')
|
||||
else:
|
||||
num_key = client_ip + '_app'
|
||||
if not public.get_error_num(num_key,20):
|
||||
return public.returnJson(False,'20 consecutive verification failures, prohibited for 1 hour')
|
||||
if not public.get_error_num(num_key, 20):
|
||||
return public.returnJson(False, '20 consecutive verification failures, prohibited for 1 hour')
|
||||
a_file = '/dev/shm/' + get.client_bind_token
|
||||
|
||||
if not public.path_safe_check(get.client_bind_token):
|
||||
@@ -256,8 +349,8 @@ class panelAdmin(panelSetup):
|
||||
import panelApi
|
||||
if not panelApi.panelApi().get_app_find(get.client_bind_token):
|
||||
public.set_error_num(num_key)
|
||||
return public.returnJson(False,'Unbound device')
|
||||
public.writeFile(a_file,'')
|
||||
return public.returnJson(False, 'Unbound device')
|
||||
public.writeFile(a_file, '')
|
||||
|
||||
if not 'key' in api_config:
|
||||
public.set_error_num(num_key)
|
||||
@@ -275,17 +368,23 @@ class panelAdmin(panelSetup):
|
||||
g.aes_key = api_config['key']
|
||||
request_token = public.md5(get.request_time + api_config['token'])
|
||||
if get.request_token == request_token:
|
||||
public.set_error_num(num_key,True)
|
||||
public.set_error_num(num_key, True)
|
||||
return False
|
||||
public.set_error_num(num_key)
|
||||
return public.returnJson(False,'Secret key verification failed')
|
||||
return public.returnJson(False, 'Secret key verification failed')
|
||||
|
||||
# 检查系统配置
|
||||
def checkConfig(self):
|
||||
if not 'config' in session:
|
||||
session['config'] = public.M('config').where("id=?", ('1',)).field(
|
||||
'webserver,sites_path,backup_path,status,mysql_root').find()
|
||||
if not 'email' in session['config']:
|
||||
|
||||
# 4.29 修复config可能是空列表导致赋值不上的问题
|
||||
if not session['config']:
|
||||
session['config'] = {}
|
||||
|
||||
# if not 'email' in session['config']:
|
||||
if session['config'] and not 'email' in session['config']:
|
||||
session['config']['email'] = public.M(
|
||||
'users').where("id=?", ('1',)).getField('email')
|
||||
if not 'address' in session:
|
||||
@@ -310,8 +409,7 @@ class panelAdmin(panelSetup):
|
||||
session['server_os'] = tmp
|
||||
return False
|
||||
|
||||
|
||||
def get_osname(self,i_file):
|
||||
def get_osname(self, i_file):
|
||||
'''
|
||||
@name 从指定文件中获取系统名称
|
||||
@author hwliang<2021-04-07>
|
||||
|
||||
+10
-12
@@ -1,10 +1,10 @@
|
||||
# coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板 x3
|
||||
# | aaPanel x3
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2017 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2017 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# | Author: hwliang <hwl@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
import base64
|
||||
import public,re,os,nginx,apache,json,time,ols
|
||||
@@ -510,7 +510,8 @@ class config:
|
||||
reg = r"^([\w\-\*]{1,100}\.){1,4}(\w{1,10}|\w{1,10}\.\w{1,10})$"
|
||||
if not re.match(reg, get.domain): return public.return_msg_gettext(False,'Format of primary domain is incorrect')
|
||||
if get.address:
|
||||
if not re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", get.address):
|
||||
from public.regexplib import match_ipv4, match_ipv6
|
||||
if not match_ipv4.match(get.address) and not match_ipv6.match(get.address) :
|
||||
return public.return_msg_gettext(False, 'Please set the correct Server IP')
|
||||
oldPort = public.GetHost(True)
|
||||
if not 'port' in get:
|
||||
@@ -1307,7 +1308,7 @@ class config:
|
||||
passwd = get.passwd
|
||||
if g != "files":
|
||||
iprep = r"(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})"
|
||||
rep_domain = "^(?=^.{3,255}$)[a-zA-Z0-9\_\-][a-zA-Z0-9\_\-]{0,62}(\.[a-zA-Z0-9\_\-][a-zA-Z0-9\_\-]{0,62})+$"
|
||||
rep_domain = r"^(?=^.{3,255}$)[a-zA-Z0-9\_\-][a-zA-Z0-9\_\-]{0,62}(\.[a-zA-Z0-9\_\-][a-zA-Z0-9\_\-]{0,62})+$"
|
||||
if not re.search(iprep, ip) and not re.search(rep_domain, ip):
|
||||
if ip != "localhost":
|
||||
return public.returnMsg(False, 'Please enter the correct [domain or IP]!')
|
||||
@@ -2441,7 +2442,7 @@ class config:
|
||||
if not 'status_code' in get:
|
||||
return public.return_msg_gettext(False,'Parameter ERROR!')
|
||||
|
||||
if re.match("^\d+$", get.status_code):
|
||||
if re.match(r"^\d+$", get.status_code):
|
||||
status_code = int(get.status_code)
|
||||
if status_code != 0:
|
||||
if status_code < 100 or status_code > 999:
|
||||
@@ -2878,7 +2879,7 @@ class config:
|
||||
}
|
||||
# request发送post请求并指定form_data参数
|
||||
res = public.httpPost(url, data)
|
||||
# public.print_log("获取问卷@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ {}".format(res))
|
||||
|
||||
try:
|
||||
res = json.loads(res)
|
||||
except:
|
||||
@@ -3162,7 +3163,7 @@ class config:
|
||||
"USER_AGENT": public.xsssec(request.headers.get('User-Agent')), # 客户端连接信息
|
||||
"ERROR_INFO": error, # 错误信息
|
||||
"PACK_TIME": public.readFile("/www/server/panel/config/update_time.pl") if os.path.exists("/www/server/panel/config/update_time.pl") else public.getDate(), # 打包时间
|
||||
"TYPE": 1,
|
||||
"TYPE": 101,
|
||||
"ERROR_ID": "{}_{}".format(error.split("\n")[0].strip(),get.get("uri", ""))
|
||||
}
|
||||
pkey = public.Md5(error_infos["ERROR_INFO"])
|
||||
@@ -3170,12 +3171,9 @@ class config:
|
||||
# 提交
|
||||
if not public.cache_get(pkey):
|
||||
try:
|
||||
public.run_thread(public.httpPost("https://api.bt.cn/bt_error/index.php", error_infos))
|
||||
public.run_thread(public.httpPost("https://geterror.aapanel.com/bt_error/index.php", error_infos))
|
||||
public.cache_set(pkey, 1, 1800)
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
return public.returnMsg(True, "OK")
|
||||
|
||||
|
||||
|
||||
|
||||
+5
-4
@@ -1,13 +1,13 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# | Author: hwliang <hwl@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
import public,db,os,time,re, json
|
||||
from BTPanel import session,cache
|
||||
from BTPanel import session, cache
|
||||
class crontab:
|
||||
field = 'id,name,type,where1,where_hour,where_minute,echo,addtime,status,save,backupTo,sName,sBody,sType,urladdress'
|
||||
field += ",save_local,notice,notice_channel"
|
||||
@@ -401,6 +401,7 @@ class crontab:
|
||||
id = get['id']
|
||||
find = public.M('crontab').where("id=?",(id,)).field('name,echo').find()
|
||||
if not find: return public.return_msg_gettext(False, 'The specified task does not exist!')
|
||||
|
||||
if not self.remove_for_crond(find['echo']): return public.return_msg_gettext(False,'Unable to write to file, please check if system hardening is enabled!')
|
||||
cronPath = public.GetConfigValue('setup_path') + '/cron'
|
||||
sfile = cronPath + '/' + find['echo']
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# coding: utf-8
|
||||
# -------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2016 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2016 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: <290070744@qq.com>
|
||||
# Author: <290070744@aapanel.com>
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# ------------------------------
|
||||
|
||||
+4
-6
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2016 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2016 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# | Author: hwliang <hwl@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
import sys,os,re,time
|
||||
if not 'class/' in sys.path:
|
||||
@@ -223,7 +223,6 @@ class data:
|
||||
* @return Json page.分页数 , count.总行数 data.取回的数据
|
||||
'''
|
||||
def getData(self,get):
|
||||
import one_key_wp
|
||||
# # net_flow_type = {
|
||||
# # "total_flow": "总流量",
|
||||
# # "7_day_total_flow": "近7天流量",
|
||||
@@ -262,14 +261,12 @@ class data:
|
||||
# # get.order = 'id desc'
|
||||
# # # net_flow_dict["order_type"] = order_type
|
||||
# # public.writeFile(net_flow_json_file, json.dumps(net_flow_dict))
|
||||
|
||||
# 如果网站列表包含 rname 字段排序 先检查表内是否有 rname字段
|
||||
if hasattr(get, "order") and get.table == 'sites':
|
||||
if get.order.startswith('rname'):
|
||||
data = public.M('sites').find()
|
||||
if 'rname' not in data.keys():
|
||||
public.M('sites').execute("ALTER TABLE 'sites' ADD 'rname' text DEFAULT ''", ())
|
||||
|
||||
table = get.table
|
||||
data = self.GetSql(get)
|
||||
SQL = public.M(table)
|
||||
@@ -331,6 +328,7 @@ class data:
|
||||
data['data'][i]['attack'] = self.get_analysis(get,data['data'][i])
|
||||
data['data'][i]['project_type'] = SQL.table('sites').where('id=?',(data['data'][i]['id'])).field('project_type').find()['project_type']
|
||||
if data['data'][i]['project_type'] == 'WP':
|
||||
import one_key_wp
|
||||
data['data'][i]['cache_status'] = one_key_wp.one_key_wp().get_cache_status(data['data'][i]['id'])
|
||||
if not data['data'][i]['status'] in ['0','1',0,1]:
|
||||
data['data'][i]['status'] = '1'
|
||||
|
||||
+19
-19
@@ -1,10 +1,10 @@
|
||||
# coding: utf-8
|
||||
# -------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2017 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2017 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# ------------------------------
|
||||
@@ -418,7 +418,7 @@ ssl-key=/www/server/mysql/mysql-test/std_data/server-key.pem
|
||||
reg = "ssl-ca=/www.*\n.*\n.*server-key.pem\n"
|
||||
conf = re.sub(reg, "", conf)
|
||||
if os.path.exists('/www/server/mysql/mysql-test/std_data/server-cert.pem'):
|
||||
conf = re.sub('\[mysqld\]', '[mysqld]\nskip_ssl', conf)
|
||||
conf = re.sub(r'\[mysqld\]', '[mysqld]\nskip_ssl', conf)
|
||||
public.writeFile(conf_file, conf)
|
||||
return public.return_msg_gettext(True, 'Setup successfully!')
|
||||
# create_ssl = None
|
||||
@@ -429,7 +429,7 @@ ssl-key=/www/server/mysql/mysql-test/std_data/server-key.pem
|
||||
# if create_ssl:
|
||||
# self._create_mysql_ssl()
|
||||
if "ssl-ca" not in conf:
|
||||
conf = re.sub('\[mysqld\]', '[mysqld]' + ssl_original_path, conf)
|
||||
conf = re.sub(r'\[mysqld\]', '[mysqld]' + ssl_original_path, conf)
|
||||
conf = re.sub('skip_ssl\n', '', conf)
|
||||
public.writeFile(conf_file, conf)
|
||||
# public.ExecShell('chown mysql.mysql /www/server/data/*.pem')
|
||||
@@ -792,7 +792,7 @@ SetLink
|
||||
password = get['password'].strip()
|
||||
try:
|
||||
if not password: return public.return_msg_gettext(False, 'Root password cannot be empty')
|
||||
rep = "^[\w@\.\?\-\_\>\<\~\!\#\$\%\^\&\*\(\)]+$"
|
||||
rep = r"^[\w@\.\?\-\_\>\<\~\!\#\$\%\^\&\*\(\)]+$"
|
||||
if not re.match(rep, password): return public.return_msg_gettext(False,
|
||||
'Database password cannot contain special characters!')
|
||||
self.sid = get.get('sid/d', 0)
|
||||
@@ -864,7 +864,7 @@ SetLink
|
||||
db_find = public.M('databases').where('id=?', (id,)).find()
|
||||
name = db_find['name']
|
||||
|
||||
rep = "^[\w@\.\?\-\_\>\<\~\!\#\$\%\^\&\*\(\)]+$"
|
||||
rep = r"^[\w@\.\?\-\_\>\<\~\!\#\$\%\^\&\*\(\)]+$"
|
||||
if not re.match(rep, newpassword): return public.return_msg_gettext(False,
|
||||
'Database password cannot contain special characters!')
|
||||
# 修改MYSQL
|
||||
@@ -1252,7 +1252,7 @@ SetLink
|
||||
ps = public.get_msg_gettext('Test Database')
|
||||
|
||||
# XSS filter
|
||||
if not re.match("^[\w+\.-]+$", value[0]): continue
|
||||
if not re.match(r"^[\w+\.-]+$", value[0]): continue
|
||||
|
||||
addTime = time.strftime('%Y-%m-%d %X', time.localtime())
|
||||
|
||||
@@ -1317,9 +1317,9 @@ SetLink
|
||||
public.CheckMyCnf()
|
||||
myfile = '/etc/my.cnf'
|
||||
mycnf = public.readFile(myfile)
|
||||
rep = "datadir\s*=\s*(.+)\n"
|
||||
rep = "datadir\\s*=\\s*(.+)\n"
|
||||
data['datadir'] = re.search(rep, mycnf).groups()[0]
|
||||
rep = "port\s*=\s*([0-9]+)\s*\n"
|
||||
rep = "port\\s*=\\s*([0-9]+)\\s*\n"
|
||||
data['port'] = re.search(rep, mycnf).groups()[0]
|
||||
except:
|
||||
data['datadir'] = '/www/server/data'
|
||||
@@ -1338,7 +1338,7 @@ SetLink
|
||||
'The same as the current storage directory, file cannot be moved!')
|
||||
|
||||
public.ExecShell('/etc/init.d/mysqld stop')
|
||||
public.ExecShell('\cp -arf ' + mysqlInfo['datadir'] + '/* ' + get.datadir + '/')
|
||||
public.ExecShell(r'\cp -arf ' + mysqlInfo['datadir'] + '/* ' + get.datadir + '/')
|
||||
public.ExecShell('chown -R mysql.mysql ' + get.datadir)
|
||||
public.ExecShell('chmod -R 755 ' + get.datadir)
|
||||
public.ExecShell('rm -f ' + get.datadir + '/*.pid')
|
||||
@@ -1365,7 +1365,7 @@ SetLink
|
||||
def SetMySQLPort(self, get):
|
||||
myfile = '/etc/my.cnf'
|
||||
mycnf = public.readFile(myfile)
|
||||
rep = r"port\s*=\s*([0-9]+)\s*\n"
|
||||
rep = "port\\s*=\\s*([0-9]+)\\s*\n"
|
||||
mycnf = re.sub(rep, 'port = ' + get.port + '\n', mycnf)
|
||||
public.writeFile(myfile, mycnf)
|
||||
public.ExecShell('/etc/init.d/mysqld restart')
|
||||
@@ -1429,19 +1429,19 @@ SetLink
|
||||
mysql_cnf = re.sub(r"\nlog-bin", "\n#log-bin", mysql_cnf)
|
||||
mysql_cnf = re.sub(r"\nbinlog_format", "\n#binlog_format", mysql_cnf)
|
||||
if not is_off_bin_log:
|
||||
if re.search("\n#\s*skip-log-bin", mysql_cnf):
|
||||
mysql_cnf = re.sub("\n#\s*skip-log-bin", "\nskip-log-bin", mysql_cnf)
|
||||
if re.search("\n#\\s*skip-log-bin", mysql_cnf):
|
||||
mysql_cnf = re.sub("\n#\\s*skip-log-bin", "\nskip-log-bin", mysql_cnf)
|
||||
else:
|
||||
mysql_cnf = re.sub("\n#\s*log-bin", "\nskip-log-bin\n#log-bin", mysql_cnf)
|
||||
mysql_cnf = re.sub("\n#\\s*log-bin", "\nskip-log-bin\n#log-bin", mysql_cnf)
|
||||
# public.ExecShell("rm -f {}/mysql-bin.*".format(mysql_data_dir))
|
||||
else: # 开启 binlog 日志
|
||||
if re.search("\n#\s*log-bin", mysql_cnf):
|
||||
mysql_cnf = re.sub("\n#\s*log-bin", "\nlog-bin", mysql_cnf)
|
||||
if re.search("\n#\\s*log-bin", mysql_cnf):
|
||||
mysql_cnf = re.sub("\n#\\s*log-bin", "\nlog-bin", mysql_cnf)
|
||||
else:
|
||||
mysql_cnf = re.sub("[mysqld]", "[mysqld]\nlog-bin=mysql-bin", mysql_cnf)
|
||||
|
||||
if re.search("\n#\s*binlog_format", mysql_cnf):
|
||||
mysql_cnf = re.sub(r"\n#\s*binlog_format", "\nbinlog_format", mysql_cnf)
|
||||
if re.search("\n#\\s*binlog_format", mysql_cnf):
|
||||
mysql_cnf = re.sub("\n#\\s*binlog_format", "\nbinlog_format", mysql_cnf)
|
||||
else:
|
||||
mysql_cnf = re.sub("[mysqld]", "[mysqld]\nbinlog_format=mixed", mysql_cnf)
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ class databaseBase:
|
||||
if data_name in checks or len(data_name) < 1:
|
||||
return public.returnMsg(False,'Database name is invalid!');
|
||||
|
||||
reg = "^\w+$"
|
||||
reg = r"^\w+$"
|
||||
if not re.match(reg, data_name):
|
||||
return public.returnMsg(False,'DATABASE_NAME_ERR_T')
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
#角色说明:
|
||||
#read:允许用户读取指定数据库
|
||||
@@ -105,7 +105,7 @@ class panelMongoDB():
|
||||
conf = self.get_config(None)
|
||||
|
||||
for opt in options:
|
||||
tmp = re.findall(opt + ":\s+(.+)",conf)
|
||||
tmp = re.findall(opt + r":\s+(.+)",conf)
|
||||
if not tmp: continue;
|
||||
data[opt] = tmp[0]
|
||||
|
||||
@@ -177,9 +177,9 @@ class main(databaseBase):
|
||||
|
||||
conf = public.readFile(self.__conf_path)
|
||||
if status:
|
||||
conf = re.sub('authorization\s*\:\s*disabled','authorization: enabled',conf)
|
||||
conf = re.sub(r'authorization\s*\:\s*disabled','authorization: enabled',conf)
|
||||
else:
|
||||
conf = re.sub('authorization\s*\:\s*enabled','authorization: disabled',conf)
|
||||
conf = re.sub(r'authorization\s*\:\s*enabled','authorization: disabled',conf)
|
||||
|
||||
public.writeFile(self.__conf_path,conf)
|
||||
self.restart_services()
|
||||
@@ -201,7 +201,7 @@ class main(databaseBase):
|
||||
if status:
|
||||
if hasattr(get,'password'):
|
||||
password = get['password'].strip()
|
||||
if not password or not re.search("^[\w@\.]+$", password):
|
||||
if not password or not re.search(r"^[\w@\.]+$", password):
|
||||
return public.return_msg_gettext(False, 'Database password cannot be empty or have special characters!')
|
||||
|
||||
# if re.search('[\u4e00-\u9fa5]',password):
|
||||
@@ -670,7 +670,7 @@ class main(databaseBase):
|
||||
try:
|
||||
if not newpassword:
|
||||
return public.returnMsg(False, 'Modify the failure,The database[' + username + ']password cannot be empty.');
|
||||
if len(re.search("^[\w@\.]+$", newpassword).groups()) > 0:
|
||||
if len(re.search(r"^[\w@\.]+$", newpassword).groups()) > 0:
|
||||
return public.returnMsg(False, 'The database password cannot be empty or contain special characters')
|
||||
|
||||
if re.search('[\u4e00-\u9fa5]',newpassword):
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: hezhihong <bt_ahong@qq.com>
|
||||
# Author: hezhihong <bt_ahong@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
@@ -154,7 +154,7 @@ class main(databaseBase,panelPgsql):
|
||||
if not self.__soft_path:self.__soft_path='{}/pgsql'.format(public.get_setup_path())
|
||||
conf = public.readFile('{}/data/postgresql.conf'.format(self.__soft_path))
|
||||
for opt in options:
|
||||
tmp = re.findall("\s+" +opt + "\s*=\s*(.+)#",conf)
|
||||
tmp = re.findall(r"\s+" +opt + r"\s*=\s*(.+)#",conf)
|
||||
if not tmp: continue;
|
||||
data[opt] = tmp[0].strip()
|
||||
if opt == 'listen_addresses':
|
||||
@@ -223,7 +223,8 @@ class main(databaseBase,panelPgsql):
|
||||
@return list
|
||||
'''
|
||||
check_result = os.system('/www/server/pgsql/bin/psql --version')
|
||||
if check_result !=0 and not public.M('database_servers').where('db_type=?','pgsql').count():return []
|
||||
if check_result !=0 and not public.M('database_servers').where('db_type=?','pgsql').count():
|
||||
return []
|
||||
return self.GetBaseCloudServer(args)
|
||||
|
||||
|
||||
@@ -302,7 +303,7 @@ class main(databaseBase,panelPgsql):
|
||||
id = get['id']
|
||||
find = public.M('databases').where("id=?",(id,)).field('id,pid,name,username,password,accept,ps,addtime,db_type,conn_config,sid,type').find();
|
||||
if not find: return public.returnMsg(False,'The specified database does not exist.')
|
||||
|
||||
|
||||
name = get['name']
|
||||
username = find['username']
|
||||
|
||||
@@ -323,15 +324,15 @@ class main(databaseBase,panelPgsql):
|
||||
|
||||
find = public.M('databases').where("id=?",(id,)).find()
|
||||
if not find: return public.returnMsg(False,'Database does not exist!')
|
||||
|
||||
|
||||
if not find['password'].strip():
|
||||
return public.returnMsg(False,'The database password is empty. Set the password first.')
|
||||
|
||||
|
||||
sql_dump = '{}/bin/pg_dump'.format(self.__soft_path)
|
||||
# return sql_dump
|
||||
if not os.path.isfile(sql_dump):
|
||||
return public.returnMsg(False,'Lack of backup tools, please first through the software store PGSQL manager!')
|
||||
|
||||
|
||||
back_path = session['config']['backup_path'] + '/database/pgsql/'
|
||||
# return back_path
|
||||
if not os.path.exists(back_path): os.makedirs(back_path)
|
||||
@@ -358,7 +359,7 @@ class main(databaseBase,panelPgsql):
|
||||
|
||||
if os.path.getsize(backupName) < 2048:
|
||||
return public.returnMsg(True, 'The backup file size is smaller than 2Kb. Check the backup integrity.')
|
||||
else:
|
||||
else:
|
||||
return public.returnMsg(True, 'BACKUP_SUCCESS')
|
||||
|
||||
def DelBackup(self,args):
|
||||
@@ -397,7 +398,7 @@ class main(databaseBase,panelPgsql):
|
||||
ext = tmp[len(tmp) -1]
|
||||
if ext not in exts:
|
||||
return public.returnMsg(False, 'DATABASE_INPUT_ERR_FORMAT')
|
||||
|
||||
|
||||
sql_dump = '{}/bin/psql'.format(self.__soft_path)
|
||||
if not os.path.exists(sql_dump):
|
||||
return public.returnMsg(False,'Lack of recovery tool, please use software management to install PGSQL!')
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
# sqlite模型
|
||||
@@ -76,7 +76,7 @@ class panelRedisDB():
|
||||
keys = ["bind","port","timeout","maxclients","databases","requirepass","maxmemory"]
|
||||
for k in keys:
|
||||
v = ""
|
||||
rep = "\n%s\s+(.+)" % k
|
||||
rep = "\n%s\\s+(.+)" % k
|
||||
group = re.search(rep,redis_conf)
|
||||
if not group:
|
||||
if k == "maxmemory":
|
||||
@@ -102,6 +102,7 @@ class main(databaseBase):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
def GetCloudServer(self,args):
|
||||
'''
|
||||
@name 获取远程服务器列表
|
||||
@@ -109,6 +110,7 @@ class main(databaseBase):
|
||||
@return list
|
||||
'''
|
||||
return self.GetBaseCloudServer(args)
|
||||
# return public.return_message(0, 0, self.GetBaseCloudServer(args))
|
||||
|
||||
|
||||
def AddCloudServer(self,args):
|
||||
@@ -373,7 +375,8 @@ class main(databaseBase):
|
||||
|
||||
nlist = []
|
||||
cloud_list = {}
|
||||
for x in self.GetCloudServer({'type':'redis'}): cloud_list['id-' + str(x['id'])] = x
|
||||
for x in self.GetCloudServer({'type':'redis'}):
|
||||
cloud_list['id-' + str(x['id'])] = x
|
||||
|
||||
path = session['config']['backup_path'] + '/database/redis/'
|
||||
if not os.path.exists(path): os.makedirs(path)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
@@ -87,6 +87,8 @@ class main(databaseBase):
|
||||
'''
|
||||
@添加远程数据库
|
||||
'''
|
||||
|
||||
|
||||
return self.AddBaseCloudServer(args)
|
||||
|
||||
def RemoveCloudServer(self,args):
|
||||
@@ -107,17 +109,18 @@ class main(databaseBase):
|
||||
|
||||
"""
|
||||
res = self.add_base_database(args)
|
||||
if not res['status']: return res
|
||||
if not res['status']:
|
||||
return res
|
||||
|
||||
data_name = res['data_name']
|
||||
username = res['username']
|
||||
password = res['data_pwd']
|
||||
|
||||
if re.match("^\d+",data_name):
|
||||
if re.match(r"^\d+",data_name):
|
||||
return public.returnMsg(False,'SQLServer databases cannot start with numbers!')
|
||||
|
||||
reg_count = 0
|
||||
regs = ['[a-z]','[A-Z]','\W','[0-9]']
|
||||
regs = ['[a-z]','[A-Z]',r'\W','[0-9]']
|
||||
for x in regs:
|
||||
if re.search(x,password): reg_count += 1
|
||||
|
||||
@@ -361,7 +364,7 @@ class main(databaseBase):
|
||||
try:
|
||||
if not newpassword:
|
||||
return public.returnMsg(False, 'The password of database [' + username + '] cannot be empty.');
|
||||
if len(re.search("^[\w@\.]+$", newpassword).groups()) > 0:
|
||||
if len(re.search(r"^[\w@\.]+$", newpassword).groups()) > 0:
|
||||
return public.returnMsg(False, 'The database password cannot be empty or contain special characters')
|
||||
except :
|
||||
return public.returnMsg(False, 'The database password cannot be empty or contain special characters')
|
||||
@@ -402,7 +405,7 @@ class main(databaseBase):
|
||||
try:
|
||||
if not password:
|
||||
return public.returnMsg(False, 'The password of database [' + username + '] cannot be empty.')
|
||||
if len(re.search("^[\w@\.]+$", password).groups()) > 0:
|
||||
if len(re.search(r"^[\w@\.]+$", password).groups()) > 0:
|
||||
return public.returnMsg(False, 'saThe password cannot be empty or have special symbols')
|
||||
except :
|
||||
return public.returnMsg(False, 'saThe password cannot be empty or have special symbols')
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
# coding: utf-8
|
||||
# -------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2017 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2017 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: 1249648969@qq.com
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
+7
-3
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# | Author: hwliang <hwl@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
import sqlite3
|
||||
@@ -390,3 +390,7 @@ class Sql():
|
||||
except:
|
||||
pass
|
||||
|
||||
def db(self,name):
|
||||
# 设置数据库名称,用于判断数据库文件
|
||||
self.__DB_NAME = name
|
||||
return self
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# | Author: hwliang <hwl@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
import re,os,sys,public,json
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# | Author: hwliang <hwl@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
import os,sys,public,json,time
|
||||
class downloadFile:
|
||||
|
||||
+16
-16
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2020 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2020 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: zhwen <zhw@bt.cn>
|
||||
# Author: zhwen <zhw@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
@@ -24,7 +24,7 @@ class FileExecuteDeny:
|
||||
def get_file_deny(self,args):
|
||||
'''
|
||||
# 添加某个网站禁止运行PHP
|
||||
author: zhwen<zhw@bt.cn>
|
||||
author: zhwen<zhw@aapanel.com>
|
||||
:param args: website 网站名 str
|
||||
:return:
|
||||
'''
|
||||
@@ -51,7 +51,7 @@ class FileExecuteDeny:
|
||||
deny_name.append(tmp[-1])
|
||||
result = []
|
||||
for i in deny_name:
|
||||
reg = '#BEGIN_DENY_{}\n\s*location\s*\~\*\s*\^(.*)\.\*.*\((.*)\)\$'.format(i.replace("|","\|"))
|
||||
reg = '#BEGIN_DENY_{}\n\\s*location\\s*\\~\\*\\s*\\^(.*)\\.\\*.*\\((.*)\\)\\$'.format(i.replace("|",r"\|"))
|
||||
re_tmp = re.search(reg,conf)
|
||||
if re_tmp:
|
||||
deny_directory = re_tmp.groups()[0]
|
||||
@@ -73,7 +73,7 @@ class FileExecuteDeny:
|
||||
deny_name.append(tmp[-1])
|
||||
result = []
|
||||
for i in deny_name:
|
||||
reg = '#BEGIN_DENY_{}\n\s*<Directory\s*\~\s*"(.*)\.\*.*\((.*)\)\$'.format(i.replace("|","\|"))
|
||||
reg = '#BEGIN_DENY_{}\n\\s*<Directory\\s*\\~\\s*"(.*)\\.\\*.*\\((.*)\\)\\$'.format(i.replace("|",r"\|"))
|
||||
deny_directory = re.search(reg,conf).groups()[0]
|
||||
deny_suffix = re.search(reg,conf).groups()[1]
|
||||
result.append({'name':i,'dir':deny_directory,'suffix':deny_suffix})
|
||||
@@ -93,7 +93,7 @@ class FileExecuteDeny:
|
||||
deny_name.append(tmp[-1])
|
||||
result = []
|
||||
for i in deny_name:
|
||||
reg = '#BEGIN_DENY_{}\n\s*rules\s*RewriteRule\s*\^(.*)\.\*.*\((.*)\)\$'.format(i.replace("|","\|"))
|
||||
reg = '#BEGIN_DENY_{}\n\\s*rules\\s*RewriteRule\\s*\\^(.*)\\.\\*.*\\((.*)\\)\\$'.format(i.replace("|",r"\|"))
|
||||
deny_directory = re.search(reg, conf).groups()[0]
|
||||
deny_suffix = re.search(reg,conf).groups()[1]
|
||||
result.append({'name':i,'dir':deny_directory,'suffix':deny_suffix})
|
||||
@@ -102,7 +102,7 @@ class FileExecuteDeny:
|
||||
def set_file_deny(self,args):
|
||||
'''
|
||||
# 添加某个网站禁止运行PHP
|
||||
author: zhwen<zhw@bt.cn>
|
||||
author: zhwen<zhw@aapanel.com>
|
||||
:param args: website 网站名 str
|
||||
:param args: deny_name 规则名称 str
|
||||
:param args: suffix 禁止访问的后续名 str
|
||||
@@ -145,7 +145,7 @@ class FileExecuteDeny:
|
||||
if not conf:
|
||||
return False
|
||||
if not dir and not suffix:
|
||||
reg = '\s*#BEGIN_DENY_{n}\n(.|\n)*#END_DENY_{n}\n'.format(n=name)
|
||||
reg = '\\s*#BEGIN_DENY_{n}\n(.|\n)*#END_DENY_{n}\n'.format(n=name)
|
||||
conf = re.sub(reg,'',conf)
|
||||
else:
|
||||
if dir[0] != '/':dir = '/'+dir
|
||||
@@ -168,12 +168,12 @@ class FileExecuteDeny:
|
||||
if not conf:
|
||||
return False
|
||||
if not dir and not suffix:
|
||||
reg = '\s*#BEGIN_DENY_{n}\n(.|\n)*#END_DENY_{n}'.format(n=name)
|
||||
reg = '\\s*#BEGIN_DENY_{n}\n(.|\n)*#END_DENY_{n}'.format(n=name)
|
||||
conf = re.sub(reg,'',conf)
|
||||
else:
|
||||
if dir[0] != '/':dir = '/'+dir
|
||||
if dir[-1] != '/':dir = dir+'/'
|
||||
new = '''
|
||||
new = r'''
|
||||
#BEGIN_DENY_{n}
|
||||
<Directory ~ "{d}.*\.({s})$">
|
||||
Order allow,deny
|
||||
@@ -183,7 +183,7 @@ class FileExecuteDeny:
|
||||
'''.format(n=name,d=dir,s=suffix)
|
||||
if '#BEGIN_DENY_{}'.format(name) in conf:
|
||||
return True
|
||||
conf = re.sub('#DENY\s*FILES',new+'\n #DENY FILES',conf)
|
||||
conf = re.sub(r'#DENY\s*FILES',new+'\n #DENY FILES',conf)
|
||||
public.writeFile(self.ap_website_conf,conf)
|
||||
return True
|
||||
|
||||
@@ -192,17 +192,17 @@ class FileExecuteDeny:
|
||||
if not conf:
|
||||
return False
|
||||
if not dir and not suffix:
|
||||
reg = '#BEGIN_DENY_{n}\n(.|\n)*#END_DENY_{n}\s*'.format(n=name)
|
||||
reg = '#BEGIN_DENY_{n}\n(.|\n)*#END_DENY_{n}\\s*'.format(n=name)
|
||||
conf = re.sub(reg,'',conf)
|
||||
else:
|
||||
new = '''
|
||||
new = r'''
|
||||
#BEGIN_DENY_{n}
|
||||
rules RewriteRule ^{d}.*\.({s})$ - [F,L]
|
||||
#END_DENY_{n}
|
||||
'''.format(n=name,d=dir,s=suffix)
|
||||
if '#BEGIN_DENY_{}'.format(name) in conf:
|
||||
return True
|
||||
conf = re.sub('autoLoadHtaccess\s*1','autoLoadHtaccess 1'+new,conf)
|
||||
conf = re.sub(r'autoLoadHtaccess\s*1','autoLoadHtaccess 1'+new,conf)
|
||||
public.writeFile(self.ols_website_conf,conf)
|
||||
return True
|
||||
|
||||
@@ -210,7 +210,7 @@ class FileExecuteDeny:
|
||||
def del_file_deny(self,args):
|
||||
'''
|
||||
# 添加某个网站禁止运行PHP
|
||||
author: zhwen<zhw@bt.cn>
|
||||
author: zhwen<zhw@aapanel.com>
|
||||
:param args: website 网站名 str
|
||||
:param args: deny_name 规则名称 str
|
||||
:return:
|
||||
|
||||
+223
-48
@@ -1,11 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
#coding:utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2016 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2016 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# | Author: hwliang <hwl@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
from base64 import b64encode
|
||||
import sys
|
||||
@@ -124,7 +124,7 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
filename = public.get_vhost_path() + '/nginx/' + siteName + '.conf'
|
||||
if os.path.exists(filename):
|
||||
conf = public.readFile(filename)
|
||||
rep = '\s*root\s+(.+);'
|
||||
rep = r'\s*root\s+(.+);'
|
||||
tmp1 = re.search(rep, conf)
|
||||
if tmp1:
|
||||
path = tmp1.groups()[0]
|
||||
@@ -132,7 +132,7 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
filename = public.get_vhost_path() + '/apache/' + siteName + '.conf'
|
||||
if os.path.exists(filename):
|
||||
conf = public.readFile(filename)
|
||||
rep = '\s*DocumentRoot\s*"(.+)"\s*\n'
|
||||
rep = '\\s*DocumentRoot\\s*"(.+)"\\s*\n'
|
||||
tmp1 = re.search(rep, conf)
|
||||
if tmp1:
|
||||
path = tmp1.groups()[0]
|
||||
@@ -398,9 +398,86 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
for m in ms.keys():
|
||||
filename = filename.replace(m,ms[m])
|
||||
return filename
|
||||
def files_list(self, path, search=None, my_sort='off', reverse=False):
|
||||
'''
|
||||
@name 遍历目录,并获取全量文件信息列表
|
||||
@param path<string> 目录路径
|
||||
@param search<string> 搜索关键词
|
||||
@param my_sort<string> 排序字段
|
||||
@param reverse<bool> 是否降序
|
||||
@return tuple (int,list)
|
||||
'''
|
||||
|
||||
nlist = []
|
||||
count = 0
|
||||
|
||||
# 文件不存在
|
||||
if not os.path.exists(path):
|
||||
return count, nlist
|
||||
|
||||
sort_key = -1
|
||||
if my_sort == 'off': # 不排序
|
||||
sort_key = -1
|
||||
elif my_sort == 'name': # 按文件名排序
|
||||
sort_key = 0
|
||||
elif my_sort == 'size': # 按文件大小排序
|
||||
sort_key = 1
|
||||
elif my_sort == 'mtime': # 按修改时间排序
|
||||
sort_key = 2
|
||||
elif my_sort == 'accept': # 按文件权限排序
|
||||
sort_key = 3
|
||||
elif my_sort == 'user': # 按文件所有者排序
|
||||
sort_key = 4
|
||||
|
||||
with os.scandir(path) as it:
|
||||
try:
|
||||
for entry in it:
|
||||
# 是否搜索
|
||||
if search:
|
||||
if entry.name.lower().find(search) == -1:
|
||||
continue
|
||||
|
||||
# 是否需要获取文件信息
|
||||
sort_val = 0
|
||||
if sort_key == 0 or sort_key == -1:
|
||||
# 通过文件名或不排序时,不获取文件信息
|
||||
sort_val = 0
|
||||
else:
|
||||
try:
|
||||
fstat = entry.stat()
|
||||
if sort_key == 1:
|
||||
sort_val = fstat.st_size
|
||||
elif sort_key == 2:
|
||||
sort_val = fstat.st_mtime
|
||||
elif sort_key == 3:
|
||||
sort_val = fstat.st_mode
|
||||
elif sort_key == 4:
|
||||
sort_val = fstat.st_uid
|
||||
except:
|
||||
pass
|
||||
|
||||
nlist.append((entry.name, sort_val))
|
||||
|
||||
# 计数
|
||||
count += 1
|
||||
except:
|
||||
pass
|
||||
|
||||
if sort_key == 0:
|
||||
# 按文件名排序
|
||||
nlist = sorted(nlist, key=lambda x: x[0], reverse=reverse)
|
||||
elif sort_key > 0:
|
||||
# 按指定字段排序
|
||||
nlist = sorted(nlist, key=lambda x: x[1], reverse=reverse)
|
||||
else:
|
||||
# 否则文件数量小于10000时,按文件名排序
|
||||
if count < 10000:
|
||||
nlist = sorted(nlist, key=lambda x: x[0], reverse=reverse)
|
||||
|
||||
return count, nlist
|
||||
|
||||
# 取文件/目录列表
|
||||
def GetDir(self, get):
|
||||
def GetDir(self, get: public.dict_obj):
|
||||
if not hasattr(get, 'path'):
|
||||
# return public.returnMsg(False,'错误的参数!')
|
||||
get.path = public.get_site_path() #'/www/wwwroot'
|
||||
@@ -425,7 +502,6 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
if not os.path.isdir(get.path):
|
||||
return public.return_msg_gettext(False,'This is not a directory')
|
||||
|
||||
import pwd
|
||||
dirnames = []
|
||||
filenames = []
|
||||
|
||||
@@ -441,7 +517,16 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
# 实例化分页类
|
||||
page = page.Page()
|
||||
info = {}
|
||||
info['count'] = self.GetFilesCount(get.path, search)
|
||||
|
||||
if not hasattr(get, 'reverse'): get.reverse = 'False'
|
||||
if not hasattr(get, 'sort'): get.sort = 'off'
|
||||
reverse = bool(get.reverse)
|
||||
if get.reverse == 'False':
|
||||
reverse = False
|
||||
|
||||
info['count'], _nlist = self.files_list(get.path, search, my_sort=get.sort, reverse=reverse)
|
||||
# 改1
|
||||
# info['count'] = self.GetFilesCount(get.path, search)
|
||||
info['row'] = 500
|
||||
if 'disk' in get:
|
||||
if get.disk == 'true': info['row'] = 2000
|
||||
@@ -472,13 +557,18 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
data['STORE'] = self.get_files_store(None)
|
||||
data['FILE_RECYCLE'] = os.path.exists('data/recycle_bin.pl')
|
||||
|
||||
if not hasattr(get, 'reverse'): get.reverse = 'False'
|
||||
if not hasattr(get, 'sort'): get.sort = 'name'
|
||||
reverse = bool(get.reverse)
|
||||
if get.reverse == 'False':
|
||||
reverse = False
|
||||
for file_info in self.__list_dir(get.path, get.sort, reverse):
|
||||
filename = os.path.join(get.path, file_info[0])
|
||||
# if info['count'] >= 200 and not os.path.exists('data/max_files_sort.pl'):
|
||||
# get.reverse = 'False'
|
||||
# reverse = False
|
||||
# get.sort = ''
|
||||
|
||||
# _nlist = self.__default_list_dir(get.path,page.SHIFT,page.ROW)
|
||||
# data['SORT'] = 0
|
||||
# else:
|
||||
# _nlist = self.__list_dir(get.path, get.sort, reverse)
|
||||
|
||||
for file_info in _nlist:
|
||||
|
||||
if search:
|
||||
if file_info[0].lower().find(search) == -1:
|
||||
continue
|
||||
@@ -487,19 +577,25 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
break
|
||||
if i < page.SHIFT:
|
||||
continue
|
||||
if not os.path.exists(filename) and not os.path.islink(filename): continue
|
||||
file_info = self.__format_stat(filename, get.path)
|
||||
if not file_info: continue
|
||||
favorite = self.__check_favorite(filename, data['STORE'])
|
||||
r_file = self.__filename_flater(file_info['name']) + ';' + str(file_info['size']) + ';' + str(file_info['mtime']) + ';' + str(
|
||||
file_info['accept']) + ';' + file_info['user'] + ';' + file_info['link']+';'\
|
||||
+ self.get_download_id(filename) + ';' + self.is_composer_json(filename)+';'\
|
||||
+ favorite+';'+self.__check_share(filename)
|
||||
if os.path.isdir(filename):
|
||||
dirnames.append(r_file)
|
||||
else:
|
||||
filenames.append(r_file)
|
||||
n += 1
|
||||
|
||||
try:
|
||||
fname = file_info[0].encode('unicode_escape').decode("unicode_escape")
|
||||
filename = os.path.join(get.path, fname)
|
||||
if not os.path.exists(filename) and not os.path.islink(filename): continue
|
||||
file_info = self.__format_stat(filename, get.path)
|
||||
if not file_info: continue
|
||||
favorite = self.__check_favorite(filename, data['STORE'])
|
||||
r_file = self.__filename_flater(file_info['name']) + ';' + str(file_info['size']) + ';' + str(file_info['mtime']) + ';' + str(
|
||||
file_info['accept']) + ';' + file_info['user'] + ';' + file_info['link']+';'\
|
||||
+ self.get_download_id(filename) + ';' + self.is_composer_json(filename)+';'\
|
||||
+ favorite+';'+self.__check_share(filename)
|
||||
if os.path.isdir(filename):
|
||||
dirnames.append(r_file)
|
||||
else:
|
||||
filenames.append(r_file)
|
||||
n += 1
|
||||
except:
|
||||
continue
|
||||
|
||||
data['DIR'] = dirnames
|
||||
data['FILES'] = filenames
|
||||
@@ -536,8 +632,77 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
data['search_history'] = public.get_search_history('files','get_list')
|
||||
public.set_dir_history('files','GetDirList',data['PATH'])
|
||||
|
||||
# 2023-3-6,增加融入企业级防篡改
|
||||
data = self._check_tamper(data)
|
||||
data = self._get_bt_sync_status_old(data)
|
||||
return data
|
||||
|
||||
# ———————————————————
|
||||
# 融合企业级防篡改 |
|
||||
# ———————————————————
|
||||
|
||||
# 防篡改:获取文件是否在保护列表中
|
||||
|
||||
def _check_tamper(self, data):
|
||||
try:
|
||||
import PluginLoader
|
||||
except:
|
||||
return {}
|
||||
args = public.dict_obj()
|
||||
args.client_ip = public.GetClientIp()
|
||||
args.fun = "check_dir_safe"
|
||||
args.s = "check_dir_safe"
|
||||
args.file_data = {
|
||||
"base_path": data['PATH'],
|
||||
"dirs": [i.split(";", 1)[0] for i in data["DIR"]],
|
||||
"files": [i.split(";", 1)[0] for i in data["FILES"]]
|
||||
}
|
||||
data["tamper_data"] = PluginLoader.plugin_run("tamper_core", "check_dir_safe", args)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
|
||||
# 获取文件同步状态
|
||||
@staticmethod
|
||||
def _get_bt_sync_status_old(data):
|
||||
config_file = "{}/plugin/rsync/config4.json".format(public.get_panel_path())
|
||||
if not os.path.exists(config_file):
|
||||
data["bt_sync"] = {}
|
||||
return data
|
||||
try:
|
||||
conf = json.loads(public.readFile(config_file))
|
||||
except json.JSONDecodeError:
|
||||
data["bt_sync"] = {}
|
||||
return data
|
||||
|
||||
dirs = [data['PATH'] + "/" + i.split(";", 1)[0] for i in data["DIR"]]
|
||||
res = [{} for _ in range(len(dirs))]
|
||||
for idx, d in enumerate(dirs):
|
||||
for value in conf.get("modules", []):
|
||||
if value.get("path", "").rstrip("/") == d:
|
||||
res[idx] = {
|
||||
"type": "modules",
|
||||
"name": value.get("name", ""),
|
||||
"status": value.get("recv_status", True),
|
||||
"path": d,
|
||||
}
|
||||
|
||||
for idx, d in enumerate(dirs):
|
||||
for value in conf.get("senders", []):
|
||||
if value.get("source", "").rstrip("/") == d:
|
||||
target = value.get("target_list", [{}])[0]
|
||||
res[idx] = {
|
||||
"type": "senders",
|
||||
"name": target.get("name", ""),
|
||||
"status": target.get("status", True),
|
||||
"path": d,
|
||||
}
|
||||
|
||||
data["bt_sync"] = res
|
||||
return data
|
||||
|
||||
|
||||
|
||||
def get_file_ps(self,filename):
|
||||
'''
|
||||
@@ -548,13 +713,17 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
'''
|
||||
|
||||
ps_path = public.get_panel_path() + '/data/files_ps'
|
||||
f_key1 = '/'.join((ps_path,public.md5(filename)))
|
||||
if os.path.exists(f_key1):
|
||||
return public.readFile(f_key1)
|
||||
try:
|
||||
f_key1 = '/'.join((ps_path,public.md5(filename)))
|
||||
|
||||
f_key2 = '/'.join((ps_path,public.md5(os.path.basename(filename))))
|
||||
if os.path.exists(f_key2):
|
||||
return public.readFile(f_key2)
|
||||
if os.path.exists(f_key1):
|
||||
return public.readFile(f_key1)
|
||||
|
||||
f_key2 = '/'.join((ps_path,public.md5(os.path.basename(filename))))
|
||||
if os.path.exists(f_key2):
|
||||
return public.readFile(f_key2)
|
||||
except:
|
||||
pass
|
||||
|
||||
pss = {
|
||||
'/www/server/data':'MySQL data storage directory!',
|
||||
@@ -600,10 +769,17 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
'/usr/local/sbin': 'System script directory',
|
||||
'/usr/local/bin': 'System script directory'
|
||||
}
|
||||
if filename in pss: return "PS:" + pss[filename]
|
||||
|
||||
if not self.recycle_list: self.recycle_list = public.get_recycle_bin_list()
|
||||
if filename + '/' in self.recycle_list: return 'PS: Recycle Bin Directory'
|
||||
if str(filename).endswith(".bt_split_json"):
|
||||
return "PS: Split the recovery profile"
|
||||
if str(filename).endswith(".bt_split"):
|
||||
return "PS: Split unit file"
|
||||
if filename in pss: return "PS:" + pss[filename]
|
||||
try:
|
||||
if not self.recycle_list: self.recycle_list = public.get_recycle_bin_list()
|
||||
except:
|
||||
pass
|
||||
if filename + '/' in self.recycle_list:'PS: Recycle Bin Directory'
|
||||
if filename in self.recycle_list: return 'PS: Recycle Bin Directory'
|
||||
return ''
|
||||
|
||||
@@ -930,8 +1106,7 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
public.WriteLog('TYPE_FILE', 'Successfully deleted directory [{}]!', (get.path,))
|
||||
self.remove_file_ps(get)
|
||||
return public.return_msg_gettext(True, ' Successfully deleted directory!')
|
||||
except Exception as e:
|
||||
public.print_log("DeleteDir error info :{}".format(e))
|
||||
except:
|
||||
return public.return_msg_gettext(False, 'Failed to delete directory!')
|
||||
|
||||
# 删除 空目录
|
||||
@@ -1256,9 +1431,9 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
public.write_log_gettext('File manager','[{}] renamed to [{}]',(get.sfile,get.dfile))
|
||||
return public.return_msg_gettext(True,'Successfully renamed!')
|
||||
else:
|
||||
public.write_log_gettext('File manager', 'Database moved!',
|
||||
public.write_log_gettext('File manager', 'File moved!',
|
||||
(get.sfile, get.dfile))
|
||||
return public.return_msg_gettext(True, 'Database moved!')
|
||||
return public.return_msg_gettext(True, 'File moved!')
|
||||
except:
|
||||
return public.return_msg_gettext(False, 'Failed to move file!')
|
||||
|
||||
@@ -1795,11 +1970,11 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
return self.GetDirSize(get)
|
||||
|
||||
# 批量操作
|
||||
def SetBatchData(self, get):
|
||||
def SetBatchData(self, get: public.dict_obj):
|
||||
if sys.version_info[0] == 2:
|
||||
get.path = get.path.encode('utf-8')
|
||||
if get.type == '1' or get.type == '2':
|
||||
session['selected'] = get
|
||||
session['selected'] = get.get_items()
|
||||
return public.return_msg_gettext(True, 'Successfully marked, please click Paste All button in the target directory!')
|
||||
elif get.type == '3':
|
||||
for key in json.loads(get.data):
|
||||
@@ -2428,7 +2603,7 @@ cd %s
|
||||
pdata['password'] = get.password
|
||||
if len(pdata['password']) < 4 and len(pdata['password']) > 0:
|
||||
return public.return_msg_gettext(False,'The length of the extracted password cannot be less than 4 digits')
|
||||
if not re.match('^\w+$',pdata['password']):
|
||||
if not re.match(r'^\w+$',pdata['password']):
|
||||
return public.return_msg_gettext(False,'The password only supports a combination of uppercase and lowercase letters and numbers')
|
||||
|
||||
if 'ps' in get: pdata['ps'] = get.ps
|
||||
@@ -2455,7 +2630,7 @@ cd %s
|
||||
pdata['token'] += "." + exts[-1]
|
||||
if len(pdata['password']) < 4 and len(pdata['password']) > 0:
|
||||
return public.return_msg_gettext(False,' Please do not enter the following special characters [ ~ ` / = ]')
|
||||
if not re.match('^\w+$',pdata['password']) and pdata['password']:
|
||||
if not re.match(r'^\w+$',pdata['password']) and pdata['password']:
|
||||
return public.return_msg_gettext(False,'The password only supports a combination of uppercase and lowercase letters and numbers')
|
||||
#更新 or 插入
|
||||
token = public.M(my_table).where('filename=?',(get.filename,)).getField('token')
|
||||
@@ -3254,7 +3429,7 @@ CREATE TABLE index_tb(
|
||||
def restore_website(self,args):
|
||||
"""
|
||||
@name 恢复站点文件
|
||||
@author zhwen<zhw@bt.cn>
|
||||
@author zhwen<zhw@aapanel.com>
|
||||
@parma file_name 备份得文件名
|
||||
@parma site_id 网站id
|
||||
"""
|
||||
@@ -3265,8 +3440,8 @@ CREATE TABLE index_tb(
|
||||
def get_progress(self,args):
|
||||
"""
|
||||
@name 获取进度日志
|
||||
@author zhwen<zhw@bt.cn>
|
||||
@author zhwen<zhw@aapanel.com>
|
||||
"""
|
||||
import panel_restore
|
||||
pr=panel_restore.panel_restore()
|
||||
return pr.get_progress(args)
|
||||
return pr.get_progress(args)
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: cjxin <cjxin@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
# 上传文件至oss
|
||||
#------------------------------
|
||||
from filesModel.base import filesBase
|
||||
import public
|
||||
|
||||
class main(filesBase):
|
||||
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
def get_oss_objects(self,get):
|
||||
"""
|
||||
@name 获取可上传的对象存储
|
||||
"""
|
||||
return self.get_all_objects(get)
|
||||
|
||||
|
||||
def download_file(self,get):
|
||||
"""
|
||||
@name 下载文件
|
||||
@param get
|
||||
file:文件路径
|
||||
"""
|
||||
|
||||
info = self.get_soft_find(get.name)
|
||||
if not info['setup']:
|
||||
return public.returnMsg(False,'未安装[{}]插件'.format(info['title']))
|
||||
|
||||
import panelTask
|
||||
task_obj = panelTask.bt_task()
|
||||
task_obj.create_task('下载文件', 1, get.url, get.path + '/' + get.filename)
|
||||
public.set_module_logs('files_down_to_file', 'download_file', 1)
|
||||
public.WriteLog('TYPE_FILE', '从 [{}] 下载文件 [{}] 到 {}'.format(info['title'],get.filename,get.path))
|
||||
return public.returnMsg(True, 'FILE_DOANLOAD')
|
||||
|
||||
QRASP55VO/1DQ98p1csw9A==
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
dBZyCsfrbwqvA0sbdGrIGg==
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
n+0ptngHIPIjFuMNQ53bfj+Na/fdhk6k1yTpAwW7j353Dw920mEqQQZjykAHeRmp0ZD/P3ftGifsmPOMf2b7XdEqyZH0yl9kjaUugj3dYPI=
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
jh3cxzkA2htccqfZRKAUdI8r17q57nOGP4OxbJlL1NAnrF4weHnS0MpT6C6jbrX5
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
kEPo6lgxLBQavG1DxRrlnEK5KohxBShsQIeNCGHkEP4=
|
||||
I8MGJUwtjfcKc5w4E0SmjHwLsErBQ84ek459TV1n0Iir/P4mdpfwDI34s6+8CBN0
|
||||
X9BNoFOwiQAnMPqEk6FnbzU/oA+chL/aEAzGH80mBrNNxRMBdiGPqgDUeLF6rer2
|
||||
XIfdJ79nObMM+vyAmKbTmw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
CjJS7KrzKM18mlLqJK9jKTB717Vvrubu5ix9tb047ao=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
9GxZpCRwMRDPejWR2Vvf+LKn0tNtFKp8Eh2tnr4Da9U=
|
||||
6c3cWGGlsEf4q4E+EjPFyg==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
9bJD7OGVYIbkQwcqio3pMkEQ5Tepk1KAKJBdik81BOHNSVFwrMdl2gFGwZvvpYDQ
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
NNh1PlSD8WUnUEbz+BU/P5ZvVL4YjAgUVrqKtQwmJSm1F1KbG0/rNY/6xTjx3EA3
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
CAhn8dRUItEbEErp4w+lX9Z2hX2+feDN0U2wxQk1jf6XkRmrNeGBO3gU/TXqpTeF
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
vHI6ym+jnn06PgL99476zxO+uTTrKbsFCbogJPwJML2TG1a7NmZkzv05uK3L/Tc8
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
n3tXewq2IYqiwFREjJjsxZJ3F7EUu5p3TiQaoXfFThA=
|
||||
ho/Q+jrWDtBeg9J9ZTnKi3+/Efbvadpf+qoH75NuGwk=
|
||||
PRG/YRzXVD8iVR3bzEcUnsWMvR86r5liyWslQeT39Bs=
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
AN33R+yjfqqAkAsFnmP/r/WGRgGkDEv8Fnc8kjQsJ7fRnV1BKZAu/huNYnIc6I01
|
||||
cbvASHjpysrsjdY5RctXmG9wund6qoaXAfnCgO+o1nY=
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmXHKWKUVVa/rOrR3+fgEd7tp63QHMzA34qukyTQgDFJrLVYVJL/Ye3kNmAIiExi//aTWiBsWXWTJE2/bLQwR3ie
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
q4nc/jwATOMUyfSjLibfEelnou8pLYpfebj3/LvnkGg=
|
||||
7fBvPEAf72Uv1YEDXbbQ3CN3MWrD+3vkr2VJCCzzEPRhwccGf00/aNA1BGgdy8WH
|
||||
7fBvPEAf72Uv1YEDXbbQ3JX8fOX6IsaFNTXjLCv8fl9nBsjACyGde1V2jqcLtcHMgHmQHXLhOkH7ECCy4Qan/Eap/d5B8ETngKGRLc1dnrFJxLrR59XTXqj5a3KAPh6f
|
||||
Ic1WBp01nLyRxbqJnsu2pypx+Gb9M9+y4CZIw5enWs8XJaZJ50IVd+4cfwZkMesXHuMlT+97TT2qjLWtQKOwIMYvrQOoIlZ+noM34BKXXbE=
|
||||
2+RceSNjD2iq0sRzepMyse3K/6KDWrRQWf3bA9DlS0ntu9Qw70LcA2SU6TO7qbj7+BZ00tLn7oRDAJhOp7GBQJ9AdWUuTKC0qj4H0sUep4AFfY3QegcrH7wS+cAOaYcaYNB7YC/AjQj4DFsev5mqOa3aXW4VcIMS3jP/SRer5vo=
|
||||
96orka/uERLyRst14azQwhCOqhTfcgFhXNAQS0hmuOHo1JRV4mvyfjFAJfZA0Y7fzjR8HN7n40vj/TKQkGxagQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
|
||||
+342
-342
@@ -1,342 +1,342 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: cjxin <cjxin@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#
|
||||
#------------------------------
|
||||
|
||||
import os,sys,re
|
||||
from filesModel.base import filesBase
|
||||
import public,json
|
||||
import tarfile,shutil,gzip
|
||||
|
||||
class main(filesBase):
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
def __check_zipfile(self,sfile,is_close = False):
|
||||
'''
|
||||
@name 检查文件是否为zip文件
|
||||
@param sfile 文件路径
|
||||
@return bool
|
||||
'''
|
||||
|
||||
pass
|
||||
|
||||
def get_zip_files(self,args):
|
||||
'''
|
||||
@name 获取压缩包内文件列表
|
||||
@param args['path'] 压缩包路径
|
||||
@return list
|
||||
'''
|
||||
sfile = args.sfile
|
||||
if not os.path.exists(sfile):
|
||||
return public.returnMsg(False,'FILE_NOT_EXISTS')
|
||||
|
||||
if not tarfile.is_tarfile(sfile):
|
||||
return public.returnMsg(False,'Not a valid tar.gz archive file')
|
||||
|
||||
zip_file = tarfile.open(sfile)
|
||||
data = {}
|
||||
for item in zip_file.getmembers():
|
||||
|
||||
sub_data = data
|
||||
f_name = self.__get_zip_filename(item)
|
||||
|
||||
f_dirs = f_name.split('/')
|
||||
for d in f_dirs:
|
||||
if not d: continue
|
||||
if not d in sub_data:
|
||||
if d == f_name[-len(d):]:
|
||||
|
||||
sub_data[d] = {
|
||||
'file_size': item.size,
|
||||
'filename':d,
|
||||
'fullpath':f_name,
|
||||
'date_time': public.format_date(times=item.mtime),
|
||||
'is_dir': 0
|
||||
}
|
||||
if item.isdir():
|
||||
sub_data[d]['is_dir'] = 1
|
||||
else:
|
||||
sub_data[d] = {}
|
||||
sub_data = sub_data[d]
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_fileinfo_by(self,args):
|
||||
'''
|
||||
@name 获取压缩包内文件信息
|
||||
@param args['path'] 压缩包路径
|
||||
@param args['filename'] 文件名
|
||||
@return dict
|
||||
'''
|
||||
|
||||
sfile = args.sfile
|
||||
filename = args.filename
|
||||
if not os.path.exists(sfile):
|
||||
return public.returnMsg(False,'FILE_NOT_EXISTS')
|
||||
|
||||
tmp_path = '{}/tmp/{}'.format(public.get_panel_path(),public.md5(sfile + filename))
|
||||
result = {}
|
||||
result['status'] = True
|
||||
result['data'] = ''
|
||||
with tarfile.open(sfile,'r') as zip_file:
|
||||
try:
|
||||
zip_file.extract(filename,tmp_path)
|
||||
result['data'] = public.readFile('{}/{}'.format(tmp_path,filename))
|
||||
except:pass
|
||||
try:
|
||||
public.rmdir(tmp_path)
|
||||
except:pass
|
||||
return result
|
||||
|
||||
def delete_zip_file(self,args):
|
||||
'''
|
||||
@name 删除压缩包内文件
|
||||
@param args['path'] 压缩包路径
|
||||
@param args['filenames'] 文件名列表,数组格式
|
||||
@return dict
|
||||
'''
|
||||
sfile = args.sfile
|
||||
filenames = args.filenames
|
||||
|
||||
if not tarfile.is_tarfile(sfile):
|
||||
return public.returnMsg(False,'Not a valid tar.gz archive file')
|
||||
|
||||
tmp_path = self.__unzip_tmp_path(sfile)
|
||||
if not tmp_path: return public.returnMsg(False,'Failed edit!')
|
||||
|
||||
#组装原有的文件
|
||||
s_list = []
|
||||
src_list = {}
|
||||
public.get_file_list(tmp_path,s_list)
|
||||
for f in s_list:
|
||||
if not os.path.isfile(f): continue
|
||||
src_file = f.replace(tmp_path,'').strip('/')
|
||||
if src_file in filenames:
|
||||
continue
|
||||
src_list[src_file] = f
|
||||
|
||||
with tarfile.open(sfile,'w') as new_zfile:
|
||||
try:
|
||||
for src_file in src_list:
|
||||
new_zfile.add(src_list[src_file],src_file)
|
||||
except:
|
||||
shutil.rmtree(tmp_path, True)
|
||||
return public.returnMsg(False,'Failed delete file,error:' + public.get_error_info())
|
||||
|
||||
shutil.rmtree(tmp_path, True)
|
||||
return public.returnMsg(True,'Compressed package file modified successfully')
|
||||
|
||||
|
||||
def write_zip_file(self,args):
|
||||
'''
|
||||
@name 写入压缩包内文件
|
||||
@param args['path'] 压缩包路径
|
||||
@param args['filename'] 文件名
|
||||
@param args['data'] 写入数据
|
||||
@return dict
|
||||
'''
|
||||
|
||||
sfile = args.sfile
|
||||
filename = args.filename
|
||||
data = args.data
|
||||
|
||||
if not os.path.exists(sfile):
|
||||
return public.returnMsg(False,'FILE_NOT_EXISTS')
|
||||
|
||||
tmp_path = self.__unzip_tmp_path(sfile)
|
||||
if not tmp_path: return public.returnMsg(False,'Failed edit!')
|
||||
public.writeFile('{}/{}'.format(tmp_path,filename),data)
|
||||
|
||||
#组装原有的文件
|
||||
s_list = []
|
||||
src_list = {}
|
||||
public.get_file_list(tmp_path,s_list)
|
||||
for f in s_list:
|
||||
if os.path.isdir(f):
|
||||
continue
|
||||
src_file = f.replace(tmp_path,'').strip('/')
|
||||
if src_file in src_list:
|
||||
continue
|
||||
src_list[src_file] = f
|
||||
|
||||
with tarfile.open(sfile,'w') as new_zfile:
|
||||
try:
|
||||
for src_file in src_list:
|
||||
new_zfile.add(src_list[src_file],src_file)
|
||||
except:
|
||||
shutil.rmtree(tmp_path, True)
|
||||
return public.returnMsg(False,'Failed modify file,error:' + public.get_error_info())
|
||||
|
||||
shutil.rmtree(tmp_path, True)
|
||||
return public.returnMsg(True,'Compressed package file modified successfully')
|
||||
|
||||
|
||||
|
||||
def extract_byfiles(self,args):
|
||||
"""
|
||||
@name 解压部分文件
|
||||
@param args['path'] 压缩包路径
|
||||
@param args['extract_path'] 解压路径
|
||||
@param args['filenames'] 文件名列表,数组格式
|
||||
"""
|
||||
sfile = args.sfile
|
||||
filenames = args.filenames
|
||||
extract_path = args.extract_path
|
||||
if not os.path.exists(sfile):
|
||||
return public.returnMsg(False,'FILE_NOT_EXISTS')
|
||||
|
||||
if not os.path.exists(extract_path):
|
||||
os.makedirs(extract_path,384)
|
||||
|
||||
tmp_path = '{}/tmp/{}'.format(public.get_panel_path(),public.md5(public.GetRandomString(32)))
|
||||
if not os.path.exists(tmp_path):
|
||||
os.makedirs(tmp_path,384)
|
||||
|
||||
with tarfile.open(sfile) as zip_file:
|
||||
try:
|
||||
m_list = {}
|
||||
|
||||
f_infos = zip_file.getmembers()
|
||||
for item in f_infos:
|
||||
filename = self.__get_zip_filename(item)
|
||||
|
||||
if filename in filenames:
|
||||
spath = os.path.join(tmp_path,filename).strip('/')
|
||||
if item.isdir():
|
||||
m_list[spath] = []
|
||||
else:
|
||||
if not 'other' in m_list:
|
||||
m_list['other'] = []
|
||||
|
||||
dir_key = os.path.dirname(spath)
|
||||
info = {'src':spath,'dst':'{}/{}'.format(extract_path, filename.strip('/'))}
|
||||
if dir_key in m_list:
|
||||
info['dst'] = '{}/{}'.format(extract_path,'/'.join(filename.split('/')[1:]))
|
||||
s_path = os.path.dirname(info['dst'])
|
||||
if not os.path.exists(s_path): os.makedirs(s_path,384)
|
||||
|
||||
m_list[dir_key].append(info)
|
||||
else:
|
||||
m_list['other'].append(info)
|
||||
|
||||
s_path = os.path.dirname(info['dst'])
|
||||
if not os.path.exists(s_path): os.makedirs(s_path, 384)
|
||||
zip_file.extract(filename.strip('/'),tmp_path)
|
||||
|
||||
for key in m_list:
|
||||
try:
|
||||
for info in m_list[key]:
|
||||
if os.getenv('BT_PANEL'):
|
||||
shutil.copyfile(info['src'],info['dst'])
|
||||
else:
|
||||
shutil.copyfile('/' + info['src'],'/' + info['dst'])
|
||||
except:
|
||||
pass
|
||||
shutil.rmtree(tmp_path, True)
|
||||
except:
|
||||
return public.returnMsg(False,'Decompression failed,error:' + public.get_error_info())
|
||||
return public.returnMsg(True,'File was decompressed successfully')
|
||||
|
||||
def __unzip_tmp_path(self,sfile):
|
||||
'''
|
||||
@name 获取临时解压路径
|
||||
@param sfile 压缩包路径
|
||||
@return str
|
||||
'''
|
||||
tmp_path = '{}/tmp/{}'.format(public.get_soft_path(),public.md5(public.GetRandomString(32)))
|
||||
with tarfile.open(sfile) as zip_file:
|
||||
try:
|
||||
zip_file.extractall(tmp_path)
|
||||
except: return False
|
||||
|
||||
return tmp_path
|
||||
|
||||
|
||||
def add_zip_file(self,args):
|
||||
'''
|
||||
@name 添加文件到压缩包
|
||||
@param args['r_path'] 跟路径
|
||||
@param args['filename'] 文件名
|
||||
@param args['f_list'] 写入数据
|
||||
@return dict
|
||||
'''
|
||||
|
||||
sfile = args.sfile
|
||||
r_path = args.r_path
|
||||
f_list = args.f_list
|
||||
if not os.path.exists(sfile):
|
||||
return public.returnMsg(False,'FILE_NOT_EXISTS')
|
||||
|
||||
tmp_path = self.__unzip_tmp_path(sfile)
|
||||
if not tmp_path: return public.returnMsg(False,'Failed edit!')
|
||||
|
||||
#组装新添加的文件
|
||||
src_list = {}
|
||||
for fname in f_list:
|
||||
if os.path.isdir(fname):
|
||||
s_list = []
|
||||
public.get_file_list(fname,s_list)
|
||||
|
||||
for f in s_list:
|
||||
if os.path.isdir(f):
|
||||
continue
|
||||
src_file = '{}/{}{}'.format(r_path,os.path.basename(fname),f.replace(fname,'')).replace('//','/')
|
||||
src_list[src_file] = f
|
||||
else:
|
||||
src_file = '{}/{}'.format(r_path, os.path.basename(fname)).replace('//','/')
|
||||
src_list[src_file] = fname
|
||||
|
||||
#组装原有的文件
|
||||
s_list = []
|
||||
public.get_file_list(tmp_path,s_list)
|
||||
for f in s_list:
|
||||
if os.path.isdir(f):
|
||||
continue
|
||||
src_file = f.replace(tmp_path,'').strip('/')
|
||||
if src_file in src_list:
|
||||
continue
|
||||
src_list[src_file] = f
|
||||
|
||||
with tarfile.open(sfile,'w') as new_zfile:
|
||||
try:
|
||||
for src_file in src_list:
|
||||
new_zfile.add(src_list[src_file],src_file)
|
||||
except:
|
||||
shutil.rmtree(tmp_path, True)
|
||||
return public.returnMsg(False,'Failed add file,error:' + public.get_error_info())
|
||||
|
||||
shutil.rmtree(tmp_path, True)
|
||||
return public.returnMsg(True,'Compressed package file modified successfully')
|
||||
|
||||
|
||||
|
||||
def __get_zip_filename(self,item):
|
||||
'''
|
||||
@name 获取压缩包文件名
|
||||
@param item 压缩包文件对象
|
||||
@return string
|
||||
'''
|
||||
filename = item.name
|
||||
try:
|
||||
filename = item.name.encode('cp437').decode('gbk')
|
||||
except:pass
|
||||
if item.isdir():
|
||||
filename += '/'
|
||||
return filename
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
QRASP55VO/1DQ98p1csw9A==
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
dBZyCsfrbwqvA0sbdGrIGg==
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
n+0ptngHIPIjFuMNQ53bfj+Na/fdhk6k1yTpAwW7j353Dw920mEqQQZjykAHeRmp0ZD/P3ftGifsmPOMf2b7XdEqyZH0yl9kjaUugj3dYPI=
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
jh3cxzkA2htccqfZRKAUdI8r17q57nOGP4OxbJlL1NAnrF4weHnS0MpT6C6jbrX5
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
Hf+bBTgRv9pVfall8ODpvg==
|
||||
I8MGJUwtjfcKc5w4E0SmjHwLsErBQ84ek459TV1n0Iir/P4mdpfwDI34s6+8CBN0
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
K3QJU/hV27C5FAVoZ+avNNMfDMygeonfI5TFnvUHjhU=
|
||||
X9BNoFOwiQAnMPqEk6FnbzU/oA+chL/aEAzGH80mBrNNxRMBdiGPqgDUeLF6rer2
|
||||
hUVhKZtvg+FKessuieMZGkP/5FS8EfJsx7HCvhsTdvM=
|
||||
y9P3+4KXYacR8m2lL04bxyxkWpCOoKKwyE9jOO9xzDU=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
CjJS7KrzKM18mlLqJK9jKTB717Vvrubu5ix9tb047ao=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
9GxZpCRwMRDPejWR2Vvf+LKn0tNtFKp8Eh2tnr4Da9U=
|
||||
6c3cWGGlsEf4q4E+EjPFyg==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
6d8NLnHX3WuS3g79bJvyhLTeka+iJoxis1kUHdyggy+yXh3Xc8xsyir/5NbKP+Sj41j2UHgL27dZFRsmbh/P+Q==
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
0LFyB+q/4AUBkCrX53xYJedFoNZHYELHOLu/R25oBrqozNv9g917+/ANMSb6X+WR
|
||||
yqM179SzW9HnBHozkU+IlaI6kf6Fax7Db/qE4wQMDFqfwVE+4rG3+IJ9S3c+p3Wf
|
||||
akHibliG6j9uvBEg96vRehUZmhX3a+KyYm/Obf/H764=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
6c3cWGGlsEf4q4E+EjPFyg==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
x41zVQ6DCtWXndDIq7U8L+5quM3ARMCnVm34NUX7l/TJzZZ100EvdUXHXI2cFH4H
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
NNh1PlSD8WUnUEbz+BU/P7D7U0y87ntgFdQV5REShmme9ACxsySMBZr2gsEQniKL
|
||||
c1XU6vxl7MsQKGo3r4amMsSWef3BumXlCWI6QCsp6pMACoHb/XNQfx2cpKV7J/MH
|
||||
akHibliG6j9uvBEg96vRer/Fg5zTlM8oj8hSAsYq018=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
YdUmdqAC07VhbSt1h6KCDASPIXTwTSkv8cm4ToJ+lpo=
|
||||
wgR07xfoapmx6eEnFHXXYmnjxw2aWD9jyym26bSe8wdUky12ZBuFKfAUxS++Pix0
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW/27EoqfC0X59kkH7imoHQb/TQW5074PHVFRKqgD5aSA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
sV2BMz3qoSZgP7XLsV0u8Ey5TTZbfTeRXmE8Lnkq8ecwI8LY+wsKkeHx5JQmHjbJ
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmWW4zkUYYb5UAUX8zS+IvdqmDjQdLy6c68fWPpLBj0d0GY6NLmGX6bobgiWRy9bUsk=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1VHvxkEcO4espNMpWHmnH39LdUi6HdEZyAx9T9sPSkCOt9wcLgOersS/HmOi2Xel
|
||||
JbnXIK/axHVmA2plDNFCpPYlXWvPB/7lIz9ynMkifTY=
|
||||
ei/1A+2pKZSasjYF/t4qooATwcryDpeJQCtosnRGcgHSsp9sawkQJUO/Q/xMUnXL
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
4nsuLyRybkZg8C3fJCsRPXDWwLMccXwEpFBdFK0JOvg=
|
||||
ZFD6pnBshb3mpu7xvvuMLemrazA4ssXDDuW5SINX4ZLsvLIwaJ4YyDANze64OGqUEj7NCJs+t+zkcUskHr+gqw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
g5xFPP9LKBd4uktrRYzGf+p1NdL+k6huN6CrzYXY3fPVQzhtKStMTpRTZpRqmhGR
|
||||
wlLHv6kT3Q/RmtMBN4nDAbqo0o2IA7mU8WVNqZvoB5I=
|
||||
VmVrGQo2zRokW/ZuO9bN6+qRbBr2ygG3RGcAIOk727ylzODmV8VRqZ4YKvduSUCu
|
||||
VmVrGQo2zRokW/ZuO9bN62psx0nYMGJaQ1S1BUtE6l8lgsopQJ3Qf5syQpAasAAf
|
||||
VmVrGQo2zRokW/ZuO9bN69Woqo49I0Fga24Nj55N9ZL81I98txu56TEAiJ0hswK9
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN69+qNrAfkaoVno2zP/PIMh/5aA4AiEej6zodAVzZFzS0
|
||||
VmVrGQo2zRokW/ZuO9bN6xT3wQu8/ZV37F/D/EekYn8lOmX2nmjCcfYXY14ohcOqo/JjN+Uf5m+lGfErLLeSsw==
|
||||
VmVrGQo2zRokW/ZuO9bN6xT3wQu8/ZV37F/D/EekYn92m0FWAHkcFEifdcSefZI3
|
||||
VmVrGQo2zRokW/ZuO9bN6xQU/k6xhXMbxscs7Gix8nNqUkjAknQH3LrGVvAyjYtQ
|
||||
VmVrGQo2zRokW/ZuO9bN6xOutEc9teLv333RLphPxTSZMBPTZ5nEHEAZCqisJAYdi0Te13nq3FDKoUwPWRFVhcbFGXs/hncVFmPVZNUBUZY=
|
||||
VmVrGQo2zRokW/ZuO9bN6wv73IH9kSzXKMUmUPacSk1KDsdrjROzTN1kzduuP0l3
|
||||
VmVrGQo2zRokW/ZuO9bN69lJPu1G3iX01kmj1/0ynPc=
|
||||
VmVrGQo2zRokW/ZuO9bN63p1oaV/8/rZOHP3bxdBsLtxlUb0X9CVsj27gKH7yxkc
|
||||
VmVrGQo2zRokW/ZuO9bN6/kiIWH8hJ6dJOo/fnNj9VLcBHtqpOZ/Rc4AjXcEm1edHKkbtiFAlXrzE+rfp/AeMQ==
|
||||
VmVrGQo2zRokW/ZuO9bN69jIxF5VISZtC2vxWRknx7k=
|
||||
VmVrGQo2zRokW/ZuO9bN69+qNrAfkaoVno2zP/PIMh80w0dM3z0phdMS+lT6j/xo
|
||||
VmVrGQo2zRokW/ZuO9bN65abAZ39yZLyKCl4nd6eov4HdKauw4+toNc5YoXvsAeW
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
+plE/1bhdo64kO07cLlUXzzWH25pNAS0eDxp8hnHILg=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
J24jXQQti6wQv5pCoF2ZrRvdf2ev6P6vInKuFAO8eQfewP9/G67aA1dZDLRwjari
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
NNh1PlSD8WUnUEbz+BU/P7D7U0y87ntgFdQV5REShmlP+1p+XjT1dvUjFUZHsqC6
|
||||
c1XU6vxl7MsQKGo3r4amMsSWef3BumXlCWI6QCsp6pMACoHb/XNQfx2cpKV7J/MH
|
||||
c1XU6vxl7MsQKGo3r4amMpPnl/Q0nxs4Ul/v+JmLHipRvS1iO3+JhmWzafMyTI0p
|
||||
akHibliG6j9uvBEg96vResIm2pvfeBRQxNU2J0BQeUc=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
YdUmdqAC07VhbSt1h6KCDASPIXTwTSkv8cm4ToJ+lpo=
|
||||
BIa0ibHnqUboaK9kYHYO4um2nnLtPSMsHb7nUhh0kKQ6CdlvwTSeB4h8LEiuwG9t
|
||||
wgR07xfoapmx6eEnFHXXYmnjxw2aWD9jyym26bSe8wdUky12ZBuFKfAUxS++Pix0
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW/27EoqfC0X59kkH7imoHQb/TQW5074PHVFRKqgD5aSA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
IZj4TYq2HlScfSdRkI+QP263Ug7hf7sm5bqxRn1G7j8CZM6KmOHJcbEZNXo2mkEAKAgQMZx8+NhDilcUt2veW2ndED3g1z4Otqk5QlUsRCjvCITtLgXlADwlPZpuWSgD
|
||||
/0ULpLqgTvInFD0r5hHANoosZ+xywkOR5dozStfmlYk=
|
||||
YSlit6erKXylrjSZnvyW8I3FYH6DLcfYpMAlko6lQqVBBd1eDeDGaujrHWIOJkcI
|
||||
YSlit6erKXylrjSZnvyW8CCccEStX4fvFvduMtCGi54=
|
||||
D1uzgsuXIKL/yxNsPwFM0QIV7+TILj/tblfnXjJ0GYRo9qF9iYlR/oIixOO4YW9r5sQV57F10J/zF5jBaEFdKw==
|
||||
vQwaisdUFOt9b0SJYuH/nrHigrTUtycF35lf58xGUQo=
|
||||
VmVrGQo2zRokW/ZuO9bN6+8scbwlFXmHwUL6N0BWPj6dlHHDEIlkodgo1A0usjGyHhQdtr/CZJG5zDxIr66oew==
|
||||
VmVrGQo2zRokW/ZuO9bN65rMxzVrOInziG0YF1uvpqBp8ZS5jWaYG3vnBxPtXcWWa9TIx0uiiZmKhmv6T3Z+yciaFXeGtzFwR28zuXWWSf6Fvx4Mh4aXTcAi9R5RGv8f
|
||||
M0ZySqkmhuHCw6olbCKv992x+E1VMoPx+GJL+VjXXxc=
|
||||
b4OJVZe8QyIpjuTpKXDL9A==
|
||||
xWoGNWjKGPfI4gq8aHoTfL6V0pkYKbeBvdfg5x1FYR8uFPtJ2x9MfdlNdGBKn+Bi
|
||||
usrsES3VVkgHW6tBbEkpHTeLztsByVaJibbFv8kSFIM=
|
||||
ruTTNFTdswRs4Mc+srnRk818d9d/TGGXzgPjSrVtMi8=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
6JhaWzGWadTJ3yzCk9OQNgkLy/m1ahTUuEy+6FiV49HNwHkAN2ZMxFTsufeIA0ig
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
dar6N0tUAb9rU8/aX1b3tGumQ1hhfk8O6qr6gmiQ1+eBvZwFkpECn+RP444+i510
|
||||
c1XU6vxl7MsQKGo3r4amMsSWef3BumXlCWI6QCsp6pMACoHb/XNQfx2cpKV7J/MH
|
||||
c1XU6vxl7MsQKGo3r4amMlEDkaPg52QqeaL1e16aTiZGdP9MF1i1K/F0icaNF/FRZY8CjFaji8Ecm2WEpXZbMiyduIw57U2lMT6kzLqch3Y=
|
||||
akHibliG6j9uvBEg96vResIm2pvfeBRQxNU2J0BQeUc=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
YdUmdqAC07VhbSt1h6KCDASPIXTwTSkv8cm4ToJ+lpo=
|
||||
BIa0ibHnqUboaK9kYHYO4kqIZZgv1yXQHpqfJ4aNJ54bUNUYTYq/0A+dhHby52Au
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
sV2BMz3qoSZgP7XLsV0u8Ey5TTZbfTeRXmE8Lnkq8ecwI8LY+wsKkeHx5JQmHjbJ
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmWW4zkUYYb5UAUX8zS+IvdqmDjQdLy6c68fWPpLBj0d0GY6NLmGX6bobgiWRy9bUsk=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
IZj4TYq2HlScfSdRkI+QP/1JxkOTIR85eefsT8+ZE4aqE0v0U76615IyJqY5UKTuMtUbLm26g8btb6vlq0a/Rg==
|
||||
sV2BMz3qoSZgP7XLsV0u8FnjXWiNqL5EgZ3mkCPlBXRqd4GmOGu47uyTs1R79OxGn8j+RZZ1XwLWsKhwXR/uRAfKx5AH0WN2iitz8d+Ezds=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
/Bf0c5l+J3LcMje0y2hT6xexfB3PDHGLzFprRXh5sZU=
|
||||
gCKKzKpjyg80fGP7iU1CosQydbZEVmkhqpAlx45K/ms=
|
||||
HI5OOAOTfAAnGE3XBxyr2vdUoaKdz9Yp4Em51oFqNhU=
|
||||
b0AcCU56KvRpMcnxfbDRg2RaKdDnbQt+ar3yTu4ASKKZrazBALhe/1DkqoflPq4v
|
||||
QOiTGJqcvhOfGILFspJCgFitD1klQoY+1I4jtCCP/XI=
|
||||
1V2v8QerKOmubvSxgB4eTFLJVKokCn/n7cBzRCyjPmfmpa/q0AQoQFAFtjS1Nskr
|
||||
JBX7lPwBHKhyRzgJY9OZ2ID8CtKJxnNl/B8H+N4MrEOtqpoairx3dp0kQkKQXLr/i2uDaqSXVIfJ6RfDnJqDlA==
|
||||
J1UGlXkKhKXD36OrXXhN8J2xIJzaLSbkMLWZBVYhIzKIhtDAsZ6oAssWKRx5BzNP
|
||||
VmVrGQo2zRokW/ZuO9bN6/vHEEiMOBtCIlg1b8xVuig=
|
||||
JBX7lPwBHKhyRzgJY9OZ2KI6iis8uoA2jLORIv/XFCtWDyuLfsIYrBQwTzzUuSVO
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
D1uzgsuXIKL/yxNsPwFM0QIV7+TILj/tblfnXjJ0GYQlAG5xlrK2k9RIx8apVXk+fYR83glUbhc3FJlByrwJkQ==
|
||||
vQwaisdUFOt9b0SJYuH/nrHigrTUtycF35lf58xGUQo=
|
||||
VmVrGQo2zRokW/ZuO9bN6xHuLV+pwxqKLEVIaJlVY1mV5wixDkrlkeQ/46GnHjPJ
|
||||
VmVrGQo2zRokW/ZuO9bN69ftsX0HT5bqVOOMRQ1dnH6J2cD5LXLKGBEYYVmwvLbOnW/+ho3f4pS5gGHbjP7S6A==
|
||||
M0ZySqkmhuHCw6olbCKv9zQJzSQJo4Zslq06bXS41SQ=
|
||||
VmVrGQo2zRokW/ZuO9bN67XKiXTToYD4Xj8EJf9tU1/Vu+G41TBzTVvAU2KLSeCv
|
||||
VmVrGQo2zRokW/ZuO9bN6zM/X2hHBCd+n2OGnnATmrTLBRO8Ka4sxejzogHbwTSQCRjmbMCS45yRDKakJA+6lygvtX8/AEkLox/HgNQ0WReKAZvStGcdGPMqn6vgZv5Gu5msyaDAcqtS9MyGyGb9+g==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
oCwMuj/95ZXy+xntYImc0fRuDbZyEvkaVbFAkuMpm9yWIfTaDuSAdU/L7ROHPmO1
|
||||
96orka/uERLyRst14azQwhCOqhTfcgFhXNAQS0hmuOGZIAyEpuVq0D9UpB4o0dY00eifTWefY3mmHrggp7bGLkFRUvNVINpyXDZbESEgd4Pe4G8AvpwDNkWSLrOyNGKY
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
O2CqINTuIULxX7Gu5GskT/Nm15YFovaVXDj8ylNfQi3d2Qbp7uZYhyvrRE1b06DK
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
t987AUZxQR72IPRcAqvQ/tuxrpVopv9MhEHHX4HHOFnF6WZD8PVxYK60YbaBpzoa
|
||||
c1XU6vxl7MsQKGo3r4amMsSWef3BumXlCWI6QCsp6pMACoHb/XNQfx2cpKV7J/MH
|
||||
c1XU6vxl7MsQKGo3r4amMpPnl/Q0nxs4Ul/v+JmLHipRvS1iO3+JhmWzafMyTI0p
|
||||
c1XU6vxl7MsQKGo3r4amMgGxGyqG90Nz+St+6838nV5Hy3ZAmDi9Ecxx2gyS4yZO
|
||||
akHibliG6j9uvBEg96vResIm2pvfeBRQxNU2J0BQeUc=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
YdUmdqAC07VhbSt1h6KCDASPIXTwTSkv8cm4ToJ+lpo=
|
||||
BIa0ibHnqUboaK9kYHYO4um2nnLtPSMsHb7nUhh0kKQ6CdlvwTSeB4h8LEiuwG9t
|
||||
XKWK9LfYDT5w2LEWWxwkc6l2k+0eByijzzjX3gaj5k8=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
wgR07xfoapmx6eEnFHXXYmnjxw2aWD9jyym26bSe8wdUky12ZBuFKfAUxS++Pix0
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW/27EoqfC0X59kkH7imoHQb/TQW5074PHVFRKqgD5aSA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
IZj4TYq2HlScfSdRkI+QP/1JxkOTIR85eefsT8+ZE4aqE0v0U76615IyJqY5UKTuMtUbLm26g8btb6vlq0a/Rg==
|
||||
sV2BMz3qoSZgP7XLsV0u8FnjXWiNqL5EgZ3mkCPlBXRqd4GmOGu47uyTs1R79OxGn8j+RZZ1XwLWsKhwXR/uRAfKx5AH0WN2iitz8d+Ezds=
|
||||
IhuisKim47k91RVt8z8qtAZ7rSCYljkiJH9HzGQ5OPx8FxzBv8dhM3FQlWygMwgCxPuj/L0zzaJH7M9JLtcNyBQAqW+52jDxmeGRDtqtSp8=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
/Bf0c5l+J3LcMje0y2hT6xexfB3PDHGLzFprRXh5sZU=
|
||||
gCKKzKpjyg80fGP7iU1CosQydbZEVmkhqpAlx45K/ms=
|
||||
HI5OOAOTfAAnGE3XBxyr2vdUoaKdz9Yp4Em51oFqNhU=
|
||||
b0AcCU56KvRpMcnxfbDRg2RaKdDnbQt+ar3yTu4ASKKZrazBALhe/1DkqoflPq4v
|
||||
QOiTGJqcvhOfGILFspJCgFitD1klQoY+1I4jtCCP/XI=
|
||||
O3CUgrw2GJfB+mDjH5+NdkjK1xGXzP/MBLULODELp6gwPy9qqsLvy+O0nI8WaT4C
|
||||
VmVrGQo2zRokW/ZuO9bN6/vHEEiMOBtCIlg1b8xVuig=
|
||||
JBX7lPwBHKhyRzgJY9OZ2ID8CtKJxnNl/B8H+N4MrEOtqpoairx3dp0kQkKQXLr/i2uDaqSXVIfJ6RfDnJqDlA==
|
||||
J1UGlXkKhKXD36OrXXhN8JAqE/N8+U09yjtfA8xA8yW9SYS4/U88+D8eMNmNqLL6
|
||||
VmVrGQo2zRokW/ZuO9bN6/vHEEiMOBtCIlg1b8xVuig=
|
||||
JBX7lPwBHKhyRzgJY9OZ2KI6iis8uoA2jLORIv/XFCtWDyuLfsIYrBQwTzzUuSVO
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
D1uzgsuXIKL/yxNsPwFM0QIV7+TILj/tblfnXjJ0GYQlAG5xlrK2k9RIx8apVXk+fYR83glUbhc3FJlByrwJkQ==
|
||||
vQwaisdUFOt9b0SJYuH/nrHigrTUtycF35lf58xGUQo=
|
||||
VmVrGQo2zRokW/ZuO9bN6xHuLV+pwxqKLEVIaJlVY1mV5wixDkrlkeQ/46GnHjPJ
|
||||
VmVrGQo2zRokW/ZuO9bN69ftsX0HT5bqVOOMRQ1dnH6J2cD5LXLKGBEYYVmwvLbOnW/+ho3f4pS5gGHbjP7S6A==
|
||||
M0ZySqkmhuHCw6olbCKv9zQJzSQJo4Zslq06bXS41SQ=
|
||||
VmVrGQo2zRokW/ZuO9bN67XKiXTToYD4Xj8EJf9tU1/Vu+G41TBzTVvAU2KLSeCv
|
||||
VmVrGQo2zRokW/ZuO9bN6zM/X2hHBCd+n2OGnnATmrTLBRO8Ka4sxejzogHbwTSQBD0QaFQ6mH2ykhpeatV5MFSAvHLSQE3mXQCKlo9Vmyj7/c2aTE5OzSuRlIiCt76fbCvV4M9DgyzOc6QS8FnjVg==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
oCwMuj/95ZXy+xntYImc0fRuDbZyEvkaVbFAkuMpm9yWIfTaDuSAdU/L7ROHPmO1
|
||||
96orka/uERLyRst14azQwhCOqhTfcgFhXNAQS0hmuOGZIAyEpuVq0D9UpB4o0dY00eifTWefY3mmHrggp7bGLkFRUvNVINpyXDZbESEgd4Pe4G8AvpwDNkWSLrOyNGKY
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
D5nlraEpeGmKL9lxoq591txjX2tGuFl4D7WJZ/91lnMQ6WZrDXvU2okqtgoaqWSS
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
VcOpbkIFMz59VlIHGus1M+TodC/Ia97E/RilXZKKBR29V7X/RlCXQzuWibEOEJfo
|
||||
c1XU6vxl7MsQKGo3r4amMsSWef3BumXlCWI6QCsp6pMACoHb/XNQfx2cpKV7J/MH
|
||||
c1XU6vxl7MsQKGo3r4amMjvzqCkQbmHuG+orSe7QiThO3NRqf8lDLQklcqf6u2x4yWOeax5QyyroyrE443cDvw==
|
||||
c1XU6vxl7MsQKGo3r4amMlEDkaPg52QqeaL1e16aTiZGdP9MF1i1K/F0icaNF/FRZY8CjFaji8Ecm2WEpXZbMiyduIw57U2lMT6kzLqch3Y=
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
YdUmdqAC07VhbSt1h6KCDASPIXTwTSkv8cm4ToJ+lpo=
|
||||
BIa0ibHnqUboaK9kYHYO4kqIZZgv1yXQHpqfJ4aNJ54bUNUYTYq/0A+dhHby52Au
|
||||
77Mf9+1xBvZiUeNTtU/s60Kyn+UEu/OgKFt23E+wd8BiTmgbWFTzjcyPW/imPN9p
|
||||
wgR07xfoapmx6eEnFHXXYmnjxw2aWD9jyym26bSe8wdUky12ZBuFKfAUxS++Pix0
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW/27EoqfC0X59kkH7imoHQb/TQW5074PHVFRKqgD5aSA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
wgR07xfoapmx6eEnFHXXYmSt8oPS+2lwNla/wCY62SBZ7HAsGrtjJH7dzi+5hXSr
|
||||
NqhMbY8+EQI8zhTG6Zh2I5csQ+/eG6egKX2sKZJStJZk02bOBi20A8UHGNy6sybt
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
IZj4TYq2HlScfSdRkI+QP263Ug7hf7sm5bqxRn1G7j8CZM6KmOHJcbEZNXo2mkEAKAgQMZx8+NhDilcUt2veWwUPocpK+8JugxVoHXyHBSRb28kLWdpmZTTf3StM9Y2XDpZ02OI3BeuyFvxLweVX9w==
|
||||
wgR07xfoapmx6eEnFHXXYm7IOJ/6J1NThWNK2EdPRzYwWPvLP+jlqDp61mwE1mzG
|
||||
NqhMbY8+EQI8zhTG6Zh2I0BiMnuwr8mLUTT6rraGmzoW2r/izQNInq2UmHNhRbv+
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
D1uzgsuXIKL/yxNsPwFM0bn1b8lc4rkM7jKkoTPs67jZgYEdG3TOZllO4+vZp0ZM
|
||||
vQwaisdUFOt9b0SJYuH/nrHigrTUtycF35lf58xGUQo=
|
||||
VmVrGQo2zRokW/ZuO9bN61lflwobhmxel33RwHEAzsw=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN67AsrXUPIcMWmsNJ6skMzcKKCpn1+SzebzO6hgphZ4RaLaD/MDC8FwcBZZJFOSWJmA==
|
||||
VmVrGQo2zRokW/ZuO9bN66NLXvUSFhBjtRrUbZsPQNOrrRiOaX/5u3wb0Rfqy+pv
|
||||
VmVrGQo2zRokW/ZuO9bN6wsF8dCAuyXrReoI3w9Yj8ejyyRZrswtbKGtDKu6ywDGElhkS5s5y7BVqVo+FqDhvA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6wOXhaCTOJSjUCWUfjx+YyYNeSRhAnvmOzc5j0wt6pWe
|
||||
VmVrGQo2zRokW/ZuO9bN61ODJTwuVdYa2e77kV4UyyiKC6xmDTYLpzmUEL6iaKIotT6XRfjdpuPhvefHRzC+7lCYolxcDYktKmTY39wnf+k=
|
||||
VmVrGQo2zRokW/ZuO9bN63p1oaV/8/rZOHP3bxdBsLtxlUb0X9CVsj27gKH7yxkc
|
||||
VmVrGQo2zRokW/ZuO9bN655297gigIv+4Ufy0bubbx7ffTJUoURR64bKe908x4ap
|
||||
VmVrGQo2zRokW/ZuO9bN62cJZxyhxghVn78AgYWoneU=
|
||||
VmVrGQo2zRokW/ZuO9bN63LTkM1jyAeOymc1jas3GbdSOgZt1gFP6QuzR+PijaPfkXI6n5+LDNetR25SN0GXgg==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hkns33MIHJ07fAs3bEPA9prEegTrYMIIXPrzC4jD9xKXsA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6+VE/nQEHJOLSC1DnxvG5TiVhVg6gVuqdGuJQhlv12yWuKoI97jUkrKrXkDjch0nxA==
|
||||
VmVrGQo2zRokW/ZuO9bN66Stm18E9cFphVzr4DVvkp0eMQP2KdIRCCvQSRwvi/ogRLfVX0ez0AMMWvL6BswFfzkKtdTc18Qoh/tgpwV2o+KvhObTvNhFYenGcSOQ2IfJ/VBsqInH+jm5934kDPyo5Q==
|
||||
VmVrGQo2zRokW/ZuO9bN6zsPJOFHzvayEpAPvGiJ0lAWXca0TugmxSi8hINZZvoHQ1Y8EIw5ZU/3qx6IfU7mzw==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HkmgImK713UKKRnRLyQBV8gyjNySqhD1ER71FyIggw6WuTb4tOz+zOmUJvBAa9I7hKop6pGwEoB2371+83RgakZhyjMJWosIoeLReEb5GcqHNA==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HkkrikeB3PyYnRyHWKvzXceKTTsB9Sbgf9uM/v0isHHFakzQxpTSrdsYuODmqyQGE3Q=
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hknz2So+gFu+BijKlvPtsNKCIi0RkX1BFpd3GhHKBMdoB6DedipwufkrnDIRLB493gRtMiXCiHSsTBNmIXqRl2RK
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HkkqG04WXvd0zYTVxLMDUCWknQtobuOLFvBEBrZieoy/MQ==
|
||||
VmVrGQo2zRokW/ZuO9bN61TKHwbNGf/2Ub0vd756U9O0Gtl0vapnf7HpdYx4U2ib
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hkk6a/inNeVFTn9NarE6P/3LG5P9KtqHegfYsmaf6Actxw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6yaURb+J41vJInDMdNBqADJBPzFwU1DWEhzV7Igw3NGvcy7cQ4IWtwYwzl4xxnS4q7aao1GGQ/lpjefMWmVC5io=
|
||||
VmVrGQo2zRokW/ZuO9bN63LTkM1jyAeOymc1jas3GbfaLzRNSm7AkFFrFp+7ESwXtG1lg7SuOb/Fvk+nDWM/LTeUYMfTnzndr1z2COlogy5E3igzgZFBhcAjJ6avABsS
|
||||
VmVrGQo2zRokW/ZuO9bN67FJHoI0w8vvrPd3RbddRrD2Em+ygcQFnOdLaXNs8ffOLcZZMjCFzoLC6LOvXRJel9lRMBQd5MAQelNetUjr7a0=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN65aFRI029wWEhVZc+cvXTRpzda0UlKTw9izNui/xkgdD
|
||||
VmVrGQo2zRokW/ZuO9bN62HWtxZ2I/oCwtyWP0WSTIg=
|
||||
VmVrGQo2zRokW/ZuO9bN6ylpzdD3c1E8cbuPHoSW5RFJzxWCEvXq+6grREYT2q2eRpfKq4CUkXaSg9PBb07Brg==
|
||||
VmVrGQo2zRokW/ZuO9bN65qgzI0QqVLALq/Lz0RhHgVj4W6v2iAhy3bpNtZbOHJ8qR+FfOTDkpmrnn3Bg7loWg==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HknNd/k4iuNp2bbqaDmaAfko6jVO83Qfz+7nZDbM61ZOu8HuZ+ZNu6hMvpayaQR5SAc=
|
||||
VmVrGQo2zRokW/ZuO9bN61TKHwbNGf/2Ub0vd756U9O0Gtl0vapnf7HpdYx4U2ib
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HknNd/k4iuNp2bbqaDmaAfkosj3Q/Uyc4ih1OKYxi2Aoat/XPMKk6ZFw9dS97mdyNCW7sbOTUzQ7vKis/hh/FWBl
|
||||
VmVrGQo2zRokW/ZuO9bN6zTwEIRXNDisRd1QRhA8x1E=
|
||||
VmVrGQo2zRokW/ZuO9bN6/6TnYYUnVY4bZC18wJU6T0=
|
||||
VmVrGQo2zRokW/ZuO9bN67XKiXTToYD4Xj8EJf9tU1/Vu+G41TBzTVvAU2KLSeCv
|
||||
M0ZySqkmhuHCw6olbCKv9zQJzSQJo4Zslq06bXS41SQ=
|
||||
VmVrGQo2zRokW/ZuO9bN6zM/X2hHBCd+n2OGnnATmrTcB3+DRCAF+pezmRjCID0udaZbU9+Bp25aQzLB8QDwQjJOciYA4ZMGenxD3oVSnPjhf/xssdSo8p33UNNP+7LnwEXEbYt+fXn2F5oiKjC6Gw==
|
||||
96orka/uERLyRst14azQwhCOqhTfcgFhXNAQS0hmuOF2h+KCvqR3zTaYTe9GwY3cxsP+/BBmVOckz/EpSQTZmvBKIrz2PIwNuNhzK8OCOI4=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
nfBQrFU5Tl0d1VcHhIJkAP9Tx9PwP8cRBjb6FOkkDsaLG6R4uDQDi4xcdtmOXEqB
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
NNh1PlSD8WUnUEbz+BU/P3euInP55YyecjBWhnEnlB7Lw5dMNDV3iHSK0kwD9rha
|
||||
yqM179SzW9HnBHozkU+IlV+BVKi+rIq6p9thxVddK2wK0J7yGt1J4fq2cywdhxRL
|
||||
akHibliG6j9uvBEg96vRemf0tAA5Rm6aB+lqKw8WFi0=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
IZj4TYq2HlScfSdRkI+QP263Ug7hf7sm5bqxRn1G7j8CZM6KmOHJcbEZNXo2mkEA3MxUp7pEuHhp8IfRMvwD6SZPogdTtHhT5unY8iIrUiU6GaMq6uosuXq8hjxV9nUgwa2iqC1n6Ziz6tiDdPy1mw==
|
||||
D1uzgsuXIKL/yxNsPwFM0bn1b8lc4rkM7jKkoTPs67jZgYEdG3TOZllO4+vZp0ZM
|
||||
vQwaisdUFOt9b0SJYuH/nrHigrTUtycF35lf58xGUQo=
|
||||
VmVrGQo2zRokW/ZuO9bN6+8scbwlFXmHwUL6N0BWPj5rk9N0kB/j2zz5GqVVZxsc
|
||||
M0ZySqkmhuHCw6olbCKv9xWw7HeiAhxWgwzOj+uORvYUGO2Wun1zPlqkYizDiyWM
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
00qsNOHBbp9Q+MTSOB/jV1gEYraNSaFlJL1NYP7mKBg=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
mObL0pW76xtWwwYeubgb11DPfOo/O10pxYUkfDIVCjm8OCRNT0T/bbX1vgDt/X1W
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
H7d2MP+WgR9k+129/mRN7ij0WzXIk6KGh6j7E1fgHISsYBh1T2OGWCH8QUwPOkcn
|
||||
c1XU6vxl7MsQKGo3r4amMvdbawOnt/oBPSHXSrswDVS5Xue1Y7sB0F2vPYt641B/
|
||||
c1XU6vxl7MsQKGo3r4amMpPnl/Q0nxs4Ul/v+JmLHipRvS1iO3+JhmWzafMyTI0p
|
||||
c1XU6vxl7MsQKGo3r4amMqf9zivp0Qb6thhCnxaiYdHXwUNLWpYP828px7Gieygp
|
||||
akHibliG6j9uvBEg96vResIm2pvfeBRQxNU2J0BQeUc=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
YdUmdqAC07VhbSt1h6KCDASPIXTwTSkv8cm4ToJ+lpo=
|
||||
g8q6WqkWsk4SUh3d5nzGDIJanaAux29CDdQxdeG/k+U=
|
||||
Vyh8kMpaq2Q+odra9mDJ3Acz3kaMgWRroPCWRIzYRMY=
|
||||
wgR07xfoapmx6eEnFHXXYmnjxw2aWD9jyym26bSe8wdUky12ZBuFKfAUxS++Pix0
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW/27EoqfC0X59kkH7imoHQb/TQW5074PHVFRKqgD5aSA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
IZj4TYq2HlScfSdRkI+QP/1JxkOTIR85eefsT8+ZE4aqE0v0U76615IyJqY5UKTuMtUbLm26g8btb6vlq0a/Rg==
|
||||
sV2BMz3qoSZgP7XLsV0u8FnjXWiNqL5EgZ3mkCPlBXRqd4GmOGu47uyTs1R79OxGn8j+RZZ1XwLWsKhwXR/uRAfKx5AH0WN2iitz8d+Ezds=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
OKNarVhdXTeaHF7smpo1Fsg5Z6GS4ctUP7SwO9m7ADsrK59qTlLvB8EsnHNRomb5
|
||||
HI5OOAOTfAAnGE3XBxyr2vdUoaKdz9Yp4Em51oFqNhU=
|
||||
mZ9rrP32sP7RJKYMPGILD+78ba2l0mR6sa16eW97WcI=
|
||||
O3CUgrw2GJfB+mDjH5+NdlB3aQOXnKkk0z1WAt9Jmo/evqziM8DhkT0YrYGb4COh
|
||||
VmVrGQo2zRokW/ZuO9bN67lx9HSk8eNN2hBCO4HpKRk=
|
||||
VmVrGQo2zRokW/ZuO9bN69ZjyuXvRyGNy9kZJ0BSUPrXcl5zPRPxpUUNlqBFMfTepJuwObNjyv5s1Bwxw+0zHA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6yiPlSW1IkAq8PnO6zy+iP3jJCfd1bhtOH5rekZFEjXi
|
||||
VmVrGQo2zRokW/ZuO9bN6yIV96dETdHvOTzc1eoxsu7+haDOTWWWdxKhfAdfjn09
|
||||
VmVrGQo2zRokW/ZuO9bN68wHZtGYQdFVE6PwKTgvaNuRprwNE+dzFP36dxj7lYWb
|
||||
VmVrGQo2zRokW/ZuO9bN60+BaOrNhyGitXORdqvsMmwFtJw9x+0nfzpYbP/xMELoydQeOelN/AlsLE8govEqlMQrfUl1PeNk2rX8fh0ZElrak4Q4jLc+GGiQ0DLMMpnH/1J5GKH49RP7rJbs5dxgJ4tOonH1clyp6d9GTs2dKrA=
|
||||
VmVrGQo2zRokW/ZuO9bN60jWe2OHiR8czCXypGRfxf3KT4lPFL0wUA7wcV6fbrUq
|
||||
sobCGpmMf4/g7+HpPqBjC6hatZ6rUY3AAzqC73FJ58Q=
|
||||
VmVrGQo2zRokW/ZuO9bN62YWnBw/cibruWabHzPuqaAcn7VyIMN4YMuZ3S9CW09ENvrO91BA4ldYfyyQpiR6Cy5R4Fei8M2XzZTUjvQbS6iXg3tLmWav6AtitMV2FQP4
|
||||
VmVrGQo2zRokW/ZuO9bN608vqClPKbLpxLXcA30riX215gq1D0BrebU6pLhAhTm2
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
/Bf0c5l+J3LcMje0y2hT6xexfB3PDHGLzFprRXh5sZU=
|
||||
gCKKzKpjyg80fGP7iU1CosQydbZEVmkhqpAlx45K/ms=
|
||||
b0AcCU56KvRpMcnxfbDRg2RaKdDnbQt+ar3yTu4ASKKZrazBALhe/1DkqoflPq4v
|
||||
QOiTGJqcvhOfGILFspJCgFitD1klQoY+1I4jtCCP/XI=
|
||||
O3CUgrw2GJfB+mDjH5+NdkjK1xGXzP/MBLULODELp6gwPy9qqsLvy+O0nI8WaT4C
|
||||
VmVrGQo2zRokW/ZuO9bN6/vHEEiMOBtCIlg1b8xVuig=
|
||||
JBX7lPwBHKhyRzgJY9OZ2ID8CtKJxnNl/B8H+N4MrEOtqpoairx3dp0kQkKQXLr/i2uDaqSXVIfJ6RfDnJqDlA==
|
||||
J1UGlXkKhKXD36OrXXhN8JAqE/N8+U09yjtfA8xA8yW9SYS4/U88+D8eMNmNqLL6
|
||||
VmVrGQo2zRokW/ZuO9bN6/vHEEiMOBtCIlg1b8xVuig=
|
||||
JBX7lPwBHKhyRzgJY9OZ2KI6iis8uoA2jLORIv/XFCtWDyuLfsIYrBQwTzzUuSVO
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
D1uzgsuXIKL/yxNsPwFM0QIV7+TILj/tblfnXjJ0GYQlAG5xlrK2k9RIx8apVXk+fYR83glUbhc3FJlByrwJkQ==
|
||||
vQwaisdUFOt9b0SJYuH/nrHigrTUtycF35lf58xGUQo=
|
||||
VmVrGQo2zRokW/ZuO9bN6xHuLV+pwxqKLEVIaJlVY1mV5wixDkrlkeQ/46GnHjPJ
|
||||
VmVrGQo2zRokW/ZuO9bN69ftsX0HT5bqVOOMRQ1dnH6J2cD5LXLKGBEYYVmwvLbOnW/+ho3f4pS5gGHbjP7S6A==
|
||||
M0ZySqkmhuHCw6olbCKv9zQJzSQJo4Zslq06bXS41SQ=
|
||||
VmVrGQo2zRokW/ZuO9bN67XKiXTToYD4Xj8EJf9tU1/Vu+G41TBzTVvAU2KLSeCv
|
||||
VmVrGQo2zRokW/ZuO9bN6zM/X2hHBCd+n2OGnnATmrTLBRO8Ka4sxejzogHbwTSQIMBV8oz+JZw1lVuk9zsKubda9eiR1++L545YBfEjatGypdQPztU2DAF6OXEg3W2a3ltwtcgo9+IKhfYuqJESBw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
oCwMuj/95ZXy+xntYImc0fRuDbZyEvkaVbFAkuMpm9yWIfTaDuSAdU/L7ROHPmO1
|
||||
96orka/uERLyRst14azQwhCOqhTfcgFhXNAQS0hmuOGZIAyEpuVq0D9UpB4o0dY00eifTWefY3mmHrggp7bGLkFRUvNVINpyXDZbESEgd4Pe4G8AvpwDNkWSLrOyNGKY
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmA0y/dvI19s9e1BRFCkk/QzH4UG1JBu620e7CQwjbQOOUvlgFJz4yLxls8aSEEo
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
NNh1PlSD8WUnUEbz+BU/P+yZLrQY+X/LEpSBMw7xwfahIuTImHO5EcUQN9HQmgqX
|
||||
LikBEoRjt8wwWzUZNw+jJqDVmHo0aqmO8fx4adbRXm90KhRgBH5ZfsJyfEAx+4JR
|
||||
akHibliG6j9uvBEg96vRei563dWr9knc+JrDspjHc/A=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
BIa0ibHnqUboaK9kYHYO4k/Xks2d0kb8EqwPCudb2sE=
|
||||
b4OJVZe8QyIpjuTpKXDL9A==
|
||||
PRG/YRzXVD8iVR3bzEcUnu1TFK0huFhoat7c0/vfEZdQ5ejFvZhOUgdVFA1LA3t54/DjYCmHvkQ18q4IM7keqQ==
|
||||
usrsES3VVkgHW6tBbEkpHTeLztsByVaJibbFv8kSFIM=
|
||||
6XDh38s4HWrzA9ChHtrpYV0DWWNc3chcp0di+Spm+pg=
|
||||
PRG/YRzXVD8iVR3bzEcUnpfl+XcdHX8i0iNThoY4QPk=
|
||||
5wsVwKLrIjIWqeTNpSVp9SZAE79lgehXxNsrtfaN8Wk=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
|
||||
+289
-289
@@ -1,289 +1,289 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: cjxin <cjxin@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#
|
||||
#------------------------------
|
||||
import os,sys,re
|
||||
from filesModel.base import filesBase
|
||||
import public,files,json,time
|
||||
|
||||
from BTPanel import cache
|
||||
|
||||
class main(filesBase):
|
||||
|
||||
|
||||
__objs = ['bos']
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
def get_logs_info(self,get):
|
||||
"""
|
||||
@查看日志
|
||||
@param get
|
||||
limit:每页显示条数
|
||||
file:日志文件
|
||||
"""
|
||||
p = 1
|
||||
limit = 200
|
||||
search = None
|
||||
file = get.file
|
||||
if 'limit' in get: limit = int(get.limit)
|
||||
if 'p' in get: limit = int(get.p)
|
||||
if 'search' in get: search = get.search
|
||||
|
||||
if not os.path.exists(file):
|
||||
return public.returnMsg(False,'Please specify file!')
|
||||
|
||||
res = {}
|
||||
res['status'] = True
|
||||
res['data'] = self.GetNumLines(file,limit,p,search)
|
||||
|
||||
res['md5'] = public.md5(res['data'])
|
||||
res['limit'] = limit
|
||||
|
||||
if not cache.get(file+'_logs_info'):
|
||||
public.set_module_logs('files_get_logs_info','get_logs_info')
|
||||
cache.set(file+'_logs_info','1',86400)
|
||||
return res
|
||||
|
||||
|
||||
def set_log_split(self,get):
|
||||
"""
|
||||
@name 文件切割
|
||||
@param filename 文件路径
|
||||
@param stype 切割类型 day:按天切割 size:按大小切割
|
||||
@param size 切割大小(stype=size必传)
|
||||
"""
|
||||
filename = get.filename
|
||||
stype = get.stype
|
||||
limit = int(get.limit)
|
||||
if not stype in ['day','size']:
|
||||
return public.returnMsg(False,'Cut type passing error.')
|
||||
|
||||
if not os.path.exists(filename):
|
||||
return public.returnMsg(False,'FILE_NOT_EXISTS')
|
||||
|
||||
if limit < 3:
|
||||
return public.returnMsg(False,'The number of reserved copies cannot be less than 3.')
|
||||
|
||||
data = {'type':stype,'limit':limit,'addtime':int(time.time())}
|
||||
if stype == 'size':
|
||||
size = int(get.size)
|
||||
if size < 1024:
|
||||
return public.returnMsg(False,'Cut size cannot be empty.')
|
||||
data['size'] = size
|
||||
|
||||
public.set_split_logs(filename,1,data)
|
||||
|
||||
return public.returnMsg(True,'successfully set.')
|
||||
|
||||
|
||||
def get_log_split(self,get):
|
||||
"""
|
||||
@name 获取文件切割信息
|
||||
@param filename 文件路径
|
||||
"""
|
||||
data = {}
|
||||
sfile = '{}/data/cutting_log.json'.format(public.get_panel_path())
|
||||
if os.path.exists(sfile):
|
||||
try:
|
||||
data = json.loads(public.readFile(sfile))
|
||||
except:pass
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_file_ext(self,filename):
|
||||
"""
|
||||
@name 获取文件扩展名
|
||||
@param filename
|
||||
"""
|
||||
ss_exts = ['.tar.gz','.tar.bz2','.tar.bz']
|
||||
for s in ss_exts:
|
||||
e_len = len(s)
|
||||
f_len = len(filename)
|
||||
if f_len < e_len: continue
|
||||
if filename[-e_len:] == s:
|
||||
return filename[:-e_len] ,s
|
||||
if filename.find('.') == -1: return filename,''
|
||||
return os.path.splitext(filename)
|
||||
|
||||
def copy_file_to(self, get):
|
||||
"""
|
||||
@name 创建文件副本
|
||||
@param get
|
||||
@return
|
||||
"""
|
||||
|
||||
sfile = get.sfile
|
||||
if not os.path.exists(sfile):
|
||||
return public.returnMsg(False, 'FILE_NOT_EXISTS')
|
||||
|
||||
spath,ext = sfile,''
|
||||
if os.path.isfile(get.sfile):
|
||||
spath,ext = self.get_file_ext(sfile)
|
||||
|
||||
# public.print_log(spath)
|
||||
for x in range(1,1000):
|
||||
dfile = '{} - copy ({}){}'.format(spath,x,ext)
|
||||
if not os.path.exists(dfile):
|
||||
break
|
||||
|
||||
get.dfile = dfile
|
||||
f_obj = files.files()
|
||||
if os.path.isdir(get.sfile):
|
||||
public.WriteLog("File manager","Create copy of the directory [{}]".format(sfile))
|
||||
return f_obj.CopyDir(get)
|
||||
|
||||
import shutil
|
||||
try:
|
||||
shutil.copyfile(get.sfile, get.dfile)
|
||||
public.WriteLog('TYPE_FILE', 'FILE_COPY_SUCCESS',
|
||||
(get.sfile, get.dfile))
|
||||
try:
|
||||
stat = os.stat(get.sfile)
|
||||
os.chmod(get.dfile,stat.st_mode)
|
||||
os.chown(get.dfile, stat.st_uid, stat.st_gid)
|
||||
except:pass
|
||||
public.WriteLog("File manager","Create copy of the file[{}]".format(sfile))
|
||||
return public.returnMsg(True, 'FILE_COPY_SUCCESS')
|
||||
except:
|
||||
return public.returnMsg(False, 'FILE_COPY_ERR')
|
||||
|
||||
|
||||
def set_topping_status(self,get):
|
||||
"""
|
||||
@name 设置文件或目录置顶
|
||||
@param get
|
||||
file:文件路径
|
||||
type:置顶类型
|
||||
"""
|
||||
sfile = get.sfile
|
||||
status = int(get.status)
|
||||
if not os.path.exists(sfile):
|
||||
import html
|
||||
sfile = html.unescape(sfile)
|
||||
if not os.path.exists(sfile):
|
||||
return public.returnMsg(False, 'File or directory does not exist.')
|
||||
|
||||
|
||||
data = {}
|
||||
conf_file = '{}/data/toping.json'.format(public.get_panel_path())
|
||||
try :
|
||||
if os.path.exists(conf_file):
|
||||
data = json.loads(public.readFile(conf_file))
|
||||
except:pass
|
||||
|
||||
if sfile in data: del data[sfile]
|
||||
|
||||
if status:
|
||||
data[sfile] = status
|
||||
public.writeFile(conf_file, json.dumps(data))
|
||||
public.set_module_logs('files_set_topping_status','set_topping_status')
|
||||
public.WriteLog("File manager","Modify [{}] top status".format(sfile))
|
||||
return public.returnMsg(True, 'Successful set.')
|
||||
|
||||
|
||||
def GetNumLines(self,path, num, p=1,search = None):
|
||||
"""
|
||||
@name 取文件指定尾行数
|
||||
@param path 文件路径
|
||||
@param num 取尾行数
|
||||
@param p 当前页
|
||||
@param search 搜索关键字
|
||||
@return list
|
||||
"""
|
||||
pyVersion = sys.version_info[0]
|
||||
max_len = 1024 * 128
|
||||
try:
|
||||
from html import escape
|
||||
if not os.path.exists(path): return ""
|
||||
start_line = (p - 1) * num
|
||||
count = start_line + num
|
||||
fp = open(path, 'rb')
|
||||
|
||||
buf = ""
|
||||
fp.seek(-1, 2)
|
||||
if fp.read(1) == "\n": fp.seek(-1, 2)
|
||||
data = []
|
||||
total_len = 0
|
||||
b = True
|
||||
n = 0
|
||||
|
||||
for i in range(count):
|
||||
while True:
|
||||
newline_pos = str.rfind(str(buf), "\n")
|
||||
|
||||
pos = fp.tell()
|
||||
if newline_pos != -1:
|
||||
if n >= start_line:
|
||||
line = buf[newline_pos + 1:]
|
||||
|
||||
is_res = True
|
||||
if search:
|
||||
is_res = False
|
||||
if line.find(search) >= 0 or re.search(search,line):
|
||||
is_res = True
|
||||
|
||||
if is_res:
|
||||
line_len = len(line)
|
||||
total_len += line_len
|
||||
sp_len = total_len - max_len
|
||||
if sp_len > 0:
|
||||
line = line[sp_len:]
|
||||
try:
|
||||
data.insert(0, escape(line))
|
||||
except:
|
||||
pass
|
||||
buf = buf[:newline_pos]
|
||||
n += 1
|
||||
break
|
||||
else:
|
||||
if pos == 0:
|
||||
b = False
|
||||
break
|
||||
to_read = min(4096, pos)
|
||||
fp.seek(-to_read, 1)
|
||||
t_buf = fp.read(to_read)
|
||||
if pyVersion == 3:
|
||||
try:
|
||||
if type(t_buf) == bytes: t_buf = t_buf.decode('utf-8',errors='ignore')
|
||||
except:
|
||||
try:
|
||||
if type(t_buf) == bytes: t_buf = t_buf.decode('gbk',errors='ignore')
|
||||
except:
|
||||
t_buf = str(t_buf)
|
||||
buf = t_buf + buf
|
||||
fp.seek(-to_read, 1)
|
||||
if pos - to_read == 0:
|
||||
buf = "\n" + buf
|
||||
if total_len >= max_len: break
|
||||
if not b: break
|
||||
fp.close()
|
||||
result = "\n".join(data)
|
||||
|
||||
if not result: raise Exception('null')
|
||||
except:
|
||||
result = ''
|
||||
if len(result) > max_len:
|
||||
result = result[-max_len:]
|
||||
|
||||
try:
|
||||
try:
|
||||
result = json.dumps(result)
|
||||
return json.loads(result).strip()
|
||||
except:
|
||||
if pyVersion == 2:
|
||||
result = result.decode('utf8', errors='ignore')
|
||||
else:
|
||||
result = result.encode('utf-8', errors='ignore').decode("utf-8", errors="ignore")
|
||||
return result.strip()
|
||||
except:
|
||||
return ""
|
||||
QRASP55VO/1DQ98p1csw9A==
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
dBZyCsfrbwqvA0sbdGrIGg==
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
n+0ptngHIPIjFuMNQ53bfj+Na/fdhk6k1yTpAwW7j353Dw920mEqQQZjykAHeRmp0ZD/P3ftGifsmPOMf2b7XdEqyZH0yl9kjaUugj3dYPI=
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
jh3cxzkA2htccqfZRKAUdI8r17q57nOGP4OxbJlL1NAnrF4weHnS0MpT6C6jbrX5
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
Hf+bBTgRv9pVfall8ODpvg==
|
||||
I8MGJUwtjfcKc5w4E0SmjHwLsErBQ84ek459TV1n0Iir/P4mdpfwDI34s6+8CBN0
|
||||
K3QJU/hV27C5FAVoZ+avNNMfDMygeonfI5TFnvUHjhU=
|
||||
X9BNoFOwiQAnMPqEk6FnbzU/oA+chL/aEAzGH80mBrNNxRMBdiGPqgDUeLF6rer2
|
||||
9ewEGhR02rX1CYy9TbJShdc5zOrGhv/95JJVBawwTJI=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
QtywOSt2jU7XEVQfd46hXhlGuDAcY6mFXPkzqinx4hA=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
CjJS7KrzKM18mlLqJK9jKTB717Vvrubu5ix9tb047ao=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
P0xFZRxBgzs6EB2PV1P1Ga8KWkeEOjCa2HwBgtCLnkI=
|
||||
9GxZpCRwMRDPejWR2Vvf+LKn0tNtFKp8Eh2tnr4Da9U=
|
||||
6c3cWGGlsEf4q4E+EjPFyg==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
/tIKPI7pxbgiB5DGE+JcX8inA0z7UW6nw0fpA/nuJtJ30NtW1IQQsUdAjwgJ+5zC
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
0fJLHIpaUEUEURheAjqV+C5PbuPsfeNtAPgfcFiqP5w=
|
||||
ho/Q+jrWDtBeg9J9ZTnKi3+/Efbvadpf+qoH75NuGwk=
|
||||
zxNKIz/Dwj9Harw3dUNEQJhfwzP9e0g+QEHF20IF9QloJJn499jB5lN74CMN7xKF
|
||||
PRG/YRzXVD8iVR3bzEcUnoM4TQf6qaKLuCt8gJ8NfkQ=
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
y+v+I4rQ8oQ+Y894tAwqPQ==
|
||||
p6i8iK7HDbvmLpoFrhNyv2ns9UjKsYvBLT40sf6Ap28=
|
||||
Nxw10FAZUk+m0nadC1hdyy162NCelWBcYGf8TIFoMWw=
|
||||
gw7rFE+f9bVF+DtSprQxBWIvcXcHzAaIYdK9TCMnZFs=
|
||||
VIHA31zdnuwVlvUv3VOlYVRNGNAMqDxg7g3P55Yig7XGJ0frgqBbhflLu9pZDsGtG7PWJFzYnbAhv0HasJD0eg==
|
||||
mcQwVxjUw79rwGN6NopbQ6kcPmfht+aHpy4N4vzTb9DbhhPn/FiUW/rz0u7pkKGy
|
||||
X/Lp4PsbbXulceSXUvGUpDfqLabbqgG4MZE+Cdy4FwlQTZqFS7MLKRTLDMwaDvILIRxQybc5sD1eU9BOwIwsyw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
wgR07xfoapmx6eEnFHXXYsXheOqb+ac7ivrKomECGJjwdSnpWE4PzbAMHxIUoYAb
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmUZFcA4o3wUnGm4YjdorXMeGmKOMmT0MYEr6v6Dtj7fXTQgHn4plKdmzjTMeVlEm5A=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
QeR/vJltSrUa36sdgLk/IfL4q9jp7Kh5fPIA7nHg0hc=
|
||||
qkpuPeWx54kZb1C5WIa62tKtrwMAUE7xRV1hPFjc0nk=
|
||||
NUDHKeYglPKQjXCsTjqHkDpPG4Ff4llamNWSKelBxqKmBtoeDOPkBptxNl9ae6xEQqyUrJT9AnSRTpSh7aXAbg==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
ezgwiw1QpepwAFNSsnvQoOJN6u8DqbLWz8qgHsO6aqB6RHHe5HToLp0+UqRpP8fb
|
||||
z+VhFG0r6WY/HBghnJVPENgMUP6uURPQG10QAuXe9q8=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
o3kxTO4RwuXO7GZ9wpXG+Wq35U1WRWDZvf7dXlWNmacOOTCJLfQ4KEfT1r5nSH7h
|
||||
xWoGNWjKGPfI4gq8aHoTfEof00xZubKgl7GPVFGSDVd7TSf0tyOZVdADGcIojOkDe5MWF/mzQs4D73pMqY5dZvgzuA9ObZjdKCQqlGE/ZFc=
|
||||
7jSw4GB3eBRbmC1MzdtYH2nxYtjMgz8klBoQVhVoidWwT8r1LlO9NvZUaeVEEEdTW81nQdiNwJibED1dKYQBkw==
|
||||
ruTTNFTdswRs4Mc+srnRkxKrfMU4HqZxGxt1RxHe024=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
0J28z5Afxj/RLIBl6j3pAgNq/oTIsu+AgqPjVKJEPvv9NLcDpzlB17tpU0lSBAVA
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
HoOSkwUjMH/v4OzYfSLZHLuEmVzOc0Jcac6Q7EBdZLI=
|
||||
wOl7lRII4ZgqRTj9M//0b0Hmiipql0KqOySDsulvH0Su8cx+3vVrHwSELz95Nt4O
|
||||
yqM179SzW9HnBHozkU+IlZmT/v3wYMBi43GV3/6zTQaofEdG+x7npWVs++h4r59tCne/rOxDxzdL+ulBEDhdXzPWQJHGam+A14zKSyFK8tY=
|
||||
yqM179SzW9HnBHozkU+IlSh6plWR6D4Za/srbzCBndvZ2MLXINNMDiNewLwvNACvbuwcvh5NzzpKTCtz6o++Uw==
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
BIa0ibHnqUboaK9kYHYO4tix8ZPIpY4+eXNZQL6TNBEr37K1gp2hFIgZaVuDpKry
|
||||
wUvHMMqfJEAtxgmf7WcojEsJZ/q+trcw4QZczEaX1wc=
|
||||
p6i8iK7HDbvmLpoFrhNyv+jCXQ+9uuqm20drf0JQzoo=
|
||||
uTEK8Ng11d3ix2pA+DD/aUSvw2QhKfq2muw9OeWLUPkFXMoY8H1+WYM2ZgNetwFM
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmVoIIr4UQdxImXSR4+nP5rPMN4durEeX4gdmJz+ASa5AAk5l7XFK6IcVVpMUMCMJmI=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
wgR07xfoapmx6eEnFHXXYsXheOqb+ac7ivrKomECGJh6sAOIfkvF5oIqf+7bT65s
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW/27EoqfC0X59kkH7imoHQb/TQW5074PHVFRKqgD5aSA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
ksF2R1E+pQ3tpguSadwptSjHYbVoil2NE4uVOms8YOU=
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmWjtdfz4jUHOisd7iLe9SzEDuNihpqofFUHBGmLmre0CFX801z657OYko3yu9pDZ2cMrn7XCoaQHi8TBS6BfnnXRgmoO+AsowNhXyROWGVmDQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
JbnXIK/axHVmA2plDNFCpMWEt1OR4iOGZbYxwMVSGXaSRClwJ7H8/1TEbkxkYcSscQPjgl6VzrZ1rA8bbkzLPGLtGrShGu4zlnLbt+BiXXQ=
|
||||
j9BWZnPkz9pNgv1SXK/8DQ0oIRVkw0dZu+9bbZ9Z2fk=
|
||||
N5/4MVITy7EOJTlZiwcB9agKfbGr368xpyc0rhumQZEuHxhitKliD0GwkptReLUf
|
||||
J1UGlXkKhKXD36OrXXhN8NU53NrHG2SKWIiwAUeD9JY=
|
||||
VmVrGQo2zRokW/ZuO9bN6zM/X2hHBCd+n2OGnnATmrQorUkV/0Z4czhLJwFbLtQgDiot4dt7MCR+IyRl/JXPGwvD97k+zv3alg0zn9SqxNU=
|
||||
NhnIR3Ilo4H2su9/cTNo/Nhao8jRz1mpKHWzTHDhdaWoB5q4jnCTxvFKzgSknYQc
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
Ic1WBp01nLyRxbqJnsu2p0K5AVX4XdWNyelWOIV6Ri/Zcn0aKD/Dw9aXBHAKiMi1
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
96orka/uERLyRst14azQwhCOqhTfcgFhXNAQS0hmuOEns7mun1htPlaJ9Dut7srZPs8zLx2mnV8J2BNAbKqHDQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
WjK+gflGKYbL+4lozgCawEUyGCXGDdulnbl2dYZOPGVzG5m1Glq7FFUvGH6sdkQl
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
NNh1PlSD8WUnUEbz+BU/P4RgpdUyasZdSn+oHMc2tG5Ug0ojdlQR9cuRD1kYLMhs
|
||||
wOl7lRII4ZgqRTj9M//0b0Hmiipql0KqOySDsulvH0Su8cx+3vVrHwSELz95Nt4O
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
JbnXIK/axHVmA2plDNFCpPYlXWvPB/7lIz9ynMkifTY=
|
||||
YdUmdqAC07VhbSt1h6KCDOQhlWQ9jG4k+MaSOV9j4FHOiSK3ETa4U5I3fxOq7tLF/PYmB1e7iFQcBIVDEiWJ0hG8ZfezZD+o0fXjWq7Tix8=
|
||||
WHkOzVx7seuLmxs5Hu+l/sD6YH+8F+kQZFoPxa6Xx38LU1lUEpTxHz0FS+pwLXBn
|
||||
vQwaisdUFOt9b0SJYuH/nrHigrTUtycF35lf58xGUQo=
|
||||
VmVrGQo2zRokW/ZuO9bN63t2MnnwkYHotYsrWH9vRICglWvh1CtLK/YdWGbWd1o9f1tzSxswHQJ7jeusy4I/wA==
|
||||
M0ZySqkmhuHCw6olbCKv992x+E1VMoPx+GJL+VjXXxc=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
+plE/1bhdo64kO07cLlUXzzWH25pNAS0eDxp8hnHILg=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
J24jXQQti6wQv5pCoF2ZrcZEDr9DJDb9XjoXgIX///kKtoJQ30XXawDWakYG93Yo
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
NNh1PlSD8WUnUEbz+BU/Px0qyBBTm/Di4HeEkA6LeK0wkzA9oyOBq1r4iQdNVJFx
|
||||
wOl7lRII4ZgqRTj9M//0b258VwcrBXb9+d6gAS2zZVE=
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
YPfxe0G+MGXmXAi6U4BEkvyb2XevHxdc8FMThKGhtzEMysaWtPfSjbuwkZA3pYeOFKhCSFYG+dkVrsVae0IfFA==
|
||||
AJ6YSai03eOKVxBS+s+A+4Cy+lk/ZeoSfixZxH7jcBI=
|
||||
h6wp9SZ6w+zAVENITafY7hRljTrwoJCPY0O2fxDuqa0=
|
||||
ieyNFTb+50j7HJWl7nbiRb4GCc6WHw87gawZDTQSQBAN4boyX2ECQxLm67quRnkg
|
||||
gZ7BoIAABc+I8g/rYzq+fxkznXPQP3aR2IC/o8MbAWFRcDH+nxQt+h5tN0pl/k/R
|
||||
gZ7BoIAABc+I8g/rYzq+fxpmPvrlSDpm2/4GV4ZL52N+f3aoouaz0DKjSpxvecRv
|
||||
VmVrGQo2zRokW/ZuO9bN608SN+rl/c82Fx3gEheLtEPWenSoQZ0ErgcGs7SYPEIE
|
||||
fE3zmgbfhO9ZwEda5GgwD2xm2m7B0YFtqnQCEsPic9MwVxNnLGn04EN6FjhytfIHBDJPSIwM3+fK2/ZA7HX2Eg==
|
||||
9uF3R/OfNUGVQlxbTNUS55dJWWqKoFe+2B8l4N6Jc2pEZCkxDuC97C1dDY8PNwf/
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
x22JLf5+9uUTDUdpgwgZ9O83E1bfgaVhykmWdJ+nZXJQ9kCBq7GuTG8v1IJzJD5h
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
dar6N0tUAb9rU8/aX1b3tPPCrmt+A77OlLLc0hq85JPAMBfiIm5+TeqFwN72RdG8
|
||||
ho/Q+jrWDtBeg9J9ZTnKi3+/Efbvadpf+qoH75NuGwk=
|
||||
3AcPLYoMMn4rxWOUMA1wJdOmdYprhThTGxGyDnWq840=
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
YdUmdqAC07VhbSt1h6KCDCoYsQLlWzDGUd9QUR41IHk=
|
||||
wgR07xfoapmx6eEnFHXXYmnjxw2aWD9jyym26bSe8wdUky12ZBuFKfAUxS++Pix0
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW+2pW4n/W6qWQ7fvKEZcw6lORQHv34KyeA811LNUCOgw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
gZq1mJvnqxTNLPjSpQ6bfKeb6fxkOx/+dElrFnEieCM=
|
||||
WHkOzVx7seuLmxs5Hu+l/v5tNYogyNy2bAogm7myZaPcxZDZSm5ntWmgTrqmpiFB
|
||||
JlxIfINDpIN74VOPKABZWw1pDjtDv1WACEXIhyxtaYCMs+iDnrosPIR34X2MwwO9+dspbEyZ5RinZUNx6/2rAA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
NnnRSiFB8Vtr5PXra2GmCcwzujRQX5ogRv1ZA//+TDFXEzK++s5GANm+fB4wZ9b1
|
||||
T6Eqs+Bi2aLwH9GlPE5AbHo5JCADBnfOf3YzkqXbPUf7ww5fPYa7xY2H8XgXCiUfUway+41gmA7KI8VTyYCtUQ==
|
||||
1V2v8QerKOmubvSxgB4eTJhFEA1z5XTTrkAvv9L033YGIXZ5LurDt9cgLUto0D+F
|
||||
VmVrGQo2zRokW/ZuO9bN68iybrt8ScY6aQlDmfS7eSM=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
a/jv9CzWHWz0h350oJLqa5TTL4zXej8PqERC4mSIOhc=
|
||||
e6XLp4vcZ1lGimtmqXOZYQEh7CM4Q/OMFSck6/Q+gT0=
|
||||
WHkOzVx7seuLmxs5Hu+l/vyBEzeQThILDQKrzavtBosY4yeDSrIgmjG8rDYDt7jf
|
||||
xWoGNWjKGPfI4gq8aHoTfLS/lZvfoJjLfC/marPQVLnKMOw4Z2B4PM+0VW7zItzI/6l7PfcB1fpqeh4CVpOVaAVtXUo8+KKsnSCrzxMrCgqvl15+qXkkBzeyMR1jFwGa
|
||||
L0eUthVnpkGsmKFAX6d+uEWqqcpDPrCTTj+Voj6q7co3v+1bz5rI1ebO+u/PYVII
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
yXqkSqtRGSEMRZqQHZ1+mrgtQzra/P1V601MdoqkoAU=
|
||||
b4OJVZe8QyIpjuTpKXDL9A==
|
||||
CUHO82G5MDpSEiqhNImyK/VmwjDkiSuGC7ZIskUb7gD65hKsx8U/XeYWPTotCZKW34T742v7dfkWr7P/TSMaHw==
|
||||
xWoGNWjKGPfI4gq8aHoTfAsoDN3ZmNarxbTXL1u4oucttlV0ayU3aRT17FqHoXJQDIiBBbSbAmeppasRVhu84Q==
|
||||
VmVrGQo2zRokW/ZuO9bN62lH7iQuGMYTOSVMNmHFiRJ/Sw4G+R4bn28hJN4qoweYFOMRMpD0ZDoWuodT/c5B7g==
|
||||
vQwaisdUFOt9b0SJYuH/nrHigrTUtycF35lf58xGUQo=
|
||||
VmVrGQo2zRokW/ZuO9bN6/hmmducS1PDoVjLNYIkh7yyxYJu3Yggs3y3xm90fY6f
|
||||
VmVrGQo2zRokW/ZuO9bN6/+pUnGYHu9kYzSmExtaF9xg/93u33jl028+UV8/J7U0fgjyTfXwYVHPB8cx9YfLBw==
|
||||
VmVrGQo2zRokW/ZuO9bN62pu9LJ9Byu1GJDSPyIAK5YfjdHOvgBbuNyy8GkgPt06Hy9Wawft7wQQemmjSGO9aA==
|
||||
M0ZySqkmhuHCw6olbCKv992x+E1VMoPx+GJL+VjXXxc=
|
||||
xWoGNWjKGPfI4gq8aHoTfLS/lZvfoJjLfC/marPQVLnKMOw4Z2B4PM+0VW7zItzIvXmsV0xjGZqPof0yohbnqV2ZK6WX/JTtF6Rsc2nFkVdqaK9KQFfwsn1rzq0uaEPH
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmXAb0WFcZv4HhfILL3G9ms3qCgcSR8133ZQaREk3oJxSA==
|
||||
mfT8DrNbUmxQ2BnZ1bZFTLh9MEuZKOpmAfF70OnZ9TU=
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW+2pW4n/W6qWQ7fvKEZcw6nnotqX+Ka5wYNWQOIeQDvg==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
y0vAsW15ZVdHlspkX2eEyTnrhgxq9w3tH5fYg0+3IYTw+fzqXDNLLSILTETgFx1f
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
DzneBA92dU5V88ETMYFQ5zTOuyBrABt5a1RgPheterisyI8z8hB6+Xmqaxszc5OF
|
||||
ho/Q+jrWDtBeg9J9ZTnKi3+/Efbvadpf+qoH75NuGwk=
|
||||
PRG/YRzXVD8iVR3bzEcUnsWMvR86r5liyWslQeT39Bs=
|
||||
SadDvAEU7JBQjzqB/CmwTKt23QO8pBBBQpkoyF+cMuk=
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
YdUmdqAC07VhbSt1h6KCDCoYsQLlWzDGUd9QUR41IHk=
|
||||
2qQ1+UjgiO2OZgsc3Luuhjl38aA5wDGtKWrWNIfYtrBlHRw9FCPi00BufKOnIQnC
|
||||
wgR07xfoapmx6eEnFHXXYmnjxw2aWD9jyym26bSe8wdUky12ZBuFKfAUxS++Pix0
|
||||
p9oVsBgcyiBMjDb8CcPOqB5miGjA7k/rR8HoMrfCBh8=
|
||||
HiVf4YuHR4gw4rFUUeRvK5DcsI9Cfqv2qLzm9sb8unefn5AgzArrWdtqSFcj8Px9
|
||||
1V2v8QerKOmubvSxgB4eTJhFEA1z5XTTrkAvv9L033abQzol1FA4tuwFJraDvx2U
|
||||
VmVrGQo2zRokW/ZuO9bN6zM/X2hHBCd+n2OGnnATmrSo1ZAQ1FHnoPT0QBpT+y//yTdMi/PIio5xW01+SMmEPbzHTSWH2AcPKinWHgjPuzZic3mlhIGEMpw0WGyqlHdR
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
JbnXIK/axHVmA2plDNFCpPYlXWvPB/7lIz9ynMkifTY=
|
||||
96gahBYKYgdoVkNtss7VEPgCInqEgx8v+sRhs1WPpZm2HnAMO4XvsEY1xpE0BXSYmvq/MLRD+JYKbipt7HmjYeBg/h3NBuTXdf9BwGtIArY=
|
||||
SY9CIZHY29IN9pslG93gZg==
|
||||
O3CUgrw2GJfB+mDjH5+NdtbkdTJdRhl+51HFBnR6kaH4/6DbnYid4U0U1SHEYx1n
|
||||
VmVrGQo2zRokW/ZuO9bN63t2MnnwkYHotYsrWH9vRICglWvh1CtLK/YdWGbWd1o9uxYVCWxZnh7Y3ENahYaMPQ==
|
||||
usrsES3VVkgHW6tBbEkpHTeLztsByVaJibbFv8kSFIM=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
P8KbMTjfuhARpOL8NoffNq+3uZDJUpCiwqTVP/jFFTbQzIztXfbek7BVBaXkRncL
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
UkQQaGHg2Aow1Gtc9bKBau0euapoYTSumuYNb1Ly8sk=
|
||||
NhnIR3Ilo4H2su9/cTNo/LBal3Bb69aVfp/VrSaJBVopEyKAKnVV8FGgN9p834dg
|
||||
IhuisKim47k91RVt8z8qtJyWLVz+KjhPuZWupljEG6xxx85dlt92sHkP0dH3RDilXI/lJNqFeQKeKpcIDtD+IA==
|
||||
Ic1WBp01nLyRxbqJnsu2pypx+Gb9M9+y4CZIw5enWs8AGlXEXTs+FitgdECPA9/lrzW8srVC0vHK9JhZxKlpY1OTyVkakThiIe7k7Hc/3yZ2FjjNKgggOZKRyD6HAzHN
|
||||
2+RceSNjD2iq0sRzepMysZEtAjuWiKl7QaPq1reOZ3L3mfen1JvnD6MPvKsBpyOKkDYBCw5cZs24QV3TsSDbQcyqIrPAseuaKXpl/OArmSc=
|
||||
96orka/uERLyRst14azQwhCOqhTfcgFhXNAQS0hmuOERocNC1mWlogqCdtng5segh8OjwBnGkbvs4sXKYd75Mw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
kkhBrrZfa9Lz2ARtxqQ9WISHe4SzqYX3OdpNmbR5L/VBHTenO90IETRFsXol/Jpv6kfKAQ8LAS+ijYGG5x08+Q==
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
a1WCYQuoRJeK3mOCGHQIllG8L0Za7F6wo/ffbPvOV8mvOIi5W6Px2rfj6NO9ykAT
|
||||
eeFiPlXUI0Fos82HYztSmZyutxdoUP9KbXnyyGYMqohKcgTCAEZmONzPn/3V/XeU
|
||||
bWa5NLmMcRfP7/pL4TxwVSNHz9M1H68NEGnEXfZWNdlCgk9i6Y3xP89ubu7Qieu3
|
||||
eeFiPlXUI0Fos82HYztSmZz5nVydpyguF0WdL2JyDxQ=
|
||||
yqM179SzW9HnBHozkU+IlRXsPW+yWAUAvWc+nnoZsRTppRoZDJSnb51AHNRYCykW
|
||||
akHibliG6j9uvBEg96vRer/Fg5zTlM8oj8hSAsYq018=
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
UxWVPzm6Eag/KO1azIHUdx+idAdS+rfPARzR88tVbgYdpuz2ULTF+2vmnBiei7OW
|
||||
Lb802TYIO8cTPX7RtIYGZ+/BDmfzYBEomwEqSDkd3VI=
|
||||
b4OJVZe8QyIpjuTpKXDL9A==
|
||||
I5csN8e3J/KIFkMa5t+SJATQ2qGW0wOfRPtcA5bj1z8nKyxnKr/hfHKXbqiTXRny
|
||||
1V2v8QerKOmubvSxgB4eTJhFEA1z5XTTrkAvv9L033ZLNQ2XZF4KsFXQ0AJ186dTqy0tFe9yVaa5Nvi4GzvRQQ==
|
||||
UiubnxD7y7+jD/CLXy/lIzUv+EQIUnxp2+tRaByCudDYzFPn13pFELSDNAgNf0aY
|
||||
wI4EEWzdSnynhqFxMCzFmvtQa54ffiTU8OKIuM+mUtbRQW9n1JFAWLuXCST3voAI
|
||||
GL/yLvMwjflJNfDPl5ASjfzFHnOGqpWC8vWJqX+sGuU7UB9p8iAxBS67EStoox2D
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
P5fFy0VqKNQcixZC6/gotxklJeUYBp6qUkCM0szi5po=
|
||||
3HDkd2BFYLPk4K73U5D+BYdx+YPBx8edbX2mUEZUhcw=
|
||||
gZ7BoIAABc+I8g/rYzq+fw0QRhyOskLowTpBMxzNkkXJfHhElpIZe5wsCdqDFCZvGpC72uDw/Cu+D1FuT4o1ew==
|
||||
NhnIR3Ilo4H2su9/cTNo/AxXtCXBAtO/DWPyG38GkWo=
|
||||
SXXsDW1aLF5ljPyJUoRc7t2uV1Ea/KDPsubfQRA1/g0=
|
||||
i/p1vQ7ugXGBvwbjECApz/Cr9YvVAiEjIabMp4aMpkk=
|
||||
zo+FVrlHkUeZ8fJX4PVhAH4W08MspSsE1ssI18UNPaA=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
wlLHv6kT3Q/RmtMBN4nDAaQcqH83V4KNJSetgkXN2mpJpLhuyLAaUNt+tKkzaLSI
|
||||
VmVrGQo2zRokW/ZuO9bN632VflaKbWaV9Wa8IOB78Qk=
|
||||
VmVrGQo2zRokW/ZuO9bN608eo5JjqlJJ+hYuirBCFcmf4cKrfv149X3GuxINE1xDDJnAj+I17VZiW+JCiwfRwA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN67FMFupuL9NnhZUvLdV1qH1jDx/7tB6qL1SG7Pqfwsin
|
||||
VmVrGQo2zRokW/ZuO9bN65qbK6/I8bncNNV3Fr84lp9CCx8VYIApMdX4h8SHWyk2
|
||||
VmVrGQo2zRokW/ZuO9bN6zEL40rbK+o6j49cNVbzKqOsExNYZ+R8lUnZEGfiuhXY
|
||||
VmVrGQo2zRokW/ZuO9bN6+EP/UfvFvq8hDmkfhk2A+qnnPSHBLYJiyMbFizN9aWEoBeZFZoLhXy50+Ts9Ur1/A==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN62OM8cyvjkpIHunHzlmyApZDgMPN1CpEHj7RB29QdSFu
|
||||
VmVrGQo2zRokW/ZuO9bN6zDu/0cPxO8iIAxo/MyAOyPtJNDgANrLqcOpy3L5oY1k
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HklSomvH/VIQjQOrkHPd2BPf
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HklTf9Kt2VbDsiUekTyaR+Eqep0h0uyOXB1iMKSg430G3P3HOaEPs8YtIeaBmiEO8lwzs03jh8/eQSyBAoQdtToH
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HkkI9vh2RQuknkZgs1Cqb07GeK7Ac8sa2K/nX9m0GTqvYw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN69jzSpHadiEPTz774Uy5h5Nmsum61eVUSkdR5LKSFtye
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HknaeZX5axwNGbFayb5AUV0mdbRkjhMqcaUp+9h1iRD5Jw==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hklp8xpCS2Qa6hQCt5qnOrYkkwQkeIQCwQPcHEA9pzUHDg==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hklt0syFuEeIYE3//UfiwS/lcyJ5NAN5s2jGe4Vc5xHKeQ==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hkmzh7YNQJ+XcGeFsDcaBjSz
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HknMDNdxIBFQcIw0RGPfFMjZjfh19zPlQyTadlR6rEMpug==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HklDS7vlaZKw8aBp1UPbgthY
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HkmbQcBvdDeaM0tbHayRHb0Q5oDsO40qheoE5NHoJ7eApdm6gYH0+XlN/FV3HdO5VZw=
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HkmO4Xe0u+mz5wM5yC6Q+Zhs
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HkmpDk5452BsZTuBSuOpo5yN
|
||||
VmVrGQo2zRokW/ZuO9bN69IgslanOR1qBWJ7u9f8kApHl7m/3x/YUX5TmvRhoWWrhrEvRs3e6Vo03iY4FZoGJQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6yAU/fW49cRu9QdgvjUnDRs=
|
||||
VmVrGQo2zRokW/ZuO9bN69qqX19RJUeMAQ5O8TuJCvc=
|
||||
VmVrGQo2zRokW/ZuO9bN69jIxF5VISZtC2vxWRknx7k=
|
||||
VmVrGQo2zRokW/ZuO9bN6w7SLxNKr+6YhBMvtqYtIS5B39SOQ9awYMdHGNN7g2HF
|
||||
VmVrGQo2zRokW/ZuO9bN61ftGV3vPtB2WjF6YrN/0jNHYRNif5kQHZWzQEGp4Mrw
|
||||
VmVrGQo2zRokW/ZuO9bN68i9AQUAyLa5Izsu2k/9DPtGLI71suphKNgMpp1nHjp3
|
||||
VmVrGQo2zRokW/ZuO9bN60FmyZq9YoZep5W4V0xLs2VJw4EwR4WqghfwBKZHKkzFW5QCRYRsMStsmunHScuj3A==
|
||||
VmVrGQo2zRokW/ZuO9bN6zw+wLmacHPHBj00bNmIGZaQr03AAq32yLrsoy6EYs3C
|
||||
VmVrGQo2zRokW/ZuO9bN67c57efC+E7a6G1EN/4VXAUA5IVAU8G/FAp8AnNhV+8pDSYVAZUG09Nqr+7c8CWyvg==
|
||||
VmVrGQo2zRokW/ZuO9bN6x9SPCVoe4PZoqZ6VqYN93GZvfLrMfeSjpwDGE6Mez3z
|
||||
VmVrGQo2zRokW/ZuO9bN64ApqCXcODvD57AL9oh19dsQTwsNrJDaw5mMC3iBkcYF
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hkn5CJpDak47Y7NTLN+SVG+JjtSLj0+GTdSHjBiYnUk9ZehN+mSf/Rh2eO5fYqxzSaFaMrHoUfHlS3DLFMFIxzNoSLKwxQP2/fXAWKceACqodA==
|
||||
VmVrGQo2zRokW/ZuO9bN69/FjVndCR4PL8NhQnFk2GePSUVga2CqkdtTIa+/EIW/
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HklDS7vlaZKw8aBp1UPbgthY
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HkmhycRnROwAaTF+9pqngLGtjJZz0E57qXffjBTU8zR5ws/8WNuh6zqeTDPmSR/EwdRf/kscgnRpkyfDhI32MBlHgF5oG/UTLtRJTD7kKhRtdQ==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HkmO4Xe0u+mz5wM5yC6Q+Zhs
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hknbl+0QAy/9I0gZXTmE2tktHVvxDseM0i9LrUUswPEB0g==
|
||||
VmVrGQo2zRokW/ZuO9bN6yZnMkqRvl1W1z1JA43ooyLsysqnBW0cSn//FgR0VFUn
|
||||
VmVrGQo2zRokW/ZuO9bN6zw+wLmacHPHBj00bNmIGZaQr03AAq32yLrsoy6EYs3C
|
||||
VmVrGQo2zRokW/ZuO9bN66U3/6225IbLyIW0FVhZRNEyLZurMXbjR98/i0DXR7zf
|
||||
VmVrGQo2zRokW/ZuO9bN6xaf2vdYGOU85+dskGN5Zti8/wz7YWu3y/jTkefW+oHw
|
||||
VmVrGQo2zRokW/ZuO9bN6xkyZls2bS2c0K0h3aqZRdZrjes6+0hX3Wr6T+0mnqitWU1y3v2I2Wt4PYH0XBjT6w==
|
||||
VmVrGQo2zRokW/ZuO9bN62zrDNonCkxA5BeQHJAPUOvVeRTu47AJZhJxjTJXUg6D
|
||||
QPiJZBcZo3Zu5kDhrrGzbI3GQxTKN1tlSYOd4wqk4Qk=
|
||||
o6QhOIN2Sc4SHELnst17uYG57hDyRaN+v5d46f3m9TtvuM1edZME3sYQm1fwKXSE
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1V2v8QerKOmubvSxgB4eTM+LVbDQYpuIwwcEKVLExe6MC8BJb9x5uoyJJlFncEM6rY6CjjYEoI1lGYiKE1nBng==
|
||||
mfT8DrNbUmxQ2BnZ1bZFTLh9MEuZKOpmAfF70OnZ9TU=
|
||||
o6QhOIN2Sc4SHELnst17uf4l+kb1P+/cnojpDP8CeKM=
|
||||
ACEEdgL/kNbx7RaZcSRxZClHBggmOTwuoukB6MgtasIiEFle6fCvd15573nsLbI9
|
||||
VmVrGQo2zRokW/ZuO9bN67Pocv3BMn87TAB+S8aqZRSL3g30PRHmEkGas7a6CXo4
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
b4OJVZe8QyIpjuTpKXDL9A==
|
||||
vQwaisdUFOt9b0SJYuH/nrHigrTUtycF35lf58xGUQo=
|
||||
VmVrGQo2zRokW/ZuO9bN61efkqHAT/xspGlYy7KhUnGfupbfN6kadJV1FzZSIvpa
|
||||
VmVrGQo2zRokW/ZuO9bN6+b0SyPGp1VLLfFreWS32CdvJQ0lilsNKGrnKkyex2l6ZoEN1nB9tzGcgrcEFt4mWg==
|
||||
M0ZySqkmhuHCw6olbCKv9zQJzSQJo4Zslq06bXS41SQ=
|
||||
VmVrGQo2zRokW/ZuO9bN6zpJcGQDok2bzZbwZ5+2z7FMKwUs1r6SjvZQDsl9E9LF
|
||||
VmVrGQo2zRokW/ZuO9bN65HmUSl6PKrPLdi3pIfWJgEYDxdXHdYYYJAWxRhWjvkMMBYOgdKbm+/g/JVB0KXlVgkWFQ0d19yx2HQHDjijpFM=
|
||||
VmVrGQo2zRokW/ZuO9bN65hAGaICagbU0z0X3nArVjY=
|
||||
VmVrGQo2zRokW/ZuO9bN65HmUSl6PKrPLdi3pIfWJgGfllFXAtMFaX/YohJyQyfhG9xy/eo7UEqOCihMHvYuSYyU9x8O35sNRwdldlOqO7VLthK8cTiezk0qcNGLbtsxNx/TEJZE7IDz5uyfUbO2Fw==
|
||||
L0eUthVnpkGsmKFAX6d+uA6wgjrZ2VgEjfvSiyQz6oysGP6R543HWJTxMrxe6FdC
|
||||
mfT8DrNbUmxQ2BnZ1bZFTLh9MEuZKOpmAfF70OnZ9TU=
|
||||
L0eUthVnpkGsmKFAX6d+uGu0U7q5yxq3pNh7Qp1zdP4=
|
||||
|
||||
+243
-243
@@ -1,243 +1,243 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: cjxin <cjxin@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#
|
||||
#------------------------------
|
||||
|
||||
import os,sys,re
|
||||
from filesModel.base import filesBase
|
||||
import public,json
|
||||
import zipfile,shutil
|
||||
try:
|
||||
from unrar import rarfile
|
||||
except:
|
||||
os.system('btpip install unrar')
|
||||
from unrar import rarfile
|
||||
|
||||
|
||||
class main(filesBase):
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
def __check_zipfile(self,sfile,is_close = False):
|
||||
'''
|
||||
@name 检查文件是否为zip文件
|
||||
@param sfile 文件路径
|
||||
@return bool
|
||||
'''
|
||||
|
||||
zip_file = None
|
||||
try:
|
||||
zip_file = rarfile.RarFile(sfile)
|
||||
except:pass
|
||||
|
||||
if is_close and zip_file:
|
||||
zip_file.close()
|
||||
|
||||
return zip_file
|
||||
|
||||
def get_zip_files(self,args):
|
||||
'''
|
||||
@name 获取压缩包内文件列表
|
||||
@param args['path'] 压缩包路径
|
||||
@return list
|
||||
'''
|
||||
sfile = args.sfile
|
||||
if not os.path.exists(sfile):
|
||||
return public.returnMsg(False,'FILE_NOT_EXISTS')
|
||||
|
||||
zip_file = self.__check_zipfile(sfile)
|
||||
if not zip_file:
|
||||
return public.returnMsg(False,'NOT_ZIP_FILE')
|
||||
|
||||
data = {}
|
||||
for item in zip_file.infolist():
|
||||
|
||||
sub_data = data
|
||||
f_name = self.__get_zip_filename(item)
|
||||
|
||||
f_dirs = f_name.split('/')
|
||||
for d in f_dirs:
|
||||
if not d: continue
|
||||
if not d in sub_data:
|
||||
if d == f_name[-len(d):]:
|
||||
tmps = item.date_time
|
||||
|
||||
sub_data[d] = {
|
||||
'file_size': item.file_size,
|
||||
'compress_size': item.compress_size,
|
||||
'filename':d,
|
||||
'fullpath':f_name,
|
||||
'date_time': public.to_date(times = '{}-{}-{} {}:{}:{}'.format(tmps[0],tmps[1],tmps[2],tmps[3],tmps[4],tmps[5])),
|
||||
'is_dir': 0
|
||||
}
|
||||
if item.flag_bits == 32:
|
||||
sub_data[d]['is_dir'] = 1
|
||||
else:
|
||||
sub_data[d] = {}
|
||||
sub_data = sub_data[d]
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_fileinfo_by(self,args):
|
||||
'''
|
||||
@name 获取压缩包内文件信息
|
||||
@param args['path'] 压缩包路径
|
||||
@param args['filename'] 文件名
|
||||
@return dict
|
||||
'''
|
||||
|
||||
sfile = args.sfile
|
||||
filename = args.filename
|
||||
if not os.path.exists(sfile):
|
||||
return public.returnMsg(False,'FILE_NOT_EXISTS')
|
||||
|
||||
result = {}
|
||||
result['status'] = True
|
||||
result['data'] = ''
|
||||
with rarfile.RarFile(sfile,'r') as zip_file:
|
||||
for item in zip_file.infolist():
|
||||
z_filename = self.__get_zip_filename(item)
|
||||
if z_filename == filename:
|
||||
|
||||
buff = zip_file.read(item.filename)
|
||||
encoding,srcBody = public.decode_data(buff)
|
||||
result['encoding'] = encoding
|
||||
result['data'] = srcBody
|
||||
break
|
||||
return result
|
||||
|
||||
def delete_zip_file(self,args):
|
||||
'''
|
||||
@name 删除压缩包内文件
|
||||
@param args['path'] 压缩包路径
|
||||
@param args['filenames'] 文件名列表,数组格式
|
||||
@return dict
|
||||
'''
|
||||
sfile = args.sfile
|
||||
filenames = args.filenames
|
||||
|
||||
return public.returnMsg(False,'RAR archive files do not support file deletion')
|
||||
|
||||
def write_zip_file(self,args):
|
||||
'''
|
||||
@name 写入压缩包内文件
|
||||
@param args['path'] 压缩包路径
|
||||
@param args['filename'] 文件名
|
||||
@param args['data'] 写入数据
|
||||
@return dict
|
||||
'''
|
||||
|
||||
sfile = args.sfile
|
||||
filename = args.filename
|
||||
data = args.data
|
||||
return public.returnMsg(False,'RAR archive does not support this function!')
|
||||
|
||||
def extract_byfiles(self,args):
|
||||
"""
|
||||
@name 解压部分文件
|
||||
@param args['path'] 压缩包路径
|
||||
@param args['extract_path'] 解压路径
|
||||
@param args['filenames'] 文件名列表,数组格式
|
||||
"""
|
||||
sfile = args.sfile
|
||||
filenames = args.filenames
|
||||
extract_path = args.extract_path
|
||||
if not os.path.exists(sfile):
|
||||
return public.returnMsg(False,'FILE_NOT_EXISTS')
|
||||
|
||||
if not os.path.exists(extract_path):
|
||||
os.makedirs(extract_path,384)
|
||||
|
||||
tmp_path = '{}/tmp/{}'.format(public.get_soft_path(),public.md5(public.GetRandomString(32)))
|
||||
if not os.path.exists(tmp_path):
|
||||
os.makedirs(tmp_path,384)
|
||||
|
||||
with rarfile.RarFile(sfile) as zip_file:
|
||||
try:
|
||||
m_list = {}
|
||||
|
||||
f_infos = zip_file.infolist()
|
||||
f_infos = sorted(f_infos,key=lambda x:x.filename)
|
||||
for item in f_infos:
|
||||
filename = self.__get_zip_filename(item)
|
||||
|
||||
if filename in filenames:
|
||||
spath = os.path.join(tmp_path,filename).strip('/')
|
||||
if item.flag_bits == 32:
|
||||
m_list[spath] = []
|
||||
else:
|
||||
if not 'other' in m_list:
|
||||
m_list['other'] = []
|
||||
|
||||
dir_key = os.path.dirname(spath)
|
||||
info = {'src':spath,'dst':'{}/{}'.format(extract_path,os.path.basename(spath))}
|
||||
if dir_key in m_list:
|
||||
info['dst'] = '{}/{}'.format(extract_path,'/'.join(filename.split('/')[1:]))
|
||||
s_path = os.path.dirname(info['dst'])
|
||||
if not os.path.exists(s_path): os.makedirs(s_path,384)
|
||||
|
||||
m_list[dir_key].append(info)
|
||||
else:
|
||||
m_list['other'].append(info)
|
||||
zip_file.extract(filename.strip('/').replace('/','\\'),tmp_path)
|
||||
for key in m_list:
|
||||
try:
|
||||
# if key != 'other':
|
||||
# dir_name = '{}/{}'.format(extract_path,os.path.basename(key))
|
||||
# if not os.path.exists(dir_name): os.makedirs(dir_name,384)
|
||||
|
||||
for info in m_list[key]:
|
||||
shutil.copyfile(info['src'],info['dst'])
|
||||
except:pass
|
||||
|
||||
shutil.rmtree(tmp_path, True)
|
||||
except:
|
||||
return public.returnMsg(False,'Decompression failed,error:' + public.get_error_info())
|
||||
return public.returnMsg(True,'The file was decompressed successfully')
|
||||
|
||||
def add_zip_file(self,args):
|
||||
'''
|
||||
@name 添加文件到压缩包
|
||||
@param args['r_path'] 跟路径
|
||||
@param args['filename'] 文件名
|
||||
@param args['f_list'] 写入数据
|
||||
@return dict
|
||||
'''
|
||||
|
||||
sfile = args.sfile
|
||||
r_path = args.r_path
|
||||
f_list = args.f_list
|
||||
return public.returnMsg(False,'RAR archive does not support this function!')
|
||||
|
||||
|
||||
|
||||
def __get_zip_filename(self,item):
|
||||
'''
|
||||
@name 获取压缩包文件名
|
||||
@param item 压缩包文件对象
|
||||
@return string
|
||||
'''
|
||||
filename = item.filename
|
||||
try:
|
||||
filename = item.filename.encode('cp437').decode('gbk')
|
||||
except:pass
|
||||
if item.flag_bits == 32:
|
||||
filename += '/'
|
||||
|
||||
return filename.replace('\\','/')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
QRASP55VO/1DQ98p1csw9A==
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
dBZyCsfrbwqvA0sbdGrIGg==
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
n+0ptngHIPIjFuMNQ53bfj+Na/fdhk6k1yTpAwW7j353Dw920mEqQQZjykAHeRmp0ZD/P3ftGifsmPOMf2b7XdEqyZH0yl9kjaUugj3dYPI=
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
jh3cxzkA2htccqfZRKAUdI8r17q57nOGP4OxbJlL1NAnrF4weHnS0MpT6C6jbrX5
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
Hf+bBTgRv9pVfall8ODpvg==
|
||||
I8MGJUwtjfcKc5w4E0SmjHwLsErBQ84ek459TV1n0Iir/P4mdpfwDI34s6+8CBN0
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
K3QJU/hV27C5FAVoZ+avNNMfDMygeonfI5TFnvUHjhU=
|
||||
X9BNoFOwiQAnMPqEk6FnbzU/oA+chL/aEAzGH80mBrNNxRMBdiGPqgDUeLF6rer2
|
||||
hUVhKZtvg+FKessuieMZGkP/5FS8EfJsx7HCvhsTdvM=
|
||||
KbrESL0Rr2jC6vOleUlueMUgBS8ubHMHEf/dewOmXjc=
|
||||
f3AsbhS4PaN1B4cUkY9T+A==
|
||||
7slA6OC5VJa1dhNh0P/HjCGJmXVn2u3xkCMlnoSxSoA=
|
||||
MMZtIZZuuuWy0CLBzKekTg==
|
||||
0cnYXLPu1n3c2VaQ3tVc+NKPyveC0ERGp532EiLQZU5gtpnLWSMk9qn8OtVlUlvH
|
||||
7slA6OC5VJa1dhNh0P/HjCGJmXVn2u3xkCMlnoSxSoA=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
CjJS7KrzKM18mlLqJK9jKTB717Vvrubu5ix9tb047ao=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
9GxZpCRwMRDPejWR2Vvf+LKn0tNtFKp8Eh2tnr4Da9U=
|
||||
6c3cWGGlsEf4q4E+EjPFyg==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
6d8NLnHX3WuS3g79bJvyhLTeka+iJoxis1kUHdyggy+yXh3Xc8xsyir/5NbKP+Sj41j2UHgL27dZFRsmbh/P+Q==
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
0LFyB+q/4AUBkCrX53xYJedFoNZHYELHOLu/R25oBrqozNv9g917+/ANMSb6X+WR
|
||||
yqM179SzW9HnBHozkU+IlaI6kf6Fax7Db/qE4wQMDFqfwVE+4rG3+IJ9S3c+p3Wf
|
||||
akHibliG6j9uvBEg96vRehUZmhX3a+KyYm/Obf/H764=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1VHvxkEcO4espNMpWHmnH1EgArAJXS2MAairjwNzV9c=
|
||||
b4OJVZe8QyIpjuTpKXDL9A==
|
||||
wQn8ViRVbUL8OLSIgBD0IAeRdK41R3m/PKt9hFbBzr88nFZgyZVILp1bIMP5rZUJ
|
||||
usrsES3VVkgHW6tBbEkpHTeLztsByVaJibbFv8kSFIM=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
l+sL2BKY+z3yDMAsWI51b39VWekdKmbfrOabwvVHTbGfiUobxgPhHW2OIZyeGUJ9
|
||||
wQn8ViRVbUL8OLSIgBD0IO53Ya1+ckG2IX47+ykaGJU=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
MxWDzXEQjj6mgdfarjHFtAA6unJa5l9pTo0P8ga3JDU=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
x41zVQ6DCtWXndDIq7U8L+5quM3ARMCnVm34NUX7l/TJzZZ100EvdUXHXI2cFH4H
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
NNh1PlSD8WUnUEbz+BU/P7D7U0y87ntgFdQV5REShmme9ACxsySMBZr2gsEQniKL
|
||||
c1XU6vxl7MsQKGo3r4amMsSWef3BumXlCWI6QCsp6pMACoHb/XNQfx2cpKV7J/MH
|
||||
akHibliG6j9uvBEg96vRer/Fg5zTlM8oj8hSAsYq018=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
YdUmdqAC07VhbSt1h6KCDASPIXTwTSkv8cm4ToJ+lpo=
|
||||
wgR07xfoapmx6eEnFHXXYmnjxw2aWD9jyym26bSe8wdUky12ZBuFKfAUxS++Pix0
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW/27EoqfC0X59kkH7imoHQb/TQW5074PHVFRKqgD5aSA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1VHvxkEcO4espNMpWHmnHy+YX2/U7Ip4Uqt3suxNhindpukzgQ1aM+PshcW/1dV1
|
||||
LuO0LAjc92aYQU4tSUEvi4x4NJPWR/eKWjRfKMSRL8o=
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmV/41TA4054wrqxXx/Q1i8cmtFJNrxypDZNiWIVVjiYLA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
JbnXIK/axHVmA2plDNFCpPYlXWvPB/7lIz9ynMkifTY=
|
||||
ei/1A+2pKZSasjYF/t4qojBnh7Bi8Fen8Fcf8mKjT9IuWg8ZCZGedub8Eqjf8qUh
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
4nsuLyRybkZg8C3fJCsRPXDWwLMccXwEpFBdFK0JOvg=
|
||||
ZFD6pnBshb3mpu7xvvuMLemrazA4ssXDDuW5SINX4ZLsvLIwaJ4YyDANze64OGqUEj7NCJs+t+zkcUskHr+gqw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
g5xFPP9LKBd4uktrRYzGf+p1NdL+k6huN6CrzYXY3fPVQzhtKStMTpRTZpRqmhGR
|
||||
wlLHv6kT3Q/RmtMBN4nDAbqo0o2IA7mU8WVNqZvoB5I=
|
||||
VmVrGQo2zRokW/ZuO9bN6+qRbBr2ygG3RGcAIOk727ylzODmV8VRqZ4YKvduSUCu
|
||||
VmVrGQo2zRokW/ZuO9bN62psx0nYMGJaQ1S1BUtE6l8lgsopQJ3Qf5syQpAasAAf
|
||||
VmVrGQo2zRokW/ZuO9bN69Woqo49I0Fga24Nj55N9ZL81I98txu56TEAiJ0hswK9
|
||||
VmVrGQo2zRokW/ZuO9bN61e1I6gZaVwmbMEHc7jd9wFEHpeilcxXyCkd5bmWx/yK
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN69+qNrAfkaoVno2zP/PIMh/5aA4AiEej6zodAVzZFzS0
|
||||
VmVrGQo2zRokW/ZuO9bN6xT3wQu8/ZV37F/D/EekYn8LNRE5UkGbTG1UxYqNO1dyU2pay/FWt6r8mJiKZ4UU/g==
|
||||
VmVrGQo2zRokW/ZuO9bN64KhHtDRs0SmcOS1WVIbDs4jrgwkpIqneJssR9hHHlJ3UJd9tZzLLz6C+UQLUJWWGbgxXo0UEEapI14RLzluAUk=
|
||||
VmVrGQo2zRokW/ZuO9bN6xT3wQu8/ZV37F/D/EekYn92m0FWAHkcFEifdcSefZI3
|
||||
VmVrGQo2zRokW/ZuO9bN6xQU/k6xhXMbxscs7Gix8nNqUkjAknQH3LrGVvAyjYtQ
|
||||
VmVrGQo2zRokW/ZuO9bN6xOutEc9teLv333RLphPxTSZMBPTZ5nEHEAZCqisJAYdx733inB6pPVPHnS53cxkslRzdzhPLD4mmySs0XcaZo8Yb7xMuMGGlmbahCRF6eC3yiiMtXXp0R7BViTpiJ04fqWtzkElISMu7z4pkkwr23TjUMjTjCelUG9Lwgmt+EiK
|
||||
VmVrGQo2zRokW/ZuO9bN6wv73IH9kSzXKMUmUPacSk1KDsdrjROzTN1kzduuP0l3
|
||||
VmVrGQo2zRokW/ZuO9bN69lJPu1G3iX01kmj1/0ynPc=
|
||||
VmVrGQo2zRokW/ZuO9bN63p1oaV/8/rZOHP3bxdBsLvjL/YDIWVk4lhx62fOdGpioi6WGXoNG40BaJlgn48VjQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6/kiIWH8hJ6dJOo/fnNj9VLcBHtqpOZ/Rc4AjXcEm1edHKkbtiFAlXrzE+rfp/AeMQ==
|
||||
VmVrGQo2zRokW/ZuO9bN69jIxF5VISZtC2vxWRknx7k=
|
||||
VmVrGQo2zRokW/ZuO9bN69+qNrAfkaoVno2zP/PIMh80w0dM3z0phdMS+lT6j/xo
|
||||
VmVrGQo2zRokW/ZuO9bN65abAZ39yZLyKCl4nd6eov4HdKauw4+toNc5YoXvsAeW
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
+plE/1bhdo64kO07cLlUXzzWH25pNAS0eDxp8hnHILg=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
J24jXQQti6wQv5pCoF2ZrRvdf2ev6P6vInKuFAO8eQfewP9/G67aA1dZDLRwjari
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
NNh1PlSD8WUnUEbz+BU/P7D7U0y87ntgFdQV5REShmlP+1p+XjT1dvUjFUZHsqC6
|
||||
c1XU6vxl7MsQKGo3r4amMsSWef3BumXlCWI6QCsp6pMACoHb/XNQfx2cpKV7J/MH
|
||||
c1XU6vxl7MsQKGo3r4amMpPnl/Q0nxs4Ul/v+JmLHipRvS1iO3+JhmWzafMyTI0p
|
||||
akHibliG6j9uvBEg96vResIm2pvfeBRQxNU2J0BQeUc=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
YdUmdqAC07VhbSt1h6KCDASPIXTwTSkv8cm4ToJ+lpo=
|
||||
BIa0ibHnqUboaK9kYHYO4um2nnLtPSMsHb7nUhh0kKQ6CdlvwTSeB4h8LEiuwG9t
|
||||
wgR07xfoapmx6eEnFHXXYmnjxw2aWD9jyym26bSe8wdUky12ZBuFKfAUxS++Pix0
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW/27EoqfC0X59kkH7imoHQb/TQW5074PHVFRKqgD5aSA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
/0ULpLqgTvInFD0r5hHANoosZ+xywkOR5dozStfmlYk=
|
||||
YSlit6erKXylrjSZnvyW8I3FYH6DLcfYpMAlko6lQqVBBd1eDeDGaujrHWIOJkcI
|
||||
YSlit6erKXylrjSZnvyW8CCccEStX4fvFvduMtCGi54=
|
||||
d2Ww7zhXROgo6Qq8ml3vsgVOxob/5TKf0KTWSmheRnqYA/wEs2DzrY8Dpm7Fq44lbdZ2N/U6naG4DD7karinEw==
|
||||
wlLHv6kT3Q/RmtMBN4nDAdAMeIPpwO0Pgawv937x0Zw4iwEVDD1EIlJA37GxF8mZ
|
||||
VmVrGQo2zRokW/ZuO9bN64/tCOCyKu41lsl+3BVlFMtjVa1DXtvHbVFGS5luzEIFtQp9eHGpneVvKz65gzXCXQ==
|
||||
VmVrGQo2zRokW/ZuO9bN69Z4WTbfjflDn+PHJe4HyeBCMRIQIdsxtS/SkQUyTK46
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN64IUBVOpZieySJUi/5Xp7IP9i2hr//841YnIEqNDctKsA4PCQR7FmaZMQHs7tdC+NQ==
|
||||
VmVrGQo2zRokW/ZuO9bN63KtgQxYoQMLiw/swXgEzq6F5dbUK15QUQFhJ/fqYDb2bGgnr3J8HSW6FkIPXw/QAPGbSGA6euyj6sY6jr9uD88=
|
||||
VmVrGQo2zRokW/ZuO9bN60+Gj1vDNaFgHQa9qY+WYQ/+8quDVQ7mW+ZFMiCB6dK3zTXaMhAFlgEsY2XTlgH4hQ==
|
||||
VmVrGQo2zRokW/ZuO9bN60dNkfoHcjUpCVMrBt5WSA9PCuYzYl0QLyyWqlMopPgY
|
||||
VmVrGQo2zRokW/ZuO9bN6zZcpHqbLPCfucCocPyjGlY=
|
||||
ruTTNFTdswRs4Mc+srnRk818d9d/TGGXzgPjSrVtMi8=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
6JhaWzGWadTJ3yzCk9OQNgkLy/m1ahTUuEy+6FiV49HNwHkAN2ZMxFTsufeIA0ig
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
dar6N0tUAb9rU8/aX1b3tGumQ1hhfk8O6qr6gmiQ1+eBvZwFkpECn+RP444+i510
|
||||
c1XU6vxl7MsQKGo3r4amMsSWef3BumXlCWI6QCsp6pMACoHb/XNQfx2cpKV7J/MH
|
||||
c1XU6vxl7MsQKGo3r4amMlEDkaPg52QqeaL1e16aTiZGdP9MF1i1K/F0icaNF/FRZY8CjFaji8Ecm2WEpXZbMiyduIw57U2lMT6kzLqch3Y=
|
||||
akHibliG6j9uvBEg96vResIm2pvfeBRQxNU2J0BQeUc=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
YdUmdqAC07VhbSt1h6KCDASPIXTwTSkv8cm4ToJ+lpo=
|
||||
BIa0ibHnqUboaK9kYHYO4kqIZZgv1yXQHpqfJ4aNJ54bUNUYTYq/0A+dhHby52Au
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
96orka/uERLyRst14azQwhCOqhTfcgFhXNAQS0hmuOGJEf1Y6VNXDjyNkW1vEjRDaMkNWHl1CoN0rBoEBVHY67QP37rmJsbUJ2x6ftwGYtZYSf3Kk0VjMvB+nFonZq5o
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
O2CqINTuIULxX7Gu5GskT/Nm15YFovaVXDj8ylNfQi3d2Qbp7uZYhyvrRE1b06DK
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
t987AUZxQR72IPRcAqvQ/tuxrpVopv9MhEHHX4HHOFnF6WZD8PVxYK60YbaBpzoa
|
||||
c1XU6vxl7MsQKGo3r4amMsSWef3BumXlCWI6QCsp6pMACoHb/XNQfx2cpKV7J/MH
|
||||
c1XU6vxl7MsQKGo3r4amMpPnl/Q0nxs4Ul/v+JmLHipRvS1iO3+JhmWzafMyTI0p
|
||||
c1XU6vxl7MsQKGo3r4amMgGxGyqG90Nz+St+6838nV5Hy3ZAmDi9Ecxx2gyS4yZO
|
||||
akHibliG6j9uvBEg96vResIm2pvfeBRQxNU2J0BQeUc=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
YdUmdqAC07VhbSt1h6KCDASPIXTwTSkv8cm4ToJ+lpo=
|
||||
BIa0ibHnqUboaK9kYHYO4um2nnLtPSMsHb7nUhh0kKQ6CdlvwTSeB4h8LEiuwG9t
|
||||
XKWK9LfYDT5w2LEWWxwkc6l2k+0eByijzzjX3gaj5k8=
|
||||
96orka/uERLyRst14azQwhCOqhTfcgFhXNAQS0hmuOGJEf1Y6VNXDjyNkW1vEjRD4/QxBrfqq90D/lFkSa20blyxshNDPqg3WrN+80ZCLiv67pSFMB4Brq3qmKK1ZCax
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
D5nlraEpeGmKL9lxoq591txjX2tGuFl4D7WJZ/91lnMQ6WZrDXvU2okqtgoaqWSS
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
VcOpbkIFMz59VlIHGus1M+TodC/Ia97E/RilXZKKBR29V7X/RlCXQzuWibEOEJfo
|
||||
c1XU6vxl7MsQKGo3r4amMsSWef3BumXlCWI6QCsp6pMACoHb/XNQfx2cpKV7J/MH
|
||||
c1XU6vxl7MsQKGo3r4amMjvzqCkQbmHuG+orSe7QiThO3NRqf8lDLQklcqf6u2x4yWOeax5QyyroyrE443cDvw==
|
||||
c1XU6vxl7MsQKGo3r4amMlEDkaPg52QqeaL1e16aTiZGdP9MF1i1K/F0icaNF/FRZY8CjFaji8Ecm2WEpXZbMiyduIw57U2lMT6kzLqch3Y=
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
YdUmdqAC07VhbSt1h6KCDASPIXTwTSkv8cm4ToJ+lpo=
|
||||
BIa0ibHnqUboaK9kYHYO4kqIZZgv1yXQHpqfJ4aNJ54bUNUYTYq/0A+dhHby52Au
|
||||
77Mf9+1xBvZiUeNTtU/s60Kyn+UEu/OgKFt23E+wd8BiTmgbWFTzjcyPW/imPN9p
|
||||
wgR07xfoapmx6eEnFHXXYmnjxw2aWD9jyym26bSe8wdUky12ZBuFKfAUxS++Pix0
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW/27EoqfC0X59kkH7imoHQb/TQW5074PHVFRKqgD5aSA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
wgR07xfoapmx6eEnFHXXYmSt8oPS+2lwNla/wCY62SBZ7HAsGrtjJH7dzi+5hXSr
|
||||
NqhMbY8+EQI8zhTG6Zh2I5csQ+/eG6egKX2sKZJStJZk02bOBi20A8UHGNy6sybt
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
IZj4TYq2HlScfSdRkI+QP263Ug7hf7sm5bqxRn1G7j8CZM6KmOHJcbEZNXo2mkEA3MxUp7pEuHhp8IfRMvwD6SZPogdTtHhT5unY8iIrUiU6GaMq6uosuXq8hjxV9nUgwa2iqC1n6Ziz6tiDdPy1mw==
|
||||
wgR07xfoapmx6eEnFHXXYm7IOJ/6J1NThWNK2EdPRzYwWPvLP+jlqDp61mwE1mzG
|
||||
NqhMbY8+EQI8zhTG6Zh2I0BiMnuwr8mLUTT6rraGmzoW2r/izQNInq2UmHNhRbv+
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
d2Ww7zhXROgo6Qq8ml3vsgVOxob/5TKf0KTWSmheRnquRJLMVVVt2mgyaZFKv044NjiViQAAPm85lrCa2jWZ2Q==
|
||||
vQwaisdUFOt9b0SJYuH/nrHigrTUtycF35lf58xGUQo=
|
||||
VmVrGQo2zRokW/ZuO9bN61lflwobhmxel33RwHEAzsw=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN67AsrXUPIcMWmsNJ6skMzcKlx905HWgBAV8CDz0otLpU
|
||||
VmVrGQo2zRokW/ZuO9bN64dz5HIueoVr5d2RnbNUIG5nWBmTbO/nPqZZ/WWusF8B2fWzSHjB5SEduhXLHWwpbFrG7MHMtEZh0rgim/Nvx4Q=
|
||||
VmVrGQo2zRokW/ZuO9bN66NLXvUSFhBjtRrUbZsPQNOrrRiOaX/5u3wb0Rfqy+pv
|
||||
VmVrGQo2zRokW/ZuO9bN6wsF8dCAuyXrReoI3w9Yj8ejyyRZrswtbKGtDKu6ywDGElhkS5s5y7BVqVo+FqDhvA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6wOXhaCTOJSjUCWUfjx+YyYNeSRhAnvmOzc5j0wt6pWe
|
||||
VmVrGQo2zRokW/ZuO9bN61ODJTwuVdYa2e77kV4UyyiKC6xmDTYLpzmUEL6iaKIotT6XRfjdpuPhvefHRzC+7lCYolxcDYktKmTY39wnf+k=
|
||||
VmVrGQo2zRokW/ZuO9bN63p1oaV/8/rZOHP3bxdBsLvjL/YDIWVk4lhx62fOdGpioi6WGXoNG40BaJlgn48VjQ==
|
||||
VmVrGQo2zRokW/ZuO9bN655297gigIv+4Ufy0bubbx7ffTJUoURR64bKe908x4ap
|
||||
VmVrGQo2zRokW/ZuO9bN62cJZxyhxghVn78AgYWoneU=
|
||||
VmVrGQo2zRokW/ZuO9bN63LTkM1jyAeOymc1jas3GbdSOgZt1gFP6QuzR+PijaPfkXI6n5+LDNetR25SN0GXgg==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hkns33MIHJ07fAs3bEPA9prEegTrYMIIXPrzC4jD9xKXsA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6+VE/nQEHJOLSC1DnxvG5TiVhVg6gVuqdGuJQhlv12yWuKoI97jUkrKrXkDjch0nxA==
|
||||
VmVrGQo2zRokW/ZuO9bN66Stm18E9cFphVzr4DVvkp0eMQP2KdIRCCvQSRwvi/ogRLfVX0ez0AMMWvL6BswFfzkKtdTc18Qoh/tgpwV2o+ISRqfA+Zum4wzK337qVQa8uzWtdDX/DDCp8lweCdFZUw==
|
||||
VmVrGQo2zRokW/ZuO9bN6zsPJOFHzvayEpAPvGiJ0lAWXca0TugmxSi8hINZZvoHQ1Y8EIw5ZU/3qx6IfU7mzw==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HkmgImK713UKKRnRLyQBV8gyjNySqhD1ER71FyIggw6WuTb4tOz+zOmUJvBAa9I7hKop6pGwEoB2371+83RgakZhyjMJWosIoeLReEb5GcqHNA==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HkkrikeB3PyYnRyHWKvzXceKTTsB9Sbgf9uM/v0isHHFakzQxpTSrdsYuODmqyQGE3Q=
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hknz2So+gFu+BijKlvPtsNKCIi0RkX1BFpd3GhHKBMdoB6DedipwufkrnDIRLB493gRtMiXCiHSsTBNmIXqRl2RK
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HkkqG04WXvd0zYTVxLMDUCWknQtobuOLFvBEBrZieoy/MQ==
|
||||
VmVrGQo2zRokW/ZuO9bN61TKHwbNGf/2Ub0vd756U9O0Gtl0vapnf7HpdYx4U2ib
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hkk6a/inNeVFTn9NarE6P/3LG5P9KtqHegfYsmaf6Actxw==
|
||||
VmVrGQo2zRokW/ZuO9bN67FJHoI0w8vvrPd3RbddRrD2Em+ygcQFnOdLaXNs8ffOckKjgP3gK8cG/TTtMkpW3DL4StNcG/wbkijZS1ecn2uSboPx9VWF3PIGue3h88Yd
|
||||
VmVrGQo2zRokW/ZuO9bN65aFRI029wWEhVZc+cvXTRpzda0UlKTw9izNui/xkgdD
|
||||
VmVrGQo2zRokW/ZuO9bN62HWtxZ2I/oCwtyWP0WSTIg=
|
||||
VmVrGQo2zRokW/ZuO9bN6yfyDpG+MDWCM+I7xrm6yMNHAsN4/aIr7LH++fbWW227
|
||||
VmVrGQo2zRokW/ZuO9bN61RP3YbpVjqNga0la0+UFBO8any5NddZFrxwPV3C0M24EIcWBMjLzVvJvQ44t1iabGq/xokqYehL60ehDQbn9KxCN13a+8iVaZY1iG866Qqj
|
||||
VmVrGQo2zRokW/ZuO9bN62eRNBkbzSoIoWrmVfjVYrLET/E/3Y6o68HoLFuelGsQJP2af8rBXdv1FclI3SNTly4xPKYQA8oVfyimWnwTn5ty/z6nec9yo4C3p/VcdNxW
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6ylpzdD3c1E8cbuPHoSW5RFJzxWCEvXq+6grREYT2q2eRpfKq4CUkXaSg9PBb07Brg==
|
||||
VmVrGQo2zRokW/ZuO9bN6zS5woMmxkovFr1YPmCwVjomnwjs8yJd8vJ968XXd0m0pndaSK8+qOGykyY0WQyhZ6POo4IRkaJlDhmmPU4hQ+8=
|
||||
VmVrGQo2zRokW/ZuO9bN643JcJR2kB926iqWdGz5U79RHIfKNGRE8o6dVdz5ZS7F
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN67XKiXTToYD4Xj8EJf9tU1/Vu+G41TBzTVvAU2KLSeCv
|
||||
M0ZySqkmhuHCw6olbCKv9zQJzSQJo4Zslq06bXS41SQ=
|
||||
VmVrGQo2zRokW/ZuO9bN6zM/X2hHBCd+n2OGnnATmrTcB3+DRCAF+pezmRjCID0udaZbU9+Bp25aQzLB8QDwQjJOciYA4ZMGenxD3oVSnPjhf/xssdSo8p33UNNP+7LnwEXEbYt+fXn2F5oiKjC6Gw==
|
||||
96orka/uERLyRst14azQwhCOqhTfcgFhXNAQS0hmuOGez0gsOf0QeJW43sHDXr/9AmAy18p0NZvV4WTviIGdP9rl3wBU2+XWJNGEpDCn6tY=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
mObL0pW76xtWwwYeubgb11DPfOo/O10pxYUkfDIVCjm8OCRNT0T/bbX1vgDt/X1W
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
H7d2MP+WgR9k+129/mRN7ij0WzXIk6KGh6j7E1fgHISsYBh1T2OGWCH8QUwPOkcn
|
||||
c1XU6vxl7MsQKGo3r4amMvdbawOnt/oBPSHXSrswDVS5Xue1Y7sB0F2vPYt641B/
|
||||
c1XU6vxl7MsQKGo3r4amMpPnl/Q0nxs4Ul/v+JmLHipRvS1iO3+JhmWzafMyTI0p
|
||||
c1XU6vxl7MsQKGo3r4amMqf9zivp0Qb6thhCnxaiYdHXwUNLWpYP828px7Gieygp
|
||||
akHibliG6j9uvBEg96vResIm2pvfeBRQxNU2J0BQeUc=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
YdUmdqAC07VhbSt1h6KCDASPIXTwTSkv8cm4ToJ+lpo=
|
||||
g8q6WqkWsk4SUh3d5nzGDIJanaAux29CDdQxdeG/k+U=
|
||||
Vyh8kMpaq2Q+odra9mDJ3Acz3kaMgWRroPCWRIzYRMY=
|
||||
96orka/uERLyRst14azQwhCOqhTfcgFhXNAQS0hmuOGJEf1Y6VNXDjyNkW1vEjRD4/QxBrfqq90D/lFkSa20blyxshNDPqg3WrN+80ZCLiv67pSFMB4Brq3qmKK1ZCax
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmA0y/dvI19s9e1BRFCkk/QzH4UG1JBu620e7CQwjbQOOUvlgFJz4yLxls8aSEEo
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
NNh1PlSD8WUnUEbz+BU/P+yZLrQY+X/LEpSBMw7xwfahIuTImHO5EcUQN9HQmgqX
|
||||
LikBEoRjt8wwWzUZNw+jJqDVmHo0aqmO8fx4adbRXm90KhRgBH5ZfsJyfEAx+4JR
|
||||
akHibliG6j9uvBEg96vRei563dWr9knc+JrDspjHc/A=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
BIa0ibHnqUboaK9kYHYO4qFxMPyUysXdjYA1FqqhK4UMv4PoX1vehXtIZKdqRHbG
|
||||
b4OJVZe8QyIpjuTpKXDL9A==
|
||||
PRG/YRzXVD8iVR3bzEcUnlkfSwESl/MBfBcCyRS23XAS+yqB8BD2Fws8ohDlx4dxPS4gXd1cpWdmGRHNT+D6KSwXWu5PYPEs39ffK4i+qWM=
|
||||
usrsES3VVkgHW6tBbEkpHTeLztsByVaJibbFv8kSFIM=
|
||||
6XDh38s4HWrzA9ChHtrpYfoDrFj6al2d9qt+zDQaqfaH1G08yJkGG2cvEJO5JVMs
|
||||
PRG/YRzXVD8iVR3bzEcUngb7XqhS9BqrxYAnnSw8i/s=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
5wsVwKLrIjIWqeTNpSVp9UQ8Pi6XZeLfFubLS2iQfjkZO92jH5vXc8qvq/7p/iKy
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
|
||||
+307
-307
@@ -1,307 +1,307 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: cjxin <cjxin@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#
|
||||
#------------------------------
|
||||
|
||||
import os, re
|
||||
from filesModel.base import filesBase
|
||||
import public, json
|
||||
from html import escape
|
||||
|
||||
|
||||
class main(filesBase):
|
||||
|
||||
__s_class = []
|
||||
|
||||
def __init__(self):
|
||||
for i in range(1, 100):
|
||||
self.__s_class.append('f-s-%s' % i)
|
||||
|
||||
def get_search_status(self, get):
|
||||
"""
|
||||
@name 验证是否可用
|
||||
"""
|
||||
return public.returnMsg(True, '1')
|
||||
|
||||
def get_search_result(self, get):
|
||||
"""
|
||||
@name 搜索文件
|
||||
@param get
|
||||
path:搜索路径
|
||||
search:搜索关键字
|
||||
limit:每页显示条数
|
||||
p:页码
|
||||
"""
|
||||
result = {}
|
||||
is_dir = 0
|
||||
search = []
|
||||
|
||||
if not 'ext' in get: get.ext = '*'
|
||||
if 'search' in get: search = get.search
|
||||
if 'is_dir' in get: is_dir = get.is_dir
|
||||
|
||||
public.set_module_logs('searchModel', 'get_search_result')
|
||||
if not is_dir:
|
||||
if len(search) == 0:
|
||||
return public.returnMsg(False, 'Please enter search keywords!')
|
||||
|
||||
if not os.path.exists(get.path):
|
||||
return public.returnMsg(False, 'Search directory does not exist!')
|
||||
|
||||
slist = self.get_search_files(get)
|
||||
if is_dir: return slist
|
||||
num = 0
|
||||
total_num = len(slist)
|
||||
if slist: public.writeSpeed('files_search', num, total_num)
|
||||
for sfile in slist:
|
||||
data = self.__check_file_contents(sfile, search)
|
||||
if data:
|
||||
result[sfile] = data
|
||||
num += 1
|
||||
public.writeSpeed('files_search', num, total_num)
|
||||
progress = int(public.getSpeed()['progress'])
|
||||
if '_ws' in get:
|
||||
get._ws.send(
|
||||
public.getJson({
|
||||
"end": False if progress < 100 else True,
|
||||
"ws_callback": get.ws_callback,
|
||||
"file": sfile,
|
||||
"progress": progress,
|
||||
"total": total_num,
|
||||
"num": num,
|
||||
"type": "get_search_result"
|
||||
}))
|
||||
if not slist and '_ws' in get:
|
||||
get._ws.send(
|
||||
public.getJson({
|
||||
"end": True,
|
||||
"ws_callback": get.ws_callback,
|
||||
"file": '',
|
||||
"progress": 100,
|
||||
"total": 0,
|
||||
"num": 0,
|
||||
"type": "get_search_result"
|
||||
}))
|
||||
return result
|
||||
|
||||
def get_search_files(self, get):
|
||||
"""
|
||||
@name 搜索文件
|
||||
@param get
|
||||
path:搜索路径
|
||||
search:搜索关键字
|
||||
"""
|
||||
|
||||
data = {}
|
||||
|
||||
data['is_sub'] = 0
|
||||
if 'is_sub' in get:
|
||||
data['is_sub'] = int(get.is_sub)
|
||||
|
||||
data['ext'] = []
|
||||
for ext in get.ext.split(','):
|
||||
if ext: data['ext'].append(ext)
|
||||
|
||||
data['s_time'] = 0
|
||||
data['e_time'] = 4070880000
|
||||
if 's_time' in get:
|
||||
data['s_time'] = int(get.s_time)
|
||||
if 'e_time' in get:
|
||||
data['e_time'] = int(get.e_time)
|
||||
|
||||
data['min_size'] = 0
|
||||
data['max_size'] = 1024 * 1024 * 10
|
||||
if 'min_size' in get:
|
||||
data['min_size'] = int(get.min_size)
|
||||
|
||||
if 'max_size' in get:
|
||||
data['max_size'] = int(get.max_size)
|
||||
|
||||
data['names'] = []
|
||||
if 'names' in get:
|
||||
data['names'] = get.names
|
||||
|
||||
flist = []
|
||||
self.__get_file_list(get.path, data, flist)
|
||||
|
||||
return flist
|
||||
|
||||
def __check_file_contents(self, sfile, contents):
|
||||
"""
|
||||
@name 验证文件内容
|
||||
@param sfile:文件路径
|
||||
@param contents:文件内容
|
||||
"""
|
||||
n = 1
|
||||
result = {}
|
||||
try:
|
||||
for line in open(sfile, 'rb'):
|
||||
try:
|
||||
if type(line) == bytes: line = line.decode('utf-8')
|
||||
except:
|
||||
line = str(line)
|
||||
|
||||
rep_list = {}
|
||||
_line = escape(line)
|
||||
p = 0
|
||||
for txt in contents:
|
||||
if not txt: continue
|
||||
p += 1
|
||||
txt = escape(txt)
|
||||
if line.find(txt) >= 0:
|
||||
_line = self.__replace_contents(
|
||||
_line, txt, p, rep_list)
|
||||
else:
|
||||
tmp = re.search('(' + txt + ')', _line, flags=re.I)
|
||||
if tmp:
|
||||
_line = self.__replace_contents(
|
||||
_line,
|
||||
tmp.groups()[0], p, rep_list)
|
||||
|
||||
for key in rep_list:
|
||||
# public.print_log(json.dumps(rep_list))
|
||||
result[n] = _line.replace(key, rep_list[key])
|
||||
n += 1
|
||||
except:
|
||||
pass
|
||||
return result
|
||||
|
||||
# line = line.replace("BT_SEARCH".format(p), )
|
||||
def __replace_contents(self, line, txt, p, rep_list):
|
||||
"""
|
||||
@name 替换文件内容
|
||||
@param line:文件内容
|
||||
@param txt:替换内容
|
||||
@param p:替换位置
|
||||
"""
|
||||
n_data = 'BT_SEARCH{}'.format(p)
|
||||
line = line.replace(txt, n_data)
|
||||
rep_list[n_data] = "<span class='{}'>{}</span>".format(
|
||||
self.__s_class[p - 1], txt)
|
||||
return line
|
||||
|
||||
def __get_file_list(self, path, data, flist):
|
||||
"""
|
||||
@name 获取文件列表
|
||||
@param path:文件路径
|
||||
@param ext:文件类型
|
||||
@param s_time:开始时间
|
||||
@param e_time:结束时间
|
||||
@param min_size:最小文件大小
|
||||
@param max_size:最大文件大小
|
||||
@param flist:返回文件列表
|
||||
"""
|
||||
|
||||
exts, s_time, e_time, min_size, max_size, names = data['ext'], data[
|
||||
's_time'], data['e_time'], data['min_size'], data[
|
||||
'max_size'], data['names']
|
||||
|
||||
for name in os.listdir(path):
|
||||
sfile = os.path.join(path, name)
|
||||
|
||||
if os.path.isdir(sfile):
|
||||
if not data['is_sub']: continue
|
||||
|
||||
self.__get_file_list(sfile, data, flist)
|
||||
else:
|
||||
|
||||
#第一步:验证文件名
|
||||
if not self.__check_filename(sfile=sfile, names=names):
|
||||
continue
|
||||
|
||||
#第二步:验证后缀
|
||||
if not self.__check_ext(sfile=sfile, exts=exts):
|
||||
continue
|
||||
|
||||
#第三步:验证时间
|
||||
if not self.__check_time(
|
||||
sfile=sfile, s_time=s_time, e_time=e_time):
|
||||
continue
|
||||
|
||||
#第四步:验证大小
|
||||
if not self.__check_size(
|
||||
sfile=sfile, min_size=min_size, max_size=max_size):
|
||||
continue
|
||||
|
||||
flist.append(sfile)
|
||||
|
||||
def __check_filename(self, sfile, names):
|
||||
"""
|
||||
@name 验证文件名
|
||||
@param sfile:文件路径
|
||||
@param names:文件名
|
||||
"""
|
||||
try:
|
||||
if len(names) == 0: return True
|
||||
|
||||
filename = os.path.basename(sfile)
|
||||
for name in names:
|
||||
if filename.find(name) >= 0:
|
||||
return True
|
||||
try:
|
||||
if re.search(name, filename):
|
||||
return True
|
||||
except:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
return False
|
||||
|
||||
def __check_ext(self, sfile, exts):
|
||||
"""
|
||||
@name 验证文件后缀
|
||||
@param sfile:文件路径
|
||||
@param exts:文件类型
|
||||
"""
|
||||
try:
|
||||
if "*" in exts:
|
||||
return True
|
||||
|
||||
spath, ext = os.path.splitext(sfile)
|
||||
if ext:
|
||||
if ext[1:] in exts:
|
||||
return True
|
||||
else:
|
||||
if 'no_ext' in exts:
|
||||
return True
|
||||
except:
|
||||
pass
|
||||
return False
|
||||
|
||||
def __check_time(self, sfile, s_time, e_time):
|
||||
"""
|
||||
@name 验证文件时间
|
||||
@param sfile:文件路径
|
||||
@param s_time:开始时间
|
||||
@param e_time:结束时间
|
||||
"""
|
||||
try:
|
||||
st_time = int(os.stat(sfile).st_mtime)
|
||||
if st_time >= s_time and st_time <= e_time:
|
||||
return True
|
||||
except:
|
||||
pass
|
||||
return False
|
||||
|
||||
def __check_size(self, sfile, min_size, max_size):
|
||||
"""
|
||||
@name 验证文件大小
|
||||
@param sfile:文件路径
|
||||
@param min_size:最小文件大小
|
||||
@param max_size:最大文件大小
|
||||
"""
|
||||
try:
|
||||
f_size = os.path.getsize(sfile)
|
||||
|
||||
if f_size >= min_size and f_size <= max_size:
|
||||
return True
|
||||
except:
|
||||
pass
|
||||
return False
|
||||
QRASP55VO/1DQ98p1csw9A==
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
dBZyCsfrbwqvA0sbdGrIGg==
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
n+0ptngHIPIjFuMNQ53bfj+Na/fdhk6k1yTpAwW7j353Dw920mEqQQZjykAHeRmp0ZD/P3ftGifsmPOMf2b7XdEqyZH0yl9kjaUugj3dYPI=
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
jh3cxzkA2htccqfZRKAUdI8r17q57nOGP4OxbJlL1NAnrF4weHnS0MpT6C6jbrX5
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
Hf+bBTgRv9pVfall8ODpvg==
|
||||
I8MGJUwtjfcKc5w4E0SmjHwLsErBQ84ek459TV1n0Iir/P4mdpfwDI34s6+8CBN0
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
xO7Wpp8LRZfjlLUey8VU9w==
|
||||
X9BNoFOwiQAnMPqEk6FnbzU/oA+chL/aEAzGH80mBrNNxRMBdiGPqgDUeLF6rer2
|
||||
Ji07I4FXLA9HlL84f+xIzwVBYHb2UR2JW88XmYqsjV8=
|
||||
FpGNKKrJzpuJOv3iM0R0pQ5MvNLfEMlC/N/hQ9UzGqI=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
CjJS7KrzKM18mlLqJK9jKTB717Vvrubu5ix9tb047ao=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
TRR4OWAtNW2TMCr31HujQ786ngB4F46vN339GISDrdk=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
9GxZpCRwMRDPejWR2Vvf+LKn0tNtFKp8Eh2tnr4Da9U=
|
||||
9zgnmC3+5N9XK5/NRaR4SCWZ3UikXYFnKKlpz6ENZEzWUZDKLOFleg2+OHdqWpsE
|
||||
32pdC9DD05OE2l0oXazDFOXcNRPwrc0ZAJ7EyyAKw9gZBJ6iOJyN12yiwNtvG/Etj4AUGv20tGUTP756+m4Fmg==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
U28wv7XxIHeRSkqXJHXzR3dYOl05WSZCrwQLHtq7mE+upUObOxjAVH+D2wuzBbzd
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
zZQPiCGCqSDO70yiwDNUrtYZbEcZaFTWzu76ev6QF+qbXnZjxFPpMEvGatyQPWPw
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
96orka/uERLyRst14azQwhCOqhTfcgFhXNAQS0hmuOFR1+D7xHQXnSFNKqEFQ40g
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
U28wv7XxIHeRSkqXJHXzR/CzOXT9fdhh18KnqL31WmtG7mgmXX+KEsVaJ9DtI5Om
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
3f+yEXMJpDOPrez5ap+fN71X0yVW9y+W39rIT+wSpcE=
|
||||
ho/Q+jrWDtBeg9J9ZTnKi3+/Efbvadpf+qoH75NuGwk=
|
||||
9uZN8r0CKVAbfzGtFDuvLwhOKNflpKM2ZwfKcLjWwCQ=
|
||||
s2s/1ED0ebJ2NmFlE8kk0/nWNx9HXYglwLmrDDl0SJVEejxjmWbqF4tItLVHJaXz
|
||||
zxNKIz/Dwj9Harw3dUNEQJhfwzP9e0g+QEHF20IF9QloJJn499jB5lN74CMN7xKF
|
||||
sziRj7t6JsRtk9qEmKAeGc8r59oagHkoEVKlJap65zo=
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
/0ULpLqgTvInFD0r5hHANoosZ+xywkOR5dozStfmlYk=
|
||||
EAqIF4KpaXVDvs4DDT5V96KZSat3hIJqR6dNVUxhnWo=
|
||||
Nxw10FAZUk+m0nadC1hdyzNerAYqJLcLvHGGVkpkJIM=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
g9LTwGsiGd7fGczReaq0piwhORjgGOZyOpIjDfyNOXCPNawCc9H7QjiYk9PnEc8K
|
||||
X/Lp4PsbbXulceSXUvGUpDfqLabbqgG4MZE+Cdy4FwlQTZqFS7MLKRTLDMwaDvILIRxQybc5sD1eU9BOwIwsyw==
|
||||
R4Jn97/68Irdow38EVIRhDowEdscaTuWxhIXOfqZKT3o/TXmpW6PH4gqeWelHNA33aMiyCRKeO0D7gfs1V70Hg==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
Ic1WBp01nLyRxbqJnsu2pypx+Gb9M9+y4CZIw5enWs/lMRSVWryD1gVdrE+N///hctbXY1m9aLHS8lUrVSnFP5O6PHEXfEjsMokMZJkUfD0=
|
||||
cbvASHjpysrsjdY5RctXmJXaYs34E4tMRz7722FvpDk=
|
||||
ACEEdgL/kNbx7RaZcSRxZD3JieACM+9p2ggEO8B4CeOCL6Z+tjHPmOoWvsHltK8C
|
||||
VmVrGQo2zRokW/ZuO9bN6zM/X2hHBCd+n2OGnnATmrSo1ZAQ1FHnoPT0QBpT+y//Ad3DLkc/FyKmgGPF5OiRLoeUNVCXj1GWzYsscvnb2SZxU4zI4hEOYLKQ5kvjDFyS
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
wgR07xfoapmx6eEnFHXXYvriJFohZH5kYuBlhocmFiOq4wyQewMJhJy8xbRXglbx
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmUaLU2ERbIduh0en1Wj1B8Tfd95oiMHCmcX2jALSwoq6RyVU7vVavWtQJUE9viKOUw=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
2/eGB4mNeTC2Lw/I1/B9jClbFP06By8Q6TQXjVRMC5aisNpbx4ptA/UYjC7wxXvn
|
||||
DUkWJc4dP0F0T3fzlo5ovg+i5a7jjY0MEmCx8kfq2jK+QHBdk0bbr2AxZ3cQqlrr
|
||||
Djb8zu0gG2jt979SRwXXjOvVYuDaNNQCNmI1OvvoD70=
|
||||
H72sLFEMWD5UKG0XW5F6nGJKzW/LoRFoOz84reF2UCk=
|
||||
2RF1tdl20VItbDNfdL2RkNTBOOe8pYfatuolPTwnN8LGADdQl54uUvT1DVF9e+iGV4cafz7X+gg6KtVrt/TXCPI9NWJqgOr1pzq/i1AhR10=
|
||||
6Kva1wVgBZWnKH8KBbNuqu0I1u+AyN34C41R+ayvUyA=
|
||||
NhnIR3Ilo4H2su9/cTNo/Fny68/2PqdXcpcFyZsnflsKTqzPOMITq9Y6CpuGnJ1XbcsahDP9y+wRMXSx0waR3Q==
|
||||
Dlyx6ZDFdkn72YIxkC3bo99d0wqqUWkm5oggFt3pXuw=
|
||||
VmVrGQo2zRokW/ZuO9bN6wd/KBNDReWGUABD3WNwVs62xWSEQgqeqad2Q73LEQLC
|
||||
7aT066WRx/cZGdWRKj2TgzQp9AN+Q9kHfKqypeMmdG4=
|
||||
xWoGNWjKGPfI4gq8aHoTfPXeKqcetXNDNllPDdGzxJIYVQirFuRW+EjhBVgYVjVDRD56A0SEtVDAKN9yNygMzg==
|
||||
jlXY8vCef9GOpgUZXz0mf9DfhxAODMs6lMdvzBIM/MW1Aq1rMVSrJYB723qLrfih3YWjEp+EB+NTwJh1y6k0Yg==
|
||||
84Vymj90Wzn5yYuvz1pUuNMKvUAWFp7QE+2Yweu4868=
|
||||
VmVrGQo2zRokW/ZuO9bN6wEyB2Guh40Pcugoyh0QBDk=
|
||||
VmVrGQo2zRokW/ZuO9bN66AnqHISKFWgaxa6i1eykZnjUYRjoLmSwgSMUPuifCRX
|
||||
VmVrGQo2zRokW/ZuO9bN62/0JMqSTjLVEyn+Ej8AxwUnCoc7c66mKn79grgEeCW4lCCimbVM8qjmKRX089HBXQZTubrP4Dlhm4eMwMPvv3E=
|
||||
VmVrGQo2zRokW/ZuO9bN6+E4b2xiC6ZHjT1m1FpW3M+cImaNbhy13Fhkj9q6wpbsV6pyGO3VUL36gOhAJ+Q9bA==
|
||||
VmVrGQo2zRokW/ZuO9bN69SEQTu8KN9su1QzyegRt9I0k+TINrUN1jOdFTWatw/A
|
||||
VmVrGQo2zRokW/ZuO9bN691C3HCcq309X4zk3aYIPPcffxT7OcwObFcDmavXvPD0
|
||||
VmVrGQo2zRokW/ZuO9bN65RsFGHNPy4PRufoKux2OhO78Lnr5z+7zzZGg1YcYuSV
|
||||
VmVrGQo2zRokW/ZuO9bN6x5oB/WlUCb6mmC2LMPppfSCyk+XA4K4GFn/hUbHBSy5
|
||||
VmVrGQo2zRokW/ZuO9bN67Ff1ABLPDzqsQSzl/a49rnaHEAmRXtCEzOMwE/sYpXvJqC4BUWuPJeNx91EHEOGRg==
|
||||
VmVrGQo2zRokW/ZuO9bN6198WF1cuKQrC1Fe1gF45Yc=
|
||||
uTEK8Ng11d3ix2pA+DD/aX0ELDXTMxMbOqDs4xOCbbtjTvaikhc80beKBuWMfrmy
|
||||
OO/dMlOTxBikYSnUTxYxGjU1adFuYtvDicPSrTmmd94=
|
||||
VmVrGQo2zRokW/ZuO9bN6xA57qdw8/aOkwkb2GLtNsM1Gxzw/Ohom0z8ykGCiYSk
|
||||
VmVrGQo2zRokW/ZuO9bN68s4dlWAY+dRAs2Ywb0QeE1L2XlwGJiaW7efF6E8T2X4
|
||||
VmVrGQo2zRokW/ZuO9bN61fiC4FaUq8z+fKBUks6tGgZfs6Lma5kU54uQlswGIQVxfzffKkvm1lDl5rcXHMFFA==
|
||||
VmVrGQo2zRokW/ZuO9bN6725gn6AE4KlYGXCgdldfTHvVePxt81VDJii+UIRV9So
|
||||
VmVrGQo2zRokW/ZuO9bN6xP6//zUY+lIi+gH0ZiMAHxrWVK37wh0Dd0rIYDgHxyh
|
||||
VmVrGQo2zRokW/ZuO9bN65Vu8PVmTF+4Dzea/bvMcEVOXNQxxERI+pswNZxPLgGG
|
||||
VmVrGQo2zRokW/ZuO9bN66+Mk4GZKdNMe7NCKER0yRk=
|
||||
VmVrGQo2zRokW/ZuO9bN6+3m7PBc9EdU7lP2yNhVBRJqxygYFe0FGSSnC9/qF3UeaMY1MoDseyFI9vmbOD5IgQ==
|
||||
VmVrGQo2zRokW/ZuO9bN64vo1FYdzVPQhcC0bXObVxs=
|
||||
ruTTNFTdswRs4Mc+srnRk818d9d/TGGXzgPjSrVtMi8=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
U28wv7XxIHeRSkqXJHXzR0xpTOufJNSwabqZ3Q3ilnxCv5GA0Lu1QixaJfBttSFg
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
3f+yEXMJpDOPrez5ap+fN71X0yVW9y+W39rIT+wSpcE=
|
||||
ho/Q+jrWDtBeg9J9ZTnKi3+/Efbvadpf+qoH75NuGwk=
|
||||
9uZN8r0CKVAbfzGtFDuvLwhOKNflpKM2ZwfKcLjWwCQ=
|
||||
s2s/1ED0ebJ2NmFlE8kk0/nWNx9HXYglwLmrDDl0SJVEejxjmWbqF4tItLVHJaXz
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
JbnXIK/axHVmA2plDNFCpPYlXWvPB/7lIz9ynMkifTY=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1zXpiGOddO9f/7P9ia16hLkuEytAkOvat/hMfHQ4YOA=
|
||||
TlcB8lXx3B+v8kN8QpOFdfk9CF2LWs/6yNZPbaaVR70=
|
||||
NhnIR3Ilo4H2su9/cTNo/ADljVwvrJpst190+kbx61cg2ptEynXXqaFn0MK3A4Gi
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
UVXwiL1XIF6sRJ+E2PuG4USOrEdsFvbOxW2jp01zP+M=
|
||||
APhqKflZUhmgRCCocHNfF8cWLKWpGdW2cBFVB8esfaebcV8Bm5icApbL9u/SmCTp
|
||||
YA93D7bVXAwMe11nxv6BP/vWRwUT7PwlT8ufhs3UDnY7vkYUBvQW6UL1K9e7/UlQ
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
LOnQOFqU6PCy7YYVSPmkA0/gTFRU2H0d6T51/GWKhnQ=
|
||||
3KmFFXpaFcYe2PH7o19+Yp8xAODhI/vWpqDGX4Xxav/TPftCcwlJ2GSdqZRIVGoo
|
||||
R8K/Ndjw+sVUFzGFOCCgwyEgZIFazHPxG2rsbkC4Mic=
|
||||
NhnIR3Ilo4H2su9/cTNo/FK+qNAG19wxGrf6AaX5vF2MYvQpe0FpvROJQN48CKmo
|
||||
vdsIgxKEnw7wmXARhJ0Oc8wVF+V4koy8W2Mh858ZTYc=
|
||||
NhnIR3Ilo4H2su9/cTNo/ILZghLpbr5j/IZD/K8v92HhdXliUZ6LIaLGw2w1580v
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
4lN0LWBzLjgquvZLEoGU4VcBfkPRXV3AgETwRHgwx0A=
|
||||
CaVVGVWiTY/j3V1bwWG579Qd9AhVS9Fosq6m4Brd0nDzkmY9JVeKm8YUIUMgLZgj
|
||||
ww1k/N0gWysBJXBpYKUCHSY84nqsRk88NU0ho54XVr4=
|
||||
NhnIR3Ilo4H2su9/cTNo/PIphezILghaR2B05A8VC0vv8lXu5MHRtSnDBC+dvcGcG17D53H9BitReg2GU8a9Tw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
m4a/CtpjJ/nMVgLJWRwZXXRLpxxOovbcYxRSxZCtA6Y=
|
||||
NhnIR3Ilo4H2su9/cTNo/Gu9KOwC8SCkdYU8skYoE5Jmz6ywJ/AKKeZKyRVis9YBz+4SGikFp/xZOPqocMHyyQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
CQqNVWmwukkhI4nkdKzMzwBsOQ+4HbTh/BOPpsEZGY8=
|
||||
bpVtspxTF2OToZILoJ1fkG7rqYhfXtulnikcgwpk7TI=
|
||||
NhnIR3Ilo4H2su9/cTNo/HvYNwc7FmYMnVorYtJsgM7mPAX2E472V3DWt24sC8XW
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
RAcgdll7MZc9X2PbkeTvEzNyiOpuxHuwyFCiwlCwtBo=
|
||||
TcUpsBX6+7VrOYYb7aAQxi+cMqvbjHfbkHkvbweeOrI08YeWNRwxkPzTCz4gVzYxXfh+l8lWk7g+IZkT/aj/bQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
5wsVwKLrIjIWqeTNpSVp9X49wYIz3gKTqq7jnocq95Q=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
6d8NLnHX3WuS3g79bJvyhAwjLxzOvQmNis0aVGbhWo1EM3d+uiOHD4+CHNQr7OvntVC01SFgrSaWBjwpxSspMw==
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
zZQPiCGCqSDO70yiwDNUrrH8Q4B8051PjWqxvRD/6G+6mZgTSaRF/+5UQJBSfsOu
|
||||
yqM179SzW9HnBHozkU+IlX5lAmWuzrOJA3YvC3xIfCIyjZshemB/XWvy+C/nSc8W
|
||||
FFgrrvXvjrcz4wZcb8tZVMfl7bl/3so2ckZ8r41azARzhi5rZ6V/H3mosyOtQ6kI
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
eUSWcSfVc151c+2QfqQTIQ==
|
||||
/0ULpLqgTvInFD0r5hHANoosZ+xywkOR5dozStfmlYk=
|
||||
b4OJVZe8QyIpjuTpKXDL9A==
|
||||
wlLHv6kT3Q/RmtMBN4nDAd5ePG9boZZ1puX9EApi7waJ3F0rdpZHQ+QUGogqxN5a
|
||||
VmVrGQo2zRokW/ZuO9bN63zFN5O/w1krXKBn8bzERXc=
|
||||
VmVrGQo2zRokW/ZuO9bN684Ix5sFjdtWSuy9M2APYQQ2cloQs45uAs7g4ZITcnIAjpBDTpZ3BrLNJFEVqJ2ojctFGKKm/95hVbuFjYtJPeM=
|
||||
VmVrGQo2zRokW/ZuO9bN6xoaa3pLsxXyLdB8GbtG2YY=
|
||||
VmVrGQo2zRokW/ZuO9bN67Ap1Q6VmWnNlLMMqeDi80Doeyvhi/U8GBPp5HHWZTzv
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6/n7n61n7R9/9XTW7LSvopM=
|
||||
VmVrGQo2zRokW/ZuO9bN6/WTynACEFT8sdNdNup1kalU+7hlVh1zylFr4591OIGa
|
||||
VmVrGQo2zRokW/ZuO9bN6zPS0z48efxTbmV0uLaJMFk=
|
||||
VmVrGQo2zRokW/ZuO9bN60IbS8l3rE5TrRrNdfxL+kX3Pzn+FDHqKXiYJg1KgmXF
|
||||
VmVrGQo2zRokW/ZuO9bN6wAx5J8iv3RazhpXmncqnrreXiCOGawHQMNMjUs2cCVN
|
||||
VmVrGQo2zRokW/ZuO9bN67Y8U6ALWboELuY6YE4ad78=
|
||||
VmVrGQo2zRokW/ZuO9bN61Rjjiw/60bucMm5EHZzOcK7qzv28rP7g4n1B0Ie7pOW
|
||||
VmVrGQo2zRokW/ZuO9bN6w5+dIR4Ypp9Zft93+s5eE5/yPjP1yhzf5/NmchfJr6N
|
||||
VmVrGQo2zRokW/ZuO9bN623LqJlCkyXYwwCXSySz5FR7MI/uUVbwFRZ9X3HsyodA5+hN+HhvBEXoBRCHeMLs1w==
|
||||
VmVrGQo2zRokW/ZuO9bN6/TV8HYrXfBS0+5RislOy6/23foxSNNR4dF+wZRb5KjO9N7VJVsNrJmtWvnUeaVjrQ==
|
||||
VmVrGQo2zRokW/ZuO9bN69jIxF5VISZtC2vxWRknx7k=
|
||||
VmVrGQo2zRokW/ZuO9bN6x97Jv5sxc/lnlSc+X41DCbYX0L0DMlJm79khasZsmeDQfkyT4p1zevxzJpYBx1DNhDBrlR5/iGnPwmNZ1OvWwg=
|
||||
VmVrGQo2zRokW/ZuO9bN6ywyqAt0WUYk0wz2RaTbkeMb61E3V3fbNF4IaFu+N7qh
|
||||
VmVrGQo2zRokW/ZuO9bN6/TV8HYrXfBS0+5RislOy6+U+Hq91CX8KUds7Nh1ZOU8nWqPG53E9RBQ5qeqTEsFmw==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hkkt5RqaKznfoAozF2brEPS6
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hkmb7MAq4qksNIzY1Eh1Jjt9/P2MbO42SPrEoJqJGO8pbA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN628UWklFrPzPT9a+yjbUprIuuMwW0I9DnLu6OGQ2TxNu
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6+Z1kfdIPo4MYDXeXMYYWIYQQ4mrc936ju682bxyn+TqEoaQoeHhJgY1bOPJ6ik4QTAOiG9gx9IRwXfuCJtr3Ko=
|
||||
VmVrGQo2zRokW/ZuO9bN66gjfjrYMn+hEmToUiACtV8=
|
||||
mfT8DrNbUmxQ2BnZ1bZFTLh9MEuZKOpmAfF70OnZ9TU=
|
||||
s6ChnXH5zaR4nss2Jj7ULBibRmB/kmin0eYU9S2eTfU=
|
||||
ruTTNFTdswRs4Mc+srnRk818d9d/TGGXzgPjSrVtMi8=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
qx/2dn1Vpqs4SJaPnWiGqCi/4MihcwwKbYGKhk4naTAD8DbuTmd7DIaIioL9KkvbIcxbbjYAhP1Y/OUfj1mnGA==
|
||||
segQHXNRrJyLOuWc8JKC3tmNT7tyg3IVKLwZ3sHcdnRU1rBJqs6RBi6qg5fjkef3qFq/cbKaLNb11SHQv37cDw==
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
K0FOgK5mh0B5pEUVGx4wW2bJABs6gWPmt6Q9o3r8p6lGdFGrw5pIphcDNNDI4Pxe
|
||||
bIts5UhOLbX+5vrkUi2fEpgbk+KLUNd8ANhOjt2CA8S7qBtqBqrK7rtUY4QlsSDu
|
||||
St8jsnBszzKBMqXhq/bixnxiRXhroGzTpl2GmFXSnRkSxzNQsMXQGk8FOXJV6Y5r
|
||||
eeFiPlXUI0Fos82HYztSmaHvIBfKy6OirpgreAVZg6s=
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
4m1ZiBOyILBTSHQf//vyC0su8pHbpnlRDppIig8J5ysXeSTJP68Ri95UQiepxvh4
|
||||
WNTuVs53ESvy99Z9NIHHsQczMhznKv/xDqWjNZ9BqOGfNIc1eIJDK8jae1LRmist
|
||||
sYeCd0P8QwDZsXD2zsYtpwOQuFBJwQCwG7+G1aTUb7MU2KmH7QjCjojJgGohPv0RKMRm2E/yyqe7h2CjSXfM2VbeNDXk2k3QOsue23kQf9w=
|
||||
32pdC9DD05OE2l0oXazDFNsU+u4bMtJzvbtUKGSOKeSn9WvZrYyoyjfX7mEYUbe3
|
||||
lGY+HGJ/DlLufZHWWlj7U5mXaKcrxjwMdkooNruC2og=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
UNfQheD+zBxMB/8PVcAnPhJH0dABCf0LFLwey6F+PqLQAVJFMjnbXXReUGDMDEqKiYFfTP5la91cu1Qzw3WaLg==
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
NNh1PlSD8WUnUEbz+BU/P2UruqssNk4NnKN+47U1SH36F2BxurMzko0B0uYv45I9
|
||||
eeFiPlXUI0Fos82HYztSmSfbblmQRmW8NByKq0O3ixRZii1ssvDqpHtqdGo6blGV
|
||||
8ehs2Cqsj3GIU4YbS+kqMopjyYZACPJP3McICcxQ7QYvefmSdk7wQxP2oL97Q4vQ
|
||||
yqM179SzW9HnBHozkU+IlY0McOeVypQ/EYlVcJDFe0GlWr6WqLSH8YZJQ3Zl80pE
|
||||
8ehs2Cqsj3GIU4YbS+kqMpJNmQ5fFIbSdkmF260fowevNNXJ45tpcmfBJiEEZGw6
|
||||
NjU4zQ5DRyOHitK6CHLOgHN7CZ8aB+Mb5HQXfP+yO3ibTcrsbI4BMbGHj3qA0+h0
|
||||
NjU4zQ5DRyOHitK6CHLOgAOFCV3qwh/1iA/qlJwZgoGUD8smj9/Bg0H/hh9Oqg6m
|
||||
wOl7lRII4ZgqRTj9M//0bzhomxn10Rjo41lvXMmPQezzGWk3GyeNMpopZ/PorkQi
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
D9SFxmTjfXKVjBp30+qz3QUFQ0c/jfdN4cWLcYJvWW8cGcuYOqW+zTq/dn4uaKX5XJmBCPK7U+oFvA5D8u9eQEuYG8CwsAxp5IrQkGPd5mY=
|
||||
MQu48JkHralDtNXBUYl7lV0bLxYB+cVYGPW5I5H4uBmKn+X1vLJuCeoRB5MaCEB5bkAaA21+lVtVi8XnA5uCfg==
|
||||
VmVrGQo2zRokW/ZuO9bN63kQ7naUTUtv0ESWGx9rzIn/1UUCp4+jfPXGiX14BdBQ
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
hxgdAHD9AaIGGBvLsEuyB8PrRl5j0RLWnVrakTTrC+wYlY21ONwMz70K497xaqGJ
|
||||
HiVf4YuHR4gw4rFUUeRvK+5LSyMNmU1h13+cLC9tnC/y8cnqYfMBKdGAnQDTVZHb
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
O3CUgrw2GJfB+mDjH5+NdjDdFbdZzMNFPWLs5nIbjTo1SpgjDweH2KPbFtbB1QDS
|
||||
VmVrGQo2zRokW/ZuO9bN69uA6kygxk2cG8IYgdG9Pr0+kDHcaDqpPo1aFOqQ6eZcFBrY15aCLHK16jKxHqaXiw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6wcnkGR1Qyn1s8+CW5+MNtzRTbQfpmPYWYZ1Zix4ol4Or3JWa7MNuH8FVEl+/LFhBA==
|
||||
sobCGpmMf4/g7+HpPqBjC6hatZ6rUY3AAzqC73FJ58Q=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6ydgd98GwzWUciEurhqUbl5zFKBgTvp0P9ayAL5RaMdP
|
||||
VmVrGQo2zRokW/ZuO9bN65a4OFYGJXxFiOGSJivVxNq5a5scduUEPHPFtX2wTOnBqbjEynLbHNU89K1bs5Z0IYpgdoxUyCGS8wiq0EgiinY=
|
||||
VmVrGQo2zRokW/ZuO9bN620zSkiHBXev6YTvy3qjpOw=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN69NIyxsu9wL3ButjWi8Vd9WFqs0F/cbYpifzswbVj1XE
|
||||
VmVrGQo2zRokW/ZuO9bN65a4OFYGJXxFiOGSJivVxNqDts0LCwhPoG9qpww/bbUj9JcO334yYaFKIcL8wQwB6/PsreYi8O27v2MuAOqvCx0=
|
||||
VmVrGQo2zRokW/ZuO9bN620zSkiHBXev6YTvy3qjpOw=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6zLSeF3gHkc70v8wH1lH7V6izJDceK8v1VqgXLP7PPFh
|
||||
VmVrGQo2zRokW/ZuO9bN65a4OFYGJXxFiOGSJivVxNrIogcyFIfNvtgKGel1Eosz
|
||||
VmVrGQo2zRokW/ZuO9bN6wJqlk/efd+QgKBb45lQkEUJURJ6AXySYv+T873/0906R7ZDY/OqM+pHGZhlC5mTCLRAh2YSqtgcguEgy7g+lDE=
|
||||
VmVrGQo2zRokW/ZuO9bN620zSkiHBXev6YTvy3qjpOw=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN61W5fU8yZndDfCoUS7iF29y1q1oDpOjeucxethGOXiRJ
|
||||
VmVrGQo2zRokW/ZuO9bN65a4OFYGJXxFiOGSJivVxNoJZTLcbrqpw1/MqZAUh2h1
|
||||
VmVrGQo2zRokW/ZuO9bN6wJqlk/efd+QgKBb45lQkEU/1xIS7OZ8UVIpUgSlst3vnPzuyqFcv172ahiYDGVFzqHNYalk2K2+ZiH00yJrmFg=
|
||||
VmVrGQo2zRokW/ZuO9bN620zSkiHBXev6YTvy3qjpOw=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6zHe1AdyxhaUooAL+hUKQDTEHrKgluuXbnSBJQrzZUMq
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
6d8NLnHX3WuS3g79bJvyhFEcylaBQH0IUk+OusBE3my0xp9xwF5QGoWXAy5mxBYi
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
zZQPiCGCqSDO70yiwDNUrvU3PfyPPxNosxB0yTLMifo=
|
||||
yqM179SzW9HnBHozkU+IlX5lAmWuzrOJA3YvC3xIfCIyjZshemB/XWvy+C/nSc8W
|
||||
bWa5NLmMcRfP7/pL4TxwVVPLg0xyCs7rLJn7q0oXZoI=
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
b4OJVZe8QyIpjuTpKXDL9A==
|
||||
ACEEdgL/kNbx7RaZcSRxZATKpSMTQ/cWmiIi7MZqRD3iHlJkfgQKP2ZXgOycctOR
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
PRG/YRzXVD8iVR3bzEcUnm+txOUxEzRjM53h5sTJkBazFR7SuI0t8ZpzuPGzrZlm
|
||||
wlLHv6kT3Q/RmtMBN4nDAaa/4pYRsvL7819NLBZ1Jsk=
|
||||
VmVrGQo2zRokW/ZuO9bN6w1AyfvV+/TKcjbtKlFZIXTurM+4yW7LDThX3d58hOXr
|
||||
VmVrGQo2zRokW/ZuO9bN69h0W3AGoL6Fh678416+Hu2KoilysLPFqxJJbiCWg0kt
|
||||
VmVrGQo2zRokW/ZuO9bN63zFN5O/w1krXKBn8bzERXc=
|
||||
VmVrGQo2zRokW/ZuO9bN66vfklQEmoLc3ecqJIXu87NMH8vbZoK4tpkEq8BGvWvlPTpczQ026/C1jKPPSYdvzg==
|
||||
VmVrGQo2zRokW/ZuO9bN66SC7guo6F2BUtjo1cx7Weub6mMMOadJGmLmKcw75lpb
|
||||
VmVrGQo2zRokW/ZuO9bN6xoaa3pLsxXyLdB8GbtG2YY=
|
||||
VmVrGQo2zRokW/ZuO9bN6/VW4n84N+xmKyiHoJANXzc=
|
||||
mfT8DrNbUmxQ2BnZ1bZFTLh9MEuZKOpmAfF70OnZ9TU=
|
||||
s6ChnXH5zaR4nss2Jj7ULBibRmB/kmin0eYU9S2eTfU=
|
||||
VMfVrQporTLzVAs+KagENs0jVofd/mPyGKFNcwoEK/8=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
6d8NLnHX3WuS3g79bJvyhORIPeJCp4wWVvEEOwBGJbMQ9B8g68lVqaXG7/c8sCgL
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
zZQPiCGCqSDO70yiwDNUrn/Ahs5WLg1NPCie3zGShu1/wSHjnFYLODLD25lQA5x1
|
||||
yqM179SzW9HnBHozkU+IlX5lAmWuzrOJA3YvC3xIfCIyjZshemB/XWvy+C/nSc8W
|
||||
8ehs2Cqsj3GIU4YbS+kqMtuucPAdJ1i3hn/BkXRR/b8uF7yzHSGAxk7z1KZFvBTC
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
b4OJVZe8QyIpjuTpKXDL9A==
|
||||
PWKGbNEPxxxpGpe8THO242QunNNWnvbBCn+iC2oElyc=
|
||||
VmVrGQo2zRokW/ZuO9bN66b1EQBxDDTQrHy92SlIikM=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
JlxIfINDpIN74VOPKABZW2ra44tSxs0ZLHEM/U3b4xykot9XDTMkG244y4YCVtPy2qfh3Sl0bgJRhkuNbAnsLw==
|
||||
YA93D7bVXAwMe11nxv6BP/8iLYI7Aa2oVDOTO+f6qRg=
|
||||
VmVrGQo2zRokW/ZuO9bN66Hq/Y+eYT69h50gLi7IyQOOipSIQ7Q/7rFMIt1AIZov
|
||||
VmVrGQo2zRokW/ZuO9bN69h0W3AGoL6Fh678416+Hu2KoilysLPFqxJJbiCWg0kt
|
||||
sobCGpmMf4/g7+HpPqBjC6hatZ6rUY3AAzqC73FJ58Q=
|
||||
VmVrGQo2zRokW/ZuO9bN69tIcUnkZWsvMTtwyCmn6vvN9UwZdc3KUcaB2lz6Du2A
|
||||
VmVrGQo2zRokW/ZuO9bN69h0W3AGoL6Fh678416+Hu2KoilysLPFqxJJbiCWg0kt
|
||||
mfT8DrNbUmxQ2BnZ1bZFTLh9MEuZKOpmAfF70OnZ9TU=
|
||||
s6ChnXH5zaR4nss2Jj7ULBibRmB/kmin0eYU9S2eTfU=
|
||||
VMfVrQporTLzVAs+KagENs0jVofd/mPyGKFNcwoEK/8=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
6d8NLnHX3WuS3g79bJvyhDsDXpgsqOpbKETjou9WOZPcc1elPxQh9cS821Ok3bVbCXSJ8u7r7Ro1XiEX76I/iw==
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
zZQPiCGCqSDO70yiwDNUrj777l5BTo9eCcYE6KEhGN3qR2uRts9okQ1lptsdQWtg
|
||||
yqM179SzW9HnBHozkU+IlX5lAmWuzrOJA3YvC3xIfCIyjZshemB/XWvy+C/nSc8W
|
||||
yqM179SzW9HnBHozkU+IlY0McOeVypQ/EYlVcJDFe0GlWr6WqLSH8YZJQ3Zl80pE
|
||||
8ehs2Cqsj3GIU4YbS+kqMpJNmQ5fFIbSdkmF260fowevNNXJ45tpcmfBJiEEZGw6
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
b4OJVZe8QyIpjuTpKXDL9A==
|
||||
jPjjou9VNwkRtlQvS7IMwT61DiJZ1n7ABVvC8lImM1GTyercqKulHtnPhz5LMb0WCoJOixq+LHAXxH4az57sJQ==
|
||||
J1UGlXkKhKXD36OrXXhN8LEiN+9Y+rPtU094/lpWCJkzL91nJbwePJFLFNxcU7a0SlIO5OZ3MwAWum4zIjkPgg==
|
||||
VmVrGQo2zRokW/ZuO9bN66b1EQBxDDTQrHy92SlIikM=
|
||||
mfT8DrNbUmxQ2BnZ1bZFTLh9MEuZKOpmAfF70OnZ9TU=
|
||||
s6ChnXH5zaR4nss2Jj7ULBibRmB/kmin0eYU9S2eTfU=
|
||||
VMfVrQporTLzVAs+KagENs0jVofd/mPyGKFNcwoEK/8=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
6d8NLnHX3WuS3g79bJvyhLHqHL4jLTDrGAIPR+WsUzXEFIbEmBGSwvvQLutL0dFcpH0AUPQoXrj49knrv9+d+g==
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
zZQPiCGCqSDO70yiwDNUrm7HG9OhPLBhZEBfEtqJxcB/kpanL2zAPOvr56+W9KHv
|
||||
yqM179SzW9HnBHozkU+IlX5lAmWuzrOJA3YvC3xIfCIyjZshemB/XWvy+C/nSc8W
|
||||
NjU4zQ5DRyOHitK6CHLOgHN7CZ8aB+Mb5HQXfP+yO3ibTcrsbI4BMbGHj3qA0+h0
|
||||
NjU4zQ5DRyOHitK6CHLOgAOFCV3qwh/1iA/qlJwZgoGUD8smj9/Bg0H/hh9Oqg6m
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
b4OJVZe8QyIpjuTpKXDL9A==
|
||||
YdTM5cWYAsOq9968GjmEIn458PkySNd5GOJg2QjTSgkgpn8VUITEbXvbBG+yQJ0k
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
gZ7BoIAABc+I8g/rYzq+f9fH+SgIZsS8Qfv+e480JkPCt3tQj/PL+v5Tjao1wdEQSyGpe2xx/8OpBGm95SqEpA==
|
||||
VmVrGQo2zRokW/ZuO9bN66b1EQBxDDTQrHy92SlIikM=
|
||||
mfT8DrNbUmxQ2BnZ1bZFTLh9MEuZKOpmAfF70OnZ9TU=
|
||||
s6ChnXH5zaR4nss2Jj7ULBibRmB/kmin0eYU9S2eTfU=
|
||||
VMfVrQporTLzVAs+KagENs0jVofd/mPyGKFNcwoEK/8=
|
||||
|
||||
+287
-287
@@ -1,287 +1,287 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: cjxin <cjxin@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
import copy
|
||||
import random
|
||||
# 获取目录大小
|
||||
#------------------------------
|
||||
import sys, os
|
||||
import json, os, time, re
|
||||
|
||||
import public
|
||||
from filesModel.base import filesBase
|
||||
|
||||
panelPath = '/www/server/panel'
|
||||
os.chdir(panelPath)
|
||||
|
||||
|
||||
class main(filesBase):
|
||||
_exe_cmd = 'ncdu'
|
||||
# 扫描历史
|
||||
log_path = '{}/data/scan/'.format(public.get_panel_path())
|
||||
# 缓存
|
||||
cache_file = '{}/config/scan_disk_cache.json'.format(public.get_panel_path())
|
||||
|
||||
def __init__(self):
|
||||
self.is_use = False
|
||||
if os.path.isdir("{}/plugin/disk_analysis".format(public.get_panel_path())):
|
||||
self.is_use = True
|
||||
if not os.path.exists(self.log_path):
|
||||
os.makedirs(self.log_path)
|
||||
if not os.path.exists(self.cache_file):
|
||||
public.writeFile(self.cache_file,"{}")
|
||||
if os.getenv('BT_PANEL'):
|
||||
self._exe_cmd = '{}/plugin/disk_analysis/ncdu'.format(panelPath)
|
||||
|
||||
def get_path_size(self, get):
|
||||
"""
|
||||
@name 根据排除目录获取路径的总大小
|
||||
@param path 目标路径
|
||||
"""
|
||||
if self.is_use is False:
|
||||
return {"code": 404, "status": False, "msg": 'Please install [Disk analysis] first !'}
|
||||
path = get.path
|
||||
is_refresh = get.is_refresh == "true"
|
||||
|
||||
real_path_dict = {} # 软连接处理
|
||||
temp_path_list = []
|
||||
for path in str(path).split(","):
|
||||
r_path = os.path.realpath(path)
|
||||
if r_path != path:
|
||||
real_path_dict[r_path] = path
|
||||
path = r_path
|
||||
if path != "/": path = str(path).rstrip("/")
|
||||
temp_path_list.append(path)
|
||||
|
||||
try:
|
||||
cache_data = json.loads(public.readFile(self.cache_file))
|
||||
except:
|
||||
cache_data = {}
|
||||
|
||||
result = {}
|
||||
|
||||
path_list = []
|
||||
if is_refresh is True:
|
||||
path_list = temp_path_list
|
||||
else:
|
||||
for path in temp_path_list:
|
||||
if cache_data.get(path) is not None:
|
||||
result[path] = cache_data.get(path)
|
||||
else:
|
||||
path_list.append(path)
|
||||
|
||||
if path_list:
|
||||
scan_path = path_list[0]
|
||||
if os.path.isfile(scan_path):
|
||||
scan_path = os.path.split(scan_path)[0]
|
||||
for path in path_list[1:]:
|
||||
while True:
|
||||
if path.startswith(scan_path):
|
||||
break
|
||||
scan_path = os.path.split(scan_path)[0]
|
||||
import string
|
||||
code = "".join(random.sample(string.ascii_letters + string.digits, 8))
|
||||
result_file = '{}{}'.format(self.log_path, f"temp_scan_size_{code}")
|
||||
scan_time = int(time.time())
|
||||
exec_shell = "{} '{}' -o '{}' ".format(self._exe_cmd, scan_path, result_file).replace('\\', '/').replace('//','/')
|
||||
public.ExecShell(exec_shell)
|
||||
scan_result = self.__get_log_size(result_file, path_list, scan_time, cache_data)
|
||||
os.remove(result_file)
|
||||
result.update(scan_result)
|
||||
public.writeFile(self.cache_file, json.dumps(cache_data))
|
||||
for r_path, path in real_path_dict.items():
|
||||
result[path] = result[r_path]
|
||||
del result[r_path]
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def __get_log_size(cls, log_file, path_list, scan_time, cache_data):
|
||||
"""
|
||||
@name 获取文件或目录大小
|
||||
@param log_file 日志文件
|
||||
"""
|
||||
result = {}
|
||||
for path in path_list:
|
||||
result[path] = None
|
||||
data = public.readFile(log_file)
|
||||
data = json.loads(data)
|
||||
data = data[-1]
|
||||
root_path = data[0]["name"]
|
||||
if root_path in path_list:
|
||||
result[root_path] = data
|
||||
else:
|
||||
cls.__get_sub_size(data[1:], root_path, path_list, result)
|
||||
for path,info in result.items():
|
||||
if info is None:
|
||||
continue
|
||||
if isinstance(info, dict):
|
||||
info["type"] = 0
|
||||
info["asize"] = info.get("asize", 0)
|
||||
info["dsize"] = info.get("dsize", 0)
|
||||
info["dir_num"] = 0
|
||||
info["file_num"] = 0
|
||||
info["total_asize"] = info.get("asize", 0)
|
||||
info["total_dsize"] = info.get("dsize", 0)
|
||||
info["stime"] = scan_time
|
||||
cls.__get_stat(path, info)
|
||||
cache_data[path] = info
|
||||
else:
|
||||
cls.__get_dirs_size(info)
|
||||
cls.__get_stat(path, info[0])
|
||||
result[path] = info[0]
|
||||
result[path]["stime"] = scan_time
|
||||
cache_data[path] = result[path]
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def __get_sub_size(cls, data, root_path, path_list, result):
|
||||
"""
|
||||
@name 获取子目录数据
|
||||
@param id int 记录id
|
||||
@param path string 目录
|
||||
"""
|
||||
if len(path_list) == 0: return
|
||||
for val in data:
|
||||
if isinstance(val, list):
|
||||
sfile = f"{root_path}/{val[0]['name']}".replace('\\', '/').replace('//', '/')
|
||||
if sfile in path_list:
|
||||
result[sfile] = val
|
||||
path_list.remove(sfile)
|
||||
if len(val) > 1:
|
||||
cls.__get_sub_size(val[1:], sfile, path_list, result)
|
||||
elif isinstance(val, dict):
|
||||
sfile = f"{root_path}/{val['name']}".replace('\\', '/').replace('//', '/')
|
||||
if sfile in path_list:
|
||||
result[sfile] = val
|
||||
path_list.remove(sfile)
|
||||
|
||||
@classmethod
|
||||
def __get_dirs_size(cls, dirs_list):
|
||||
"""
|
||||
@param info 目录信息
|
||||
@param result 结果
|
||||
"""
|
||||
dir_info = dirs_list[0]
|
||||
dir_info["type"] = 1
|
||||
dir_info["asize"] = dir_info.get("asize", 0)
|
||||
dir_info["dsize"] = dir_info.get("dsize", 0)
|
||||
dir_info["dirs"] = 0
|
||||
dir_info["files"] = 0
|
||||
dir_info["dir_num"] = 0
|
||||
dir_info["file_num"] = 0
|
||||
dir_info["total_asize"] = dir_info.get("asize", 0)
|
||||
dir_info["total_dsize"] = dir_info.get("dsize", 0)
|
||||
for info in dirs_list[1:]:
|
||||
if isinstance(info, list): # 目录
|
||||
dir_info["dirs"] += 1
|
||||
dir_info["dir_num"] += 1
|
||||
cls.__get_dirs_size(info)
|
||||
temp_info = info[0]
|
||||
dir_info["dir_num"] += temp_info["dir_num"]
|
||||
dir_info["file_num"] += temp_info["file_num"]
|
||||
dir_info["total_asize"] += temp_info["total_asize"]
|
||||
dir_info["total_dsize"] += temp_info["total_dsize"]
|
||||
else:
|
||||
if info.get("excluded") == "pattern":
|
||||
continue
|
||||
dir_info["files"] += 1
|
||||
dir_info["file_num"] += 1
|
||||
if info.get("asize") is None: info["asize"] = 0
|
||||
if info.get("dsize") is None: info["dsize"] = 0
|
||||
info["type"] = 0
|
||||
dir_info["total_asize"] += info["asize"]
|
||||
dir_info["total_dsize"] += info["dsize"]
|
||||
|
||||
@classmethod
|
||||
def __get_stat(cls, path, info):
|
||||
if not os.path.exists(path):
|
||||
info["accept"] = None
|
||||
info["user"] = None
|
||||
info["mtime"] = "--"
|
||||
info["ps"] = None
|
||||
return
|
||||
stat_file = os.stat(path)
|
||||
|
||||
info["accept"] = oct(stat_file.st_mode)[-3:]
|
||||
import pwd
|
||||
try:
|
||||
info["user"] = pwd.getpwuid(stat_file.st_uid).pw_name
|
||||
except:
|
||||
info["user"] = str(stat_file.st_uid)
|
||||
info["atime"] = int(stat_file.st_atime)
|
||||
info["ctime"] = int(stat_file.st_ctime)
|
||||
info["mtime"] = int(stat_file.st_mtime)
|
||||
info["ps"] = cls.get_file_ps(path)
|
||||
|
||||
@classmethod
|
||||
def get_file_ps(cls,filename):
|
||||
'''
|
||||
@name 获取文件或目录备注
|
||||
@author hwliang<2020-10-22>
|
||||
@param filename<string> 文件或目录全路径
|
||||
@return string
|
||||
'''
|
||||
|
||||
ps_path = public.get_panel_path() + '/data/files_ps'
|
||||
f_key1 = '/'.join((ps_path,public.md5(filename)))
|
||||
if os.path.exists(f_key1):
|
||||
return public.readFile(f_key1)
|
||||
|
||||
f_key2 = '/'.join((ps_path,public.md5(os.path.basename(filename))))
|
||||
if os.path.exists(f_key2):
|
||||
return public.readFile(f_key2)
|
||||
|
||||
pss = {
|
||||
'/www/server/data': 'This is the default data directory of the MySQL database, please do not delete it!',
|
||||
'/www/server/mysql': 'MySQL program directory',
|
||||
'/www/server/redis': 'Redis program directory',
|
||||
'/www/server/mongodb': 'MongoDB program directory',
|
||||
'/www/server/nvm': 'PM2/NVM/NPM program directory',
|
||||
'/www/server/pass': 'Website BasicAuth authentication password storage directory',
|
||||
'/www/server/speed': 'Website acceleration data directory',
|
||||
'/www/server/docker': 'Docker plugin and data directory',
|
||||
'/www/server/total': 'Website monitoring report data directory',
|
||||
'/www/server/btwaf': 'WAF firewall data directory',
|
||||
'/www/server/pure-ftpd': 'ftp program directory',
|
||||
'/www/server/phpmyadmin': 'phpMyAdmin program directory',
|
||||
'/www/server/rar': 'rar expansion library directory, will lose support for RAR compressed files after deletion',
|
||||
'/www/server/stop': 'The website deactivates the page directory, please do not delete it!',
|
||||
'/www/server/nginx': 'Nginx program directory',
|
||||
'/www/server/apache': 'Apache program directory',
|
||||
'/www/server/cron': 'Scheduled task script and log directory',
|
||||
'/www/server/php': 'PHP directory, all PHP version interpreters are in this directory',
|
||||
'/www/server/tomcat': 'Tomcat program directory',
|
||||
'/www/php_session': 'PHP-SESSION isolation directory',
|
||||
'/www/server/panel': 'aaPanel program directory',
|
||||
'/proc': 'system process directory',
|
||||
'/dev': 'system device directory',
|
||||
'/sys': 'system call directory',
|
||||
'/tmp': 'system temporary file directory',
|
||||
'/var/log': 'System log directory',
|
||||
'/var/run': 'System running log directory',
|
||||
'/var/spool': 'system queue directory',
|
||||
'/var/lock': 'system lock directory',
|
||||
'/var/mail': 'system mail directory',
|
||||
'/mnt': 'System mount directory',
|
||||
'/media': 'System multimedia directory',
|
||||
'/dev/shm': 'system shared memory directory',
|
||||
'/lib': 'system dynamic library directory',
|
||||
'/lib64': 'system dynamic library directory',
|
||||
'/lib32': 'system dynamic library directory',
|
||||
'/usr/lib': 'system dynamic library directory',
|
||||
'/usr/lib64': 'system dynamic library directory',
|
||||
'/usr/local/lib': 'system dynamic library directory',
|
||||
'/usr/local/lib64': 'system dynamic library directory',
|
||||
'/usr/local/libexec': 'system dynamic library directory',
|
||||
'/usr/local/sbin': 'System script directory',
|
||||
'/usr/local/bin': 'System script directory'
|
||||
|
||||
|
||||
}
|
||||
if filename in pss: return "PS:" + pss[filename]
|
||||
return None
|
||||
QRASP55VO/1DQ98p1csw9A==
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
dBZyCsfrbwqvA0sbdGrIGg==
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
n+0ptngHIPIjFuMNQ53bfj+Na/fdhk6k1yTpAwW7j353Dw920mEqQQZjykAHeRmp0ZD/P3ftGifsmPOMf2b7XdEqyZH0yl9kjaUugj3dYPI=
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
jh3cxzkA2htccqfZRKAUdI8r17q57nOGP4OxbJlL1NAnrF4weHnS0MpT6C6jbrX5
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
2unYDUJ7AQka0zNDbcMACQ==
|
||||
PDg4EOFKN+dK2UrpwNWHLw==
|
||||
svfNqiZI0zsAZVvJZhVKxDnsn+e2c8eSwsWdNJ9ryew=
|
||||
I8MGJUwtjfcKc5w4E0SmjHwLsErBQ84ek459TV1n0Iir/P4mdpfwDI34s6+8CBN0
|
||||
Sm95VfslcvrZUo7dRR9Ibg==
|
||||
1in3eluyrI5kuyCXT4wxGR0BSfUj5K16kanLx7m3x4E=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
XIfdJ79nObMM+vyAmKbTmw==
|
||||
X9BNoFOwiQAnMPqEk6FnbzU/oA+chL/aEAzGH80mBrNNxRMBdiGPqgDUeLF6rer2
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VD9zfcC25A/8QOaHOhC/08+yyCMXeBqRf4/ga7jFrTkT7C7mOGjvtRvT5O1nKry9
|
||||
P8yT4+bsOs+HQJp87m1F/reOtBiqflci0dOv1dBJ5CE=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
CjJS7KrzKM18mlLqJK9jKTB717Vvrubu5ix9tb047ao=
|
||||
02raNMOqWaNt7xMESPC3lwgVxysXSXHuDQdM35j2P78=
|
||||
20lLzEXEs+ueAd+bOAB+91r8jzaQl96Rr4UooYVAhek=
|
||||
9UNCW/IYJm3y0yDOfWJu1hDSEjrLqqinLz9ENpiz7Bp7U6FvhbSHpw2fG7yfwZm2o8XmdX7QFCP6PAgeC3qwLA==
|
||||
5C9WmrmzTMoEG9WnQlXcow==
|
||||
7dl/3jjStHv3YKwNaOrbP+Oo5xU5m7MdajxYoJc85S92TEuqkIbRI+ohiQ6vWWtZzZM2CO+G/Tt7tZ9oQFyeGBfi+jfxFGgmnYMxeUi1JaJixQo/7XHqj5ninApCrSrr
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
9GxZpCRwMRDPejWR2Vvf+LKn0tNtFKp8Eh2tnr4Da9U=
|
||||
OV1bY3WjlWolVVGpf7K0XuXsoXQHr87ax8nvHq6xsHk=
|
||||
WHkOzVx7seuLmxs5Hu+l/t+vqO/0m+n9UCf5LD77H/SwGtkYMMmsF4cVmuhhatEVLh7WBABwVLMyOLWUBB+RadwWiICXHtE1kzcSxcgplF89E4ZHUf3MK6MmlUz6ew99
|
||||
32pdC9DD05OE2l0oXazDFBSGVTBsjpcBhCs4oxG+0yc=
|
||||
wgR07xfoapmx6eEnFHXXYrIeMJaP3Lg2M3zaGXD/L9jMBZ/1Gnw5H1SVochJBBx+
|
||||
NqhMbY8+EQI8zhTG6Zh2I8eIwd9vy9oCMj+HlVpAR/l7CFW4GiuliNJFtFnBA50C
|
||||
wgR07xfoapmx6eEnFHXXYrIeMJaP3Lg2M3zaGXD/L9iDQP8kO4z+Nh9k9xWY+COM/KxrWvWZ4Fal5fq021KjFA==
|
||||
xWoGNWjKGPfI4gq8aHoTfBq1oaYa956TFzYuHTbqc+nolHQ42C9PtbiSn1F6OlCtRmnEtWURclz1HQwAElCBzw==
|
||||
NHEVGZTYwXqY5vJLoK2Wy88Jwk3YGlNccZ+9V9zZnU+eb80uFKXdlJTW19PQSswv
|
||||
32pdC9DD05OE2l0oXazDFCUyxYReX+Pd+b7Itml48JbsM7EEkGoW/LLDCJHqhTgLDQkOzUwuHM/Ow28K/8sDHIyBKBfp8UiP7Spf6jDWw6w=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
doXPckCdzE7wjT67BB6bRaf5yMsyg97qMshMoQ7p5vyoCIqIGhDYBeIX7pK+6SIf
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
2e9aPy7fN0yHEJSt/vm4HRBZEsq1/zwflCBuSjOe7lpc8+97QgE8TmPh9W3s4bjTFqkssBBzUB3kSkpHlHBB8A==
|
||||
eeFiPlXUI0Fos82HYztSmdKUUr+D7SPt33f2BsZZi0+Z/4tXriyUkCyekpFOTLlk
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
MzOj4ZiBOJDNVP8vi/lFQNbYGt1FVk3Is6YVV6wzt87cMUguwHtxV3/Xy4LTsg2e
|
||||
L0eUthVnpkGsmKFAX6d+uEP20LPBDczIBUCH+eDLR4XWtYJ6VE0yMGgVZeHE55+Q/qVjwg2ycnFdmwmE1t4pQK7rMwd5XeH6SKf0j0LJj1rcjuZWiUfgbRgMQOHfmWeVoHXJd8Gdujzjmu8XVaU3Yg==
|
||||
5zgvKM85O5RcGwttJ2rWIPdwxXoXLnOjmhL6DYLhvpA=
|
||||
R7vEIxyjiiVKR30PQVdBXTc3ZCpAzCM1mvOBtDg5HBdxFY32n+U4Vd4HmL3xGJ0J
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
ziQs1GyPUQ7zPh2xP+c4C9jWdniwpr48mYVqFpshpfPIMeXmT5sEphPHgd7xjv51
|
||||
ygXqV8JYtXUVMKjwSB6Bx/HL/6ZwOKweTtEx9fTOy34=
|
||||
RDZxR0eU/0YxwhYtovyGeVmHi5rJUJIHwjySNLmeLsS/YgiTjCQe80TqXYEeRodv
|
||||
diZ40h9D+5PatJtYF1tU0duwNTXVBazmSgO2LE1bzRxihfbnQEKkYw7WpzZBa6M4
|
||||
UbJuac0dxLiN+5ocS3w2vVbjWbzmARN1Q6nZRO+hN/U=
|
||||
VmVrGQo2zRokW/ZuO9bN66bxma0YBg8TGr7zrmdMIaysrwI2tOjz2KGqNWCW4fyv
|
||||
VmVrGQo2zRokW/ZuO9bN64fCWnvBG95BbHi3cQzmuAc=
|
||||
n/Vg/an64od1JqfYD8zjtnTgUj5eucdPqy9I4MCTvJdvKMaMV+njWEGl8CrMjCbman94UdMu8eZchGcaRr1oYw==
|
||||
A7tBmpCaSLjSrSFXFx4rD5DetX8LfpTB33kFqMYK0Od6ZH8Gs/Y11F09RX46+ICL
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
b4OJVZe8QyIpjuTpKXDL9A==
|
||||
7jSw4GB3eBRbmC1MzdtYH7AtgesWi6JQAvIQf6OzE3nseJy0QnGK6G6JTZ8m4DdlPAzSNTALqHevuq2kA19SCpPCP9OhqpP+gq0PaqyDu7o=
|
||||
mfT8DrNbUmxQ2BnZ1bZFTLh9MEuZKOpmAfF70OnZ9TU=
|
||||
7jSw4GB3eBRbmC1MzdtYH8hFhUduGUWsUH3mRmUlIWM=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
/0ULpLqgTvInFD0r5hHANoosZ+xywkOR5dozStfmlYk=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
7S/W1w5l8hNVTCb+pjBU6IQBp7oTWR1btD/WKY+MFgg=
|
||||
nI4TFpKsgYpjAeaQko6KTiS9GERA58xL2uQkIWwz+8U=
|
||||
9uZN8r0CKVAbfzGtFDuvLxswrINnjWvMwuMvv7mQFLJ/lDrB0Yzi1jeGmHGjb9sx
|
||||
l2FJPs4YkAmmok1ulDRuSA==
|
||||
wlLHv6kT3Q/RmtMBN4nDAf5jouZDDJebuZx0e+GqD0kRo3kF/7jgrUa9LjtTIi7k
|
||||
VmVrGQo2zRokW/ZuO9bN63WXNO21aDfpqHWqTMbiAspwMoEKToJ9evkuxTBcHidMf81BXfmdf+zT9d8k7rZRQQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6xFqwj56iFFIvII+sEi91i3uqenZ1RukB/iwA5+BqIZ4sn4SaQnBu9P1A4Q+K1sZtQ==
|
||||
VmVrGQo2zRokW/ZuO9bN65hAGaICagbU0z0X3nArVjY=
|
||||
VmVrGQo2zRokW/ZuO9bN6zviB9IGvmdqavzf213hyy5ybw9UFAPNCxKWXRAzML9G
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
WJAfjl0WrD5Jtca2LHLz1bmB1KYomdySnhMTj+CfBFQ=
|
||||
X9N2KsRYiOx20Z7QjlcKwPlYTqzzndgDM6lpBv04BpdP5Pg3w1osXEPQndKx0rQg
|
||||
O3CUgrw2GJfB+mDjH5+NdjXyt5QeWCsfAO3Xba+4ChG/q7Y+X5y6P+nc7wDmMC42
|
||||
VmVrGQo2zRokW/ZuO9bN62VgOORuMBXqkUitwmHVIrDnse5ewM1R/I5hzCpTRGjRPjKi5jw4W/gnKcBGD9YBwg==
|
||||
wlLHv6kT3Q/RmtMBN4nDAb3TgOhh+jcLpHwNqZ402ohizeRChhJH0mnfBvfdrTFZ
|
||||
VmVrGQo2zRokW/ZuO9bN632VflaKbWaV9Wa8IOB78Qk=
|
||||
VmVrGQo2zRokW/ZuO9bN6423Hrz4GlH+nD6sJ78NwiKP8lp8FUcPhY9VQRWbCG1fwt6D/Suz+3Mw4fD7HRaoaw==
|
||||
VmVrGQo2zRokW/ZuO9bN69qqX19RJUeMAQ5O8TuJCvc=
|
||||
VmVrGQo2zRokW/ZuO9bN69ZI8jvRenlEUWjnEq2NCPyDOWUWUPrjde05ZcnIjqs3pWRoX/dFNNNs2i/oTDcoYA==
|
||||
p9oVsBgcyiBMjDb8CcPOqP1vx7YoaEO9HCXBZO2TNso=
|
||||
Ds0U5vkLcQbSiWM0OBg+t4r9+nkADB6+pTfs6BnR2ZxqURGwpq1kta+TPw+SFYxBQFmX+7Si0OBWn9a+xTaiWnluFS3e3tzgqB5tisWnRARhFcyQwPYfaZhQ4qC+koZE
|
||||
o6QhOIN2Sc4SHELnst17uev8ILgDsE8F6Lr4r3FiO5kX4kPxG5GWPpKuy8MG+3Pp5ak0QKFbZROCqcYHAtfrS5iit3HYIQ4qteW8Mhs5eEUKNbIOTh/MQvOi25rbe0W/
|
||||
X9N2KsRYiOx20Z7QjlcKwJ/jTfZo3KZRc7Jt0Yxl4gCUzaVNOZtVdc33LG13QSPt
|
||||
dAlD/BDiyhUNR82MoKY54wOQA9Y9TRrid6IAzqKFFYlKwy9skQ3yRe3T15WYhesi1YWjlAGeJABXbkoJuF6IIk7XVJH7co5nkqJxZSD49Qxzny6hNig6oVk/d6uY6w1QCaRfrBs5nTcMZExJVAB7WmDhGKieI8G2bZn9lROj5A4=
|
||||
xWoGNWjKGPfI4gq8aHoTfM/GWNK1ohgau/P6Yy5hh4NxJd/Z/S8GTdLTsA9JjQHV
|
||||
X9N2KsRYiOx20Z7QjlcKwI4qbj7KfnKOrIFv7Z4lLtGUYNfIhUqPnWQkQbUEaS3fINZ8F83Vu3A+GF1Unidx3ROcHOnR+dfswdftnV7DDxk2JxMxGEO/rdyz4HhDx1HR
|
||||
gC7pmugJ3/w5trYRkDiKMZu2feMB3hGfqRh2TQebwmSMQbtzCVrS+b4WQ4vQR9dB
|
||||
o6QhOIN2Sc4SHELnst17uZEi6P73uFYiKT8ZfdKaq74uZIFYFu8J6CF85QIftAeI
|
||||
xWoGNWjKGPfI4gq8aHoTfBq1oaYa956TFzYuHTbqc+kuoHiBgr/0Fv8qNCoSuQiv1gF3L0eu9kJUZmaEmUpN5x4xDhiRRncANufGyvnI5q4=
|
||||
5eMaCO4xAK2QW4QfX+0YtKbMF1jS3cxAAkXneuE7di9ABuvCVnZ4SdZbeTDi2qoaSmKkDI5m7fh2F112P2pzKA==
|
||||
o6QhOIN2Sc4SHELnst17udxbOsHgV61axCR3P3wfex8g46ZP1Sdx4i+CYHMTr6rl
|
||||
pZu1Giln7AYpCOrLbI27d9Gmita51EFD9OUkFL56AbY=
|
||||
ruTTNFTdswRs4Mc+srnRk818d9d/TGGXzgPjSrVtMi8=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
+qdJgONcot1WKgm0a/QSWRfjD/63UhGjDDaD83ombAk=
|
||||
k7Mgm/6UlihxNIWiDi7/FQWsPKdojVfNRBOtHAgYqheCYcsU4cUBPL/6I95dDtlT9USt45h9FK4d7rl/Yz+V2cXy5SkFT71kfnrU3MZE6nE=
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
NNh1PlSD8WUnUEbz+BU/P3oJY/mwDRD7KWNhsy6/Y2mb4RNPwLuEAcMxo+t3fDjM
|
||||
bIts5UhOLbX+5vrkUi2fEgVzsPbCG1s61jTt5yW6ACsP1ywsg+01aUDIv4DP01qd
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
/0ULpLqgTvInFD0r5hHANoosZ+xywkOR5dozStfmlYk=
|
||||
RDZxR0eU/0YxwhYtovyGeVX2L0QGVwLQX8TIwLObEVs=
|
||||
o6QhOIN2Sc4SHELnst17uQC18YJWaV/6CEkrqfg0jS20MlFgiNUSShqPpoyfxdJZ
|
||||
HNr5/wGY+7coHgowTe94Ll4RZO1qTURSl37kSeltNLP9Vb6jtwiW6YkMWV99p4O4
|
||||
gEJ/mwYAYmzZtF+bOEtqdkC8SHP+P7fOYSe7UxEq8rmitn+SghIfUQayzs5YBbRY
|
||||
nWJfxfGKXK3M33nhNtnE4rhyN+G2GEkqT49HwMRlHEY=
|
||||
Vh41Si6Af7eSg+/W8dfTM7yg2G8U6j8xv+R+xKztdB06IZseCUPYnwY/NdWIvEVs
|
||||
emk1Y/Al74+4sZ82aqgV0lhGJemXCaG1r29Gpu+zhWmouexK5AYktd5VzhuOMg2z
|
||||
o6QhOIN2Sc4SHELnst17ufzdxJH6EiDMn2kcCw/f00XLHkMwjtUD6soxHwPjfI56
|
||||
l2FJPs4YkAmmok1ulDRuSA==
|
||||
+Zjg8k4ZNVjB46NJnSn8ErakeJYqLEw9DhX8QKCz44c1fatMLaKfX4kADtdWsVo0m3DBdTfktt2+zvPnSnSwlvIi2oJRgthe7eFBbm0/pMs=
|
||||
RDZxR0eU/0YxwhYtovyGeVzRqxe/x+r1aScdsXNjbZEDJM/n9+iJeJ6fjq5jg85x
|
||||
1D18KWr2hdVsBcdZx1OaPQlScmRtGt3pyfQ0+O6DoOA=
|
||||
VmVrGQo2zRokW/ZuO9bN6/vHEEiMOBtCIlg1b8xVuig=
|
||||
1D18KWr2hdVsBcdZx1OaPWpmi5eWzbYhJFCY/NY8C/Oa7c/XoIMLf5OfmxNwBC4p
|
||||
VmVrGQo2zRokW/ZuO9bN69Xj6ooDVrRi+Qx0VVbxxuGwXblBGt+UMa3iQsUS+MLX
|
||||
VmVrGQo2zRokW/ZuO9bN6z0Wv8dJZfITZaz7/LBnekh8eKiykXRkJuTroXNsk4sHsjMzx3ehYnBiRsLxQ3l1Ew==
|
||||
VmVrGQo2zRokW/ZuO9bN65vHbxdhaeboWCi24FUvfUKxwpfWxuzCii3Vfl81U5n04eCJ/I9xuyAFs+a+utQoLA==
|
||||
VmVrGQo2zRokW/ZuO9bN66hhLXcZ90iz+YURPNpCdCsAm2RnkTlvB3/dCAYY43QH
|
||||
VmVrGQo2zRokW/ZuO9bN68uGmvNP6wueRXu6UnefD+wH+Yr2ww3IH83h4hC1VuyV
|
||||
VmVrGQo2zRokW/ZuO9bN61sfi9NDWbb3IEw7V243XdGQhqhFSYbmb3HIkuCdE2VLLMjOBsOxdHyxz3Pp+dE5gA==
|
||||
VmVrGQo2zRokW/ZuO9bN6/jrSn0BMJUjTRmq3s4EygRutAv5minFbaCDNSpGOnuGOGbAGxzYhr5FfgbC2LAzaA==
|
||||
VmVrGQo2zRokW/ZuO9bN66KELFqGTvIFlqiTgxQshiEJtYy+NLL3drj2rKA5FLSA
|
||||
VmVrGQo2zRokW/ZuO9bN69qUnlBYp99FW3NU5/GK+PzoHh9gUCjYvnxOqd2JqPw/
|
||||
VmVrGQo2zRokW/ZuO9bN69yVdWZ+lX5d/HxJ8n7Oe9lsFn7ww5+jazR8dqP2+S/V
|
||||
sobCGpmMf4/g7+HpPqBjC6hatZ6rUY3AAzqC73FJ58Q=
|
||||
VmVrGQo2zRokW/ZuO9bN6+bUoxQpnmE0JVwLD8EwzQ/H7dsGXPHJ9cqQZTkojMQ+
|
||||
VmVrGQo2zRokW/ZuO9bN69qUnlBYp99FW3NU5/GK+PyS8CBUEJbhmFgtsc9tZNZa
|
||||
VmVrGQo2zRokW/ZuO9bN6+EOVn5y2jsFMxK6Zwn+wS/mDi05KQxr36Au3RyQiAZt
|
||||
VmVrGQo2zRokW/ZuO9bN645GzHl1E1lX49ZzqICVdNd+qq6XjowUV36TmrdcDLlJRAtaa5meR0QErawnLRsIbw==
|
||||
VmVrGQo2zRokW/ZuO9bN69yVdWZ+lX5d/HxJ8n7Oe9kengQKSCiIkCs6PDQVWcCGpn3+rLZxeaOALBnRhwQmjw==
|
||||
ruTTNFTdswRs4Mc+srnRk818d9d/TGGXzgPjSrVtMi8=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
+qdJgONcot1WKgm0a/QSWRfjD/63UhGjDDaD83ombAk=
|
||||
Zj8NVVe0emTHliAvlpCAerp3iS8Ldzanll9i5zjVEzHQg8mhLB3GjOH9WUhexCJRTK10ie4Li3ku0ivs8PwncfL0CsJ9wuEyiySAnQ+YkT4=
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
NNh1PlSD8WUnUEbz+BU/PxQtnmghDNkLHWxwLL5Pfd80TPKT3Fq0L6v1zn15TQIi
|
||||
LikBEoRjt8wwWzUZNw+jJgWwZ72bx/3Bg25s1ZrnmbQ=
|
||||
eeFiPlXUI0Fos82HYztSmQX4Tn/GgRQusZFpFlvVnwGj3wnNVeLP8HbDx9FBGXTK
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
ERFPcpFJ5x6x1iUKDQh3uuNBeWAGk63K78XGpIjhm2+rBpfY1aEG51pD1dP3DCm1
|
||||
mDvBoIQgD/LTzVDzjae4UJqJvNLzaOzwnnIlpmmAT9w=
|
||||
1D18KWr2hdVsBcdZx1OaPS9U/g0ilrDQencOJy/eayhgybOUx8AzmnF0FRkjYK4+
|
||||
VmVrGQo2zRokW/ZuO9bN68DMZ7Jr2bE3tmVz/lTLfwFI/TgA0E/RsREqTEyLRZTtM7CfvidC3a+UoB6eKaAipGC8lyEDiDjU2OcuQXtivS1abYS5vnbaL+qjgg9xvxZW
|
||||
VmVrGQo2zRokW/ZuO9bN6zAeYkrMwd7SuWC1RgnERpd/CtxQ8iNGHrTJa/V2vhqa
|
||||
VmVrGQo2zRokW/ZuO9bN64O9/l1Cw+LCUDbA/A3sef0aZa1fkxQn/BGfLBYcyIz6
|
||||
VmVrGQo2zRokW/ZuO9bN60zutLkqghuDP33toq5yXb5QoAWEq42gUIT7CcbtapHA
|
||||
VmVrGQo2zRokW/ZuO9bN615f1QfyDTLI7xBDK4WokeoZ/LXykw7EJtsaIC8dNCUB
|
||||
VmVrGQo2zRokW/ZuO9bN60/t3y383iQehg4Rf7JHddlsYUFMmzhkXzzyUyBqcUubPvH2W0j6argePbntySyUzU3AV893eEQa7Yym533kWfk=
|
||||
F9Sftf1PoN5P+lgvc+r10GOWQ9m5fvKDb6g+UBNuAqJgppHlIonewfzaqeYuks8R
|
||||
VmVrGQo2zRokW/ZuO9bN68DMZ7Jr2bE3tmVz/lTLfwGYa8KblejDwqMGy0HS7E4EgxqdWnOJ4dMlPPf1V/WbB45LajcY2+ifZj2xLXa9OfFHv0/Gwu03ahXrFxuCROiu
|
||||
VmVrGQo2zRokW/ZuO9bN6zAeYkrMwd7SuWC1RgnERpd/CtxQ8iNGHrTJa/V2vhqa
|
||||
VmVrGQo2zRokW/ZuO9bN64O9/l1Cw+LCUDbA/A3sef0aZa1fkxQn/BGfLBYcyIz6
|
||||
VmVrGQo2zRokW/ZuO9bN60zutLkqghuDP33toq5yXb5QoAWEq42gUIT7CcbtapHA
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
+qdJgONcot1WKgm0a/QSWRfjD/63UhGjDDaD83ombAk=
|
||||
uvcMgENha6hOb5ExkFYzxifcHMl1I6jrVqfUC4eNgIoj4KJOBKY4nAmoO9a/O2O4
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
LikBEoRjt8wwWzUZNw+jJnTofnNhv2W4ginDjUT/BhyY1a6MiWTuSLmwGyGxJyoG
|
||||
OOMIt/WiNRdlMd3fGCaVnH8L1KXFwR+AJLHaxenwu6I=
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
mLDy5md6q2DkMFpvLtFlrbgr2CZgO+U3exRgHQl+WcSH91VecYi0XBGIdUBcdsZg
|
||||
mLDy5md6q2DkMFpvLtFlrQOIllMJ+wGUeIFDucuWhfM=
|
||||
mLDy5md6q2DkMFpvLtFlrU7D4Mf1ddl1j/aFZsBH/L00FFBrPDB3T673ZTtvJXi7T4ttNDvQwxI44e41cn9A6A==
|
||||
mLDy5md6q2DkMFpvLtFlravQqYs0c/bzbQZd9QN3+nxowiHk/rK8+h8Eqv5Ky8lOiVVSR1FIS/LaTiW4is7mBg==
|
||||
mLDy5md6q2DkMFpvLtFlrbzw3oheqXbD2qwAZMcuA6Q=
|
||||
mLDy5md6q2DkMFpvLtFlrWGBrB/jcgDQIi0rEIX5vN8=
|
||||
mLDy5md6q2DkMFpvLtFlrZ1FI9J4zyIUAMeW/0xk+lP3z9xCfVcSg+XRPXHC2cuC
|
||||
mLDy5md6q2DkMFpvLtFlrZCAR5DUc2ey3Q5f9VfOQLDhu05EqWt2hD1A7vDKSpvg
|
||||
mLDy5md6q2DkMFpvLtFlrVE4nQqlZKqeRHuhcjYG9cBcbIb6mWq6nCQfXdYqVLBuaNiK7wnpdzENXVQGO4xxag==
|
||||
mLDy5md6q2DkMFpvLtFlrQsEeGnN4vdParE9CDgiAK4tpdIWqozh7FV+BqtNBoddCimScVPthPo5boSZ2aCWKQ==
|
||||
6P8mKfouOK1hwXy3MrrCzRw2UxbgP+Mth9DRZFMbu9aRbVUdtXbkT66ZlvG5+Djo
|
||||
1D18KWr2hdVsBcdZx1OaPWpmi5eWzbYhJFCY/NY8C/MQbhQT7DlATgfnJmvUUqXY/dtM6WhYa2J1aR47iGCprQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6wPqF0gJwvcSllqTssBN3IQFplxd+VVRZRZSvCVDzHK4
|
||||
VmVrGQo2zRokW/ZuO9bN61DdfsWGlVNr7xf50OuAfKCWMv/w8v4ixbracqKZTk/4
|
||||
VmVrGQo2zRokW/ZuO9bN6+bUoxQpnmE0JVwLD8EwzQ/H7dsGXPHJ9cqQZTkojMQ+
|
||||
VmVrGQo2zRokW/ZuO9bN62MG6pIvkYn7nEiOjeoc64MrwokZLOOcTxaO8jmQiVHe
|
||||
VmVrGQo2zRokW/ZuO9bN61DdfsWGlVNr7xf50OuAfKAMMGpuitrqnk3bkbSIR8tK74tenFOnrkxVhSzwMR4nkQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6/Ly/04eT22h1xyl4dSvQSMNqp7Qyw2t5SG7+K+1JJ0tG30ZCAYaAQLvLpQPeNMYHQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6+BIYCVAZKyRqKArWI1vncDdczYfwtpU5zW2MXjhy/z24GxeAx3QYpL0FUnYH9XQhhs1p0qlJik4yELSlk3g+Jw=
|
||||
VmVrGQo2zRokW/ZuO9bN6+BIYCVAZKyRqKArWI1vncB97WLhqixtZQpLQVJjO8F9rmnhbOS/OmY6IJG+17UdTrJrlEUKFErdk4ikKnb3BL8=
|
||||
sobCGpmMf4/g7+HpPqBjC6hatZ6rUY3AAzqC73FJ58Q=
|
||||
VmVrGQo2zRokW/ZuO9bN65CBdpRIOtptu///2YRyptDJuSvuNBDGWMFm3MShUYhGV2dg4J7PVbUNMjSG7+hBZw==
|
||||
VmVrGQo2zRokW/ZuO9bN620zSkiHBXev6YTvy3qjpOw=
|
||||
VmVrGQo2zRokW/ZuO9bN6xRaRh2h2yn72BLBhrbk40FNmSd9pOkjInUT3PKeP00k
|
||||
VmVrGQo2zRokW/ZuO9bN6/Ly/04eT22h1xyl4dSvQSNU5MWz1FGNCr4JsFoMFY0M
|
||||
VmVrGQo2zRokW/ZuO9bN60HvClbwMpABlSn73UhadQPjjrFMVzyd6bmtZhfVjiZU0huAoInXX/Q18uefitNtu7dcNYig6Kw0BYoxUhMMT0E=
|
||||
VmVrGQo2zRokW/ZuO9bN61igX6t9WmvQd//qUjyBL6Batd2BDC4WPD9BlNf7ZSqbQhMB7M2MNINGZFx+z9nGKVdGMF8NhqzIBLeQIOPk9kQ=
|
||||
VmVrGQo2zRokW/ZuO9bN69Xj6ooDVrRi+Qx0VVbxxuGwXblBGt+UMa3iQsUS+MLX
|
||||
VmVrGQo2zRokW/ZuO9bN6+BIYCVAZKyRqKArWI1vncBha4twiqqqB+Lkuo23an3nEDeccqba1p3sRs3HYCm9Zw==
|
||||
VmVrGQo2zRokW/ZuO9bN6+BIYCVAZKyRqKArWI1vncBg1CWm6ODKEO48OETuF/c/M7gx4RLnKkvGw4yWkxfmUw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
+qdJgONcot1WKgm0a/QSWRfjD/63UhGjDDaD83ombAk=
|
||||
6tCwW2TgXgdok4IQCfIwE64+sANSz5E9miXDw6QJ0r+y7ra3wf2izxuhjiJCK0VR
|
||||
wgR07xfoapmx6eEnFHXXYo4se8cEG3Kpe+KryARC+58c1jICgdZ/yfiiPJOB8osn
|
||||
iZaIsa48RXfE+uf/yF/rQB5Pyu2LLCSwLBPzS3UQNqB6gGSsuwVrKFDeT7S7ipIY
|
||||
iZaIsa48RXfE+uf/yF/rQJ1gz5XqVdLjUgxnZLiZ0kxneHQUMBy4uvSK/N8oOaAN
|
||||
iZaIsa48RXfE+uf/yF/rQNi9uyLdvBZCesZvX8KcrGbG22Xqw+geSPuZqdcR8y/X
|
||||
iZaIsa48RXfE+uf/yF/rQGg6DytIW0WefmXAsCDYL0s=
|
||||
L0eUthVnpkGsmKFAX6d+uBWSR38I0ooDiDs76zI3rHk=
|
||||
45hn3FAK6/Q5+BKz66I4FYGZrfj46julOMe5ClqgRDsgDKqc5g62TlKmklK79LSu
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
a3HCOwVwgUUsIXy0NI30N1OnTRGwPCMCQnd24LPbvMgw/R3ae9al5MVMPI50MW70reHrwrOjYxRGfyTEKtkxrw==
|
||||
q4nc/jwATOMUyfSjLibfEQ+nVsCkuVXEdAcBKpgjqkY=
|
||||
b4OJVZe8QyIpjuTpKXDL9A==
|
||||
iZaIsa48RXfE+uf/yF/rQOvVhu/ngkyor/C5n/UzkBlCx3epFa1yEIpBPWIrtKEsgWftLDpGjIPx7n5zFnTscEhgReIowtD1ib7ZaN1X1YU=
|
||||
mfT8DrNbUmxQ2BnZ1bZFTLh9MEuZKOpmAfF70OnZ9TU=
|
||||
iZaIsa48RXfE+uf/yF/rQAZ+EA0c51yFjsX9CPHlh/5ktj0ZrD7uCaj/wgnzHlOCeQCMjWvzIk/DQlZByMiq+Q==
|
||||
XoHMeaTuJPZ1ZwkBYGxPGNO/fZdFrQeGdb4hk4VRpV0VW7fg9Snb4rb537T74XCuh+3WZ9XaioboPMJTeFhjmA==
|
||||
RCRD0rTmvzRnTOGXlaehMNmLKF59VFrNXo8fzNysbhTBKccco5cEPB8/dJX6dFqJWYqn10Vvxc/CzhwbE8EJnA==
|
||||
I9ZqFYKrj9zbehR1kVWMoO1GI6M1qqtG2eBy4D/nldc6VNZO14SHN/sd2voQ0WEXWYIgTZTr4rDtrGXNBr4IBQ==
|
||||
p50nNlFbWWSM5Jl8TEsk4TnLz+h+3cBHymV4PzApmXUNqbCVGjhE1qvOMYMtCX6R
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
+qdJgONcot1WKgm0a/QSWRfjD/63UhGjDDaD83ombAk=
|
||||
J24jXQQti6wQv5pCoF2ZrcLSPgZELT2A2fhuhSpqDo6BY87dEmAzodysqNgyKvzt
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
hpr9H7QXrORqNT7P49jOYzeYsCbBz/1birJj/JpatlFkFxq27b1MCr3POwO46E7P
|
||||
YThduOXrtrzATLnwayQWnaA2rNH65m9eJvXKw5GWAAUtcZdLSGJWwaU999R64Cgx
|
||||
7JQQDTi0T2idhFjao4jEpTcu0vyrf72ks6Zg9LXjcLTZ8NE7V7tyehMaTKgkL7Idboxtgmjsd+qtDVj49PH4pQ==
|
||||
h2Amc56dmaRo3inGZxN9N3ZLtg8BK5nYtLYDA42Z8AY=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
YPE3JL0PMUUnZO0HIdJJMQIGfUXEkt1C3jRrwzATAL//GACiXsL3H69yk+yUtmy1bN8AwykNHE9d/OHOYjevUg==
|
||||
DarJ6ebtq241LBXqUNSmb8Hia5oTaY/pb+ay91woMws0FeL7ToyJ9YGj7DCzO+EoR/kGoHazwB7LUQuT5rt+Tw==
|
||||
WHkOzVx7seuLmxs5Hu+l/kOzZi2ouy/XqACgrRboMuAkPXB/7WhDgtDQxPBuCGk/
|
||||
L0eUthVnpkGsmKFAX6d+uDbeqTXIh0y0jrTQHkGxk00ztM8l4dexLnzgjvrsNYuo
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
xRFNEm+nIUjh4cyIzan96kWy6IA9PfznyfSNsYXjhcyekoNWgDiMNKfLwh7IzzFp6unM4EoEl230CfvpYsKmgM609XzA4rC8JK4FwC/3GZM=
|
||||
WHkOzVx7seuLmxs5Hu+l/tfRUTtAad8Cb/6s2BEj2MF5sacS9liWC0L9lFX0T/8D
|
||||
L0eUthVnpkGsmKFAX6d+uDbeqTXIh0y0jrTQHkGxk02YaDJD923/KMmkdZImosxQ
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
uqDej/AgJHcP58Evn06kx+BRYuP+Rv/P3yyKDCiEank=
|
||||
M6xDbqnqlGC4Hwvm9iO9WpYNmQzB5Emv8bNh+GjwifhyGxJaxrM3Nu55hGkrzp3Na0UgKMMZhQFDdB1qBnzZM4GXlShJqy10Xh8Ng3hvM6XmMaUNRpE1sspYrkvl/ok8txPZkGD8+6CimGoeq/gHc3IooOAxEh16uaQ9V4oWzew=
|
||||
M6xDbqnqlGC4Hwvm9iO9WqiWh7KxdPf1TCqsUz96BP2LPZ5/6OAavVK3NQ5oRvG2WRCLP8CLNwYIKWfO7LKcMQ==
|
||||
M6xDbqnqlGC4Hwvm9iO9Wscmcj6WdKWpwKUcX7+6wD9qlaetybTVnC7NRyEMXQaUruJxuLP7EQajaE97ybYV+A==
|
||||
M6xDbqnqlGC4Hwvm9iO9WmrzpW7xqvFOkXRrquG/LdmkWI44+PZZb3h8jfRCzfXDDJpmmDVFpMslk/lOV8ORKMKf4lFQfW6IN3gOezMVNdk=
|
||||
M6xDbqnqlGC4Hwvm9iO9Wrluw3FaFu0rQlI5v3W4Gahe5M3IH/7altsfw4aQIzFTFEp+kqHOFqW9zknlolTgr2aDwLbq3LeRkrF/cccTrDo=
|
||||
M6xDbqnqlGC4Hwvm9iO9Wui7tfyp3EhrtndI0VQ+0bDRrlG5yESM9XqTcbJlcOwgCZixtz2l/jHsCLjZop31bNpXX4KYhl+/OzIp1VoECupI8G0NECKhXZGxwFP67OGP
|
||||
M6xDbqnqlGC4Hwvm9iO9WoTR3NAG7MGBrcMrYbTxwvg2d5zTs9QiVoeexs7vgrp1tLfB/Bf9Au9wHlmv00K5zdOfVB4vDxKGSGToV0vyVNU=
|
||||
M6xDbqnqlGC4Hwvm9iO9Wsk/YBXEvbh9Uvmnh0QJSiFhxQ69X5Iboy1Wk54I9i1KGX689Qf7r00dKSrjZWYdjLOCaQVypVZpz26m19HQouI=
|
||||
M6xDbqnqlGC4Hwvm9iO9WkK3xOAmzw0wgWg759KvLhH+T5S/PN6qHRHRQ9T3LKPDzTOSNkmC8BZsFn/KJ+t2aLi6nBteKpQt56QmNdl4dqs=
|
||||
M6xDbqnqlGC4Hwvm9iO9WicgU1xjseoMDlsA3ET1//BCkdCo5I3potyMnxOy8NaEhbkT/s1OThM0Dsk3VBA/QNrh8++5Afxt13QBvjjNDXI=
|
||||
M6xDbqnqlGC4Hwvm9iO9WgMokrgL8MxEJjEYatsrUV+m4TFjPvxx1gKKyfrM5ibGqjVXQhxhwIodZHTc6JZeUg==
|
||||
M6xDbqnqlGC4Hwvm9iO9Wr1kU9VI/yudDc/eHU/ewRmVwLQ8jsS8G8r/7F9bWy1TnWfhsRCr+7KbyaufVfaXfcW7CUaFOxd/zmAVrMdCGCc=
|
||||
M6xDbqnqlGC4Hwvm9iO9WgnywlPbX5KSPk43KpzNKONPq30CaJS4nUs0mMkP5+hbSivbSe4CLkF0KKyRNsQATD8ju8dPAj+f107ThzNYRGhbxWww+AVK7muD42wODMJWmw/m4J/JHWAWU3/ibv9MTKX/YkfOX0bmEcp9LHx2Qxw=
|
||||
M6xDbqnqlGC4Hwvm9iO9WmJCBrWMX5jYxKbKR4/u41xMqvIPvD3LZfDUhKcoaKuCpfnCZ+EipXVt8I72Nc/dYrkGyEFkdOLMBXhB0XKMLR6STMFXt34k9atd9Qw9x9lNnqTZZXN2lErP5TZWivV35w==
|
||||
M6xDbqnqlGC4Hwvm9iO9Wqld6rg2Lx98CYBge5Z6YW6hSCzeqqkJgURG552IJQtYStVrim5S05TrSOKTWH7I0Q==
|
||||
M6xDbqnqlGC4Hwvm9iO9WtVd4iOTlcBudzv96785RaYKs1fhppqqdhgtHLqtXL7XvQgtx4SyuONpafq5eZA/ig==
|
||||
M6xDbqnqlGC4Hwvm9iO9WgHNFBZvpw4Ykrar5o7UITLqUwDKmFnO9r5qPTi6XzxGGIRw44iLmxNRh6SGGLj5FfIqITod7iAWgEPz9f8TRmg=
|
||||
M6xDbqnqlGC4Hwvm9iO9WuZW+fuUZB8WpAoWyO5L3TVNxM59XEoFvdP/J5Mq7mp3CFXj+BrERDZdtku4jEnITQzW/Dt7uaUWhWDMFwB/e23rItPvfJnVza4yTyKuwcrG09UsVKbA37u7vX9Q8N+YMQ==
|
||||
M6xDbqnqlGC4Hwvm9iO9Wve61oMllAKK7aIpkSBv6ZwWnrC4aacWBYjk6HyqSYHL3Hq0XfzMZLHvhQDh2db3gQ==
|
||||
M6xDbqnqlGC4Hwvm9iO9WoVS+2ab/4yGLNZfC++bUsOORjTX6oF3vbSWEKIYHfC+YN+4SdEA/Th8xOpeytLoDDgQyYgcj2oY5OlwO/zmBYo=
|
||||
M6xDbqnqlGC4Hwvm9iO9WjKEpRdLTg7WVPHPtUqJqomzwXwNg8PGbqA/U5P5s2Ph9e4kTSbmMaVhig1rkgK80A==
|
||||
ThMMHJmbSWymjnzPL8su8sBHn5UE8cpNu9WLRZiCzbQKCkCL03sgs+DNRoTYeavL9RZ2I8MdhFqyZIgb2dUmGw==
|
||||
7sp6hnTw2OtZMRbJTXg9rCuLplGGh0CaZ+h81UyYXoTfxQz5dfr9h/PfGPK3/x1X
|
||||
V3FyDbaPyt/GrdnaVxxGP5QP34MBqfVhEo9rUYClIQ8GQn13ZWbZ1M6lAwu32F6B
|
||||
aTu3nEEJ7aNZbzv6PgxsAMIq5Ov2mq1jFSdTHQbA4AjQAxNj/KCefFN/tFo+IuhQiYS29bChBFdJoonMS2dVyA==
|
||||
UaZ+UhuuDk5ogKtL0+DbtF7ZZMj2uXAUIl9TJ345Nxmn7StJaC+PsiBVbPv50MBUIixchc/TaeXRoVZZIe8nmg==
|
||||
UaZ+UhuuDk5ogKtL0+DbtO8lJySRwyixd8VH5w6ddE5sq42a0K/FaZh7d6UNKygbk02lvC2lEd8zp1b07VqucA==
|
||||
UaZ+UhuuDk5ogKtL0+DbtEs4/ygchHdZq2caT5P7ZAY/kfYVA9rE+SmVnD6+LpWybbHzyvSm6PZuNWfaxF7GPw==
|
||||
UaZ+UhuuDk5ogKtL0+DbtMpwh8AvPkdmTABoemWOBnMsvPbmXsy2D3mw7ujaSN+uVEXDHvmeZaWIoPTaqnsQVw==
|
||||
UaZ+UhuuDk5ogKtL0+DbtN/ExXZO6r+1Hcx6QYA2uMFerjP1PMKvvs4KUFhJZHFNY9UPjmpmdJT54wPfO3Unnw==
|
||||
hQ7Zur2CVZat0LHXIoOqQEKciq0mRp3cUUC7gBemh69qrx4U+SnMEWhzDrNvYhgm
|
||||
OcTtZEQzjmqOEoLAu9WIDBnMum7894CWxyFLkwGu5IwtyjTHaWA2GKONXV4r9vTbg7+1p4tBESO9qkBU74HTEw==
|
||||
7sp6hnTw2OtZMRbJTXg9rCpKNGJwajbjYG7HLQCEEEXdDjiGpseZYp9Crn852qiTgxwj5jsQKnu7vZaHhMdVCw==
|
||||
aeUTuKRk4Cv0a6/hj5z/Azbob5vVUjA8C9zwLz131NFQ9+8QpUnpNMjZSkEDyzqvNJOEE7EErl0S1qQyJp0S5A==
|
||||
aeUTuKRk4Cv0a6/hj5z/A0ufTREaztlpquv0pmAqO4eQBh/OIVHNrMu+G8nKcxX6NRI3YvUe7O2X95abzQ0iTA==
|
||||
aeUTuKRk4Cv0a6/hj5z/A66msItV6S9si1UO/Jz4XEtSerCl4q49UQ9M8vbWbqsSRL7I2Hi6gUZNJBpgAByHeg==
|
||||
Yh5IC9IfOdzCK3e5XDQpq7zb2TsOXHn+3J5O2euHIXfq/mGF5OhOVbuFMPjXnQ+M0Dg5Ohnqz2pi0eTNKIzU3g==
|
||||
Yh5IC9IfOdzCK3e5XDQpq+2odTci4K1zbNd8NJCQULk+QCw5/atmY2M9xvTShAOrmRgT9J1cZGUyLM7hRG6T9Q==
|
||||
Yh5IC9IfOdzCK3e5XDQpqxA3qd3TcYSVTzrAlmiWJldxDn1jD1ym4yTsgSajOLNbDK+wnMHISwB8YRnXcqofniSCYnGaRqMvj3MURlsXp1w=
|
||||
Yh5IC9IfOdzCK3e5XDQpq4DKOluGK9CtCgb/1zx0eeCNnM5UGmgXLCeepHrrYTn7VFMw8Fm+mwdLVExOl2tjpZOppE4njUrAe4tqn0RXteY=
|
||||
Yh5IC9IfOdzCK3e5XDQpq5Ifj6xfZnDox3MD5utXFuixhN8RmZlHKUvwYnDADhnNXPn0TzBaUVp8y3F1IayBhZc9me9kQSHvBQ7soWODUbs=
|
||||
Yh5IC9IfOdzCK3e5XDQpqzRhjv/5t8mv7bNNVXSZA0n4tEX8ATMW6aOFzRYG1NzH8pTBJQ/1EU81Zjuy4E0Uaw==
|
||||
Yh5IC9IfOdzCK3e5XDQpq5aQfSbh2TPEVX96QEtEYaDiuEyvpOigBao3+w795EB9JATH6Wr2GIoRnqzXQgdrIA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
661hZf7vhUQ+50okfwfTXw==
|
||||
fE3zmgbfhO9ZwEda5GgwD0R+fpJ7JqroVfr4B5FO/AhYM3WK1zBVVzIzdn4lt3dirmMTx0U2aKsHZMW89EKgpg==
|
||||
aPdLEV6HY2SBr9CPW/3NlfBbk//L4rv3UKu5v766u0A=
|
||||
|
||||
+170
-170
@@ -1,170 +1,170 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: cjxin <cjxin@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
# 上传文件至oss
|
||||
#------------------------------
|
||||
import os
|
||||
from filesModel.base import filesBase
|
||||
import public,smtplib
|
||||
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.utils import formataddr
|
||||
|
||||
class main(filesBase):
|
||||
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
def get_oss_objects(self,get):
|
||||
"""
|
||||
@name 获取可上传的对象存储
|
||||
"""
|
||||
return self.get_all_objects(get)
|
||||
|
||||
|
||||
|
||||
def get_file_list(self,get):
|
||||
"""
|
||||
@name 获取可上传的对象存储
|
||||
"""
|
||||
return self.get_base_objects(get)
|
||||
|
||||
|
||||
|
||||
def check_email_config(self,get):
|
||||
"""
|
||||
@name 检测邮箱是否配置
|
||||
"""
|
||||
import config
|
||||
|
||||
c_obj = config.config()
|
||||
mail_config = c_obj.get_msg_configs(get)['mail']
|
||||
|
||||
return mail_config
|
||||
|
||||
def send_to_email(self,get):
|
||||
"""
|
||||
@name 发送文件到邮件
|
||||
@flist list 文件列表
|
||||
@msg string 邮件正文
|
||||
@to string 邮件接收人,多个逗号隔开
|
||||
"""
|
||||
|
||||
import config
|
||||
c_obj = config.config()
|
||||
|
||||
try:
|
||||
mail_config = c_obj.get_msg_configs(get)['mail']['data']
|
||||
if not mail_config :
|
||||
return public.returnMsg(False,'未正确配置邮箱信息。')
|
||||
|
||||
if not mail_config['send']['qq_mail']:
|
||||
return public.returnMsg(False,'未正确配置邮箱信息。')
|
||||
except:
|
||||
return public.returnMsg(False,'未正确配置邮箱信息。')
|
||||
|
||||
msg = get.msg
|
||||
receive_list = get.to_email.split(',')
|
||||
if len(receive_list) <= 0:
|
||||
return public.returnMsg(False,'发送失败,接收者不能为空.')
|
||||
|
||||
|
||||
#附件文件
|
||||
flist = []
|
||||
if 'flist' in get: flist = get.flist
|
||||
|
||||
result = {}
|
||||
result['status'] = True
|
||||
result['list'] = {}
|
||||
for email in receive_list:
|
||||
slist = {}
|
||||
try:
|
||||
data = MIMEMultipart()
|
||||
data['From'] = formataddr([mail_config['send']['qq_mail'], mail_config['send']['qq_mail']])
|
||||
data['To'] = formataddr([mail_config['send']['qq_mail'], email.strip()])
|
||||
data['Subject'] = '宝塔面板消息通知'
|
||||
if int(mail_config['send']['port']) == 465:
|
||||
server = smtplib.SMTP_SSL(str(mail_config['send']['hosts']), str(mail_config['send']['port']))
|
||||
else:
|
||||
server = smtplib.SMTP(str(mail_config['send']['hosts']), str(mail_config['send']['port']))
|
||||
|
||||
data.attach(MIMEText(msg, 'html', 'utf-8'))
|
||||
|
||||
slist['error'] = {}
|
||||
#添加附件
|
||||
for filename in flist:
|
||||
if not os.path.exists(filename):
|
||||
slist['error'][filename] = '文件不存在'
|
||||
continue
|
||||
|
||||
#超过50M无法发送
|
||||
if os.path.getsize(filename) > 50 * 1024 *1024:
|
||||
slist['error'][filename] = '文件大于50M'
|
||||
continue
|
||||
|
||||
#中文无法发送
|
||||
if public.check_chinese(filename):
|
||||
slist['error'][filename] = '文件名包含中文,发送失败.'
|
||||
continue
|
||||
|
||||
att1 = MIMEText(open(filename, 'rb').read(), 'base64', 'utf-8')
|
||||
att1["Content-Type"] = 'application/octet-stream'
|
||||
att1["Content-Disposition"] = 'attachment; filename="' + os.path.basename(filename) + '"'
|
||||
data.attach(att1)
|
||||
|
||||
server.login(mail_config['send']['qq_mail'], mail_config['send']['qq_stmp_pwd'])
|
||||
server.sendmail(mail_config['send']['qq_mail'], [email.strip(), ], data.as_string())
|
||||
server.quit()
|
||||
slist['status'] = True
|
||||
except :
|
||||
slist = '发送失败,' + public.get_error_info()
|
||||
|
||||
result['list'][email] = slist
|
||||
public.set_module_logs('files_send_to_email', 'send_to_email', 1)
|
||||
return result
|
||||
|
||||
|
||||
|
||||
def upload_file(self,args):
|
||||
"""
|
||||
@name 上传文件到指定的对象存储
|
||||
"""
|
||||
|
||||
name = args.name
|
||||
filename = args.filename
|
||||
bucket = args.object_name.rstrip('/')
|
||||
|
||||
if not os.path.exists(filename):
|
||||
return public.returnMsg(False,'FILE_NOT_EXIST')
|
||||
|
||||
info = self.get_soft_find(name)
|
||||
if not info['setup']:
|
||||
return public.returnMsg(False,'未安装[{}]插件'.format(info['title']))
|
||||
|
||||
sfile = '{path}/plugin/{name}/{name}_main.py'.format(path=public.get_panel_path(),name=name)
|
||||
if public.readFile(sfile).find('upload_to') == -1:
|
||||
return public.returnMsg(False,'暂不支持该操作,请将[{}]插件升级到最新版'.format(info['title']))
|
||||
|
||||
#创建任务
|
||||
import panelTask
|
||||
task_obj = panelTask.bt_task()
|
||||
msg = '上传文件{}到{}'.format(filename,info['title'])
|
||||
exec_shell = 'btpython -u {spath} upload_to {file} {bucket}/{filename}'.format(spath=sfile,file=filename,bucket=bucket,filename=os.path.basename(filename))
|
||||
task_obj.create_task(msg, 0, exec_shell)
|
||||
|
||||
public.set_module_logs('files_upload_to_file', 'upload_file', 1)
|
||||
public.WriteLog('TYPE_FILE', msg)
|
||||
return public.returnMsg(True, '已添加到上传队列.')
|
||||
|
||||
|
||||
|
||||
|
||||
QRASP55VO/1DQ98p1csw9A==
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
dBZyCsfrbwqvA0sbdGrIGg==
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
n+0ptngHIPIjFuMNQ53bfj+Na/fdhk6k1yTpAwW7j353Dw920mEqQQZjykAHeRmp0ZD/P3ftGifsmPOMf2b7XdEqyZH0yl9kjaUugj3dYPI=
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
jh3cxzkA2htccqfZRKAUdI8r17q57nOGP4OxbJlL1NAnrF4weHnS0MpT6C6jbrX5
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
kEPo6lgxLBQavG1DxRrlnEK5KohxBShsQIeNCGHkEP4=
|
||||
I8MGJUwtjfcKc5w4E0SmjHwLsErBQ84ek459TV1n0Iir/P4mdpfwDI34s6+8CBN0
|
||||
dTLQ8Wr3wPn7w6pte1B1YA==
|
||||
X9BNoFOwiQAnMPqEk6FnbzU/oA+chL/aEAzGH80mBrNNxRMBdiGPqgDUeLF6rer2
|
||||
bPP96Leq4/6bN59hBCaYlI8pXwmlcWoHnMhS0JRYMuI=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
NbgOlQKOVjgcHXr2EWkJqQWzgWH6Vq8RJ/AUSzSss8IVUY2HzghyE71ZaXPBTLGv
|
||||
NbgOlQKOVjgcHXr2EWkJqeTgbDhQ7kNNY/wz8y2GqwZTfVZH1snrz7MBnfOT91tS
|
||||
E9KwiiXGE37hdLvk/mY+UIznMbuZ/AbAoo9N1G0YvoLz61bIHX5Q0KQJryQ9TSuJ
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
CjJS7KrzKM18mlLqJK9jKTB717Vvrubu5ix9tb047ao=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
9GxZpCRwMRDPejWR2Vvf+LKn0tNtFKp8Eh2tnr4Da9U=
|
||||
6c3cWGGlsEf4q4E+EjPFyg==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
9bJD7OGVYIbkQwcqio3pMkEQ5Tepk1KAKJBdik81BOHNSVFwrMdl2gFGwZvvpYDQ
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
NNh1PlSD8WUnUEbz+BU/P5ZvVL4YjAgUVrqKtQwmJSm1F1KbG0/rNY/6xTjx3EA3
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
lt0ONPc5ulpyg8e5cXCrlcNbN4AJdkj3/jMJ6CSe6OnifSM9+lA1O2PeRoAR/q0t
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
J24jXQQti6wQv5pCoF2ZrcF30x6jIElrdtnLwh7xjCTUby5LexzwAUmLxkZ6OZp9
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
NNh1PlSD8WUnUEbz+BU/P5ZvVL4YjAgUVrqKtQwmJSm1F1KbG0/rNY/6xTjx3EA3
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
CAhn8dRUItEbEErp4w+lX9NUcXl4jGRSijSFq7galTkLvLnalDlhEukOn7KLDmPy
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
mz/fdzicrSUPVLp6o7PwCSAYjWkN2zpyX6N0H3XQ+Re/2H8C5nEqNaf5oXzlLd5r
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
0LFyB+q/4AUBkCrX53xYJZNkGwqwopNQ7HR7+KY/2yjfRImCHWTpijZdrdo/d8l8
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
KbLSYqE/CR9TL3ZELtBVg8UiZep5zt9moZHOJ5ffCHo=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
iTSUWsaHz8xtfxXo170oO/0vr9reANk6j9ykbM5WiCYFw3OvMYMGyJ3KgPGMrF0H
|
||||
PXCtqxQPPqk7Lcqhz/3AoGaqmPHjN4rP7NSesY70x/92ifCLZ8Okvt9nT27s6jtrmbW9pJXGLgLNf+3meuER5A==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
FEZSdYhAV26PfOeirhfda9fPkPkpgcLIU1bSxCG9qHs=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
DJtqiO8w/dKi7HwLds9peNr7IF6LPtUssSL3IuNOYGLlHjOwFmfwe9OK3nxxRRgN
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
a1WCYQuoRJeK3mOCGHQIliYA3yrJMlMcLCMVYxV0uObw5q3Q+Zn4+NYyZBHBqFEE
|
||||
+kvn6XYS2Dcvt6Ptafb+egXt7PQiX4xuk1EJQthbw8LHHFksw4XlK/hEZYEN6MEz
|
||||
Nl6FAwmBymcnkmQ2v1saoWguYo5PAJb10t78p9wNmQ967hJsaE/VyX2nuWwy3sK2
|
||||
JEQfGov5ldbBWaI3aZWXDNAOlBZZiYaTkM41OkhTw7DxlEAMKtlD3FDpetB/Ra/HrMZWBT2ISI5K4C7FovZIWg==
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
KbLSYqE/CR9TL3ZELtBVg8UiZep5zt9moZHOJ5ffCHo=
|
||||
iTSUWsaHz8xtfxXo170oO/0vr9reANk6j9ykbM5WiCYFw3OvMYMGyJ3KgPGMrF0H
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
b4OJVZe8QyIpjuTpKXDL9A==
|
||||
HNqEbxya75q97PmRdMU8Fq0RpPGtQqmyQcXNysvYcIzmzwtTL2CB6nQWsuCPipUki6fsBjosP5fyCX/lXfWtP2aHIN8g6JRrW4TZbYQNKv4=
|
||||
1V2v8QerKOmubvSxgB4eTATuLP/YkzXuFS9s9v29gfLs7HzcbbjmTiso+zmsCZ3S
|
||||
VmVrGQo2zRokW/ZuO9bN6zM/X2hHBCd+n2OGnnATmrRQLiV7W1lz/PImX//PWNLkFIuv7VUgU3+a6PwWzgXXaB4nsglac/VuhWclPIvVlgOIAaNg2YXbEjwkZqivaweq
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1V2v8QerKOmubvSxgB4eTJ841yfu7l5arGk2XF/kO8mJfg3iuq4dIggjGJ90dwx8t4CE+4HLudLp33Sh9joOLg==
|
||||
VmVrGQo2zRokW/ZuO9bN6zM/X2hHBCd+n2OGnnATmrRQLiV7W1lz/PImX//PWNLkFIuv7VUgU3+a6PwWzgXXaB4nsglac/VuhWclPIvVlgOIAaNg2YXbEjwkZqivaweq
|
||||
mfT8DrNbUmxQ2BnZ1bZFTLh9MEuZKOpmAfF70OnZ9TU=
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmWg3MlyzvlsDpJ2tFZppFlDIgMeiVDQ2HRCla7COtNJPjhTSrDI29qVP4xDeSndmdE=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
uIl0RcuWgRCPZivR9HE5K6P0KAPh0+c0Ci+5o0mjZKg=
|
||||
KHVPPgRdeAM1K9qeWQ6AiqCJ1c6DyhB9VCKPe+SB8o/S5eT66VcxZqE1Abf23JR5
|
||||
gApoKqs53F0hB+0nTxFBUK0sDmJFt2pcRuqhtiHPJ+voEfz/6grsNrnqbl6KL3aq
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmVf/86mCDVHuaSE/lwim7QrFi5TEaeF6XshC8H9LAxRJInVUSAqtWixvfFY8aKz+m1a1RsFEpCSFGYL1Q+qZONa
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
gHZvnjbK0+c2DWpdjJTIKjYmDJs6pOpneqykoeukYiI=
|
||||
RAcgdll7MZc9X2PbkeTvEzNyiOpuxHuwyFCiwlCwtBo=
|
||||
NgkU9z71J5Awi50+35yVrVFRMlqzLfxgW8oRH+8xszId0swAa3xYf+cQPC3GoRX8
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
/0ULpLqgTvInFD0r5hHANoosZ+xywkOR5dozStfmlYk=
|
||||
YSlit6erKXylrjSZnvyW8I3FYH6DLcfYpMAlko6lQqVBBd1eDeDGaujrHWIOJkcI
|
||||
YSlit6erKXylrjSZnvyW8Dke2RKJMhjXyxnQzpVZgOM=
|
||||
Ys4BPYSOoHeIx+ql4jJylD2VLnaOQOBr+k3Ytq5owd23kxsNazPnVuATSOUovBrq
|
||||
bWoUv86VLMtyRQlo14Ahu3xfaGKmZUw7MPoURoMwHGI=
|
||||
vQwaisdUFOt9b0SJYuH/nrHigrTUtycF35lf58xGUQo=
|
||||
VmVrGQo2zRokW/ZuO9bN68uMQcDaeKFBnSol/Upw31Zbihi4vGENQHlL+dj6DCvT
|
||||
VmVrGQo2zRokW/ZuO9bN61HRAGek/auc8b4JvIZlfzGQ/b8xNkzKFp1KEGLxgbuwAYkeWczxvXCQWc0loQzSHyq5aP4vAsBP8KIObacZsHW2l0eK/68p8LwM/KD04HbjIFDKWSdnqDmGI5E/oEv2+A==
|
||||
VmVrGQo2zRokW/ZuO9bN6/0hFCJypSh6x2UIBkV7VvXsU+cO8B7S9xx1VVZWBeu0eYDfkAI5IGvcY5NDn0MqTPYuqy5Bl3zY8pT547cBMFbo51+sa93m7/eHEKuy5GXE
|
||||
VmVrGQo2zRokW/ZuO9bN6wHsvvxh4guxHr80r9yaINtJrvRK6UdvNL8JUA1IT/spxWK1U/dlzvPRDq60WZSm+w==
|
||||
VmVrGQo2zRokW/ZuO9bN6xd9hVVPG/da3jOneq2RZCcce997vOo+rQywLRgLWiWuNr25+4z1FY+siXTO3eViyQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6/CxiXZULdhjyOp1jTEufd+jVXQuLPUTInFNcnpN1I4wKnR+4QeoyJLsqr/3r41c5otdZB5U+KnTPi6U0yHupXO5fT2t9XsGdz3dQ6SMRN8yg9FL1qHp4ThJ4cz/lg4X6o4uGI+UWHWKQ4ipM/V7GcM=
|
||||
VmVrGQo2zRokW/ZuO9bN65hAGaICagbU0z0X3nArVjY=
|
||||
VmVrGQo2zRokW/ZuO9bN6/CxiXZULdhjyOp1jTEufd8fOViMKvV/4EBLt4qPjTM3P8imZTOW0FDMijb9jSuw0FVDpqK7f2sMpzWe9pEkHJdj7JuaHPwQym1UOAXnaGko///EYYbAEydMFZn+m+korg==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN63WsPkEtKdp9rQFEV0mc0Bp0wD1zMIehj9MyHLROd0aILFdAc3MAmaemnxPAUiPekw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6zsXuunPbx71ngX6BaQenPNbA+Mg7i1nazF95o2HQtU5
|
||||
VmVrGQo2zRokW/ZuO9bN6xTkk9WeCniuLJmLBef2m+U=
|
||||
VmVrGQo2zRokW/ZuO9bN65Mk3nfYCJEpzMz8EnuHOsgreh18KDp4UtHG8fOCTUhO
|
||||
VmVrGQo2zRokW/ZuO9bN62oRed6hCMosT7UP35UqsiKbQbJoCKHWLyJn/Vx814Ro/Ee5KiD6gqXP3nh6dppi/w==
|
||||
VmVrGQo2zRokW/ZuO9bN6waLqc54ChZODKGJgS1pLojVY2evr/6W6eipUfB4kUV4tIbbM82aET5PVAdbZXXdUO/Z4wJ1V7uPGDDu8Cb4YmQ=
|
||||
VmVrGQo2zRokW/ZuO9bN68wHZtGYQdFVE6PwKTgvaNuRprwNE+dzFP36dxj7lYWb
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6x8dPCIFym0qQ4B6l0auqv3VSU3SG/i9eUcnpJrb1L+X
|
||||
VmVrGQo2zRokW/ZuO9bN6ziVGg/SZJQ2a2ljdz3XhcVn97lFqgG8ziUZ47BfMFG9UXbT2kS6y93cABsoh/aDUSuKrmA11kGt+hTSze7FVyk=
|
||||
VmVrGQo2zRokW/ZuO9bN6waLqc54ChZODKGJgS1pLojVY2evr/6W6eipUfB4kUV4jBljvu51ZnW8hS8WXSpu7pv1/kMj8Ak/oIB5g6oKubA=
|
||||
VmVrGQo2zRokW/ZuO9bN68wHZtGYQdFVE6PwKTgvaNuRprwNE+dzFP36dxj7lYWb
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6+Hp+GvFtSASnTbptRcIg2lSnsLRR4J22UX96CUCq+KR
|
||||
VmVrGQo2zRokW/ZuO9bN64qagL+89Aq4rR/hcuQ6/QaZLgJxtVesokbhCUzfxCwfKcyVGoV3zyER2vrKLj8C4A==
|
||||
VmVrGQo2zRokW/ZuO9bN6waLqc54ChZODKGJgS1pLojVY2evr/6W6eipUfB4kUV40d40RaKmxMWpfhvj8ZyruQ/Q/AdiPvG5CMZanDD6YE98WLACskd36bpmVVS7VPAS
|
||||
VmVrGQo2zRokW/ZuO9bN68wHZtGYQdFVE6PwKTgvaNuRprwNE+dzFP36dxj7lYWb
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6xUIvvF7vKpIldg0eDQ2GLdixkmDxxbU+OXh2/259dgakzCXh2oDJ0AfTKNrUbZ5d31ZrBNmK8mELWMQzPcKOzPm5KFJw1Mu/Hkb1SkNQs1d
|
||||
VmVrGQo2zRokW/ZuO9bN69P4p4urRz6LNH8T7D85tUmvT6fU8K2BiEON885R0KsYZZwTue89GlNh5Rj+HJ/0l8p8Xk8+ZEyH9zTSoSVrZuM=
|
||||
VmVrGQo2zRokW/ZuO9bN69P4p4urRz6LNH8T7D85tUnJY2h08qZtVSMViVJ80aOFEB7NOmEnSXBDfiqhTqlpxqE7hd3sxipptIDNtiux052BIE9Ab59zGW7HA4ampTWIfcrnofD4U94ciAzYjH7cMQ==
|
||||
VmVrGQo2zRokW/ZuO9bN68SNBDbgryQsl/pB0VGbLvqWKmuDEMs3IPB8IEm2OG3x
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6+UgxYwTsTpiHdnLypOQ/kZoFZH3aRRa3jGRdR795Y1mA6vXFA8gZ85TG3MqCavIWvAJnmCjVt23ZkwLlEM33Qocr5vG2sgJeT2xmYYZ/iICcOfrgbcyhaRW17sPNkIRlw==
|
||||
VmVrGQo2zRokW/ZuO9bN6yYgZ33nPjoy4tOZmNaX7mQaiu/N7s/Mw1Ei0aMstGjWDlGg9LgiJMyZKxaW8bZyIjtyH8MUjBVG9J4w3mR65uirBBRQcKVp1rVnwRuAvlAOObnzQPL0B/HA/xlJ0/WDfA==
|
||||
VmVrGQo2zRokW/ZuO9bN60vhRuPY/LJZF8HROzC0dFI=
|
||||
VmVrGQo2zRokW/ZuO9bN6/6qy3lEE/QMSwWTRtFJoaMcGV0W2eYWCTCr8Hkveve9
|
||||
M0ZySqkmhuHCw6olbCKv99p0Om1sGOCLOPcvWBGiKm4=
|
||||
VmVrGQo2zRokW/ZuO9bN6wgdH+0DZQge5QIlnRbbyGVIwpFYFAZXcG4ciFkbD8xGTtzX6dDhJzsy6JEW1M67sQDPORs3az4NjR88iM8Lcnk=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
o6QhOIN2Sc4SHELnst17uQbQrK2Z34ZMKBCsEar9NNzRcJW4KMeQ4yhsPKTJaw1j
|
||||
Ic1WBp01nLyRxbqJnsu2pypx+Gb9M9+y4CZIw5enWs9jY9CEkJ+mtN1RRkcQDmMZqWpTNzdr+Hy3p75kNCSdGSik+k6MbKPBA27LVqGIPTg=
|
||||
ruTTNFTdswRs4Mc+srnRk818d9d/TGGXzgPjSrVtMi8=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
jGPLgFRMa/gLI5pn0C8oszLqa5isI224m2QOfckbxLELIVt69gRzqdxrFQlcGXIa
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
n3tXewq2IYqiwFREjJjsxQv5FBS89YO3jVo+BgMdPGUBLkZx5+ZpOpx7LWu6PFKo8b9SqRNn6c5JZVzlsIkp+A==
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
xsCYviGksjEQaKpL56on/X7AnEB6uKwmFpBflqwZHQ4=
|
||||
BIa0ibHnqUboaK9kYHYO4um2nnLtPSMsHb7nUhh0kKQ6CdlvwTSeB4h8LEiuwG9t
|
||||
a7gbuXC0s2yINkxKhLLBokQAN48UxYxa6jCVIMQ9FeJoGd91ZEhhcfiymqUdYGqf
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
wgR07xfoapmx6eEnFHXXYsXheOqb+ac7ivrKomECGJh6sAOIfkvF5oIqf+7bT65s
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW/27EoqfC0X59kkH7imoHQ/iPzQ+uFBITVsVoGpItD5Q==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
AN33R+yjfqqAkAsFnmP/r/WGRgGkDEv8Fnc8kjQsJ7c32mbK3YgEYOi8MYXpOqJy
|
||||
cbvASHjpysrsjdY5RctXmG9wund6qoaXAfnCgO+o1nY=
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmXHKWKUVVa/rOrR3+fgEd7tp63QHMzA34qukyTQgDFJrLVYVJL/Ye3kNmAIiExi//aTWiBsWXWTJE2/bLQwR3ie
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
YdUmdqAC07VhbSt1h6KCDGWrMrUVsu+cay2sf0G/q6n9TVdK0jEcTi9z8Mi4uhlIHBQoCZCJNLutARg3AcC9GZkJHoO5OtM5wGrnT579QQ/33LGKQp33LdowTPKOj8mg+5XvwqiamHNJ4b6qkc35ZA==
|
||||
TQRmC0vOvJ1P+lfyS3Os4fdA9rnIPjSDuS8zcTDjbSEVtc81+Y4AUEIsuAgPRMzVhLwEUrXGM6DCeZ1rhkVK8w==
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmUzJgj0ZVdf8DkqZrnrpLRzKvaQBgq7m7DBF8Wb/aWuxeFqQz2lv84Je+M0d4O8q9Ux2G7KTGW8VqvvCK6513pJrAuADi3mTtgVX9Y0JiEdnx9iCVypIiCmLG0BR48sQeM=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
y9uLKqgxuwiJJuaISH8LNlJR2o2Cr2uNLeYPxMDYl/0=
|
||||
q4nc/jwATOMUyfSjLibfEelnou8pLYpfebj3/LvnkGg=
|
||||
7fBvPEAf72Uv1YEDXbbQ3CN3MWrD+3vkr2VJCCzzEPRhwccGf00/aNA1BGgdy8WH
|
||||
59Mj0OVU6q9AFARXxvxfN1dW2G3zJI+4zsdXTWh4XwFG18UDXnpLmLIfLIZ41jcpe1yBIt+f+JDrMrCbBNf/9Xy836/xgiba8x96DZU3Wlg=
|
||||
pcGeDqO6jWjADfc8Oyd0b2PTNAiWtNjPy+4ZuJym09tcrllO4bi9TB9YXcFHDN8ulWbcZDzkd3vYSjeW6cb+7a07iV7nvIzEjupMBYIINGsixBBRFVjl2m3gGdMptbNGHA9dcrK5ewH6POHu2UFt2t23FwcWAqOHzR3sL67HAErpzje2T7IZlttmY5tQ/RPJ4QDTGGJ3YSogtm9/Z9ZSs7wMVRGX8M2Eia5bIBLZuxk=
|
||||
7fBvPEAf72Uv1YEDXbbQ3Kl5asOP7Hk9Z+oJF57QC0c//DIVOxrgJlRJ07hlZuLdNPXnVpbKF/o/zidPewH4xQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
Ic1WBp01nLyRxbqJnsu2pypx+Gb9M9+y4CZIw5enWs8ZqmZBUF1OtUXbF0cnfKWhyLN47Y9VJ4gMAghwAahsZHCVXCB6/L26wmeLJb9nC4o=
|
||||
2+RceSNjD2iq0sRzepMyse3K/6KDWrRQWf3bA9DlS0lC8P1AVP/ryfVnqkju1FOT
|
||||
96orka/uERLyRst14azQwhCOqhTfcgFhXNAQS0hmuOEvWExeU8Y5S6VzOcEFIF/zQLgeURpx14jzr1s57LjK94c4cdiNmekvORipQcUMeV4=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
|
||||
+327
-327
@@ -1,327 +1,327 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: cjxin <cjxin@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#
|
||||
#------------------------------
|
||||
|
||||
import os,sys,re
|
||||
from filesModel.base import filesBase
|
||||
import public,json
|
||||
import zipfile,shutil
|
||||
from pathlib import Path
|
||||
class main(filesBase):
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
def __check_zipfile(self,sfile,is_close = False):
|
||||
'''
|
||||
@name 检查文件是否为zip文件
|
||||
@param sfile 文件路径
|
||||
@return bool
|
||||
'''
|
||||
|
||||
zip_file = None
|
||||
try:
|
||||
zip_file = zipfile.ZipFile(sfile)
|
||||
except:pass
|
||||
|
||||
if is_close and zip_file:
|
||||
zip_file.close()
|
||||
|
||||
return zip_file
|
||||
|
||||
def get_zip_files(self,args):
|
||||
'''
|
||||
@name 获取压缩包内文件列表
|
||||
@param args['path'] 压缩包路径
|
||||
@return list
|
||||
'''
|
||||
sfile = args.sfile
|
||||
if not os.path.exists(sfile):
|
||||
return public.returnMsg(False,'FILE_NOT_EXISTS')
|
||||
|
||||
zip_file = self.__check_zipfile(sfile)
|
||||
if not zip_file:
|
||||
return public.returnMsg(False,'NOT_ZIP_FILE')
|
||||
|
||||
data = {}
|
||||
for item in zip_file.infolist():
|
||||
sub_data = data
|
||||
f_name = self.__get_zip_filename(item)
|
||||
|
||||
f_dirs = f_name.split('/')
|
||||
|
||||
d_idx = 0
|
||||
for d in f_dirs:
|
||||
if not d: continue
|
||||
if not d in sub_data:
|
||||
if d == f_name[-len(d):] and d_idx == len(f_dirs) - 1:
|
||||
tmps = item.date_time
|
||||
sub_data[d] = {
|
||||
'file_size': item.file_size,
|
||||
'compress_size': item.compress_size,
|
||||
'compress_type': item.compress_type,
|
||||
'filename':d,
|
||||
'fullpath':f_name,
|
||||
'date_time': public.to_date(times = '{}-{}-{} {}:{}:{}'.format(tmps[0],tmps[1],tmps[2],tmps[3],tmps[4],tmps[5])),
|
||||
'is_dir': 0
|
||||
}
|
||||
if item.is_dir():
|
||||
sub_data[d]['is_dir'] = 1
|
||||
else:
|
||||
sub_data[d] = {}
|
||||
d_idx += 1
|
||||
sub_data = sub_data[d]
|
||||
|
||||
zip_file.close()
|
||||
return data
|
||||
|
||||
|
||||
def get_fileinfo_by(self,args):
|
||||
'''
|
||||
@name 获取压缩包内文件信息
|
||||
@param args['path'] 压缩包路径
|
||||
@param args['filename'] 文件名
|
||||
@return dict
|
||||
'''
|
||||
|
||||
sfile = args.sfile
|
||||
filename = args.filename
|
||||
if not os.path.exists(sfile):
|
||||
return public.returnMsg(False,'FILE_NOT_EXISTS')
|
||||
|
||||
result = {}
|
||||
result['status'] = True
|
||||
result['data'] = ''
|
||||
with zipfile.ZipFile(sfile,'r') as zip_file:
|
||||
for item in zip_file.infolist():
|
||||
z_filename = self.__get_zip_filename(item)
|
||||
if z_filename == filename:
|
||||
|
||||
buff = zip_file.read(item.filename)
|
||||
encoding,srcBody = public.decode_data(buff)
|
||||
result['encoding'] = encoding
|
||||
result['data'] = srcBody
|
||||
break
|
||||
return result
|
||||
|
||||
def delete_zip_file(self,args):
|
||||
'''
|
||||
@name 删除压缩包内文件
|
||||
@param args['path'] 压缩包路径
|
||||
@param args['filenames'] 文件名列表,数组格式
|
||||
@return dict
|
||||
'''
|
||||
sfile = args.sfile
|
||||
filenames = args.filenames
|
||||
if not os.path.exists(sfile):
|
||||
return public.returnMsg(False,'FILE_NOT_EXISTS')
|
||||
|
||||
with zipfile.ZipFile(sfile,'r') as zip_file:
|
||||
with zipfile.ZipFile(sfile + '.tmp','w',zipfile.ZIP_DEFLATED) as new_zfile:
|
||||
for item in zip_file.infolist():
|
||||
filename = self.__get_zip_filename(item)
|
||||
|
||||
if filename in filenames:
|
||||
continue
|
||||
src_name = item.filename
|
||||
item.filename = filename
|
||||
new_zfile.writestr(item,zip_file.read(src_name))
|
||||
shutil.move(sfile + '.tmp',sfile)
|
||||
return public.returnMsg(True,'File deleted successfully')
|
||||
|
||||
def write_zip_file(self,args):
|
||||
'''
|
||||
@name 写入压缩包内文件
|
||||
@param args['path'] 压缩包路径
|
||||
@param args['filename'] 文件名
|
||||
@param args['data'] 写入数据
|
||||
@return dict
|
||||
'''
|
||||
|
||||
sfile = args.sfile
|
||||
filename = args.filename
|
||||
data = args.data
|
||||
if not os.path.exists(sfile):
|
||||
return public.returnMsg(False,'FILE_NOT_EXISTS')
|
||||
|
||||
with zipfile.ZipFile(sfile,'r') as zip_file:
|
||||
with zipfile.ZipFile(sfile + '.tmp','w',zipfile.ZIP_DEFLATED) as new_zfile:
|
||||
for item in zip_file.infolist():
|
||||
z_filename = self.__get_zip_filename(item)
|
||||
if z_filename == filename:
|
||||
continue
|
||||
|
||||
new_zfile.writestr(item,zip_file.read(item.filename))
|
||||
new_zfile.writestr(filename, data=data, compress_type=zipfile.ZIP_DEFLATED)
|
||||
|
||||
shutil.move(sfile + '.tmp',sfile)
|
||||
return public.returnMsg(True,'File written successfully')
|
||||
|
||||
|
||||
def extract_byfiles(self,args):
|
||||
"""
|
||||
@name 解压部分文件
|
||||
@param args['path'] 压缩包路径
|
||||
@param args['extract_path'] 解压路径
|
||||
@param args['filenames'] 文件名列表,数组格式
|
||||
"""
|
||||
|
||||
zip_path = ''
|
||||
if 'zip_path' in args: zip_path = args.zip_path
|
||||
sfile = args.sfile
|
||||
filenames = args.filenames
|
||||
extract_path = args.extract_path
|
||||
if not os.path.exists(sfile):
|
||||
return public.returnMsg(False,'FILE_NOT_EXISTS')
|
||||
|
||||
if not os.path.exists(extract_path):
|
||||
os.makedirs(extract_path,384)
|
||||
|
||||
tmp_path = '{}/tmp/{}'.format(public.get_soft_path(),public.md5(public.GetRandomString(32)))
|
||||
if not os.path.exists(tmp_path):
|
||||
os.makedirs(tmp_path,384)
|
||||
|
||||
with zipfile.ZipFile(sfile) as zip_file:
|
||||
try:
|
||||
m_list = {}
|
||||
for item in zip_file.infolist():
|
||||
filename = self.__get_zip_filename(item)
|
||||
|
||||
if filename in filenames:
|
||||
spath = os.path.join(tmp_path,filename).strip('/')
|
||||
if item.is_dir():
|
||||
m_list[spath] = []
|
||||
else:
|
||||
if not 'other' in m_list:
|
||||
m_list['other'] = []
|
||||
|
||||
dir_key = os.path.dirname(spath)
|
||||
info = {'src':spath,'dst':'{}/{}'.format(extract_path,filename.strip('/'))}
|
||||
if zip_path:
|
||||
info['dst'] = '{}/{}'.format(extract_path,filename.replace(zip_path,'').strip('/'))
|
||||
|
||||
s_path = os.path.dirname(info['dst'])
|
||||
if not os.path.exists(s_path): os.makedirs(s_path,384)
|
||||
|
||||
if dir_key in m_list:
|
||||
m_list[dir_key].append(info)
|
||||
else:
|
||||
m_list['other'].append(info)
|
||||
|
||||
item.filename = filename
|
||||
zip_file.extract(item,tmp_path)
|
||||
|
||||
for key in m_list:
|
||||
try:
|
||||
for info in m_list[key]:
|
||||
if os.getenv('BT_PANEL'):
|
||||
shutil.copyfile(info['src'],info['dst'])
|
||||
else:
|
||||
shutil.copyfile('/' + info['src'],'/' + info['dst'])
|
||||
except:
|
||||
pass
|
||||
|
||||
shutil.rmtree(tmp_path, True)
|
||||
except:
|
||||
return public.returnMsg(False,'Decompression failed,error:' + public.get_error_info())
|
||||
return public.returnMsg(True,'The file was decompressed successfully')
|
||||
|
||||
def add_zip_file(self,args):
|
||||
'''
|
||||
@name 添加文件到压缩包
|
||||
@param args['r_path'] 跟路径
|
||||
@param args['filename'] 文件名
|
||||
@param args['f_list'] 写入数据
|
||||
@return dict
|
||||
'''
|
||||
|
||||
sfile = args.sfile
|
||||
r_path = args.r_path
|
||||
f_list = args.f_list
|
||||
if not os.path.exists(sfile):
|
||||
return public.returnMsg(False,'FILE_NOT_EXISTS')
|
||||
|
||||
#追加原路径
|
||||
src_list = {}
|
||||
for fname in f_list:
|
||||
if os.path.isdir(fname):
|
||||
s_list = []
|
||||
public.get_file_list(fname,s_list)
|
||||
|
||||
for f in s_list:
|
||||
if os.path.isdir(f):
|
||||
continue
|
||||
src_file = '{}/{}{}'.format(r_path,os.path.basename(fname),f.replace(fname,''))
|
||||
src_list[src_file] = f
|
||||
else:
|
||||
src_file = r_path + '/' + os.path.basename(fname)
|
||||
src_list[src_file] = fname
|
||||
|
||||
tmp_path = sfile + '.tmp'
|
||||
if os.path.exists(tmp_path):
|
||||
os.remove(tmp_path)
|
||||
|
||||
with zipfile.ZipFile(sfile,'r') as zip_file:
|
||||
with zipfile.ZipFile(tmp_path,'w',zipfile.ZIP_DEFLATED) as new_zfile:
|
||||
try:
|
||||
#过滤旧文件
|
||||
for item in zip_file.namelist():
|
||||
if item in src_list:
|
||||
continue
|
||||
new_zfile.writestr(item,zip_file.read(item))
|
||||
|
||||
#追加新文件
|
||||
for src_file in src_list:
|
||||
new_zfile.write(src_list[src_file],src_file)
|
||||
except:
|
||||
return public.returnMsg(False,'Failed add file,error:' + public.get_error_info())
|
||||
|
||||
shutil.move(tmp_path,sfile)
|
||||
return public.returnMsg(True,'Compressed package file modified successfully')
|
||||
|
||||
|
||||
# def __get_zip_filename(self,item):
|
||||
# '''
|
||||
# @name 获取压缩包文件名
|
||||
# @param item 压缩包文件对象
|
||||
# @return string
|
||||
# '''
|
||||
# path = item.filename
|
||||
# try:
|
||||
# path_name = path.decode('utf-8')
|
||||
# except:
|
||||
# path_name = path.encode('cp437').decode('gbk')
|
||||
# path_name = path_name.encode('utf-8').decode('utf-8')
|
||||
# return path_name
|
||||
|
||||
|
||||
|
||||
|
||||
def __get_zip_filename(self,item):
|
||||
'''
|
||||
@name 获取压缩包文件名
|
||||
@param item 压缩包文件对象
|
||||
@return string
|
||||
'''
|
||||
|
||||
|
||||
filename = item.filename
|
||||
try:
|
||||
filename = item.filename.encode('cp437').decode('gbk')
|
||||
except:pass
|
||||
return filename
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
QRASP55VO/1DQ98p1csw9A==
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
dBZyCsfrbwqvA0sbdGrIGg==
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
n+0ptngHIPIjFuMNQ53bfj+Na/fdhk6k1yTpAwW7j353Dw920mEqQQZjykAHeRmp0ZD/P3ftGifsmPOMf2b7XdEqyZH0yl9kjaUugj3dYPI=
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
jh3cxzkA2htccqfZRKAUdI8r17q57nOGP4OxbJlL1NAnrF4weHnS0MpT6C6jbrX5
|
||||
I8MGJUwtjfcKc5w4E0SmjHtl5KRuv0WI7NyW3SlEwCrZmcmaREiC99KS4CzwW5Su330khbLdQaeuAWr4x/NqQCTep2zIARzdXiKXPh1Fe+M=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
Hf+bBTgRv9pVfall8ODpvg==
|
||||
I8MGJUwtjfcKc5w4E0SmjHwLsErBQ84ek459TV1n0Iir/P4mdpfwDI34s6+8CBN0
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
K3QJU/hV27C5FAVoZ+avNNMfDMygeonfI5TFnvUHjhU=
|
||||
X9BNoFOwiQAnMPqEk6FnbzU/oA+chL/aEAzGH80mBrNNxRMBdiGPqgDUeLF6rer2
|
||||
hUVhKZtvg+FKessuieMZGkP/5FS8EfJsx7HCvhsTdvM=
|
||||
KbrESL0Rr2jC6vOleUlueMUgBS8ubHMHEf/dewOmXjc=
|
||||
yUFFATi+ZVxTJRU9zfoit8QIFboIm1z3wG2Pz/1LIy0=
|
||||
CjJS7KrzKM18mlLqJK9jKTB717Vvrubu5ix9tb047ao=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
9GxZpCRwMRDPejWR2Vvf+LKn0tNtFKp8Eh2tnr4Da9U=
|
||||
6c3cWGGlsEf4q4E+EjPFyg==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
6d8NLnHX3WuS3g79bJvyhLTeka+iJoxis1kUHdyggy+yXh3Xc8xsyir/5NbKP+Sj41j2UHgL27dZFRsmbh/P+Q==
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
0LFyB+q/4AUBkCrX53xYJedFoNZHYELHOLu/R25oBrqozNv9g917+/ANMSb6X+WR
|
||||
yqM179SzW9HnBHozkU+IlaI6kf6Fax7Db/qE4wQMDFqfwVE+4rG3+IJ9S3c+p3Wf
|
||||
akHibliG6j9uvBEg96vRehUZmhX3a+KyYm/Obf/H764=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1VHvxkEcO4espNMpWHmnH1EgArAJXS2MAairjwNzV9c=
|
||||
b4OJVZe8QyIpjuTpKXDL9A==
|
||||
wQn8ViRVbUL8OLSIgBD0ID21VtRI2rJC6jqthFugWvWVef56vW1JZ4xiXoQ3GDDo
|
||||
usrsES3VVkgHW6tBbEkpHTeLztsByVaJibbFv8kSFIM=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
l+sL2BKY+z3yDMAsWI51b39VWekdKmbfrOabwvVHTbGfiUobxgPhHW2OIZyeGUJ9
|
||||
wQn8ViRVbUL8OLSIgBD0IO53Ya1+ckG2IX47+ykaGJU=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
MxWDzXEQjj6mgdfarjHFtAA6unJa5l9pTo0P8ga3JDU=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
x41zVQ6DCtWXndDIq7U8L+5quM3ARMCnVm34NUX7l/TJzZZ100EvdUXHXI2cFH4H
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
NNh1PlSD8WUnUEbz+BU/P7D7U0y87ntgFdQV5REShmme9ACxsySMBZr2gsEQniKL
|
||||
c1XU6vxl7MsQKGo3r4amMsSWef3BumXlCWI6QCsp6pMACoHb/XNQfx2cpKV7J/MH
|
||||
akHibliG6j9uvBEg96vRer/Fg5zTlM8oj8hSAsYq018=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
YdUmdqAC07VhbSt1h6KCDASPIXTwTSkv8cm4ToJ+lpo=
|
||||
wgR07xfoapmx6eEnFHXXYmnjxw2aWD9jyym26bSe8wdUky12ZBuFKfAUxS++Pix0
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW/27EoqfC0X59kkH7imoHQb/TQW5074PHVFRKqgD5aSA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1VHvxkEcO4espNMpWHmnHy+YX2/U7Ip4Uqt3suxNhindpukzgQ1aM+PshcW/1dV1
|
||||
LuO0LAjc92aYQU4tSUEvi4x4NJPWR/eKWjRfKMSRL8o=
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmV/41TA4054wrqxXx/Q1i8cmtFJNrxypDZNiWIVVjiYLA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
JbnXIK/axHVmA2plDNFCpPYlXWvPB/7lIz9ynMkifTY=
|
||||
ei/1A+2pKZSasjYF/t4qojBnh7Bi8Fen8Fcf8mKjT9IuWg8ZCZGedub8Eqjf8qUh
|
||||
4nsuLyRybkZg8C3fJCsRPXDWwLMccXwEpFBdFK0JOvg=
|
||||
ZFD6pnBshb3mpu7xvvuMLemrazA4ssXDDuW5SINX4ZLsvLIwaJ4YyDANze64OGqUEj7NCJs+t+zkcUskHr+gqw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
g5xFPP9LKBd4uktrRYzGf+p1NdL+k6huN6CrzYXY3fPVQzhtKStMTpRTZpRqmhGR
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
wkESzX/Mo7zNrX6wCsHIMgfYkIJy+Dcvs4tK//49fTc=
|
||||
wlLHv6kT3Q/RmtMBN4nDAbqo0o2IA7mU8WVNqZvoB5I=
|
||||
VmVrGQo2zRokW/ZuO9bN6+qRbBr2ygG3RGcAIOk727ylzODmV8VRqZ4YKvduSUCu
|
||||
VmVrGQo2zRokW/ZuO9bN62psx0nYMGJaQ1S1BUtE6l8lgsopQJ3Qf5syQpAasAAf
|
||||
VmVrGQo2zRokW/ZuO9bN69Woqo49I0Fga24Nj55N9ZL6pyjjGewhvRJVBn8x2mvRw+9QouFIpzWY1J2Ub+ZqxCSNlCNDuqqN6YMHyK4kxCg=
|
||||
VmVrGQo2zRokW/ZuO9bN61e1I6gZaVwmbMEHc7jd9wFEHpeilcxXyCkd5bmWx/yK
|
||||
VmVrGQo2zRokW/ZuO9bN69+qNrAfkaoVno2zP/PIMh/5aA4AiEej6zodAVzZFzS0
|
||||
VmVrGQo2zRokW/ZuO9bN6xT3wQu8/ZV37F/D/EekYn8LNRE5UkGbTG1UxYqNO1dyU2pay/FWt6r8mJiKZ4UU/g==
|
||||
VmVrGQo2zRokW/ZuO9bN64KhHtDRs0SmcOS1WVIbDs4jrgwkpIqneJssR9hHHlJ3UJd9tZzLLz6C+UQLUJWWGbgxXo0UEEapI14RLzluAUk=
|
||||
VmVrGQo2zRokW/ZuO9bN64KhHtDRs0SmcOS1WVIbDs6tF3Tt2+gNwTBcUtu+YYQKSt4+UQPUctZ0/+hfCqv3GxDub0pA8qeNN8AxvOE+5lk=
|
||||
VmVrGQo2zRokW/ZuO9bN6xT3wQu8/ZV37F/D/EekYn92m0FWAHkcFEifdcSefZI3
|
||||
VmVrGQo2zRokW/ZuO9bN6xQU/k6xhXMbxscs7Gix8nNqUkjAknQH3LrGVvAyjYtQ
|
||||
VmVrGQo2zRokW/ZuO9bN6xOutEc9teLv333RLphPxTSZMBPTZ5nEHEAZCqisJAYdx733inB6pPVPHnS53cxkslRzdzhPLD4mmySs0XcaZo8Yb7xMuMGGlmbahCRF6eC3yiiMtXXp0R7BViTpiJ04fqWtzkElISMu7z4pkkwr23TjUMjTjCelUG9Lwgmt+EiK
|
||||
VmVrGQo2zRokW/ZuO9bN6wv73IH9kSzXKMUmUPacSk1KDsdrjROzTN1kzduuP0l3
|
||||
VmVrGQo2zRokW/ZuO9bN69lJPu1G3iX01kmj1/0ynPc=
|
||||
VmVrGQo2zRokW/ZuO9bN63p1oaV/8/rZOHP3bxdBsLvxN3810q5P2uCqBbefHbrK
|
||||
VmVrGQo2zRokW/ZuO9bN6/kiIWH8hJ6dJOo/fnNj9VLcBHtqpOZ/Rc4AjXcEm1edHKkbtiFAlXrzE+rfp/AeMQ==
|
||||
VmVrGQo2zRokW/ZuO9bN69jIxF5VISZtC2vxWRknx7k=
|
||||
VmVrGQo2zRokW/ZuO9bN69+qNrAfkaoVno2zP/PIMh80w0dM3z0phdMS+lT6j/xo
|
||||
VmVrGQo2zRokW/ZuO9bN65rWaakWr3uiXA345yT9jOU=
|
||||
VmVrGQo2zRokW/ZuO9bN65abAZ39yZLyKCl4nd6eov4HdKauw4+toNc5YoXvsAeW
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1VHvxkEcO4espNMpWHmnHx0/qyT1YxdKfIVIaA4qitI=
|
||||
+plE/1bhdo64kO07cLlUXzzWH25pNAS0eDxp8hnHILg=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
J24jXQQti6wQv5pCoF2ZrRvdf2ev6P6vInKuFAO8eQfewP9/G67aA1dZDLRwjari
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
NNh1PlSD8WUnUEbz+BU/P7D7U0y87ntgFdQV5REShmlP+1p+XjT1dvUjFUZHsqC6
|
||||
c1XU6vxl7MsQKGo3r4amMsSWef3BumXlCWI6QCsp6pMACoHb/XNQfx2cpKV7J/MH
|
||||
c1XU6vxl7MsQKGo3r4amMpPnl/Q0nxs4Ul/v+JmLHipRvS1iO3+JhmWzafMyTI0p
|
||||
akHibliG6j9uvBEg96vResIm2pvfeBRQxNU2J0BQeUc=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
YdUmdqAC07VhbSt1h6KCDASPIXTwTSkv8cm4ToJ+lpo=
|
||||
BIa0ibHnqUboaK9kYHYO4um2nnLtPSMsHb7nUhh0kKQ6CdlvwTSeB4h8LEiuwG9t
|
||||
wgR07xfoapmx6eEnFHXXYmnjxw2aWD9jyym26bSe8wdUky12ZBuFKfAUxS++Pix0
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW/27EoqfC0X59kkH7imoHQb/TQW5074PHVFRKqgD5aSA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
/0ULpLqgTvInFD0r5hHANoosZ+xywkOR5dozStfmlYk=
|
||||
YSlit6erKXylrjSZnvyW8I3FYH6DLcfYpMAlko6lQqVBBd1eDeDGaujrHWIOJkcI
|
||||
YSlit6erKXylrjSZnvyW8CCccEStX4fvFvduMtCGi54=
|
||||
6Vd1Vz4KEbM/6qVZBGLAGuJhapKEU8TBPzOQYI4q82gnJ7Pu1Da4cxfKJ3J95+e7Z75/5e7XrUkjQFagToxKXA==
|
||||
wlLHv6kT3Q/RmtMBN4nDAdAMeIPpwO0Pgawv937x0Zw4iwEVDD1EIlJA37GxF8mZ
|
||||
VmVrGQo2zRokW/ZuO9bN64/tCOCyKu41lsl+3BVlFMtjVa1DXtvHbVFGS5luzEIFtQp9eHGpneVvKz65gzXCXQ==
|
||||
VmVrGQo2zRokW/ZuO9bN69Z4WTbfjflDn+PHJe4HyeBCMRIQIdsxtS/SkQUyTK46
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN64IUBVOpZieySJUi/5Xp7IP9i2hr//841YnIEqNDctKsA4PCQR7FmaZMQHs7tdC+NQ==
|
||||
VmVrGQo2zRokW/ZuO9bN63KtgQxYoQMLiw/swXgEzq6F5dbUK15QUQFhJ/fqYDb2bGgnr3J8HSW6FkIPXw/QAPGbSGA6euyj6sY6jr9uD88=
|
||||
VmVrGQo2zRokW/ZuO9bN60+Gj1vDNaFgHQa9qY+WYQ/+8quDVQ7mW+ZFMiCB6dK3zTXaMhAFlgEsY2XTlgH4hQ==
|
||||
VmVrGQo2zRokW/ZuO9bN60dNkfoHcjUpCVMrBt5WSA9PCuYzYl0QLyyWqlMopPgY
|
||||
VmVrGQo2zRokW/ZuO9bN6zZcpHqbLPCfucCocPyjGlY=
|
||||
ruTTNFTdswRs4Mc+srnRk818d9d/TGGXzgPjSrVtMi8=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
6JhaWzGWadTJ3yzCk9OQNgkLy/m1ahTUuEy+6FiV49HNwHkAN2ZMxFTsufeIA0ig
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
dar6N0tUAb9rU8/aX1b3tGumQ1hhfk8O6qr6gmiQ1+eBvZwFkpECn+RP444+i510
|
||||
c1XU6vxl7MsQKGo3r4amMsSWef3BumXlCWI6QCsp6pMACoHb/XNQfx2cpKV7J/MH
|
||||
c1XU6vxl7MsQKGo3r4amMlEDkaPg52QqeaL1e16aTiZGdP9MF1i1K/F0icaNF/FRZY8CjFaji8Ecm2WEpXZbMiyduIw57U2lMT6kzLqch3Y=
|
||||
akHibliG6j9uvBEg96vResIm2pvfeBRQxNU2J0BQeUc=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
YdUmdqAC07VhbSt1h6KCDASPIXTwTSkv8cm4ToJ+lpo=
|
||||
BIa0ibHnqUboaK9kYHYO4kqIZZgv1yXQHpqfJ4aNJ54bUNUYTYq/0A+dhHby52Au
|
||||
wgR07xfoapmx6eEnFHXXYmnjxw2aWD9jyym26bSe8wdUky12ZBuFKfAUxS++Pix0
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW/27EoqfC0X59kkH7imoHQb/TQW5074PHVFRKqgD5aSA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
6Vd1Vz4KEbM/6qVZBGLAGuJhapKEU8TBPzOQYI4q82gnJ7Pu1Da4cxfKJ3J95+e7Z75/5e7XrUkjQFagToxKXA==
|
||||
1hs1FfIPISXmd7TJ/r+Vl5VOoCywAZyr7zSPYceKQIcrfmFscSLitBH8rHfUTRshPd3qsDNW2TEFVB/BherqRUPAAaKNdUCadxkxouQ603/UPQa2mdlVSAGn2R+CvNrg
|
||||
VmVrGQo2zRokW/ZuO9bN650CvvO4YLL+rKCQnmVaPF2En1jKNRAIMYaPmWw4DTM2qNuk40r70LOd5/jqlUfMYw==
|
||||
VmVrGQo2zRokW/ZuO9bN6wsF8dCAuyXrReoI3w9Yj8ejyyRZrswtbKGtDKu6ywDGElhkS5s5y7BVqVo+FqDhvA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6wOXhaCTOJSjUCWUfjx+YyYNeSRhAnvmOzc5j0wt6pWe
|
||||
VmVrGQo2zRokW/ZuO9bN68wHZtGYQdFVE6PwKTgvaNuRprwNE+dzFP36dxj7lYWb
|
||||
VmVrGQo2zRokW/ZuO9bN6xrJVNh48JOJRHCQYI4xAH6seRNi5O7iARUSsCPjTbt2
|
||||
VmVrGQo2zRokW/ZuO9bN6/GmqY1U6uFDyEbXCwKITV7VrKjU57dBsJG4vNk6MQiq
|
||||
VmVrGQo2zRokW/ZuO9bN657WYPgEitoQAm574YXmF9lUB867LK9es4C6vHCx401D0rMP+Q/+dVAUlvxCaivz4QRggUPK+VUMIqZGEHb1ljU=
|
||||
u8vW5y2SRttIHP9hhx+fqksl4XiiUx+QjIOk2+hITXxAagiDFp3uE2PeHg2zFP6D
|
||||
96orka/uERLyRst14azQwhCOqhTfcgFhXNAQS0hmuOH6nbHs2WDQfzsBPtsBHumfOcU290Wam9UwXjcW8zT/eaFb4gRZNo5rRuNz1TQ6cJU=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
O2CqINTuIULxX7Gu5GskT/Nm15YFovaVXDj8ylNfQi3d2Qbp7uZYhyvrRE1b06DK
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
t987AUZxQR72IPRcAqvQ/tuxrpVopv9MhEHHX4HHOFnF6WZD8PVxYK60YbaBpzoa
|
||||
c1XU6vxl7MsQKGo3r4amMsSWef3BumXlCWI6QCsp6pMACoHb/XNQfx2cpKV7J/MH
|
||||
c1XU6vxl7MsQKGo3r4amMpPnl/Q0nxs4Ul/v+JmLHipRvS1iO3+JhmWzafMyTI0p
|
||||
c1XU6vxl7MsQKGo3r4amMgGxGyqG90Nz+St+6838nV5Hy3ZAmDi9Ecxx2gyS4yZO
|
||||
akHibliG6j9uvBEg96vResIm2pvfeBRQxNU2J0BQeUc=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
YdUmdqAC07VhbSt1h6KCDASPIXTwTSkv8cm4ToJ+lpo=
|
||||
BIa0ibHnqUboaK9kYHYO4um2nnLtPSMsHb7nUhh0kKQ6CdlvwTSeB4h8LEiuwG9t
|
||||
XKWK9LfYDT5w2LEWWxwkc6l2k+0eByijzzjX3gaj5k8=
|
||||
wgR07xfoapmx6eEnFHXXYmnjxw2aWD9jyym26bSe8wdUky12ZBuFKfAUxS++Pix0
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW/27EoqfC0X59kkH7imoHQb/TQW5074PHVFRKqgD5aSA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
6Vd1Vz4KEbM/6qVZBGLAGuJhapKEU8TBPzOQYI4q82gnJ7Pu1Da4cxfKJ3J95+e7Z75/5e7XrUkjQFagToxKXA==
|
||||
1hs1FfIPISXmd7TJ/r+Vl5VOoCywAZyr7zSPYceKQIcrfmFscSLitBH8rHfUTRshPd3qsDNW2TEFVB/BherqRUPAAaKNdUCadxkxouQ603/UPQa2mdlVSAGn2R+CvNrg
|
||||
VmVrGQo2zRokW/ZuO9bN650CvvO4YLL+rKCQnmVaPF2En1jKNRAIMYaPmWw4DTM2qNuk40r70LOd5/jqlUfMYw==
|
||||
VmVrGQo2zRokW/ZuO9bN6xIOVX/jmHApY1vYi7p62efnJA3RwDkPnY0p8K402cIDtEidZgORRD2w1kwOy8ktqQ==
|
||||
VmVrGQo2zRokW/ZuO9bN655gCVY8shnXyf3BTAhOCEseA+FmLUdf2zTZRuj4Gshw
|
||||
VmVrGQo2zRokW/ZuO9bN68wHZtGYQdFVE6PwKTgvaNuRprwNE+dzFP36dxj7lYWb
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN657WYPgEitoQAm574YXmF9lUB867LK9es4C6vHCx401DoXSgI87+dv1IXTMOs5pogfgyGxM8q3ngzmVKGd4oLv0=
|
||||
VmVrGQo2zRokW/ZuO9bN61dxACaOXPUs+kKrrvH8m6V6uiphjbaKMJwgGptqRuCR9Cj1NHc2Yj+FdsrtTHaQoM49Sy0pv/Om5EdLdtFFjJ5lg/dZmMsubirsi45j9AT4
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
u8vW5y2SRttIHP9hhx+fqksl4XiiUx+QjIOk2+hITXxAagiDFp3uE2PeHg2zFP6D
|
||||
96orka/uERLyRst14azQwhCOqhTfcgFhXNAQS0hmuOFPUBPOYID993hmow4PfQhItCgegxeWNdVD4M5OUfiqV7yqGqj3L0yy/roD2hGd6ho=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
D5nlraEpeGmKL9lxoq591txjX2tGuFl4D7WJZ/91lnMQ6WZrDXvU2okqtgoaqWSS
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
VcOpbkIFMz59VlIHGus1M+TodC/Ia97E/RilXZKKBR29V7X/RlCXQzuWibEOEJfo
|
||||
c1XU6vxl7MsQKGo3r4amMsSWef3BumXlCWI6QCsp6pMACoHb/XNQfx2cpKV7J/MH
|
||||
c1XU6vxl7MsQKGo3r4amMjvzqCkQbmHuG+orSe7QiThO3NRqf8lDLQklcqf6u2x4yWOeax5QyyroyrE443cDvw==
|
||||
c1XU6vxl7MsQKGo3r4amMlEDkaPg52QqeaL1e16aTiZGdP9MF1i1K/F0icaNF/FRZY8CjFaji8Ecm2WEpXZbMiyduIw57U2lMT6kzLqch3Y=
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
0NowFhvxcpa35RgS0fkY9ejQNksclvfpv75ehCpzJxQ=
|
||||
rTZ4GehPWBQfXf82D1FIzy9S8wkwIsZ3K9dIGaM8SqbP43GsEZhJZUm22nJ+2gPqOOxkmco8qaHhW3SBF16WUg==
|
||||
YdUmdqAC07VhbSt1h6KCDASPIXTwTSkv8cm4ToJ+lpo=
|
||||
BIa0ibHnqUboaK9kYHYO4kqIZZgv1yXQHpqfJ4aNJ54bUNUYTYq/0A+dhHby52Au
|
||||
77Mf9+1xBvZiUeNTtU/s60Kyn+UEu/OgKFt23E+wd8BiTmgbWFTzjcyPW/imPN9p
|
||||
wgR07xfoapmx6eEnFHXXYmnjxw2aWD9jyym26bSe8wdUky12ZBuFKfAUxS++Pix0
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW/27EoqfC0X59kkH7imoHQb/TQW5074PHVFRKqgD5aSA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
wgR07xfoapmx6eEnFHXXYmSt8oPS+2lwNla/wCY62SBZ7HAsGrtjJH7dzi+5hXSr
|
||||
NqhMbY8+EQI8zhTG6Zh2I5csQ+/eG6egKX2sKZJStJZk02bOBi20A8UHGNy6sybt
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
IZj4TYq2HlScfSdRkI+QP263Ug7hf7sm5bqxRn1G7j8CZM6KmOHJcbEZNXo2mkEA3MxUp7pEuHhp8IfRMvwD6SZPogdTtHhT5unY8iIrUiU6GaMq6uosuXq8hjxV9nUgwa2iqC1n6Ziz6tiDdPy1mw==
|
||||
wgR07xfoapmx6eEnFHXXYm7IOJ/6J1NThWNK2EdPRzYwWPvLP+jlqDp61mwE1mzG
|
||||
NqhMbY8+EQI8zhTG6Zh2I0BiMnuwr8mLUTT6rraGmzoW2r/izQNInq2UmHNhRbv+
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
6Vd1Vz4KEbM/6qVZBGLAGuJhapKEU8TBPzOQYI4q82iJ2tHfDbjNfVtFa8KsTVYDHjxHgDB1l5TRkSasuLGs5g==
|
||||
vQwaisdUFOt9b0SJYuH/nrHigrTUtycF35lf58xGUQo=
|
||||
VmVrGQo2zRokW/ZuO9bN61lflwobhmxel33RwHEAzsw=
|
||||
VmVrGQo2zRokW/ZuO9bN650CvvO4YLL+rKCQnmVaPF2En1jKNRAIMYaPmWw4DTM2qNuk40r70LOd5/jqlUfMYw==
|
||||
VmVrGQo2zRokW/ZuO9bN6wsF8dCAuyXrReoI3w9Yj8ejyyRZrswtbKGtDKu6ywDGElhkS5s5y7BVqVo+FqDhvA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6wOXhaCTOJSjUCWUfjx+YyYNeSRhAnvmOzc5j0wt6pWe
|
||||
VmVrGQo2zRokW/ZuO9bN61ODJTwuVdYa2e77kV4UyyiKC6xmDTYLpzmUEL6iaKIotT6XRfjdpuPhvefHRzC+7lCYolxcDYktKmTY39wnf+k=
|
||||
VmVrGQo2zRokW/ZuO9bN63p1oaV/8/rZOHP3bxdBsLvxN3810q5P2uCqBbefHbrK
|
||||
VmVrGQo2zRokW/ZuO9bN655297gigIv+4Ufy0bubbx7ffTJUoURR64bKe908x4ap
|
||||
VmVrGQo2zRokW/ZuO9bN62cJZxyhxghVn78AgYWoneU=
|
||||
VmVrGQo2zRokW/ZuO9bN63LTkM1jyAeOymc1jas3GbdSOgZt1gFP6QuzR+PijaPfkXI6n5+LDNetR25SN0GXgg==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hkns33MIHJ07fAs3bEPA9prEegTrYMIIXPrzC4jD9xKXsA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6+VE/nQEHJOLSC1DnxvG5TiVhVg6gVuqdGuJQhlv12yWuKoI97jUkrKrXkDjch0nxA==
|
||||
VmVrGQo2zRokW/ZuO9bN66Stm18E9cFphVzr4DVvkp0eMQP2KdIRCCvQSRwvi/ogRLfVX0ez0AMMWvL6BswFfzkKtdTc18Qoh/tgpwV2o+Kht3IBHRneKuZIpe6ZGcaJTVPTytE4Bqe8/Zl36QIobQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6xSxF3eqlbsmTCkJFu+pH46xsXmb4t0jdQQcKfcGkEaM
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HkmgImK713UKKRnRLyQBV8gyjNySqhD1ER71FyIggw6WuQR8Ewb2c166ROgirDfRPbjt18mJAcMOqb3NN1zON9EtMy2glRMsNpgCk7fMSHxR7K6cqkD4EtrpnRF/O2N/bUo=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6yaURb+J41vJInDMdNBqADJBPzFwU1DWEhzV7Igw3NGvcy7cQ4IWtwYwzl4xxnS4q7aao1GGQ/lpjefMWmVC5io=
|
||||
VmVrGQo2zRokW/ZuO9bN63LTkM1jyAeOymc1jas3GbfaLzRNSm7AkFFrFp+7ESwXtG1lg7SuOb/Fvk+nDWM/LdSTEbaou9dv1kw9992cO1wzuimxPOSJKkAKKU5hd+6f
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6zsPJOFHzvayEpAPvGiJ0lAWXca0TugmxSi8hINZZvoHQ1Y8EIw5ZU/3qx6IfU7mzw==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HkkqG04WXvd0zYTVxLMDUCWknQtobuOLFvBEBrZieoy/MQ==
|
||||
VmVrGQo2zRokW/ZuO9bN61TKHwbNGf/2Ub0vd756U9O0Gtl0vapnf7HpdYx4U2ib
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hkk6a/inNeVFTn9NarE6P/3LG5P9KtqHegfYsmaf6Actxw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN68jWU1VqsROJtSXOaVTpeKWZDZ536km13XBycpNTV7Nhu/w7ITcYY+83JHaD4GV4Ww==
|
||||
VmVrGQo2zRokW/ZuO9bN67FJHoI0w8vvrPd3RbddRrDBThH0/mxaArrt9hDAJ1SFmBLkHrD34oMhy7mWtOnyYg==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN65aFRI029wWEhVZc+cvXTRpzda0UlKTw9izNui/xkgdD
|
||||
VmVrGQo2zRokW/ZuO9bN62HWtxZ2I/oCwtyWP0WSTIg=
|
||||
VmVrGQo2zRokW/ZuO9bN6ylpzdD3c1E8cbuPHoSW5RFJzxWCEvXq+6grREYT2q2eRpfKq4CUkXaSg9PBb07Brg==
|
||||
VmVrGQo2zRokW/ZuO9bN65qgzI0QqVLALq/Lz0RhHgVj4W6v2iAhy3bpNtZbOHJ8qR+FfOTDkpmrnn3Bg7loWg==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HknNd/k4iuNp2bbqaDmaAfko6jVO83Qfz+7nZDbM61ZOu8HuZ+ZNu6hMvpayaQR5SAc=
|
||||
VmVrGQo2zRokW/ZuO9bN61TKHwbNGf/2Ub0vd756U9O0Gtl0vapnf7HpdYx4U2ib
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HknNd/k4iuNp2bbqaDmaAfkosj3Q/Uyc4ih1OKYxi2Aoat/XPMKk6ZFw9dS97mdyNCW7sbOTUzQ7vKis/hh/FWBl
|
||||
VmVrGQo2zRokW/ZuO9bN6zTwEIRXNDisRd1QRhA8x1E=
|
||||
VmVrGQo2zRokW/ZuO9bN6/6TnYYUnVY4bZC18wJU6T0=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN67XKiXTToYD4Xj8EJf9tU1/Vu+G41TBzTVvAU2KLSeCv
|
||||
M0ZySqkmhuHCw6olbCKv9zQJzSQJo4Zslq06bXS41SQ=
|
||||
VmVrGQo2zRokW/ZuO9bN6zM/X2hHBCd+n2OGnnATmrTcB3+DRCAF+pezmRjCID0udaZbU9+Bp25aQzLB8QDwQjJOciYA4ZMGenxD3oVSnPjhf/xssdSo8p33UNNP+7LnwEXEbYt+fXn2F5oiKjC6Gw==
|
||||
96orka/uERLyRst14azQwhCOqhTfcgFhXNAQS0hmuOGez0gsOf0QeJW43sHDXr/9AmAy18p0NZvV4WTviIGdP9rl3wBU2+XWJNGEpDCn6tY=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
mObL0pW76xtWwwYeubgb11DPfOo/O10pxYUkfDIVCjm8OCRNT0T/bbX1vgDt/X1W
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
H7d2MP+WgR9k+129/mRN7ij0WzXIk6KGh6j7E1fgHISsYBh1T2OGWCH8QUwPOkcn
|
||||
c1XU6vxl7MsQKGo3r4amMvdbawOnt/oBPSHXSrswDVS5Xue1Y7sB0F2vPYt641B/
|
||||
c1XU6vxl7MsQKGo3r4amMpPnl/Q0nxs4Ul/v+JmLHipRvS1iO3+JhmWzafMyTI0p
|
||||
c1XU6vxl7MsQKGo3r4amMqf9zivp0Qb6thhCnxaiYdHXwUNLWpYP828px7Gieygp
|
||||
akHibliG6j9uvBEg96vResIm2pvfeBRQxNU2J0BQeUc=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
YdUmdqAC07VhbSt1h6KCDASPIXTwTSkv8cm4ToJ+lpo=
|
||||
g8q6WqkWsk4SUh3d5nzGDIJanaAux29CDdQxdeG/k+U=
|
||||
Vyh8kMpaq2Q+odra9mDJ3Acz3kaMgWRroPCWRIzYRMY=
|
||||
wgR07xfoapmx6eEnFHXXYmnjxw2aWD9jyym26bSe8wdUky12ZBuFKfAUxS++Pix0
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW/27EoqfC0X59kkH7imoHQb/TQW5074PHVFRKqgD5aSA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
nZKk1bbhIicHthktrQ3ySmJb3nXruK0WPj1O/nD1Op8=
|
||||
HI5OOAOTfAAnGE3XBxyr2vdUoaKdz9Yp4Em51oFqNhU=
|
||||
mZ9rrP32sP7RJKYMPGILD+78ba2l0mR6sa16eW97WcI=
|
||||
O3CUgrw2GJfB+mDjH5+NdlB3aQOXnKkk0z1WAt9Jmo/evqziM8DhkT0YrYGb4COh
|
||||
VmVrGQo2zRokW/ZuO9bN67lx9HSk8eNN2hBCO4HpKRk=
|
||||
VmVrGQo2zRokW/ZuO9bN69ZjyuXvRyGNy9kZJ0BSUPrXcl5zPRPxpUUNlqBFMfTepJuwObNjyv5s1Bwxw+0zHA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6yiPlSW1IkAq8PnO6zy+iP3jJCfd1bhtOH5rekZFEjXi
|
||||
VmVrGQo2zRokW/ZuO9bN6yIV96dETdHvOTzc1eoxsu7+haDOTWWWdxKhfAdfjn09
|
||||
VmVrGQo2zRokW/ZuO9bN68wHZtGYQdFVE6PwKTgvaNuRprwNE+dzFP36dxj7lYWb
|
||||
VmVrGQo2zRokW/ZuO9bN60+BaOrNhyGitXORdqvsMmwFtJw9x+0nfzpYbP/xMELoydQeOelN/AlsLE8govEqlMQrfUl1PeNk2rX8fh0ZElrak4Q4jLc+GGiQ0DLMMpnHYH/V4LeOzo0DpkYIcND3BA==
|
||||
VmVrGQo2zRokW/ZuO9bN60jWe2OHiR8czCXypGRfxf3KT4lPFL0wUA7wcV6fbrUq
|
||||
sobCGpmMf4/g7+HpPqBjC6hatZ6rUY3AAzqC73FJ58Q=
|
||||
VmVrGQo2zRokW/ZuO9bN6xYvvPJ68rqA+nqtjvksoecuaI1I6HrJYyQuBkEcxg38GjzrZVp9q6JUUtfh0kiUIfnKe6wTljkMngNv5DLroHo=
|
||||
VmVrGQo2zRokW/ZuO9bN608vqClPKbLpxLXcA30riX215gq1D0BrebU6pLhAhTm2
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
IZj4TYq2HlScfSdRkI+QP1DXXDz3reXEAHM/ysmIbguf7VfJ/dsB+EE4b/l5XAWj
|
||||
WHkOzVx7seuLmxs5Hu+l/tg64oMMngzQdC6c5uFYkJSfhDT5Ar0GKZd268ltWLHQ
|
||||
gC7pmugJ3/w5trYRkDiKMWt651l7qmaQDKAvk9X5I0aA2tjC5DMB6fPkHfzLvY+S
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
6Vd1Vz4KEbM/6qVZBGLAGuJhapKEU8TBPzOQYI4q82gnJ7Pu1Da4cxfKJ3J95+e7Z75/5e7XrUkjQFagToxKXA==
|
||||
1hs1FfIPISXmd7TJ/r+Vl5VOoCywAZyr7zSPYceKQIdJVXu7JYnBUb+iQtMPqcsojEatZy5pDdbDBezG5DA1qLdz7Wh2R5B0piUodv86TpthC/OIBMMyceg05hLT05OZ
|
||||
VmVrGQo2zRokW/ZuO9bN63zFN5O/w1krXKBn8bzERXc=
|
||||
VmVrGQo2zRokW/ZuO9bN63uaPsI9SGIYFo4qu6fQZHL9GGcTmbqkN3kKfV4iG89B
|
||||
VmVrGQo2zRokW/ZuO9bN6364+6D+dT33Zk25tJjqlVgtoL29ZI9bEfBKQ6cfJNwStfozG9mThVS88sNzbEnfeg==
|
||||
VmVrGQo2zRokW/ZuO9bN69uIuNlhHDMeqLOAnCu5uPWT8evwqXAwcfDwsmWoxBJB
|
||||
VmVrGQo2zRokW/ZuO9bN6yMdhcWuddd6xv9F64cBYywreWSVvaR5B3yfWI7OYuMP
|
||||
VmVrGQo2zRokW/ZuO9bN60D33f2rnzf/qOtpO3Ttt+1LbZoGyDvOeulSnp2R0ilck0EERjIpT/ktNM4srJBraTngKI5B04/LBl3323wp0nE=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN69ypGNbHyZMpYxMtQ3L+IMga3+inL7nbSVVsRnlPcc0U
|
||||
VmVrGQo2zRokW/ZuO9bN64Ads2ODFtiVcSlOcVp7F8BTH9nWa2Xc95X7mNQD1kCu
|
||||
VmVrGQo2zRokW/ZuO9bN60D33f2rnzf/qOtpO3Ttt+12NIPaRofJCp377XaLKfiybd59Ihi7pD1c3XhLcDanb1TM1C1QH4BPTOHZUBJeWHk=
|
||||
VmVrGQo2zRokW/ZuO9bN6xoaa3pLsxXyLdB8GbtG2YY=
|
||||
VmVrGQo2zRokW/ZuO9bN6y1I47Lsjes5Xkzm/KZ2HUikKCfZfG5oV8DWImIHip5MlpGXTmv9J1XV3V25fcmp5aa8KtmY5GAfonB0YuJLBm3Qyg6ipnG5U8MSK0eJ5IXtPW102IBhcOrIDStubnpSgQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
u8vW5y2SRttIHP9hhx+fqmx0hSbFOYRP5+aWkTy93ZFnIE/WAAXjKYo8eEgVBv85
|
||||
96orka/uERLyRst14azQwhCOqhTfcgFhXNAQS0hmuOGZIAyEpuVq0D9UpB4o0dY00eifTWefY3mmHrggp7bGLkFRUvNVINpyXDZbESEgd4Pe4G8AvpwDNkWSLrOyNGKY
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
Y9+a9leOyTyP83EF6Ql2IDgu816zIZ8AFaS4gCHUHX0nvp4HPB59n314/EkGNhAM
|
||||
dZw+CO0w3i/S02Fo8A/bXw==
|
||||
Z9W5TG7rzK3ZhbnWjdfJ37W7cUH0ZUZ4etA9G1eKq/5LlOl/dP9tIF16dAZSZX24
|
||||
kjVV/zwZdFNcXb0/4WIo43yY3WhctfxqYlJeIJT/Zt4raVptLNgdCJ85x2QCj7en
|
||||
v9zi26p7nzNT8ihOFEIGAPHAc1CmBd9eN42Km9GL48E=
|
||||
dZw+CO0w3i/S02Fo8A/bXw==
|
||||
OMrLNahybxYaZATa0EbsUraPl9ZQXb7EqnmkiDHNafM=
|
||||
GMvSy/NpCRnN8GukyNJXGQ==
|
||||
ZurH5ZOEBjKhuKKsOJuaZcaZjwgsQXIB71JtU6gEl5anuc8gN8IUF/VRflvF49gf
|
||||
tb7N17ccXzCvhV9hZH479H/o3ElcTFJ2wxaYkBX0qHE=
|
||||
ZurH5ZOEBjKhuKKsOJuaZT9OROQzGwZwPFsfOlMOqlW/n1s9EF2CXY7nIzE2BeWQUoQiVGUxtmYToskldhUSJg==
|
||||
ZurH5ZOEBjKhuKKsOJuaZZOj4gtB0ZybAayCdpeA+rzvR2xX3QPBG1G+d2mABcg83+eEtNBqMdpVGWRkdFdjju+Fp/5HLdmKRV5bbO3vpgI=
|
||||
xF/vKN+xQbwK2H7vBii2bVr0r4cs4Y9Wc0/WOSJt5a4=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmA0y/dvI19s9e1BRFCkk/QzH4UG1JBu620e7CQwjbQOOUvlgFJz4yLxls8aSEEo
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
NNh1PlSD8WUnUEbz+BU/P+yZLrQY+X/LEpSBMw7xwfahIuTImHO5EcUQN9HQmgqX
|
||||
LikBEoRjt8wwWzUZNw+jJqDVmHo0aqmO8fx4adbRXm90KhRgBH5ZfsJyfEAx+4JR
|
||||
akHibliG6j9uvBEg96vRei563dWr9knc+JrDspjHc/A=
|
||||
KZTmaJLp+FU9X93j5Tpqtw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
BIa0ibHnqUboaK9kYHYO4qFxMPyUysXdjYA1FqqhK4UMv4PoX1vehXtIZKdqRHbG
|
||||
b4OJVZe8QyIpjuTpKXDL9A==
|
||||
PRG/YRzXVD8iVR3bzEcUnlkfSwESl/MBfBcCyRS23XAS+yqB8BD2Fws8ohDlx4dxPS4gXd1cpWdmGRHNT+D6KSwXWu5PYPEs39ffK4i+qWM=
|
||||
usrsES3VVkgHW6tBbEkpHTeLztsByVaJibbFv8kSFIM=
|
||||
5wsVwKLrIjIWqeTNpSVp9SZAE79lgehXxNsrtfaN8Wk=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
# coding: utf-8
|
||||
# -------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2014-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: wzz <wzz@bt.cn>
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# ------------------------------
|
||||
# 系统防火墙模型 - 底层基类
|
||||
# ------------------------------
|
||||
|
||||
import sys
|
||||
if "/www/server/panel/class" not in sys.path:
|
||||
sys.path.insert(0, "/www/server/panel/class")
|
||||
import public
|
||||
|
||||
|
||||
class Base(object):
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
# 2024/3/22 下午 3:18 通用返回
|
||||
def _result(self, status: bool, msg: str) -> dict:
|
||||
'''
|
||||
@name 通用返回
|
||||
@author wzz <2024/3/22 下午 3:19>
|
||||
@param status: True/False
|
||||
msg: 提示信息
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
return {"status": status, "msg": msg}
|
||||
|
||||
# 2024/3/22 下午 4:55 检查是否设置了net.ipv4.ip_forward = 1,没有则设置
|
||||
def check_ip_forward(self) -> dict:
|
||||
'''
|
||||
@name 检查是否设置了net.ipv4.ip_forward = 1,没有则设置
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
stdout, stderr = public.ExecShell("sysctl net.ipv4.ip_forward")
|
||||
if "net.ipv4.ip_forward = 1" not in stdout:
|
||||
# 2024/3/22 下午 4:56 永久设置
|
||||
stdout, stderr = public.ExecShell("echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf")
|
||||
if stderr:
|
||||
return self._result(False, "设置net.ipv4.ip_forward失败, err: {}".format(stderr))
|
||||
|
||||
stdout, stderr = public.ExecShell("sysctl -p")
|
||||
if stderr:
|
||||
return self._result(False, "设置net.ipv4.ip_forward失败, err: {}".format(stderr))
|
||||
return self._result(True, "设置net.ipv4.ip_forward成功")
|
||||
return self._result(True, "net.ipv4.ip_forward已经设置")
|
||||
|
||||
# 2024/3/18 上午 11:35 处理192.168.1.100-192.168.1.200这种ip范围
|
||||
# 返回192.168.1.100,192.168.1.101,192.168.1...,192.168.1.200列表
|
||||
def handle_ip_range(self, ip):
|
||||
'''
|
||||
@name 处理192.168.1.100-192.168.1.200这种ip范围的ip列表
|
||||
@author wzz <2024/3/19 下午 4:58>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
ip_range = ip.split("-")
|
||||
ip_start = ip_range[0]
|
||||
ip_end = ip_range[1]
|
||||
ip_start = ip_start.split(".")
|
||||
ip_end = ip_end.split(".")
|
||||
ip_start = [int(i) for i in ip_start]
|
||||
ip_end = [int(i) for i in ip_end]
|
||||
ip_list = []
|
||||
for i in range(ip_start[0], ip_end[0] + 1):
|
||||
for j in range(ip_start[1], ip_end[1] + 1):
|
||||
for k in range(ip_start[2], ip_end[2] + 1):
|
||||
for l in range(ip_start[3], ip_end[3] + 1):
|
||||
ip_list.append("{}.{}.{}.{}".format(i, j, k, l))
|
||||
return ip_list
|
||||
@@ -0,0 +1,750 @@
|
||||
#!/www/server/panel/pyenv/bin/python3.7
|
||||
# coding: utf-8
|
||||
# -------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2014-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: wzz <wzz@bt.cn>
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# ------------------------------
|
||||
# 系统防火墙模型 - firewalld封装库
|
||||
# ------------------------------
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
if "/www/server/panel/class" not in sys.path:
|
||||
sys.path.insert(0, "/www/server/panel/class")
|
||||
import public
|
||||
from firewallModel.app.appBase import Base
|
||||
|
||||
|
||||
class Firewalld(Base):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.cmd_str = self._set_cmd_str()
|
||||
|
||||
def _set_cmd_str(self) -> str:
|
||||
return "firewall-cmd"
|
||||
|
||||
# 2024/3/20 下午 12:00 获取防火墙状态
|
||||
def status(self) -> bool:
|
||||
'''
|
||||
@name 获取防火墙状态
|
||||
@author wzz <2024/3/20 下午 12:01>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
stdout, stderr = public.ExecShell("systemctl is-active firewalld")
|
||||
if "not running" in stdout:
|
||||
return False
|
||||
return True
|
||||
except Exception as e:
|
||||
return False
|
||||
|
||||
# 2024/3/20 下午 12:00 获取防火墙版本号
|
||||
def version(self) -> str:
|
||||
'''
|
||||
@name 获取防火墙版本号
|
||||
@author wzz <2024/3/20 下午 12:00>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
stdout, stderr = public.ExecShell("firewall-cmd --version")
|
||||
if "FirewallD is not running" in stdout:
|
||||
return "Firewalld 没有启动,请先启动再试"
|
||||
if stderr:
|
||||
return "获取firewalld版本失败, err: {}".format(stderr)
|
||||
return stdout.strip()
|
||||
|
||||
# 2024/3/20 下午 12:08 启动防火墙
|
||||
def start(self) -> dict:
|
||||
'''
|
||||
@name 启动防火墙
|
||||
@author wzz <2024/3/20 下午 12:08>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
stdout, stderr = public.ExecShell("systemctl start firewalld")
|
||||
if stderr:
|
||||
return self._result(False, "启动防火墙失败, err: {}".format(stderr))
|
||||
return self._result(True, "启动防火墙成功")
|
||||
|
||||
# 2024/3/20 下午 12:10 停止防火墙
|
||||
def stop(self) -> dict:
|
||||
'''
|
||||
@name 停止防火墙
|
||||
@author wzz <2024/3/20 下午 12:10>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
stdout, stderr = public.ExecShell("systemctl stop firewalld")
|
||||
if stderr:
|
||||
return self._result(False, "停止防火墙失败, err: {}".format(stderr))
|
||||
return self._result(True, "停止防火墙成功")
|
||||
|
||||
# 2024/3/20 下午 12:11 重启防火墙
|
||||
def restart(self) -> dict:
|
||||
'''
|
||||
@name 重启防火墙
|
||||
@author wzz <2024/3/20 下午 12:11>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
stdout, stderr = public.ExecShell("systemctl restart firewalld")
|
||||
if stderr:
|
||||
return self._result(False, "重启防火墙失败, err: {}".format(stderr))
|
||||
return self._result(True, "重启防火墙成功")
|
||||
|
||||
# 2024/3/20 下午 12:11 重载防火墙
|
||||
def reload(self) -> dict:
|
||||
'''
|
||||
@name 重载防火墙
|
||||
@author wzz <2024/3/20 下午 12:11>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
stdout, stderr = public.ExecShell("firewall-cmd --reload")
|
||||
if stderr:
|
||||
return self._result(False, "重载防火墙失败, err: {}".format(stderr))
|
||||
return self._result(True, "重载防火墙成功")
|
||||
|
||||
# 2024/3/20 下午 12:12 获取所有防火墙端口列表
|
||||
def list_port(self) -> list:
|
||||
'''
|
||||
@name 获取所有防火墙端口列表
|
||||
@author wzz <2024/3/20 下午 12:12>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
return self.parse_public_zone()["ports"] + self.list_output_port()
|
||||
|
||||
# 2024/3/20 下午 12:12 获取防火墙端口INPUT列表
|
||||
def list_input_port(self) -> list:
|
||||
'''
|
||||
@name 获取防火墙端口列表
|
||||
@author wzz <2024/3/20 下午 12:12>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
return self.parse_public_zone()["ports"]
|
||||
|
||||
# 2024/3/22 上午 11:28 获取所有OUTPUT的direct 端口规则
|
||||
def list_output_port(self) -> list:
|
||||
'''
|
||||
@name 获取所有OUTPUT的direct 端口规则
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
list_direct_rules = self.parse_direct_xml()["ports"]
|
||||
datas = []
|
||||
for rule in list_direct_rules:
|
||||
if rule.get("Chain") == "OUTPUT":
|
||||
datas.append(rule)
|
||||
return datas
|
||||
|
||||
# 2024/3/20 下午 12:21 获取防火墙的rule的ip规则列表
|
||||
def list_address(self) -> list:
|
||||
'''
|
||||
@name 获取防火墙的rule的ip规则列表
|
||||
@author wzz <2024/3/20 下午 2:45>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
return self.parse_public_zone()["rules"] + self.list_output_address()
|
||||
|
||||
# 2024/3/20 下午 12:21 获取防火墙的rule input的ip规则列表
|
||||
def list_input_address(self) -> list:
|
||||
'''
|
||||
@name 获取防火墙的rule input的ip规则列表
|
||||
@author wzz <2024/3/20 下午 2:45>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
return self.parse_public_zone()["rules"]
|
||||
|
||||
# 2024/3/22 下午 4:07 获取所有OUTPUT的direct ip规则
|
||||
def list_output_address(self) -> list:
|
||||
'''
|
||||
@name 获取所有OUTPUT的direct ip规则
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
list_direct_rules = self.parse_direct_xml()["rules"]
|
||||
datas = []
|
||||
for rule in list_direct_rules:
|
||||
if rule.get("Chain") == "OUTPUT":
|
||||
datas.append(rule)
|
||||
return datas
|
||||
|
||||
# 2024/3/20 下午 5:34 添加或删除防火墙端口
|
||||
def input_port(self, info: dict, operation: str) -> dict:
|
||||
'''
|
||||
@name 添加或删除防火墙端口
|
||||
@author wzz <2024/3/20 下午 5:34>
|
||||
@param info:{"Port": args[2], "Protocol": args[3]}
|
||||
operation: add/remove
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
if operation not in ["add", "remove"]:
|
||||
return self._result(False, "不支持的操作: {}".format(operation))
|
||||
|
||||
# 2024/3/25 下午 6:00 处理tcp/udp双协议的端口
|
||||
if info['Protocol'].find("/") != -1:
|
||||
stdout, stderr = public.ExecShell(
|
||||
"{cmd_str} --zone=public --{operation}-port={port}/{prot} --permanent"
|
||||
.format(
|
||||
cmd_str=self.cmd_str,
|
||||
operation=operation,
|
||||
port=info['Port'],
|
||||
prot="tcp"
|
||||
)
|
||||
)
|
||||
if stderr:
|
||||
return self._result(False, "设置端口失败, err: {}".format(stderr))
|
||||
stdout, stderr = public.ExecShell(
|
||||
"{cmd_str} --zone=public --{operation}-port={port}/{prot} --permanent"
|
||||
.format(
|
||||
cmd_str=self.cmd_str,
|
||||
operation=operation,
|
||||
port=info['Port'],
|
||||
prot="udp"
|
||||
)
|
||||
)
|
||||
if stderr:
|
||||
return self._result(False, "设置端口失败, err: {}".format(stderr))
|
||||
else:
|
||||
# 2024/3/25 下午 6:00 处理单协议的端口
|
||||
stdout, stderr = public.ExecShell(
|
||||
"{cmd_str} --zone=public --{operation}-port={port}/{prot} --permanent"
|
||||
.format(
|
||||
cmd_str=self.cmd_str,
|
||||
operation=operation,
|
||||
port=info['Port'],
|
||||
prot=info['Protocol']
|
||||
)
|
||||
)
|
||||
if stderr:
|
||||
return self._result(False, "设置端口失败, err: {}".format(stderr))
|
||||
return self._result(True, "设置入站端口成功")
|
||||
|
||||
# 2024/3/20 下午 6:02 设置output的防火墙端口规则
|
||||
def output_port(self, info: dict, operation: str) -> dict:
|
||||
'''
|
||||
@name 设置output的防火墙端口规则
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
if operation not in ["add", "remove"]:
|
||||
return self._result(False, "不支持的操作: {}".format(operation))
|
||||
|
||||
if info['Strategy'] == "accept":
|
||||
info['Strategy'] = "ACCEPT"
|
||||
elif info['Strategy'] == "drop":
|
||||
info['Strategy'] = "DROP"
|
||||
elif info['Strategy'] == "reject":
|
||||
info['Strategy'] = "REJECT"
|
||||
else:
|
||||
return self._result(False, "不支持的策略: {}".format(info['Strategy']))
|
||||
|
||||
info['Port'] = info['Port'].replace("-", ":")
|
||||
|
||||
if "/" in info['Protocol']:
|
||||
info['Protocol'] = info['Protocol'].split("/")
|
||||
for pp in info['Protocol']:
|
||||
if not pp in ["tcp", "udp"]:
|
||||
return self._result(False, "设置出站端口失败, err: 协议不支持 {}".format(pp))
|
||||
|
||||
stdout, stderr = public.ExecShell(
|
||||
"{cmd_str} --permanent --direct --{operation}-rule ipv4 filter OUTPUT {priority} -p {prot} --dport {port} -j {strategy}"
|
||||
.format(
|
||||
cmd_str=self.cmd_str,
|
||||
operation=operation,
|
||||
priority=info['Priority'],
|
||||
prot=pp,
|
||||
port=info['Port'],
|
||||
strategy=info['Strategy']
|
||||
)
|
||||
)
|
||||
if stderr:
|
||||
return self._result(False, "设置出站端口失败, err: {}".format(stderr))
|
||||
else:
|
||||
stdout, stderr = public.ExecShell(
|
||||
"{cmd_str} --permanent --direct --{operation}-rule ipv4 filter OUTPUT {priority} -p {prot} --dport {port} -j {strategy}"
|
||||
.format(
|
||||
cmd_str=self.cmd_str,
|
||||
operation=operation,
|
||||
priority=info['Priority'],
|
||||
prot=info['Protocol'],
|
||||
port=info['Port'],
|
||||
strategy=info['Strategy']
|
||||
)
|
||||
)
|
||||
|
||||
if stderr:
|
||||
return self._result(False, "设置出站端口失败, err: {}".format(stderr))
|
||||
|
||||
return self._result(True, "设置出站端口成功")
|
||||
|
||||
def set_rich_rule(self, info: dict, operation: str) -> dict:
|
||||
'''
|
||||
@name 添加或删除复杂规则
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
rule_str = "rule family={}".format(info['Family'].lower())
|
||||
if "Address" in info and info["Address"] != "all":
|
||||
rule_str += " source address={}".format(info['Address'])
|
||||
if info.get("Port"):
|
||||
rule_str += " port port={}".format(info['Port'])
|
||||
if info.get("Protocol"):
|
||||
rule_str += " protocol={}".format(info['Protocol'])
|
||||
rule_str += " {}".format(info['Strategy'])
|
||||
|
||||
stdout, stderr = public.ExecShell(
|
||||
"{} --zone=public --{}-rich-rule='{}' --permanent"
|
||||
.format(self.cmd_str, operation, rule_str))
|
||||
|
||||
if stderr:
|
||||
return self._result(False, "设置规则:{} 失败, err: {}".format(operation, rule_str, stderr))
|
||||
return self._result(True, "设置规则成功".format(operation))
|
||||
|
||||
# 2024/3/22 上午 11:35 添加或删除复杂规则
|
||||
def rich_rules(self, info: dict, operation: str) -> dict:
|
||||
'''
|
||||
@name 添加或删除复杂规则
|
||||
@author wzz <2024/3/22 上午 11:35>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
if operation not in ["add", "remove"]:
|
||||
return self._result(False, "不支持的规则操作: {}".format(operation))
|
||||
|
||||
if "Protocol" in info and info["Protocol"] == "all":
|
||||
info["Protocol"] = "tcp/udp"
|
||||
|
||||
if "Protocol" in info and info['Protocol'].find("/") != -1:
|
||||
result_list = []
|
||||
for protocol in info['Protocol'].split("/"):
|
||||
info['Protocol'] = protocol
|
||||
result_list.append(self.set_rich_rule(info, operation))
|
||||
|
||||
return {"status": True, "msg": result_list}
|
||||
else:
|
||||
return self.set_rich_rule(info, operation)
|
||||
|
||||
# 2024/3/24 下午 10:43 设置output的防火墙ip规则
|
||||
def output_rich_rules(self, info: dict, operation: str) -> dict:
|
||||
'''
|
||||
@name 设置output的防火墙ip规则
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
if operation not in ["add", "remove"]:
|
||||
return self._result(False, "不支持的操作: {}".format(operation))
|
||||
|
||||
if info['Strategy'] == "accept":
|
||||
info['Strategy'] = "ACCEPT"
|
||||
elif info['Strategy'] == "drop":
|
||||
info['Strategy'] = "DROP"
|
||||
elif info['Strategy'] == "reject":
|
||||
info['Strategy'] = "REJECT"
|
||||
else:
|
||||
return self._result(False, "不支持的策略: {}".format(info['Strategy']))
|
||||
|
||||
rich_rules = self.cmd_str + " --permanent --direct --{0}-rule ipv4 filter OUTPUT".format(operation)
|
||||
if "Priority" in info:
|
||||
rich_rules += " {}".format(info["Priority"])
|
||||
if "Address" in info:
|
||||
rich_rules += " -d {}".format(info["Address"])
|
||||
if "Protocol" in info:
|
||||
rich_rules += " -p {}".format(info["Protocol"])
|
||||
if "Port" in info:
|
||||
info["Port"] = info["Port"].replace("-", ":")
|
||||
rich_rules += " --dport {}".format(info["Port"])
|
||||
if "Strategy" in info:
|
||||
rich_rules += " -j {}".format(info["Strategy"])
|
||||
|
||||
stdout, stderr = public.ExecShell(rich_rules)
|
||||
if "success" not in stdout and stderr:
|
||||
return self._result(False, "设置出站地址失败, err: {}".format(stderr))
|
||||
if "NOT_ENABLED" in stderr:
|
||||
return self._result(False, "规则不存在")
|
||||
return self._result(True, "设置出站地址成功")
|
||||
|
||||
# 2024/3/22 下午 12:22 解析public区域的防火墙规则
|
||||
def parse_public_zone(self) -> dict:
|
||||
'''
|
||||
@name 解析public区域的防火墙规则
|
||||
@author wzz <2024/3/22 下午 12:22>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"services": services, "ports": ports, "rules": rules} rules是ip规则
|
||||
'''
|
||||
try:
|
||||
import xml.etree.ElementTree as ET
|
||||
file_path = "/etc/firewalld/zones/public.xml"
|
||||
if not os.path.exists(file_path):
|
||||
return {"services": [], "ports": [], "rules": [], "forward_ports": []}
|
||||
|
||||
services = []
|
||||
ports = []
|
||||
rules = []
|
||||
forward_ports = []
|
||||
|
||||
tree = ET.parse(file_path)
|
||||
root = tree.getroot()
|
||||
|
||||
for elem in root:
|
||||
# 2024/3/22 下午 3:01 服务规则
|
||||
if elem.tag == "service":
|
||||
services.append(elem.attrib['name'])
|
||||
# 2024/3/22 下午 3:01 端口规则
|
||||
elif elem.tag == "port":
|
||||
port = {
|
||||
"Protocol": elem.attrib["protocol"],
|
||||
"Port": elem.attrib["port"],
|
||||
"Strategy": "accept",
|
||||
"Family": "ipv4",
|
||||
"Address": "all",
|
||||
"Chain": "INPUT",
|
||||
}
|
||||
ports.append(port)
|
||||
# 2024/3/22 下午 3:01 复杂的规则配置
|
||||
elif elem.tag == "rule":
|
||||
rule = {"Family": elem.attrib["family"] if "family" in elem.attrib else "ipv4"}
|
||||
for subelem in elem:
|
||||
rule["Strategy"] = "accept"
|
||||
if subelem.tag == "source":
|
||||
if "address" in subelem.attrib:
|
||||
rule["Address"] = subelem.attrib["address"]
|
||||
else:
|
||||
continue
|
||||
rule["Address"] = "all" if rule["Address"] == "Anywhere" else rule["Address"]
|
||||
elif subelem.tag == "port":
|
||||
rule["port"] = {"protocol": subelem.attrib["protocol"], "port": subelem.attrib["port"]}
|
||||
elif subelem.tag == "drop":
|
||||
rule["Strategy"] = "drop"
|
||||
elif subelem.tag == "accept":
|
||||
rule["Strategy"] = "accept"
|
||||
elif subelem.tag == "forward-port":
|
||||
rule["forward-port"] = {
|
||||
"protocol": subelem.attrib["protocol"],
|
||||
"S_Port": subelem.attrib["port"],
|
||||
"T_Address": subelem.attrib["to-addr"],
|
||||
"T_Port": subelem.attrib["to-port"],
|
||||
}
|
||||
|
||||
# 2024/3/22 下午 3:02 如果端口在里面,就放到端口规则列表中,否则就是ip规则
|
||||
if "port" in rule:
|
||||
ports.append({
|
||||
"Protocol": rule["port"]["protocol"] if "protocol" in rule else "tcp",
|
||||
"Port": rule["port"]["port"],
|
||||
"Strategy": rule["Strategy"] if "Strategy" in rule else "accept",
|
||||
"Family": rule["Family"] if "Family" in rule else "ipv4",
|
||||
"Address": rule["Address"] if "Address" in rule else "all",
|
||||
"Chain": "INPUT",
|
||||
})
|
||||
# 2024/3/25 下午 5:01 处理带源ip的端口转发规则
|
||||
elif "forward-port" in rule:
|
||||
forward_ports.append({
|
||||
"type": "port_forward",
|
||||
"number": len(forward_ports) + 1,
|
||||
"Protocol": rule["forward-port"]["protocol"],
|
||||
"S_Address": rule["Address"],
|
||||
"S_Port": rule["forward-port"]["S_Port"],
|
||||
"T_Address": rule["forward-port"]["T_Address"],
|
||||
"T_Port": rule["forward-port"]["T_Port"],
|
||||
})
|
||||
else:
|
||||
if "Address" not in rule:
|
||||
continue
|
||||
|
||||
rule["Chain"] = "INPUT"
|
||||
rules.append(rule)
|
||||
# 2024/3/25 下午 2:57 端口转发规则
|
||||
elif elem.tag == "forward-port":
|
||||
port = {
|
||||
"type": "port_forward",
|
||||
"number": len(forward_ports) + 1,
|
||||
"Protocol": elem.attrib["protocol"] if "protocol" in elem.attrib else "tcp",
|
||||
"S_Address": "",
|
||||
"S_Port": elem.attrib["port"] if "port" in elem.attrib else "",
|
||||
"T_Address": elem.attrib["to-addr"] if "to-addr" in elem.attrib else "",
|
||||
"T_Port": elem.attrib["to-port"] if "to-port" in elem.attrib else "",
|
||||
}
|
||||
forward_ports.append(port)
|
||||
|
||||
return {"services": services, "ports": ports, "rules": rules, "forward_ports": forward_ports}
|
||||
except Exception as e:
|
||||
return {"services": [], "ports": [], "rules": [], "forward_ports": []}
|
||||
|
||||
# 2024/3/22 下午 2:32 解析direct.xml的防火墙规则
|
||||
def parse_direct_xml(self) -> dict:
|
||||
'''
|
||||
@name 解析direct.xml的防火墙规则
|
||||
@author wzz <2024/3/22 下午 2:32>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return list[dict{}...]
|
||||
'''
|
||||
try:
|
||||
import xml.etree.ElementTree as ET
|
||||
file_path = "/etc/firewalld/direct.xml"
|
||||
if not os.path.exists(file_path):
|
||||
return {"ports": [], "rules": []}
|
||||
|
||||
ports = []
|
||||
rules = []
|
||||
|
||||
tree = ET.parse(file_path)
|
||||
root = tree.getroot()
|
||||
|
||||
for elem in root:
|
||||
if elem.tag == "rule":
|
||||
protocol = "tcp"
|
||||
port = ""
|
||||
strategy = ""
|
||||
address = ""
|
||||
|
||||
elem_t = elem.text.split(" ")
|
||||
# 2024/3/22 下午 4:14 解析 Options 得到端口,策略,地址,协议
|
||||
for i in elem_t:
|
||||
if i == "-p":
|
||||
protocol = elem_t[elem_t.index(i) + 1] # 如果找到匹配项,结果为索引+1的值,-p tcp,值为tcp
|
||||
elif i == "--dport":
|
||||
port = elem_t[elem_t.index(i) + 1]
|
||||
elif i == "-j":
|
||||
strategy = elem_t[elem_t.index(i) + 1]
|
||||
elif i == "-d":
|
||||
address = elem_t[elem_t.index(i) + 1]
|
||||
|
||||
rule = {
|
||||
"Family": elem.attrib["ipv"],
|
||||
"Chain": elem.attrib["chain"],
|
||||
"Strategy": strategy.lower(),
|
||||
"Address": address if address != "" else "all",
|
||||
# "Options": elem.text
|
||||
}
|
||||
|
||||
# 2024/3/22 下午 4:13 如果端口不为空,就是端口规则
|
||||
if port != "":
|
||||
rule["Port"] = port
|
||||
rule["Protocol"] = protocol
|
||||
|
||||
ports.append(rule)
|
||||
# 2024/3/22 下午 4:14 如果端口为空,就是ip规则
|
||||
else:
|
||||
rules.append(rule)
|
||||
|
||||
return {"ports": ports, "rules": rules}
|
||||
except Exception as e:
|
||||
return {"ports": [], "rules": []}
|
||||
|
||||
# 2024/3/22 下午 4:54 检查是否开启了masquerade,没有则开启
|
||||
def check_masquerade(self) -> dict:
|
||||
'''
|
||||
@name 检查是否开启了masquerade,没有则开启
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
stdout, stderr = public.ExecShell("firewall-cmd --query-masquerade")
|
||||
if "no" in stdout:
|
||||
stdout, stderr = public.ExecShell("firewall-cmd --add-masquerade")
|
||||
if stderr:
|
||||
return self._result(False, "开启masquerade失败, err: {}".format(stderr))
|
||||
return self._result(True, "开启masquerade成功")
|
||||
return self._result(True, "masquerade已经开启")
|
||||
|
||||
# 2024/3/22 下午 4:57 设置端口转发
|
||||
def port_forward(self, info: dict, operation: str) -> dict:
|
||||
'''
|
||||
@name 设置端口转发
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
if operation not in ["add", "remove"]:
|
||||
return self._result(False, "不支持的操作: {}".format(operation))
|
||||
|
||||
if operation == "add":
|
||||
check_masquerade = self.check_masquerade()
|
||||
if not check_masquerade["status"]:
|
||||
return check_masquerade
|
||||
|
||||
# 2024/3/25 下午 6:07 处理有源地址的情况
|
||||
if "S_Address" in info and info["S_Address"] != "":
|
||||
# 2024/3/25 下午 6:05 处理tcp/udp双协议的情况
|
||||
if info['Protocol'].find("/") != -1:
|
||||
rich_rules = self.cmd_str + " --zone=public"
|
||||
rich_rules += " --{0}-rich-rule='rule family=\"{1}\" source address=\"{2}\" forward-port port=\"{3}\" protocol=\"tcp\" to-port=\"{4}\" to-addr=\"{5}\"' --permanent".format(
|
||||
operation,
|
||||
info['Family'],
|
||||
info['S_Address'],
|
||||
info['S_Port'],
|
||||
info['T_Port'],
|
||||
info['T_Address'],
|
||||
)
|
||||
stdout, stderr = public.ExecShell(rich_rules)
|
||||
if "success" not in stdout and stderr:
|
||||
if "ALREADY_ENABLED" in stderr:
|
||||
return self._result(True, "端口转发规则已经存在")
|
||||
return self._result(False, "设置端口转发失败, err: {}".format(stderr))
|
||||
|
||||
rich_rules = self.cmd_str + " --zone=public"
|
||||
rich_rules += " --{0}-rich-rule='rule family=\"{1}\" source address=\"{2}\" forward-port port=\"{3}\" protocol=\"udp\" to-port=\"{4}\" to-addr=\"{5}\"' --permanent".format(
|
||||
operation,
|
||||
info['Family'],
|
||||
info['S_Address'],
|
||||
info['S_Port'],
|
||||
info['T_Port'],
|
||||
info['T_Address'],
|
||||
)
|
||||
stdout, stderr = public.ExecShell(rich_rules)
|
||||
if "success" not in stdout and stderr:
|
||||
if "ALREADY_ENABLED" in stderr:
|
||||
return self._result(True, "端口转发规则已经存在")
|
||||
return self._result(False, "设置端口转发失败, err: {}".format(stderr))
|
||||
|
||||
# 2024/3/25 下午 6:05 处理单协议的情况
|
||||
else:
|
||||
rich_rules = self.cmd_str + " --zone=public"
|
||||
rich_rules += " --{0}-rich-rule='rule family=\"{1}\" source address=\"{2}\" forward-port port=\"{3}\" protocol=\"{4}\" to-port=\"{5}\" to-addr=\"{6}\"'".format(
|
||||
operation,
|
||||
info['Family'],
|
||||
info['S_Address'],
|
||||
info['S_Port'],
|
||||
info['Protocol'],
|
||||
info['T_Port'],
|
||||
info['T_Address'],
|
||||
)
|
||||
rich_rules += " --permanent"
|
||||
stdout, stderr = public.ExecShell(rich_rules)
|
||||
if "success" not in stdout and stderr:
|
||||
if "ALREADY_ENABLED" in stderr:
|
||||
return self._result(True, "端口转发规则已经存在")
|
||||
return self._result(False, "设置端口转发失败, err: {}".format(stderr))
|
||||
|
||||
# 2024/3/25 下午 6:08 处理没有源地址的情况
|
||||
else:
|
||||
# 2024/3/25 下午 6:05 处理tcp/udp双协议的情况
|
||||
if info['Protocol'].find("/") != -1:
|
||||
stdout, stderr = public.ExecShell(
|
||||
"{} --zone=public --{}-forward-port='port={}:proto={}:toport={}:toaddr={}' --permanent"
|
||||
.format(self.cmd_str, operation, info['S_Port'], "udp", info['T_Port'], info['T_Address'])
|
||||
)
|
||||
if "success" not in stdout and stderr:
|
||||
if "ALREADY_ENABLED" in stderr:
|
||||
return self._result(True, "端口转发规则已经存在")
|
||||
return self._result(False, "设置端口转发失败, err: {}".format(stderr))
|
||||
|
||||
stdout, stderr = public.ExecShell(
|
||||
"{} --zone=public --{}-forward-port='port={}:proto={}:toport={}:toaddr={}' --permanent"
|
||||
.format(self.cmd_str, operation, info['S_Port'], "tcp", info['T_Port'], info['T_Address'])
|
||||
)
|
||||
if "success" not in stdout and stderr:
|
||||
if "ALREADY_ENABLED" in stderr:
|
||||
return self._result(True, "端口转发规则已经存在")
|
||||
return self._result(False, "设置端口转发失败, err: {}".format(stderr))
|
||||
# 2024/3/25 下午 6:09 处理单协议的情况
|
||||
else:
|
||||
stdout, stderr = public.ExecShell(
|
||||
"{} --zone=public --{}-forward-port='port={}:proto={}:toport={}:toaddr={}' --permanent"
|
||||
.format(self.cmd_str, operation, info['S_Port'], info['Protocol'], info['T_Port'], info['T_Address'])
|
||||
)
|
||||
if "success" not in stdout and stderr:
|
||||
if "ALREADY_ENABLED" in stderr:
|
||||
return self._result(True, "端口转发规则已经存在")
|
||||
return self._result(False, "设置端口转发失败, err: {}".format(stderr))
|
||||
|
||||
return self._result(True, "设置端口转发成功")
|
||||
|
||||
# 2024/3/25 下午 2:37 获取所有端口转发规则
|
||||
def list_port_forward(self) -> list:
|
||||
'''
|
||||
@name 获取所有端口转发规则
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return list[dict{}...]
|
||||
'''
|
||||
return self.parse_public_zone()["forward_ports"]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = sys.argv
|
||||
firewall = Firewalld()
|
||||
Firewalld_status = firewall.status()
|
||||
if len(args) < 2:
|
||||
print("Welcome to the Firewalld command-line interface!")
|
||||
print("Firewall status is :", Firewalld_status)
|
||||
print("Firewall version: ", firewall.version())
|
||||
if Firewalld_status == "not running":
|
||||
print("Firewalld未启动,请启动Firewalld后再执行命令!")
|
||||
print("启动命令: start")
|
||||
print()
|
||||
sys.exit(1)
|
||||
print("Usage: ")
|
||||
print("status: Get the status of the firewall.")
|
||||
print("version: Get the version of the firewall.")
|
||||
print("start: Start the firewall.")
|
||||
print("stop: Stop the firewall.")
|
||||
print("restart: Restart the firewall.")
|
||||
print("reload: Reload the firewall.")
|
||||
print("list_input_port: List all input ports.")
|
||||
print("list_input_address: List all input address rules.")
|
||||
print("input_port: Add or remove input port.")
|
||||
print("output_port: Add or remove output port.")
|
||||
print("list_output_port: List all output ports.")
|
||||
print("list_output_address: List all output address rules.")
|
||||
print("rich_rules: Add or remove rich rules.")
|
||||
sys.exit(1)
|
||||
|
||||
if args[1] == "status":
|
||||
print("Firewall status is :", Firewalld_status)
|
||||
elif args[1] == "version":
|
||||
print("Firewall version: ", firewall.version())
|
||||
elif args[1] == "start":
|
||||
print(firewall.start())
|
||||
elif args[1] == "stop":
|
||||
print(firewall.stop())
|
||||
elif args[1] == "restart":
|
||||
print(firewall.restart())
|
||||
elif args[1] == "reload":
|
||||
print(firewall.reload())
|
||||
elif args[1] == "list_input_port":
|
||||
print(firewall.list_input_port())
|
||||
elif args[1] == "list_input_address":
|
||||
print(firewall.list_input_address())
|
||||
elif args[1] == "input_port":
|
||||
if len(args) < 4:
|
||||
print("Usage: input_port Port Protocol")
|
||||
sys.exit(1)
|
||||
print(firewall.input_port({"Port": args[2], "Protocol": args[3]}, args[4]))
|
||||
elif args[1] == "output_port":
|
||||
if len(args) < 6:
|
||||
print("Usage: output_port Port Protocol Strategy Priority")
|
||||
sys.exit(1)
|
||||
print(firewall.output_port({"Port": args[2], "Protocol": args[3], "Strategy": args[4], "Priority": args[5]}, args[6]))
|
||||
elif args[1] == "list_output_port":
|
||||
print(firewall.list_output_port())
|
||||
elif args[1] == "list_output_address":
|
||||
print(firewall.list_output_address())
|
||||
elif args[1] == "rich_rules":
|
||||
if len(args) < 4:
|
||||
print("Usage: rich_rules Family Address Port Protocol Strategy")
|
||||
sys.exit(1)
|
||||
print(firewall.rich_rules({"Family": args[2], "Address": args[3], "Port": args[4], "Protocol": args[5], "Strategy": args[6]}, args[7]))
|
||||
elif args[1] == "output_rich_rules":
|
||||
if len(args) < 6:
|
||||
print("Usage: output_rich_rules Family Address Port Protocol Strategy Priority")
|
||||
sys.exit(1)
|
||||
print(firewall.output_rich_rules({"Family": args[2], "Address": args[3], "Port": args[4], "Protocol": args[5], "Strategy": args[6], "Priority": args[7]}, args[8]))
|
||||
elif args[1] == "port_forward":
|
||||
if len(args) < 7:
|
||||
print("Usage: port_forward Port Protocol ToPort ToAddr")
|
||||
sys.exit(1)
|
||||
print(firewall.port_forward({"Port": args[2], "Protocol": args[3], "ToPort": args[4], "ToAddr": args[5]}, args[6]))
|
||||
else:
|
||||
print("Command not found!")
|
||||
sys.exit(1)
|
||||
|
||||
@@ -0,0 +1,939 @@
|
||||
#!/www/server/panel/pyenv/bin/python3.7
|
||||
# coding: utf-8
|
||||
# -------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2014-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: wzz <wzz@bt.cn>
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# ------------------------------
|
||||
# 系统防火墙模型 - iptables封装库
|
||||
# ------------------------------
|
||||
|
||||
import re
|
||||
import subprocess
|
||||
import os
|
||||
import sys
|
||||
|
||||
if "/www/server/panel/class" not in sys.path:
|
||||
sys.path.insert(0, "/www/server/panel/class")
|
||||
import public
|
||||
from firewallModel.app.appBase import Base
|
||||
|
||||
|
||||
# import re
|
||||
|
||||
class Iptables(Base):
|
||||
def __init__(self):
|
||||
self.cmd_str = self._set_cmd_str()
|
||||
self.protocol = {
|
||||
"6": "tcp",
|
||||
"17": "udp",
|
||||
"0": "all"
|
||||
}
|
||||
|
||||
def _set_cmd_str(self):
|
||||
return "iptables"
|
||||
|
||||
# 2024/3/19 下午 5:00 获取系统防火墙的运行状态
|
||||
def status(self):
|
||||
'''
|
||||
@name 获取系统防火墙的运行状态
|
||||
@author wzz <2024/3/19 下午 5:00>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
return "running"
|
||||
|
||||
# 2024/3/19 下午 5:00 获取系统防火墙的版本号
|
||||
def version(self):
|
||||
'''
|
||||
@name 获取系统防火墙的版本号
|
||||
@author wzz <2024/3/19 下午 5:00>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
result = public.ExecShell("iptables -v 2>&1|awk '{print $2}'|head -1")[0].replace("\n", "")
|
||||
if result == "":
|
||||
return "未知的iptables版本"
|
||||
return result
|
||||
except Exception as e:
|
||||
return "未知版本"
|
||||
|
||||
# 2024/3/19 下午 5:00 启动防火墙
|
||||
def start(self):
|
||||
'''
|
||||
@name 启动防火墙
|
||||
@author wzz <2024/3/19 下午 5:00>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
return self._result(True, "当前系统防火墙为iptables,不支持设置状态")
|
||||
|
||||
# 2024/3/19 下午 5:00 停止防火墙
|
||||
def stop(self):
|
||||
'''
|
||||
@name 停止防火墙
|
||||
@author wzz <2024/3/19 下午 5:00>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
return self._result(True, "当前系统防火墙为iptables,不支持停止")
|
||||
|
||||
# 2024/3/19 下午 4:59 重启防火墙
|
||||
def restart(self):
|
||||
'''
|
||||
@name 重启防火墙
|
||||
@author wzz <2024/3/19 下午 4:59>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
return self._result(True, "当前系统防火墙为iptables,不支持重启")
|
||||
|
||||
# 2024/3/19 下午 4:59 重载防火墙
|
||||
def reload(self):
|
||||
'''
|
||||
@name 重载防火墙
|
||||
@author wzz <2024/3/19 下午 4:59>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
return self._result(True, "当前系统防火墙为iptables,不支持重载")
|
||||
|
||||
# 2024/3/19 下午 3:36 检查表名是否合法
|
||||
def check_table_name(self, table_name):
|
||||
'''
|
||||
@name 检查表名是否合法
|
||||
@param "table_name": "filter/nat/mangle/raw/security"
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
table_names = ['filter', 'nat', 'mangle', 'raw', 'security']
|
||||
if table_name not in table_names:
|
||||
return False
|
||||
return True
|
||||
|
||||
# 2024/3/19 下午 3:55 解析规则列表输出,返回规则列表字典
|
||||
def parse_rules(self, stdout):
|
||||
'''
|
||||
@name 解析规则列表输出,返回规则列表字典
|
||||
@author wzz <2024/3/19 下午 3:53>
|
||||
字段含义:
|
||||
"number": 规则编号,对应规则在链中的顺序。
|
||||
"chain": 规则所属的链的名称。
|
||||
"pkts": 规则匹配的数据包数量。
|
||||
"bytes": 规则匹配的数据包字节数。
|
||||
"target": 规则的目标动作,表示数据包匹配到该规则后应该执行的操作。
|
||||
"prot": 规则适用的协议类型。
|
||||
"opt": 规则的选项,包括规则中使用的匹配条件或特定选项。
|
||||
"in": 规则匹配的数据包的输入接口。
|
||||
"out": 规则匹配的数据包的输出接口。
|
||||
"source": 规则匹配的数据包的源地址。
|
||||
"destination": 规则匹配的数据包的目标地址。
|
||||
"options": 规则的其他选项或说明,通常是规则中的注释或附加信息。
|
||||
|
||||
protocol(port协议头中数字对应的协议类型):
|
||||
0: 表示所有协议
|
||||
1: ICMP(Internet 控制消息协议)
|
||||
6: TCP(传输控制协议)
|
||||
17: UDP(用户数据报协议)
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
lines = stdout.strip().split('\n')
|
||||
rules = []
|
||||
current_chain = None
|
||||
for line in lines:
|
||||
if line.startswith("Chain"):
|
||||
current_chain = line.split()[1]
|
||||
elif (line.startswith("target") or line.strip() == "" or "source" in line or
|
||||
"Warning: iptables-legacy tables present" in line):
|
||||
# 过滤表头,空行,警告
|
||||
continue
|
||||
else:
|
||||
rule_info = line.split()
|
||||
rule = {
|
||||
"number": rule_info[0],
|
||||
"chain": current_chain,
|
||||
"pkts": rule_info[1],
|
||||
"bytes": rule_info[2],
|
||||
"target": rule_info[3],
|
||||
"prot": rule_info[4],
|
||||
"opt": rule_info[5],
|
||||
"in": rule_info[6],
|
||||
"out": rule_info[7],
|
||||
"source": rule_info[8],
|
||||
"destination": rule_info[9],
|
||||
"options": " ".join(rule_info[10:]).strip()
|
||||
}
|
||||
rules.append(rule)
|
||||
return rules
|
||||
|
||||
# 2024/3/19 下午 3:02 列出指定表的指定链的规则
|
||||
def list_rules(self, parm):
|
||||
'''
|
||||
@name 列出指定表的指定链的规则
|
||||
@author wzz <2024/3/19 下午 3:02>
|
||||
@param
|
||||
@return
|
||||
'''
|
||||
try:
|
||||
if not self.check_table_name(parm['table']):
|
||||
return "错误: 不支持的表名."
|
||||
stdout = subprocess.check_output(
|
||||
[self.cmd_str, '-t', parm['table'], '-L', parm['chain_name'], '-nv', '--line-numbers'],
|
||||
stderr=subprocess.STDOUT, universal_newlines=True
|
||||
)
|
||||
return self.parse_rules(stdout)
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
# 2024/4/29 下午12:16 列出iptables中所有INPUT和OUTPUT的端口规则
|
||||
def list_port(self):
|
||||
'''
|
||||
@name 列出iptables中所有INPUT和OUTPUT的端口规则
|
||||
@return [{
|
||||
"Protocol": "tcp",
|
||||
"Port": "8888",
|
||||
"Strategy": "accept",
|
||||
"Family": "ipv4",
|
||||
"Address": "all",
|
||||
"Chain": "INPUT"
|
||||
}]
|
||||
'''
|
||||
try:
|
||||
list_port = self.list_input_port() + self.list_output_port()
|
||||
for i in list_port:
|
||||
i["Strategy"] = i["Strategy"].lower()
|
||||
return list_port
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
# 2024/4/29 下午2:39 列出防火墙中所有的INPUT端口规则
|
||||
def list_input_port(self):
|
||||
'''
|
||||
@name 列出防火墙中所有的INPUT端口规则
|
||||
@return [{
|
||||
"Protocol": "tcp",
|
||||
"Port": "8888",
|
||||
"Strategy": "accept",
|
||||
"Family": "ipv4",
|
||||
"Address": "all",
|
||||
"Chain": "INPUT"
|
||||
}]
|
||||
'''
|
||||
try:
|
||||
list_port = self.get_chain_port("INPUT")
|
||||
for i in list_port:
|
||||
i["Strategy"] = i["Strategy"].lower()
|
||||
return list_port
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
# 2024/4/29 下午2:39 列出防火墙中所有的OUTPUT端口规则
|
||||
def list_output_port(self):
|
||||
'''
|
||||
@name 列出防火墙中所有的OUTPUT端口规则
|
||||
@return [{
|
||||
"Protocol": "tcp",
|
||||
"Port": "8888",
|
||||
"Strategy": "accept",
|
||||
"Family": "ipv4",
|
||||
"Address": "all",
|
||||
"Chain": "OUTPUT"
|
||||
}]
|
||||
'''
|
||||
try:
|
||||
list_port = self.get_chain_port("OUTPUT")
|
||||
for i in list_port:
|
||||
i["Strategy"] = i["Strategy"].lower()
|
||||
return list_port
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
# 2024/4/29 下午3:28 根据链来获取端口规则,暂时只支持INPUT/OUTPUT链
|
||||
def get_chain_port(self, chain):
|
||||
'''
|
||||
@name 根据链来获取端口规则
|
||||
@author wzz <2024/4/29 下午3:29>
|
||||
@param chain = INPUT/OUTPUT
|
||||
@return [{
|
||||
"Protocol": "tcp",
|
||||
"Port": "8888",
|
||||
"Strategy": "accept",
|
||||
"Family": "ipv4",
|
||||
"Address": "all",
|
||||
"Chain": "OUTPUT"
|
||||
}]
|
||||
'''
|
||||
if chain not in ["INPUT", "OUTPUT"]:
|
||||
return []
|
||||
|
||||
try:
|
||||
stdout = self.get_chain_data(chain)
|
||||
if stdout == "":
|
||||
return []
|
||||
|
||||
lines = stdout.strip().split('\n')
|
||||
rules = []
|
||||
for line in lines:
|
||||
if line.startswith("Chain"):
|
||||
continue
|
||||
if not "dpt:" in line and not "multiport sports" in line:
|
||||
continue
|
||||
rule_info = line.split()
|
||||
if rule_info[0] == "num":
|
||||
continue
|
||||
if not rule_info[3] in ["ACCEPT", "DROP", "REJECT"]:
|
||||
continue
|
||||
if not rule_info[4] in self.protocol:
|
||||
continue
|
||||
if not "dpt" in rule_info[-1] and not "-" in rule_info[-1] and not ":" in rule_info[-1]:
|
||||
continue
|
||||
|
||||
if ":" in rule_info[-1] and not "dpt" in rule_info[-1]:
|
||||
Port = rule_info[-1]
|
||||
elif "-" in rule_info[-1]:
|
||||
Port = rule_info[-5].split(":")[1]
|
||||
else:
|
||||
Port = rule_info[-1].split(":")[1]
|
||||
|
||||
if "source IP range" in line and "multiport sports" in line:
|
||||
Address = rule_info[-4]
|
||||
elif not "0.0.0.0/0" in rule_info[8]:
|
||||
Address = rule_info[8]
|
||||
elif "-" in rule_info[-1]:
|
||||
Address = rule_info[-1]
|
||||
else:
|
||||
Address = "all"
|
||||
|
||||
rule = {
|
||||
"Protocol": self.protocol[rule_info[4]],
|
||||
"Port": Port,
|
||||
"Strategy": rule_info[3],
|
||||
"Family": "ipv4",
|
||||
"Address": Address,
|
||||
"Chain": chain,
|
||||
}
|
||||
rules.append(rule)
|
||||
|
||||
return rules
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
# 2024/4/29 下午3:28 根据链来获取IP规则,暂时只支持INPUT/OUTPUT链
|
||||
def get_chain_ip(self, chain):
|
||||
'''
|
||||
@name 根据链来获取端口规则
|
||||
@author wzz <2024/4/29 下午3:29>
|
||||
@param chain = INPUT/OUTPUT
|
||||
@return [
|
||||
{
|
||||
"Family": "ipv4",
|
||||
"Address": "192.168.1.190",
|
||||
"Strategy": "accept",
|
||||
"Chain": "INPUT"
|
||||
}
|
||||
]
|
||||
'''
|
||||
if chain not in ["INPUT", "OUTPUT"]:
|
||||
return []
|
||||
|
||||
try:
|
||||
stdout = self.get_chain_data(chain)
|
||||
if stdout == "":
|
||||
return []
|
||||
|
||||
lines = stdout.strip().split('\n')
|
||||
rules = []
|
||||
for line in lines:
|
||||
if line.startswith("Chain"):
|
||||
continue
|
||||
if "dpt:" in line or "multiport sports" in line:
|
||||
continue
|
||||
rule_info = line.split()
|
||||
if rule_info[0] == "num":
|
||||
continue
|
||||
if not rule_info[3] in ["ACCEPT", "DROP", "REJECT"]:
|
||||
continue
|
||||
if not rule_info[4] in self.protocol:
|
||||
continue
|
||||
|
||||
Address = ""
|
||||
if not "0.0.0.0/0" in rule_info[8]:
|
||||
Address = rule_info[8]
|
||||
elif "0.0.0.0/0" in rule_info[8] and "-" in rule_info[-1]:
|
||||
Address = rule_info[-1]
|
||||
|
||||
if Address == "":
|
||||
continue
|
||||
|
||||
rule = {
|
||||
"Family": "ipv4",
|
||||
"Address": Address,
|
||||
"Strategy": rule_info[3],
|
||||
"Chain": chain,
|
||||
}
|
||||
rules.append(rule)
|
||||
|
||||
return rules
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
# 2024/4/29 下午4:01 获取指定链的数据
|
||||
def get_chain_data(self, chain):
|
||||
'''
|
||||
@name 获取指定链的数据
|
||||
@author wzz <2024/4/29 下午4:01>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
cmd = "{} -t filter -L {} -nv --line-numbers".format(self.cmd_str, chain)
|
||||
stdout, stderr = public.ExecShell(cmd)
|
||||
return stdout
|
||||
except Exception as e:
|
||||
return ""
|
||||
|
||||
# 2024/4/29 下午2:46 列出防火墙中所有的INPUT和OUTPUT的ip规则
|
||||
def list_address(self):
|
||||
'''
|
||||
@name 列出防火墙中所有的ip规则
|
||||
@author wzz <2024/4/29 下午2:47>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return
|
||||
'''
|
||||
try:
|
||||
list_address = self.get_chain_ip("INPUT") + self.get_chain_ip("OUTPUT")
|
||||
for i in list_address:
|
||||
i["Strategy"] = i["Strategy"].lower()
|
||||
return list_address
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
# 2024/4/29 下午2:48 列出防火墙中所有input的ip规则
|
||||
def list_input_address(self):
|
||||
'''
|
||||
@name 列出防火墙中所有input的ip规则
|
||||
@author wzz <2024/4/29 下午2:48>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
list_address = self.get_chain_ip("INPUT")
|
||||
for i in list_address:
|
||||
i["Strategy"] = i["Strategy"].lower()
|
||||
return list_address
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
# 2024/4/29 下午2:49 列出防火墙中所有output的ip规则
|
||||
def list_output_address(self):
|
||||
'''
|
||||
@name 列出防火墙中所有output的ip规则
|
||||
@author wzz <2024/4/29 下午2:49>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
list_address = self.get_chain_ip("OUTPUT")
|
||||
for i in list_address:
|
||||
i["Strategy"] = i["Strategy"].lower()
|
||||
return list_address
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
# 2024/4/29 下午2:49 添加INPUT端口规则
|
||||
def input_port(self, info, operation):
|
||||
'''
|
||||
@name 添加INPUT端口规则
|
||||
@author wzz <2024/4/29 下午2:50>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
return self.set_chain_port(info, operation, "INPUT")
|
||||
except Exception as e:
|
||||
return self._result(False, "设置端口规则失败:{}".format(str(e)))
|
||||
|
||||
# 2024/4/29 下午2:50 设置output端口策略
|
||||
def output_port(self, info, operation):
|
||||
'''
|
||||
@name 设置output端口策略
|
||||
@author wzz <2024/4/29 下午2:50>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
return self.set_chain_port(info, operation, "OUTPUT")
|
||||
except Exception as e:
|
||||
return self._result(False, "设置端口规则失败:{}".format(str(e)))
|
||||
|
||||
# 2024/4/29 下午4:49 添加/删除指定链的端口规则
|
||||
def set_chain_port(self, info, operation, chain):
|
||||
'''
|
||||
@name 添加/删除指定链的端口规则
|
||||
@author wzz <2024/4/29 下午4:49>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
if not chain in ["INPUT", "OUTPUT"]:
|
||||
return self._result(False, "设置端口规则失败:{}".format("不支持的链类型"))
|
||||
|
||||
if info['Protocol'] not in ["tcp", "udp"]:
|
||||
return self._result(False, "设置端口规则失败:{}".format("不支持的协议类型"))
|
||||
if info["Strategy"] == "accept":
|
||||
info["Strategy"] = "ACCEPT"
|
||||
elif info["Strategy"] == "drop":
|
||||
info["Strategy"] = "DROP"
|
||||
elif info["Strategy"] == "reject":
|
||||
info["Strategy"] = "REJECT"
|
||||
else:
|
||||
return self._result(False, "设置端口规则失败:{}".format("不支持的策略类型"))
|
||||
|
||||
if operation == "add":
|
||||
operation = "-I"
|
||||
elif operation == "remove":
|
||||
operation = "-D"
|
||||
|
||||
rule = "{} -t filter {} {} -p {} --dport {} -j {}".format(
|
||||
self.cmd_str,
|
||||
operation,
|
||||
chain,
|
||||
info['Protocol'],
|
||||
info['Port'],
|
||||
info['Strategy']
|
||||
)
|
||||
stdout, stderr = public.ExecShell(rule)
|
||||
if stderr:
|
||||
return self._result(False, "设置端口规则失败:{}".format(stderr))
|
||||
return self._result(True, "设置端口规则成功")
|
||||
except Exception as e:
|
||||
return self._result(False, "设置端口规则失败:{}".format(str(e)))
|
||||
|
||||
# 2024/4/29 下午5:01 添加/删除指定链的复杂端口规则
|
||||
def set_chain_rich_port(self, info, operation, chain):
|
||||
'''
|
||||
@name 添加/删除指定链的复杂端口规则
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
if not chain in ["INPUT", "OUTPUT"]:
|
||||
return self._result(False, "设置端口规则失败:{}".format("不支持的链类型"))
|
||||
|
||||
if "Address" in info and info["Address"] == "":
|
||||
info["Address"] = "all"
|
||||
if "Address" in info and public.is_ipv6(info['Address']):
|
||||
return self._result(False, "设置端口规则失败:{}".format("不支持的IPV6地址"))
|
||||
|
||||
if info['Protocol'] not in ["tcp", "udp"]:
|
||||
return self._result(False, "设置端口规则失败:{}".format("不支持的协议类型"))
|
||||
if info["Strategy"] == "accept":
|
||||
info["Strategy"] = "ACCEPT"
|
||||
elif info["Strategy"] == "drop":
|
||||
info["Strategy"] = "DROP"
|
||||
elif info["Strategy"] == "reject":
|
||||
info["Strategy"] = "REJECT"
|
||||
else:
|
||||
return self._result(False, "设置端口规则失败:{}".format("不支持的策略类型"))
|
||||
|
||||
if operation == "add":
|
||||
operation = "-I"
|
||||
elif operation == "remove":
|
||||
operation = "-D"
|
||||
|
||||
info['Port'] = info['Port'].replace("-", ":")
|
||||
info["Address"] = info["Address"].replace(":", "-")
|
||||
if ":" in info['Port'] or "-" in info['Port']:
|
||||
if ":" in info["Address"] or "-" in info["Address"]:
|
||||
# iptables -t filter -I INPUT -m iprange --src-range 192.168.1.100-192.168.1.200 -p tcp -m multiport --sports 8000:9000 -j ACCEPT
|
||||
rule = "{} -t filter {} {} -m iprange --src-range {} -p {} -m multiport --sports {} -j {}".format(
|
||||
self.cmd_str,
|
||||
operation,
|
||||
chain,
|
||||
info['Address'],
|
||||
info['Protocol'],
|
||||
info['Port'],
|
||||
info['Strategy']
|
||||
)
|
||||
else:
|
||||
# iptables -t filter -I INPUT -p tcp -m multiport --sports 8000:9000 -s 192.168.1.100 -j ACCEPT
|
||||
rule = "{} -t filter {} {} -p {} -m multiport --sports {} -s {} -j {}".format(
|
||||
self.cmd_str,
|
||||
operation,
|
||||
chain,
|
||||
info['Protocol'],
|
||||
info['Port'],
|
||||
info['Address'],
|
||||
info['Strategy']
|
||||
)
|
||||
else:
|
||||
if ":" in info["Address"] or "-" in info["Address"]:
|
||||
# iptables -t filter -I OUTPUT -p tcp --dport 22333 -m iprange --src-range 192.168.1.100-192.168.1.200 -j ACCEPT
|
||||
rule = "{} -t filter {} {} -p {} --dport {} -m iprange --src-range {} -j {}".format(
|
||||
self.cmd_str,
|
||||
operation,
|
||||
chain,
|
||||
info['Protocol'],
|
||||
info['Port'],
|
||||
info['Address'],
|
||||
info['Strategy']
|
||||
)
|
||||
else:
|
||||
# iptables -t filter -I OUTPUT -p tcp --dport 22333 -s 192.168.1.0/24 -j ACCEPT
|
||||
rule = "{} -t filter {} {} -p {} --dport {} -s {} -j {}".format(
|
||||
self.cmd_str,
|
||||
operation,
|
||||
chain,
|
||||
info['Protocol'],
|
||||
info['Port'],
|
||||
info['Address'],
|
||||
info['Strategy']
|
||||
)
|
||||
|
||||
stdout, stderr = public.ExecShell(rule)
|
||||
if stderr:
|
||||
return self._result(False, "设置端口规则失败:{}".format(stderr))
|
||||
return self._result(True, "设置端口规则成功")
|
||||
except Exception as e:
|
||||
return self._result(False, "设置端口规则失败:{}".format(str(e)))
|
||||
|
||||
# 2024/4/29 下午5:01 添加/删除指定链的复杂ip规则
|
||||
def set_chain_rich_ip(self, info, operation, chain):
|
||||
'''
|
||||
@name 添加/删除指定链的复杂ip规则
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
if not chain in ["INPUT", "OUTPUT"]:
|
||||
return self._result(False, "设置规则失败:{}".format("不支持的链类型"))
|
||||
|
||||
if "Address" in info and info["Address"] == "":
|
||||
info["Address"] = "all"
|
||||
if "Address" in info and public.is_ipv6(info['Address']):
|
||||
return self._result(False, "设置规则失败:{}".format("不支持的IPV6地址"))
|
||||
|
||||
if info["Strategy"] == "accept":
|
||||
info["Strategy"] = "ACCEPT"
|
||||
elif info["Strategy"] == "drop":
|
||||
info["Strategy"] = "DROP"
|
||||
elif info["Strategy"] == "reject":
|
||||
info["Strategy"] = "REJECT"
|
||||
else:
|
||||
return self._result(False, "设置规则失败:{}".format("不支持的策略类型"))
|
||||
|
||||
if operation == "add":
|
||||
operation = "-I"
|
||||
elif operation == "remove":
|
||||
operation = "-D"
|
||||
|
||||
if ":" in info["Address"] or "-" in info["Address"]:
|
||||
# iptables -t filter -I INPUT -m iprange --src-range 192.168.1.100-192.168.1.200 -j ACCEPT
|
||||
rule = "{} -t filter {} {} -m iprange --src-range {} -j {}".format(
|
||||
self.cmd_str,
|
||||
operation,
|
||||
chain,
|
||||
info['Address'],
|
||||
info['Strategy']
|
||||
)
|
||||
else:
|
||||
# iptables -t filter -I INPUT -s 192.168.1.100 -j ACCEPT
|
||||
rule = "{} -t filter {} {} -s {} -j {}".format(
|
||||
self.cmd_str,
|
||||
operation,
|
||||
chain,
|
||||
info['Address'],
|
||||
info['Strategy']
|
||||
)
|
||||
|
||||
|
||||
stdout, stderr = public.ExecShell(rule)
|
||||
if stderr:
|
||||
return self._result(False, "设置规则失败:{}".format(stderr))
|
||||
return self._result(True, "设置规则成功")
|
||||
except Exception as e:
|
||||
return self._result(False, "设置规则失败:{}".format(str(e)))
|
||||
|
||||
# 2024/4/29 下午2:51 INPUT复杂一些的规则管理
|
||||
def rich_rules(self, info, operation):
|
||||
'''
|
||||
@name
|
||||
@author wzz <2024/4/29 下午2:51>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
if "Priority" in info and not "Port" in info:
|
||||
return self.set_chain_rich_ip(info, operation, "INPUT")
|
||||
else:
|
||||
return self.set_chain_rich_port(info, operation, "INPUT")
|
||||
except Exception as e:
|
||||
return self._result(False, "设置端口规则失败:{}".format(str(e)))
|
||||
|
||||
# 2024/4/29 下午2:52 OUTPUT复杂一些的规则管理
|
||||
def output_rich_rules(self, info, operation):
|
||||
'''
|
||||
@name OUTPUT复杂一些的规则管理
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
if "Priority" in info and not "Port" in info:
|
||||
return self.set_chain_rich_ip(info, operation, "OUTPUT")
|
||||
else:
|
||||
return self.set_chain_rich_port(info, operation, "OUTPUT")
|
||||
except Exception as e:
|
||||
return self._result(False, "设置端口规则失败:{}".format(str(e)))
|
||||
|
||||
# 2024/3/19 下午 3:03 清空指定链中的所有规则
|
||||
def flush_chain(self, chain_name):
|
||||
'''
|
||||
@name 清空指定链中的所有规则
|
||||
@author wzz <2024/3/19 下午 3:03>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
subprocess.check_output(
|
||||
[self.cmd_str, '-F', chain_name], stderr=subprocess.STDOUT, universal_newlines=True
|
||||
)
|
||||
return chain_name + " chain flushed successfully."
|
||||
except Exception as e:
|
||||
return "Failed to flush " + chain_name + " chain."
|
||||
|
||||
# 2024/3/19 下午 3:03 获取当前系统中可用的链的名称列表
|
||||
def get_chain_names(self, parm):
|
||||
'''
|
||||
@name 获取当前系统中可用的链的名称列表
|
||||
@author wzz <2024/3/19 下午 3:03>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
if not self.check_table_name(parm['table']):
|
||||
return "错误: 不支持的表名."
|
||||
stdout = subprocess.check_output(
|
||||
[self.cmd_str, '-t', parm['table'], '-L'], stderr=subprocess.STDOUT, universal_newlines=True
|
||||
)
|
||||
chain_names = re.findall(r"Chain\s([A-Z]+)", stdout)
|
||||
return chain_names
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
# 2024/3/19 下午 3:17 构造端口转发规则,然后调用insert_rule方法插入规则
|
||||
def port_forward(self, info, operation):
|
||||
'''
|
||||
@name 构造端口转发规则,然后调用insert_rule方法插入规则
|
||||
@param "info": {
|
||||
"Protocol": "tcp/udp",
|
||||
"S_Port": "80",
|
||||
"T_Address": "0.0.0.0/0",
|
||||
"T_Port": "8080"
|
||||
}
|
||||
@param "operation": "add" or "remove"
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
rule = " -p {}".format(info['Protocol'])
|
||||
|
||||
if "S_Address" in info and info['S_Address'] != "":
|
||||
rule += " -s {}".format(info['S_Address'])
|
||||
|
||||
rule += " --dport {0} -j DNAT --to-destination {1}:{2}".format(
|
||||
info['S_Port'],
|
||||
info['T_Address'],
|
||||
info['T_Port'],
|
||||
)
|
||||
|
||||
parm = {
|
||||
"table": "nat",
|
||||
"chain_name": "PREROUTING",
|
||||
"rule": rule
|
||||
}
|
||||
if operation not in ["add", "remove"]:
|
||||
return "请输入正确的操作类型. (add/remove)"
|
||||
|
||||
if operation == "add":
|
||||
parm['type'] = "-I"
|
||||
elif operation == "remove":
|
||||
parm['type'] = "-D"
|
||||
return self.rule_manage(parm)
|
||||
except Exception as e:
|
||||
return self._result(False, "设置端口转发规则失败:{}".format(str(e)))
|
||||
|
||||
# 2024/3/19 下午 3:03 在指定链中管理规则
|
||||
def rule_manage(self, parm):
|
||||
'''
|
||||
@name 在指定链中管理规则
|
||||
@author wzz <2024/3/19 下午 3:03>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
if not self.check_table_name(parm['table']):
|
||||
return self._result(False, "不支持的表名{}".format(parm['table']))
|
||||
|
||||
rule = "{} -t {} {} {} {}".format(
|
||||
self.cmd_str, parm['table'], parm['type'], parm['chain_name'], parm['rule']
|
||||
)
|
||||
stdout, stderr = public.ExecShell(rule)
|
||||
if stderr:
|
||||
return self._result(False, "规则设置失败:{}".format(stderr))
|
||||
|
||||
return self._result(True, "规则设置成功")
|
||||
except Exception as e:
|
||||
return self._result(False, "规则设置失败: {}".format(str(e)))
|
||||
|
||||
# 2024/4/29 下午5:55 获取所有端口转发列表
|
||||
def list_port_forward(self):
|
||||
'''
|
||||
@name 获取所有端口转发列表
|
||||
@author wzz <2024/4/29 下午5:55>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
return self.get_nat_prerouting_rules()
|
||||
|
||||
# 2024/3/19 下午 4:00 调用list_rules获取所有nat表中的PREROUTING链的规则(端口转发规则),并分析成字典返回
|
||||
def get_nat_prerouting_rules(self):
|
||||
'''
|
||||
@name 调用list_rules获取所有nat表中的PREROUTING链的规则(端口转发规则),并分析成字典返回
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
port_forward_rules = self.list_rules({"table": "nat", "chain_name": "PREROUTING"})
|
||||
rules = []
|
||||
for rule in port_forward_rules:
|
||||
if rule["target"] != "DNAT": continue
|
||||
options = rule["options"].split(' ')
|
||||
|
||||
protocol = "TCP"
|
||||
if rule["prot"] == "6" or rule["prot"] == "tcp":
|
||||
protocol = "TCP"
|
||||
elif rule["prot"] == "17" or rule["prot"] == "udp":
|
||||
protocol = "UDP"
|
||||
elif rule["prot"] == "0" or rule["prot"] == "all":
|
||||
protocol = "TCP/UDP"
|
||||
rules.append({
|
||||
"type": "port_forward",
|
||||
"number": rule["number"],
|
||||
"S_Address": rule["source"],
|
||||
"S_Port": options[1].split("dpt:")[1],
|
||||
"T_Address": options[2].split("to:")[1].split(":")[0],
|
||||
"T_Port": options[2].split("to:")[1].split(":")[1],
|
||||
"Protocol": protocol.lower()
|
||||
})
|
||||
return rules
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
# 2024/4/29 下午2:43 格式化输出json
|
||||
def format_json(self, data):
|
||||
'''
|
||||
@name 格式化输出json
|
||||
@param "data": json数据
|
||||
@return json字符串
|
||||
'''
|
||||
import json
|
||||
from pygments import highlight, lexers, formatters
|
||||
|
||||
formatted_json = json.dumps(data, indent=3)
|
||||
colorful_json = highlight(formatted_json.encode('utf-8'), lexers.JsonLexer(),
|
||||
formatters.TerminalFormatter())
|
||||
return colorful_json
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = sys.argv
|
||||
firewall = Iptables()
|
||||
if len(args) < 2:
|
||||
print("Welcome to the iptables command-line interface!")
|
||||
print()
|
||||
print("Available options:")
|
||||
print("list_rules: list_rules <table> <chain_name>")
|
||||
print("flush_chain: flush_chain <table>")
|
||||
print("get_chain_names: get_chain_names <table>")
|
||||
print("port_forward: port_forward <S_Address> <S_Port> <T_Address> <T_Port> <Protocol> <Operation>")
|
||||
print("get_nat_prerouting_rules: get_nat_prerouting_rules")
|
||||
print()
|
||||
sys.exit(1)
|
||||
if args[1] == "list_rules":
|
||||
# firewall.list_rules({"table": args[2], "chain_name": args[3]})
|
||||
print(firewall.list_rules({"table": args[2], "chain_name": args[3]}))
|
||||
elif args[1] == "flush_chain":
|
||||
print(firewall.flush_chain(args[2]))
|
||||
elif args[1] == "get_chain_names":
|
||||
table = args[2] if len(args) > 2 else "filter"
|
||||
print(firewall.get_chain_names({"table": table}))
|
||||
elif args[1] == "port_forward":
|
||||
if len(args) < 8:
|
||||
print("传参使用方法: port_forward <S_Address> <S_Port> <T_Address> <T_Port> <Protocol> <Operation>")
|
||||
sys.exit(1)
|
||||
|
||||
info = {
|
||||
"S_Address": args[2],
|
||||
"S_Port": args[3],
|
||||
"T_Address": args[4],
|
||||
"T_Port": args[5],
|
||||
"Protocol": args[6]
|
||||
}
|
||||
print(firewall.port_forward(info, args[7]))
|
||||
elif args[1] == "get_nat_prerouting_rules":
|
||||
import json
|
||||
from pygments import highlight, lexers, formatters
|
||||
|
||||
formatted_json = json.dumps(firewall.get_nat_prerouting_rules(), indent=3)
|
||||
colorful_json = highlight(formatted_json.encode('utf-8'), lexers.JsonLexer(),
|
||||
formatters.TerminalFormatter())
|
||||
print(colorful_json)
|
||||
# print(firewall.get_nat_prerouting_rules())
|
||||
elif args[1] == "list_port":
|
||||
print(firewall.format_json(firewall.list_port()))
|
||||
elif args[1] == "list_input_port":
|
||||
print(firewall.format_json(firewall.list_input_port()))
|
||||
elif args[1] == "list_output_port":
|
||||
print(firewall.format_json(firewall.list_output_port()))
|
||||
elif args[1] == "list_address":
|
||||
print(firewall.format_json(firewall.list_address()))
|
||||
elif args[1] == "list_input_address":
|
||||
print(firewall.format_json(firewall.list_input_address()))
|
||||
elif args[1] == "list_output_address":
|
||||
print(firewall.format_json(firewall.list_output_address()))
|
||||
elif args[1] == "input_port":
|
||||
info = {
|
||||
"Protocol": args[2],
|
||||
"Port": args[3],
|
||||
"Strategy": args[4]
|
||||
}
|
||||
print(firewall.input_port(info, args[5]))
|
||||
elif args[1] == "output_port":
|
||||
info = {
|
||||
"Protocol": args[2],
|
||||
"Port": args[3],
|
||||
"Strategy": args[4]
|
||||
}
|
||||
print(firewall.output_port(info, args[5]))
|
||||
elif args[1] == "rich_rules":
|
||||
info = {
|
||||
"Protocol": args[2],
|
||||
"Port": args[3],
|
||||
"Address": args[4],
|
||||
"Strategy": args[5]
|
||||
}
|
||||
print(firewall.rich_rules(info, args[6]))
|
||||
elif args[1] == "output_rich_rules":
|
||||
info = {
|
||||
"Protocol": args[2],
|
||||
"Port": args[3],
|
||||
"Address": args[4],
|
||||
"Strategy": args[5]
|
||||
}
|
||||
print(firewall.output_rich_rules(info, args[6]))
|
||||
else:
|
||||
print("不支持的传参: " + args[1])
|
||||
sys.exit(1)
|
||||
@@ -0,0 +1,729 @@
|
||||
#!/www/server/panel/pyenv/bin/python3.7
|
||||
# coding: utf-8
|
||||
# -------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2014-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: wzz <wzz@bt.cn>
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# ------------------------------
|
||||
# 系统防火墙模型 - ufw封装库
|
||||
# ------------------------------
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
import sys
|
||||
if "/www/server/panel/class" not in sys.path:
|
||||
sys.path.insert(0, "/www/server/panel/class")
|
||||
import public
|
||||
# import re
|
||||
from firewallModel.app.appBase import Base
|
||||
|
||||
class Ufw(Base):
|
||||
def __init__(self):
|
||||
self.cmd_str = self._set_cmd_str()
|
||||
|
||||
def _set_cmd_str(self):
|
||||
return "ufw"
|
||||
|
||||
# 2024/3/19 下午 5:00 获取系统防火墙的运行状态
|
||||
def status(self):
|
||||
'''
|
||||
@name 获取系统防火墙的运行状态
|
||||
@author wzz <2024/3/19 下午 5:00>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
result = subprocess.run([self.cmd_str, "status"], capture_output=True, text=True, check=True)
|
||||
if "Status: active" in result.stdout:
|
||||
return "running"
|
||||
elif "状态: 激活" in result.stdout:
|
||||
return "running"
|
||||
else:
|
||||
return "not running"
|
||||
except subprocess.CalledProcessError:
|
||||
return "not running"
|
||||
except Exception as e:
|
||||
return "not running"
|
||||
|
||||
# 2024/3/19 下午 5:00 获取系统防火墙的版本号
|
||||
def version(self):
|
||||
'''
|
||||
@name 获取系统防火墙的版本号
|
||||
@author wzz <2024/3/19 下午 5:00>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
result = subprocess.run([self.cmd_str, "version"], capture_output=True, text=True, check=True)
|
||||
info = result.stdout.replace("\n", "")
|
||||
return info.replace("ufw ", "")
|
||||
except Exception as e:
|
||||
return "未知版本"
|
||||
|
||||
# 2024/3/19 下午 5:00 启动防火墙
|
||||
def start(self):
|
||||
'''
|
||||
@name 启动防火墙
|
||||
@author wzz <2024/3/19 下午 5:00>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
stdout, stderr = public.ExecShell("echo y | {} enable".format(self.cmd_str))
|
||||
if stderr:
|
||||
return self._result(False, "启动防火墙失败:{}".format(stderr))
|
||||
return self._result(True, "启动防火墙成功")
|
||||
except Exception as e:
|
||||
return self._result(False, "启动防火墙失败:{}".format(str(e)))
|
||||
|
||||
# 2024/3/19 下午 5:00 停止防火墙
|
||||
def stop(self):
|
||||
'''
|
||||
@name 停止防火墙
|
||||
@author wzz <2024/3/19 下午 5:00>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
stdout, stderr = public.ExecShell("{} disable".format(self.cmd_str))
|
||||
if stderr:
|
||||
return self._result(False, "停止防火墙失败:{}".format(stderr))
|
||||
return self._result(True, "停止防火墙成功")
|
||||
except Exception as e:
|
||||
return self._result(False, "停止防火墙失败:{}".format(str(e)))
|
||||
|
||||
# 2024/3/19 下午 4:59 重启防火墙
|
||||
def restart(self):
|
||||
'''
|
||||
@name 重启防火墙
|
||||
@author wzz <2024/3/19 下午 4:59>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
self.stop()
|
||||
self.start()
|
||||
except Exception as e:
|
||||
return self._result(False, "重启防火墙失败:{}".format(str(e)))
|
||||
|
||||
# 2024/3/19 下午 4:59 重载防火墙
|
||||
def reload(self):
|
||||
'''
|
||||
@name 重载防火墙
|
||||
@author wzz <2024/3/19 下午 4:59>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
subprocess.run([self.cmd_str, "reload"], check=True, stdout=subprocess.PIPE)
|
||||
except Exception as e:
|
||||
return self._result(False, "重载防火墙失败:{}".format(str(e)))
|
||||
|
||||
# 2024/3/19 上午 10:39 列出防火墙中所有端口规则
|
||||
def list_port(self):
|
||||
'''
|
||||
@name 列出防火墙中所有端口规则
|
||||
@author wzz <2024/3/19 上午 10:39>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[self.cmd_str, "status", "verbose"], capture_output=True, text=True, check=True
|
||||
)
|
||||
port_infos = result.stdout.split("\n")
|
||||
datas = []
|
||||
is_start = False
|
||||
for line in port_infos:
|
||||
if line.startswith("-"):
|
||||
is_start = True
|
||||
continue
|
||||
if not is_start:
|
||||
continue
|
||||
item_fire = self._load_info(line, "port")
|
||||
if item_fire.get("Port") and item_fire["Port"] != "Anywhere" and "." not in item_fire["Port"]:
|
||||
item_fire["Port"] = item_fire["Port"].replace(":", "-")
|
||||
item_fire["Address"] = "all" if item_fire["Address"] == "Anywhere" else item_fire["Address"]
|
||||
|
||||
datas.append(item_fire)
|
||||
return datas
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
# 2024/3/19 上午 10:39 列出防火墙中所有input端口规则
|
||||
def list_input_port(self):
|
||||
'''
|
||||
@name 列出防火墙中所有input端口规则
|
||||
@author wzz <2024/3/19 上午 10:39>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[self.cmd_str, "status", "verbose"], capture_output=True, text=True, check=True
|
||||
)
|
||||
port_infos = result.stdout.split("\n")
|
||||
datas = []
|
||||
is_start = False
|
||||
for line in port_infos:
|
||||
if line.startswith("-"):
|
||||
is_start = True
|
||||
continue
|
||||
if not is_start:
|
||||
continue
|
||||
item_fire = self._load_info(line, "port")
|
||||
if item_fire.get("Port") and item_fire["Port"] != "Anywhere" and "." not in item_fire["Port"]:
|
||||
item_fire["Port"] = item_fire["Port"].replace(":", "-")
|
||||
|
||||
if item_fire["Chain"] == "INPUT":
|
||||
datas.append(item_fire)
|
||||
return datas
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
# 2024/3/19 上午 10:39 列出防火墙中所有output端口规则
|
||||
def list_output_port(self):
|
||||
'''
|
||||
@name 列出防火墙中所有output端口规则
|
||||
@author wzz <2024/3/19 上午 10:39>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[self.cmd_str, "status", "verbose"], capture_output=True, text=True, check=True
|
||||
)
|
||||
port_infos = result.stdout.split("\n")
|
||||
datas = []
|
||||
is_start = False
|
||||
for line in port_infos:
|
||||
if line.startswith("-"):
|
||||
is_start = True
|
||||
continue
|
||||
if not is_start:
|
||||
continue
|
||||
item_fire = self._load_info(line, "port")
|
||||
if item_fire.get("Port") and item_fire["Port"] != "Anywhere" and "." not in item_fire["Port"]:
|
||||
item_fire["Port"] = item_fire["Port"].replace(":", "-")
|
||||
|
||||
if item_fire["Chain"] == "OUTPUT":
|
||||
datas.append(item_fire)
|
||||
return datas
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
# 2024/3/19 上午 10:39 列出防火墙中所有的ip规则
|
||||
def list_address(self):
|
||||
'''
|
||||
@name 列出防火墙中所有的ip规则
|
||||
@author wzz <2024/3/19 上午 10:39>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[self.cmd_str, "status", "verbose"], capture_output=True, text=True, check=True
|
||||
)
|
||||
port_infos = result.stdout.split("\n")
|
||||
datas = []
|
||||
is_start = False
|
||||
for line in port_infos:
|
||||
if line.startswith("-"):
|
||||
is_start = True
|
||||
continue
|
||||
if not is_start:
|
||||
continue
|
||||
item_fire = self._load_info(line, "address")
|
||||
if "Port" in item_fire: continue
|
||||
if item_fire.get("Address"):
|
||||
datas.append(item_fire)
|
||||
return datas
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
# 2024/3/19 上午 10:39 列出防火墙中所有input的ip规则
|
||||
def list_input_address(self):
|
||||
'''
|
||||
@name 列出防火墙中所有input的ip规则
|
||||
@author wzz <2024/3/19 上午 10:39>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[self.cmd_str, "status", "verbose"], capture_output=True, text=True, check=True
|
||||
)
|
||||
port_infos = result.stdout.split("\n")
|
||||
datas = []
|
||||
is_start = False
|
||||
for line in port_infos:
|
||||
if line.startswith("-"):
|
||||
is_start = True
|
||||
continue
|
||||
if not is_start:
|
||||
continue
|
||||
if " IN" not in line:
|
||||
continue
|
||||
item_fire = self._load_info(line, "address")
|
||||
if "Port" in item_fire: continue
|
||||
if item_fire.get("Address"):
|
||||
datas.append(item_fire)
|
||||
return datas
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
# 2024/3/19 上午 10:39 列出防火墙中所有output的ip规则
|
||||
def list_output_address(self):
|
||||
'''
|
||||
@name 列出防火墙中所有output的ip规则
|
||||
@author wzz <2024/3/19 上午 10:39>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[self.cmd_str, "status", "verbose"], capture_output=True, text=True, check=True
|
||||
)
|
||||
port_infos = result.stdout.split("\n")
|
||||
datas = []
|
||||
is_start = False
|
||||
for line in port_infos:
|
||||
if line.startswith("-"):
|
||||
is_start = True
|
||||
continue
|
||||
if not is_start:
|
||||
continue
|
||||
if " OUT" not in line:
|
||||
continue
|
||||
item_fire = self._load_info(line, "address")
|
||||
if "Port" in item_fire: continue
|
||||
if item_fire.get("Address"):
|
||||
datas.append(item_fire)
|
||||
return datas
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
# 2024/3/19 下午 4:59 添加端口规则
|
||||
def input_port(self, info, operation):
|
||||
'''
|
||||
@name 添加端口规则
|
||||
@author wzz <2024/3/19 下午 4:59>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
if info["Strategy"] == "accept":
|
||||
info["Strategy"] = "allow"
|
||||
elif info["Strategy"] == "drop":
|
||||
info["Strategy"] = "deny"
|
||||
|
||||
if info["Port"].find('-') != -1:
|
||||
info["Port"] = info["Port"].replace('-', ':')
|
||||
|
||||
if operation == "add":
|
||||
if info['Protocol'].find("/") != -1:
|
||||
rich_rule = self.cmd_str + " insert 1 {} {}".format(info['Strategy'], info['Port'])
|
||||
stdout, stderr = public.ExecShell(rich_rule)
|
||||
elif info['Protocol'] == "tcp/udp":
|
||||
stdout, stderr = public.ExecShell(self.cmd_str + " allow " + info['Port'])
|
||||
else:
|
||||
stdout, stderr = public.ExecShell(self.cmd_str + " allow " + info['Port'] + "/" + info['Protocol'])
|
||||
else:
|
||||
if info['Protocol'].find("/") != -1:
|
||||
rich_rule = "{} delete {} {}".format(self.cmd_str, info['Strategy'], info['Port'])
|
||||
stdout, stderr = public.ExecShell(rich_rule)
|
||||
elif info['Protocol'] == "tcp/udp":
|
||||
stdout, stderr = public.ExecShell(self.cmd_str + " delete allow " + info['Port'])
|
||||
else:
|
||||
stdout, stderr = public.ExecShell(self.cmd_str + " delete allow " + info['Port'] + "/" + info['Protocol'])
|
||||
|
||||
if stderr:
|
||||
if "setlocale" in stderr:
|
||||
return self._result(True, "设置端口规则成功")
|
||||
return self._result(False, "设置端口规则失败:{}".format(stderr))
|
||||
|
||||
return self._result(True, "设置端口规则成功")
|
||||
|
||||
except Exception as e:
|
||||
if "setlocale" in str(e):
|
||||
return self._result(True, "设置端口规则成功")
|
||||
return self._result(False, "设置端口规则失败:{}".format(str(e)))
|
||||
|
||||
# 2024/3/24 下午 11:28 设置output端口策略
|
||||
def output_port(self, info, operation):
|
||||
'''
|
||||
@name 设置output端口策略
|
||||
@param info: 端口号
|
||||
@param operation: 操作
|
||||
@return None
|
||||
'''
|
||||
try:
|
||||
if info["Strategy"] == "accept":
|
||||
info["Strategy"] = "allow"
|
||||
elif info["Strategy"] == "drop":
|
||||
info["Strategy"] = "deny"
|
||||
|
||||
if operation == "add":
|
||||
if info['Protocol'].find('/') != -1:
|
||||
cmd = "{} {} out {}".format(self.cmd_str, info['Strategy'], info['Port'])
|
||||
else:
|
||||
cmd = "{} {} out {}/{}".format(self.cmd_str, info['Strategy'], info['Port'], info['Protocol'])
|
||||
else:
|
||||
if info['Protocol'].find('/') != -1:
|
||||
cmd = "{} delete {} out {}".format(self.cmd_str, info['Strategy'], info['Port'])
|
||||
else:
|
||||
cmd = "{} delete {} out {}/{}".format(self.cmd_str, info['Strategy'], info['Port'], info['Protocol'])
|
||||
stdout, stderr = public.ExecShell(cmd)
|
||||
if stderr:
|
||||
if "setlocale" in stderr:
|
||||
return self._result(True, "设置端口规则成功")
|
||||
return self._result(False, "设置output端口规则失败:{}".format(stderr))
|
||||
return self._result(True, "设置output端口规则成功")
|
||||
except Exception as e:
|
||||
if "setlocale" in str(e):
|
||||
return self._result(True, "设置output端口规则成功")
|
||||
return self._result(False, "设置output端口规则失败:{}".format(str(e)))
|
||||
|
||||
# 2024/3/19 下午 4:58 复杂一些的规则管理
|
||||
def rich_rules(self, info, operation):
|
||||
'''
|
||||
@name 复杂一些的规则管理
|
||||
@author wzz <2024/3/19 下午 4:58>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
try:
|
||||
if info["Strategy"] == "accept":
|
||||
info["Strategy"] = "allow"
|
||||
elif info["Strategy"] == "drop":
|
||||
info["Strategy"] = "deny"
|
||||
else:
|
||||
return self._result(False, "未知的策略参数:{}".format(info["Strategy"]))
|
||||
|
||||
rule_str = "{} insert 1 {} ".format(self.cmd_str, info["Strategy"])
|
||||
if "Address" in info and public.is_ipv6(info['Address']):
|
||||
rule_str = "{} {} ".format(self.cmd_str, info["Strategy"])
|
||||
if operation == "remove":
|
||||
rule_str = "{} delete {} ".format(self.cmd_str, info["Strategy"])
|
||||
|
||||
if "Address" in info and info['Address'] != "all":
|
||||
rule_str += "from {} ".format(info['Address'])
|
||||
if len(info.get("Protocol", "")) != 0 and "/" not in info['Protocol']:
|
||||
rule_str += "proto {} ".format(info['Protocol'])
|
||||
if len(info.get("Port", "")) != 0:
|
||||
rule_str += "to any port {} ".format(info['Port'])
|
||||
stdout, stderr = public.ExecShell(rule_str)
|
||||
if stderr:
|
||||
if "Rule added" in stdout or "Rule deleted" in stdout or "Rule updated" in stdout or "Rule inserted" in stdout or "Skipping adding existing rule" in stdout:
|
||||
return self._result(True, "设置规则成功")
|
||||
if "setlocale" in stderr:
|
||||
return self._result(True, "设置规则成功")
|
||||
return self._result(False, "规则设置失败:{}".format(stderr))
|
||||
return self._result(True, "设置规则成功")
|
||||
except Exception as e:
|
||||
if "setlocale" in str(e):
|
||||
return self._result(True, "设置规则成功")
|
||||
return self._result(False, "规则设置失败:{}".format(e))
|
||||
|
||||
# 2024/3/24 下午 11:29 设置output rich_rules
|
||||
def output_rich_rules(self, info, operation):
|
||||
'''
|
||||
@name 设置output rich_rules
|
||||
@param info: 规则
|
||||
@param operation: 操作
|
||||
@return None
|
||||
'''
|
||||
try:
|
||||
if info["Strategy"] == "accept":
|
||||
info["Strategy"] = "allow"
|
||||
elif info["Strategy"] == "drop":
|
||||
info["Strategy"] = "deny"
|
||||
else:
|
||||
return self._result(False, "未知的策略: {}".format(info["Strategy"]))
|
||||
|
||||
rule_str = "{} insert 1 {} ".format(self.cmd_str, info["Strategy"])
|
||||
if "Address" in info and public.is_ipv6(info['Address']):
|
||||
rule_str = "{} {} ".format(self.cmd_str, info["Strategy"])
|
||||
if operation == "remove":
|
||||
rule_str = "{} delete {} ".format(self.cmd_str, info["Strategy"])
|
||||
|
||||
if len(info.get("Address", "")) != 0:
|
||||
rule_str += "out from {} ".format(info['Address'])
|
||||
if len(info.get("Protocol", "")) != 0:
|
||||
rule_str += "proto {} ".format(info['Protocol'])
|
||||
if len(info.get("Port", "")) != 0:
|
||||
rule_str += "to any port {} ".format(info['Port'])
|
||||
stdout, stderr = public.ExecShell(rule_str)
|
||||
if stderr:
|
||||
if "Rule added" in stdout or "Rule deleted" in stdout or "Rule updated" in stdout or "Rule inserted" in stdout or "Skipping adding existing rule" in stdout:
|
||||
return self._result(True, "设置output规则成功")
|
||||
if "setlocale" in stderr:
|
||||
return self._result(True, "设置规则成功")
|
||||
return self._result(False, "outpu规则设置失败:{}".format(stderr))
|
||||
return self._result(True, "设置output规则成功")
|
||||
except Exception as e:
|
||||
if "setlocale" in str(e):
|
||||
return self._result(True, "设置output规则成功")
|
||||
return self._result(False, "outpu规则设置失败:{}".format(e))
|
||||
|
||||
# 2024/3/19 下午 5:01 解析防火墙规则信息,返回字典格式数据,用于添加或删除防火墙规则
|
||||
def _load_info(self, line, fire_type):
|
||||
'''
|
||||
@name 解析防火墙规则信息,返回字典格式数据,用于添加或删除防火墙规则
|
||||
@author wzz <2024/3/19 上午 10:38>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
fields = line.split()
|
||||
item_info = {}
|
||||
if "LIMIT" in line or "ALLOW FWD" in line:
|
||||
return item_info
|
||||
if len(fields) < 4:
|
||||
return item_info
|
||||
if fields[0] == "Anywhere" and fire_type != "port":
|
||||
item_info["Strategy"] = "drop"
|
||||
|
||||
if fields[1] != "(v6)":
|
||||
if fields[1] == "ALLOW":
|
||||
item_info["Strategy"] = "accept"
|
||||
if fields[2] == "IN":
|
||||
item_info["Chain"] = "INPUT"
|
||||
elif fields[2] == "OUT":
|
||||
item_info["Chain"] = "OUTPUT"
|
||||
item_info["Address"] = fields[3]
|
||||
item_info["Family"] = "ipv4"
|
||||
else:
|
||||
if fields[2] == "ALLOW":
|
||||
item_info["Strategy"] = "accept"
|
||||
if fields[3] == "IN":
|
||||
item_info["Chain"] = "INPUT"
|
||||
elif fields[3] == "OUT":
|
||||
item_info["Chain"] = "OUTPUT"
|
||||
item_info["Address"] = fields[4]
|
||||
item_info["Family"] = "ipv6"
|
||||
|
||||
return item_info
|
||||
|
||||
if "/" in fields[0]:
|
||||
item_info["Port"] = fields[0].split("/")[0]
|
||||
item_info["Protocol"] = fields[0].split("/")[1]
|
||||
else:
|
||||
item_info["Port"] = fields[0]
|
||||
item_info["Protocol"] = "tcp/udp"
|
||||
|
||||
if "v6" in fields[1]:
|
||||
item_info["Family"] = "ipv6"
|
||||
if fields[2] == "ALLOW":
|
||||
item_info["Strategy"] = "accept"
|
||||
else:
|
||||
item_info["Strategy"] = "drop"
|
||||
|
||||
if fields[3] == "IN":
|
||||
item_info["Chain"] = "INPUT"
|
||||
elif fields[3] == "OUT":
|
||||
item_info["Chain"] = "OUTPUT"
|
||||
item_info["Address"] = fields[4]
|
||||
|
||||
else:
|
||||
item_info["Family"] = "ipv4" if ":" not in fields[3] else "ipv6"
|
||||
|
||||
if fields[1] == "ALLOW":
|
||||
item_info["Strategy"] = "accept"
|
||||
else:
|
||||
item_info["Strategy"] = "drop"
|
||||
|
||||
if fields[2] == "IN":
|
||||
item_info["Chain"] = "INPUT"
|
||||
elif fields[2] == "OUT":
|
||||
item_info["Chain"] = "OUTPUT"
|
||||
item_info["Address"] = fields[3]
|
||||
|
||||
return item_info
|
||||
|
||||
# 2024/3/25 下午 2:29 设置端口转发
|
||||
def port_forward(self, info, operation):
|
||||
'''
|
||||
@name 设置端口转发
|
||||
@param port: 端口号
|
||||
@param ip: ip地址
|
||||
@param operation: 操作
|
||||
@return None
|
||||
'''
|
||||
from firewallModel.app.iptables import Iptables
|
||||
self.firewall = Iptables()
|
||||
return self.firewall.port_forward(info, operation)
|
||||
|
||||
# 2024/3/25 下午 2:34 获取所有端口转发列表
|
||||
def list_port_forward(self):
|
||||
'''
|
||||
@name 获取所有端口转发列表
|
||||
@return None
|
||||
'''
|
||||
from firewallModel.app.iptables import Iptables
|
||||
self.firewall = Iptables()
|
||||
return self.firewall.get_nat_prerouting_rules()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = sys.argv
|
||||
firewall = Ufw()
|
||||
ufw_status = firewall.status()
|
||||
if len(args) < 2:
|
||||
print("Welcome to the UFW (Uncomplicated Firewall) command-line interface!")
|
||||
print("Firewall status is :", ufw_status)
|
||||
print("Firewall version: ", firewall.version())
|
||||
if ufw_status == "not running":
|
||||
print("ufw未启动,请启动ufw后再执行命令!")
|
||||
print("启动命令: start")
|
||||
print()
|
||||
sys.exit(1)
|
||||
print()
|
||||
print("Available options:")
|
||||
print("1. Check Firewall Status: status")
|
||||
print("2. Check Firewall Version: version")
|
||||
print("3. Start Firewall: start")
|
||||
print("4. Stop Firewall: stop")
|
||||
print("5. Restart Firewall: restart")
|
||||
print("6. Reload Firewall: reload")
|
||||
print("7. List All Ports: list_port")
|
||||
print("8. List All IP Addresses: list_address")
|
||||
print("9. Add Port: add_port <port> <protocol>")
|
||||
print("10. Remove Port: remove_port <port> <protocol>")
|
||||
print("11. Add Port Rule: add_port_rule <address> <port> <protocol> <strategy> <operation>")
|
||||
print("12. Remove Port Rule: remove_port_rule <address> <port> <protocol> <strategy> <operation>")
|
||||
print("13. Add IP Rule: add_ip_rule <address> <strategy> <operation>")
|
||||
print("14. Remove IP Rule: remove_ip_rule <address> <strategy> <operation>")
|
||||
print()
|
||||
sys.exit(1)
|
||||
if args[1] == "status":
|
||||
print(firewall.status())
|
||||
elif args[1] == "version":
|
||||
print(firewall.version())
|
||||
elif args[1] == "start":
|
||||
error = firewall.start()
|
||||
if error:
|
||||
print(f"Error: {error}")
|
||||
else:
|
||||
print("Firewall started successfully.")
|
||||
elif args[1] == "stop":
|
||||
error = firewall.stop()
|
||||
if error:
|
||||
print(f"Error: {error}")
|
||||
else:
|
||||
print("Firewall stopped successfully.")
|
||||
elif args[1] == "restart":
|
||||
error = firewall.restart()
|
||||
if error:
|
||||
print(f"Error: {error}")
|
||||
else:
|
||||
print("Firewall restarted successfully.")
|
||||
elif args[1] == "reload":
|
||||
error = firewall.reload()
|
||||
if error:
|
||||
print(f"Error: {error}")
|
||||
else:
|
||||
print("Firewall reloaded successfully.")
|
||||
elif args[1] == "list_input_port":
|
||||
ports = firewall.list_input_port()
|
||||
for p in ports:
|
||||
print(p)
|
||||
elif args[1] == "list_output_port":
|
||||
ports = firewall.list_output_port()
|
||||
for p in ports:
|
||||
print(p)
|
||||
elif args[1] == "list_input_address":
|
||||
addresses = firewall.list_input_address()
|
||||
for a in addresses:
|
||||
print(a)
|
||||
elif args[1] == "list_output_address":
|
||||
addresses = firewall.list_output_address()
|
||||
for a in addresses:
|
||||
print(a)
|
||||
elif args[1] == "add_port":
|
||||
port = args[2]
|
||||
protocol = args[3]
|
||||
error = firewall.input_port(f"{port}/{protocol}", "allow")
|
||||
if error:
|
||||
print(f"Error: {error}")
|
||||
else:
|
||||
print(f"Port {port}/{protocol} added successfully.")
|
||||
elif args[1] == "remove_port":
|
||||
port = args[2]
|
||||
protocol = args[3]
|
||||
error = firewall.input_port(f"{port}/{protocol}", "remove")
|
||||
if error:
|
||||
print(f"Error: {error}")
|
||||
else:
|
||||
print(f"Port {port}/{protocol} removed successfully.")
|
||||
elif args[1] == "add_port_rule":
|
||||
address = args[2]
|
||||
port = args[3]
|
||||
protocol = args[4]
|
||||
strategy = args[5]
|
||||
operation = args[6]
|
||||
error = firewall.rich_rules(
|
||||
{"Address": address, "Port": port, "Protocol": protocol, "Strategy": strategy}, operation)
|
||||
if error:
|
||||
print(f"Error: {error}")
|
||||
else:
|
||||
print("Rich rule added successfully.")
|
||||
elif args[1] == "remove_port_rule":
|
||||
address = args[2]
|
||||
port = args[3]
|
||||
protocol = args[4]
|
||||
strategy = args[5]
|
||||
operation = args[6]
|
||||
error = firewall.rich_rules(
|
||||
{"Address": address, "Port": port, "Protocol": protocol, "Strategy": strategy}, operation)
|
||||
if error:
|
||||
print(f"Error: {error}")
|
||||
else:
|
||||
print("Rich rule removed successfully.")
|
||||
elif args[1] == "add_ip_rule":
|
||||
address = args[2]
|
||||
strategy = args[3]
|
||||
operation = args[4]
|
||||
error = firewall.rich_rules(
|
||||
{"Address": address, "Strategy": strategy}, operation)
|
||||
if error:
|
||||
print(f"Error: {error}")
|
||||
else:
|
||||
print("Rich rule added successfully.")
|
||||
elif args[1] == "remove_ip_rule":
|
||||
address = args[2]
|
||||
strategy = args[3]
|
||||
operation = args[4]
|
||||
error = firewall.rich_rules(
|
||||
{"Address": address, "Strategy": strategy}, operation)
|
||||
if error:
|
||||
print(f"Error: {error}")
|
||||
else:
|
||||
print("Rich rule removed successfully.")
|
||||
elif args[1] == "output_port":
|
||||
port = args[2]
|
||||
operation = args[3]
|
||||
error = firewall.output_port(port, operation)
|
||||
if error:
|
||||
print(f"Error: {error}")
|
||||
else:
|
||||
print(f"Output port {port} {operation} successfully.")
|
||||
elif args[1] == "output_rich_rules":
|
||||
address = args[2]
|
||||
port = args[3]
|
||||
protocol = args[4]
|
||||
strategy = args[5]
|
||||
operation = args[6]
|
||||
error = firewall.output_rich_rules(
|
||||
{"Address": address, "Port": port, "Protocol": protocol, "Strategy": strategy}, operation)
|
||||
if error:
|
||||
print(f"Error: {error}")
|
||||
else:
|
||||
print("Output rich rule added successfully.")
|
||||
else:
|
||||
print("Invalid args")
|
||||
sys.exit(1)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,220 @@
|
||||
# coding: utf-8
|
||||
# -------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2014-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: wzz <wzz@bt.cn>
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# ------------------------------
|
||||
# 系统防火墙模型 - 基类
|
||||
# ------------------------------
|
||||
|
||||
import os
|
||||
import re
|
||||
from typing import Dict, Union, Any
|
||||
from xml.etree.ElementTree import ElementTree
|
||||
|
||||
import public
|
||||
|
||||
|
||||
class Base(object):
|
||||
|
||||
def __init__(self):
|
||||
self.config_path = "{}/class/firewallModel/config".format(public.get_panel_path())
|
||||
self._isUfw = False
|
||||
self._isFirewalld = False
|
||||
self._isIptables = False
|
||||
if os.path.exists('/usr/sbin/ufw'):
|
||||
self._isUfw = True
|
||||
from firewallModel.app.ufw import Ufw
|
||||
self.firewall = Ufw()
|
||||
elif os.path.exists('/usr/sbin/firewalld'):
|
||||
self._isFirewalld = True
|
||||
from firewallModel.app.firewalld import Firewalld
|
||||
self.firewall = Firewalld()
|
||||
elif not self._isUfw and not self._isFirewalld:
|
||||
self._isIptables = True
|
||||
from firewallModel.app.iptables import Iptables
|
||||
self.firewall = Iptables()
|
||||
_months = {'Jan': '01', 'Feb': '02', 'Mar': '03', 'Apr': '04', 'May': '05', 'Jun': '06', 'Jul': '07',
|
||||
'Aug': '08', 'Sep': '09', 'Sept': '09', 'Oct': '10', 'Nov': '11', 'Dec': '12'}
|
||||
|
||||
# 2024/3/14 上午 11:27 获取防火墙运行状态
|
||||
def get_firewall_status(self) -> bool:
|
||||
'''
|
||||
@name 获取防火墙运行状态
|
||||
@author wzz <2024/3/14 上午 11:27>
|
||||
@param
|
||||
@return bool True/False
|
||||
'''
|
||||
if self._isUfw:
|
||||
res = public.ExecShell("systemctl is-active ufw")[0]
|
||||
if res == "active": return True
|
||||
res = public.ExecShell("systemctl list-units | grep ufw")[0]
|
||||
if res.find('active running') != -1: return True
|
||||
res = public.ExecShell('/lib/ufw/ufw-init status')[0]
|
||||
if res.find("Firewall is not running") != -1: return False
|
||||
res = public.ExecShell('ufw status verbose')[0]
|
||||
if res.find('inactive') != -1: return False
|
||||
return True
|
||||
if self._isFirewalld:
|
||||
res = public.ExecShell("ps -ef|grep firewalld|grep -v grep")[0]
|
||||
if res: return True
|
||||
res = public.ExecShell("systemctl is-active firewalld")[0]
|
||||
if res == "active": return True
|
||||
res = public.ExecShell("systemctl list-units | grep firewalld")[0]
|
||||
if res.find('active running') != -1: return True
|
||||
return False
|
||||
else:
|
||||
res = public.ExecShell("/etc/init.d/iptables status")[0]
|
||||
if res.find('not running') != -1: return False
|
||||
res = public.ExecShell("systemctl is-active iptables")[0]
|
||||
if res == "active": return True
|
||||
return True
|
||||
|
||||
# 2024/3/14 上午 11:30 设置禁ping
|
||||
def set_ping(self, get) -> dict:
|
||||
'''
|
||||
@name 设置禁ping
|
||||
@author wzz <2024/3/14 上午 11:31>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
get.status = get.get("status", "1")
|
||||
get.status = str(get.status) if str(get.status) in ['0', '1'] else '1'
|
||||
|
||||
filename = '/etc/sysctl.conf'
|
||||
conf = public.readFile(filename)
|
||||
if conf.find('net.ipv4.icmp_echo') != -1:
|
||||
rep = r"net\.ipv4\.icmp_echo.*"
|
||||
conf = re.sub(rep, 'net.ipv4.icmp_echo_ignore_all=' + get.status + "\n", conf)
|
||||
else:
|
||||
conf += "\nnet.ipv4.icmp_echo_ignore_all=" + get.status + "\n"
|
||||
|
||||
if public.writeFile(filename, conf):
|
||||
public.ExecShell('sysctl -p')
|
||||
return public.returnMsg(True, 'SUCCESS')
|
||||
else:
|
||||
return public.returnMsg(
|
||||
False,
|
||||
'<a style="color:red;">错误:设置失败,sysctl.conf不可写!</a><br>'
|
||||
'1、如果安装了[宝塔系统加固],请先关闭<br>'
|
||||
'2、如果安装了云锁,请关闭[系统加固]功能<br>'
|
||||
'3、如果安装了安全狗,请关闭[系统防护]功能<br>'
|
||||
'4、如果使用了其它安全软件,请先卸载<br>'
|
||||
)
|
||||
|
||||
# 2024/3/14 上午 11:37 获取网站日志目录的大小
|
||||
def get_www_logs_size(self, get) -> Dict[str, Union[str, Any]]:
|
||||
'''
|
||||
@name 获取网站日志目录的大小
|
||||
@author wzz <2024/3/14 上午 11:37>
|
||||
@param
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
path_size = public.get_size_total("/www/wwwlogs")
|
||||
if not path_size:
|
||||
return {"log_path": "/www/wwwlogs", "size": "0B"}
|
||||
|
||||
return {"log_path": "/www/wwwlogs", "size": public.to_size(path_size["/www/wwwlogs"])}
|
||||
|
||||
# 2024/3/25 上午 10:50 获取防火墙类型,firewall或ufw
|
||||
def _get_firewall_type(self) -> str:
|
||||
'''
|
||||
@name 获取防火墙类型,firewall或ufw
|
||||
@return str firewall/ufw
|
||||
'''
|
||||
import os
|
||||
if os.path.exists('/usr/sbin/ufw'):
|
||||
return 'ufw'
|
||||
if os.path.exists('/usr/sbin/firewalld'):
|
||||
return 'firewall'
|
||||
return 'iptables'
|
||||
|
||||
# 2024/3/26 下午 5:01 获取指定域名的A记录
|
||||
def get_a_ip(self, domain: str) -> str:
|
||||
'''
|
||||
@name 获取指定域名的A记录
|
||||
@param domain: 域名
|
||||
@return str
|
||||
'''
|
||||
try:
|
||||
import socket
|
||||
return socket.gethostbyname(domain)
|
||||
except Exception as e:
|
||||
return ""
|
||||
|
||||
# 2024/3/26 下午 5:40 检查是否已添加计划任务,如果没有则添加
|
||||
def check_resolve_crontab(self):
|
||||
'''
|
||||
@name 检查是否已添加计划任务
|
||||
@author wzz <2024/3/26 下午 5:41>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
python_path = "{}/pyenv/bin/python".format(public.get_panel_path())
|
||||
|
||||
if not public.M('crontab').where('name=?', ('[勿删]系统防火墙域名解析检测任务',)).count():
|
||||
cmd = '{} {}'.format(python_path, '/www/server/panel/script/firewall_domain.py')
|
||||
args = {"name": "[勿删]系统防火墙域名解析检测任务", "type": 'minute-n', "where1": '5', "hour": '',
|
||||
"minute": '', "sName": "",
|
||||
"sType": 'toShell', "notice": '', "notice_channel": '', "save": '', "save_local": '1',
|
||||
"backupTo": '', "sBody": cmd,
|
||||
"urladdress": ''}
|
||||
import crontab
|
||||
res = crontab.crontab().AddCrontab(args)
|
||||
if res and "id" in res.keys():
|
||||
return True
|
||||
return False
|
||||
return True
|
||||
|
||||
# 2024/3/26 下午 11:37 当没有域名解析时,删除域名解析的计划任务
|
||||
def remove_resolve_crontab(self):
|
||||
'''
|
||||
@name 当没有域名解析时,删除域名解析的计划任务
|
||||
@author wzz <2024/3/26 下午 11:37>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
|
||||
if not public.M('firewall_domain').count():
|
||||
pdata = public.M('crontab').where('name=?', '[勿删]系统防火墙域名解析检测任务').select()
|
||||
if pdata:
|
||||
import crontab
|
||||
for i in pdata:
|
||||
args = {"id": i['id']}
|
||||
crontab.crontab().DelCrontab(args)
|
||||
|
||||
# 2024/3/26 下午 6:22 端口扫描
|
||||
def CheckPort(self, port, protocol):
|
||||
'''
|
||||
@name 端口扫描
|
||||
@author wzz <2024/3/26 下午 6:22>
|
||||
@param "data":{"参数名":""} <数据类型> 参数描述
|
||||
@return dict{"status":True/False,"msg":"提示信息"}
|
||||
'''
|
||||
import socket
|
||||
localIP = '127.0.0.1'
|
||||
temp = {}
|
||||
temp['port'] = port
|
||||
temp['local'] = True
|
||||
|
||||
try:
|
||||
if 'tcp' in protocol.lower():
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.settimeout(0.01)
|
||||
s.connect((localIP, port))
|
||||
s.close()
|
||||
if 'udp' in protocol.lower():
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.settimeout(0.01)
|
||||
s.sendto(b'', (localIP, port))
|
||||
s.close()
|
||||
except:
|
||||
temp['local'] = False
|
||||
|
||||
result = 0
|
||||
if temp['local']: result += 2
|
||||
return result
|
||||
+10
-10
@@ -1,8 +1,8 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板 x5
|
||||
# | aaPanel x5
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2018 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2018 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 1249648969@qq.com
|
||||
# +-------------------------------------------------------------------
|
||||
@@ -138,7 +138,7 @@ class firewalls:
|
||||
def AddDropAddress(self,get):
|
||||
import time
|
||||
import re
|
||||
rep = "^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(\/\d{1,2})?$"
|
||||
rep = r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(\/\d{1,2})?$"
|
||||
if not re.search(rep,get.port): return public.return_msg_gettext(False,'IP address youve entered is illegal!');
|
||||
address = get.port
|
||||
if public.M('firewall').where("port=?",(address,)).count() > 0: return public.return_msg_gettext(False,'The IP exists in block list, no need to repeat processing!')
|
||||
@@ -189,7 +189,7 @@ class firewalls:
|
||||
def AddAcceptPort(self,get):
|
||||
flag=False
|
||||
import re
|
||||
rep = "^\d{1,5}(:\d{1,5})?$"
|
||||
rep = r"^\d{1,5}(:\d{1,5})?$"
|
||||
if not re.search(rep,get.port): return public.return_msg_gettext(False,'Port range is incorrect!');
|
||||
import time
|
||||
port = get.port
|
||||
@@ -297,7 +297,7 @@ class firewalls:
|
||||
filename = '/etc/sysctl.conf'
|
||||
conf = public.readFile(filename)
|
||||
if conf.find('net.ipv4.icmp_echo') != -1:
|
||||
rep = u"net\.ipv4\.icmp_echo.*"
|
||||
rep = r"net\.ipv4\.icmp_echo.*"
|
||||
conf = re.sub(rep,'net.ipv4.icmp_echo_ignore_all='+get.status,conf)
|
||||
else:
|
||||
conf += "\nnet.ipv4.icmp_echo_ignore_all="+get.status
|
||||
@@ -320,7 +320,7 @@ class firewalls:
|
||||
file = '/etc/ssh/sshd_config'
|
||||
conf = public.readFile(file)
|
||||
|
||||
rep = "#*Port\s+([0-9]+)\s*\n"
|
||||
rep = "#*Port\\s+([0-9]+)\\s*\n"
|
||||
conf = re.sub(rep, "Port "+port+"\n", conf)
|
||||
public.writeFile(file,conf)
|
||||
|
||||
@@ -345,7 +345,7 @@ class firewalls:
|
||||
def GetSshInfo(self,get):
|
||||
file = '/etc/ssh/sshd_config'
|
||||
conf = public.readFile(file)
|
||||
rep = "#*Port\s+([0-9]+)\s*\n"
|
||||
rep = "#*Port\\s+([0-9]+)\\s*\n"
|
||||
port = re.search(rep,conf).groups(0)[0]
|
||||
import system
|
||||
panelsys = system.system();
|
||||
@@ -367,7 +367,7 @@ class firewalls:
|
||||
try:
|
||||
file = '/etc/sysctl.conf'
|
||||
conf = public.readFile(file)
|
||||
rep = "#*net\.ipv4\.icmp_echo_ignore_all\s*=\s*([0-9]+)"
|
||||
rep = r"#*net\.ipv4\.icmp_echo_ignore_all\s*=\s*([0-9]+)"
|
||||
tmp = re.search(rep,conf).groups(0)[0]
|
||||
if tmp == '1': isPing = False
|
||||
except:
|
||||
@@ -397,11 +397,11 @@ class firewalls:
|
||||
flag = False
|
||||
import re
|
||||
# 判断端口是否正确
|
||||
rep = "^\d{1,5}(:\d{1,5})?$"
|
||||
rep = r"^\d{1,5}(:\d{1,5})?$"
|
||||
if not re.search(rep, get.port): return public.return_msg_gettext(False, 'Port range is incorrect! should be between 100-65535');
|
||||
|
||||
# 判断IP是否正确
|
||||
rep2 = "^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(\/\d{1,2})?$"
|
||||
rep2 = r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(\/\d{1,2})?$"
|
||||
if not re.search(rep2, get.address): return public.return_msg_gettext(False, 'IP address is illegal!');
|
||||
import time
|
||||
ports = get.port
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
#!/usr/bin/env python
|
||||
# coding:utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2017 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2017 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 1249648969@qq.com,
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
+9
-10
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板 x3
|
||||
# | aaPanel x3
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2016 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2016 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# | Author: hwliang <hwl@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
import sys,os,public,re,firewalld,time
|
||||
|
||||
@@ -310,15 +310,13 @@ class firewalls:
|
||||
|
||||
#改远程端口
|
||||
def SetSshPort(self,get):
|
||||
|
||||
port = get.port
|
||||
if not port:
|
||||
return public.return_msg_gettext(False, 'Port range must be between 22 and 65535!')
|
||||
try:
|
||||
if int(port) < 22 or int(port) > 65535: return public.return_msg_gettext(False,'Port range must be between 22 and 65535!')
|
||||
except:
|
||||
return public.return_msg_gettext(False, 'Port range must be between 22 and 65535!')
|
||||
|
||||
ports = ['21','25','80','443','8080','888','8888','7800']
|
||||
if port in ports: return public.return_msg_gettext(False,'Do NOT use common default port!')
|
||||
if port in ports:
|
||||
return public.return_msg_gettext(False,'Do NOT use common default port!')
|
||||
# return public.return_message(-1, 0, 'Do NOT use common default port!')
|
||||
file = '/etc/ssh/sshd_config'
|
||||
conf = public.readFile(file)
|
||||
|
||||
@@ -343,6 +341,7 @@ class firewalls:
|
||||
public.M('firewall').add('port,ps,addtime',(port,'SSH remote service',time.strftime('%Y-%m-%d %X',time.localtime())))
|
||||
public.WriteLog("TYPE_FIREWALL", "FIREWALL_SSH_PORT",(port,))
|
||||
return public.return_msg_gettext(True,'Setup successfully!')
|
||||
# return public.return_message(0, 0, 'Setup successfully!')
|
||||
|
||||
#取SSH信息
|
||||
def GetSshInfo(self,get):
|
||||
|
||||
+7
-7
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# + -------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# + -------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2016 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2016 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# + -------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# | Author: hwliang <hwl@aapanel.com>
|
||||
# + -------------------------------------------------------------------
|
||||
import public,db,re,os,firewalls
|
||||
try:
|
||||
@@ -24,13 +24,13 @@ class ftp:
|
||||
import files,time
|
||||
fileObj=files.files()
|
||||
if get['ftp_username'].strip().find(' ') != -1: return public.returnMsg(False,'Username cannot contain spaces')
|
||||
if re.search("\W+",get['ftp_username']): return {'status':False,'code':501,'msg':public.get_msg_gettext('Username is illegal, special characters are NOT allowed!')}
|
||||
if re.search(r"\W+",get['ftp_username']): return {'status':False,'code':501,'msg':public.get_msg_gettext('Username is illegal, special characters are NOT allowed!')}
|
||||
if len(get['ftp_username']) < 3: return {'status':False,'code':501,'msg':public.get_msg_gettext('Username is illegal, cannot be less than 3 characters!')}
|
||||
if not fileObj.CheckDir(get['path']): return {'status':False,'code':501,'msg':public.get_msg_gettext('System critical directory cannot be used as FTP directory!')}
|
||||
if public.M('ftps').where('name=?',(get.ftp_username.strip(),)).count(): return public.return_msg_gettext(False,'User [{}] exists!',(get.ftp_username,))
|
||||
username = get['ftp_username'].strip()
|
||||
if re.search("[\/\\\:\*\?\"\'\<\>\|]+",username):
|
||||
return public.return_msg_gettext(False,"Name cannot contain /\:*?\"<>| symbol")
|
||||
if re.search("[\\/\\\\:\\*\\?\"\'\\<\\>\\|]+",username):
|
||||
return public.return_msg_gettext(False,"Name cannot contain /\\:*?\"<>| symbol")
|
||||
password = get['ftp_password'].strip()
|
||||
if len(password) < 6: return public.return_msg_gettext(False, 'Password must be at least [{}] characters',("6",))
|
||||
get.path = get['path'].replace(' ','')
|
||||
@@ -122,7 +122,7 @@ class ftp:
|
||||
if int(port) < 1 or int(port) > 65535: return public.return_msg_gettext(False,'Port range is incorrect!')
|
||||
file = '/www/server/pure-ftpd/etc/pure-ftpd.conf'
|
||||
conf = public.readFile(file)
|
||||
rep = u"\n#?\s*Bind\s+[0-9]+\.[0-9]+\.[0-9]+\.+[0-9]+,([0-9]+)"
|
||||
rep = u"\n#?\\s*Bind\\s+[0-9]+\\.[0-9]+\\.[0-9]+\\.+[0-9]+,([0-9]+)"
|
||||
#preg_match(rep,conf,tmp)
|
||||
conf = re.sub(rep,"\nBind 0.0.0.0," + port,conf)
|
||||
public.writeFile(file,conf)
|
||||
|
||||
+29
-110
@@ -1,8 +1,8 @@
|
||||
#coding: utf-8
|
||||
# + -------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# + -------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2016 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2016 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# + -------------------------------------------------------------------
|
||||
# | Author: hezhihong <272267659@@qq.cn>
|
||||
# + -------------------------------------------------------------------
|
||||
@@ -30,6 +30,8 @@ month_list = {
|
||||
|
||||
|
||||
class ftplog:
|
||||
__AUTH_MSG =public.to_string ([84 ,104 ,105 ,115 ,32 ,102 ,101 ,97 ,116 ,117 ,114 ,101 ,32 ,105 ,115 ,32 ,101 ,120 ,99 ,108 ,117 ,115 ,105 ,118 ,101 ,32 ,116 ,111 ,32 ,116 ,104 ,101 ,32 ,112 ,114 ,111 ,32 ,101 ,100 ,105 ,116 ,105 ,111 ,110 ,44 ,32 ,112 ,108 ,101 ,97 ,115 ,101 ,32 ,97 ,99 ,116 ,105 ,118 ,97 ,116 ,101 ,32 ,105 ,116 ,32 ,102 ,105 ,114 ,115 ,116 ])
|
||||
|
||||
def __init__(self):
|
||||
self.__messages_file = "/var/log/"
|
||||
self.__ftp_backup_path = public.get_backup_path() + '/pure-ftpd/'
|
||||
@@ -75,128 +77,44 @@ class ftplog:
|
||||
reverse=False)
|
||||
return file_name_list
|
||||
|
||||
def __check_auth(self):
|
||||
from plugin_auth_v2 import Plugin as Plugin
|
||||
plugin_obj = Plugin(False)
|
||||
plugin_list = plugin_obj.get_plugin_list()
|
||||
import PluginLoader
|
||||
self.__IS_PRO_MEMBER = PluginLoader.get_auth_state() > 0
|
||||
return int(plugin_list["pro"]) > time.time() or self.__IS_PRO_MEMBER
|
||||
|
||||
def set_ftp_log(self, get):
|
||||
"""
|
||||
@name 开启、关闭、获取日志状态
|
||||
@name 开启、关闭、获取日志状态
|
||||
@author hezhihong
|
||||
@param get.exec_name 执行的动作
|
||||
"""
|
||||
if not self.__check_auth():
|
||||
return public.returnMsg(False, self.__AUTH_MSG)
|
||||
if not hasattr(get, 'exec_name'):
|
||||
return public.returnMsg(False, 'The parameter is incorrect!')
|
||||
conf_path = '/etc/rsyslog.conf'
|
||||
conf = public.readFile(conf_path)
|
||||
import re
|
||||
search_str = r"ftp\.\*.*\t*.*\t*.*-/var/log/pure-ftpd.log"
|
||||
search_str_two = "ftp.none"
|
||||
rep_str = '\nftp.*\t\t-/var/log/pure-ftpd.log\n'
|
||||
result = re.search(search_str, conf)
|
||||
ftp_file='/etc/rsyslog.d/pure-ftpd.conf'
|
||||
write_string = '\nftp.*\t\t-/var/log/pure-ftpd.log\n'
|
||||
#获取日志状态
|
||||
if get.exec_name == 'getlog':
|
||||
if result:
|
||||
return_result = 'start'
|
||||
if os.path.exists(ftp_file):
|
||||
return public.returnMsg(True, 'start')
|
||||
else:
|
||||
return_result = 'stop'
|
||||
return public.returnMsg(True, return_result)
|
||||
#开启日志审计
|
||||
return public.returnMsg(True, 'stop')
|
||||
|
||||
# 开启日志审计
|
||||
elif get.exec_name == 'start':
|
||||
# 兼容之前开启,会将配置文件搞坏
|
||||
if conf.count('ftp.nonenftp') > 5:
|
||||
conf = '''
|
||||
# /etc/rsyslog.conf configuration file for rsyslog
|
||||
#
|
||||
# For more information install rsyslog-doc and see
|
||||
# /usr/share/doc/rsyslog-doc/html/configuration/index.html
|
||||
#
|
||||
# Default logging rules can be found in /etc/rsyslog.d/50-default.conf
|
||||
|
||||
|
||||
#################
|
||||
#### MODULES ####
|
||||
#################
|
||||
|
||||
module(load="imuxsock") # provides support for local system logging
|
||||
#module(load="immark") # provides --MARK-- message capability
|
||||
|
||||
# provides UDP syslog reception
|
||||
#module(load="imudp")
|
||||
#input(type="imudp" port="514")
|
||||
|
||||
# provides TCP syslog reception
|
||||
#module(load="imtcp")
|
||||
#input(type="imtcp" port="514")
|
||||
|
||||
# provides kernel logging support and enable non-kernel klog messages
|
||||
module(load="imklog" permitnonkernelfacility="on")
|
||||
|
||||
###########################
|
||||
#### GLOBAL DIRECTIVES ####
|
||||
###########################
|
||||
|
||||
#
|
||||
# Use traditional timestamp format.
|
||||
# To enable high precision timestamps, comment out the following line.
|
||||
#
|
||||
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
|
||||
|
||||
# Filter duplicated messages
|
||||
$RepeatedMsgReduction on
|
||||
|
||||
#
|
||||
# Set the default permissions for all log files.
|
||||
#
|
||||
$FileOwner syslog
|
||||
$FileGroup adm
|
||||
$FileCreateMode 0640
|
||||
$DirCreateMode 0755
|
||||
$Umask 0022
|
||||
$PrivDropToUser syslog
|
||||
$PrivDropToGroup syslog
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Where to place spool and state files
|
||||
#
|
||||
$WorkDirectory /var/spool/rsyslog
|
||||
|
||||
#
|
||||
# Include all config files in /etc/rsyslog.d/
|
||||
#
|
||||
$IncludeConfig /etc/rsyslog.d/*.conf
|
||||
|
||||
|
||||
|
||||
'''
|
||||
public.writeFile(conf_path, conf)
|
||||
return self.set_ftp_log(get)
|
||||
if '*.info;mail.none;authpriv.none;' not in conf:
|
||||
conf += '\n*.info;mail.none;authpriv.none;cron.none /var/log/messages\n'
|
||||
if result:
|
||||
conf = conf.replace(search_str, rep_str)
|
||||
else:
|
||||
conf += rep_str
|
||||
#禁止ftp日志写入/var/log/messages
|
||||
|
||||
d_conf = conf[conf.rfind('info;'):]
|
||||
d_conf = d_conf[:d_conf.find('/')]
|
||||
s_conf = d_conf.replace(',', ';')
|
||||
if s_conf.find(search_str_two) == -1:
|
||||
str_index = s_conf.rfind(';')
|
||||
s_conf = s_conf[:str_index +
|
||||
1] + search_str_two + s_conf[str_index + 1:]
|
||||
conf = conf.replace(d_conf, s_conf)
|
||||
public.writeFile(ftp_file, write_string)
|
||||
self.add_crontab()
|
||||
#关闭日志审计
|
||||
# 关闭日志审计
|
||||
elif get.exec_name == 'stop':
|
||||
if result:
|
||||
conf = re.sub(search_str, '', conf)
|
||||
#取消禁止ftp日志写入/var/log/messages
|
||||
if conf.find(search_str_two) != -1:
|
||||
conf = conf.replace(search_str_two, '')
|
||||
for i in [';;', ',,', ';,', ',;']:
|
||||
if conf.find(i) != -1: conf = conf.replace(i, '')
|
||||
if os.path.exists(ftp_file):
|
||||
os.remove(ftp_file)
|
||||
if os.path.exists(ftp_file):
|
||||
return public.returnMsg(False, 'failed to close the log')
|
||||
self.del_crontab()
|
||||
public.writeFile(conf_path, conf)
|
||||
public.ExecShell('systemctl restart rsyslog')
|
||||
return public.returnMsg(True, 'successfully set')
|
||||
|
||||
@@ -404,6 +322,7 @@ $IncludeConfig /etc/rsyslog.d/*.conf
|
||||
if search_str not in line: continue
|
||||
|
||||
tmp_v = line.split(search_str)
|
||||
if len(tmp_v[0].strip().split())<3:continue
|
||||
hostname = tmp_v[0].strip().split()[3].strip()
|
||||
action_time = tmp_v[0].replace(hostname, '').strip()
|
||||
action_info['time'] = self.get_format_time(action_time)
|
||||
|
||||
+16
-10
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# | Author: hwliang <hwl@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
# +-------------------------------------------------------------------
|
||||
@@ -440,13 +440,19 @@ exit($header."\r\n\r\n".json_encode($body));
|
||||
match = re.search("(.|\n)+\r\n\r\n",req)
|
||||
if not match: return req,{},0
|
||||
tmp = match.group().split("\r\n")
|
||||
i = 0
|
||||
if tmp[i].find('Continue') != -1: i+=1
|
||||
if not tmp[i]: i+=1
|
||||
try:
|
||||
status_code = int(tmp[i].split()[1])
|
||||
except:
|
||||
status_code = 0
|
||||
|
||||
status_code = 0
|
||||
|
||||
from public.regexplib import search_http_response_status_line
|
||||
|
||||
for i in range(len(tmp) - 1):
|
||||
m = search_http_response_status_line.search(tmp[i])
|
||||
if not m:
|
||||
continue
|
||||
|
||||
status_code = int(m.group(1))
|
||||
break
|
||||
|
||||
body = req.replace(match.group(),'')
|
||||
return body,tmp,status_code
|
||||
|
||||
|
||||
+52
-11
@@ -1,15 +1,16 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# | Author: hwliang <hwl@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
import time,public,db,os,sys,json,re,shutil
|
||||
os.chdir('/www/server/panel')
|
||||
|
||||
def control_init():
|
||||
update_py312()
|
||||
public.chdck_salt()
|
||||
clear_other_files()
|
||||
sql_pacth()
|
||||
@@ -21,6 +22,7 @@ def control_init():
|
||||
clean_max_log('/root/.pm2/pm2.log',1024*1024*20)
|
||||
remove_tty1()
|
||||
clean_hook_log()
|
||||
acme_crond_reinit()
|
||||
run_new()
|
||||
clean_max_log('/www/server/cron',1024*1024*5,20)
|
||||
clean_max_log("/www/server/panel/plugin/webhook/script",1024*1024*1)
|
||||
@@ -31,7 +33,7 @@ def control_init():
|
||||
set_pma_access()
|
||||
# public.set_open_basedir()
|
||||
clear_fastcgi_safe()
|
||||
update_py37()
|
||||
# update_py37()
|
||||
run_script()
|
||||
set_php_cli_env()
|
||||
check_enable_php()
|
||||
@@ -45,6 +47,7 @@ def control_init():
|
||||
#hide_docker()
|
||||
rep_pyenv_link()
|
||||
rm_apache_cgi_test()
|
||||
uninstall_pip_lxml()
|
||||
|
||||
def rm_apache_cgi_test():
|
||||
'''
|
||||
@@ -56,6 +59,32 @@ def rm_apache_cgi_test():
|
||||
if os.path.exists(test_cgi_file):
|
||||
os.remove(test_cgi_file)
|
||||
|
||||
def uninstall_pip_lxml():
|
||||
'''
|
||||
@name 如果lxml版本大于5.0.0卸载它,解决部分机器 import bs4 程序崩溃的问题
|
||||
'''
|
||||
try:
|
||||
import lxml
|
||||
if lxml.__version__ > '5.0.0':
|
||||
public.ExecShell('/www/server/panel/pyenv/bin/pip3 uninstall lxml -y')
|
||||
except:
|
||||
pass
|
||||
|
||||
def acme_crond_reinit():
|
||||
'''
|
||||
@name 修复acme定时任务
|
||||
@return void
|
||||
'''
|
||||
try:
|
||||
lets_config_file = os.path.join(public.get_panel_path(),'config/letsencrypt_v2.json')
|
||||
if not os.path.exists(lets_config_file): return
|
||||
|
||||
import acme_v2
|
||||
acme_v2.acme_v2().set_crond()
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def rep_pyenv_link():
|
||||
'''
|
||||
@name 修复pyenv环境软链
|
||||
@@ -156,7 +185,7 @@ def clear_other_files():
|
||||
shutil.copyfile(src_file,init_file)
|
||||
if os.path.getsize(init_file) < 10:
|
||||
public.ExecShell("chattr -i " + init_file)
|
||||
public.ExecShell("\cp -arf %s %s" % (src_file,init_file))
|
||||
public.ExecShell(r"\cp -arf %s %s" % (src_file,init_file))
|
||||
public.ExecShell("chmod +x %s" % init_file)
|
||||
except:pass
|
||||
public.writeFile('/var/bt_setupPath.conf','/www')
|
||||
@@ -484,7 +513,7 @@ def set_php_cli_env():
|
||||
if not os.path.exists(php_fpm) and os.path.exists(php_fpm_src): os.symlink(php_fpm_src,php_fpm)
|
||||
if not os.path.exists(php_pecl) and os.path.exists(php_pecl_src): os.symlink(php_pecl_src,php_pecl)
|
||||
if not os.path.exists(php_pear) and os.path.exists(php_pear_src): os.symlink(php_pear_src,php_pear)
|
||||
public.ExecShell("\cp -f {} {}".format(php_ini,php_cli_ini)) # 每次复制新的php.ini到php-cli.ini
|
||||
public.ExecShell(r"\cp -f {} {}".format(php_ini,php_cli_ini)) # 每次复制新的php.ini到php-cli.ini
|
||||
public.ExecShell('sed -i "/disable_functions/d" {}'.format(php_cli_ini)) # 清理禁用函数
|
||||
bashrc_body += "alias php{}='php{} -c {}'\n".format(php_version,php_version,php_cli_ini) # 设置别名
|
||||
else:
|
||||
@@ -507,7 +536,7 @@ def check_enable_php():
|
||||
for php_v in php_versions:
|
||||
ngx_php_conf = public.get_setup_path() + '/nginx/conf/enable-php-{}.conf'.format(php_v)
|
||||
if os.path.exists(ngx_php_conf): continue
|
||||
enable_conf = '''
|
||||
enable_conf = r'''
|
||||
location ~ [^/]\.php(/|$)
|
||||
{{
|
||||
try_files $uri =404;
|
||||
@@ -549,7 +578,7 @@ def run_script():
|
||||
|
||||
if not os.path.exists(script_info['script_file']) \
|
||||
or script_info['script_file'].find('/www/server/panel/plugin/') != 0 \
|
||||
or not re.match('^\w+$',script_info['script_file']):
|
||||
or not re.match(r'^\w+$',script_info['script_file']):
|
||||
os.remove(script_conf_file)
|
||||
if os.path.exists(exec_log_file): os.remove(exec_log_file)
|
||||
continue
|
||||
@@ -594,6 +623,7 @@ def files_set_mode():
|
||||
["/www/backup","","root",600,True],
|
||||
["/www/wwwlogs","","www",700,True],
|
||||
["/www/enterprise_backup","","root",600,True],
|
||||
["/www/server/panel/webserver", "", "root", 755, False],
|
||||
["/www/server/cron","","root",700,True],
|
||||
["/www/server/cron","/*.log","root",600,True],
|
||||
["/www/server/stop","","root",755,True],
|
||||
@@ -602,7 +632,7 @@ def files_set_mode():
|
||||
["/www/server/panel/class","","root",600,True],
|
||||
["/www/server/panel/data","","root",600,True],
|
||||
["/www/server/panel/plugin","","root",600,False],
|
||||
["/www/server/panel/BTPanel","","root",600,True],
|
||||
["/www/server/panel/BTPanel","","root",755,True],
|
||||
["/www/server/panel/vhost","","root",600,True],
|
||||
["/www/server/panel/rewrite","","root",600,True],
|
||||
["/www/server/panel/config","","root",600,True],
|
||||
@@ -617,6 +647,7 @@ def files_set_mode():
|
||||
["/www/server/panel/BT-Panel","","root",700,False],
|
||||
["/www/server/panel/BT-Task","","root",700,False],
|
||||
["/www/server/panel","/*.py","root",600,False],
|
||||
["/www/server/panel","","root",755,False],
|
||||
["/dev/shm/session.db","","root",600,False],
|
||||
["/dev/shm/session_py3","","root",600,True],
|
||||
["/dev/shm/session_py2","","root",600,True],
|
||||
@@ -706,7 +737,7 @@ def set_pma_access():
|
||||
|
||||
|
||||
|
||||
#尝试升级到独立环境
|
||||
#尝试升级到独立环境3.7
|
||||
def update_py37():
|
||||
pyenv='/www/server/panel/pyenv/bin/python3'
|
||||
pyenv_exists='/www/server/panel/data/pyenv_exists.pl'
|
||||
@@ -716,6 +747,16 @@ def update_py37():
|
||||
public.writeFile(pyenv_exists,'True')
|
||||
return True
|
||||
|
||||
#尝试升级到独立环境3.12
|
||||
def update_py312():
|
||||
pyenv='/www/server/panel/pyenv/bin/python3.12'
|
||||
if os.path.exists(pyenv): return False
|
||||
download_url = public.get_url()
|
||||
only_update_pyenv312 = '/tmp/only_update_pyenv312.pl'
|
||||
public.writeFile(only_update_pyenv312, 'True')
|
||||
public.ExecShell("nohup curl -k {}/install/update_7.x_en.sh|bash &>/tmp/panelUpdate.pl &".format(download_url))
|
||||
return True
|
||||
|
||||
def test_ping():
|
||||
_f = '/www/server/panel/data/ping_token.pl'
|
||||
if os.path.exists(_f): os.remove(_f)
|
||||
@@ -855,7 +896,7 @@ def disable_putenv(fun_name):
|
||||
if os.path.exists(is_set_disable): return True
|
||||
php_vs = public.get_php_versions()
|
||||
php_ini = "/www/server/php/{0}/etc/php.ini"
|
||||
rep = "disable_functions\s*=\s*.*"
|
||||
rep = r"disable_functions\s*=\s*.*"
|
||||
for pv in php_vs:
|
||||
php_ini_path = php_ini.format(pv)
|
||||
if not os.path.exists(php_ini_path): continue
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: lkq <lkq@bt.cn>
|
||||
# | Author: lkq <lkq@aapanel.com>
|
||||
# |
|
||||
# | 日志分析工具
|
||||
# +-------------------------------------------------------------------
|
||||
@@ -21,7 +21,7 @@ class log_analysis:
|
||||
def __init__(self):
|
||||
if not os.path.exists(self.path + '/log/'): os.makedirs(self.path + '/log/')
|
||||
if not os.path.exists(self.log_analysis_path):
|
||||
log_analysis_data = '''help(){
|
||||
log_analysis_data = r'''help(){
|
||||
echo "Usage: ./action.sh [options] [FILE] [OUTFILE] "
|
||||
echo "Options:"
|
||||
echo "xxx.sh san_log [FILE] Get the log list with the keywords xss|sql|mingsense information|php code execution in the successful request [OUTFILE] 11"
|
||||
@@ -231,7 +231,7 @@ echo "[*] shut down"
|
||||
result['is_status'] = True
|
||||
else:
|
||||
result['is_status'] = False
|
||||
if os.path.exists(speed+".time"):
|
||||
if os.path.exists(speed+".time") and os.path.getsize(speed+".time") > 0:
|
||||
time_data, start_time, status = public.ReadFile(self.path + '/log/' + log_path + ".time").split("[]")
|
||||
if status == '1' or start_time==1:
|
||||
result['time']=time_data
|
||||
@@ -257,4 +257,4 @@ echo "[*] shut down"
|
||||
type_list = ['xss', 'sql', 'san', 'php', 'ip', 'url']
|
||||
if get.type not in type_list: return public.ReturnMsg(False, 'Type mismatch')
|
||||
if not os.path.exists(speed + get.type + '.log'): return public.ReturnMsg(False, 'Record does not exist')
|
||||
return self.get_log_count(speed + get.type + '.log', is_body=True)
|
||||
return self.get_log_count(speed + get.type + '.log', is_body=True)
|
||||
|
||||
+452
-469
@@ -1,469 +1,452 @@
|
||||
#coding: utf-8
|
||||
# + -------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# + -------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2016 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# + -------------------------------------------------------------------
|
||||
# | Author: hezhihong <272267659@@qq.cn>
|
||||
# + -------------------------------------------------------------------
|
||||
import public, os, time
|
||||
from logsModel.base import logsBase
|
||||
|
||||
try:
|
||||
from BTPanel import session
|
||||
except:
|
||||
pass
|
||||
#英文转月份缩写
|
||||
month_list = {
|
||||
"Jan": "1",
|
||||
"Feb": "2",
|
||||
"Mar": "3",
|
||||
"Apr": "4",
|
||||
"May": "5",
|
||||
"Jun": "6",
|
||||
"Jul": "7",
|
||||
"Aug": "8",
|
||||
"Sept": "9",
|
||||
"Sep": "9",
|
||||
"Oct": "10",
|
||||
"Nov": "11",
|
||||
"Dec": "12"
|
||||
}
|
||||
|
||||
|
||||
class main(logsBase):
|
||||
def __init__(self):
|
||||
self.__messages_file = "/var/log/"
|
||||
self.__ftp_backup_path = public.get_backup_path() + '/pure-ftpd/'
|
||||
if not os.path.isdir(self.__ftp_backup_path):
|
||||
public.ExecShell('mkdir -p {}'.format(self.__ftp_backup_path))
|
||||
self.__script_py = public.get_panel_path() + '/script/ftplogs_cut.py'
|
||||
|
||||
def get_file_list(self, path, is_bakcup=False):
|
||||
"""
|
||||
@name 取所有messages日志文件
|
||||
@param path: 日志文件路径
|
||||
@return: 返回日志文件列表
|
||||
"""
|
||||
files = os.listdir(path)
|
||||
if is_bakcup:
|
||||
file_name_list = [{
|
||||
"file": "/var/log/pure-ftpd.log",
|
||||
"time": int(time.time())
|
||||
}]
|
||||
else:
|
||||
file_name_list = []
|
||||
for i in files:
|
||||
tmp_dict = {}
|
||||
if not i: continue
|
||||
file_path = path + i
|
||||
tmp_dict['file'] = file_path
|
||||
if is_bakcup:
|
||||
if os.path.isfile(file_path) and i.find('pure-ftpd.log') != -1:
|
||||
tmp_dict['time'] = int(
|
||||
public.to_date(
|
||||
times=os.path.basename(file_path).split('_')[0] +
|
||||
' 00:00:00'))
|
||||
file_name_list.append(tmp_dict)
|
||||
else:
|
||||
if os.path.isfile(file_path) and i.find('messages') != -1:
|
||||
tmp_dict['time'] = int(
|
||||
public.to_date(
|
||||
times=os.path.basename(file_path).split('-')[1] +
|
||||
' 00:00:00'))
|
||||
file_name_list.append(tmp_dict)
|
||||
file_name_list = sorted(file_name_list,
|
||||
key=lambda x: x['time'],
|
||||
reverse=False)
|
||||
return file_name_list
|
||||
|
||||
def set_ftp_log(self, get):
|
||||
"""
|
||||
@name 开启、关闭、获取日志状态
|
||||
@author hezhihong
|
||||
@param get.exec_name 执行的动作
|
||||
"""
|
||||
if not hasattr(get, 'exec_name'):
|
||||
return public.returnMsg(False, 'The parameter is incorrect!')
|
||||
conf_path = '/etc/rsyslog.conf'
|
||||
conf = public.readFile(conf_path)
|
||||
import re
|
||||
search_str = r"ftp\.\*.*\t*.*\t*.*-/var/log/pure-ftpd.log"
|
||||
search_str_two = "ftp.none"
|
||||
rep_str = '\nftp.*\t\t-/var/log/pure-ftpd.log\n'
|
||||
result = re.search(search_str, conf)
|
||||
#获取日志状态
|
||||
if get.exec_name == 'getlog':
|
||||
if result:
|
||||
return_result = 'start'
|
||||
else:
|
||||
return_result = 'stop'
|
||||
return public.returnMsg(True, return_result)
|
||||
#开启日志审计
|
||||
elif get.exec_name == 'start':
|
||||
if result:
|
||||
conf = conf.replace(search_str, rep_str)
|
||||
else:
|
||||
conf += rep_str
|
||||
#禁止ftp日志写入/var/log/messages
|
||||
|
||||
d_conf = conf[conf.rfind('info;'):]
|
||||
d_conf = d_conf[:d_conf.find('/')]
|
||||
s_conf = d_conf.replace(',', ';')
|
||||
if s_conf.find(search_str_two) == -1:
|
||||
str_index = s_conf.rfind(';')
|
||||
s_conf = s_conf[:str_index +
|
||||
1] + search_str_two + s_conf[str_index + 1:]
|
||||
conf = conf.replace(d_conf, s_conf)
|
||||
self.add_crontab()
|
||||
#关闭日志审计
|
||||
elif get.exec_name == 'stop':
|
||||
if result:
|
||||
conf = re.sub(search_str, '', conf)
|
||||
#取消禁止ftp日志写入/var/log/messages
|
||||
if conf.find(search_str_two) != -1:
|
||||
conf = conf.replace(search_str_two, '')
|
||||
for i in [';;', ',,', ';,', ',;']:
|
||||
if conf.find(i) != -1: conf = conf.replace(i, '')
|
||||
self.del_crontab()
|
||||
public.writeFile(conf_path, conf)
|
||||
public.ExecShell('systemctl restart rsyslog')
|
||||
return public.returnMsg(True, 'successfully set')
|
||||
|
||||
def get_format_time(self, englist_time):
|
||||
"""
|
||||
@name 时间英文转换
|
||||
"""
|
||||
chinanese_time = ''
|
||||
try:
|
||||
for i in month_list.keys():
|
||||
if i in englist_time:
|
||||
tmp_time = englist_time.replace(i, month_list[i])
|
||||
tmp_time = tmp_time.split()
|
||||
chinanese_time = '{}-{} {}'.format(tmp_time[0], tmp_time[1],
|
||||
tmp_time[2])
|
||||
break
|
||||
return chinanese_time
|
||||
except:
|
||||
return chinanese_time
|
||||
|
||||
def get_login_log(self, get):
|
||||
"""
|
||||
@name 取登录日志
|
||||
@author hezhihong
|
||||
@param get.user_name ftp用户名
|
||||
return
|
||||
"""
|
||||
|
||||
search_str = 'pure-ftpd:'
|
||||
search_str2 = 'pure-ftpd['
|
||||
if not hasattr(get, 'user_name'):
|
||||
return public.returnMsg(False, 'The parameter is incorrect!')
|
||||
args = public.dict_obj()
|
||||
args.exec_name = 'getlog'
|
||||
file_name = self.__ftp_backup_path
|
||||
is_backup = True
|
||||
if self.set_ftp_log(get) == 'stop':
|
||||
file_name = self.__messages_file
|
||||
is_backup = False
|
||||
file_list = self.get_file_list(file_name, is_backup)
|
||||
data = []
|
||||
sortid = 0
|
||||
tmp_dict = {}
|
||||
login_all = []
|
||||
for file in file_list:
|
||||
|
||||
if not os.path.isfile(file['file']): continue
|
||||
conf = public.readFile(file['file'])
|
||||
lines = conf.split('\n')
|
||||
for line in lines:
|
||||
if not line: continue
|
||||
login_info = {}
|
||||
if search_str not in line and search_str2 not in line:
|
||||
continue
|
||||
tmp_value = ' is now logged in'
|
||||
info = line[:line.find(search_str)].strip()
|
||||
if not info:
|
||||
info = line[:line.find(search_str2)].strip()
|
||||
hostname = info.split()[-1]
|
||||
exec_time = info.split(hostname)[0].strip()
|
||||
exec_time = self.get_format_time(exec_time)
|
||||
ip = line[line.find('(') + 1:line.find(')')].split('@')[1]
|
||||
|
||||
#取登录成功日志
|
||||
if tmp_value in line:
|
||||
user = line.split(tmp_value)[0].strip().split()[-1]
|
||||
if user == '?' or user != get.user_name: continue
|
||||
dict_index = '{}__{}'.format(user, ip)
|
||||
if dict_index not in tmp_dict:
|
||||
tmp_dict[dict_index] = []
|
||||
tmp_dict[dict_index].append(exec_time)
|
||||
|
||||
#取登出日志
|
||||
tmp_value = '[INFO] Logout.'
|
||||
tmp_value_two = 'Timeout - try typing a little faster next time'
|
||||
if tmp_value in line or tmp_value_two in line:
|
||||
user = line[line.find('(') +
|
||||
1:line.find(')')].split('@')[0]
|
||||
if user == '?' or user != get.user_name: continue
|
||||
dict_index = '{}__{}'.format(user, ip)
|
||||
try:
|
||||
login_info['out_time'] = exec_time
|
||||
login_info['in_time'] = tmp_dict[dict_index][0]
|
||||
login_info['user'] = user
|
||||
login_info['ip'] = ip
|
||||
login_info['status'] = 'Success' #0为登录失败,1为登录成功
|
||||
login_info['sortid'] = sortid
|
||||
login_all.append(login_info)
|
||||
tmp_dict[dict_index] = []
|
||||
sortid += 1
|
||||
except:
|
||||
pass
|
||||
#取登录失败日志
|
||||
tmp_value = 'Authentication failed for user'
|
||||
if tmp_value in line:
|
||||
user = line.split(tmp_value)[-1].replace('[', '').replace(
|
||||
']', '').strip()
|
||||
if user == '?' or user != get.user_name: continue
|
||||
login_info['user'] = user
|
||||
login_info['ip'] = ip
|
||||
login_info['status'] = 'Failure' #0为登录失败,1为登录成功
|
||||
login_info['in_time'] = exec_time
|
||||
login_info['out_time'] = exec_time
|
||||
login_info['sortid'] = sortid
|
||||
login_all.append(login_info)
|
||||
sortid += 1
|
||||
|
||||
if tmp_dict:
|
||||
for item in tmp_dict.keys():
|
||||
if not tmp_dict[item]: continue
|
||||
info = {
|
||||
"status": "login successful",
|
||||
"in_time": tmp_dict[item][0],
|
||||
"out_time": "connecting",
|
||||
"user": item.split('__')[0],
|
||||
"ip": item.split('__')[1],
|
||||
"sortid": sortid
|
||||
}
|
||||
sortid += 1
|
||||
login_all.append(info)
|
||||
#搜索过滤
|
||||
if login_all and 'search' in get and get.search and get.search.strip():
|
||||
for info in login_all:
|
||||
try:
|
||||
search_str = str(get.search).strip().lower()
|
||||
# public.writeFile('/tmp/aa.aa', get.search)
|
||||
if info['ip'].find(search_str) != -1 or info['user'].lower(
|
||||
).find(search_str) != -1 or info['status'].find(
|
||||
search_str) != -1 or info['in_time'].find(
|
||||
search_str) != -1:
|
||||
data.append(info)
|
||||
elif info['out_time'] and info['out_time'].find(
|
||||
search_str) != -1:
|
||||
data.append(info)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
for info2 in login_all:
|
||||
data.append(info2)
|
||||
|
||||
data = sorted(data, key=lambda x: x['sortid'], reverse=True)
|
||||
return self.get_page(data, get)
|
||||
|
||||
def get_page(self, data, get):
|
||||
"""
|
||||
@name 取分页
|
||||
@author hezhihong
|
||||
@param data 需要分页的数据 list
|
||||
@param get.p 第几页
|
||||
@return 指定分页数据
|
||||
"""
|
||||
# 包含分页类
|
||||
import page
|
||||
# 实例化分页类
|
||||
page = page.Page()
|
||||
|
||||
info = {}
|
||||
info['count'] = len(data)
|
||||
info['row'] = 10
|
||||
info['p'] = 1
|
||||
if hasattr(get, 'p'):
|
||||
info['p'] = int(get['p'])
|
||||
info['uri'] = {}
|
||||
info['return_js'] = ''
|
||||
# 获取分页数据
|
||||
result = {}
|
||||
result['page'] = page.GetPage(info, limit='1,2,3,4,5,8')
|
||||
n = 0
|
||||
result['data'] = []
|
||||
for i in range(info['count']):
|
||||
if n >= page.ROW: break
|
||||
if i < page.SHIFT: continue
|
||||
n += 1
|
||||
result['data'].append(data[i])
|
||||
return result
|
||||
|
||||
def get_action_log(self, get):
|
||||
"""
|
||||
@name 取操作日志
|
||||
@author hezhihong
|
||||
@param get.user_name ftp用户名
|
||||
return {"upload":[],"download":[],"rename":[],"delete":[]}
|
||||
"""
|
||||
search_str = 'pure-ftpd:'
|
||||
args = public.dict_obj()
|
||||
args.exec_name = 'getlog'
|
||||
file_name = self.__ftp_backup_path
|
||||
is_backup = True
|
||||
if self.set_ftp_log(get) == 'stop':
|
||||
file_name = self.__messages_file
|
||||
is_backup = False
|
||||
file_list = self.get_file_list(file_name, is_backup)
|
||||
if not hasattr(get, 'user_name'):
|
||||
return public.returnMsg(False, 'The parameter is incorrect!')
|
||||
data = []
|
||||
tmp_data = []
|
||||
sortid = 0
|
||||
for file in file_list:
|
||||
if not os.path.isfile(file['file']): continue
|
||||
conf = public.readFile(file['file'])
|
||||
lines = conf.split('\n')
|
||||
for line in lines:
|
||||
if not line: continue
|
||||
action_info = {}
|
||||
if search_str not in line: continue
|
||||
|
||||
tmp_v = line.split(search_str)
|
||||
hostname = tmp_v[0].strip().split()[3].strip()
|
||||
action_time = tmp_v[0].replace(hostname, '').strip()
|
||||
action_info['time'] = self.get_format_time(action_time)
|
||||
|
||||
upload_value = ' uploaded '
|
||||
download_value = ' downloaded '
|
||||
rename_value = 'successfully renamed or moved:'
|
||||
delete_value = ' Deleted '
|
||||
ip = line[line.find('(') + 1:line.find(')')].split('@')[1]
|
||||
action_info['ip'] = ip
|
||||
action_info['type'] = ''
|
||||
#取操作用户
|
||||
user = ''
|
||||
if upload_value in line or download_value in line or rename_value in line or delete_value in line:
|
||||
user = line[line.find('(') +
|
||||
1:line.find(')')].split('@')[0]
|
||||
action_info['sortid'] = sortid
|
||||
sortid = sortid + 1
|
||||
if not user or user != get.user_name: continue
|
||||
#取上传日志
|
||||
if (get.type == 'all'
|
||||
or get.type == 'upload') and upload_value in line:
|
||||
line_list = line.split()
|
||||
upload_index = line_list.index('uploaded')
|
||||
# action_info['file'] = line_list[upload_index - 1].replace(
|
||||
# '//', '/')
|
||||
action_info['file'] = line[line.find(']') +
|
||||
1:line.rfind('(')].replace(
|
||||
'uploaded',
|
||||
'').replace('//',
|
||||
'/').strip()
|
||||
action_info['type'] = 'upload'
|
||||
tmp_data.append(action_info)
|
||||
#取下载日志
|
||||
if (get.type == 'all'
|
||||
or get.type == 'download') and download_value in line:
|
||||
line_list = line.split()
|
||||
upload_index = line_list.index('downloaded')
|
||||
action_info['file'] = line_list[upload_index - 1].replace(
|
||||
'//', '/')
|
||||
action_info['type'] = 'download'
|
||||
tmp_data.append(action_info)
|
||||
#取重命名日志
|
||||
if (get.type == 'all'
|
||||
or get.type == 'rename') and rename_value in line:
|
||||
action_info['file'] = line.split(rename_value)[1].replace(
|
||||
'->', 'Renamed to').strip().replace('//', '/')
|
||||
action_info['type'] = 'rename'
|
||||
tmp_data.append(action_info)
|
||||
#取删除日志
|
||||
if (get.type == 'all'
|
||||
or get.type == 'delete') and delete_value in line:
|
||||
action_info['file'] = line.split()[-1].strip().replace(
|
||||
'//', '/')
|
||||
action_info['type'] = 'delete'
|
||||
tmp_data.append(action_info)
|
||||
# f.close
|
||||
#搜索过滤
|
||||
if tmp_data and 'search' in get and get.search and get.search.strip():
|
||||
for info in tmp_data:
|
||||
search_str = str(get.search).strip().lower()
|
||||
if info['ip'].find(search_str) != -1 or info['file'].lower(
|
||||
).find(search_str) != -1 or info['type'].find(
|
||||
search_str) != -1 or info['time'].find(
|
||||
search_str) != -1 or get.user_name.lower().find(
|
||||
search_str) != -1:
|
||||
data.append(info)
|
||||
else:
|
||||
for info2 in tmp_data:
|
||||
data.append(info2)
|
||||
data = sorted(data, key=lambda x: x['sortid'], reverse=True)
|
||||
return self.get_page(data, get)
|
||||
|
||||
def del_crontab(self):
|
||||
"""
|
||||
@name 删除项目定时清理任务
|
||||
@auther hezhihong<2022-10-31>
|
||||
@return
|
||||
"""
|
||||
cron_name = '[Do not delete] FTP audit log cutting task'
|
||||
cron_path = public.GetConfigValue('setup_path') + '/cron/'
|
||||
cron_list = public.M('crontab').where("name=?", (cron_name, )).select()
|
||||
if cron_list:
|
||||
for i in cron_list:
|
||||
if not i: continue
|
||||
cron_echo = public.M('crontab').where(
|
||||
"id=?", (i['id'], )).getField('echo')
|
||||
args = {"id": i['id']}
|
||||
import crontab
|
||||
crontab.crontab().DelCrontab(args)
|
||||
del_cron_file = cron_path + cron_echo
|
||||
public.ExecShell(
|
||||
"crontab -u root -l| grep -v '{}'|crontab -u root -".
|
||||
format(del_cron_file))
|
||||
|
||||
def add_crontab(self):
|
||||
"""
|
||||
@name 构造日志切割任务
|
||||
"""
|
||||
python_path = ''
|
||||
try:
|
||||
python_path = public.ExecShell('which btpython')[0].strip("\n")
|
||||
except:
|
||||
try:
|
||||
python_path = public.ExecShell('which python')[0].strip("\n")
|
||||
except:
|
||||
pass
|
||||
if not python_path: return False
|
||||
if not public.M('crontab').where('name=?',
|
||||
('[Do not delete] FTP audit log cutting task', )).count():
|
||||
cmd = '{} {}'.format(python_path, self.__script_py)
|
||||
args = {
|
||||
"name": "[Do not delete] FTP audit log cutting task",
|
||||
"type": 'day',
|
||||
"where1": '',
|
||||
"hour": '0',
|
||||
"minute": '1',
|
||||
"sName": "",
|
||||
"sType": 'toShell',
|
||||
"notice": '0',
|
||||
"notice_channel": '',
|
||||
"save": '',
|
||||
"save_local": '1',
|
||||
"backupTo": '',
|
||||
"sBody": cmd,
|
||||
"urladdress": ''
|
||||
}
|
||||
import crontab
|
||||
res = crontab.crontab().AddCrontab(args)
|
||||
if res and "id" in res.keys():
|
||||
return True
|
||||
return False
|
||||
return True
|
||||
QRASP55VO/1DQ98p1csw9A==
|
||||
PsDvd5tup7sspheXmdBjJ9/VPPpQm3Z93wJWBqKcwhPstZtP/mNaMKeE886qnOocqTecg7HmhY5phLEK5HEF6dZHSv0Wlj6b6xPrN6rZ/hs=
|
||||
5G1X0WJyak7IcriKROwRfg==
|
||||
PsDvd5tup7sspheXmdBjJ9/VPPpQm3Z93wJWBqKcwhPstZtP/mNaMKeE886qnOocqTecg7HmhY5phLEK5HEF6dZHSv0Wlj6b6xPrN6rZ/hs=
|
||||
ZuLVraRZUj2RhJbyALJsxNMuhZe1AKXjIZKX1s/bahYi6PnNCfy1Qv0MKdv1oxSXYGJY2PXP7NLNatPW4VSB/zJjWGw5HqJLpeYo/MseDrI=
|
||||
PsDvd5tup7sspheXmdBjJ9/VPPpQm3Z93wJWBqKcwhPstZtP/mNaMKeE886qnOocqTecg7HmhY5phLEK5HEF6dZHSv0Wlj6b6xPrN6rZ/hs=
|
||||
mlbcpvT0kUVOtns2yTGydDt4+07xDvuvRqS/JgkUon3SrcxUlm2Z4rG4Pa9PwOq+
|
||||
PsDvd5tup7sspheXmdBjJ9/VPPpQm3Z93wJWBqKcwhPstZtP/mNaMKeE886qnOocqTecg7HmhY5phLEK5HEF6dZHSv0Wlj6b6xPrN6rZ/hs=
|
||||
iOUsBGgOHEqzdAdQgfAp4trfzBztc5RmfOjqgmGickU=
|
||||
XQTKBPclCgMYfJTNC1Qwx9JOU5PR8V/GzRhXc9amMLuHdAcID+TXUZzz7SdDuJA9
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
f3AsbhS4PaN1B4cUkY9T+A==
|
||||
vlNl0s/hLJ4MLdvF5a1XATBpmRe09mwg70GHdHdh7mTmKAaerhorUT+w+dAajOtb
|
||||
MMZtIZZuuuWy0CLBzKekTg==
|
||||
i8F7pUrlHPBNsIux2MgfYA==
|
||||
hAZTEkbxoxowQJisJSulNX6xYijfsoIV2aWlEpje85k=
|
||||
Fzf1WPeHT+phfW8FPaBhNw==
|
||||
iwW5Y10vLm5bol1PMh2K5PcgF/7PR7VaxhpNPLVQXiQ=
|
||||
iiFBxU1BEtsymTSqJJqljqN1RY1RLiUspBdLrvd0CW0=
|
||||
ldCxpJy7GYU9Z3wc/nhJ/te4XvT+sJUYSl50ZnBKy3w=
|
||||
CrJuPSINqYUMS/s5z4adcU1LJqJ2Sojj3C2wjmLuRsM=
|
||||
Psg6WqdUeMsPYvW+jnYn0evEHl+1XoE/rnCfo+c6WdA=
|
||||
1z8iprMiHgI6LYZftXGjKDYPI7FVqZWCQ09oWcM3Pag=
|
||||
o1ftBjL5WX5IAh9xWVdqd9wdMBvoYRdNfl+IAvPWFp8=
|
||||
QUUBWS4HdgaVs9J11lpeBKBH5NkT6WbMMMnumMF/7Aw=
|
||||
tfRWYnUvHUwnwQYB+ywLpslVnsH3tMXHAPD/cYoTpT4=
|
||||
AtAHlguqAHnQsUP0meqLH3VU1D/0sLjQMR/6J/fyRbM=
|
||||
7MgotmZFCo6+Kg3s1/uhRtwRAi7VKRh0cRfONXMb3yI=
|
||||
CvGG8CijcRlYyvz5dGomfhXk6DzjYPOBtu63/Veri24=
|
||||
/PTfuW9bPdAz/6cUQf+E55cP43jnvaceBCRBneohYbA=
|
||||
YHmVAP+XfXvh6Do8nF7SSw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
Tz7Nk5H535VRrRyTrsKtQL8WpBb8+0Czjnl0ON67RWc=
|
||||
gSinJxQ2Dl02IUzuK5alezKMVZMklWE7tWiUg2329L/n+lRYCQ9UCFbErLWlw54SDdzf2aW7xcFo9f6yWsFr+Gmxv7QW7ILh8TsYOZ9znNp1PFfZW6D80dgQ9cC19CuCsN/nORHFj+ZzOKgvaEAfFiLoGt0ZpN5vpGxumpW0gpcWn6x7Ldft+bCe8OO/4vq4eE9RKaqjTgoUu0FLyAKLMsUrm9spdqinKdfS+0njcmvjNfpj5WOsg4REfjqMdCjT+eYrQYJpSEhzTFpPXaGYrdCg7TnFabrpVoJ3F5uhjQdkKGWqXHHHV/nbuQtIHnCtT8dwjmznuv5sSlpRCVqsgj9kw0VHrZYCN0PnqZ18QBTTb6aQzq2vcHCtyHbfnTgZYpXapiGZtR0S/U7DzfJCjnAyqRZxt4/wKHbAGYy8PQ8OUSXjFZJkxujMHXXUoxC2tVM7rRO1UyMTyERrP/FjuBzgj8YxTjyaxV4GnCT02jD45RbtdAK6txhyTaDZXcGS
|
||||
9GxZpCRwMRDPejWR2Vvf+LKn0tNtFKp8Eh2tnr4Da9U=
|
||||
NRG8WiBknxy8LZ7uM7Rtwjpor9jB6CRSN8s/tRh0bCGCT3O3yIYveV/kC3whqCOj
|
||||
g+9Bvcv6QScOWqD1KWI83lDWKDEvFH24UumsH9uh9SSEzyoQuAQyJOm+k2nYRQYDLlXqKegz+5H8/A6yDuU4hTssV9YA2l/qH0zdlTP5IOI=
|
||||
wgR07xfoapmx6eEnFHXXYsrtutdMRxYffYBJpExAFLL3LFn2eCspav2L+PBokDEhe88eat5Ab0fx9+MVZjZtHQ==
|
||||
xWoGNWjKGPfI4gq8aHoTfOgPIu3QGZOJ5qEujzh3pzi1Iz2/AHJ8GvmS3bUx5254nOirctK/k6BFZA2v8ayK/EDVY6Wbr2d7jYxq8UAugp4=
|
||||
uRzTWU2MnopGqqEdWeT6ZU1hlM1Dw8+qKY/ieJj+NsUqvH0CTNguPTeX+Laan8WHKtl7c/+1YA4rF+Fa3pfogwkGJNEhZb49H+rX+WZ7S1s=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
J24jXQQti6wQv5pCoF2ZrQbQF1j1bF4/QmmX1CwZUVEjmug7a9JAroEXBBTfhYssEYHy8XwASHc+rw3shghfWA==
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
a1WCYQuoRJeK3mOCGHQIlhC5ovOIKOhQYI+YFVzTxDyBspL/Zz/EA3ekwqZLC22t
|
||||
eeFiPlXUI0Fos82HYztSmTsAYhvcpYqGtZuapEgzpCBypVgTjJ6W0KJC4ipcw897
|
||||
WuRvIBaPNRsVGEMoM4NSTioH6DPOvYqQxMaOqX/7OKFY0pBl49Sar+3IeBmADhmj
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
N5xldEoitd9eWUThCvdOTB6LOXhNE9TOsjnkpc/9SMN2L8WJXh22t578ODk/HhdL
|
||||
oxiSpIWwD4wuBub3KU1/cF5fchu1Vqpk+nU9bn11yzo=
|
||||
PRG/YRzXVD8iVR3bzEcUnjHro+U+4TucaVNI9ygPWuVU3EqLuxmqZkTk2CyNK7O/
|
||||
VmVrGQo2zRokW/ZuO9bN68uCgzKuG5LF3dEm8osmV0HPcWbbdr6DBOymTEvfp0P/ftdl4LLYfLwuPpwsYazhEA==
|
||||
VmVrGQo2zRokW/ZuO9bN68sblSJDKz0OqxMt0bHs/NUCob2DYRF35HVY0+LpxHBb
|
||||
iDFAoKi0IJZ7t2pJuBivrw==
|
||||
l2FJPs4YkAmmok1ulDRuSA==
|
||||
PRG/YRzXVD8iVR3bzEcUnt6EfhtcL4GrcBoio2oUko9nPAoPP0N4kWpuhhh+oYdV
|
||||
9zgnmC3+5N9XK5/NRaR4SMVNup0N5fm76yGD/GNlNnU=
|
||||
sDlCNtGYD6nPzg4cZ+6YAIVaGRKK1htDJsqNdoebWm8=
|
||||
1V2v8QerKOmubvSxgB4eTCXRIGj4wwBQxqmi+7HBYgg=
|
||||
PRG/YRzXVD8iVR3bzEcUntHGmZ5qTlWv7ywh0UaUxJzXifYQX4pUcW7z5PPhLeh5
|
||||
sDlCNtGYD6nPzg4cZ+6YAOK/4Cv++bqYgS9TyEF32cuA5AzQdBq8lyKWQabFTagT
|
||||
1D18KWr2hdVsBcdZx1OaPWkr8ytK7qVWaaza8e1vU6k=
|
||||
VmVrGQo2zRokW/ZuO9bN66Vh5+Ci920JkrzQsTHn083JJPLf45hGeTPWU0PgjupO+yaDkxvgzGWeJhaeVem9Wq+8oeyKDNsYcPKXT94yeZ0UymKFveKN91eF38ApXJp2
|
||||
VmVrGQo2zRokW/ZuO9bN625bd4BNT0j+VcP1nTIY6XaDTRy5+5AWHUZPakkiglNT
|
||||
VmVrGQo2zRokW/ZuO9bN69TcL00if5hvJ8+IR0VhUuvoRwQz2rzPWjBJm1Mk3z5a
|
||||
VmVrGQo2zRokW/ZuO9bN62AVcq3plEcj4rxrsvQ9pPDU08M8azrqNxOOot3ghWHctbl7KH0YZqLimlQWQDerlojzSftx5vWNNRCgaO4RyF8=
|
||||
VmVrGQo2zRokW/ZuO9bN6xD6PoCXoaoICnYYUV03lnrKjmQB9MEOOIg0j4Z9zWge
|
||||
VmVrGQo2zRokW/ZuO9bN6/wMRobeZASkZ7UgaRv/zbQEquXghr8pcxoQVAx9J5G/e9b3CtH5KoqK0sb3R99OsA==
|
||||
sobCGpmMf4/g7+HpPqBjC6hatZ6rUY3AAzqC73FJ58Q=
|
||||
VmVrGQo2zRokW/ZuO9bN66Vh5+Ci920JkrzQsTHn083JJPLf45hGeTPWU0PgjupOJvco2FZSOBWgiEqCcFM7Q/vW4PqCZLGYaAAy6qf2tko=
|
||||
VmVrGQo2zRokW/ZuO9bN625bd4BNT0j+VcP1nTIY6XaDTRy5+5AWHUZPakkiglNT
|
||||
VmVrGQo2zRokW/ZuO9bN69TcL00if5hvJ8+IR0VhUuvoRwQz2rzPWjBJm1Mk3z5a
|
||||
VmVrGQo2zRokW/ZuO9bN62AVcq3plEcj4rxrsvQ9pPDU08M8azrqNxOOot3ghWHctbl7KH0YZqLimlQWQDerlpd+8N/8ymIPDrStsyiyEo4=
|
||||
VmVrGQo2zRokW/ZuO9bN6xD6PoCXoaoICnYYUV03lnrKjmQB9MEOOIg0j4Z9zWge
|
||||
VmVrGQo2zRokW/ZuO9bN6/wMRobeZASkZ7UgaRv/zbQEquXghr8pcxoQVAx9J5G/e9b3CtH5KoqK0sb3R99OsA==
|
||||
ojv9MyHa70Aio7SDrWcjwSYYqgfeHLgPvpjtVJfUmX0s6OSNU+WrIf9mNVPQ5TfqPavTidvffxVkcshQNOCsRA==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HklNjZdFug/ngOpMcvCKxEBrAN68NaDKAtp2GLglVerAbQ==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HkllTuznFui81R4CASaEKJI9
|
||||
5wsVwKLrIjIWqeTNpSVp9YtfZPXXv5krNmxeXAjq+NQ=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
JKgfL+COM6qpIwe0Wm0zY0qrBwJPhJivgZdbq2ek/MNyEskG/o3RxQuD1murI70P
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
9JiWXiRNWDTg+XstQ0v3tAQjzhKVhg9yH4FpL7cmNHMby1dZvf+KLKXDFxiL/GyHwt+mo7J9Eh26MMHXk7dZ7A==
|
||||
vyYQukiyWticSXOwUY8MiznZqoLnnCC/RUpXDOGxEsg=
|
||||
ho/Q+jrWDtBeg9J9ZTnKizg5CYSqIH+8noUWvD9u7YuJKKfD4Zw1m+s2/8nfOg5c
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
fLETQ22HuDIh4ibW1C50WajryFpGmdAvdbylaFXR0PYbVChIKwUBviTdPnbJl3rp
|
||||
uTEK8Ng11d3ix2pA+DD/aYq6iiRaSOVPA0xTeOGnO8KEq+qETa/PY3c3TUpiGOuA
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmVtxbXBpGlFIU9ZBe0L9nDB3cJqXtkVNxiOuaaYNBuGag==
|
||||
c0jePRxtTVZYop75Q5JCFonnV+X8W6zX0oXQ+sQuZtHIAMgLt2jbmRWY4GrPgmiW
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW7Akukb+j0lqloIv/j7uSM4oazJqFVNfgaZWfRnkezm/n/qRAFeZXm0pd4Y650TvY=
|
||||
Mmz9tB5RaVIWQerkiDs2BePvXl4dNWSjl+vJFVGrvpac5kzICL/kBoClsURQxOPYTWXamhuvoo8Pwhw/Asx8vw==
|
||||
R14ZYm6mELJXNFBxHSBttdYfQPT7lYz3sNsgm+2cAVEVZqqsWoLADHy1tzgaDLwVuLUQU00i5jhUkarevZBgbw==
|
||||
jpkMvZxe0AU7LK72hOoSV9O2+nkRjDR2qPsiciba+P0=
|
||||
SSb4svay1O2En913Q8HWTI5XiKI6KpCz9PP4OKkiVgIZ9PAiv190X/Q6cvCmIvEn
|
||||
O3CUgrw2GJfB+mDjH5+NdgM4cG182DjbaaqgGRQTDbbHFEBxIQHWpD3HPFUKruz8
|
||||
VmVrGQo2zRokW/ZuO9bN62aET6XweFEf8bCs0QU19kFV77Lm2Kxx3MCAPMJIlJSp
|
||||
sobCGpmMf4/g7+HpPqBjC6hatZ6rUY3AAzqC73FJ58Q=
|
||||
VmVrGQo2zRokW/ZuO9bN62aET6XweFEf8bCs0QU19kF1ezkxxQftj/4sG8qLYubO
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmVhrSS9BSOA1ZLru6nt/7dm75/vFI6+H/XoIqtvVBWgGA==
|
||||
13vYlKuO6A3n1KjBvCLS2cZOnSAYizlRW6NVt55Nvpg=
|
||||
Rc/EJuEm/I9INM8fD5RDm8V6NM+R609UAWBHMDxIGH1KB0feE4DfP+R5GNLxg7AM
|
||||
xWoGNWjKGPfI4gq8aHoTfBMUl5q05yLZWa9BqWZ+hHXNzfrvrNJv7lUhLv58UG50furKaKDp9/7/vwDMn7xgPA==
|
||||
32pdC9DD05OE2l0oXazDFBLSw6QGkeD2EftJ95N/ZFU=
|
||||
9Ky7E5Jxg7bFh45xr+PtLAQzRENCwucwjn+oXpXkeQE=
|
||||
Rc/EJuEm/I9INM8fD5RDm8V6NM+R609UAWBHMDxIGH3FuQzm6WS6LLN0bq9R/qzA
|
||||
O3CUgrw2GJfB+mDjH5+NdgM4cG182DjbaaqgGRQTDbbHFEBxIQHWpD3HPFUKruz8
|
||||
VmVrGQo2zRokW/ZuO9bN6zRl0iz3kGEFiV+wGJc1Rx+/HiOt/vX0mu63k3Gx19QQ
|
||||
VmVrGQo2zRokW/ZuO9bN6xF1SJaAm3VttartJvhccJmq0nitHFfMxYtPtCzV22AE
|
||||
VmVrGQo2zRokW/ZuO9bN6y1I47Lsjes5Xkzm/KZ2HUikKCfZfG5oV8DWImIHip5MshUySi7lDaZb63pdnAbPrhvWTvaNXMG/2J1IdORcGPQ=
|
||||
32pdC9DD05OE2l0oXazDFFXAy1MI/uPhakkzCdBdnMA=
|
||||
4+wKB+Tel1iow8au3cOIJaTLjj3pysITCcJJ7ec43Sg8lqI/J7o8CtRAAtYI0AOu3JqoT8kI2t89ug8sZ1eCiQ==
|
||||
96orka/uERLyRst14azQwhCOqhTfcgFhXNAQS0hmuOHsyhzYJSgj0XYfDyZD/qpmTBlCMqtpJ0emRNzsjaERyA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
f+rqXRH5RpetwpbV8cB3LNb4H/TF90wkaKs48d1M7L+avSymddn7mKYz0NItjsSS
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
6Jpks4lpI/jb7zQY9ZwZK1zkFQHFLO1SftfqDQPgq1EBsFoAqyniZa+4+xJKzZfT
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
IOQ7R1QbtHtN/omAE4BWfAjZgPJASxuTDruVD3whaNc=
|
||||
b4OJVZe8QyIpjuTpKXDL9A==
|
||||
wlLHv6kT3Q/RmtMBN4nDAQ8YSs8Zt0gDBRyWHhM8ed+GGdWzPmL+jZ6S+F5YV+22
|
||||
VmVrGQo2zRokW/ZuO9bN6xjRZ/jgghl2/5XRKMIuEuFfgv1283QcodM/1ZOCBV+E
|
||||
VmVrGQo2zRokW/ZuO9bN6x+Y6lBOlB/5zr7yqielcHbAt1j/vhhHLiR0XLFVJ4MYIB7qEVFJCIX6M64zazFiQeEMWR6HA8xoXyo6nAZJhlk=
|
||||
VmVrGQo2zRokW/ZuO9bN6zKW75ke8QGqFd99GlEdhOmQAXdMhXbfkO0SVCSKXZhAgrRq5E4FlbZVLyjCi8XIzw==
|
||||
VmVrGQo2zRokW/ZuO9bN6/VA0tcNP0B0yWPLZItZlkbpytNLRqAe/ddM0lgyhD/+AVdhq9Y31ZAG+aChEtUpGjK+qk8XXC1AHcYIovJNZ+PRowAmFi0HJrFUfIQN6E7Q
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hkl8sUPd5ZHgQChuaaRMaehpXsF9xMLoel3FaVnpw+fNuSwrGC7RSUXTIrW2j2yH61A=
|
||||
VmVrGQo2zRokW/ZuO9bN6zZcpHqbLPCfucCocPyjGlY=
|
||||
L0eUthVnpkGsmKFAX6d+uK/AWodUm3mcxHH2qymBAgItW7Ziboyd2OX6uMRxQUgs
|
||||
mfT8DrNbUmxQ2BnZ1bZFTLh9MEuZKOpmAfF70OnZ9TU=
|
||||
L0eUthVnpkGsmKFAX6d+uK/AWodUm3mcxHH2qymBAgItW7Ziboyd2OX6uMRxQUgs
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
69Uik37T733MFTHEnugne9sIK0q/BrAEinbmIsH25IyzJWj8GWaHG6Tu8rx0i8YI
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
a1WCYQuoRJeK3mOCGHQIluXzbJqLPwB2hMZiB6idlsw=
|
||||
vyYQukiyWticSXOwUY8MiznZqoLnnCC/RUpXDOGxEsg=
|
||||
ho/Q+jrWDtBeg9J9ZTnKi7Z8oMuCLRtnjC35Cw+4aVDyKydByU+COt6lumOoVZyj
|
||||
1xJ0clp+39cOWW64WGs9Tw==
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
avTFp0LCGrKbHzgXWCq/pYahaBNfx164yVsSAVTJDN4lWK0zoj6Eh3CajVgk0hPL
|
||||
avTFp0LCGrKbHzgXWCq/pSoIEj7PXeiBI2BkNQsojArLvnQoeeQAiRG4S9Ely2YX
|
||||
c0jePRxtTVZYop75Q5JCFsMjGu62TZDSljeQjMtCShNsz0Y9SFIv08dPVdTjI95b
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW7Akukb+j0lqloIv/j7uSM4oazJqFVNfgaZWfRnkezm/n/qRAFeZXm0pd4Y650TvY=
|
||||
TzinVBSdupkFZuXDgmwYfiSs5GTHKq13dTr2kdVzFPy0Jh42rAak6FUbANl5whZO
|
||||
W7OoNBP/IWbYzUOvpg/slY2NVhp515LKHRWJIoHB+V62OipmiB60YwRsLUoQ2Yhe
|
||||
ojv9MyHa70Aio7SDrWcjwQ0VSHrTkMcwddE36Wz7lCz16K6ytw4GpaCto2OYzTO/
|
||||
IfOrW6dR51K0HWsQz64KwMZLSub5xEzT/cQoJpZiUus=
|
||||
MzOj4ZiBOJDNVP8vi/lFQIcd3YW2BaDb4kSPJzNVOdlx1Fa3HoeBVOYpiRWE7XX1
|
||||
PRG/YRzXVD8iVR3bzEcUno4Z8XHjrzDgKJNn9oJou7lkrRw3h7on47id8HDtKTRy
|
||||
j7S8zldDFIkYlZuEh7uh1S+jR/V5xbpfKOdCgELD/V8=
|
||||
yqOVJCkAGOhqcQYBOo7yqReCj9ixiaIB5tdlZ21DAUB9HlVyjl18y9Mfwf2BKrxO1mdZmBSOas0Z9YsNQ75XTg==
|
||||
NYuttixIfaRvF0QtYZhNf933obSmTd0Sfv1RLv5CWew=
|
||||
jg/rCd1ltkosbKN5ZG2fjyfZDh9bj6LoXpZWnO+Jm3I=
|
||||
kTToPYSGc065HLDqbjV0HFp+qk2oCg3rcMPzGznvj4s=
|
||||
UsNFlHPXrsQOqjn4RzHaA2d+Dsggsz8fegt1C0el50M=
|
||||
m5EI3+BXxkQEYKYaxORD+qnAwk1i08GBypJtuz97N8s=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1V2v8QerKOmubvSxgB4eTFLJVKokCn/n7cBzRCyjPmemCDNpavHplLKoYC5ZrVB11XPhYbqw8m0ksUK1fSNNJw==
|
||||
k1ktu/l6HFULD7Vyr8Cv0HMlLvOl3L1DvBU4YpKX0wAfHx0c0egKY2YtT74Sqa68k3g5TvkiAzu1NRNlkcoBZw==
|
||||
rtgmVFvoY2d3wTFk50ruC6zmYmoALMFLQOc+xc+vXmJzN60uRcu12WAXC28NrZ2x
|
||||
wlLHv6kT3Q/RmtMBN4nDAesM/ZGOfx7RLjx/t+u4GQE=
|
||||
VmVrGQo2zRokW/ZuO9bN692Dxe6/pJb49NcEGwdYFHp1ykWA3uXz8Dyrp2BHgNzY
|
||||
VmVrGQo2zRokW/ZuO9bN65W0SAM+Lz+ixIA1yfBIlyIfbjLiw8kUEWgRJErCtT/B
|
||||
VmVrGQo2zRokW/ZuO9bN63sbeay11c+Azj5VEIm5hpE6JlT9cIzf6HYvRvtfkHtUzfa7mLb2YRp06Fq3uXR7IgrEOFQK+h9IpdXLW6HxD8Q=
|
||||
VmVrGQo2zRokW/ZuO9bN620zSkiHBXev6YTvy3qjpOw=
|
||||
VmVrGQo2zRokW/ZuO9bN68NGdAuCULKcdnQ9QIPhYF2d+4WoU/gSRVS6rllapIH/JcXSlRMgq/Lahda1FjioQA==
|
||||
VmVrGQo2zRokW/ZuO9bN6/D3pD6pMXGNmGG8sGEgUx6XUzf02GbZTCaXui9nRWWO8tkj2O9evUoVTjlZbcp3bw==
|
||||
VmVrGQo2zRokW/ZuO9bN656ysh/dA/L9/oKKFnGsliQ=
|
||||
VmVrGQo2zRokW/ZuO9bN62VJEYtP1Byl1VdEwj5br8q1Cxt1YWn0/LGOVI2rmkKmLTqDuNfg3z4w6nFv1fa0OQ6VY4XRiSyXGr0pXrL72no=
|
||||
VmVrGQo2zRokW/ZuO9bN682I1WfoM5O31Eu4y7eErmS1UbchPX+RbJH8okRw6uaf
|
||||
VmVrGQo2zRokW/ZuO9bN6wGhkWn/nbtYgnRrfABp3Wx1AshDUYpYVsgVW1JY2KGZFsqdt6fYlLewntOhfc3+yQ==
|
||||
VmVrGQo2zRokW/ZuO9bN61QRx6pmjScEC6Mg8X6jMiYZxM1o8NnnHqaeAW/oXr0H2CGH5XEtUznATSrKZ2lZEQ==
|
||||
VmVrGQo2zRokW/ZuO9bN69ytvi1kzpknGdq50rt6Uk+ubFehg+T5L/Wn9jlHITZARQHXl2+Us7ChTWXRkBLidjmBIhghC83F2q0QovPWPAU=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6+WmmMTtHxp83MPGxzXMHzRsy/BAZUo3PX2S6H3yS5eG
|
||||
VmVrGQo2zRokW/ZuO9bN6+lw59pqaZzeIqhj6WMFLKB/zu4YnIm31wuOcKLBoPXS
|
||||
VmVrGQo2zRokW/ZuO9bN63uBz94NTvSB4ZlhYbDfvddgnVY5f5JKOORH7Tw2EYEWgIaiQrzxYa4sTWMTgESGdzp52DXDe+CM2icfFsZP8BQ=
|
||||
VmVrGQo2zRokW/ZuO9bN6yiRU09M/IrGNAMi1AT8LbUYEEDidCw2lDVT2RUEf/k9qsU1Wf5Nkpaqk5UUK1L+GYF2qfhogkOZK7QKKEBb1pw=
|
||||
VmVrGQo2zRokW/ZuO9bN61tUoNETw2Gi1D/Pq4qmNf5zhx/EQVRufI8LJkPSSi0Ih/xPpxJTJaW6aikR8po+Gw==
|
||||
VmVrGQo2zRokW/ZuO9bN60TADvNmgaySXS1m1WJNuPeBE1HygRWbriOlU7U2Ssu3klRVzuCKqRzIyX8uoMGm2Q==
|
||||
VmVrGQo2zRokW/ZuO9bN6+NxpNK9XYUauw2abZQW3LIA6UmYzalir4YjKFLEIVPk8tEmxjCF+UBrUqEASEZ7LQ==
|
||||
VmVrGQo2zRokW/ZuO9bN69V5vRMZphCh9ZgEve1d0/wJCCaWNPSysYTVRsjVkHV1kaWCUu2teK5jcDOFuBzPQg==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN62Ywq26Utqu0XTnaZ+HQKopdamM5KbwMRVVnvfRPuEM1
|
||||
VmVrGQo2zRokW/ZuO9bN69qq0Yi+mSeaf9labGycI4pPobf7Rk2EV5UV2RidC6jX
|
||||
VmVrGQo2zRokW/ZuO9bN63BfTcQ4tGBocvZdkD6/kO+b2BWi71GtoR82tq7ZzboaxwEKuBjLI8hR7w2Vz8MwvmfTeIGeWGGODE9Xm7plcChd9CESFtAhCbsVbUZfRATe
|
||||
VmVrGQo2zRokW/ZuO9bN6+lw59pqaZzeIqhj6WMFLKD5/dQ70v3ovug8BVS13b+a04fDuz4GqTVSudpfL0PZ3Q==
|
||||
VmVrGQo2zRokW/ZuO9bN6/JsORMmbxegVkakcQYSuOtPUInnHZyjGgz46mtOv7qSxkpfnDglI1Zm24CHtbp9uw==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HknACUIF0SHq3Wk7UPJPdvLnBytT0bs3KMa3b9ztxfxoAOuFAPEC6llaTPvEl5nkxFo=
|
||||
VmVrGQo2zRokW/ZuO9bN6yiRU09M/IrGNAMi1AT8LbUYEEDidCw2lDVT2RUEf/k9qsU1Wf5Nkpaqk5UUK1L+GYF2qfhogkOZK7QKKEBb1pw=
|
||||
VmVrGQo2zRokW/ZuO9bN61tUoNETw2Gi1D/Pq4qmNf5zhx/EQVRufI8LJkPSSi0Ih/xPpxJTJaW6aikR8po+Gw==
|
||||
VmVrGQo2zRokW/ZuO9bN62HWtxZ2I/oCwtyWP0WSTIg=
|
||||
VmVrGQo2zRokW/ZuO9bN651w9MrkrO5sEgMcUVTfH6/zCWmOuloAo6ldSTiaAbum79T3ZyCN2uTGYeWaRk8ZDw==
|
||||
VmVrGQo2zRokW/ZuO9bN651w9MrkrO5sEgMcUVTfH6996q3aNX+Q/j+AZP8Qvo1SsqECC6pGPNuHt7GBg6OuU7Z1kO5CyxL0yZW1h1ERJGY=
|
||||
VmVrGQo2zRokW/ZuO9bN651w9MrkrO5sEgMcUVTfH69ya1Zc1M+KUYAJsz6AJ8F9YFPnDyZrQbgW0mxsmgLccg==
|
||||
VmVrGQo2zRokW/ZuO9bN651w9MrkrO5sEgMcUVTfH69tjxVx99Q6mXAvsEky2j6E
|
||||
VmVrGQo2zRokW/ZuO9bN651w9MrkrO5sEgMcUVTfH6+u5zuOiB74Y40ABQeHY7iFbajQdIlVw8YH0S9x9fm/0gGxi5N3i0IL4ZOQgrP8+OX40wVL+NzPVrUtKnd1s0s9
|
||||
VmVrGQo2zRokW/ZuO9bN651w9MrkrO5sEgMcUVTfH693/pJPvxX08JK6/fU1NpPhvWQO/SYGDQsMBTlZKO7NUA==
|
||||
VmVrGQo2zRokW/ZuO9bN65UApnVIJ5/vPXwprQ1J61CB61rainG+jx/I7BmKhaXNbQAK6argkLKn8aYOSqMyZg==
|
||||
VmVrGQo2zRokW/ZuO9bN6+NxpNK9XYUauw2abZQW3LIA6UmYzalir4YjKFLEIVPk8tEmxjCF+UBrUqEASEZ7LQ==
|
||||
VmVrGQo2zRokW/ZuO9bN64RgViN5TsYlk5QzRuGR7Q/OP4DOltXpxjAehZXCVn5t
|
||||
VmVrGQo2zRokW/ZuO9bN6zTwEIRXNDisRd1QRhA8x1E=
|
||||
VmVrGQo2zRokW/ZuO9bN6/6TnYYUnVY4bZC18wJU6T0=
|
||||
VmVrGQo2zRokW/ZuO9bN69wvhLovBGRbT42dQt1px1AK/igYwlUjVrS2AJALzGdr
|
||||
VmVrGQo2zRokW/ZuO9bN6xfwiyo+r5sBtLLY/yC2JQuHAqyNIUWdS8mL+/TK0tDkDYK6sWUkPNuSjWFfywjVYg==
|
||||
VmVrGQo2zRokW/ZuO9bN6+lw59pqaZzeIqhj6WMFLKB/zu4YnIm31wuOcKLBoPXS
|
||||
VmVrGQo2zRokW/ZuO9bN63uBz94NTvSB4ZlhYbDfvddgnVY5f5JKOORH7Tw2EYEWfecK1ZYcY5aRkTVMuXTf4H0ornquPXZt6sNbcV9pvdE=
|
||||
VmVrGQo2zRokW/ZuO9bN69fMKIOt3Fz+VdjDCrbU0LCl+bFI5Faw9xdIi1QHkSiy
|
||||
VmVrGQo2zRokW/ZuO9bN6yiRU09M/IrGNAMi1AT8LbUYEEDidCw2lDVT2RUEf/k9qsU1Wf5Nkpaqk5UUK1L+GYF2qfhogkOZK7QKKEBb1pw=
|
||||
VmVrGQo2zRokW/ZuO9bN69q3A6NsFro7W8cTziR/HLwPXg3jnnr3ZgO5MqTOchYl
|
||||
VmVrGQo2zRokW/ZuO9bN69q3A6NsFro7W8cTziR/HLymwotzxdwFuDwNOf7s1SnK
|
||||
VmVrGQo2zRokW/ZuO9bN69q3A6NsFro7W8cTziR/HLxqHw0Wm+3Oz89atXNvpO+3MXp3Qtmegk6NHmWrFwnYkOvDHfuz5NaWnAG6esuIjESLWMw8mumKWR+OGLFQatxn
|
||||
VmVrGQo2zRokW/ZuO9bN69q3A6NsFro7W8cTziR/HLyUNjqRPrStY0n7cNwmxO8c2/xYLBixqHfcg+3JdMiYfw==
|
||||
VmVrGQo2zRokW/ZuO9bN69q3A6NsFro7W8cTziR/HLx3KKJ5e9ptEgMTxJyuDzDUvQprgIXqnEOJyY8Wjzx/7g==
|
||||
VmVrGQo2zRokW/ZuO9bN69q3A6NsFro7W8cTziR/HLzg8EOHacHSOV2zn2Ehx3MZFJJGKychYjDMMiIIfaMNUg==
|
||||
VmVrGQo2zRokW/ZuO9bN6zSaI2hF+nruhyzPFkleUq8kEqJLrAmChIOBKZkxcqwkGxR20IThZlGA1Dw2fFbmvg==
|
||||
VmVrGQo2zRokW/ZuO9bN61yX1Dmgg5/3/nXVEduWvGRjAxUjUGE7S9oN2liQJclq
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
M8WJLh8/G3HKYOcF0o/j+ZydjE/y4s9kCBsZH9Ydiys=
|
||||
wlLHv6kT3Q/RmtMBN4nDAR8Bo0ERF5FTL0peq/6tsQxyyboaug1HqBM4U72iapnH
|
||||
VmVrGQo2zRokW/ZuO9bN68F9oo0dUBAgf3zfH+UjZ2vBnQt9FOIIe/Mpc+VcY0hPyb7Y4hQhLdZIwPaG+7+qSw==
|
||||
VmVrGQo2zRokW/ZuO9bN6wO+YLo8joUjMSrMMYsU2gc=
|
||||
VmVrGQo2zRokW/ZuO9bN6wxqWDjyux4j5kWMbM/YT04A7rFtRY3ZvKwNmal8z607JZ0N1ek63JQAbp1/rMmDdg==
|
||||
VmVrGQo2zRokW/ZuO9bN66+oTs/ylSo2IwYwivOcQ5QBeGO3/qhUXmuWRmyY22oicnIskjhngFIDfDK5fq2/pg==
|
||||
VmVrGQo2zRokW/ZuO9bN6wPyViMJrLgq6QE06AJQ/mAxMxhT6z5+FEPokBQMNnem
|
||||
VmVrGQo2zRokW/ZuO9bN61Ayy1rssK205MlM60bu6RKTG0Yfp2Lha8/dhaOOY7W18jbXMCbohsZ+i3OCAo0UDg==
|
||||
VmVrGQo2zRokW/ZuO9bN63oDITMAygWGYYDyry55YDO/Rs3iFoOYCQPRB0Vo6QHG
|
||||
VmVrGQo2zRokW/ZuO9bN65wPRQBNUUIF+K895b5fOrPxf0bXsfEkNdHCrolD4R0g
|
||||
VmVrGQo2zRokW/ZuO9bN654Enj8yhWFV20SJ83piZWE=
|
||||
VmVrGQo2zRokW/ZuO9bN63D/Hc2z6pQlInT4BP7h+Iw=
|
||||
VmVrGQo2zRokW/ZuO9bN6yUmZOZSHWWMW4cj+zuxv+kqaCT5BWcHH/D3f8p49LGM
|
||||
zvzyAjCZxViDIIg5wIBcfv3Z+YCuz/oELxYEQudPAfA=
|
||||
/jVx2Sfk8Nv4tQDKNVrh5YQDDOyw39n94XpeN+Fc18Kb/ocx6XA91E4DLjnGHUVOp/hG38KiBHnsJF7rC+FrGh3/Y7Yjh+e73kBNop061ts4ALDF136iqb3NjiK6eB/P
|
||||
wlLHv6kT3Q/RmtMBN4nDARhCtgHyXaIoGDNPdzxanK1C9qqxbuBKdK1MCBW9e3yd
|
||||
VmVrGQo2zRokW/ZuO9bN63zFN5O/w1krXKBn8bzERXc=
|
||||
VmVrGQo2zRokW/ZuO9bN65v9BdTfHDX5h5JoIA/XwnnexMAistxqcEkO+FfI33OD8/CZEhqElXeJdGaAFQ+8dlBsrteF3JVNER2SAEya4ro=
|
||||
VmVrGQo2zRokW/ZuO9bN60wy8tZH9NZmPUZU3ymx7Rp230YC0uhO/IEmXkv95OC+kYR59ne0kzYbTAnbjiDQU/tfbdzA12veXVBzv74WMwI=
|
||||
VmVrGQo2zRokW/ZuO9bN6w1QwjDxqY23oBLfy+yRgv/pNEUynCImsZYJyFdRKiY3f9n/tdlMbWaxhorqdeT5IvbcJCzD8QfNSTYnlePbg2dOcteS5jjxFSQ3VLx5bqO0
|
||||
VmVrGQo2zRokW/ZuO9bN6xDmLuIA9/MQHFSh5NeXQIQ+yxAa1KwUsFahRjuiZ8Mht4CYtcVKfJe+264KUvItRwPdoTCmQExpQVyY7LXmw64=
|
||||
VmVrGQo2zRokW/ZuO9bN6zj/WJ/j3Gpxi/RO5HrCvbVpMoEipT3erObxJsWCoytEOGK/hbak+7Shcx1wGKtjvE9kvRNNO0FTZ9ViojU52Bs=
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hkkdh44SEE/n2JvhNVaLLGFkAT0r5NcHasfhHQIuEbaS/w==
|
||||
VmVrGQo2zRokW/ZuO9bN6yC3ZNj/jGmx0c5FxYA8mMYFovl3/pDr9xKbkD9+awkq
|
||||
VmVrGQo2zRokW/ZuO9bN6y282QljYt9u/aACctfJxlfOZSOWj+ka4WVOhE7+gYPHIAVL1wqdRYXpc242KdGWJ/V8BbFe5Mk6POcVdzCcc/E=
|
||||
VmVrGQo2zRokW/ZuO9bN6zj/WJ/j3Gpxi/RO5HrCvbUT/1fI7DpxplEbSq3o7wy5
|
||||
VmVrGQo2zRokW/ZuO9bN6yC3ZNj/jGmx0c5FxYA8mMYFovl3/pDr9xKbkD9+awkq
|
||||
VmVrGQo2zRokW/ZuO9bN6xoaa3pLsxXyLdB8GbtG2YY=
|
||||
VmVrGQo2zRokW/ZuO9bN6/VW4n84N+xmKyiHoJANXzc=
|
||||
l2FJPs4YkAmmok1ulDRuSA==
|
||||
wlLHv6kT3Q/RmtMBN4nDAU4MoUw37WOeYAqXUx8nKXV08D/vyeLYo268Q6TQAkcy
|
||||
VmVrGQo2zRokW/ZuO9bN68rwZzz6qT+BRwAM0w/VgNam6voCMhL/LyfmhkE+4WOq
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
YabJCT93a3/IohXaIkr3oSIBZqGhFAEcGH7Ca/SaLLaG+fOp90QxSi85tpj3adUdyNOydRy2vjmM402XZpsX3+nkFnHf2XtWx5xSFzCScjM=
|
||||
CAhn8dRUItEbEErp4w+lX6BuaW4lR2EIOU/Z+PBe2bh+we0izGB82w9NP/FQvC5X
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
oSOaxL22S+/P+2LLtATJSAaArdQ7fQZ1yguM5QAidIUD9pZGaNnuSKZ/6l+iYdvR
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
hpr9H7QXrORqNT7P49jOY2MKXv3knmxSuBVQsYMFcyo=
|
||||
YThduOXrtrzATLnwayQWnd8n5YD62KOD6YsiYJw+RAk=
|
||||
7JQQDTi0T2idhFjao4jEpWRxFagB+y/O50vW7a0bZYhQWe9QbLzaMInaqQiRp7EGliGMBr4A0vhy+GCOuLQR2g==
|
||||
7JQQDTi0T2idhFjao4jEpVM5kDnYAXzeJH6AUYrQZAHIQ4Zi/CV9839Nkf/Sc8cE
|
||||
h2Amc56dmaRo3inGZxN9N4t4UB6ZIYdgw3I8UrLsiK9g6KbQ85/a9qF4mH08k4ge
|
||||
rErGIG0jHuEUhPzM/Cvn7eDAiXr3299blfSBm1Bfub0=
|
||||
B3iNup9pdvLGx6CAo6KC6KE/v+ibyUyH8Yud04Lz810=
|
||||
q4nc/jwATOMUyfSjLibfEenY5RFzfDAlBFkea5rX8Ic=
|
||||
nhEO6jGYTLTxNd7tfL8haGb6dIE98SqR0mAOJokWbaA=
|
||||
2gqFvhn8R1IfPGeV2rMswbHUHFXVUzGBLmhsu02wzqE=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
C3JSV38/w2nvM3I7TZ5+4epkOMkaWYvoOErk6ygROHs=
|
||||
to+v3MAswOY2NqesdSm5E+gSyJU0y7Xs7zqrUefMUuCWwwmO2rJrPN7egFiRQVKU
|
||||
vJtKpUSg5Ukl4nJbF6QjQJ7EE1taDQMnZThgUYKjS1A=
|
||||
m64JmVQ8ZxnJzJGTbbSLFgYYjwLvqe5k1J852jWCJ20=
|
||||
GDxnwLueKeYNT0/dIp4TaMZIrCOXt9Fadk7QEvmi3LY=
|
||||
iZaIsa48RXfE+uf/yF/rQBFFBTbLDCVgmOpzzd9fNSoU5yqcis6eMa2AhGtSBk42
|
||||
8+kEPw2kbWRhVZANSTiFn91S4x0IfqnYB21Go0MrYHk=
|
||||
ed2GXKkXmwU2EQk+6MUOb5wVZ0JLOm9I7uChKGZVytg=
|
||||
ojcUvW+Z2ehEJ6yMJpmY+4qFMPDKWboTeo1Y4LE86Gs=
|
||||
/0ULpLqgTvInFD0r5hHANoosZ+xywkOR5dozStfmlYk=
|
||||
YSlit6erKXylrjSZnvyW8KJQ5WBrDhjuDH3szUt3rF4TtLL3u+2vhmfGxql7dElVlZ+FltHCrJLtURHR876Z+5QJwoIiDk96EuxXOkKMTdk=
|
||||
DaK4moDemtv24P20mOaUzQ==
|
||||
YSlit6erKXylrjSZnvyW8F3ElaLeR/Rlppv/IAE6pDs=
|
||||
9zgnmC3+5N9XK5/NRaR4SOWz2y/YEwWVWSZltrwvNrSfE3PSPwQMDu0BXDhBm14C
|
||||
1V2v8QerKOmubvSxgB4eTCxJBqBlZI1ptPijcUHCDz5sYoASyVMieGEeAAQXWrck
|
||||
1D18KWr2hdVsBcdZx1OaPfHgcwFUa7nBQO7bfH5tm74XTDXVMzBwLoLCrGgXhe0X
|
||||
fqq/Y0gPbKQeEXzqLGS0q/J+017f+uH388qCfSeGlh8=
|
||||
o6QhOIN2Sc4SHELnst17uYigovIGLGw9Sk8MSoNStgLGPEqp/JNtpdjWEUUK4pQG
|
||||
ruTTNFTdswRs4Mc+srnRk818d9d/TGGXzgPjSrVtMi8=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
lkFGPJ6keZ1Jd10HSdN0i5ZJfFnQV/nGEGCTaGt06s58zYz056g6djTo00sC9scb
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
a1WCYQuoRJeK3mOCGHQIlhrCEedAYfpQnUktuEYoFlw=
|
||||
vyYQukiyWticSXOwUY8MiznZqoLnnCC/RUpXDOGxEsg=
|
||||
ho/Q+jrWDtBeg9J9ZTnKi7Z8oMuCLRtnjC35Cw+4aVDyKydByU+COt6lumOoVZyj
|
||||
AWid6G8ypXqQe9XxPPYED6EG/d+wAZpLmHn10ofRnJm2zuVMuvU9qhZPIJsbg007g9BmQxGLRAPjJyKkcrVzW+hTwBZcS8FDXPlLD0f/q/4=
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
avTFp0LCGrKbHzgXWCq/pYahaBNfx164yVsSAVTJDN4lWK0zoj6Eh3CajVgk0hPL
|
||||
TzinVBSdupkFZuXDgmwYfiSs5GTHKq13dTr2kdVzFPy0Jh42rAak6FUbANl5whZO
|
||||
W7OoNBP/IWbYzUOvpg/slY2NVhp515LKHRWJIoHB+V62OipmiB60YwRsLUoQ2Yhe
|
||||
ojv9MyHa70Aio7SDrWcjwQ0VSHrTkMcwddE36Wz7lCz16K6ytw4GpaCto2OYzTO/
|
||||
IfOrW6dR51K0HWsQz64KwMZLSub5xEzT/cQoJpZiUus=
|
||||
MzOj4ZiBOJDNVP8vi/lFQIcd3YW2BaDb4kSPJzNVOdlx1Fa3HoeBVOYpiRWE7XX1
|
||||
PRG/YRzXVD8iVR3bzEcUno4Z8XHjrzDgKJNn9oJou7lkrRw3h7on47id8HDtKTRy
|
||||
j7S8zldDFIkYlZuEh7uh1S+jR/V5xbpfKOdCgELD/V8=
|
||||
yqOVJCkAGOhqcQYBOo7yqReCj9ixiaIB5tdlZ21DAUB9HlVyjl18y9Mfwf2BKrxO1mdZmBSOas0Z9YsNQ75XTg==
|
||||
c0jePRxtTVZYop75Q5JCFsMjGu62TZDSljeQjMtCShNsz0Y9SFIv08dPVdTjI95b
|
||||
L0eUthVnpkGsmKFAX6d+uDz5ZRBys3d0SQKK5GYgSmW7Akukb+j0lqloIv/j7uSM4oazJqFVNfgaZWfRnkezm/n/qRAFeZXm0pd4Y650TvY=
|
||||
NYuttixIfaRvF0QtYZhNf933obSmTd0Sfv1RLv5CWew=
|
||||
z7RR81hY6MAA2voH8Z2gcSMl4BzicmRRwwcx6alhVes=
|
||||
jg/rCd1ltkosbKN5ZG2fjyfZDh9bj6LoXpZWnO+Jm3I=
|
||||
m5EI3+BXxkQEYKYaxORD+qnAwk1i08GBypJtuz97N8s=
|
||||
1V2v8QerKOmubvSxgB4eTFLJVKokCn/n7cBzRCyjPmemCDNpavHplLKoYC5ZrVB11XPhYbqw8m0ksUK1fSNNJw==
|
||||
k1ktu/l6HFULD7Vyr8Cv0HMlLvOl3L1DvBU4YpKX0wAfHx0c0egKY2YtT74Sqa68k3g5TvkiAzu1NRNlkcoBZw==
|
||||
rtgmVFvoY2d3wTFk50ruC6zmYmoALMFLQOc+xc+vXmJzN60uRcu12WAXC28NrZ2x
|
||||
wlLHv6kT3Q/RmtMBN4nDAesM/ZGOfx7RLjx/t+u4GQE=
|
||||
VmVrGQo2zRokW/ZuO9bN692Dxe6/pJb49NcEGwdYFHp1ykWA3uXz8Dyrp2BHgNzY
|
||||
VmVrGQo2zRokW/ZuO9bN69YWkPGheqxTevWr4koVetNO2nXtSSYd+VohbeMtpTJM
|
||||
VmVrGQo2zRokW/ZuO9bN63sbeay11c+Azj5VEIm5hpFeadOrAd8WGDCLEKR35dm2edAnPxHas9j394knOwJ8NA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN69nNx2wsmuj5rj8dMZU/ic5BLawNF/f6lthvaeVh/Ls+
|
||||
VmVrGQo2zRokW/ZuO9bN69Fm+oKgY4oZ96N2lUN0xCYIR65p/6S+rx79lvSqg2I47knqkaZTvrsnLR+tEwCTnA==
|
||||
VmVrGQo2zRokW/ZuO9bN6+qkEKPDxNwYFnkXN8TuQuYkotp65nYQ0fa3zEFof2zYnFi/LEybvPyjh48Z1idmyjl0NtdcsjLBkBJ13a8Xf98=
|
||||
VmVrGQo2zRokW/ZuO9bN6wm11lyKsRHgTY7hsLdIWagcAA4Fqj10A0nlHnCL31hRaLimdtsSr1rF3vfwAkIE9UNe1Oq6AC93jtsLEBybVC4=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN69fMYEokQlwk/9w9fdzOny6b4sFM5OW1KAT1oeECeG7J
|
||||
VmVrGQo2zRokW/ZuO9bN6x9kSHAfsYQbQ95eUk47zCSU++ESIivk4zGTm21DHKkHEqyRv+yZpHFD0LXHT4m58A==
|
||||
VmVrGQo2zRokW/ZuO9bN68s9bgaf6E2UUkkykIzwZHpz3P+5wRaqeeTuq1ofqFvFKnCBTa5TbqmgBM/RmZJPNAUu69T5cyQoQbj9yc2u8n0=
|
||||
VmVrGQo2zRokW/ZuO9bN65llTn0pe1t030hd6gBN+zBd3IDBl9SSuthuY26B8/Pu
|
||||
VmVrGQo2zRokW/ZuO9bN69ytvi1kzpknGdq50rt6Uk+ubFehg+T5L/Wn9jlHITZARQHXl2+Us7ChTWXRkBLidjmBIhghC83F2q0QovPWPAU=
|
||||
VmVrGQo2zRokW/ZuO9bN62HF7Hu1aUGvgMj3NxvOaP7lJ1t3oULkhfzDpf5obr4i
|
||||
VmVrGQo2zRokW/ZuO9bN6yfJ0tQlmRWb/s+hHO4yegbY9OZJu7Pz1YpWO35g7fWo
|
||||
VmVrGQo2zRokW/ZuO9bN63coKIwm0os5grqf/FNTOQs15MAmmbu+Svk4r/hr3Mwt
|
||||
VmVrGQo2zRokW/ZuO9bN633IXjOdT/W54PqLLNSn1Vg=
|
||||
VmVrGQo2zRokW/ZuO9bN60VxqaV005HoUzQg7og2uQzzkGvTFfQImHgCDcOTreTvBj0gdrkAAkZ1tFN5kmALjU7kVG7jii3XUUaGJzXU1Dm0brYcNqsnFgqAbRd+hLig734vVILUrNX+DvQbOCpPeCtyQ8YEDj2QHDc0gf1laMU=
|
||||
VmVrGQo2zRokW/ZuO9bN6/JsORMmbxegVkakcQYSuOtPUInnHZyjGgz46mtOv7qSxkpfnDglI1Zm24CHtbp9uw==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HknACUIF0SHq3Wk7UPJPdvLnBytT0bs3KMa3b9ztxfxoAOuFAPEC6llaTPvEl5nkxFo=
|
||||
VmVrGQo2zRokW/ZuO9bN6/HUq2I+boGDdrr74hWiH13yvcZl75di1EfS2yW7gx+JTVNJQF0HOMQVAegRfGv1eA==
|
||||
VmVrGQo2zRokW/ZuO9bN64OaX2n92Ly7KbozWq7a7t04nFfOkcL8NsC84xQi78iQ
|
||||
VmVrGQo2zRokW/ZuO9bN6+a8J14HUH3L5V5KblyMysRYdesKR+fGd24F6C9j1l7wwo/p5lCfK41p1tvTNJzD/Q==
|
||||
VmVrGQo2zRokW/ZuO9bN6yZNwtKaS0KLSStVEVMnEqjMcCKBADGrWUZZOFSQE2G8
|
||||
VmVrGQo2zRokW/ZuO9bN6+3TErdL9P5BVvv77uxFNG6LDoAfDNrQcomm1VDCoez1
|
||||
VmVrGQo2zRokW/ZuO9bN661ybCBlxEvwailf4eTD9bqZ+RlmOwSQwtD/IjfE4TEXKm1zXESIuOIjor2vta6yx+sUjFgCbNTyLF8DtvW/9/Y=
|
||||
VmVrGQo2zRokW/ZuO9bN61EVRyU6dsJr2EqyMVPbztJnTc0M4smwvC4e37Qh7Ms8
|
||||
VmVrGQo2zRokW/ZuO9bN67E2Rg2DTyty5YPAV4Joqwwqw9NcbRGp5GK4uyK1s8dkEGH9RxcsHHlq/24VKap3dQ==
|
||||
VmVrGQo2zRokW/ZuO9bN6xRDOkMGch8OU8UdKKuA98T78S/RtIEO+vPGquNUPYP8j7Hqi5x7cOT1rq7lCPTbFRrq+ZOiuhVZC6d2uE6b5Y4RMkjy5kdxgYDR8lyh08y6
|
||||
VmVrGQo2zRokW/ZuO9bN6x+CQDkpZHTSzVJB0vr6/owqo2rDPdhhBctC47HwoQJI
|
||||
VmVrGQo2zRokW/ZuO9bN6/HUq2I+boGDdrr74hWiH12i/zuDq/sxwawfAUxLzsmyvkFQXYvSK+lgmw3Dfruf8oUMKRDLCW0YoRSFNGJnVRA=
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HkmJ6/ykoozm7YfC70113tbsRK8vQxRXP6m1Lk5Pq4lJ71yrM2OyBQ2a20YT6ATnjGs=
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hkl8sUPd5ZHgQChuaaRMaehp008Hpwo+KIS41Bq+plw28g==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hkl8sUPd5ZHgQChuaaRMaehpCUt6sS2ZM7/SgZvw2/D7KN2T4F8mibCUg/Vu5XXI0q8=
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hkl8sUPd5ZHgQChuaaRMaehp369EMxzMKwrpZ1Fsc6Rzihs0R+CDz1UtQsB7s3e2X1Y=
|
||||
VmVrGQo2zRokW/ZuO9bN6/HUq2I+boGDdrr74hWiH12q9ECvLOWcUe9cfTPHyuxucjjrMsKMpYA6OLWCOLB2Qw==
|
||||
VmVrGQo2zRokW/ZuO9bN64rXDFbHdbWNMaZnXznjAwk28c0+eGFiwoRx33gWzY3PbndTr3mFKpviH1b0k1s0KA==
|
||||
VmVrGQo2zRokW/ZuO9bN68uqYuUF7HS6ZsAigA5dAhhdPk0G+p/b9PgaumDuRt89
|
||||
VmVrGQo2zRokW/ZuO9bN6+3TErdL9P5BVvv77uxFNG6LDoAfDNrQcomm1VDCoez1
|
||||
VmVrGQo2zRokW/ZuO9bN661ybCBlxEvwailf4eTD9bpaS2w5sSDIfS2hUtvDW/ZPwVwLAcDR+Kc98dntjxh559OJdKONTmZolY5AjSf4KMU=
|
||||
VmVrGQo2zRokW/ZuO9bN61EVRyU6dsJr2EqyMVPbztJnTc0M4smwvC4e37Qh7Ms8
|
||||
VmVrGQo2zRokW/ZuO9bN67E2Rg2DTyty5YPAV4Joqwwqw9NcbRGp5GK4uyK1s8dkfYflZHE0nkkYN92Iz4DvtrB7pbXI8nJ1B+v8kBcTL9k=
|
||||
VmVrGQo2zRokW/ZuO9bN6/HUq2I+boGDdrr74hWiH10h4UbnbgTDNlKt0H8bnNKHH19OWWvR1gRk3zXeKMJ+R8jqCu7/rIb/rNBOG+zFbIM=
|
||||
VmVrGQo2zRokW/ZuO9bN6wRsqCOcYvLI1Bp/40+s8jeuGD+dib11yOYzha+J15yw
|
||||
VmVrGQo2zRokW/ZuO9bN6/HUq2I+boGDdrr74hWiH11DboSZV8b8syS3y20nGfXmJMrA3OSI5dV3PIVmDHiETg==
|
||||
VmVrGQo2zRokW/ZuO9bN64rXDFbHdbWNMaZnXznjAwk28c0+eGFiwoRx33gWzY3PbndTr3mFKpviH1b0k1s0KA==
|
||||
VmVrGQo2zRokW/ZuO9bN66uuxBZGV0E5w7uGfD+hzU4AmPi0rGaOz7BvwaEoiXgK
|
||||
VmVrGQo2zRokW/ZuO9bN6+3TErdL9P5BVvv77uxFNG6LDoAfDNrQcomm1VDCoez1
|
||||
VmVrGQo2zRokW/ZuO9bN661ybCBlxEvwailf4eTD9brMUFxnvPbybqGRmv07gv34NbyJ44u8fMbC6Sq1JkAEaNjiyTMCoEHy6fKKN/tEOOE=
|
||||
VmVrGQo2zRokW/ZuO9bN6/HUq2I+boGDdrr74hWiH112Cwgr1gup7jex1yHReVWxiyvsKVsK3znbe1ecdgFhbIZqxwirWCHagb7ADC5VmGM=
|
||||
VmVrGQo2zRokW/ZuO9bN6yc8qBfgAsioQiqSI3s7WIFM5rHpAQSYfkhRNfXBk2JBPvIvjRzS10i3GMc0J2bxTrSvtMX11tg5EOzI+VjAy9E=
|
||||
VmVrGQo2zRokW/ZuO9bN6/HUq2I+boGDdrr74hWiH12W5piSXwXcBTxZsgj+fR5PRj+yKlsuMRhvQaQszRXFiA==
|
||||
VmVrGQo2zRokW/ZuO9bN64rXDFbHdbWNMaZnXznjAwk28c0+eGFiwoRx33gWzY3PbndTr3mFKpviH1b0k1s0KA==
|
||||
VmVrGQo2zRokW/ZuO9bN69jndazZ1JZSETYUFSRjpTYuSd0gU4R+ef5NLXuDtL3Q
|
||||
VmVrGQo2zRokW/ZuO9bN6+3TErdL9P5BVvv77uxFNG6LDoAfDNrQcomm1VDCoez1
|
||||
VmVrGQo2zRokW/ZuO9bN661ybCBlxEvwailf4eTD9bqkLLlR3IpZgSDiX5ChzlR6NnjTJlDwKlsxY/AdyE1faRiMQGjhE0oX8Ie0uAI0rvI=
|
||||
VmVrGQo2zRokW/ZuO9bN6/HUq2I+boGDdrr74hWiH112Cwgr1gup7jex1yHReVWxP38Ud5r+2JgPLAafH7N4i6SpRZsaYMAGNiTp9HaQsd4=
|
||||
VmVrGQo2zRokW/ZuO9bN6wRsqCOcYvLI1Bp/40+s8jeuGD+dib11yOYzha+J15yw
|
||||
VmVrGQo2zRokW/ZuO9bN6/HUq2I+boGDdrr74hWiH13ETFhTDjpNg4UjDJ/ZX/5m5v/P88Ser/GIltB+CyiPFA==
|
||||
VmVrGQo2zRokW/ZuO9bN64rXDFbHdbWNMaZnXznjAwk28c0+eGFiwoRx33gWzY3PbndTr3mFKpviH1b0k1s0KA==
|
||||
SS3eUI6O4Am57+zsCenaFkHmh+pwM+FJ/cut0UtoxJ0=
|
||||
zvzyAjCZxViDIIg5wIBcfv3Z+YCuz/oELxYEQudPAfA=
|
||||
M8WJLh8/G3HKYOcF0o/j+UKQix7E5QZpJV0Tfc/XRq/AKN5kkYE+IMwFcAyVsz2M5wHJAN89+nJ1b7GSY68O6925BBXUxFwqdflokenOUZU=
|
||||
wlLHv6kT3Q/RmtMBN4nDAZf8v50ttctcXvJzAQ4D3y4VerbRFUVUK+NjcpNFPsa+
|
||||
VmVrGQo2zRokW/ZuO9bN60s8cEnb0+qXY0vQh1/7elp8TJKn/o/Cr8ab/L4KpzVyx+zZfHPJlblcJVM2evPA8Q==
|
||||
VmVrGQo2zRokW/ZuO9bN62wFNZfsNF2gO4y5vOS6dGtOhTIohM0/9iaTTdt4VAkwr3U4JR6xB2mGWrp5KaqxgOX+iIeHDUU+B09yhkuBbeQ=
|
||||
VmVrGQo2zRokW/ZuO9bN6zJHGvDJmOJJYHHdXzByxKsyeKpya/o0dns6NEjvZ9FhBqfG56Ge8FxUmH1UPM8WYg==
|
||||
VmVrGQo2zRokW/ZuO9bN641hlBSX1Vyx3lcgSR68G0pIVXm8+RXV4rlYHPfD1CE2Ifl6RiQnkn3hT82X+tXXDQim3jnyNRBLGfZDXhejLG8=
|
||||
VmVrGQo2zRokW/ZuO9bN6zj/WJ/j3Gpxi/RO5HrCvbVpMoEipT3erObxJsWCoytE96eId0MgNxxUF/+ybzG/f+gvdjS4IHHuGSQJeLB3dqc=
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6Hkkdh44SEE/n2JvhNVaLLGFkAT0r5NcHasfhHQIuEbaS/w==
|
||||
VmVrGQo2zRokW/ZuO9bN67WLIC8ccIPl/iWyXLvwqc6z89/fim1Zup64yhd9bw8m
|
||||
l2FJPs4YkAmmok1ulDRuSA==
|
||||
wlLHv6kT3Q/RmtMBN4nDATXcKKq3YicYjT+ilqwnePASEk6UJ4kb2FJ4sCzHQMkb
|
||||
VmVrGQo2zRokW/ZuO9bN68rwZzz6qT+BRwAM0w/VgNam6voCMhL/LyfmhkE+4WOq
|
||||
YabJCT93a3/IohXaIkr3oSIBZqGhFAEcGH7Ca/SaLLaG+fOp90QxSi85tpj3adUdyNOydRy2vjmM402XZpsX3+nkFnHf2XtWx5xSFzCScjM=
|
||||
CAhn8dRUItEbEErp4w+lX6BuaW4lR2EIOU/Z+PBe2bh+we0izGB82w9NP/FQvC5X
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VEyEXJTNTVvV1TGW5V2yEMzjBDxvV9j1MdPjo5gCe0Q=
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
dar6N0tUAb9rU8/aX1b3tI5lWSbcXQgKxiMzJeLasCmdJgT+u3YcH7fkhDzLb+1X
|
||||
9BuKX7c+cBUFGH/xEQqKwDJwv6pCDrQbGrc/aEaAxEizXN1tDiWRXfYhvFOYGiCD
|
||||
3AcPLYoMMn4rxWOUMA1wJdOmdYprhThTGxGyDnWq840=
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
90/F6C3nHF3UrQ/Er80CwwMY0Oi3JHbGAYQNb/w2V49c1F+wL9hoGKNjAjwN6pWeeHbxvhz6JqsdWpYj5f3cjKeHXg+8Lul7hoesFngMXfE=
|
||||
g9lRvj200ApJT2I/NDdmaNS2bs03/Yy1N4LL8JCPrSEGtYUIbFGqz+9Nvsx/WW8DAPlJEAOAh1mN1Q2H5srR9aN9BcyfgbXU677udPpvmJs=
|
||||
AC/CEOsuoGTyXbh39EUlAxckdwNHSoPmK9UbpHaeRy5+9wXscQv0OinnRdatf4o5vPdsr8lUrlC4beVwlerQ34wo2xApt+NOGbWFjuh6p10OnBiFzXIsBBGS2CKsc8ur
|
||||
HBkACpLXsHV9FQoDE2PMYwSntxSga34Rul8QLEjV96M=
|
||||
wlLHv6kT3Q/RmtMBN4nDAeWjc9eUr6obACCnQsg7vueRPByWE2DayjQ0xFllv1tW
|
||||
VmVrGQo2zRokW/ZuO9bN65VlXQyBOMicxNyTkfSbDVVHhvBq22DM+S7/byvVxhpE
|
||||
VmVrGQo2zRokW/ZuO9bN6yititPhxMgpb/nuYcU2bQxlVrgi32/YGL7BfDcYBS6ZrhF8DKeSq4/xyWh1l402NQ==
|
||||
VmVrGQo2zRokW/ZuO9bN60VWeNWzP5MtK6lHtmFWfiOlcDBQw592yq0YxYnQPyb2cY8haKBhRx3ogIkozyLzGA==
|
||||
VmVrGQo2zRokW/ZuO9bN61P2OVHnBm22rHl5VcwespdSVFvlh6jWmhNQGuWaiPCn
|
||||
VmVrGQo2zRokW/ZuO9bN6/C3rj8+QHPPw24V/a4Ay7A=
|
||||
VmVrGQo2zRokW/ZuO9bN61MqA9WsfKOg/tExmVwPpl7QnDnpNlS+CkeEkfTa9kINLQXgJYeYvwm13Q5goIzeLg==
|
||||
VmVrGQo2zRokW/ZuO9bN632LGHZY9uic2w89Yj9RNWLrcjnK57CYRX2bXewhAHx7FVtzwI0ZOgY/T/V/6qaQlw==
|
||||
VmVrGQo2zRokW/ZuO9bN6+8Z7TpabL3QP28zOzKbdjakEuF8eNiysMFwArESQEwY
|
||||
VmVrGQo2zRokW/ZuO9bN6yg8DfkEZba0oHLbAQabDs+4/JxGHZrKdgs6bMyBPLRMxwPtWLarWOkPgDMMkW2/RUdxOLVZk3+IQpAGkMdAX/s=
|
||||
VmVrGQo2zRokW/ZuO9bN62dh+FzI+VGLu7ulc+ItFAbFXemabBEE/LbP+46UYm60
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
JEnsSsP7ogTJg1OXQ2YdoeqaOYYcnxFN3j3ktV+Kpps=
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
8xWkPvEiREBWC3F3wdDkfHfKi35MXWHSVRhGdhf5R5T9XB9HNeEomkbAWdDKXpBP
|
||||
Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
tsXNkoeF46BtVmFZ50qzKkC9C9rJjI8DYYqtZ5sTRNk=
|
||||
b4OJVZe8QyIpjuTpKXDL9A==
|
||||
cjZRE5RYY9TGg8THaNbKeimi7CKPJrP0YrozyGJJ6po8VG8Og36dzm29TqPtykmq3ShDIRxTK5G7NnirQ35JIwA7rlx3Yk1mP0YkpIDY3Ec=
|
||||
mfT8DrNbUmxQ2BnZ1bZFTLh9MEuZKOpmAfF70OnZ9TU=
|
||||
vQwaisdUFOt9b0SJYuH/nrHigrTUtycF35lf58xGUQo=
|
||||
VmVrGQo2zRokW/ZuO9bN60gMmPI+qllGkwxOA9qbMmMB1m4JoBAOFYQ6YXkMo1VXquwSJ3IOKilGLS5oWPYO5OYeeloJXPkrrYqwK73A4D8=
|
||||
M0ZySqkmhuHCw6olbCKv9zQJzSQJo4Zslq06bXS41SQ=
|
||||
VmVrGQo2zRokW/ZuO9bN64/n5EL8V7CIqhp9FPzHEuQ=
|
||||
W3A5Dt+8AxWSKsTYeXZoL1vLKDueV7P0Ut7HIASfZlp4D0IrBt2bwp8YHjJXXxXp
|
||||
W3A5Dt+8AxWSKsTYeXZoLzB4TUiScS3D8yuLKBmm3AwWtYcxV6f46K0T0Egvi5WKkEtlHJveHdb2egjl/+1LDg==
|
||||
VmVrGQo2zRokW/ZuO9bN64ZTCtjiSIe1Vj/8GYr6HkknASfUzt1VKHSynjO/3GCHs8NYZ0lBfA3YkEhN9KGBNrviqTxIwFkI8b8tfQOhuu8e1qX/wTQkIHS4gFt6ErXtomVQ+AVI6XYbacH6pVLAEQ==
|
||||
3ihEq+EcGY3EkKhgSscgbxPe6xF3X8bYDWyX0qt6BtkDpzyqs5cxV+fqGAxgw4n0F0ocWo63+pTEB2B02sSu997O+t/1VUp8dx53F4oaaq8=
|
||||
1S1xjYS0s+Ph1PyvECx3QMdMFDZ5B3+BEK8kyCfI1RM=
|
||||
VmVrGQo2zRokW/ZuO9bN67pnuem2Cn+Z/63FRYUcFkLoOrSR0T8WP6DifYG5JOXMPR4AFoHBPiKvg8hnpKw+PCDgxml+g92wfGPN8zZ2WJk=
|
||||
VmVrGQo2zRokW/ZuO9bN64Ga+02XCL+A28NNybmlSnI=
|
||||
VmVrGQo2zRokW/ZuO9bN65a8NYx2zqK2mFD4wjj1HmQ=
|
||||
VmVrGQo2zRokW/ZuO9bN61jw9zMkfm0nvQi9tveiWV0=
|
||||
VmVrGQo2zRokW/ZuO9bN6zYzNJFTIYiz/a08bSUNc5M=
|
||||
VmVrGQo2zRokW/ZuO9bN6ztX+cJqy4yqv63JnfA/mqI=
|
||||
VmVrGQo2zRokW/ZuO9bN60jLKcJEMj36X6NZvvwxF/XvqrmJF3W3RArdDHrkgZZ6
|
||||
VmVrGQo2zRokW/ZuO9bN6zskyREk1B9SpIIVpfE36zU=
|
||||
VmVrGQo2zRokW/ZuO9bN63leNhHVk6qBYEqAElCrxOXVPHIpJ8U4k7mou4tbIR/7
|
||||
VmVrGQo2zRokW/ZuO9bN68tloVdndHDn6gJZRayJG+k=
|
||||
VmVrGQo2zRokW/ZuO9bN617eR9WvYqaE7y/ppCzNL1570CCRJc668VdVufs+tRvC
|
||||
VmVrGQo2zRokW/ZuO9bN6x59qEj9owkguOGj8QrHQSLi1Q/1C75rARTXu4TGt8DP
|
||||
VmVrGQo2zRokW/ZuO9bN60Bq4PDCei1vxH18OtSGKCg=
|
||||
VmVrGQo2zRokW/ZuO9bN67biU+BUR7/d7BkQj4RgpT8E7BfCa3N4KcxGo7ivT2Hg
|
||||
YH231WTDnzQG3bFilBiqIg==
|
||||
p9oVsBgcyiBMjDb8CcPOqP2sLQ/zn5Dzo5lCtrgxqTQ=
|
||||
lOh2GtzHjjMM8E9J40AuOcPN2eZCahfvScF49QHmlNXYE5PQWq+WYPigt3dG9DzvOjcs8WVNkHQ6P1pZps2Ehg==
|
||||
UbJuac0dxLiN+5ocS3w2vTpUyzdtCQ6EQJg8V3275Z+ztU2/bGujfta5s3IG3yXD
|
||||
VmVrGQo2zRokW/ZuO9bN66b1EQBxDDTQrHy92SlIikM=
|
||||
L0eUthVnpkGsmKFAX6d+uKdLEGlEXm+o7O9zcmHr26U=
|
||||
guSZID0bFQuDFoWO2uxAJoOpitq6s6c9ladjgxAHqGE=
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: cjxin <bt_ahong@qq.com>
|
||||
# Author: cjxin <bt_ahong@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
@@ -198,7 +198,7 @@ class main(logsBase):
|
||||
try:
|
||||
if self.find_line_str(_line,search):
|
||||
#根据用户名查找
|
||||
if username and not re.search('-\s+({})\s+\('.format(username),_line):
|
||||
if username and not re.search(r'-\s+({})\s+\('.format(username),_line):
|
||||
continue
|
||||
|
||||
find_idx += 1
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: cjxin <bt_ahong@qq.com>
|
||||
# Author: cjxin <bt_ahong@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: wzjie <wzj@bt.cn>
|
||||
# | Author: wzjie <wzj@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
import os
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2020 宝塔软件(http://www.bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2020 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 沐落 <cjx@bt.cn>
|
||||
# | Author: 沐落 <cjx@aapanel.com>
|
||||
# | Author: lx
|
||||
# | 消息通道邮箱模块
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2020 宝塔软件(http://www.bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2020 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: lx
|
||||
# | 消息通道飞书通知模块
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2020 宝塔软件(http://www.bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2020 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 沐落 <cjx@bt.cn>
|
||||
# | Author: 沐落 <cjx@aapanel.com>
|
||||
# | Author: lx
|
||||
# | 消息通道邮箱模块
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2020 宝塔软件(http://www.bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2020 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 沐落 <cjx@bt.cn>
|
||||
# | Author: 沐落 <cjx@aapanel.com>
|
||||
# | Author: lx
|
||||
# | 消息通道邮箱模块
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
# coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2020 宝塔软件(http://www.bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2020 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: jose <zhw@bt.cn>
|
||||
# | Author: jose <zhw@aapanel.com>
|
||||
# | 消息通道电报模块
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2020 宝塔软件(http://www.bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2020 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 沐落 <cjx@bt.cn>
|
||||
# | Author: 沐落 <cjx@aapanel.com>
|
||||
# | Author: lx
|
||||
# | 消息通道邮箱模块
|
||||
# | 常用功能
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2020 宝塔软件(http://www.bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2020 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 沐落 <cjx@bt.cn>
|
||||
# | Author: 沐落 <cjx@aapanel.com>
|
||||
# | Author: lx
|
||||
# | 消息通道邮箱模块
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
+22
-22
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
@@ -38,7 +38,7 @@ class nginx:
|
||||
gets = ["worker_processes","worker_connections","keepalive_timeout","gzip","gzip_min_length","gzip_comp_level","client_max_body_size","server_names_hash_bucket_size","client_header_buffer_size"]
|
||||
n = 0
|
||||
for i in gets:
|
||||
rep = "(%s)\s+(\w+)" % i
|
||||
rep = r"(%s)\s+(\w+)" % i
|
||||
k = re.search(rep, ngconfcontent)
|
||||
if not k:
|
||||
return public.return_msg_gettext(False,"Get key {} False".format(k))
|
||||
@@ -64,7 +64,7 @@ class nginx:
|
||||
gets = ["client_body_buffer_size"]
|
||||
n = 0
|
||||
for i in gets:
|
||||
rep = "(%s)\s+(\w+)" % i
|
||||
rep = r"(%s)\s+(\w+)" % i
|
||||
k = re.search(rep, proxycontent)
|
||||
if not k:
|
||||
return public.return_msg_gettext(False,"Get key {} False".format(k))
|
||||
@@ -88,14 +88,14 @@ class nginx:
|
||||
n+=1
|
||||
return conflist
|
||||
|
||||
def SetNginxValue(self,get):
|
||||
def SetNginxValue(self, get: public.dict_obj):
|
||||
ngconfcontent = public.readFile(self.nginxconf)
|
||||
proxycontent = public.readFile(self.proxyfile)
|
||||
if public.get_webserver() == 'nginx':
|
||||
shutil.copyfile(self.nginxconf, '/tmp/ng_file_bk.conf')
|
||||
shutil.copyfile(self.proxyfile, '/tmp/proxyfile_bk.conf')
|
||||
conflist = []
|
||||
getdict = get.__dict__
|
||||
getdict = get.get_items()
|
||||
for i in getdict.keys():
|
||||
if i != "__module__" and i != "__doc__" and i != "data" and i != "args" and i != "action":
|
||||
getpost = {
|
||||
@@ -105,13 +105,13 @@ class nginx:
|
||||
conflist.append(getpost)
|
||||
|
||||
for c in conflist:
|
||||
rep = "%s\s+[^kKmMgG\;\n]+" % c["name"]
|
||||
rep = r"%s\s+[^kKmMgG\;\n]+" % c["name"]
|
||||
if c["name"] == "worker_processes" or c["name"] == "gzip":
|
||||
if not re.search("auto|on|off|\d+", c["value"]):
|
||||
return public.return_msg_gettext(False, 'Parameter ERROR!')
|
||||
if not re.search(r"auto|on|off|\d+", c["value"]):
|
||||
return public.return_msg_gettext(False, 'Parameter ERROR! -1')
|
||||
else:
|
||||
if not re.search("\d+", c["value"]):
|
||||
return public.return_msg_gettext(False, 'Parameter ERROR!')
|
||||
if not re.search(r"\d+", c["value"]):
|
||||
return public.return_msg_gettext(False, 'Parameter ERROR! -2')
|
||||
if re.search(rep,ngconfcontent):
|
||||
newconf = "%s %s" % (c["name"],c["value"])
|
||||
ngconfcontent = re.sub(rep,newconf,ngconfcontent)
|
||||
@@ -132,7 +132,7 @@ class nginx:
|
||||
def add_nginx_access_log_format(self,args):
|
||||
'''
|
||||
@name 添加日志格式
|
||||
@author zhwen<zhw@bt.cn>
|
||||
@author zhwen<zhw@aapanel.com>
|
||||
@param log_format 需要设置的日志格式["$server_name","$remote_addr","-"....]
|
||||
@param log_format_name
|
||||
@param act 操作方式 add/edit
|
||||
@@ -151,7 +151,7 @@ class nginx:
|
||||
conf = public.readFile(self.nginxconf)
|
||||
if not conf:
|
||||
return public.return_msg_gettext(False,'Nginx configuration file does not exist!')
|
||||
reg = 'http(\n|\s)+{'
|
||||
reg = r'http(\n|\s)+{'
|
||||
conf = re.sub(reg,'http\n\t{'+data,conf)
|
||||
public.writeFile(self.nginxconf,conf)
|
||||
public.serviceReload()
|
||||
@@ -162,14 +162,14 @@ class nginx:
|
||||
def del_nginx_access_log_format(self,args):
|
||||
'''
|
||||
@name 删除日志格式
|
||||
@author zhwen<zhw@bt.cn>
|
||||
@author zhwen<zhw@aapanel.com>
|
||||
@param log_format_name
|
||||
'''
|
||||
log_format_name = args.log_format_name
|
||||
conf = public.readFile(self.nginxconf)
|
||||
if not conf:
|
||||
return public.return_msg_gettext(False, 'Nginx configuration file does not exist!')
|
||||
reg = '\s*#LOG_FORMAT_BEGIN_{n}(\n|.)+#LOG_FORMAT_END_{n}\n?'.format(n=args.log_format_name)
|
||||
reg = r'\s*#LOG_FORMAT_BEGIN_{n}(\n|.)+#LOG_FORMAT_END_{n}\n?'.format(n=args.log_format_name)
|
||||
conf = re.sub(reg,'',conf)
|
||||
self._del_format_log_of_website(log_format_name)
|
||||
public.writeFile(self.nginxconf,conf)
|
||||
@@ -227,7 +227,7 @@ class nginx:
|
||||
format_name = [i.split('LOG_FORMAT_BEGIN_')[-1] for i in data]
|
||||
format_log = {}
|
||||
for i in format_name:
|
||||
format_reg = "#LOG_FORMAT_BEGIN_{n}(\n|.)+log_format\s+{n}\s*(.*);".format(n=i)
|
||||
format_reg = r"#LOG_FORMAT_BEGIN_{n}(\n|.)+log_format\s+{n}\s*(.*);".format(n=i)
|
||||
tmp = re.search(format_reg,conf)
|
||||
if not tmp:
|
||||
continue
|
||||
@@ -240,7 +240,7 @@ class nginx:
|
||||
def set_format_log_to_website(self,args):
|
||||
'''
|
||||
@name 设置日志格式
|
||||
@author zhwen<zhw@bt.cn>
|
||||
@author zhwen<zhw@aapanel.com>
|
||||
@param sites aaa.com,bbb.com
|
||||
@param log_format_name
|
||||
'''
|
||||
@@ -248,13 +248,13 @@ class nginx:
|
||||
sites = loads(args.sites)
|
||||
try:
|
||||
all_site = public.M('sites').field('name').select()
|
||||
reg = 'access_log\s+/www.*{}\s*;'.format(args.log_format_name)
|
||||
reg = r'access_log\s+/www.*{}\s*;'.format(args.log_format_name)
|
||||
for site in all_site:
|
||||
website_conf_file = '/www/server/panel/vhost/nginx/{}.conf'.format(site['name'])
|
||||
conf = public.readFile(website_conf_file)
|
||||
if not conf:
|
||||
return public.return_msg_gettext(False, 'Nginx configuration file does not exist!')
|
||||
format_exist_reg = '(access_log\s+/www.*\.log).*;'
|
||||
format_exist_reg = r'(access_log\s+/www.*\.log).*;'
|
||||
access_log = self.get_nginx_access_log(conf)
|
||||
if not access_log:
|
||||
continue
|
||||
@@ -272,7 +272,7 @@ class nginx:
|
||||
|
||||
def get_nginx_access_log(self,nginx_conf):
|
||||
try:
|
||||
reg = 'access_log\s+(.*\.log)'
|
||||
reg = r'access_log\s+(.*\.log)'
|
||||
log_path = re.findall(reg, nginx_conf)
|
||||
if not log_path:
|
||||
return False
|
||||
@@ -309,7 +309,7 @@ class nginx:
|
||||
if not site_format_log_status[s]:
|
||||
continue
|
||||
website_conf_file = '/www/server/panel/vhost/nginx/{}.conf'.format(s)
|
||||
format_exist_reg = 'access_log\s+/www.*\.log\s+{};'.format(log_format_name)
|
||||
format_exist_reg = r'access_log\s+/www.*\.log\s+{};'.format(log_format_name)
|
||||
conf = public.readFile(website_conf_file)
|
||||
if not conf:continue
|
||||
if not re.search(format_exist_reg,conf):continue
|
||||
|
||||
+20
-20
@@ -1,10 +1,10 @@
|
||||
# coding: utf-8
|
||||
# -------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: zhwwen <zhw@bt.cn>
|
||||
# Author: zhwwen <zhw@aapanel.com>
|
||||
# -------------------------------------------------------------------
|
||||
#
|
||||
# ------------------------------
|
||||
@@ -26,7 +26,7 @@ class ols:
|
||||
conf = public.readFile(self._main_conf_path)
|
||||
data = {}
|
||||
for k in keys:
|
||||
rep = '{}\s+(\w+)'.format(k)
|
||||
rep = r'{}\s+(\w+)'.format(k)
|
||||
tmp = re.search(rep,conf)
|
||||
if tmp:
|
||||
data[k] = tmp.groups(1)
|
||||
@@ -43,7 +43,7 @@ class ols:
|
||||
conf = public.readFile(self._main_conf_path)
|
||||
data = json.loads(get.array)
|
||||
for k in data:
|
||||
rep = '{}\s+(\w+)'.format(k)
|
||||
rep = r'{}\s+(\w+)'.format(k)
|
||||
tmp = re.search(rep,conf)
|
||||
if tmp:
|
||||
conf = re.sub('{}.*'.format(k),'{} {}'.format(k,data[k]),conf)
|
||||
@@ -58,24 +58,24 @@ class ols:
|
||||
data = {}
|
||||
sitename = public.M('sites').where("id=?", (get.id,)).getField('name')
|
||||
conf = public.readFile(self._detail_conf_path.format(sitename))
|
||||
rep = 'expiresByType\s+(.*)'
|
||||
rep = r'expiresByType\s+(.*)'
|
||||
tmp = re.search(rep,conf)
|
||||
|
||||
if tmp:
|
||||
tmp = tmp.groups(1)[0].split(',')
|
||||
for i in tmp:
|
||||
if 'image' in i:
|
||||
rep = 'image\/\*=A(\d+)'
|
||||
rep = r'image\/\*=A(\d+)'
|
||||
data['image'] = re.search(rep,conf).groups(1)[0]
|
||||
print(data['image'])
|
||||
if 'css' in i:
|
||||
rep = 'css=A(\d+)'
|
||||
rep = r'css=A(\d+)'
|
||||
data['css'] = re.search(rep, conf).groups(1)[0]
|
||||
if 'javascript' in i:
|
||||
rep = 'javascript=A(\d+)'
|
||||
rep = r'javascript=A(\d+)'
|
||||
data['javascript'] = re.search(rep, conf).groups(1)[0]
|
||||
if 'font' in i:
|
||||
rep = 'font.*=A(\d+)'
|
||||
rep = r'font.*=A(\d+)'
|
||||
data['font'] = re.search(rep, conf).groups(1)[0]
|
||||
return data
|
||||
|
||||
@@ -92,12 +92,12 @@ class ols:
|
||||
print(self._detail_conf_path.format(sitename))
|
||||
values = json.loads(get.values)
|
||||
for k in values:
|
||||
rep = '{}/[\*\w+=]=A\d+'.format(k)
|
||||
rep = r'{}/[\*\w+=]=A\d+'.format(k)
|
||||
old_cache = re.search(rep,conf)
|
||||
if not old_cache:
|
||||
continue
|
||||
old_cache = old_cache.group()
|
||||
new_cache = re.sub('\d+',values[k],old_cache)
|
||||
new_cache = re.sub(r'\d+',values[k],old_cache)
|
||||
conf = conf.replace(old_cache,new_cache)
|
||||
public.writeFile(self._detail_conf_path.format(sitename),conf)
|
||||
public.serviceReload()
|
||||
@@ -127,13 +127,13 @@ class ols:
|
||||
if tmp:
|
||||
# 获取排除文件
|
||||
tmp = tmp.group()
|
||||
rep = '#\s*excluding.*\n.*\((.*)\)'
|
||||
rep = r'#\s*excluding.*\n.*\((.*)\)'
|
||||
tmp = re.search(rep,tmp)
|
||||
if tmp:
|
||||
data['exclude_file'] = [i+'.php' for i in tmp.groups(1)[0].split('|')]
|
||||
print(data)
|
||||
# 获取缓存时间
|
||||
rep = 'max-age=(\d+)'
|
||||
rep = r'max-age=(\d+)'
|
||||
tmp = re.search(rep,conf)
|
||||
if tmp:
|
||||
data['maxage'] = tmp.groups(1)[0]
|
||||
@@ -154,7 +154,7 @@ class ols:
|
||||
conf = self.get_private_cache_conf(get.id)[0]
|
||||
file = self.get_private_cache_conf(get.id)[1]
|
||||
if 'BTLSCACHE_BEGIN' not in conf:
|
||||
confstr = """#######################BTLSCACHE_BEGIN#######################
|
||||
confstr = r"""#######################BTLSCACHE_BEGIN#######################
|
||||
|
||||
<IfModule LiteSpeed>
|
||||
RewriteEngine on
|
||||
@@ -206,10 +206,10 @@ RewriteRule (.*\.php)?$ - [E=Cache-Control:private]
|
||||
for file in get.exclude_file.split('\n'):
|
||||
exclude_files.append(file.split('.')[0])
|
||||
exclude_file = "|".join(exclude_files)
|
||||
old_exc_rep = 'RewriteCond\s+\%\{REQUEST_URI\}\s+\!/\(.*\)\\\.php\$'
|
||||
new_exc = 'RewriteCond %{REQUEST_URI} !/(' + exclude_file + ')\.php$'
|
||||
old_exc_rep = r'RewriteCond\s+\%\{REQUEST_URI\}\s+\!/\(.*\)\\\.php\$'
|
||||
new_exc = 'RewriteCond %{REQUEST_URI} !/(' + exclude_file + r')\.php$'
|
||||
bt_conf = re.sub(old_exc_rep,new_exc,bt_conf)
|
||||
old_max_age_rep = 'max-age=\d+'
|
||||
old_max_age_rep = r'max-age=\d+'
|
||||
new_max_age = 'max-age={}'.format(int(get.max_age))
|
||||
bt_conf = re.sub(old_max_age_rep,new_max_age,bt_conf)
|
||||
conf = re.sub(bt_conf_rep,bt_conf,conf)
|
||||
@@ -247,11 +247,11 @@ RewriteRule (.*\.php)?$ - [E=Cache-Control:private]
|
||||
conf = public.readFile(path)
|
||||
ap_path = '/www/server/panel/vhost/apache/{}.conf'.format(s['sitename'])
|
||||
ap_conf = public.readFile(ap_path)
|
||||
tmp = re.search('ServerName\s+SSL\.(.*)',ap_conf)
|
||||
tmp = re.search(r'ServerName\s+SSL\.(.*)',ap_conf)
|
||||
s['phpv'] = re.search(phpv_reg,conf).groups(1)[0]
|
||||
s['rundir'] = re.search(rundir_reg.format(s),conf).groups(1)[0]
|
||||
s['ssl_domain'] =tmp.groups(1)[0] if tmp else None
|
||||
s['port'] = re.search('listen\s+(\d+);',conf).groups(1)[0]
|
||||
s['port'] = re.search(r'listen\s+(\d+);',conf).groups(1)[0]
|
||||
return siteinfo
|
||||
|
||||
def _make_args(self):
|
||||
|
||||
+17
-17
@@ -1,10 +1,10 @@
|
||||
# coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2016 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2016 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: zhwen <zhwen@bt.cn>
|
||||
# | Author: zhwen <zhwen@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
import os
|
||||
import time
|
||||
@@ -73,7 +73,7 @@ class one_key_wp:
|
||||
else:
|
||||
self.get_plugin_page()
|
||||
resp = self.__plugin_page_content
|
||||
_ajax_nonce_rep = '"ajax_nonce\\\"\:\\\"(\w+)'
|
||||
_ajax_nonce_rep = '"ajax_nonce\\\"\\:\\\"(\\w+)'
|
||||
rex = re.search(_ajax_nonce_rep, resp)
|
||||
if rex:
|
||||
self.__ajax_nonce = rex.group(1)
|
||||
@@ -130,7 +130,7 @@ class one_key_wp:
|
||||
# hosts = public.readFile('/etc/hosts')
|
||||
# if not hosts:
|
||||
# return False
|
||||
# if not re.search('127.0.0.1\s+{}'.format(self.__domain),hosts):
|
||||
# if not re.search(r'127.0.0.1\s+{}'.format(self.__domain),hosts):
|
||||
# public.writeFile('/etc/hosts','\n127.0.0.1 {}'.format(self.__domain),'a+')
|
||||
|
||||
self.__session_resp = retry(
|
||||
@@ -270,7 +270,7 @@ class one_key_wp:
|
||||
hosts = public.readFile('/etc/hosts')
|
||||
if not hosts:
|
||||
return False
|
||||
if not re.search('127.0.0.1\s+{}'.format(values['site_name']), hosts):
|
||||
if not re.search(r'127.0.0.1\s+{}'.format(values['site_name']), hosts):
|
||||
public.writeFile('/etc/hosts', '\n127.0.0.1 {}'.format(values['site_name']), 'a+')
|
||||
|
||||
self.write_logs("|-Start initializing Wordpress...")
|
||||
@@ -362,7 +362,7 @@ class one_key_wp:
|
||||
def get_update_wp_nonce(self):
|
||||
url = "http://{}/wp-admin/update-core.php".format(self.__domain)
|
||||
# res = self.action_plugin_get(url)
|
||||
_wp_nonce_rep = '"_wpnonce\\\"\svalue=\\\"(\w+)'
|
||||
_wp_nonce_rep = '"_wpnonce\\\"\\svalue=\\\"(\\w+)'
|
||||
# rex = re.search(_wp_nonce_rep,res)
|
||||
# if rex:
|
||||
# self.__wp_nonce = rex.group(1)
|
||||
@@ -414,7 +414,7 @@ class one_key_wp:
|
||||
|
||||
def get_smart_http_expire_form_nonce(self, url):
|
||||
public.writeFile('/tmp/2', str(self.action_plugin_get(url)))
|
||||
smart_http_expire_form_nonce = '"smart_http_expire_form_nonce\\\"\svalue=\\\"(\w+)'
|
||||
smart_http_expire_form_nonce = '"smart_http_expire_form_nonce\\\"\\svalue=\\\"(\\w+)'
|
||||
return self.get_wp_nonce(self.action_plugin_get(url), smart_http_expire_form_nonce)
|
||||
|
||||
def set_nginx_helper(self, values):
|
||||
@@ -557,7 +557,7 @@ class one_key_wp:
|
||||
conf_file = "{}/wp-includes/version.php".format(path)
|
||||
conf = public.readFile(conf_file)
|
||||
try:
|
||||
version = re.search('\$wp_version\s*=\s*[\'\"]{1}([\d\.]*)[\'\"]{1}', conf).groups(1)[0]
|
||||
version = re.search('\\$wp_version\\s*=\\s*[\'\"]{1}([\\d\\.]*)[\'\"]{1}', conf).groups(1)[0]
|
||||
except:
|
||||
version = "00"
|
||||
return version
|
||||
@@ -569,7 +569,7 @@ class one_key_wp:
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36'
|
||||
}
|
||||
result = requests.get(url, headers=headers)
|
||||
result = re.search('Download\s+WordPress\s+([\d\.]+)', result.text)
|
||||
result = re.search(r'Download\s+WordPress\s+([\d\.]+)', result.text)
|
||||
if result:
|
||||
return result.group(1)
|
||||
return "00"
|
||||
@@ -793,13 +793,13 @@ class one_key_wp:
|
||||
rep_domain = r"^(?=^.{3,255}$)[a-zA-Z0-9\_\-][a-zA-Z0-9\_\-]{0,62}(\.[a-zA-Z0-9\_\-][a-zA-Z0-9\_\-]{0,62})+$"
|
||||
values = {}
|
||||
if hasattr(args, 'd_id'):
|
||||
if re.search('\d+', args.d_id):
|
||||
if re.search(r'\d+', args.d_id):
|
||||
values["d_id"] = args.d_id
|
||||
else:
|
||||
return public.return_msg_gettext(False, "Please check if the [{}] format is correct For example: {}",
|
||||
("d_id", "99"))
|
||||
if hasattr(args, 's_id'):
|
||||
if re.search('\d+', args.s_id):
|
||||
if re.search(r'\d+', args.s_id):
|
||||
values["s_id"] = args.s_id
|
||||
else:
|
||||
return public.return_msg_gettext(False, "Please check if the [{}] format is correct For example: {}",
|
||||
@@ -1218,7 +1218,7 @@ class optimize_db:
|
||||
class fast_cgi:
|
||||
|
||||
def get_fastcgi_conf(self, version):
|
||||
conf = """
|
||||
conf = r"""
|
||||
set $skip_cache 0;
|
||||
if ($request_method = POST) {
|
||||
set $skip_cache 1;
|
||||
@@ -1294,7 +1294,7 @@ class fast_cgi:
|
||||
one_key_wp().write_logs("|-Nginx FastCgi cache configuration already exists")
|
||||
print("Nginx FastCgi cache configuration already exists")
|
||||
return public.return_msg_gettext(True, "Nginx FastCgi cache configuration already exists")
|
||||
rep = "http\s*\n\s*{"
|
||||
rep = "http\\s*\n\\s*{"
|
||||
content = re.sub(rep, "http\n\t{" + conf, content)
|
||||
public.writeFile(conf_path, content)
|
||||
|
||||
@@ -1328,7 +1328,7 @@ class fast_cgi:
|
||||
print("Nginx init FastCgi cache configuration already exists")
|
||||
return public.return_msg_gettext(True, "Nginx init FastCgi cache configuration already exists")
|
||||
# content_init = re.sub(r"\$NGINX_BIN -c \$CONFIGFILE", + conf2, content_init)
|
||||
rep2 = "\$NGINX_BIN -c \$CONFIGFILE"
|
||||
rep2 = r"\$NGINX_BIN -c \$CONFIGFILE"
|
||||
content_init = re.sub(rep2, conf2 + " $NGINX_BIN -c $CONFIGFILE", content_init)
|
||||
public.writeFile(init_path, content_init)
|
||||
|
||||
@@ -1366,7 +1366,7 @@ class fast_cgi:
|
||||
print("FastCgi configuration does not exist in website configuration")
|
||||
one_key_wp().write_logs("|-FastCgi configuration does not exist in website configuration, skip")
|
||||
return public.return_msg_gettext(False, "FastCgi configuration does not exist in website configuration")
|
||||
rep = "include\s+enable-php-{}-wpfastcgi.conf;".format(version)
|
||||
rep = r"include\s+enable-php-{}-wpfastcgi.conf;".format(version)
|
||||
conf = re.sub(rep, "include enable-php-{}.conf;".format(version), conf)
|
||||
else:
|
||||
fastcgi_conf = "include enable-php-{}-wpfastcgi.conf;".format(version)
|
||||
@@ -1375,7 +1375,7 @@ class fast_cgi:
|
||||
"|-The FastCgi configuration already exists in the website configuration, skip it")
|
||||
return public.return_msg_gettext(True,
|
||||
"The FastCgi configuration already exists in the website configuration")
|
||||
rep = "include\s+enable-php-{}.conf;".format(version)
|
||||
rep = r"include\s+enable-php-{}.conf;".format(version)
|
||||
conf = re.sub(rep, fastcgi_conf, conf)
|
||||
public.writeFile(conf_path, conf)
|
||||
conf_pass = public.checkWebConfig()
|
||||
|
||||
+5
-5
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2016 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2016 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# | Author: hwliang <hwl@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
import math,string,public,re
|
||||
|
||||
@@ -200,8 +200,8 @@ class Page():
|
||||
def __SetUri(self,request_uri):
|
||||
#构造URI
|
||||
try:
|
||||
request_uri = re.sub("&p=\d+",'&',request_uri)
|
||||
request_uri = re.sub("\?p=\d+",'?',request_uri)
|
||||
request_uri = re.sub(r"&p=\d+",'&',request_uri)
|
||||
request_uri = re.sub(r"\?p=\d+",'?',request_uri)
|
||||
if request_uri.find('&') == -1:
|
||||
if request_uri[-1] != '?': request_uri += '?'
|
||||
else:
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2017 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2017 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# | Author: hwliang <hwl@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
import public,os,json,time
|
||||
class panelApi:
|
||||
|
||||
+9
-65
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2019 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2019 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
@@ -60,8 +60,8 @@ class panelAuth:
|
||||
def check_serverid(self,get):
|
||||
if get.serverid != self.create_serverid(get): return False
|
||||
return True
|
||||
# 旧接口 没有永久版
|
||||
def get_plugin_price2(self, get):
|
||||
|
||||
def get_plugin_price(self, get):
|
||||
try:
|
||||
userPath = 'data/userInfo.json'
|
||||
if not 'pluginName' in get and not 'product_id' in get: return public.return_msg_gettext(False,'Parameter ERROR!')
|
||||
@@ -71,7 +71,7 @@ class panelAuth:
|
||||
params['product_id'] = self.get_plugin_info(get.pluginName)['id']
|
||||
else:
|
||||
params['product_id'] = get.product_id
|
||||
data = self.send_cloud('{}/api/product/prices'.format(self.__official_url), params)
|
||||
data = self.send_cloud('{}/api/product/pricesV3'.format(self.__official_url), params)
|
||||
if not data:
|
||||
return public.return_msg_gettext(False, 'Please log in to your aaPanel account on the panel first!')
|
||||
if not data['success']:
|
||||
@@ -82,61 +82,7 @@ class panelAuth:
|
||||
except:
|
||||
del(session['get_product_list'])
|
||||
return public.return_msg_gettext(False,'Syncing information, please try again!\n {}',(public.get_error_info(),))
|
||||
|
||||
# 获取永久版信息
|
||||
def get_plugin_price3(self, get):
|
||||
try:
|
||||
userPath = 'data/userInfo.json'
|
||||
if not 'pluginName' in get and not 'product_id' in get:
|
||||
return public.return_msg_gettext(False,'Parameter ERROR!')
|
||||
if not os.path.exists(userPath):
|
||||
return public.return_msg_gettext(False,'Please login with account first')
|
||||
params = {}
|
||||
if not hasattr(get,'product_id'):
|
||||
params['product_id'] = self.get_plugin_info(get.pluginName)['id']
|
||||
else:
|
||||
params['product_id'] = get.product_id
|
||||
|
||||
data = self.send_cloud('{}/api/product/pricesV2'.format(self.__official_url), params)
|
||||
|
||||
if not data:
|
||||
return public.return_msg_gettext(False, 'Please log in to your aaPanel account on the panel first!')
|
||||
if not data['success']:
|
||||
return public.return_msg_gettext(False,data['msg'])
|
||||
return data['res']
|
||||
except:
|
||||
# del(session['get_product_list'])
|
||||
return public.return_msg_gettext(False,'Syncing information, please try again!\n {}',(public.get_error_info(),))
|
||||
|
||||
# 获取价格列表 新增多机购买
|
||||
def get_plugin_price(self, get):
|
||||
try:
|
||||
userPath = 'data/userInfo.json'
|
||||
if not 'pluginName' in get and not 'product_id' in get:
|
||||
return public.return_msg_gettext(False, 'Parameter ERROR!')
|
||||
if not os.path.exists(userPath):
|
||||
return public.return_msg_gettext(False, 'Please login with account first')
|
||||
params = {}
|
||||
if not hasattr(get, 'product_id'):
|
||||
params['product_id'] = self.get_plugin_info(get.pluginName)['id']
|
||||
else:
|
||||
params['product_id'] = get.product_id
|
||||
|
||||
data = self.send_cloud('{}/api/product/pricesV3'.format(self.__official_url), params)
|
||||
|
||||
if not data:
|
||||
return public.return_msg_gettext(False, 'Please log in to your aaPanel account on the panel first!')
|
||||
if not data['success']:
|
||||
return public.return_msg_gettext(False, data['msg'])
|
||||
return data['res']
|
||||
except Exception as ex:
|
||||
public.print_log("获取价格报错 {}".format(ex))
|
||||
# del(session['get_product_list'])
|
||||
return public.return_msg_gettext(False, 'Syncing information, please try again!\n {}',
|
||||
(public.get_error_info(),))
|
||||
|
||||
|
||||
|
||||
|
||||
def get_plugin_info(self,pluginName):
|
||||
data = self.get_business_plugin(None)
|
||||
if not data: return None
|
||||
@@ -183,7 +129,6 @@ class panelAuth:
|
||||
return public.return_msg_gettext(False, data['res'])
|
||||
return data['res']
|
||||
|
||||
|
||||
def get_stripe_session_id(self,get):
|
||||
|
||||
params = {}
|
||||
@@ -413,8 +358,7 @@ class panelAuth:
|
||||
data = self.send_cloud('{}/api/user/productAuthorizes'.format(self.__official_url), params)
|
||||
if not data:
|
||||
return []
|
||||
if not data['success']:
|
||||
return []
|
||||
if not data['success']: return []
|
||||
data = data['res']
|
||||
# return [i for i in data['list'] if i['status'] != 'activated' and get.pid == i['product_id']]
|
||||
res = list()
|
||||
@@ -444,7 +388,7 @@ class panelAuth:
|
||||
if hasattr(get,'coupon_id') and get.pay_channel == '10':
|
||||
params['coupon_id'] = get.coupon_id
|
||||
data = self.send_cloud('{}/api/authorize/product/renew'.format(self.__official_url), params)
|
||||
# public.print_log('############ 续费接口 {}'.format(data))
|
||||
|
||||
if not data['success']:
|
||||
data['res'] = 'Invalid authorize OR authorize not found!'
|
||||
return data
|
||||
|
||||
+25
-5
@@ -1,10 +1,10 @@
|
||||
# coding: utf-8
|
||||
# -------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# ------------------------------
|
||||
@@ -422,10 +422,30 @@ class backup:
|
||||
def backup_site(self, siteName, save=3, exclude=[], echo_id=None):
|
||||
try:
|
||||
self.echo_start()
|
||||
find = public.M('sites').where('name=?', (siteName,)).field('id,path').find()
|
||||
find = public.M('sites').where('name=?', (siteName,)).field('id,path,project_type').find()
|
||||
public.print_log(find)
|
||||
if not find:
|
||||
if not find or not isinstance(find, dict):
|
||||
raise Exception(' The directory for does not exist')
|
||||
|
||||
# Wordpress
|
||||
if find['project_type'] == 'WP2':
|
||||
import PluginLoader
|
||||
if PluginLoader.get_auth_state() < 1:
|
||||
self.echo_info(public.get_msg_gettext('Authorization is invalid or expired'))
|
||||
return None
|
||||
|
||||
try:
|
||||
from wp_toolkit import wpbackup
|
||||
bak_info = wpbackup(find['id']).backup_full_get_data()
|
||||
self.echo_info(public.get_msg_gettext('Backup wordpress [{}] successfully', (siteName,)))
|
||||
self.echo_end()
|
||||
return bak_info.bak_file
|
||||
except Exception as e:
|
||||
public.print_error()
|
||||
self.echo_info(str(e))
|
||||
self.echo_end()
|
||||
return None
|
||||
|
||||
spath = find['path']
|
||||
pid = find['id']
|
||||
fname = 'web_{}_{}.tar.gz'.format(siteName, public.format_date("%Y%m%d_%H%M%S"))
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2017 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2017 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
@@ -32,8 +32,8 @@ class Controller:
|
||||
if args['mod_name'] in ['base']: return public.return_status_code(1000,'错误的调用!')
|
||||
public.exists_args('def_name,mod_name',args)
|
||||
if args['def_name'].find('__') != -1: return public.return_status_code(1000,'调用的方法名称中不能包含“__”字符')
|
||||
if not re.match(r"^\w+$",args['mod_name']): return public.return_status_code(1000,'调用的模块名称中不能包含\w以外的字符')
|
||||
if not re.match(r"^\w+$",args['def_name']): return public.return_status_code(1000,'调用的方法名称中不能包含\w以外的字符')
|
||||
if not re.match(r"^\w+$",args['mod_name']): return public.return_status_code(1000,r'调用的模块名称中不能包含\w以外的字符')
|
||||
if not re.match(r"^\w+$",args['def_name']): return public.return_status_code(1000,r'调用的方法名称中不能包含\w以外的字符')
|
||||
except:
|
||||
return public.get_error_object()
|
||||
# 参数处理
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2017 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2017 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
@@ -32,8 +32,8 @@ class DatabaseController:
|
||||
if args['mod_name'] in ['base']: return public.return_status_code(1000,'Bad call!')
|
||||
public.exists_args('def_name,mod_name',args)
|
||||
if args['def_name'].find('__') != -1: return public.return_status_code(1000,'The called method name cannot contain the "__" character')
|
||||
if not re.match(r"^\w+$",args['mod_name']): return public.return_status_code(1000,'The called module name cannot contain characters other than \w')
|
||||
if not re.match(r"^\w+$",args['def_name']): return public.return_status_code(1000,'The called module name cannot contain characters other than \w')
|
||||
if not re.match(r"^\w+$",args['mod_name']): return public.return_status_code(1000,r'The called module name cannot contain characters other than \w')
|
||||
if not re.match(r"^\w+$",args['def_name']): return public.return_status_code(1000,r'The called module name cannot contain characters other than \w')
|
||||
except:
|
||||
return public.get_error_object()
|
||||
# 参数处理
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 沐落 <cjx@bt.cn>
|
||||
# | Author: 沐落 <cjx@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
import public,os,sys,json,time,random
|
||||
import requests
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
@@ -29,9 +29,9 @@ class HttpProxy:
|
||||
'''
|
||||
headers = {}
|
||||
for h in p_res.headers.keys():
|
||||
if h in ['Content-Encoding','Transfer-Encoding']: continue
|
||||
if h in ['content-encoding', 'Content-Encoding', 'transfer-encoding', 'Transfer-Encoding']: continue
|
||||
headers[h] = p_res.headers[h]
|
||||
if h in ['Location']:
|
||||
if h in ['location', 'Location']:
|
||||
|
||||
if headers[h].find('phpmyadmin_') != -1:
|
||||
if not self._pma_path:
|
||||
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 沐落 <cjx@bt.cn>
|
||||
# | Author: 沐落 <cjx@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
import os,sys,json,time,re
|
||||
setup_path = '/www/server/panel'
|
||||
@@ -763,7 +763,7 @@ class panelLets:
|
||||
tlist = []
|
||||
for siteName in old_list:
|
||||
if not siteName in cron_list: tlist.append(siteName)
|
||||
print(public.get_msg_gettext('|-[{}] Not expired or the site does not use the Let\s Encrypt certificate.',(','.join(tlist),)))
|
||||
print(public.get_msg_gettext(r'|-[{}] Not expired or the site does not use the Let\s Encrypt certificate.',(','.join(tlist),)))
|
||||
print(public.get_msg_gettext('|-{} Waiting for renewal [{}].',(time.strftime('%Y-%m-%d %X',time.localtime()),str(len(cron_list)))))
|
||||
|
||||
sucess_list = []
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <2020-05-18>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: cjxin <cjxin@bt.cn>
|
||||
# Author: cjxin <cjxin@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
# 备份
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: cjxin <cjxin@bt.cn>
|
||||
# Author: cjxin <cjxin@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
# 面板其他模型新增功能
|
||||
|
||||
@@ -0,0 +1,274 @@
|
||||
# coding: utf-8
|
||||
# -------------------------------------------------------------------
|
||||
# aaPanel
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: cjxin <cjxin@aapanel.com>
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# 备份
|
||||
# ------------------------------
|
||||
import os, sys, re, json, shutil, psutil, time
|
||||
from panelModel.base import panelBase
|
||||
import public, config, panelTask
|
||||
|
||||
try:
|
||||
from BTPanel import cache
|
||||
except:pass
|
||||
|
||||
class main(panelBase):
|
||||
__table = 'task_list'
|
||||
# public.check_database_field("ssl_data.db","ssl_info")
|
||||
task_obj = panelTask.bt_task()
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
"""
|
||||
@name 获取面板日志
|
||||
"""
|
||||
def get_update_logs(self,get):
|
||||
try:
|
||||
|
||||
skey = 'panel_update_logs'
|
||||
res = cache.get(skey)
|
||||
if res: return res
|
||||
|
||||
res = public.httpPost('https://www.bt.cn/Api/getUpdateLogs?type=Linux',{})
|
||||
|
||||
start_index = res.find('(') + 1
|
||||
end_index = res.rfind(')')
|
||||
json_data = res[start_index:end_index]
|
||||
|
||||
res = json.loads(json_data)
|
||||
cache.set(skey,res,60)
|
||||
except:
|
||||
res = []
|
||||
|
||||
return res
|
||||
|
||||
def get_public_config(self, args):
|
||||
"""
|
||||
@name 获取公共配置
|
||||
"""
|
||||
public.print_log("error 3366666 原始方法: ")
|
||||
_config_obj = config.config()
|
||||
data = _config_obj.get_config(args)
|
||||
|
||||
data['task_list'] = self.task_obj.get_task_lists(args)
|
||||
data['task_count'] = public.M('tasks').where("status!=?", ('1',)).count()
|
||||
data['get_pd'] = self.get_pd(args)
|
||||
data['ipv6'] = ''
|
||||
if _config_obj.get_ipv6_listen(None): data['ipv6'] = 'checked'
|
||||
data['is_local'] = ''
|
||||
if public.is_local(): data['is_local'] = 'checked'
|
||||
|
||||
if data['get_pd'] and data['get_pd'][2] != -1:
|
||||
time_diff = (data['get_pd'][2]-int(time.time())) % (365*86400)
|
||||
data['active_pro_time'] = int(time.time()) - (365*86400 - time_diff)
|
||||
else:
|
||||
data['active_pro_time'] = 0
|
||||
data['status_code'] = _config_obj.get_not_auth_status()
|
||||
if os.path.exists('/www/server/panel/config/api.json'):
|
||||
try:
|
||||
res = json.loads(public.readFile('/www/server/panel/config/api.json'))
|
||||
data['api'] = 'checked' if res['open'] else ''
|
||||
except:
|
||||
public.ExecShell('rm -f /www/server/panel/config/api.json')
|
||||
data['api'] = ''
|
||||
else:
|
||||
data['api'] = ''
|
||||
return data
|
||||
|
||||
def get_pd(self, get):
|
||||
from BTPanel import cache
|
||||
tmp = -1
|
||||
try:
|
||||
import panelPlugin
|
||||
# get = public.dict_obj()
|
||||
# get.init = 1
|
||||
tmp1 = panelPlugin.panelPlugin().get_cloud_list(get)
|
||||
except:
|
||||
tmp1 = None
|
||||
if tmp1:
|
||||
tmp = tmp1[public.to_string([112, 114, 111])]
|
||||
ltd = tmp1.get('ltd', -1)
|
||||
else:
|
||||
ltd = -1
|
||||
tmp4 = cache.get(
|
||||
public.to_string([112, 95, 116, 111, 107, 101, 110]))
|
||||
if tmp4:
|
||||
tmp_f = public.to_string([47, 116, 109, 112, 47]) + tmp4
|
||||
if not os.path.exists(tmp_f): public.writeFile(tmp_f, '-1')
|
||||
tmp = public.readFile(tmp_f)
|
||||
if tmp: tmp = int(tmp)
|
||||
if not ltd: ltd = -1
|
||||
if tmp == None: tmp = -1
|
||||
if ltd < 1:
|
||||
if ltd == -2:
|
||||
tmp3 = public.to_string([
|
||||
60, 115, 112, 97, 110, 32, 99, 108, 97, 115, 115, 61, 34,
|
||||
98, 116, 108, 116, 100, 45, 103, 114, 97, 121, 34, 62, 60,
|
||||
115, 112, 97, 110, 32, 115, 116, 121, 108, 101, 61, 34, 99,
|
||||
111, 108, 111, 114, 58, 32, 35, 102, 99, 54, 100, 50, 54,
|
||||
59, 102, 111, 110, 116, 45, 119, 101, 105, 103, 104, 116,
|
||||
58, 32, 98, 111, 108, 100, 59, 109, 97, 114, 103, 105, 110,
|
||||
45, 114, 105, 103, 104, 116, 58, 53, 112, 120, 34, 62,
|
||||
24050, 36807, 26399, 60, 47, 115, 112, 97, 110, 62, 60, 97,
|
||||
32, 99, 108, 97, 115, 115, 61, 34, 98, 116, 108, 105, 110,
|
||||
107, 34, 32, 111, 110, 99, 108, 105, 99, 107, 61, 34, 98,
|
||||
116, 46, 115, 111, 102, 116, 46, 117, 112, 100, 97, 116,
|
||||
97, 95, 108, 116, 100, 40, 41, 34, 62, 32493, 36153, 60,
|
||||
47, 97, 62, 60, 47, 115, 112, 97, 110, 62
|
||||
])
|
||||
elif tmp == -1:
|
||||
tmp3 = public.to_string([
|
||||
60, 115, 112, 97, 110, 32, 99, 108, 97, 115, 115, 61, 34,
|
||||
98, 116, 112, 114, 111, 45, 102, 114, 101, 101, 34, 32,
|
||||
111, 110, 99, 108, 105, 99, 107, 61, 34, 98, 116, 46, 115,
|
||||
111, 102, 116, 46, 117, 112, 100, 97, 116, 97, 95, 99, 111,
|
||||
109, 109, 101, 114, 99, 105, 97, 108, 95, 118, 105, 101,
|
||||
119, 40, 41, 34, 32, 116, 105, 116, 108, 101, 61, 34,
|
||||
28857, 20987, 21319, 32423, 21040, 21830, 19994, 29256, 34,
|
||||
62, 20813, 36153, 29256, 60, 47, 115, 112, 97, 110, 62
|
||||
])
|
||||
elif tmp == -2:
|
||||
tmp3 = public.to_string([
|
||||
60, 115, 112, 97, 110, 32, 99, 108, 97, 115, 115, 61, 34,
|
||||
98, 116, 112, 114, 111, 45, 103, 114, 97, 121, 34, 62, 60,
|
||||
115, 112, 97, 110, 32, 115, 116, 121, 108, 101, 61, 34, 99,
|
||||
111, 108, 111, 114, 58, 32, 35, 102, 99, 54, 100, 50, 54,
|
||||
59, 102, 111, 110, 116, 45, 119, 101, 105, 103, 104, 116,
|
||||
58, 32, 98, 111, 108, 100, 59, 109, 97, 114, 103, 105, 110,
|
||||
45, 114, 105, 103, 104, 116, 58, 53, 112, 120, 34, 62,
|
||||
24050, 36807, 26399, 60, 47, 115, 112, 97, 110, 62, 60, 97,
|
||||
32, 99, 108, 97, 115, 115, 61, 34, 98, 116, 108, 105, 110,
|
||||
107, 34, 32, 111, 110, 99, 108, 105, 99, 107, 61, 34, 98,
|
||||
116, 46, 115, 111, 102, 116, 46, 117, 112, 100, 97, 116,
|
||||
97, 95, 112, 114, 111, 40, 41, 34, 62, 32493, 36153, 60,
|
||||
47, 97, 62, 60, 47, 115, 112, 97, 110, 62
|
||||
])
|
||||
if tmp >= 0 and ltd in [-1, -2]:
|
||||
if tmp == 0:
|
||||
tmp2 = public.to_string([27704, 20037, 25480, 26435])
|
||||
tmp3 = public.to_string([
|
||||
60, 115, 112, 97, 110, 32, 99, 108, 97, 115, 115, 61,
|
||||
34, 98, 116, 112, 114, 111, 34, 62, 123, 48, 125, 60,
|
||||
115, 112, 97, 110, 32, 115, 116, 121, 108, 101, 61, 34,
|
||||
99, 111, 108, 111, 114, 58, 32, 35, 102, 99, 54, 100,
|
||||
50, 54, 59, 102, 111, 110, 116, 45, 119, 101, 105, 103,
|
||||
104, 116, 58, 32, 98, 111, 108, 100, 59, 34, 62, 123,
|
||||
49, 125, 60, 47, 115, 112, 97, 110, 62, 60, 47, 115,
|
||||
112, 97, 110, 62
|
||||
]).format(
|
||||
public.to_string([21040, 26399, 26102, 38388, 65306]),
|
||||
tmp2)
|
||||
else:
|
||||
tmp2 = time.strftime(
|
||||
public.to_string([37, 89, 45, 37, 109, 45, 37, 100]),
|
||||
time.localtime(tmp))
|
||||
tmp3 = public.to_string([
|
||||
60, 115, 112, 97, 110, 32, 99, 108, 97, 115, 115, 61,
|
||||
34, 98, 116, 112, 114, 111, 34, 62, 21040, 26399,
|
||||
26102, 38388, 65306, 60, 115, 112, 97, 110, 32, 115,
|
||||
116, 121, 108, 101, 61, 34, 99, 111, 108, 111, 114, 58,
|
||||
32, 35, 102, 99, 54, 100, 50, 54, 59, 102, 111, 110,
|
||||
116, 45, 119, 101, 105, 103, 104, 116, 58, 32, 98, 111,
|
||||
108, 100, 59, 109, 97, 114, 103, 105, 110, 45, 114,
|
||||
105, 103, 104, 116, 58, 53, 112, 120, 34, 62, 123, 48,
|
||||
125, 60, 47, 115, 112, 97, 110, 62, 60, 97, 32, 99,
|
||||
108, 97, 115, 115, 61, 34, 98, 116, 108, 105, 110, 107,
|
||||
34, 32, 111, 110, 99, 108, 105, 99, 107, 61, 34, 98,
|
||||
116, 46, 115, 111, 102, 116, 46, 117, 112, 100, 97,
|
||||
116, 97, 95, 112, 114, 111, 40, 41, 34, 62, 32493,
|
||||
36153, 60, 47, 97, 62, 60, 47, 115, 112, 97, 110, 62
|
||||
]).format(tmp2)
|
||||
else:
|
||||
tmp3 = public.to_string([
|
||||
60, 115, 112, 97, 110, 32, 99, 108, 97, 115, 115, 61, 34,
|
||||
98, 116, 108, 116, 100, 45, 103, 114, 97, 121, 34, 32, 111,
|
||||
110, 99, 108, 105, 99, 107, 61, 34, 98, 116, 46, 115, 111,
|
||||
102, 116, 46, 117, 112, 100, 97, 116, 97, 95, 108, 116,
|
||||
100, 40, 41, 34, 32, 116, 105, 116, 108, 101, 61, 34,
|
||||
28857, 20987, 21319, 32423, 21040, 20225, 19994, 29256, 34,
|
||||
62, 20813, 36153, 29256, 60, 47, 115, 112, 97, 110, 62
|
||||
])
|
||||
else:
|
||||
tmp3 = public.to_string([
|
||||
60, 115, 112, 97, 110, 32, 99, 108, 97, 115, 115, 61, 34, 98,
|
||||
116, 108, 116, 100, 34, 62, 21040, 26399, 26102, 38388, 65306,
|
||||
60, 115, 112, 97, 110, 32, 115, 116, 121, 108, 101, 61, 34, 99,
|
||||
111, 108, 111, 114, 58, 32, 35, 102, 99, 54, 100, 50, 54, 59,
|
||||
102, 111, 110, 116, 45, 119, 101, 105, 103, 104, 116, 58, 32,
|
||||
98, 111, 108, 100, 59, 109, 97, 114, 103, 105, 110, 45, 114,
|
||||
105, 103, 104, 116, 58, 53, 112, 120, 34, 62, 123, 125, 60, 47,
|
||||
115, 112, 97, 110, 62, 60, 97, 32, 99, 108, 97, 115, 115, 61,
|
||||
34, 98, 116, 108, 105, 110, 107, 34, 32, 111, 110, 99, 108,
|
||||
105, 99, 107, 61, 34, 98, 116, 46, 115, 111, 102, 116, 46, 117,
|
||||
112, 100, 97, 116, 97, 95, 108, 116, 100, 40, 41, 34, 62,
|
||||
32493, 36153, 60, 47, 97, 62, 60, 47, 115, 112, 97, 110, 62
|
||||
]).format(
|
||||
time.strftime(
|
||||
public.to_string([37, 89, 45, 37, 109, 45, 37, 100]),
|
||||
time.localtime(ltd)))
|
||||
|
||||
return tmp3, tmp, ltd
|
||||
|
||||
@staticmethod
|
||||
def set_backup_path(get):
|
||||
try:
|
||||
backup_path = get.backup_path.strip().rstrip("/")
|
||||
except AttributeError:
|
||||
return public.returnMsg(False, "参数错误")
|
||||
|
||||
if not os.path.exists(backup_path):
|
||||
return public.returnMsg(False, "指定目录不存在")
|
||||
|
||||
if backup_path[-1] == "/":
|
||||
backup_path = backup_path[:-1]
|
||||
|
||||
import files
|
||||
try:
|
||||
from BTPanel import session
|
||||
except:
|
||||
session = None
|
||||
fs = files.files()
|
||||
|
||||
if not fs.CheckDir(get.backup_path):
|
||||
return public.returnMsg(False, '不能使用系统关键目录作为默认备份目录')
|
||||
if session is not None:
|
||||
session['config']['backup_path'] = os.path.join('/', backup_path)
|
||||
db_backup = backup_path + '/database'
|
||||
site_backup = backup_path + '/site'
|
||||
|
||||
if not os.path.exists(db_backup):
|
||||
try:
|
||||
os.makedirs(db_backup, 384)
|
||||
except:
|
||||
public.ExecShell('mkdir -p ' + db_backup)
|
||||
|
||||
if not os.path.exists(site_backup):
|
||||
try:
|
||||
os.makedirs(site_backup, 384)
|
||||
except:
|
||||
public.ExecShell('mkdir -p ' + site_backup)
|
||||
|
||||
public.M('config').where("id=?", ('1',)).save('backup_path', (get.backup_path,))
|
||||
public.WriteLog('TYPE_PANEL', 'PANEL_SET_SUCCESS', (get.backup_path,))
|
||||
|
||||
public.restart_panel()
|
||||
return public.returnMsg(True, "设置成功")
|
||||
|
||||
def get_soft_status(self,get):
|
||||
if not hasattr(get,'name'): return public.returnMsg(False,'参数错误')
|
||||
name = get.name.strip()
|
||||
if name == 'sqlite':
|
||||
return public.returnMsg(True,'符合!')
|
||||
if os.path.exists('/www/server/{}'.format(name)) and len(os.listdir('/www/server/{}'.format(name))) > 2:
|
||||
return public.returnMsg(True,'符合!')
|
||||
if name == ['mysql','pgsql','sqlserver','mongodb','redis']:
|
||||
count = public.M('database_servers').where("LOWER(db_type)=LOWER(?)", (name,)).count()
|
||||
if count > 0: return public.returnMsg(True,'符合!')
|
||||
return public.returnMsg(False,'不符合!')
|
||||
+23
-10
@@ -2,9 +2,9 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Windows面板
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 沐落 <cjx@bt.cn>
|
||||
# | Author: 沐落 <cjx@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
import re,os,sys,public
|
||||
@@ -43,7 +43,8 @@ class panelMssql:
|
||||
try:
|
||||
import pymssql
|
||||
except :
|
||||
os.system("btpip install pymssql==2.1.4")
|
||||
os.system("btpip install pymssql==2.3.0")
|
||||
# os.system("btpip install pymssql==2.1.4")
|
||||
import pymssql
|
||||
|
||||
|
||||
@@ -53,17 +54,29 @@ class panelMssql:
|
||||
self.__DB_PORT = self.get_port()
|
||||
|
||||
try:
|
||||
|
||||
if self.__DB_CLOUD:
|
||||
self.__DB_CONN = pymssql.connect(server = self.__DB_HOST, port= str(self.__DB_PORT),user=self.__DB_USER,password=self.__DB_PASS,database = None,login_timeout = 30,timeout = 0,autocommit = True)
|
||||
|
||||
if self.__DB_CLOUD:
|
||||
try:
|
||||
self.__DB_CONN = pymssql.connect(server=self.__DB_HOST, port=str(self.__DB_PORT),
|
||||
user=self.__DB_USER,
|
||||
password=self.__DB_PASS, database=None, login_timeout=30,
|
||||
timeout=0, autocommit=True, charset="CP936", tds_version='7.0')
|
||||
except:
|
||||
self.__DB_ERR = 'Failed to connect to database! Check that the remote database information is correct'
|
||||
return False
|
||||
# self.__DB_CONN = pymssql.connect(server=self.__DB_HOST, port=str(self.__DB_PORT),
|
||||
# user=self.__DB_USER,
|
||||
# password=self.__DB_PASS, database=None, login_timeout=30,
|
||||
# timeout=0, autocommit=True, charset="CP936", tds_version='7.0')
|
||||
else:
|
||||
self.__DB_CONN = pymssql.connect(server = self.__DB_HOST, port= str(self.__DB_PORT),login_timeout = 30,timeout = 0,autocommit = True)
|
||||
self.__DB_CUR = self.__DB_CONN.cursor() #将数据库连接信息,赋值给cur。
|
||||
self.__DB_CUR = self.__DB_CONN.cursor() #将数据库连接信息,赋值给cur。
|
||||
self.__DB_CONN = pymssql.connect(server=self.__DB_HOST, port=str(self.__DB_PORT), login_timeout=30,
|
||||
timeout=0, autocommit=True, charset="CP936", tds_version='7.0')
|
||||
self.__DB_CUR = self.__DB_CONN.cursor() # 将数据库连接信息,赋值给cur。
|
||||
self.__DB_CUR = self.__DB_CONN.cursor() # 将数据库连接信息,赋值给cur。
|
||||
if self.__DB_CUR:
|
||||
return True
|
||||
else:
|
||||
self.__DB_ERR = '连接数据库失败,请检查是否安装SQL Server'
|
||||
self.__DB_ERR = 'Failed to connect to the database, please check whether SQL Server is installed'
|
||||
return False
|
||||
except Exception as ex:
|
||||
self.__DB_ERR = public.get_error_info()
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# | Author: hwliang <hwl@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
import re,os,sys,public
|
||||
|
||||
+9
-9
@@ -1,10 +1,10 @@
|
||||
#coding:utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# | Author: hwliang <hwl@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
# +-------------------------------------------------------------------
|
||||
@@ -199,18 +199,18 @@ class panelPHP:
|
||||
# if o_pma_root:
|
||||
# if not os.path.exists(pma_root):
|
||||
# os.makedirs(pma_root)
|
||||
# public.ExecShell("\cp -arf {}/* {}/".format(o_pma_root,pma_root))
|
||||
# public.ExecShell(r"\cp -arf {}/* {}/".format(o_pma_root,pma_root))
|
||||
# public.ExecShell("chown -R www:www {}".format(pma_root))
|
||||
# public.ExecShell("chmod -R 700 {}".format(pma_root))
|
||||
# public.ExecShell("\cp -arf {} {}".format(pma_version_f1,pma_version_f2))
|
||||
# public.ExecShell(r"\cp -arf {} {}".format(pma_version_f1,pma_version_f2))
|
||||
# index = public.readFile(pma_root + '/index.php')
|
||||
# if index:
|
||||
# if index.find("use PhpMyAdmin\\Util") != -1:
|
||||
# resp = "use PhpMyAdmin\\Util;\nif(function_exists('opcache_invalidate')) opcache_invalidate('/www/server/phpmyadmin/pma/config.inc.php');"
|
||||
# index = index.replace("use PhpMyAdmin\\Util;",resp)
|
||||
# elif index.find("use PMA\libraries\LanguageManager;") != -1:
|
||||
# resp = "use PMA\libraries\LanguageManager;\nif(function_exists('opcache_invalidate')) opcache_invalidate('/www/server/phpmyadmin/pma/config.inc.php');"
|
||||
# index = index.replace("use PMA\libraries\LanguageManager;",resp)
|
||||
# elif index.find(r"use PMA\libraries\LanguageManager;") != -1:
|
||||
# resp = "use PMA\\libraries\\LanguageManager;\nif(function_exists('opcache_invalidate')) opcache_invalidate('/www/server/phpmyadmin/pma/config.inc.php');"
|
||||
# index = index.replace(r"use PMA\libraries\LanguageManager;",resp)
|
||||
# elif index.find("require_once 'libraries/common.inc.php';") != -1:
|
||||
# resp = "if(function_exists('opcache_invalidate')) opcache_invalidate('/www/server/phpmyadmin/pma/config.inc.php');\nrequire_once 'libraries/common.inc.php';"
|
||||
# index = index.replace("require_once 'libraries/common.inc.php';",resp)
|
||||
@@ -364,7 +364,7 @@ class panelPHP:
|
||||
# dst_path = '/www/server/adminer'
|
||||
# if os.path.exists(src_path):
|
||||
# if not os.path.exists(dst_path): os.makedirs(dst_path)
|
||||
# public.ExecShell("\cp -arf {}/* {}/".format(src_path, dst_path))
|
||||
# public.ExecShell(r"\cp -arf {}/* {}/".format(src_path, dst_path))
|
||||
# public.ExecShell("chown -R www:www {}".format(dst_path))
|
||||
# public.ExecShell("chmod -R 700 {}".format(dst_path))
|
||||
# public.ExecShell("rm -rf {}".format(src_path))
|
||||
|
||||
+609
-152
@@ -1,36 +1,83 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
import public,os,sys,json,time,psutil,py_compile,re
|
||||
from BTPanel import session,cache,send_file
|
||||
import public
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import time
|
||||
import psutil
|
||||
import re
|
||||
import shutil
|
||||
import requests
|
||||
from BTPanel import session, cache, send_file
|
||||
|
||||
|
||||
if sys.version_info[0] == 3: from importlib import reload
|
||||
|
||||
|
||||
class mget: pass
|
||||
|
||||
|
||||
class panelPlugin:
|
||||
__isTable = None
|
||||
__install_path = None
|
||||
__tasks = None
|
||||
__list = 'data/list.json'
|
||||
__type = 'data/type.json'
|
||||
__index = 'config/index.json'
|
||||
__link = 'config/link.json'
|
||||
__product_list = None
|
||||
__plugin_list = None
|
||||
__exists_names = {}
|
||||
__plugin_s_list = []
|
||||
|
||||
__official_url = 'https://www.aapanel.com'
|
||||
# __official_url = 'http://dev.aapanel.com'
|
||||
pids = None
|
||||
ROWS = 15
|
||||
|
||||
def __init__(self):
|
||||
self.__isTable = None
|
||||
self.__tasks = None
|
||||
self.__product_list = None
|
||||
self.__plugin_list = None
|
||||
self.__exists_names = {}
|
||||
self.__plugin_s_list = []
|
||||
self.__plugin_info = None
|
||||
self.__plugin_name = None
|
||||
self.__plugin_object = None
|
||||
self.__plugin_list = None
|
||||
self.__panel_path = '/www/server/panel'
|
||||
self.__plugin_path = self.__panel_path + '/plugin/'
|
||||
self.__plugin_save_file = self.__panel_path + '/data/plugin_bin.pl'
|
||||
self.__api_root_url = self.__official_url + '/api'
|
||||
self.__api_url = self.__api_root_url + '/panel/get_plugin_list'
|
||||
self.__download_url = self.__api_root_url + '/panel/download_plugin'
|
||||
self.__download_d_main_url = self.__api_root_url + '/panel/download_plugin_main'
|
||||
self._check_url = self.__api_root_url + '/panel/get_soft_list_status'
|
||||
self._unbinding_url = self.__api_root_url + '/panel/get_unbinding'
|
||||
self.__tmp_path = self.__panel_path + '/temp/'
|
||||
self.__plugin_timeout = 3600
|
||||
self.__is_php = False
|
||||
self.__install_opt = 'i'
|
||||
self.__pid = 0
|
||||
self.__path_error = self.__panel_path + '/data/error_pl.pl'
|
||||
self.__error_html = '/www/server/panel/BTPanel/templates/default/block_error.html'
|
||||
self.__sub_rules = []
|
||||
self.__replace_rule = []
|
||||
|
||||
self.pids = None
|
||||
self.ROWS = 15
|
||||
|
||||
self.__install_path = '/www/server/panel/plugin'
|
||||
|
||||
#检查依赖
|
||||
if not self.__tasks:
|
||||
try:
|
||||
self.__tasks = public.M('tasks').where("status!=?", ('1',)).field('status,name').select()
|
||||
except:
|
||||
self.__tasks = []
|
||||
|
||||
if not os.path.exists(self.__tmp_path):
|
||||
os.makedirs(self.__tmp_path, 0o755)
|
||||
|
||||
# 检查依赖
|
||||
def check_deps(self,get):
|
||||
cacheKey = 'plugin_lib_list'
|
||||
if not 'force' in get:
|
||||
@@ -79,11 +126,11 @@ class panelPlugin:
|
||||
return True
|
||||
|
||||
#检查依赖
|
||||
def check_dependnet(self,dependnet):
|
||||
if not dependnet: return True
|
||||
dependnets = dependnet.split(',')
|
||||
def check_dependent(self,dependent):
|
||||
if not dependent: return True
|
||||
dependents = dependent.split(',')
|
||||
status = True
|
||||
for dep in dependnets:
|
||||
for dep in dependents:
|
||||
if not dep: continue
|
||||
if dep.find('|') != -1:
|
||||
names = dep.split('|')
|
||||
@@ -137,7 +184,7 @@ class panelPlugin:
|
||||
if not self.check_mutex(pluginInfo['mutex']): return public.return_msg_gettext(False, 'Please uninstall [{}] first',
|
||||
(self.mutex_title,))
|
||||
if not hasattr(get, 'id'):
|
||||
if not self.check_dependnet(pluginInfo['dependent']): return public.return_msg_gettext(False, 'Depends on the following software, please install [{}] first',
|
||||
if not self.check_dependent(pluginInfo['dependent']): return public.return_msg_gettext(False, 'Depends on the following software, please install [{}] first',
|
||||
(pluginInfo['dependent'],))
|
||||
if 'version' in get:
|
||||
for versionInfo in pluginInfo['versions']:
|
||||
@@ -153,7 +200,32 @@ class panelPlugin:
|
||||
m_ps = {0: "All", 1: "Centos", 2: "Ubuntu/Debian"}
|
||||
return public.return_msg_gettext(False, 'Only supports [{}] system',(m_ps[int(versionInfo['os_limit'])],))
|
||||
if not hasattr(get, 'id'):
|
||||
if not self.check_dependnet(versionInfo['dependent']): return public.return_msg_gettext(False,'Depend on the following software, please install first [{}]',(versionInfo['dependent'],))
|
||||
if not self.check_dependent(versionInfo['dependent']): return public.return_msg_gettext(False,'Depend on the following software, please install first [{}]',(versionInfo['dependent'],))
|
||||
|
||||
# 获取插件安装包下载进度
|
||||
def get_download_speed(self, get):
|
||||
'''
|
||||
@name 获取插件下载进度
|
||||
@author hwliang<2021-06-25>
|
||||
@param plugin_name<string> 插件名称
|
||||
@return dict
|
||||
'''
|
||||
result = self.__get_download_speed(get.plugin_name)
|
||||
return result
|
||||
|
||||
# 取消下载
|
||||
def close_install(self, get):
|
||||
'''
|
||||
@name 取消指定插件安装过程
|
||||
@author hwliang<2021-07-07>
|
||||
@param plugin_name<string> 插件名称
|
||||
@return void
|
||||
'''
|
||||
plugin_name = get.plugin_name.strip()
|
||||
tmp_path = '{}/{}'.format(self.__tmp_path, plugin_name)
|
||||
if os.path.exists(tmp_path): shutil.rmtree(tmp_path)
|
||||
return public.returnMsg(False, '安装过程已取消!')
|
||||
|
||||
#安装插件
|
||||
def install_plugin(self,get):
|
||||
str1 = public.get_msg_gettext("System critical directory is not writable!")
|
||||
@@ -173,6 +245,7 @@ class panelPlugin:
|
||||
return check_result
|
||||
if pluginInfo['name'] in ['dns_manager','mail_sys']:
|
||||
pluginInfo['type'] = 5
|
||||
|
||||
if pluginInfo['type'] != 5:
|
||||
result = self.install_sync(pluginInfo,get)
|
||||
else:
|
||||
@@ -209,16 +282,21 @@ class panelPlugin:
|
||||
if os.path.exists(pluginInfo['install_checks']): update =pluginInfo['versions'][0]['version_msg']
|
||||
return self.update_zip(None,toFile,update)
|
||||
else:
|
||||
download_url = public.get_url() + '/install/plugin/' + pluginInfo['name'] + '_en/install.sh'
|
||||
toFile = '/tmp/%s.sh' % pluginInfo['name']
|
||||
public.downloadFile(download_url,toFile)
|
||||
self.set_pyenv(toFile)
|
||||
public.ExecShell('/bin/bash ' + toFile + ' install &> /tmp/panelShell.pl')
|
||||
if os.path.exists(pluginInfo['install_checks']):
|
||||
public.write_log_gettext('Installer','Successfully installed plugin [{}]',(pluginInfo['title'],))
|
||||
if os.path.exists(toFile): os.remove(toFile)
|
||||
return public.return_msg_gettext(True,'Installation succeeded!')
|
||||
return public.return_msg_gettext(False,'Installation failed')
|
||||
# download_url = public.get_url() + '/install/plugin/' + pluginInfo['name'] + '_en/install.sh'
|
||||
# toFile = '/tmp/%s.sh' % pluginInfo['name']
|
||||
# public.downloadFile(download_url,toFile)
|
||||
# self.set_pyenv(toFile)
|
||||
# public.ExecShell('/bin/bash ' + toFile + ' install &> /tmp/panelShell.pl')
|
||||
# if os.path.exists(pluginInfo['install_checks']):
|
||||
# public.write_log_gettext('Installer','Successfully installed plugin [{}]',(pluginInfo['title'],))
|
||||
# if os.path.exists(toFile): os.remove(toFile)
|
||||
# return public.return_msg_gettext(True,'Installation succeeded!')
|
||||
# return public.return_msg_gettext(False,'Installation failed')
|
||||
|
||||
if hasattr(get, 'min_version'):
|
||||
get.version += '.' + get.min_version
|
||||
|
||||
return self.__install_plugin(pluginInfo['name'], get.version)
|
||||
|
||||
# 设置Python环境变量
|
||||
def set_pyenv(self, filename):
|
||||
@@ -235,7 +313,11 @@ class panelPlugin:
|
||||
|
||||
#异步安装
|
||||
def install_async(self,pluginInfo,get):
|
||||
mtype = 'install';
|
||||
# # 只取主版本号与子版本号,忽略修订号
|
||||
# if 'version' in get:
|
||||
# get.version = '.'.join(str(get.version).split('.')[:2])
|
||||
|
||||
mtype = 'install'
|
||||
mmsg = public.get_msg_gettext('Install')
|
||||
if hasattr(get, 'upgrade'):
|
||||
mtype = 'update'
|
||||
@@ -267,6 +349,11 @@ class panelPlugin:
|
||||
execstr = "cd /www/server/panel/install && /bin/bash install_soft.sh {} {} {} {} {}".format(
|
||||
get.type, mtype, get.sName, get.version, ols_execstr)
|
||||
if get.sName == "phpmyadmin":
|
||||
# 当面板开启SSL时,标记下次打开phpmyadmin时需要设置SSL
|
||||
if os.path.exists('{}/data/ssl.pl'.format(public.get_panel_path())):
|
||||
with open('{}/data/phpmyadmin_ssl.mark'.format(public.get_panel_path()), 'w') as fp:
|
||||
fp.write('1')
|
||||
|
||||
execstr += "&> /tmp/panelExec.log"
|
||||
if public.get_webserver() == 'openlitespeed':
|
||||
execstr += " && sleep 1 && /usr/local/lsws/bin/lswsctrl restart"
|
||||
@@ -322,74 +409,45 @@ class panelPlugin:
|
||||
return public.return_msg_gettext(True,"Uninstallation succeeded")
|
||||
|
||||
#从云端取列表
|
||||
def get_cloud_list(self,get=None):
|
||||
lcoalTmp = 'data/plugin.json'
|
||||
softList = None
|
||||
listTmp = public.readFile(lcoalTmp)
|
||||
force_refresh = 0
|
||||
try:
|
||||
if listTmp: softList = json.loads(listTmp)
|
||||
if 'success' in softList and not softList['success']:
|
||||
if os.path.exists(lcoalTmp): os.remove(lcoalTmp)
|
||||
force_refresh = 1
|
||||
except:
|
||||
if os.path.exists(lcoalTmp): os.remove(lcoalTmp)
|
||||
def get_cloud_list(self, get=None):
|
||||
force = 0
|
||||
if get and hasattr(get, 'force'):
|
||||
force = int(get.force)
|
||||
|
||||
if 'focre_cloud' in session:
|
||||
if session['focre_cloud']:
|
||||
force = 1
|
||||
session['focre_cloud'] = False
|
||||
|
||||
if 'init_cloud' not in session:
|
||||
force = 1
|
||||
session['init_cloud'] = True
|
||||
|
||||
softList = public.load_soft_list(True if force == 1 else False)
|
||||
|
||||
if get and 'init' in get:
|
||||
if softList:
|
||||
if 'success' not in softList:
|
||||
return softList
|
||||
|
||||
focre = 0
|
||||
if hasattr(get,'force'): focre = int(get.force)
|
||||
if session:
|
||||
if 'focre_cloud' in session:
|
||||
if session['focre_cloud']:
|
||||
focre = 1
|
||||
session['focre_cloud'] = False
|
||||
|
||||
if not 'init_cloud' in session:
|
||||
focre = 1
|
||||
session['init_cloud'] = True
|
||||
if force_refresh == 1:
|
||||
focre = 1
|
||||
if not softList or focre > 0:
|
||||
self.clean_panel_log()
|
||||
# cloudUrl = 'https://console.aapanel.com/api/panel/get_soft_list'
|
||||
cloudUrl = '{}/api/panel/getSoftList'.format(self.__official_url)
|
||||
import panelAuth
|
||||
import requests
|
||||
pdata = panelAuth.panelAuth().create_serverid(None)
|
||||
# listTmp = public.httpPost(cloudUrl,pdata,6)
|
||||
url_headers={}
|
||||
if 'token' in pdata:
|
||||
url_headers = {"authorization": "bt {}".format(pdata['token'])}
|
||||
pdata['environment_info'] = json.dumps(public.fetch_env_info())
|
||||
|
||||
# listTmp = requests.post(cloudUrl, params=pdata, headers=url_headers,verify=False,timeout=10)
|
||||
# listTmp=listTmp.json()
|
||||
|
||||
try:
|
||||
listTmp = requests.post(cloudUrl, params=pdata, headers=url_headers, verify=False, timeout=10)
|
||||
listTmp.raise_for_status() # 检查请求是否成功,如果不成功会抛出异常
|
||||
listTmp = listTmp.json()
|
||||
except:
|
||||
listTmp = False
|
||||
|
||||
if listTmp is False:
|
||||
listTmp = public.readFile(lcoalTmp)
|
||||
try:
|
||||
softList = listTmp
|
||||
except:
|
||||
pass
|
||||
if softList: public.writeFile(lcoalTmp,json.dumps(softList))
|
||||
if force > 0:
|
||||
public.ExecShell('rm -f /tmp/bmac_*')
|
||||
public.run_thread(self.getCloudPHPExt)
|
||||
# 专业版和企业版到期提醒,aaPanel目前没有先注释
|
||||
# self.expire_msg(softList)
|
||||
|
||||
try:
|
||||
public.writeFile("/tmp/" + cache.get('p_token'),str(softList['pro']))
|
||||
except:pass
|
||||
p_token = cache.get('p_token')
|
||||
|
||||
if p_token is None:
|
||||
p_token = 'bmac_' + public.Md5(public.get_mac_address())
|
||||
cache.set('p_token', p_token)
|
||||
|
||||
public.writeFile("/tmp/" + p_token, str(softList['pro']))
|
||||
public.writeFile('/tmp/{}.time'.format(p_token), str(int(time.time())))
|
||||
except:
|
||||
pass
|
||||
|
||||
sType = 0
|
||||
try:
|
||||
if hasattr(get,'type'): sType = int(get['type'])
|
||||
@@ -414,14 +472,13 @@ class panelPlugin:
|
||||
sType = 0
|
||||
except:pass
|
||||
|
||||
|
||||
try:
|
||||
softList = json.loads(softList)
|
||||
except:
|
||||
pass
|
||||
# 扫描本地插件并追加到软件列表中
|
||||
softList['list'] = self.get_local_plugin(softList['list'])
|
||||
softList['list'] = self.get_types(softList['list'],sType)
|
||||
if hasattr(get,'query'):
|
||||
|
||||
# 软件列表分类处理
|
||||
softList['list'] = self.get_types(softList['list'], sType)
|
||||
|
||||
if hasattr(get, 'query'):
|
||||
if get.query:
|
||||
get.query = get.query.lower()
|
||||
tmpList = []
|
||||
@@ -431,11 +488,11 @@ class panelPlugin:
|
||||
softInfo['ps'].lower().find(get.query) != -1:
|
||||
tmpList.append(softInfo)
|
||||
softList['list'] = tmpList
|
||||
|
||||
for softInfo in softList['list']:
|
||||
if 'uninsatll_checks' not in softInfo:
|
||||
softInfo['uninsatll_checks'] = softInfo['uninstall_checks']
|
||||
# if not softList['list']:
|
||||
# if os.path.exists(lcoalTmp): os.remove(lcoalTmp)
|
||||
|
||||
return softList
|
||||
|
||||
#取提醒标记
|
||||
@@ -656,7 +713,7 @@ class panelPlugin:
|
||||
"s_version": "0",
|
||||
"manager_version": "1",
|
||||
"c_manager_version": "1",
|
||||
"dependnet": "",
|
||||
"dependent": "",
|
||||
"mutex": "",
|
||||
"install_checks": "/www/server/panel/plugin/" + info['name'],
|
||||
"uninsatll_checks": "/www/server/panel/plugin/" + info['name'],
|
||||
@@ -666,7 +723,7 @@ class panelPlugin:
|
||||
{
|
||||
"m_version": m_version[0],
|
||||
"version": m_version[1],
|
||||
"dependnet": "",
|
||||
"dependent": "",
|
||||
"mem_limit": 32,
|
||||
"cpu_limit": 1,
|
||||
"os_limit": 0,
|
||||
@@ -756,20 +813,14 @@ class panelPlugin:
|
||||
return softList
|
||||
|
||||
#取首页软件列表
|
||||
def get_index_list(self,get=None):
|
||||
def get_index_list(self, get=None):
|
||||
softList = self.get_cloud_list(get)['list']
|
||||
if not softList:
|
||||
get.force = 1
|
||||
softList = self.get_cloud_list(get)['list']
|
||||
if not softList: return public.return_msg_gettext(False,'Failed to get software list ({})',"401")
|
||||
softList = self.set_coexist(softList)
|
||||
# # 只取应用名
|
||||
# lista = [i['name'] for i in softList]
|
||||
#
|
||||
# public.print_log("23454566777^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^_______________________________"
|
||||
# "列表 {}".format(lista))
|
||||
if not os.path.exists(self.__index):
|
||||
public.writeFile(self.__index,'[]')
|
||||
if not os.path.exists(self.__index): public.writeFile(self.__index,'[]')
|
||||
try:
|
||||
indexList = json.loads(public.ReadFile(self.__index))
|
||||
except Exception:
|
||||
@@ -1021,11 +1072,18 @@ class panelPlugin:
|
||||
|
||||
if softInfo['name'] == sName:
|
||||
if sName == 'phpmyadmin':
|
||||
# 检查是否需要开启SSL
|
||||
if os.path.exists('{}/data/phpmyadmin_ssl.mark'.format(public.get_panel_path())) and os.path.exists('{}/phpmyadmin'.format(public.get_setup_path())):
|
||||
os.remove('{}/data/phpmyadmin_ssl.mark'.format(public.get_panel_path()))
|
||||
from ajax_v2 import ajax
|
||||
ajax().set_phpmyadmin_ssl(public.to_dict_obj({'v': '1'}))
|
||||
|
||||
from BTPanel import get_phpmyadmin_dir
|
||||
pmd = get_phpmyadmin_dir()
|
||||
softInfo['ext'] = self.getPHPMyAdminStatus()
|
||||
if softInfo['ext'] and pmd:
|
||||
softInfo['ext']['url'] = 'http://' + public.GetHost() + ':'+ pmd[1] + '/' + pmd[0]
|
||||
port = softInfo['ext']['ssl_port'] if softInfo['ext'].get('ssl_enabled', False) else pmd[1]
|
||||
softInfo['ext']['url'] = 'http' + ('s' if softInfo['ext'].get('ssl_enabled', False) else '') + '://' + public.GetHost() + ':'+ port + '/' + pmd[0]
|
||||
if "php-" in sName:
|
||||
v = softInfo["versions"][0]["m_version"]
|
||||
v1 = v.replace(".", "")
|
||||
@@ -1036,6 +1094,7 @@ class panelPlugin:
|
||||
else:
|
||||
softInfo["php_ini"] = "/www/server/php/{}/etc/php.ini".format(v1)
|
||||
return self.check_status(softInfo)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
@@ -1181,7 +1240,13 @@ class panelPlugin:
|
||||
page = page.Page()
|
||||
info = {}
|
||||
info['count'] = len(data)
|
||||
info['row'] = self.ROWS
|
||||
info['row'] = self.ROWS
|
||||
if hasattr(get,'row'):
|
||||
try:
|
||||
info['row'] = int(get['row'])
|
||||
except:
|
||||
info['row'] = self.ROWS
|
||||
|
||||
info['p'] = 1
|
||||
if hasattr(get,'p'):
|
||||
try:
|
||||
@@ -1637,7 +1702,7 @@ class panelPlugin:
|
||||
if os.path.exists('/www/server/apache/bin/httpd'):
|
||||
v1 = session.get('httpdv')
|
||||
if not v1:
|
||||
v1 = public.ExecShell("/www/server/apache/bin/httpd -v|grep Apache|awk '{print $3}'|sed 's/Apache\///'")[0].strip();
|
||||
v1 = public.ExecShell(r"/www/server/apache/bin/httpd -v|grep Apache|awk '{print $3}'|sed 's/Apache\///'")[0].strip();
|
||||
session['httpdv'] = v1
|
||||
#if name == 'mysql':
|
||||
# if os.path.exists('/www/server/mysql/bin/mysql'): v1 = public.ExecShell("mysql -V|awk '{print $5}'|sed 's/,//'")[0].strip();
|
||||
@@ -1749,6 +1814,8 @@ class panelPlugin:
|
||||
pstatus = False
|
||||
phpversion = "54"
|
||||
phpport = '888'
|
||||
ssl_port = '887'
|
||||
ssl_enabled = False
|
||||
if os.path.exists(configFile):
|
||||
conf = public.readFile(configFile)
|
||||
rep = r"listen\s+([0-9]+)\s*;"
|
||||
@@ -1756,6 +1823,15 @@ class panelPlugin:
|
||||
if rtmp:
|
||||
phpport = rtmp.groups()[0]
|
||||
|
||||
# SSL配置文件查看
|
||||
ssl_config_file = '{}/vhost/nginx/phpmyadmin.conf'.format(public.get_panel_path())
|
||||
if os.path.exists(ssl_config_file) and os.path.getsize(ssl_config_file) > 10:
|
||||
tmps = public.readFile(ssl_config_file)
|
||||
m = re.search(r"listen\s*(\d+)", tmps)
|
||||
if m is not None:
|
||||
ssl_enabled = True
|
||||
ssl_port = m.group(1)
|
||||
|
||||
if conf.find('AUTH_START') != -1: pauth = True
|
||||
if conf.find(setupPath + '/stop') == -1: pstatus = True
|
||||
configFile = setupPath + '/nginx/conf/enable-php.conf'
|
||||
@@ -1786,8 +1862,19 @@ class panelPlugin:
|
||||
rtmp = re.search(rep,conf)
|
||||
if rtmp:
|
||||
phpport = rtmp.groups()[0]
|
||||
|
||||
# SSL配置文件查看
|
||||
ssl_config_file = '{}/vhost/apache/phpmyadmin.conf'.format(public.get_panel_path())
|
||||
if os.path.exists(ssl_config_file) and os.path.getsize(ssl_config_file) > 10:
|
||||
tmps = public.readFile(ssl_config_file)
|
||||
m = re.search(r"Listen\s*(\d+)", tmps)
|
||||
if m is not None:
|
||||
ssl_enabled = True
|
||||
ssl_port = m.group(1)
|
||||
|
||||
if conf.find('AUTH_START') != -1: pauth = True
|
||||
if conf.find('/www/server/stop') == -1: pstatus = True
|
||||
|
||||
if os.path.exists('/usr/local/lsws/bin/lswsctrl'):
|
||||
result = self._get_ols_myphpadmin_info()
|
||||
if result:
|
||||
@@ -1808,7 +1895,9 @@ class panelPlugin:
|
||||
|
||||
tmp['run'] = pstatus
|
||||
tmp['phpversion'] = phpversion
|
||||
tmp['ssl_enabled'] = ssl_enabled
|
||||
tmp['port'] = phpport
|
||||
tmp['ssl_port'] = ssl_port
|
||||
tmp['auth'] = pauth
|
||||
except Exception as ex:
|
||||
tmp['status'] = False
|
||||
@@ -1819,18 +1908,18 @@ class panelPlugin:
|
||||
filename = "/www/server/panel/vhost/openlitespeed/detail/phpmyadmin.conf"
|
||||
conf = public.readFile(filename)
|
||||
if not conf:return False
|
||||
reg = '/usr/local/lsws/lsphp(\d+)/bin/lsphp'
|
||||
reg = r'/usr/local/lsws/lsphp(\d+)/bin/lsphp'
|
||||
php_v = re.search(reg,conf)
|
||||
phpversion = '73'
|
||||
phpport = '888'
|
||||
if php_v:
|
||||
phpversion = php_v.groups(1)
|
||||
phpversion = php_v.group(1)
|
||||
filename = '/www/server/panel/vhost/openlitespeed/listen/888.conf'
|
||||
conf = public.readFile(filename)
|
||||
reg = 'address\s+\*\:(\d+)'
|
||||
reg = r'address\s+\*\:(\d+)'
|
||||
php_port = re.search(reg,conf)
|
||||
if php_port:
|
||||
phpport = php_port.groups(1)
|
||||
phpport = php_port.group(1)
|
||||
pauth = False
|
||||
pstatus = False
|
||||
if conf.find('/www/server/stop') == -1: pstatus = True
|
||||
@@ -2164,43 +2253,12 @@ class panelPlugin:
|
||||
return find['title']
|
||||
|
||||
|
||||
|
||||
#请求插件事件
|
||||
def a(self,get):
|
||||
if not hasattr(get,'name'): return public.return_msg_gettext(False,'Input name of plugin!')
|
||||
def a(self, get):
|
||||
try:
|
||||
if not public.path_safe_check("%s/%s" % (get.name,get.s)): return public.return_msg_gettext(False,'Requested method [{}] does not exist!')
|
||||
path = self.__install_path + '/' + get.name
|
||||
|
||||
# aaa = path + '/'+get.name+'_main.py'
|
||||
# public.print_log("@@@@@@@@@@@@@@@@@aaa {}".format(aaa))
|
||||
|
||||
if not os.path.exists(path + '/'+get.name+'_main.py'):
|
||||
if os.path.exists(path+'/index.php'):
|
||||
# bbb = path+'/index.php'
|
||||
# public.print_log("@@@@@@@@@@@@@@@@@bbb {}".format(bbb))
|
||||
|
||||
|
||||
import panelPHP
|
||||
return panelPHP.panelPHP(get.name).exec_php_script(get)
|
||||
return public.return_msg_gettext(False,'This plugin does NOT have extend function!')
|
||||
|
||||
if not self.check_accept(get):return public.return_msg_gettext(False,"You did not purchase [ {} ] or the authorization has expired", (self.get_title_byname(get),))
|
||||
public.package_path_append(path)
|
||||
plugin_main = __import__(get.name+'_main')
|
||||
try:
|
||||
reload(plugin_main)
|
||||
except: pass
|
||||
|
||||
pluginObject = eval('plugin_main.' + get.name + '_main()')
|
||||
if not hasattr(pluginObject,get.s): return public.return_msg_gettext(False,'Requested method [{}] does not exist!',(get.s,))
|
||||
execStr = 'pluginObject.' + get.s + '(get)'
|
||||
return eval(execStr)
|
||||
return public.run_plugin(get.name, get.s, get)
|
||||
except:
|
||||
import traceback
|
||||
errorMsg = traceback.format_exc()
|
||||
public.writeFile('logs/done.log',errorMsg)
|
||||
return public.return_msg_gettext(False,'%s:<br> %s ' % (public.get_msg_gettext('Sorry, something went wrong'),errorMsg.replace('\n','<br>')))
|
||||
return public.get_error_object(None, plugin_name=get.name)
|
||||
|
||||
#上传插件包
|
||||
def update_zip(self,get = None,tmp_file = None, update = False):
|
||||
tmp_path = '/www/server/panel/temp'
|
||||
@@ -2266,7 +2324,7 @@ class panelPlugin:
|
||||
if not os.path.exists(get.tmp_path): return public.return_msg_gettext(False,'TEM_FILE_NOT_EXIST!')
|
||||
plugin_path = '/www/server/panel/plugin/' + get.plugin_name
|
||||
if not os.path.exists(plugin_path): os.makedirs(plugin_path)
|
||||
public.ExecShell("\cp -a -r " + get.tmp_path + '/* ' + plugin_path + '/')
|
||||
public.ExecShell(r"\cp -a -r " + get.tmp_path + '/* ' + plugin_path + '/')
|
||||
public.ExecShell('chmod -R 600 ' + plugin_path)
|
||||
self.set_pyenv(plugin_path + '/install.sh')
|
||||
public.ExecShell('cd ' + plugin_path + ' && bash install.sh install &> /tmp/panelShell.pl')
|
||||
@@ -2384,4 +2442,403 @@ class panelPlugin:
|
||||
config_data.append(args_name)
|
||||
public.writeFile(config_file,"\n".join(config_data))
|
||||
public.write_log_gettext('Software manager','Setup software: Custom compilation parameters for {} are configured as: {}'.format(get.name,config_data))
|
||||
return public.return_msg_gettext(True,'Setup successfully!')
|
||||
return public.return_msg_gettext(True,'Setup successfully!')
|
||||
|
||||
# 安装插件
|
||||
def __install_plugin(self, upgrade_plugin_name, upgrade_version=None):
|
||||
'''
|
||||
@name 安装指定插件
|
||||
@author hwliang<2021-06-21>
|
||||
@param upgrade_plugin_name<string> 插件名称
|
||||
@param upgrade_version<string> 插件版本 版本号.指定版本号 / tls.最新正式版 / beta.最新测试版
|
||||
@return dict
|
||||
'''
|
||||
self.__plugin_name = upgrade_plugin_name
|
||||
plugin_info = self.__get_plugin_find(upgrade_plugin_name)
|
||||
if not plugin_info:
|
||||
raise public.PanelError('指定插件不存在,无法安装!')
|
||||
if not plugin_info['versions']:
|
||||
raise public.PanelError('指定插件当前未发布版本信息,请稍候再安装!')
|
||||
if not upgrade_version:
|
||||
upgrade_version = '{}.{}'.format(
|
||||
plugin_info['versions'][0]['m_version'],
|
||||
plugin_info['versions'][0]['version'])
|
||||
filename = self.__download_plugin(upgrade_plugin_name, upgrade_version)
|
||||
# 如果下载失败
|
||||
if isinstance(filename, dict):
|
||||
return filename
|
||||
return self.__unpackup_plugin(filename)
|
||||
|
||||
# 修复插件
|
||||
def __repair_plugin(self, upgrade_plugin_name, upgrade_version=None):
|
||||
'''
|
||||
@name 修复指定插件
|
||||
@author hwliang<2021-06-21>
|
||||
@param upgrade_plugin_name<string> 插件名称
|
||||
@param upgrade_version<string> 插件版本 版本号.指定版本号 / tls.最新正式版 / beta.最新测试版
|
||||
@return dict
|
||||
'''
|
||||
self.__install_opt = 'r'
|
||||
return self.__install_plugin(upgrade_plugin_name, upgrade_version)
|
||||
|
||||
# 升级插件版本
|
||||
def __upgrade_plugin(self, upgrade_plugin_name, upgrade_version=None):
|
||||
'''
|
||||
@name 升级到指定版本
|
||||
@author hwliang<2021-06-21>
|
||||
@param upgrade_plugin_name<string> 插件名称
|
||||
@param upgrade_version<string> 插件版本 版本号.指定版本号 / tls.最新正式版 / beta.最新测试版
|
||||
@return dict
|
||||
'''
|
||||
self.__install_opt = 'u'
|
||||
return self.__install_plugin(upgrade_plugin_name, upgrade_version)
|
||||
|
||||
# 获取插件信息
|
||||
def __get_plugin_info(self, upgrade_plugin_name):
|
||||
'''
|
||||
@name 获取插件信息
|
||||
@author hwliang<2021-06-15>
|
||||
@param upgrade_plugin_name<string> 插件名称
|
||||
@return dict
|
||||
'''
|
||||
plugin_info_file = '{}/{}/info.json'.format(self.__plugin_path,
|
||||
upgrade_plugin_name)
|
||||
if not os.path.exists(plugin_info_file): return {}
|
||||
info_body = self.__read_file(plugin_info_file)
|
||||
if not info_body: return {}
|
||||
plugin_info = json.loads(info_body)
|
||||
return plugin_info
|
||||
|
||||
# 获取插件最近1条更新日志
|
||||
def __get_update_msg(self, upgrade_plugin_name, upgrade_version):
|
||||
'''
|
||||
@name 检查指定插件版本更新日志
|
||||
@author hwliang<2021-06-21>
|
||||
@param upgrade_plugin_name<string> 插件名称
|
||||
@param upgrade_version<string> 插件版本
|
||||
@return string
|
||||
'''
|
||||
plugin_update_msg = ''
|
||||
plugin_info = self.__get_plugin_find(upgrade_plugin_name)
|
||||
if not plugin_info: return plugin_update_msg
|
||||
for _version_info in plugin_info['versions']:
|
||||
l_version = '{}.{}'.format(_version_info['m_version'],
|
||||
_version_info['version'])
|
||||
if l_version == upgrade_version:
|
||||
plugin_update_msg = _version_info['update_msg']
|
||||
break
|
||||
return plugin_update_msg
|
||||
|
||||
# 获取插件最近10条更新日志
|
||||
def __get_plugin_upgrades(self, upgrade_plugin_name):
|
||||
'''
|
||||
@name 检查指定插件最近10条更新日志
|
||||
@author hwliang<2021-06-21>
|
||||
@param upgrade_plugin_name<string> 插件名称
|
||||
@return list
|
||||
'''
|
||||
plugin_info = self.__get_plugin_find(upgrade_plugin_name)
|
||||
if not plugin_info: return []
|
||||
|
||||
try:
|
||||
upgrade_list = public.httpPost(
|
||||
self.__api_root_url + '/down/get_update_msg',
|
||||
{'soft_id': plugin_info['id']})
|
||||
return json.loads(upgrade_list)
|
||||
except:
|
||||
return []
|
||||
|
||||
# 获取指定软件信息
|
||||
def __get_plugin_find(self, upgrade_plugin_name=None):
|
||||
'''
|
||||
@name 获取指定软件信息
|
||||
@author hwliang<2021-06-15>
|
||||
@param upgrade_plugin_name<string> 插件名称
|
||||
@return dict
|
||||
'''
|
||||
self.__ensure_plugin_list_obtained(True)
|
||||
|
||||
for p_data_info in self.__plugin_list['list']:
|
||||
if p_data_info['name'] == upgrade_plugin_name:
|
||||
upgrade_plugin_name = p_data_info['name']
|
||||
return p_data_info
|
||||
|
||||
# 如果不在插件列表中
|
||||
return self.__get_plugin_info(upgrade_plugin_name)
|
||||
|
||||
# 检查插件依赖
|
||||
def __check_dependent(self, upgrade_plugin_name):
|
||||
'''
|
||||
@name 检查指定插件的依赖安装情况
|
||||
@author hwliang<2021-06-21>
|
||||
@param upgrade_plugin_name<string> 插件名称
|
||||
@return dict
|
||||
'''
|
||||
plugin_info = self.__get_plugin_find(upgrade_plugin_name)
|
||||
if not plugin_info: return {}
|
||||
if not plugin_info['dependent']: return {}
|
||||
deployment_list = {}
|
||||
for dependent_plu_name in plugin_info['dependent'].split(','):
|
||||
p_info = self.__get_plugin_find(dependent_plu_name)
|
||||
if not p_info: continue
|
||||
deployment_list[dependent_plu_name] = os.path.exists(
|
||||
p_info['install_checks'])
|
||||
return deployment_list
|
||||
|
||||
# 读取指定文件
|
||||
def __read_file(self, filename, open_mode='r'):
|
||||
'''
|
||||
@name 读取指定文件
|
||||
@author hwliang<2021-06-16>
|
||||
@param filename<string> 文件名
|
||||
@param mode<string> 打开模式, 默认: r
|
||||
@return bytes or string
|
||||
'''
|
||||
f_object = open(filename, mode=open_mode)
|
||||
file_body = f_object.read()
|
||||
f_object.close()
|
||||
return file_body
|
||||
|
||||
# 解包插件压缩包
|
||||
def __unpackup_plugin(self, tmp_file):
|
||||
'''
|
||||
@name 解包插件包
|
||||
@author hwliang<2021-06-21>
|
||||
@param tmp_file<string> 下载好的保存路径,从self.download_plugin方法中获取
|
||||
@return dict
|
||||
'''
|
||||
if type(tmp_file) == dict:
|
||||
return tmp_file
|
||||
|
||||
if "false" in tmp_file or "错误" in tmp_file:
|
||||
return json.loads(tmp_file)
|
||||
|
||||
s_tmp_path = self.__tmp_path
|
||||
if not os.path.exists(s_tmp_path):
|
||||
os.makedirs(s_tmp_path, mode=384)
|
||||
|
||||
if tmp_file:
|
||||
if not os.path.exists(tmp_file):
|
||||
return public.returnMsg(False, '文件下载失败!')
|
||||
import panelTask as plu_panelTask
|
||||
plu_panelTask.bt_task()._unzip(tmp_file, s_tmp_path, '',
|
||||
'/dev/null')
|
||||
if os.path.exists(tmp_file):
|
||||
os.remove(tmp_file)
|
||||
|
||||
s_tmp_path = os.path.join(s_tmp_path, self.__plugin_name)
|
||||
|
||||
p_info = os.path.join(s_tmp_path, 'info.json')
|
||||
if not os.path.exists(p_info):
|
||||
d_path = None
|
||||
for plugin_df in os.walk(s_tmp_path):
|
||||
if len(plugin_df[2]) < 3: continue
|
||||
if not 'info.json' in plugin_df[2]: continue
|
||||
if not 'install.sh' in plugin_df[2]: continue
|
||||
if not os.path.exists(plugin_df[0] + '/info.json'): continue
|
||||
d_path = plugin_df[0]
|
||||
if d_path:
|
||||
s_tmp_path = d_path
|
||||
p_info = s_tmp_path + '/info.json'
|
||||
try:
|
||||
try:
|
||||
plugin_data_info = json.loads(public.ReadFile(p_info))
|
||||
except:
|
||||
plugin_data_info = json.loads(self.__read_file(p_info))
|
||||
|
||||
plugin_data_info['size'] = public.get_path_size(s_tmp_path)
|
||||
if not 'author' in plugin_data_info:
|
||||
plugin_data_info['author'] = 'aapanel'
|
||||
if not 'home' in plugin_data_info:
|
||||
plugin_data_info['home'] = 'https://www.aapanel.com'
|
||||
|
||||
p_info_file = self.__plugin_path + plugin_data_info[
|
||||
'name'] + '/info.json'
|
||||
plugin_data_info['old_version'] = '0'
|
||||
plugin_data_info['tmp_path'] = s_tmp_path
|
||||
if os.path.exists(p_info_file):
|
||||
try:
|
||||
old_info = json.loads(public.ReadFile(p_info_file))
|
||||
plugin_data_info['old_version'] = old_info['versions']
|
||||
except:
|
||||
pass
|
||||
except:
|
||||
public.ExecShell("rm -rf " + s_tmp_path + '/*')
|
||||
return public.get_error_object(plugin_name=self.__plugin_name)
|
||||
plugin_data_info['install_opt'] = self.__install_opt
|
||||
plugin_data_info['dependent'] = self.__check_dependent(plugin_data_info['name'])
|
||||
plugin_data_info['update_msg'] = self.__get_update_msg(
|
||||
plugin_data_info['name'], plugin_data_info['versions'])
|
||||
not_check = self.not_cpu_or_bit(plugin_data_info)
|
||||
if not_check:
|
||||
if os.path.exists(s_tmp_path): shutil.rmtree(s_tmp_path)
|
||||
return not_check
|
||||
|
||||
return plugin_data_info
|
||||
|
||||
# 检测是否为不支持的平台和系统位数
|
||||
def not_cpu_or_bit(self, plugin_data_info):
|
||||
'''
|
||||
@name 检测是否为不支持的平台和系统位数
|
||||
@author hwliang<2021-07-07>
|
||||
@param plugin_data_info<dict> 插件信息数据
|
||||
@return dict or None
|
||||
'''
|
||||
if 'not_os_bit' in plugin_data_info:
|
||||
if public.get_sysbit() == int(plugin_data_info['not_os_bit']):
|
||||
return public.returnMsg(
|
||||
False,
|
||||
'该应用不支持{}位系统'.format(plugin_data_info['not_os_bit']))
|
||||
if 'not_cpu_type' in plugin_data_info:
|
||||
if not plugin_data_info['not_cpu_type']: return None
|
||||
machine = os.uname().machine
|
||||
for c_type in plugin_data_info['not_cpu_type']:
|
||||
c_type = c_type.lower()
|
||||
result = public.returnMsg(
|
||||
False, '该应用不支持{}平台,{}'.format(c_type, machine))
|
||||
if c_type in ['arm', 'aarch64', 'aarch']:
|
||||
if machine in ['aarch64', 'aarch']:
|
||||
return result
|
||||
elif c_type in ['mips', 'mips64', 'mips64el']:
|
||||
if machine.find('mips') != -1:
|
||||
return result
|
||||
elif c_type in ['x86', 'x86-64']:
|
||||
if machine in ['x86', 'x86-64']:
|
||||
return result
|
||||
return None
|
||||
|
||||
# 下载插件安装包
|
||||
def __download_plugin(self, upgrade_plugin_name, upgrade_version):
|
||||
'''
|
||||
@name 下载插件包
|
||||
@author hwliang<2021-06-21>
|
||||
@param upgrade_plugin_name<string> 插件名称
|
||||
@param upgrade_version<string> 插件版本
|
||||
@return string 保存路径
|
||||
'''
|
||||
|
||||
pkey = '{}_pre'.format(upgrade_plugin_name)
|
||||
pdata = public.get_user_info()
|
||||
pdata['name'] = upgrade_plugin_name
|
||||
pdata['version'] = upgrade_version
|
||||
pdata['os'] = 'Linux'
|
||||
pdata['environment_info'] = json.dumps(public.fetch_env_info(), ensure_ascii=False)
|
||||
filename = '{}/{}.zip'.format(self.__tmp_path, upgrade_plugin_name)
|
||||
if not os.path.exists(self.__tmp_path):
|
||||
os.makedirs(self.__tmp_path, 384)
|
||||
|
||||
if not cache.get(pkey):
|
||||
import config, socket
|
||||
import requests.packages.urllib3.util.connection as urllib3_conn
|
||||
_ip_type = config.config().get_request_iptype()
|
||||
old_family = urllib3_conn.allowed_gai_family
|
||||
if _ip_type == 'ipv4':
|
||||
urllib3_conn.allowed_gai_family = lambda: socket.AF_INET
|
||||
elif _ip_type == 'ipv6':
|
||||
urllib3_conn.allowed_gai_family = lambda: socket.AF_INET6
|
||||
try:
|
||||
download_res = requests.post(
|
||||
self.__download_url,
|
||||
pdata,
|
||||
headers=public.get_requests_headers(),
|
||||
timeout=(60, 1800),
|
||||
stream=True)
|
||||
except Exception as ex:
|
||||
str_ex = str(ex)
|
||||
if 'Name or service not known' in str_ex:
|
||||
return public.returnMsg(False,
|
||||
'下载软件包时DNS解析失败,请检查服务器网络配置是否正常: <p>Error: Name or service not known</p>')
|
||||
elif 'Failed to establish a new connection' in str_ex:
|
||||
return public.returnMsg(False,
|
||||
'连接下载节点失败,请尝试到【面板设置】页面切换通讯节点,或检查服务器网络是否正常: <p>Error: Failed to establish a new connection</p>')
|
||||
elif 'Read timed out' in str_ex:
|
||||
return public.returnMsg(False,
|
||||
'连接下载节点失败,请尝试到【面板设置】页面切换通讯节点,或检查服务器网络是否正常: <p>Error: Read timed out</p>')
|
||||
elif 'Connection refused' in str_ex:
|
||||
return public.returnMsg(False,
|
||||
'连接下载节点失败,请尝试到【面板设置】页面切换通讯节点,或检查服务器网络是否正常: <p>Error: Connection refused</p>')
|
||||
elif 'Remote end closed connection without response' in str_ex:
|
||||
return public.returnMsg(False,
|
||||
'连接下载节点失败,请尝试到【面板设置】页面切换通讯节点,或检查服务器网络是否正常: <p>Error: Remote end closed connection without response</p>')
|
||||
else:
|
||||
return public.returnMsg(False, '连接下载节点失败,请尝试到【面板设置】页面切换通讯节点,或检查服务器网络是否正常: <p>Error: {}</p>'.format(str_ex))
|
||||
finally:
|
||||
urllib3_conn.allowed_gai_family = old_family
|
||||
|
||||
try:
|
||||
headers_total_size = int(download_res.headers['File-size'])
|
||||
except:
|
||||
try:
|
||||
return json.loads(download_res.text).json()
|
||||
except:
|
||||
if download_res.text.find('<html>') != -1:
|
||||
raise public.PanelError(
|
||||
public.error_conn_cloud(download_res.text))
|
||||
raise public.PanelError(download_res.text)
|
||||
|
||||
res_down_size = 0
|
||||
res_chunk_size = 8192
|
||||
last_time = time.time()
|
||||
with open(filename, 'wb+') as with_res_f:
|
||||
try:
|
||||
for download_chunk in download_res.iter_content(
|
||||
chunk_size=res_chunk_size):
|
||||
if download_chunk:
|
||||
with_res_f.write(download_chunk)
|
||||
speed_last_size = len(download_chunk)
|
||||
res_down_size += speed_last_size
|
||||
res_start_time = time.time()
|
||||
res_timeout = (res_start_time - last_time)
|
||||
res_sec_speed = int(res_down_size / res_timeout)
|
||||
pre_text = '{}/{}/{}'.format(res_down_size,
|
||||
headers_total_size,
|
||||
res_sec_speed)
|
||||
cache.set(pkey, pre_text, 3600)
|
||||
|
||||
except Exception as ex:
|
||||
ex_str = str(ex)
|
||||
if "Read timed out" in ex_str:
|
||||
return public.returnMsg(False, '软件包下载超时,请重试: {}'.format(ex_str))
|
||||
if "No space left on device" in ex_str:
|
||||
return public.returnMsg(False, "磁盘空间不足,请先清理后再试!")
|
||||
finally:
|
||||
with_res_f.close()
|
||||
if cache.get(pkey): cache.delete(pkey)
|
||||
|
||||
if public.FileMd5(filename) != download_res.headers['Content-md5']:
|
||||
return public.returnMsg(False, '软件包校验失败,请更新软件列表,并重试')
|
||||
else:
|
||||
while True:
|
||||
time.sleep(1)
|
||||
if not cache.get(pkey): break
|
||||
return ''
|
||||
return filename
|
||||
|
||||
# 获取插件安装包下载进度
|
||||
def __get_download_speed(self, upgrade_plugin_name):
|
||||
'''
|
||||
@name 取插件下载进度
|
||||
@author hwliang<2021-06-21>
|
||||
@param upgrade_plugin_name<string> 插件名称
|
||||
@return dict
|
||||
'''
|
||||
pkey = '{}_pre'.format(upgrade_plugin_name)
|
||||
pre_text = cache.get(pkey)
|
||||
if not pre_text:
|
||||
return public.returnMsg(False, '指定进度信息不存在!')
|
||||
result = {"status": True}
|
||||
pre_tmp = pre_text.split('/')
|
||||
result['down_size'], result['total_size'] = (int(pre_tmp[0]),
|
||||
int(pre_tmp[1]))
|
||||
result['down_pre'] = round(
|
||||
result['down_size'] / result['total_size'] * 100, 1)
|
||||
result['sec_speed'] = int(float(pre_tmp[2]))
|
||||
result['need_time'] = int(
|
||||
(result['total_size'] - result['down_size']) / result['sec_speed'])
|
||||
return result
|
||||
|
||||
|
||||
# 获取插件与授权信息
|
||||
def __ensure_plugin_list_obtained(self, force: bool = False):
|
||||
if force or not self.__plugin_list:
|
||||
self.__plugin_list = public.load_soft_list(force)
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2019 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2019 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
import public,os
|
||||
from BTPanel import request,abort,send_file
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2017 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2017 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
@@ -32,8 +32,8 @@ class ProjectController:
|
||||
if args['mod_name'] in ['base']: return public.return_status_code(1000,'wrong call!')
|
||||
public.exists_args('def_name,mod_name',args)
|
||||
if args['def_name'].find('__') != -1: return public.return_status_code(1000,'Called method name cannot contain [ __ ] characters')
|
||||
if not re.match(r"^\w+$",args['mod_name']): return public.return_status_code(1000,'The called module name cannot contain characters other than \w')
|
||||
if not re.match(r"^\w+$",args['def_name']): return public.return_status_code(1000,'The called module name cannot contain characters other than \w')
|
||||
if not re.match(r"^\w+$",args['mod_name']): return public.return_status_code(1000,r'The called module name cannot contain characters other than \w')
|
||||
if not re.match(r"^\w+$",args['def_name']): return public.return_status_code(1000,r'The called module name cannot contain characters other than \w')
|
||||
except:
|
||||
return public.get_error_object()
|
||||
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2016 宝塔软件(http://www.bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2016 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 沐落 <cjx@bt.cn>
|
||||
# | Author: 沐落 <cjx@aapanel.com>
|
||||
# | Author: lx
|
||||
# | 消息推送管理
|
||||
# | 对外方法 get_modules_list、install_module、uninstall_module、get_module_template、set_push_config、get_push_config、del_push_config
|
||||
|
||||
+16
-16
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2018 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2018 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
@@ -21,7 +21,7 @@ class panelRedirect:
|
||||
#匹配目标URL的域名并返回
|
||||
def GetToDomain(self,tourl):
|
||||
if tourl:
|
||||
rep = "https?://([\w\-\.]+)"
|
||||
rep = r"https?://([\w\-\.]+)"
|
||||
tu = re.search(rep, tourl)
|
||||
return tu.group(1)
|
||||
|
||||
@@ -105,7 +105,7 @@ class panelRedirect:
|
||||
if os.path.exists(ng_file):
|
||||
ng_conf = public.readFile(ng_file)
|
||||
if not p_conf:
|
||||
rep = "#SSL-END(\n|.)*\/redirect\/.*\*.conf;"
|
||||
rep = "#SSL-END(\n|.)*\\/redirect\\/.*\\*.conf;"
|
||||
ng_conf = re.sub(rep, '#SSL-END', ng_conf)
|
||||
public.writeFile(ng_file, ng_conf)
|
||||
return
|
||||
@@ -114,13 +114,13 @@ class panelRedirect:
|
||||
sitenamelist.append(i["sitename"])
|
||||
|
||||
if get.sitename in sitenamelist:
|
||||
rep = "include.*\/redirect\/.*\*.conf;"
|
||||
rep = r"include.*\/redirect\/.*\*.conf;"
|
||||
if not re.search(rep,ng_conf):
|
||||
ng_conf = ng_conf.replace("#SSL-END","#SSL-END\n\t%s\n\t" % public.get_msg_gettext('#referenced redirect rule, if commented, the configured redirect rule will be invalid') + "include " + ng_redirectfile + ";")
|
||||
public.writeFile(ng_file,ng_conf)
|
||||
|
||||
else:
|
||||
rep = "#SSL-END(\n|.)*\/redirect\/.*\*.conf;"
|
||||
rep = "#SSL-END(\n|.)*\\/redirect\\/.*\\*.conf;"
|
||||
ng_conf = re.sub(rep,'#SSL-END',ng_conf)
|
||||
public.writeFile(ng_file, ng_conf)
|
||||
|
||||
@@ -134,18 +134,18 @@ class panelRedirect:
|
||||
if os.path.exists(ap_file):
|
||||
ap_conf = public.readFile(ap_file)
|
||||
if p_conf == "[]":
|
||||
rep = "\n*%s\n+\s+IncludeOptiona[\s\w\/\.\*]+" % public.get_msg_gettext('#referenced redirect rule, if commented, the configured redirect rule will be invalid')
|
||||
rep = "\n*%s\n+\\s+IncludeOptiona[\\s\\w\\/\\.\\*]+" % public.get_msg_gettext('#referenced redirect rule, if commented, the configured redirect rule will be invalid')
|
||||
ap_conf = re.sub(rep, '', ap_conf)
|
||||
public.writeFile(ap_file, ap_conf)
|
||||
return
|
||||
if sitename in p_conf:
|
||||
rep = "%s(\n|.)+IncludeOptional.*\/redirect\/.*conf" % public.get_msg_gettext('#referenced redirect rule')
|
||||
rep = "%s(\n|.)+IncludeOptional.*\\/redirect\\/.*conf" % public.get_msg_gettext('#referenced redirect rule')
|
||||
rep1 = "combined"
|
||||
if not re.search(rep,ap_conf):
|
||||
ap_conf = ap_conf.replace(rep1, rep1 + "\n\t%s" % public.get_msg_gettext('#referenced redirect rule, if commented, the configured redirect rule will be invalid') +"\n\tIncludeOptional " + ap_redirectfile)
|
||||
public.writeFile(ap_file,ap_conf)
|
||||
else:
|
||||
rep = "\n*%s\n+\s+IncludeOptiona[\s\w\/\.\*]+" % public.get_msg_gettext('#referenced redirect rule, if commented, the configured redirect rule will be invalid')
|
||||
rep = "\n*%s\n+\\s+IncludeOptiona[\\s\\w\\/\\.\\*]+" % public.get_msg_gettext('#referenced redirect rule, if commented, the configured redirect rule will be invalid')
|
||||
ap_conf = re.sub(rep,'', ap_conf)
|
||||
public.writeFile(ap_file, ap_conf)
|
||||
|
||||
@@ -167,7 +167,7 @@ class panelRedirect:
|
||||
if self.__CheckRedirect(get.sitename,get.redirectname,is_error_page):
|
||||
return public.return_msg_gettext(False, 'Specified redirect name already exists')
|
||||
#检测目标URL格式
|
||||
rep = "http(s)?\:\/\/([a-zA-Z0-9][-a-zA-Z0-9]{0,62}\.)+([a-zA-Z0-9][a-zA-Z0-9]{0,62})+.?"
|
||||
rep = r"http(s)?\:\/\/([a-zA-Z0-9][-a-zA-Z0-9]{0,62}\.)+([a-zA-Z0-9][a-zA-Z0-9]{0,62})+.?"
|
||||
if 'tourl' in get and not re.match(rep, get.tourl):
|
||||
return public.returnMsg(False, 'Target URL format is wrong %s' + get.tourl)
|
||||
|
||||
@@ -180,12 +180,12 @@ class panelRedirect:
|
||||
else:
|
||||
if not get.redirectpath:
|
||||
return public.return_msg_gettext(False, 'Please enter redirected path')
|
||||
#repte = "[\?\=\[\]\)\(\*\&\^\%\$\#\@\!\~\`{\}\>\<\,\',\"]+"
|
||||
#repte = "[\\?\\=\\[\\]\\)\\(\\*\\&\\^\\%\\$\\#\\@\\!\\~\\`{\\}\\>\\<\\,\',\"]+"
|
||||
# 检测路径格式
|
||||
if "/" not in get.redirectpath:
|
||||
return public.return_msg_gettext(False, 'Path format is incorrect, the format is /xxx')
|
||||
#if re.search(repte, get.redirectpath):
|
||||
# return public.return_msg_gettext(False, "代理目录不能有以下特殊符号 ?,=,[,],),(,*,&,^,%,$,#,@,!,~,`,{,},>,<,\,',\"]")
|
||||
# return public.return_msg_gettext(False, "代理目录不能有以下特殊符号 ?,=,[,],),(,*,&,^,%,$,#,@,!,~,`,{,},>,<,\\,',\"]")
|
||||
#检测域名是否已经存在配置文件
|
||||
repeatdomain = self.__CheckRepeatDomain(get,action)
|
||||
if repeatdomain:
|
||||
@@ -384,7 +384,7 @@ class panelRedirect:
|
||||
"""
|
||||
if self.__firsturl:redirect_path=self.__firsturl
|
||||
add_type=',R={}]'.format(str(r_type))
|
||||
add_str='#REWRITE-START\n<IfModule mod_rewrite.c>\n RewriteEngine on\n RewriteCond %\{REQUEST_FILENAME\} !-f\n RewriteCond %{REQUEST_FILENAME} !-d\n RewriteRule . '+redirect_path+' [L'+add_type+'\n</IfModule>\n#REWRITE-END'
|
||||
add_str='#REWRITE-START\n<IfModule mod_rewrite.c>\n RewriteEngine on\n RewriteCond %\\{REQUEST_FILENAME\\} !-f\n RewriteCond %{REQUEST_FILENAME} !-d\n RewriteRule . '+redirect_path+' [L'+add_type+'\n</IfModule>\n#REWRITE-END'
|
||||
redirectname_md5 = self.__calc_md5(redirectname)
|
||||
file_path= "%s/panel/vhost/apache/redirect/%s" % (self.setupPath,site_name)
|
||||
public.ExecShell("mkdir -p %s" % file_path)
|
||||
@@ -620,9 +620,9 @@ class panelRedirect:
|
||||
old_conf = public.readFile(conf_path)
|
||||
rep =""
|
||||
if i == "nginx":
|
||||
rep += "#301-START\n+[\s\w\:\/\.\;\$]+#301-END"
|
||||
rep += "#301-START\n+[\\s\\w\\:\\/\\.\\;\\$]+#301-END"
|
||||
if i == "apache":
|
||||
rep += "#301-START[\n\<\>\w\.\s\^\*\$\/\[\]\(\)\:\,\=]+#301-END"
|
||||
rep += "#301-START[\n\\<\\>\\w\\.\\s\\^\\*\\$\\/\\[\\]\\(\\)\\:\\,\\=]+#301-END"
|
||||
conf = re.sub(rep, "", old_conf)
|
||||
public.writeFile(conf_path, conf)
|
||||
public.serviceReload()
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
|
||||
+6
-7
@@ -1,10 +1,10 @@
|
||||
# coding: utf-8
|
||||
# -------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2016 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2016 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# ------------------------------
|
||||
@@ -34,7 +34,7 @@ class panelSSL:
|
||||
|
||||
|
||||
__BINDURL = 'https://www.aapanel.com/api/user' # 获取token 获取官网token
|
||||
# __BINDURL = 'https:///dev.aapanel.com/api/user' # 获取token 获取官网token
|
||||
# __BINDURL = 'http://dev.aapanel.com/api/user' # 获取token 获取官网token
|
||||
|
||||
__CODEURL = 'https://api.bt.cn/Auth/GetBindCode' # 获取绑定验证码
|
||||
__UPATH = 'data/userInfo.json'
|
||||
@@ -66,7 +66,6 @@ class panelSSL:
|
||||
else:
|
||||
self.__userInfo = {}
|
||||
|
||||
# public.print_log('初始化 !!!!!!!!!!!!!!!!!!!用户信息: {}'.format(self.__userInfo))
|
||||
try:
|
||||
if self.__userInfo:
|
||||
# 记录里没有这两个key
|
||||
@@ -141,7 +140,7 @@ class panelSSL:
|
||||
# public.print_log("写入用户信息 @@@@222 {}".format(self.__APIURL + '/user/login'))
|
||||
result = json.loads(rtmp)
|
||||
# public.print_log("写入用户信息 @@@@ {}".format(rtmp))
|
||||
public.print_log("写入用户信息 @@@@ {}".format(result))
|
||||
# public.print_log("写入用户信息 @@@@ {}".format(result))
|
||||
if result['success']:
|
||||
bind = 'data/bind.pl'
|
||||
if os.path.exists(bind): os.remove(bind)
|
||||
@@ -1056,7 +1055,7 @@ class panelSSL:
|
||||
if cert_list and all_domain:
|
||||
for cert in cert_list:
|
||||
d_cert = ''
|
||||
if re.match("^\*\..*", cert):
|
||||
if re.match(r"^\*\..*", cert):
|
||||
d_cert = cert.replace('*.', '')
|
||||
for domain in all_domain:
|
||||
if cert == domain:
|
||||
|
||||
+21
-21
@@ -14,26 +14,26 @@ class safe:
|
||||
ev = public.GetMsg("EXPLOITABLE_VULNERABILITIES")
|
||||
dc = public.GetMsg("DANGEROUS_CITATION")
|
||||
rulelist = [
|
||||
{'msg':get_post_ev,'level':danger,'code':'(\$_(GET|POST|REQUEST)\[.{0,15}\]\s{0,10}\(\s{0,10}\$_(GET|POST|REQUEST)\[.{0,15}\]\))'},
|
||||
{'msg':one_word_th,'level':high_risk,'code':'((eval|assert)(\s|\n)*\((\s|\n)*\$_(POST|GET|REQUEST)\[.{0,15}\]\))'},
|
||||
{'msg':one_word_th,'level':high_risk,'code':'(eval(\s|\n)*\(base64_decode(\s|\n)*\((.|\n){1,200})'},
|
||||
{'msg':webshell,'level':danger,'code':'(function\_exists\s*\(\s*[\'|\"](shell\_exec|system|popen|exec|proc\_open|passthru)+[\'|\"]\s*\))'},
|
||||
{'msg':webshell,'level':danger,'code':'((exec|shell\_exec|passthru)+\s*\(\s*\$\_(\w+)\[(.*)\]\s*\))'},
|
||||
{'msg':ev,'level':danger,'code':'(\$(\w+)\s*\(\s.chr\(\d+\)\))'},
|
||||
{'msg':webshell,'level':danger,'code':'(\$(\w+)\s*\$\{(.*)\})'},
|
||||
{'msg':get_post_cookie_ev,'level':danger,'code':'(\$(\w+)\s*\(\s*\$\_(GET|POST|REQUEST|COOKIE|SERVER)+\[(.*)\]\s*\))'},
|
||||
{'msg':get_post_cookie_ev,'level':danger,'code':'(\$\_(GET|POST|REQUEST|COOKIE|SERVER)+\[(.*)\]\(\s*\$(.*)\))'},
|
||||
{'msg':webshell,'level':danger,'code':'(\$\_\=(.*)\$\_)'},
|
||||
{'msg':webshell,'level':danger,'code':'(\$(.*)\s*\((.*)\/e(.*)\,\s*\$\_(.*)\,(.*)\))'},
|
||||
{'msg':webshell,'level':danger,'code':'(new com\s*\(\s*[\'|\"]shell(.*)[\'|\"]\s*\))'},
|
||||
{'msg':webshell,'level':danger,'code':'(echo\s*curl\_exec\s*\(\s*\$(\w+)\s*\))'},
|
||||
{'msg':public.GetMsg("HAZARDOUS_FILE_OPERATION_VULNERABILITIES"),'level':high_risk,'code':'((fopen|fwrite|fputs|file\_put\_contents)+\s*\((.*)\$\_(GET|POST|REQUEST|COOKIE|SERVER)+\[(.*)\](.*)\))'},
|
||||
{'msg':public.GetMsg("DANGEROUS_UPLOAD_VULNERABILITIES"),'level':danger,'code':'(\(\s*\$\_FILES\[(.*)\]\[(.*)\]\s*\,\s*\$\_(GET|POST|REQUEST)+\[(.*)\]\[(.*)\]\s*\))'},
|
||||
{'msg':dc,'level':high_risk,'code':'(\$\_(\w+)(.*)(eval|assert|include|require|include\_once|require\_once)+\s*\(\s*\$(\w+)\s*\))'},
|
||||
{'msg':dc,'level':high_risk,'code':'((include|require|include\_once|require\_once)+\s*\(\s*[\'|\"](\w+)\.(jpg|gif|ico|bmp|png|txt|zip|rar|htm|css|js)+[\'|\"]\s*\))'},
|
||||
{'msg':ev,'level':danger,'code':'(eval\s*\(\s*\(\s*\$\$(\w+))'},
|
||||
{'msg':one_word_th,'level':high_risk,'code':'((eval|assert|include|require|include\_once|require\_once|array\_map|array\_walk)+\s*\(\s*\$\_(GET|POST|REQUEST|COOKIE|SERVER|SESSION)+\[(.*)\]\s*\))'},
|
||||
{'msg':one_word_th,'level':danger,'code':'(preg\_replace\s*\((.*)\(base64\_decode\(\$)'}
|
||||
{'msg':get_post_ev,'level':danger,'code':r'(\$_(GET|POST|REQUEST)\[.{0,15}\]\s{0,10}\(\s{0,10}\$_(GET|POST|REQUEST)\[.{0,15}\]\))'},
|
||||
{'msg':one_word_th,'level':high_risk,'code':'((eval|assert)(\\s|\n)*\\((\\s|\n)*\\$_(POST|GET|REQUEST)\\[.{0,15}\\]\\))'},
|
||||
{'msg':one_word_th,'level':high_risk,'code':'(eval(\\s|\n)*\\(base64_decode(\\s|\n)*\\((.|\n){1,200})'},
|
||||
{'msg':webshell,'level':danger,'code':'(function\\_exists\\s*\\(\\s*[\'|\"](shell\\_exec|system|popen|exec|proc\\_open|passthru)+[\'|\"]\\s*\\))'},
|
||||
{'msg':webshell,'level':danger,'code':r'((exec|shell\_exec|passthru)+\s*\(\s*\$\_(\w+)\[(.*)\]\s*\))'},
|
||||
{'msg':ev,'level':danger,'code':r'(\$(\w+)\s*\(\s.chr\(\d+\)\))'},
|
||||
{'msg':webshell,'level':danger,'code':r'(\$(\w+)\s*\$\{(.*)\})'},
|
||||
{'msg':get_post_cookie_ev,'level':danger,'code':r'(\$(\w+)\s*\(\s*\$\_(GET|POST|REQUEST|COOKIE|SERVER)+\[(.*)\]\s*\))'},
|
||||
{'msg':get_post_cookie_ev,'level':danger,'code':r'(\$\_(GET|POST|REQUEST|COOKIE|SERVER)+\[(.*)\]\(\s*\$(.*)\))'},
|
||||
{'msg':webshell,'level':danger,'code':r'(\$\_\=(.*)\$\_)'},
|
||||
{'msg':webshell,'level':danger,'code':r'(\$(.*)\s*\((.*)\/e(.*)\,\s*\$\_(.*)\,(.*)\))'},
|
||||
{'msg':webshell,'level':danger,'code':'(new com\\s*\\(\\s*[\'|\"]shell(.*)[\'|\"]\\s*\\))'},
|
||||
{'msg':webshell,'level':danger,'code':r'(echo\s*curl\_exec\s*\(\s*\$(\w+)\s*\))'},
|
||||
{'msg':public.GetMsg("HAZARDOUS_FILE_OPERATION_VULNERABILITIES"),'level':high_risk,'code':r'((fopen|fwrite|fputs|file\_put\_contents)+\s*\((.*)\$\_(GET|POST|REQUEST|COOKIE|SERVER)+\[(.*)\](.*)\))'},
|
||||
{'msg':public.GetMsg("DANGEROUS_UPLOAD_VULNERABILITIES"),'level':danger,'code':r'(\(\s*\$\_FILES\[(.*)\]\[(.*)\]\s*\,\s*\$\_(GET|POST|REQUEST)+\[(.*)\]\[(.*)\]\s*\))'},
|
||||
{'msg':dc,'level':high_risk,'code':r'(\$\_(\w+)(.*)(eval|assert|include|require|include\_once|require\_once)+\s*\(\s*\$(\w+)\s*\))'},
|
||||
{'msg':dc,'level':high_risk,'code':'((include|require|include\\_once|require\\_once)+\\s*\\(\\s*[\'|\"](\\w+)\\.(jpg|gif|ico|bmp|png|txt|zip|rar|htm|css|js)+[\'|\"]\\s*\\))'},
|
||||
{'msg':ev,'level':danger,'code':r'(eval\s*\(\s*\(\s*\$\$(\w+))'},
|
||||
{'msg':one_word_th,'level':high_risk,'code':r'((eval|assert|include|require|include\_once|require\_once|array\_map|array\_walk)+\s*\(\s*\$\_(GET|POST|REQUEST|COOKIE|SERVER|SESSION)+\[(.*)\]\s*\))'},
|
||||
{'msg':one_word_th,'level':danger,'code':r'(preg\_replace\s*\((.*)\(base64\_decode\(\$)'}
|
||||
]
|
||||
|
||||
ruleFile = '/www/server/panel/data/ruleList.conf';
|
||||
@@ -101,7 +101,7 @@ class safe:
|
||||
def checkPHPINI(self):
|
||||
setupPath = '/www/server';
|
||||
phps = public.get_php_versions()
|
||||
rep = "disable_functions\s*=\s*(.+)\n"
|
||||
rep = "disable_functions\\s*=\\s*(.+)\n"
|
||||
defs = ['passthru','exec','system','chroot','chgrp','chown','shell_exec','popen','ini_alter','ini_restore','dl','openlog','syslog','readlink','symlink','popepassthru']
|
||||
data = []
|
||||
for phpv in phps:
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2017 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2017 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
@@ -32,8 +32,8 @@ class SafeController:
|
||||
if args['mod_name'] in ['base']: return public.return_status_code(1000,'wrong call!')
|
||||
public.exists_args('def_name,mod_name',args)
|
||||
if args['def_name'].find('__') != -1: return public.return_status_code(1000,'The called method name cannot contain the "__" character')
|
||||
if not re.match(r"^\w+$",args['mod_name']): return public.return_status_code(1000,'The called module name cannot contain characters other than \w')
|
||||
if not re.match(r"^\w+$",args['def_name']): return public.return_status_code(1000,'The called module name cannot contain characters other than \w')
|
||||
if not re.match(r"^\w+$",args['mod_name']): return public.return_status_code(1000,r'The called module name cannot contain characters other than \w')
|
||||
if not re.match(r"^\w+$",args['def_name']): return public.return_status_code(1000,r'The called module name cannot contain characters other than \w')
|
||||
except:
|
||||
return public.get_error_object()
|
||||
# 参数处理
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | version :1.0
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 梁凯强 <1249648969@qq.com>
|
||||
# | Author: 梁凯强 <1249648969@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
# | 快速检索
|
||||
# +--------------------------------------------------------------------
|
||||
|
||||
+213
-188
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2017 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2017 aaPanel(www.aapanel.com) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
|
||||
+5
-5
@@ -1,10 +1,10 @@
|
||||
#coding: utf-8
|
||||
# -------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2019-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# Copyright (c) 2019-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# Author: hwliang <hwl@aapanel.com>
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# ------------------------------
|
||||
@@ -369,7 +369,7 @@ class bt_task:
|
||||
self.install_rar()
|
||||
pass_opt = '-p-'
|
||||
if password:
|
||||
password = password.replace("&","\&").replace('"','\"')
|
||||
password = password.replace("&",r"\&").replace('"','\"')
|
||||
pass_opt = '-p"{}"'.format(password)
|
||||
|
||||
public.ExecShell(rar_file + ' x '+ pass_opt +' -u -y "' + sfile + '" "' + dfile + '" &> ' + log_file)
|
||||
@@ -571,7 +571,7 @@ class bt_task:
|
||||
public.ExecShell("sed -i '/password=/d' " + my_cnf)
|
||||
if act:
|
||||
mycnf = public.readFile(my_cnf)
|
||||
rep = "\[mysqldump\]\nuser=root"
|
||||
rep = "\\[mysqldump\\]\nuser=root"
|
||||
sea = "[mysqldump]\n"
|
||||
subStr = sea + "user=root\npassword=\"" + root + "\"\n"
|
||||
mycnf = mycnf.replace(sea, subStr)
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <2020-05-18>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/python
|
||||
#coding: utf-8
|
||||
# Author: lkqiang<lkq@bt.cn>
|
||||
# Author: lkqiang<lkq@aapanel.com>
|
||||
# panelWaf.py
|
||||
# code: 面板基础安全类
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <2020-08-04>
|
||||
# +-------------------------------------------------------------------
|
||||
@@ -227,7 +227,7 @@ class panelWarning:
|
||||
if not os.path.exists(self.new_vul_list):
|
||||
if zip_file != '':
|
||||
downfile = self.__path+'/'+zip_file
|
||||
public.downloadFile("/safe_warning/{}".format(public.get_url(),zip_file), downfile)
|
||||
public.downloadFile("{}/safe_warning/{}".format(public.get_url(), zip_file), downfile)
|
||||
o, e = public.ExecShell("unzip -o {} -d {}".format(downfile, self.__path))
|
||||
# 解压报错
|
||||
if e != "":
|
||||
@@ -1433,9 +1433,9 @@ if __name__ == "__main__":
|
||||
|
||||
# #coding: utf-8
|
||||
# # +-------------------------------------------------------------------
|
||||
# # | 宝塔Linux面板
|
||||
# # | aaPanel
|
||||
# # +-------------------------------------------------------------------
|
||||
# # | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# # | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# # +-------------------------------------------------------------------
|
||||
# # | Author: hwliang <2020-08-04>
|
||||
# # +-------------------------------------------------------------------
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
// +-------------------------------------------------------------------
|
||||
// | 宝塔Linux面板
|
||||
// | aaPanel
|
||||
// +-------------------------------------------------------------------
|
||||
// | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
// | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
// +-------------------------------------------------------------------
|
||||
// | Author: hwliang <hwl@bt.cn>
|
||||
// | Author: hwliang <hwl@aapanel.com>
|
||||
// +-------------------------------------------------------------------
|
||||
|
||||
// +-------------------------------------------------------------------
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# coding: utf-8
|
||||
# -------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
# aaPanel
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: zhwwen <zhw@bt.cn>
|
||||
# Author: zhwwen <zhw@aapanel.com>
|
||||
# -------------------------------------------------------------------
|
||||
#
|
||||
# ------------------------------
|
||||
@@ -127,7 +127,7 @@ class panel_restore:
|
||||
def restore_website_backup(self,args):
|
||||
"""
|
||||
@name 恢复站点文件
|
||||
@author zhwen<zhw@bt.cn>
|
||||
@author zhwen<zhw@aapanel.com>
|
||||
@parma file_name 备份得文件名
|
||||
@parma site_id 网站id
|
||||
"""
|
||||
@@ -171,7 +171,7 @@ class panel_restore:
|
||||
def get_progress(self, get):
|
||||
"""
|
||||
@name 获取进度日志
|
||||
@author zhwen<zhw@bt.cn>
|
||||
@author zhwen<zhw@aapanel.com>
|
||||
"""
|
||||
# result = public.GetNumLines(self._progress_file, 20)
|
||||
result = public.ExecShell('tail -n 20 {}'.format(self._progress_file))[0]
|
||||
@@ -183,7 +183,7 @@ class panel_restore:
|
||||
def restore_db_backup(self,args):
|
||||
"""
|
||||
@name 恢复站点文件
|
||||
@author zhwen<zhw@bt.cn>
|
||||
@author zhwen<zhw@aapanel.com>
|
||||
@parma file_name 备份得文件名 /www/backup/database/db_test_com_20200817_112722.sql.gz|Google Drive|db_test_com_20200817_112722.sql.gz
|
||||
@parma obj_name 数据库名
|
||||
"""
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | version :1.0
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 梁凯强 <1249648969@qq.com>
|
||||
# | Author: 梁凯强 <1249648969@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
# | 快速检索
|
||||
# +--------------------------------------------------------------------
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板 x3
|
||||
# | aaPanel x3
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2017 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2017 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: zhw <zhw@bt.cn>
|
||||
# | Author: zhw <zhw@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
import public
|
||||
@@ -59,12 +59,42 @@ class panel_telegram_bot:
|
||||
|
||||
# 使用tg机器人发送消息
|
||||
def send_by_tg_bot(self,content,parse_mode=None):
|
||||
"""
|
||||
@author hezhihong
|
||||
"""
|
||||
|
||||
"parse_mode 消息格式 html/markdown/markdownv2"
|
||||
content = self.process_character(content)
|
||||
|
||||
# content = self.process_character(content)
|
||||
conf = self.get_tg_conf()
|
||||
try:
|
||||
bot = telegram.Bot(conf['bot_token'])
|
||||
result = bot.send_message(text=content, chat_id=int(conf['my_id']), parse_mode="MarkdownV2")
|
||||
return result
|
||||
result= self.send_message(conf['bot_token'],conf['my_id'],content)
|
||||
if not result['status']:
|
||||
return False
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
return False
|
||||
|
||||
|
||||
def send_message(self, bot_token, chat_id, msg):
|
||||
"""
|
||||
tg发送信息
|
||||
@msg 消息正文
|
||||
@author hezhihong
|
||||
"""
|
||||
msg = self.process_character(msg)
|
||||
url = 'https://api.telegram.org/bot{}/sendMessage'.format(bot_token)
|
||||
data = {
|
||||
'chat_id': chat_id,
|
||||
'text': msg,
|
||||
'parse_mode':'MarkdownV2',
|
||||
}
|
||||
try:
|
||||
import requests
|
||||
response = requests.post(url, json=data)
|
||||
if response.status_code == 200:
|
||||
return public.returnMsg(True,0,response.json())
|
||||
else:
|
||||
return public.returnMsg(False,json.loads(response.text))
|
||||
except Exception as e:
|
||||
return public.returnMsg(False,str(e))
|
||||
|
||||
+13
-13
@@ -1,10 +1,10 @@
|
||||
# coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# | aaPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# | Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: lkqiang <lkq@bt.cn>
|
||||
# | Author: lkqiang <lkq@aapanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
# +--------------------------------------------------------------------
|
||||
# | 密码管理
|
||||
@@ -88,7 +88,7 @@ class password:
|
||||
|
||||
# 开启密码登陆
|
||||
def SetPassword(self, get):
|
||||
ssh_password = '\n#?PasswordAuthentication\s\w+'
|
||||
ssh_password = '\n#?PasswordAuthentication\\s\\w+'
|
||||
file = public.readFile('/etc/ssh/sshd_config')
|
||||
if len(re.findall(ssh_password, file)) == 0:
|
||||
file_result = file + '\nPasswordAuthentication yes'
|
||||
@@ -114,15 +114,15 @@ class password:
|
||||
public.ExecShell("ssh-keygen -t %s -P '' -f ~/.ssh/id_rsa |echo y" % type)
|
||||
if os.path.exists(file[0]):
|
||||
public.ExecShell('cat %s >%s && chmod 600 %s' % (file[0], file[-1], file[-1]))
|
||||
rec = '\n#?RSAAuthentication\s\w+'
|
||||
rec2 = '\n#?PubkeyAuthentication\s\w+'
|
||||
rec = '\n#?RSAAuthentication\\s\\w+'
|
||||
rec2 = '\n#?PubkeyAuthentication\\s\\w+'
|
||||
file = public.readFile('/etc/ssh/sshd_config')
|
||||
if len(re.findall(rec, file)) == 0: file = file + '\nRSAAuthentication yes'
|
||||
if len(re.findall(rec2, file)) == 0: file = file + '\nPubkeyAuthentication yes'
|
||||
file_ssh = re.sub(rec, '\nRSAAuthentication yes', file)
|
||||
file_result = re.sub(rec2, '\nPubkeyAuthentication yes', file_ssh)
|
||||
if ssh == 'no':
|
||||
ssh_password = '\n#?PasswordAuthentication\s\w+'
|
||||
ssh_password = '\n#?PasswordAuthentication\\s\\w+'
|
||||
if len(re.findall(ssh_password, file_result)) == 0:
|
||||
file_result = file_result + '\nPasswordAuthentication no'
|
||||
else:
|
||||
@@ -137,8 +137,8 @@ class password:
|
||||
# 关闭sshkey
|
||||
def StopKey(self, get):
|
||||
file = ['/root/.ssh/id_rsa.pub', '/root/.ssh/id_rsa', '/root/.ssh/authorized_keys']
|
||||
rec = '\n#?RSAAuthentication\s\w+'
|
||||
rec2 = '\n#?PubkeyAuthentication\s\w+'
|
||||
rec = '\n#?RSAAuthentication\\s\\w+'
|
||||
rec2 = '\n#?PubkeyAuthentication\\s\\w+'
|
||||
file = public.readFile('/etc/ssh/sshd_config')
|
||||
file_ssh = re.sub(rec, '\n#RSAAuthentication no', file)
|
||||
file_result = re.sub(rec2, '\n#PubkeyAuthentication no', file_ssh)
|
||||
@@ -151,9 +151,9 @@ class password:
|
||||
def GetConfig(self, get):
|
||||
result = {}
|
||||
file = public.readFile('/etc/ssh/sshd_config')
|
||||
rec = '\n#?RSAAuthentication\s\w+'
|
||||
pubkey = '\n#?PubkeyAuthentication\s\w+'
|
||||
ssh_password = '\nPasswordAuthentication\s\w+'
|
||||
rec = '\n#?RSAAuthentication\\s\\w+'
|
||||
pubkey = '\n#?PubkeyAuthentication\\s\\w+'
|
||||
ssh_password = '\nPasswordAuthentication\\s\\w+'
|
||||
ret = re.findall(ssh_password, file)
|
||||
if not ret:
|
||||
result['password'] = 'no'
|
||||
@@ -183,7 +183,7 @@ class password:
|
||||
# 关闭密码方式
|
||||
def StopPassword(self, get):
|
||||
file = public.readFile('/etc/ssh/sshd_config')
|
||||
ssh_password = '\n#?PasswordAuthentication\s\w+'
|
||||
ssh_password = '\n#?PasswordAuthentication\\s\\w+'
|
||||
file_result = re.sub(ssh_password, '\nPasswordAuthentication no', file)
|
||||
self.Wirte('/etc/ssh/sshd_config', file_result)
|
||||
self.RestartSsh()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user