mirror of
https://github.com/aaPanel/aaPanel.git
synced 2026-08-17 21:25:47 +02:00
Update to 7.10.0
[+] Add Mail Server to the left menu. [+] Add Mail Server - WebMail (requires Mail Server upgrade 5.1) [+] Add WP Toolkit Plugin, Theme installation. [+] Add Mail Server Login info. [+] Add Mail Server WebMail One-click Login (requires Mail Server upgrade 5.2). [+] Redesigned Security - Firewall. [*] Optimized Mass Mail sending speed. [*] Optimized the CPU usage problem of aaPanel startup service. [-] Fix apache application, renew SSL issue. [-] Fix Let's Encrypt account registeration failed. [-] Fix openlitespeed using capital letters on domain name caused the website cannot be accessed issue. [-] Fix problem of failure to reset root password in some versions of MariaDB. [-] Fix an error in modifying Permission in some cases of MySQL. [-] Fix the Website category display problem.
This commit is contained in:
+178
-37
@@ -70,6 +70,7 @@ class acme_v2:
|
||||
_conf_file = 'config/letsencrypt.json'
|
||||
_conf_file_v2 = 'config/letsencrypt_v2.json'
|
||||
_request_type = 'curl'
|
||||
_stop_rp_file = '{}/data/stop_rp_when_renew_ssl.pl'.format(public.get_panel_path())
|
||||
|
||||
def __init__(self):
|
||||
if not os.path.exists(self._conf_file_v2) and os.path.exists(self._conf_file):
|
||||
@@ -1752,62 +1753,187 @@ fullchain.pem Paste into certificate input box
|
||||
|
||||
if not os.path.exists(args.auth_to):
|
||||
return public.return_msg_gettext(False, 'Invalid site directory, please check if the specified site exists!')
|
||||
try:
|
||||
# 检查认证环境
|
||||
check_result = self.check_auth_env(args)
|
||||
if check_result:
|
||||
return check_result
|
||||
|
||||
# 检查认证环境
|
||||
check_result = self.check_auth_env(args)
|
||||
if check_result:
|
||||
return check_result
|
||||
return self.apply_cert(json.loads(args.domains), args.auth_type, args.auth_to)
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
self.turnon_redirect_proxy_httptohttps(args)
|
||||
|
||||
return self.apply_cert(json.loads(args.domains), args.auth_type, args.auth_to)
|
||||
|
||||
# 检查认证环境
|
||||
def check_auth_env(self,args):
|
||||
for domain in json.loads(args.domains):
|
||||
if public.checkIp(domain): continue
|
||||
if domain.find('*.') != -1 and args.auth_type in ['http','tls']:
|
||||
return public.return_msg_gettext(False, 'Universal domain names cannot apply for certificates using file verification!')
|
||||
|
||||
data = public.M('sites').where('id=?', (args.id,)).find()
|
||||
if not data:
|
||||
return public.return_msg_gettext(False, "Website lost, unable to continue applying for certificate")
|
||||
else:
|
||||
args.siteName = data['name']
|
||||
site_type = data["project_type"]
|
||||
|
||||
use_nginx_conf_to_auth = False
|
||||
if args.auth_type in ['http', 'tls'] and public.get_webserver() == "nginx": # nginx 在lua验证和可重启的
|
||||
if self.can_use_lua_for_site(args.siteName, site_type):
|
||||
use_nginx_conf_to_auth = True
|
||||
else:
|
||||
if self.can_use_if_for_file_check(args.siteName, site_type):
|
||||
use_nginx_conf_to_auth = True
|
||||
|
||||
def turnon_redirect_proxy_httptohttps(self, args):
|
||||
import panelSite
|
||||
s = panelSite.panelSite()
|
||||
if args.auth_type in ['http', 'tls'] and use_nginx_conf_to_auth is False:
|
||||
if not 'siteName' in args:
|
||||
args.siteName = public.M('sites').where('id=?', (args.id,)).getField('name')
|
||||
args.sitename = args.siteName
|
||||
self.turnon_redirect(args, s)
|
||||
self.turnon_proxy(args, s)
|
||||
self.turnon_httptohttps(args, s)
|
||||
public.serviceReload()
|
||||
|
||||
def turnon_httptohttps(self, args, s):
|
||||
conf_file = '{}/data/stop_httptohttps.pl'.format(public.get_panel_path())
|
||||
if os.path.exists(conf_file):
|
||||
write_log('|-Turning on http to https')
|
||||
s.HttpToHttps(args)
|
||||
try:
|
||||
os.remove(conf_file)
|
||||
except:
|
||||
pass
|
||||
|
||||
def turnon_proxy(self, args, s):
|
||||
conf_file = '{}/data/stop_p_tmp.pl'.format(public.get_panel_path())
|
||||
if not os.path.exists(conf_file):
|
||||
return
|
||||
write_log('|-Turning on proxy')
|
||||
conf = json.loads(public.readFile(conf_file))
|
||||
data = s.GetProxyList(args)
|
||||
for x in data:
|
||||
if x['sitename'] not in conf:
|
||||
continue
|
||||
if x['proxyname'] not in conf[x['sitename']]:
|
||||
continue
|
||||
args.type = 1
|
||||
args.advanced = x['advanced']
|
||||
args.cache = x['cache']
|
||||
args.cachetime = x['cachetime']
|
||||
args.proxydir = x['proxydir']
|
||||
args.proxyname = x['proxyname']
|
||||
args.proxysite = x['proxysite']
|
||||
args.sitename = x['sitename']
|
||||
args.subfilter = json.dumps(x['subfilter'])
|
||||
args.todomain = x['todomain']
|
||||
s.ModifyProxy(args)
|
||||
try:
|
||||
os.remove(conf_file)
|
||||
except:
|
||||
pass
|
||||
|
||||
def turnon_redirect(self, args, s):
|
||||
conf_file = '{}/data/stop_r_tmp.pl'.format(public.get_panel_path())
|
||||
if not os.path.exists(conf_file):
|
||||
return
|
||||
write_log('|-Turning on redirection')
|
||||
conf = json.loads(public.readFile(conf_file))
|
||||
data = s.GetRedirectList(args)
|
||||
for x in data:
|
||||
if x['sitename'] not in conf:
|
||||
continue
|
||||
if x['redirectname'] not in conf[x['sitename']]:
|
||||
continue
|
||||
args.type = 1
|
||||
args.sitename = x['sitename']
|
||||
args.holdpath = x['holdpath']
|
||||
args.redirectname = x['redirectname']
|
||||
args.redirecttype = x['redirecttype']
|
||||
args.domainorpath = x['domainorpath']
|
||||
args.redirectpath = x['redirectpath']
|
||||
args.redirectdomain = json.dumps(x['redirectdomain'])
|
||||
args.tourl = x['tourl']
|
||||
s.ModifyRedirect(args)
|
||||
try:
|
||||
os.remove(conf_file)
|
||||
except:
|
||||
pass
|
||||
|
||||
# 检查认证环境
|
||||
def check_auth_env(self, args, check=None):
|
||||
if not check:
|
||||
return
|
||||
for domain in json.loads(args.domains):
|
||||
if public.checkIp(domain): continue
|
||||
if domain.find('*.') != -1 and args.auth_type in ['http', 'tls']:
|
||||
raise public.return_msg_gettext(False,
|
||||
'Pan domain names cannot apply for a certificate using [File Verification]!')
|
||||
import panelSite
|
||||
s = panelSite.panelSite()
|
||||
if args.auth_type in ['http', 'tls']:
|
||||
try:
|
||||
rp_conf = public.readFile(self._stop_rp_file)
|
||||
try:
|
||||
if rp_conf:
|
||||
rp_conf = json.loads(rp_conf)
|
||||
except:
|
||||
write_log('|-Failed to parse configuration file')
|
||||
if not 'siteName' in args:
|
||||
args.siteName = public.M('sites').where('id=?', (args.id,)).getField('name')
|
||||
args.sitename = args.siteName
|
||||
data = s.GetRedirectList(args)
|
||||
# 检查重定向是否开启
|
||||
if type(data) == list:
|
||||
redirect_tmp = {args.sitename: []}
|
||||
for x in data:
|
||||
if x['type']: return public.return_msg_gettext(False,
|
||||
if rp_conf and x['sitename'] in rp_conf:
|
||||
if str(x['type']) == '0':
|
||||
continue
|
||||
args.type = 0
|
||||
args.sitename = x['sitename']
|
||||
args.holdpath = x['holdpath']
|
||||
args.redirectname = x['redirectname']
|
||||
args.redirecttype = x['redirecttype']
|
||||
args.domainorpath = x['domainorpath']
|
||||
args.redirectpath = x['redirectpath']
|
||||
args.redirectdomain = json.dumps(x['redirectdomain'])
|
||||
args.tourl = x['tourl']
|
||||
args.notreload = True
|
||||
write_log("|- Turning off redirection {}".format(args.redirectname))
|
||||
s.ModifyRedirect(args)
|
||||
redirect_tmp[args.sitename].append(x['redirectname'])
|
||||
else:
|
||||
if x['type']: return public.return_msg_gettext(False,
|
||||
'Your site has 301 Redirect on,Please turn it off first!')
|
||||
if redirect_tmp[args.sitename]:
|
||||
public.writeFile('{}/data/stop_r_tmp.pl'.format(public.get_panel_path()),
|
||||
json.dumps(redirect_tmp))
|
||||
data = s.GetProxyList(args)
|
||||
# # 检查反向代理是否开启
|
||||
# if type(data) == list:
|
||||
# for x in data:
|
||||
# if x['type']: return public.return_msg_gettext(False,
|
||||
# 'Sites with reverse proxy turned on cannot apply for SSL!')
|
||||
# 检查反向代理是否开启
|
||||
if type(data) == list:
|
||||
proxy_tmp = {args.sitename: []}
|
||||
for x in data:
|
||||
if rp_conf and x['sitename'] in rp_conf:
|
||||
if str(x['type']) == '0':
|
||||
continue
|
||||
args.type = 0
|
||||
args.advanced = x['advanced']
|
||||
args.cache = x['cache']
|
||||
args.cachetime = x['cachetime']
|
||||
args.proxydir = x['proxydir']
|
||||
args.proxyname = x['proxyname']
|
||||
args.proxysite = x['proxysite']
|
||||
args.sitename = x['sitename']
|
||||
args.subfilter = json.dumps(x['subfilter'])
|
||||
args.todomain = x['todomain']
|
||||
args.notreload = True
|
||||
s.ModifyProxy(args)
|
||||
write_log("|- Turning off proxy {}".format(args.proxyname))
|
||||
proxy_tmp[args.sitename].append(x['proxyname'])
|
||||
else:
|
||||
if x['type']: return public.return_msg_gettext(False,
|
||||
'Sites with reverse proxy turned on cannot apply for SSL!')
|
||||
if proxy_tmp[args.sitename]:
|
||||
public.writeFile('{}/data/stop_p_tmp.pl'.format(public.get_panel_path()), json.dumps(proxy_tmp))
|
||||
# 检查旧重定向是否开启
|
||||
data = s.Get301Status(args)
|
||||
if data['status']:
|
||||
return public.return_msg_gettext(False,
|
||||
'The website has been redirected, please close it before applying!')
|
||||
#判断是否强制HTTPS
|
||||
# 判断是否强制HTTPS
|
||||
if s.IsToHttps(args.siteName):
|
||||
return public.return_msg_gettext(False,
|
||||
if os.path.exists(self._stop_rp_file):
|
||||
if rp_conf and args.siteName in rp_conf:
|
||||
write_log("|- Turning off http to https")
|
||||
s.CloseToHttps(args)
|
||||
public.writeFile('{}/data/stop_httptohttps.pl'.format(public.get_panel_path()), '')
|
||||
else:
|
||||
return public.return_msg_gettext(False,
|
||||
'After configuring Force HTTPS, you cannot use [File Verification] to apply for a certificate!')
|
||||
public.serviceReload()
|
||||
except:
|
||||
return False
|
||||
else:
|
||||
@@ -1884,7 +2010,7 @@ fullchain.pem Paste into certificate input box
|
||||
skey_file = '{}/{}/privkey.pem'.format(cert_paths,c_name)
|
||||
skey = public.readFile(skey_file)
|
||||
if not skey: continue
|
||||
if skey == pkey:
|
||||
if skey == pkey or 1==1:
|
||||
args.siteName = c_name
|
||||
site_info = public.M('sites').where('name=?', c_name).find()
|
||||
if not site_info or isinstance(site_info, str):
|
||||
@@ -2176,7 +2302,17 @@ fullchain.pem Paste into certificate input box
|
||||
n = 0
|
||||
self.get_apis()
|
||||
cert = None
|
||||
args = public.to_dict_obj({})
|
||||
for index in order_index:
|
||||
args.domains = json.dumps(self._config['orders'][index]['domains'])
|
||||
args.auth_type = self._config['orders'][index]['auth_type']
|
||||
args.auth_to = self._config['orders'][index]['auth_to']
|
||||
sitename = args.auth_to.split('/')[-1]
|
||||
if not sitename:
|
||||
sitename = self._config['orders'][index]['auth_to'].split('/')[-2]
|
||||
args.siteName = sitename
|
||||
write_log('|-Renew the visa certificate and start checking the environment')
|
||||
self.check_auth_env(args, check=True)
|
||||
n += 1
|
||||
domains = _test_domains(self._config['orders'][index]['domains'], self._config['orders'][index]['auth_to'],self._config['orders'][index]['auth_type'])
|
||||
if len(domains) == 0:
|
||||
@@ -2188,6 +2324,11 @@ fullchain.pem Paste into certificate input box
|
||||
(n, str(self._config['orders'][index]['domains']))))
|
||||
write_log(public.get_msg_gettext('|-Creating order..'))
|
||||
cert = self.renew_cert_to(self._config['orders'][index]['domains'],self._config['orders'][index]['auth_type'],self._config['orders'][index]['auth_to'],index)
|
||||
# aapanel 用
|
||||
try:
|
||||
self.turnon_redirect_proxy_httptohttps(args)
|
||||
except:
|
||||
pass
|
||||
return cert
|
||||
|
||||
except Exception as ex:
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ class panelSetup:
|
||||
if ua.find('spider') != -1 or g.ua.find('bot') != -1:
|
||||
return abort(403)
|
||||
|
||||
g.version = '7.0.6'
|
||||
g.version = '7.10.0'
|
||||
g.title = public.GetConfigValue('title')
|
||||
g.uri = request.path
|
||||
g.debug = os.path.exists('data/debug.pl')
|
||||
|
||||
+13
-3
@@ -828,7 +828,9 @@ SetLink
|
||||
admin_user, my_host[0]))
|
||||
mysql_obj.execute(
|
||||
"ALTER USER `%s`@`%s` IDENTIFIED BY '%s'" % (admin_user, my_host[0], password))
|
||||
elif m_version.find('10.5.') != -1 or m_version.find('10.4.') != -1:
|
||||
# elif m_version.find('10.5.') != -1 or m_version.find('10.4.') != -1:
|
||||
elif any(mariadb_ver in m_version for mariadb_ver in
|
||||
['10.5.', '10.4.', '10.6.', '10.7.', '10.11.', '11.3.']):
|
||||
accept = self.map_to_list(
|
||||
mysql_obj.query("select Host from mysql.user where User='{}'".format(admin_user)))
|
||||
for my_host in accept:
|
||||
@@ -1534,7 +1536,11 @@ SetLink
|
||||
|
||||
if not 'Run' in result and result:
|
||||
result['Run'] = int(time.time()) - int(result['Uptime'])
|
||||
tmp = panelMysql.panelMysql().query('show master status')
|
||||
m_version = public.readFile(public.GetConfigValue('setup_path') + '/mysql/version.pl')
|
||||
if m_version.find('8.4') != -1 or m_version.find('9.0') != -1:
|
||||
tmp = panelMysql.panelMysql().query('SHOW BINARY LOG STATUS')
|
||||
else:
|
||||
tmp = panelMysql.panelMysql().query('show master status')
|
||||
try:
|
||||
|
||||
result['File'] = tmp[0][0]
|
||||
@@ -1558,7 +1564,11 @@ SetLink
|
||||
|
||||
text = public.readFile(index_file)
|
||||
|
||||
rows = panelMysql.panelMysql().query("show master status")
|
||||
m_version = public.readFile(public.GetConfigValue('setup_path') + '/mysql/version.pl')
|
||||
if m_version.find('8.4') != -1 or m_version.find('9.0') != -1:
|
||||
rows = panelMysql.panelMysql().query("SHOW BINARY LOG STATUS")
|
||||
else:
|
||||
rows = panelMysql.panelMysql().query("show master status")
|
||||
|
||||
current_log = ""
|
||||
if not isinstance(rows, list):
|
||||
|
||||
@@ -212,6 +212,7 @@ class Sql():
|
||||
self._close()
|
||||
self.__DB_CONN.commit()
|
||||
self.rm_lock()
|
||||
|
||||
return id
|
||||
except Exception as ex:
|
||||
return "error: " + str(ex)
|
||||
|
||||
+64
-27
@@ -8,26 +8,43 @@
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔HTTP通信库
|
||||
# | 宝塔HTTP通信库
|
||||
# +-------------------------------------------------------------------
|
||||
import os,sys,re
|
||||
import ssl
|
||||
|
||||
import public
|
||||
import json
|
||||
import socket
|
||||
import requests
|
||||
import config
|
||||
import requests.packages.urllib3.util.connection as urllib3_conn
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
|
||||
class http:
|
||||
_ip_type = None
|
||||
def __init__(self):
|
||||
self._ip_type = config.config().get_request_iptype()
|
||||
self._ip_type = self.get_request_iptype()
|
||||
|
||||
def get(self,url,timeout = 60,headers = {},verify = False,type = 'python'):
|
||||
|
||||
def get_request_iptype(self, get=None):
|
||||
'''
|
||||
@name 获取云端请求线路
|
||||
@author hwliang<2022-02-09>
|
||||
@return auto/ipv4/ipv6
|
||||
'''
|
||||
|
||||
v4_file = '{}/data/v4.pl'.format(public.get_panel_path())
|
||||
if not os.path.exists(v4_file): return 'auto'
|
||||
iptype = public.readFile(v4_file).strip()
|
||||
if not iptype: return 'auto'
|
||||
if iptype == '-4': return 'ipv4'
|
||||
return 'ipv6'
|
||||
|
||||
def get(self,url,timeout = (6,60),headers = {},verify = False,type = 'python'):
|
||||
url = self.quote(url)
|
||||
# url = public.get_home_node(url)
|
||||
if type in ['python','src','php']:
|
||||
old_family = urllib3_conn.allowed_gai_family
|
||||
try:
|
||||
@@ -90,8 +107,9 @@ class http:
|
||||
result = self._get_py3(url,timeout,headers,verify)
|
||||
return result
|
||||
|
||||
def post(self,url,data,timeout = 60,headers = {},verify = False,type = 'python'):
|
||||
def post(self,url,data,timeout = (6,60),headers = {},verify = False,type = 'python'):
|
||||
url = self.quote(url)
|
||||
# url = public.get_home_node(url)
|
||||
if type in ['python','src','php']:
|
||||
old_family = urllib3_conn.allowed_gai_family
|
||||
try:
|
||||
@@ -102,7 +120,6 @@ class http:
|
||||
|
||||
result = requests.post(url,data,timeout=timeout,headers=headers,verify=verify)
|
||||
except:
|
||||
public.print_log(public.get_error_info())
|
||||
try:
|
||||
# IPV6?
|
||||
if self._ip_type != 'ipv6':
|
||||
@@ -219,6 +236,8 @@ class http:
|
||||
|
||||
#POST请求,通过CURL
|
||||
def _post_curl(self,url,data,timeout,headers,verify):
|
||||
if isinstance(timeout,tuple):
|
||||
timeout = timeout[1]
|
||||
headers_str = self._str_headers(headers)
|
||||
pdata = self._str_post(data,headers_str)
|
||||
_ssl_verify = ''
|
||||
@@ -229,6 +248,8 @@ class http:
|
||||
|
||||
#POST请求,通过PHP
|
||||
def _post_php(self,url,data,timeout,headers,verify):
|
||||
if isinstance(timeout,tuple):
|
||||
timeout = timeout[1]
|
||||
php_version = self._get_php_version()
|
||||
if not php_version:
|
||||
raise Exception('No PHP version available!')
|
||||
@@ -337,6 +358,8 @@ exit($header."\r\n\r\n".json_encode($body));
|
||||
|
||||
#GET请求,通过CURL
|
||||
def _get_curl(self,url,timeout,headers,verify):
|
||||
if isinstance(timeout,tuple):
|
||||
timeout = timeout[1]
|
||||
headers_str = self._str_headers(headers)
|
||||
_ssl_verify = ''
|
||||
if not verify: _ssl_verify = ' -k'
|
||||
@@ -346,9 +369,12 @@ exit($header."\r\n\r\n".json_encode($body));
|
||||
|
||||
#GET请求,通过PHP
|
||||
def _get_php(self,url,timeout,headers,verify):
|
||||
if isinstance(timeout,tuple):
|
||||
timeout = timeout[1]
|
||||
php_version = self._get_php_version()
|
||||
if not php_version:
|
||||
raise Exception('No PHP version available!')
|
||||
|
||||
ip_type = ''
|
||||
if self._ip_type == 'ipv6':
|
||||
ip_type = 'curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);'
|
||||
@@ -439,21 +465,21 @@ exit($header."\r\n\r\n".json_encode($body));
|
||||
def _curl_format(self,req):
|
||||
match = re.search("(.|\n)+\r\n\r\n",req)
|
||||
if not match: return req,{},0
|
||||
tmp = match.group().split("\r\n")
|
||||
|
||||
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(),'')
|
||||
tmp = match.group()
|
||||
body = req.replace(tmp,'')
|
||||
try:
|
||||
for line in tmp.split('\r\n'):
|
||||
if line.find('HTTP/') != -1:
|
||||
if line.find('Continue') != -1: continue
|
||||
status_code = int(re.search(r'HTTP/[\d\.]+\s(\d+)',line).groups()[0])
|
||||
break
|
||||
if status_code == 100:
|
||||
status_code = 200
|
||||
except:
|
||||
if body:
|
||||
status_code = 200
|
||||
else:
|
||||
status_code = 0
|
||||
return body,tmp,status_code
|
||||
|
||||
#构造适用于PHP的headers
|
||||
@@ -475,13 +501,13 @@ exit($header."\r\n\r\n".json_encode($body));
|
||||
str_pdata = ''
|
||||
if headers.find('application/jose') != -1 \
|
||||
or headers.find('application/josn') != -1:
|
||||
if type(pdata) == dict:
|
||||
if type(pdata) == dict:
|
||||
pdata = json.dumps(pdata)
|
||||
if type(pdata) == bytes:
|
||||
pdata = pdata.decode('utf-8')
|
||||
str_pdata += " -d '{}'".format(pdata)
|
||||
return str_pdata
|
||||
|
||||
|
||||
for key in pdata.keys():
|
||||
str_pdata += " -F '{}={}'".format(key ,pdata[key])
|
||||
return str_pdata
|
||||
@@ -491,13 +517,14 @@ exit($header."\r\n\r\n".json_encode($body));
|
||||
if 'Content-Type' in headers:
|
||||
if headers['Content-Type'].find('application/jose') != -1 \
|
||||
or headers['Content-Type'].find('application/josn') != -1:
|
||||
if type(pdata) == dict:
|
||||
if type(pdata) == dict:
|
||||
pdata = json.dumps(pdata)
|
||||
if type(pdata) == str:
|
||||
pdata = pdata.encode('utf-8')
|
||||
return pdata
|
||||
return public.url_encode(pdata)
|
||||
|
||||
|
||||
#响应头对象
|
||||
class http_headers:
|
||||
def __contains__(self, key):
|
||||
@@ -527,6 +554,12 @@ class response:
|
||||
self.format_headers(headers)
|
||||
|
||||
def format_headers(self,raw_headers):
|
||||
if isinstance(raw_headers,str):
|
||||
raw_headers = raw_headers.strip().split('\r\n')
|
||||
if isinstance(raw_headers,dict):
|
||||
for k in raw_headers.keys():
|
||||
self.headers[k] = raw_headers[k]
|
||||
return
|
||||
raw = []
|
||||
for h in raw_headers:
|
||||
if not h: continue
|
||||
@@ -563,7 +596,7 @@ __version__ = 1.0
|
||||
|
||||
#请请求方法
|
||||
def get_stype(s_type):
|
||||
if not s_type:
|
||||
if not s_type:
|
||||
s_type_file = '/www/server/panel/data/http_type.pl'
|
||||
if os.path.exists(s_type_file):
|
||||
tmp_type = public.readFile(s_type_file)
|
||||
@@ -585,7 +618,7 @@ def get_headers(headers):
|
||||
headers['User-Agent'] = DEFAULT_HEADERS['User-Agent']
|
||||
return headers
|
||||
|
||||
def post(url,data = {},timeout = 60,headers = {},verify = False,s_type = None):
|
||||
def post(url,data = {},timeout = (15,120),headers = {},verify = False,s_type = None):
|
||||
'''
|
||||
POST请求
|
||||
@param [url] string URL地址
|
||||
@@ -595,13 +628,15 @@ def post(url,data = {},timeout = 60,headers = {},verify = False,s_type = None):
|
||||
@param [verify] bool 是否验证ssl证书 默认False
|
||||
@param [s_type] string 请求方法 默认python 可选:curl或php
|
||||
'''
|
||||
if isinstance(timeout,list):
|
||||
timeout = tuple(timeout)
|
||||
p = http()
|
||||
try:
|
||||
return p.post(url,data,timeout,get_headers(headers),verify,get_stype(s_type))
|
||||
except:
|
||||
raise Exception(public.get_error_info())
|
||||
|
||||
def get(url,timeout = 60,headers = {},verify = False,s_type = None):
|
||||
def get(url,timeout = (15,120),headers = {},verify = False,s_type = None):
|
||||
'''
|
||||
GET请求
|
||||
@param [url] string URL地址
|
||||
@@ -610,6 +645,8 @@ def get(url,timeout = 60,headers = {},verify = False,s_type = None):
|
||||
@param [verify] bool 是否验证ssl证书 默认False
|
||||
@param [s_type] string 请求方法 默认python 可选:curl或php
|
||||
'''
|
||||
if isinstance(timeout,list):
|
||||
timeout = tuple(timeout)
|
||||
p = http()
|
||||
try:
|
||||
return p.get(url,timeout,get_headers(headers),verify,get_stype(s_type))
|
||||
|
||||
+2
-2
@@ -42,7 +42,7 @@ def control_init():
|
||||
null_html()
|
||||
remove_other()
|
||||
deb_bashrc()
|
||||
upgrade_gevent()
|
||||
# upgrade_gevent()
|
||||
upgrade_polkit()
|
||||
#hide_docker()
|
||||
rep_pyenv_link()
|
||||
@@ -670,7 +670,7 @@ def files_set_mode():
|
||||
|
||||
recycle_list = public.get_recycle_bin_list()
|
||||
for recycle_path in recycle_list:
|
||||
m_paths.append([recycle_path,'','root',600,True])
|
||||
m_paths.append([recycle_path,'','root',600,False])
|
||||
|
||||
for m in m_paths:
|
||||
if not os.path.exists(m[0]): continue
|
||||
|
||||
+2
-1
@@ -37,7 +37,8 @@ class panelAuth:
|
||||
data['server_id'] = serverid
|
||||
public.writeFile(userPath,json.dumps(data))
|
||||
return data
|
||||
except: return public.return_msg_gettext(False,'Please login with account first')
|
||||
except:
|
||||
return public.return_msg_gettext(False,'Please login with account first')
|
||||
|
||||
|
||||
def create_plugin_other_order(self,get):
|
||||
|
||||
@@ -425,6 +425,7 @@ class panelPlugin:
|
||||
|
||||
softList = public.load_soft_list(True if force == 1 else False)
|
||||
|
||||
|
||||
if get and 'init' in get:
|
||||
if softList:
|
||||
if 'success' not in softList:
|
||||
@@ -809,7 +810,7 @@ class panelPlugin:
|
||||
import one_key_wp
|
||||
one_key_wp.fast_cgi().set_nginx_conf()
|
||||
one_key_wp.fast_cgi().set_nginx_init()
|
||||
public.ExecShell("/etc/init.d/nginx start")
|
||||
public.ExecShell("/etc/init.d/nginx reload")
|
||||
return softList
|
||||
|
||||
#取首页软件列表
|
||||
@@ -1093,6 +1094,7 @@ class panelPlugin:
|
||||
softInfo["php_ini"] = "/usr/local/lsws/lsphp{}/etc/php.ini".format(v1)
|
||||
else:
|
||||
softInfo["php_ini"] = "/www/server/php/{}/etc/php.ini".format(v1)
|
||||
|
||||
return self.check_status(softInfo)
|
||||
|
||||
return False
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
from contextlib import contextmanager
|
||||
import threading
|
||||
|
||||
|
||||
# 存储所有已排序的线程锁
|
||||
_local = threading.local()
|
||||
|
||||
|
||||
@contextmanager
|
||||
def acquire(*locks, timeout=-1):
|
||||
'''
|
||||
@name 避免死锁
|
||||
@author Zhj
|
||||
@param locks<[]threading.Lock> 线程锁
|
||||
@param timeout<integer> 最长阻塞时间/秒
|
||||
@return None
|
||||
'''
|
||||
# 升序排序
|
||||
locks = sorted(locks, key=lambda x: id(x))
|
||||
|
||||
# 确保按顺序加锁
|
||||
acquired = getattr(_local, 'acquired', [])
|
||||
if timeout <= 0 and acquired and max(id(lock) for lock in acquired) >= id(locks[0]):
|
||||
raise RuntimeError('Lock Order Violation')
|
||||
|
||||
# 加锁
|
||||
acquired.extend(locks)
|
||||
_local.acquired = acquired
|
||||
|
||||
try:
|
||||
# 按顺序加锁
|
||||
for lock in locks:
|
||||
lock.acquire(timeout=timeout)
|
||||
|
||||
# 转出程序控制权
|
||||
yield
|
||||
finally:
|
||||
# 倒序释放锁
|
||||
for lock in reversed(locks):
|
||||
try:
|
||||
lock.release()
|
||||
except: pass
|
||||
del (acquired[-len(locks):],)
|
||||
+130
-38
@@ -5,17 +5,12 @@ import json, os, sys, time, re, socket, importlib, binascii, base64, io, string,
|
||||
import gettext
|
||||
import typing
|
||||
import werkzeug.datastructures
|
||||
from .exceptions import PanelError
|
||||
from .validate import Param, trim_filter
|
||||
from .regexplib import match_ipv4, match_ipv6, match_class_private_property, match_safe_path, match_based_host, \
|
||||
find_url_root
|
||||
find_url_root, search_sql_special_chars
|
||||
from .tools import is_number
|
||||
|
||||
|
||||
import collections
|
||||
|
||||
# Common structures
|
||||
aap_t_simple_result = collections.namedtuple('aap_t_simple_result', ['success', 'msg'])
|
||||
aap_t_mysql_dump_info = collections.namedtuple('aap_t_mysql_dump_info', ['db_name', 'file', 'dump_time'])
|
||||
from .structures import aap_t_simple_result, aap_t_mysql_dump_info
|
||||
|
||||
|
||||
es = gettext.translation('en', localedir='/www/server/panel/BTPanel/static/language', languages=['en'])
|
||||
@@ -48,6 +43,24 @@ def M(table):
|
||||
return sql.table(table)
|
||||
|
||||
|
||||
# Easy Sqlite Toolkit for query
|
||||
def S(table_name: typing.Optional[str] = None, db_name: str = 'default'):
|
||||
from .sqlite_easy import Db
|
||||
|
||||
query = Db(db_name).query()
|
||||
|
||||
if table_name is not None and str(table_name).strip() != '':
|
||||
query.table(str(table_name).strip())
|
||||
|
||||
return query
|
||||
|
||||
|
||||
# Easy Sqlite Toolkit for connection
|
||||
def SqliteConn(db_name: str = 'default'):
|
||||
from .sqlite_easy import Db
|
||||
return Db(db_name)
|
||||
|
||||
|
||||
# 连接MYSQL数据库
|
||||
def MysqlConn(db_name: typing.Optional[str] = None, db_user: str = 'root', db_pwd: typing.Optional[str] = None, db_host: str = 'localhost'):
|
||||
from panel_mysql_v2 import PanelMysqlWithContext
|
||||
@@ -1471,30 +1484,30 @@ def checkWebConfig(repair_num=2):
|
||||
"ulimit -n 8192 ; {setup_path}/nginx/sbin/nginx -t -c {setup_path}/nginx/conf/nginx.conf".format(
|
||||
setup_path=setup_path))
|
||||
writeFile('/tmp/nginx_new.conf', readFile('/www/server/nginx/conf/nginx.conf'))
|
||||
print_log('checkWebConfig--result:{}'.format(result))
|
||||
# print_log('checkWebConfig--result:{}'.format(result))
|
||||
searchStr = 'successful'
|
||||
nginx_version = ExecShell("{}/nginx/sbin/nginx -v".format(setup_path))
|
||||
print_log('nginx')
|
||||
# print_log('nginx')
|
||||
version_info = nginx_version[1]
|
||||
elif web_s == 'apache':
|
||||
print_log('apache')
|
||||
# print_log('apache')
|
||||
# else:
|
||||
result = ExecShell("ulimit -n 8192 ; {setup_path}/apache/bin/apachectl -t".format(setup_path=setup_path))
|
||||
searchStr = 'Syntax OK'
|
||||
apache_version = ExecShell("{}/apache/bin/httpd -v".format(setup_path))
|
||||
version_info = apache_version[1]
|
||||
else:
|
||||
print_log('other')
|
||||
# print_log('other')
|
||||
result = ["1", "1"]
|
||||
searchStr = "1"
|
||||
version_info = "Unknow"
|
||||
print_log('checkWebConfig--result1:{}'.format(result))
|
||||
# print_log('checkWebConfig--result1:{}'.format(result))
|
||||
if result[1].find(
|
||||
'the "listen ... http2" directive is deprecated, use the "http2" directive instead') != -1 and web_s == "nginx" and is_change_nginx_http2():
|
||||
if repair_num > 0:
|
||||
repair_num -= 1
|
||||
change_nginx_http2()
|
||||
print_log('nginx----1')
|
||||
# print_log('nginx----1')
|
||||
return checkWebConfig(repair_num)
|
||||
|
||||
if result[1].find(searchStr) == -1:
|
||||
@@ -1503,14 +1516,14 @@ def checkWebConfig(repair_num=2):
|
||||
if repair_num > 0:
|
||||
repair_num -= 1
|
||||
change_nginx_old_http2()
|
||||
print_log('nginx----2')
|
||||
# print_log('nginx----2')
|
||||
return checkWebConfig(repair_num)
|
||||
|
||||
if result[1].find('[emerg] invalid parameter "quic" in') != -1 and web_s == "nginx" and not is_nginx_http3():
|
||||
if repair_num > 0:
|
||||
repair_num -= 1
|
||||
remove_nginx_quic()
|
||||
print_log('nginx----3')
|
||||
# print_log('nginx----3')
|
||||
return checkWebConfig(repair_num)
|
||||
|
||||
WriteLog("TYPE_SOFT", 'CONF_CHECK_ERR', (result[1],))
|
||||
@@ -1525,9 +1538,9 @@ def checkWebConfig(repair_num=2):
|
||||
0, result[1].split("\n")[0].strip())
|
||||
except Exception as e:
|
||||
err_collect(result[1], 0, result[1].split("\n")[0].strip())
|
||||
print_log('nginx----4')
|
||||
# print_log('nginx----4')
|
||||
return result[1]
|
||||
print_log('nginx----5')
|
||||
# print_log('nginx----5')
|
||||
return True
|
||||
|
||||
|
||||
@@ -2326,6 +2339,31 @@ def get_os_version():
|
||||
version = "{} (Py{}.{}.{})".format(version, v_info.major, v_info.minor, v_info.micro)
|
||||
return xsssec(version)
|
||||
|
||||
#获取总大小
|
||||
def get_size_total(paths = []):
|
||||
|
||||
data = {}
|
||||
try:
|
||||
if type(paths) == str:
|
||||
paths = [paths]
|
||||
|
||||
n_list = []
|
||||
for path in paths:
|
||||
if os.path.exists(path):
|
||||
n_list.append(path)
|
||||
else:
|
||||
data[path] = 0
|
||||
|
||||
if len(n_list) > 0:
|
||||
shell = 'du -s {}'.format(' '.join(n_list).strip())
|
||||
res = ExecShell(shell)[0]
|
||||
for n in res.split("\n"):
|
||||
tmp = n.split("\t")
|
||||
if len(tmp) < 2: continue
|
||||
data[tmp[1]] = int(tmp[0]) * 1024
|
||||
except:pass
|
||||
return data
|
||||
|
||||
|
||||
# 取文件或目录大小
|
||||
def get_path_size(path, exclude=[]):
|
||||
@@ -2813,6 +2851,24 @@ def is_local():
|
||||
return os.path.exists(s_file)
|
||||
|
||||
|
||||
# Dump面板数据库结构+数据
|
||||
def dump_panel_databases():
|
||||
backup_path = '{}/data/db_backups'.format(get_panel_path())
|
||||
|
||||
if not os.path.exists(backup_path):
|
||||
os.makedirs(backup_path, 0o755)
|
||||
|
||||
backup_databases = (
|
||||
'default',
|
||||
)
|
||||
|
||||
def row_check_func(row: str) -> bool:
|
||||
return row.find('INSERT INTO "logs" ') < 0
|
||||
|
||||
for db_name in backup_databases:
|
||||
with SqliteConn(db_name) as db:
|
||||
db.dump('{}/{}.sql'.format(backup_path, db_name), row_check_func)
|
||||
|
||||
# 自动备份面板数据
|
||||
def auto_backup_panel():
|
||||
try:
|
||||
@@ -2824,6 +2880,10 @@ def auto_backup_panel():
|
||||
backup_path = b_path + '/' + day_date
|
||||
backup_file = backup_path + '.zip'
|
||||
if os.path.exists(backup_path) or os.path.exists(backup_file): return True
|
||||
|
||||
# 导出面板数据库结构+数据
|
||||
dump_panel_databases()
|
||||
|
||||
ignore_default = ''
|
||||
ignore_system = ''
|
||||
max_size = 100 * 1024 * 1024
|
||||
@@ -4425,6 +4485,22 @@ def get_local_ip():
|
||||
except:
|
||||
return '127.0.0.1'
|
||||
|
||||
def get_local_ip_2():
|
||||
"""获取内网IP"""
|
||||
import socket
|
||||
s = None
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.connect(('8.8.8.8', 80))
|
||||
ip = s.getsockname()[0]
|
||||
return ip
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
if s is not None:
|
||||
s.close()
|
||||
return '127.0.0.1'
|
||||
|
||||
|
||||
def create_logs():
|
||||
import db
|
||||
@@ -4773,19 +4849,6 @@ def is_debug():
|
||||
return os.path.exists(debug_file)
|
||||
|
||||
|
||||
class PanelError(Exception):
|
||||
'''
|
||||
@name 宝塔通用异常对像
|
||||
@author hwliang<2021-06-25>
|
||||
'''
|
||||
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def __str__(self):
|
||||
return ("An error occurred while the panel was running: {}".format(str(self.value)))
|
||||
|
||||
|
||||
def sys_path_append(path):
|
||||
'''
|
||||
@name 追加引用路径
|
||||
@@ -6107,7 +6170,9 @@ def return_area(result, key):
|
||||
tmps.append(data[key])
|
||||
|
||||
res = get_ips_area(tmps)
|
||||
if 'status' in res: return result
|
||||
if 'status' in res:
|
||||
|
||||
return result
|
||||
|
||||
for data in result:
|
||||
if data[key] in res:
|
||||
@@ -8099,6 +8164,7 @@ def run_plugin_v2(plugin_name: str, def_name: str, args: dict_obj):
|
||||
if isinstance(res['msg'], str):
|
||||
if res['msg'].find('Traceback ') != -1:
|
||||
raise PanelError(res['msg'])
|
||||
|
||||
if isinstance(res, dict):
|
||||
if 'status' in res and 'msg' in res:
|
||||
status = 0 if res['status'] else -1
|
||||
@@ -8107,9 +8173,11 @@ def run_plugin_v2(plugin_name: str, def_name: str, args: dict_obj):
|
||||
else:
|
||||
# 改返回
|
||||
res = return_message(0, 0, res)
|
||||
if isinstance(res, list):
|
||||
if isinstance(res, (list, str, int)):
|
||||
res = return_message(0, 0, res)
|
||||
return res
|
||||
|
||||
|
||||
# 加载插件列表与授权列表
|
||||
def load_soft_list(force: bool = True):
|
||||
local_cache_file = '{}/data/plugin_bin.pl'.format(get_panel_path())
|
||||
@@ -8124,12 +8192,33 @@ def load_soft_list(force: bool = True):
|
||||
url_headers = {"authorization": "bt {}".format(pdata['token'])}
|
||||
pdata['environment_info'] = json.dumps(fetch_env_info())
|
||||
|
||||
resp = requests.post(cloudUrl, params=pdata, headers=url_headers, verify=False, timeout=10)
|
||||
update_ok = False
|
||||
ex = None
|
||||
|
||||
# 请求成功后将授权密文信息写入本地文件
|
||||
if resp.status_code == 200:
|
||||
with open(local_cache_file, 'w') as fp:
|
||||
fp.write(resp.text)
|
||||
# 默认重试5次
|
||||
for _ in range(5):
|
||||
try:
|
||||
resp = requests.post(cloudUrl, params=pdata, headers=url_headers, verify=False, timeout=10)
|
||||
|
||||
# 请求成功后将授权密文信息写入本地文件
|
||||
if resp.status_code == 200:
|
||||
with open(local_cache_file, 'w') as fp:
|
||||
fp.write(resp.text)
|
||||
update_ok = True
|
||||
break
|
||||
except Exception as ex:
|
||||
pass
|
||||
|
||||
# 本地缓存存在则让其读取本地缓存
|
||||
if not update_ok:
|
||||
update_ok = os.path.exists(local_cache_file) and os.path.getsize(local_cache_file) >= 10
|
||||
|
||||
# 本地缓存都不存在,如果捕获到异常则抛出异常,否则抛出获取软件列表与授权信息失败的提示
|
||||
if not update_ok:
|
||||
if ex is not None:
|
||||
raise ex
|
||||
|
||||
raise PanelError(get_msg_gettext('Load softlist and authorizations failed, please wait for few moment and try again.'))
|
||||
|
||||
import PluginLoader
|
||||
|
||||
@@ -8275,3 +8364,6 @@ def make_panel_tmp_path_with_context():
|
||||
shutil.rmtree(tmp_path)
|
||||
|
||||
|
||||
# 处理SQL语句中的特殊字符
|
||||
def escape_sql_str(s: str) -> str:
|
||||
return search_sql_special_chars.sub(r'\\\g<0>', s)
|
||||
|
||||
@@ -9,3 +9,17 @@ class HintException(Exception):
|
||||
# 无授权异常
|
||||
class NoAuthorizationException(HintException):
|
||||
pass
|
||||
|
||||
|
||||
# 面板错误异常
|
||||
class PanelError(Exception):
|
||||
'''
|
||||
@name 面板通用异常对像
|
||||
@author hwliang<2021-06-25>
|
||||
'''
|
||||
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def __str__(self):
|
||||
return ("An error occurred while the panel was running: {}".format(str(self.value)))
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
from .acquire import acquire
|
||||
import threading
|
||||
import gc
|
||||
|
||||
|
||||
_GC_DISABLE_COUNT = 0
|
||||
_GC_DISABLE_COUNT_LOCK = threading.Lock()
|
||||
|
||||
|
||||
# 停用GC
|
||||
def gc_disable():
|
||||
with acquire(_GC_DISABLE_COUNT_LOCK, timeout=1):
|
||||
global _GC_DISABLE_COUNT
|
||||
_GC_DISABLE_COUNT += 1
|
||||
if _GC_DISABLE_COUNT > 1:
|
||||
return
|
||||
gc.disable()
|
||||
|
||||
|
||||
# 启用GC
|
||||
def gc_enable():
|
||||
with acquire(_GC_DISABLE_COUNT_LOCK, timeout=1):
|
||||
global _GC_DISABLE_COUNT
|
||||
_GC_DISABLE_COUNT -= 1
|
||||
if _GC_DISABLE_COUNT > 0:
|
||||
return
|
||||
gc.enable()
|
||||
@@ -27,3 +27,6 @@ match_general_version_format = re.compile(r'^\d+(?:\.\d+){1,2}$')
|
||||
|
||||
# md5格式验证
|
||||
match_md5_format = re.compile(r'^[a-fA-F0-9]{32}$')
|
||||
|
||||
# SQL字符串中的常用特殊字符
|
||||
search_sql_special_chars = re.compile(r'''(?<!\\)(?:[%_]|\\(?![^\\abfnrtvxuUN'"0-7]))''')
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
import collections
|
||||
|
||||
# Common structures
|
||||
aap_t_simple_result = collections.namedtuple('aap_t_simple_result', ['success', 'msg'])
|
||||
aap_t_mysql_dump_info = collections.namedtuple('aap_t_mysql_dump_info', ['db_name', 'file', 'dump_time'])
|
||||
@@ -1,6 +1,18 @@
|
||||
import typing
|
||||
|
||||
|
||||
# 创建一个管道函数
|
||||
def make_pipe(fs: typing.List[callable]) -> callable:
|
||||
"""
|
||||
创建一个管道函数
|
||||
@param fs: callable 数据过滤函数
|
||||
@return: any
|
||||
"""
|
||||
def helper(val: any) -> any:
|
||||
return my_pipe(val, fs)
|
||||
return helper
|
||||
|
||||
|
||||
def my_pipe(val: any, fs: typing.List[callable]) -> any:
|
||||
"""
|
||||
管道数据过滤函数
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import copy
|
||||
import re
|
||||
import json
|
||||
import socket
|
||||
@@ -5,6 +6,7 @@ import os
|
||||
import typing
|
||||
from .regexplib import match_ipv4, match_ipv6, match_safe_path, match_based_host
|
||||
from .exceptions import HintException
|
||||
from .structures import aap_t_simple_result
|
||||
|
||||
|
||||
class Param:
|
||||
@@ -325,15 +327,15 @@ class Param:
|
||||
|
||||
return self
|
||||
|
||||
def do_filter(self, val, extra_filters: typing.List[callable] = []) -> any:
|
||||
def do_filter(self, val, extra_filters: typing.Union[typing.List[callable], typing.Tuple[callable]] = ()) -> any:
|
||||
"""
|
||||
执行参数过滤器
|
||||
@param val: any
|
||||
@param extra_filters: list[callable]
|
||||
@param extra_filters: list[callable]|tuple[callable]
|
||||
@return: any
|
||||
"""
|
||||
from functools import reduce
|
||||
return reduce(lambda x, y: y(x), extra_filters + self.__filters, val)
|
||||
return reduce(lambda x, y: y(x), list(extra_filters) + self.__filters, val)
|
||||
|
||||
|
||||
class _ValidateRule:
|
||||
@@ -1251,3 +1253,35 @@ def _get_number_data_type(s):
|
||||
pass
|
||||
|
||||
return float
|
||||
|
||||
|
||||
# 参数验证器
|
||||
class Validator:
|
||||
def __init__(self, rules: typing.Union[typing.Tuple[Param], typing.List[Param]], raise_exc: bool = True):
|
||||
self.__RULES = list(rules)
|
||||
self.__RAISE_EXC = raise_exc
|
||||
|
||||
# 参数格式校验
|
||||
def check(self, args: dict) -> aap_t_simple_result:
|
||||
try:
|
||||
for v in self.__RULES:
|
||||
v.do_validate(args)
|
||||
except Exception as e:
|
||||
if self.__RAISE_EXC:
|
||||
raise
|
||||
|
||||
return aap_t_simple_result(False, str(e))
|
||||
|
||||
return aap_t_simple_result(True, 'ok')
|
||||
|
||||
# 参数列表过滤
|
||||
def filter(self, args: dict) -> typing.Dict:
|
||||
new_args = {}
|
||||
|
||||
for v in self.__RULES:
|
||||
if v.name not in args:
|
||||
continue
|
||||
|
||||
new_args = v.do_filter(args[v.name])
|
||||
|
||||
return new_args
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import struct
|
||||
|
||||
|
||||
# varint编码 -> bytes
|
||||
def _varint_encode(num):
|
||||
res = b''
|
||||
|
||||
while num > 127:
|
||||
res += struct.pack('B', 0x80 | (num & 0x7f))
|
||||
num >>= 7
|
||||
|
||||
res += struct.pack('B', num)
|
||||
|
||||
return res
|
||||
|
||||
|
||||
# varint解码 -> num, length
|
||||
def _varint_decode(bs):
|
||||
res = 0
|
||||
n = 0
|
||||
for shift in range(0, 64, 7):
|
||||
if n > len(bs) - 1:
|
||||
break
|
||||
|
||||
res |= (bs[n] & 0x7f) << shift
|
||||
if (bs[n] & 0x80) == 0:
|
||||
break
|
||||
|
||||
n += 1
|
||||
|
||||
return res, n + 1
|
||||
@@ -3979,6 +3979,7 @@ class Sqlite():
|
||||
if 'ports' not in create_table_str:
|
||||
public.M('firewall_country').execute('ALTER TABLE "firewall_country" ADD "ports" TEXT DEFAULT ""')
|
||||
|
||||
|
||||
def create_trigger(self, sql):
|
||||
self.GetConn()
|
||||
self.connection.text_factory = str
|
||||
|
||||
@@ -31,6 +31,7 @@ Z8UsPk1Q7HtwjRd4g01ryw==
|
||||
1aJ5h9ef6qScYRSEXHxMz/JV+hrqnP7g6CgzmGbTA34=
|
||||
CH5utP+NORdjI2nqATw4gJ30bQaw4oV4TkWtZlCiO9A=
|
||||
lbIj6ug3LX3xS019kmbRSTcfm4XASPCYnVO8MD2z14s=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
iZaIsa48RXfE+uf/yF/rQD9SK8CJ49+yPAMIKmMZPD4=
|
||||
lOh2GtzHjjMM8E9J40AuOc+/vc1yhUL+xJx/Mivlb25pg5HBJ1HJ91Rfq30bJq9S
|
||||
UbJuac0dxLiN+5ocS3w2vRp92UK1M7Voei4ApHZyTgY=
|
||||
@@ -46,6 +47,7 @@ n+FHKmWLbioNpC38yMj4WmiXmXqyLuzKUmIAM1Ft5eM=
|
||||
NhnIR3Ilo4H2su9/cTNo/MME7jTfPzQcknP67wyItNzcCacoNjdvCuiW0x8udsSO/edftRARPJ4xwm1wQrVT2A==
|
||||
wlLHv6kT3Q/RmtMBN4nDATwL/9Oa0sOvSxwVwQfq99U=
|
||||
VmVrGQo2zRokW/ZuO9bN68Jg91voF9Ce3nf2o3e+jkofqu9SSuRXcnpG7smrmLLo
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
ruTTNFTdswRs4Mc+srnRk818d9d/TGGXzgPjSrVtMi8=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
6d8NLnHX3WuS3g79bJvyhMRKs67DB9ZOIiBDrB02YSQctSNS1aqQlPvqVprQ2WDG
|
||||
@@ -79,12 +81,24 @@ NhnIR3Ilo4H2su9/cTNo/E4e/PRk3DEtgyjsUDeOpSOwGpZehbHYaLN6kP4SrhN+PFbXCI6E8Z+8865U
|
||||
NhnIR3Ilo4H2su9/cTNo/C/mkLay+Rx5WJjwGcYV7pSktyrOzy78W2NcadJ49lO1rNrUNnnzcDMri5NWEH6lGQ==
|
||||
lOh2GtzHjjMM8E9J40AuOVVeyoh6rSy98QMdDBotkjU+CpzMJCQMfJrCkE4uEcQAgmW0jhOnZHI5mtglpnoAuAijuP+2lAOsmb6+b+801pIjLK0hXXo2u4rmG7jkFs3R
|
||||
lOh2GtzHjjMM8E9J40AuOeMCiZGQsphriaBgvIdFiyOx9f7gw874ih7YoSVMDwrD
|
||||
po4gDbkGtZGvsVkqlQC6Zk1QKYt+qgmWUuOhwfsrpNM=
|
||||
UGSctzorKMmnxEYKNtDxBkvvz1CdKfyqaYWXn+7HAZs=
|
||||
H3J5DRxCAs+XlPdoiqbWAEZVqk05dBQ8werKVFELygI=
|
||||
Nmty3iAt3gg+2KizVN6liKmDLACKNT+MEyuPvHlGUL0=
|
||||
f6i+lsi35nURDz6EJdx9zM/Xoipvs34XVfwWJ+ux8Rz4TrR2SQjbZyH7vEKb4+j7XHgmC6Tno9YQTDHgMt7KvA==
|
||||
f6i+lsi35nURDz6EJdx9zPe9sAZUDW4g/hSLMBY3GwUCmNfIfC8KOHeSO809Y8w27XB15/GObFgtW8jGLDFVo4rNGRmYk5EoTxiyqJIynfM=
|
||||
f6i+lsi35nURDz6EJdx9zJ1NdDiS6rl/V65/WzP7UnD287V9OI9eUAxpVVAypE0R6jBuu9m5+CfA9lKwAL+Ugw==
|
||||
f6i+lsi35nURDz6EJdx9zP3qDzts9NJ9hUb9FLBlZPiEI1reqP0Bvb6u2Go1C6W520PcmKNl6yPUdQg3CyPVFw==
|
||||
f6i+lsi35nURDz6EJdx9zP3qDzts9NJ9hUb9FLBlZPjh9tUjDopYIJdWnlez/R4iusV7Q7kFLjNuptMCVKKjau8wDFuaVvvJaons0mcTOeA=
|
||||
f6i+lsi35nURDz6EJdx9zCmK7pAVDIsd7rC/+Z3x1nxzo59ABA+BErfoy9qoZOL+
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
NhnIR3Ilo4H2su9/cTNo/A5SzFv4xHkReni2nLCW9wf/+pP3k795kKoMZAQXwXD6
|
||||
wlLHv6kT3Q/RmtMBN4nDASCRBoPIX3WHiVt75UTjznI=
|
||||
VmVrGQo2zRokW/ZuO9bN63WVsNPEwwprYYkAUqx5H2WQM74qCCEzrB3qJy/Mpn1CTpqeZGmRvqbYKmI/uSdTZw==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
VmVrGQo2zRokW/ZuO9bN61LJQniFugoi6x2ujjnJM7tldXKimSA8e3cVKdvY80W2
|
||||
VmVrGQo2zRokW/ZuO9bN67RCeNzfj+jMtOje3k8i9wttmphwpnBlwKU3a9Kqv06thCgoZf5HfOCSRRY7q4YWeg==
|
||||
VmVrGQo2zRokW/ZuO9bN64CPlXy2HmOeksJNoNOmCTRN2iWrExIMUdvTGpj/NNWq+ALT/bwKyDsjcfkGB9eQcrQ3H8UC+ywFIkXx32JcLCKuolLfVZKLqPTsQHTpYF9P
|
||||
VmVrGQo2zRokW/ZuO9bN6yDw6frMtVHHQaPzsZSKK0aES6D4Kud9zFd68X/jO6wJ
|
||||
VmVrGQo2zRokW/ZuO9bN65hAGaICagbU0z0X3nArVjY=
|
||||
@@ -93,7 +107,10 @@ VmVrGQo2zRokW/ZuO9bN61V3/TpT/zrd2QvdUtMgGKQFi9VDtwL4Vc83iegeMAft36zpJ+t/eeWtmA4E
|
||||
VmVrGQo2zRokW/ZuO9bN6wKjnvaTwlMeHWSuJ/EAxZ8Z1KtkmFIaU/d9KNNMifcN
|
||||
VmVrGQo2zRokW/ZuO9bN62ExR0OHxzNY3oC4Mfi694VYJyilbRPMd6JDlCBDdbCe
|
||||
32pdC9DD05OE2l0oXazDFLdmyVEUr33LQ7qI5CZQN57igfVF4gan9s5C0Jnc3Ki1
|
||||
6ZPJI/HSoc4xA2zncU65FpfH+eGtPlOYNU1YCnnAis8=
|
||||
mfT8DrNbUmxQ2BnZ1bZFTLh9MEuZKOpmAfF70OnZ9TU=
|
||||
xWoGNWjKGPfI4gq8aHoTfD6f0CqCimlZnuwJn30N/jbJCxj2C7n4F84hVVongdjniXe3Q9FJQdrMpXJ94VHz5g==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
s6ChnXH5zaR4nss2Jj7ULBibRmB/kmin0eYU9S2eTfU=
|
||||
ruTTNFTdswRs4Mc+srnRk818d9d/TGGXzgPjSrVtMi8=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
@@ -107,6 +124,7 @@ b4OJVZe8QyIpjuTpKXDL9A==
|
||||
NhnIR3Ilo4H2su9/cTNo/Ps3vYSOiOY6esn1xeoWmAlmLwmaOoQ9T7lnCb6TRVZ67prVtxc96eRcwG0EieQAHA==
|
||||
mfT8DrNbUmxQ2BnZ1bZFTLh9MEuZKOpmAfF70OnZ9TU=
|
||||
xWoGNWjKGPfI4gq8aHoTfBq1oaYa956TFzYuHTbqc+nhmNgO2Yqkfbla+bgPzSp/ulULnjCxA+skRNBtWTg0BA==
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
+plE/1bhdo64kO07cLlUXzzWH25pNAS0eDxp8hnHILg=
|
||||
1u+XjG/2+GSQRv6EzCaWRQ==
|
||||
0jp9NuG0oWLkMfJ/MsYOmfu7WkSnZjHksXr6BBYLZSUOzHDXl9XjsxiUKNVbrHEG
|
||||
|
||||
Reference in New Issue
Block a user