update to 6.8.27

This commit is contained in:
aaPanel
2022-12-16 10:40:55 +08:00
parent d2a66661db
commit 7dcaa2b5ce
148 changed files with 22281 additions and 13876 deletions
+325 -181
View File
@@ -1,5 +1,5 @@
#!/usr/bin/python
#coding: utf-8
# coding: utf-8
# -------------------------------------------------------------------
# 宝塔Linux面板
# -------------------------------------------------------------------
@@ -18,21 +18,22 @@ import binascii
import hashlib
import base64
import json
import copy
import time
import os
import sys
os.chdir('/www/server/panel')
if not 'class/' in sys.path:
sys.path.insert(0,'class/')
sys.path.insert(0, 'class/')
import http_requests as requests
requests.DEFAULT_TYPE = 'curl'
import public
try:
import OpenSSL
except:
public.ExecShell("pip install -I pyopenssl")
public.ExecShell("btpip install -I pyOpenSSL")
import OpenSSL
try:
import dns.resolver
@@ -40,6 +41,7 @@ except:
public.ExecShell("pip install dnspython")
import dns.resolver
class acme_v2:
_url = None
_apis = None
@@ -89,7 +91,7 @@ class acme_v2:
result = res.json()
if "type" in result:
if result['type'] == 'urn:acme:error:serverInternal':
raise Exception(public.getMsg('ACME_MSG_ERR'))
raise Exception(public.get_msg_gettext('Service shutdown or internal error due to maintenance, check [ https://letsencrypt.status.io ] see for more details.'))
if not os.path.exists('/www/server/panel/data/http_type.pl'):
public.writeFile('/www/server/panel/data/http_type.pl','python')
self.get_apis()
@@ -125,19 +127,19 @@ class acme_v2:
self.set_crond()
return account
except Exception as ex:
return public.returnMsg(False,str(ex))
return public.return_msg_gettext(False,str(ex))
# 设置帐户信息
def set_account_info(self, args):
if not 'account' in self._config:
return public.returnMsg(False, 'ACME_ACCOUNT_ERR')
return public.return_msg_gettext(False, 'The specified account does not exist')
account = json.loads(args.account)
if 'email' in account:
self._config['email'] = account['email']
del(account['email'])
self._config['account'][self._mod_index[self._debug]] = account
self.save_config()
return public.returnMsg(True, 'ACME_SUCCESS_ACCOUNT_SETUP')
return public.return_msg_gettext(True, 'Setup successfully!')
# 获取订单列表
def get_orders(self, args):
@@ -153,19 +155,19 @@ class acme_v2:
# 删除订单
def remove_order(self, args):
if not 'orders' in self._config:
return public.returnMsg(False, 'ACME_ORDER_NOT_EXIST')
return public.return_msg_gettext(False, 'The specified order does not exist!')
if not args.index in self._config['orders']:
return public.returnMsg(False, 'ACME_ORDER_NOT_EXIST')
return public.return_msg_gettext(False, 'The specified order does not exist!')
del(self._config['orders'][args.index])
self.save_config()
return public.returnMsg(True, 'ACME_DEL_ODER_SUCCESS')
return public.return_msg_gettext(True, 'Order deleted successfully!')
# 取指定订单数据
def get_order_find(self, args):
if not 'orders' in self._config:
return public.returnMsg(False, 'ACME_ORDER_NOT_EXIST')
return public.return_msg_gettext(False, 'The specified order does not exist!')
if not args.index in self._config['orders']:
return public.returnMsg(False, 'ACME_ORDER_NOT_EXIST')
return public.return_msg_gettext(False, 'The specified order does not exist!')
result = self._config['orders'][args.index]
result['cert'] = self.get_cert_info(args.index)
return result
@@ -186,27 +188,27 @@ class acme_v2:
if not os.path.exists(path): # 尝试重新下载证书
self.download_cert(args.index)
if not os.path.exists(path):
return public.returnMsg(False, 'ACME_GET_CERT_ERR')
return public.return_msg_gettext(False, 'Certificate read failed, directory does not exist!')
import panelTask
bt_task = panelTask.bt_task()
zip_file = path+'/cert.zip'
result = bt_task._zip(path, '.', path+'/cert.zip', '/dev/null', 'zip')
if not os.path.exists(zip_file):
return result
return public.returnMsg(True, zip_file)
return public.return_msg_gettext(True, zip_file)
# 吊销证书
def revoke_order(self, index):
if type(index) != str:
index = index.index
if not index in self._config['orders']:
raise Exception(public.getMsg('ACME_ORDER_NOT_EXIST'))
raise Exception(public.get_msg_gettext('The specified order does not exist!'))
cert_path = self._config['orders'][index]['save_path']
if not os.path.exists(cert_path):
raise Exception(public.getMsg('ACME_CERT_ERR'))
raise Exception(public.get_msg_gettext('No certificate found for the specified order!'))
cert = self.dump_der(cert_path)
if not cert:
raise Exception(public.getMsg('ACME_CERT_READ_ERR'))
raise Exception(public.get_msg_gettext('Certificate read failed!'))
payload = {
"certificate": self.calculate_safe_base64(cert),
"reason": 4
@@ -217,7 +219,7 @@ class acme_v2:
public.ExecShell("rm -rf {}".format(cert_path))
del(self._config['orders'][index])
self.save_config()
return public.returnMsg(True, "Certificate revoked!")
return public.return_msg_gettext(True, "Certificate revoked!")
return res.json()
# 取根域名和记录值
@@ -320,7 +322,7 @@ class acme_v2:
def create_order(self, domains, auth_type, auth_to, index=None):
domains = self.format_domains(domains)
if not domains:
raise Exception(public.getMsg('ACME_DOMAIN_ERR'))
raise Exception(public.get_msg_gettext('Need at least a domain name!'))
# 构造标识
identifiers = []
for domain_name in domains:
@@ -348,7 +350,7 @@ class acme_v2:
a_auth = res.json()
ret_title = self.get_error(str(a_auth))
raise StopIteration(
"{0} >>>> {1}".format(
"{} >>>> {}".format(
ret_title,
json.dumps(a_auth)
)
@@ -365,7 +367,7 @@ class acme_v2:
# 获取验证信息
def get_auths(self, index):
if not index in self._config['orders']:
raise Exception(public.getMsg('ACME_ORDER_NOT_EXIST'))
raise Exception(public.get_msg_gettext('The specified order does not exist!'))
# 检查是否已经获取过授权信息
if 'auths' in self._config['orders'][index]:
@@ -447,7 +449,7 @@ class acme_v2:
if not self._config['orders'][index]['auth_type'] in ['http','tls']:
return True
acme_path = '{}/.well-known/acme-challenge'.format(self._config['orders'][index]['auth_to'])
write_log(public.getMsg('ACME_V_DIR',(acme_path,)))
write_log(public.get_msg_gettext('|-Verify the dir{}',(acme_path,)))
if os.path.exists(acme_path):
public.ExecShell("rm -f {}/*".format(acme_path))
acme_path = '/www/server/stop/.well-known/acme-challenge'
@@ -476,7 +478,7 @@ class acme_v2:
except:
err = public.get_error_info()
print(err)
raise Exception(public.getMsg('ACME_WRITE_V_FILE_ERR',(err,)))
raise Exception(public.get_msg_gettext('Writing verification file failed: {}',(err,)))
# 解析域名
def create_dns_record(self, auth_to, domain, dns_value):
@@ -507,7 +509,7 @@ class acme_v2:
key = dc['data'][0]['value']
secret = dc['data'][1]['value']
except:
raise Exception(public.getMsg('ACME_DNS_API_ERR'))
raise Exception(public.get_msg_gettext('No valid DNSAPI key information found'))
else:
key = tmp[1]
secret = tmp[2]
@@ -526,7 +528,7 @@ class acme_v2:
# 验证域名
def auth_domain(self, index):
if not index in self._config['orders']:
raise Exception(public.getMsg('ACME_ORDER_NOT_EXIST'))
raise Exception(public.get_msg_gettext('The specified order does not exist!'))
# 开始验证
for auth in self._config['orders'][index]['auths']:
@@ -553,7 +555,7 @@ class acme_v2:
number_of_checks = 0
while True:
if desired_status == ['valid', 'invalid']:
write_log(public.getMsg('ACME_QUERY_V_RESULT',(str(number_of_checks + 1),)))
write_log(public.get_msg_gettext('|-{} Query verification results..',(str(number_of_checks + 1),)))
time.sleep(self._wait_time)
check_authorization_status_response = self.acme_request(url, "")
a_auth = check_authorization_status_response.json()
@@ -561,7 +563,7 @@ class acme_v2:
number_of_checks += 1
if authorization_status in desired_status:
if authorization_status == "invalid":
write_log("|-"+public.getMsg('VERIFICATION_FAILED'))
write_log("|-"+public.get_msg_gettext('Verification failed'))
try:
if 'error' in a_auth['challenges'][0]:
ret_title = a_auth['challenges'][0]['error']['detail']
@@ -575,7 +577,7 @@ class acme_v2:
except:
ret_title = str(a_auth)
raise StopIteration(
"{0} >>>> {1}".format(
"{} >>>> {}".format(
ret_title,
json.dumps(a_auth)
)
@@ -584,75 +586,75 @@ class acme_v2:
if number_of_checks == self._max_check_num:
raise StopIteration(
public.getMsg('ACME_V_TIMES',(
public.get_msg_gettext('Error: Attempted verification {} times. The maximum number of verifications is {}. The verification interval is {} seconds.',(
str(number_of_checks),
str(self._max_check_num),
str(self._wait_time)
)))
if desired_status == ['valid', 'invalid']:
write_log(public.getMsg('ACME_V_SUCCESS'))
write_log(public.get_msg_gettext('|-Verification succeeded!'))
return check_authorization_status_response
# 格式化错误输出
def get_error(self, error):
if error.find("Max checks allowed") >= 0:
return public.getMsg('ACME_ERR_MSG1')
return public.get_msg_gettext('CA cannot verify your domain name, please check if the domain name resolution is correct, or wait 5-10 minutes and try again.')
elif error.find("Max retries exceeded with") >= 0 or error.find('status_code=0 ') != -1:
return public.getMsg('ACME_ERR_MSG2')
return public.get_msg_gettext('CA server connection timed out, please try again later.')
elif error.find("The domain name belongs") >= 0:
return public.getMsg('ACME_ERR_MSG3')
return public.get_msg_gettext('The domain name does not belong to this DNS service provider, please make sure the domain name is filled in correctly.')
elif error.find('login token ID is invalid') >= 0:
return public.getMsg('ACME_ERR_MSG4')
return public.get_msg_gettext('DNS server connection failed, please check if the key is correct.')
elif error.find('Error getting validation data') != -1:
return public.getMsg('ACME_ERR_MSG5')
return public.get_msg_gettext('Data validation failed and the CA was unable to get the correct captcha from the authenticated connection.')
elif "too many certificates already issued for exact set of domains" in error:
return public.getMsg('ACME_ERR_MSG6',(str(re.findall("exact set of domains: (.+):", error)),))
return public.get_msg_gettext('Issuing failed, the domain {} has exceeded the limit of weekly reissues!',(str(re.findall("exact set of domains: (.+):", error)),))
elif "Error creating new account :: too many registrations for this IP" in error:
return public.getMsg('ACME_ERR_MSG7')
return public.get_msg_gettext('Issuing failed, the current server IP has reached the limit of creating up to 10 accounts every 3 hours.')
elif "DNS problem: NXDOMAIN looking up A for" in error:
return public.getMsg('ACME_ERR_MSG8')
return public.get_msg_gettext('Validation failed, domain name was not resolved, or resolution did not take effect!')
elif "Invalid response from" in error:
return public.getMsg('ACME_ERR_MSG9')
return public.get_msg_gettext('Verification failed, domain name resolution error or verification URL cannot be accessed!')
elif error.find('TLS Web Server Authentication') != -1:
return public.getMsg('ACME_ERR_MSG10')
return public.get_msg_gettext('Connection to CA server failed, please try again later.')
elif error.find('Name does not end in a public suffix') != -1:
return public.getMsg('ACME_ERR_MSG11',(str(re.findall("Cannot issue for \"(.+)\":", error)),))
return public.get_msg_gettext('Unsupported domain name {}, please check the domain name is correct!',(str(re.findall("Cannot issue for \"(.+)\":", error)),))
elif error.find('No valid IP addresses found for') != -1:
return public.getMsg('ACME_ERR_MSG12',(str(re.findall("No valid IP addresses found for (.+)", error)),))
return public.get_msg_gettext('No resolution record was found for domain name {}, please check if the domain name resolution takes effect!',(str(re.findall("No valid IP addresses found for (.+)", error)),))
elif error.find('No TXT record found at') != -1:
return public.getMsg('ACME_ERR_MSG13',(str(re.findall("No TXT record found at (.+)", error)),))
return public.get_msg_gettext('No valid TXT resolution record was found in the domain name {}, please check whether the TXT record is parsed correctly. If it is applied by DNSAPI, please try again in 10 minutes!',(str(re.findall("No TXT record found at (.+)", error)),))
elif error.find('Incorrect TXT record') != -1:
return public.getMsg('ACME_ERR_MSG14',(str(re.findall("found at (.+)", error)), str(re.findall("Incorrect TXT record \"(.+)\"", error))))
return public.get_msg_gettext('A wrong TXT record was found on {}: {}, please check whether the TXT resolution is correct, if it is applied by DNSAPI, please try again in 10 minutes!',(str(re.findall("found at (.+)", error)), str(re.findall("Incorrect TXT record \"(.+)\"", error))))
elif error.find('Domain not under you or your user') != -1:
return public.getMsg('ACME_ERR_MSG15')
return public.get_msg_gettext('This domain name does not exist under this dnspod account, adding resolution failed!')
elif error.find('SERVFAIL looking up TXT for') != -1:
return public.getMsg('ACME_ERR_MSG16',(str(re.findall("looking up TXT for (.+)", error)),))
return public.get_msg_gettext('No valid TXT resolution record was found in the domain name {}, please check whether the TXT record is parsed correctly. If it is applied by DNSAPI, please try again in 10 minutes!',(str(re.findall("looking up TXT for (.+)", error)),))
elif error.find('Timeout during connect') != -1:
return public.getMsg('ACME_ERR_MSG17')
return public.get_msg_gettext('The connection timed out and the CA server was unable to access your website!')
elif error.find("DNS problem: SERVFAIL looking up CAA for") != -1:
return public.getMsg('ACME_ERR_MSG18',(str(re.findall("looking up CAA for (.+)", error)),))
return public.get_msg_gettext('Domain name {} is currently required to verify the CAA record, please parse the CAA record manually, or retry the application after 1 hour!',(str(re.findall("looking up CAA for (.+)", error)),))
elif error.find("Read timed out.") != -1:
return public.getMsg('ACME_ERR_MSG19')
return public.get_msg_gettext('The verification timed out. Please check if the domain name is resolved correctly. If it is resolved correctly, the connection between the server and LetsEncrypt may be abnormal. Please try again later!')
elif error.find('Cannot issue for') != -1:
return public.getMsg('ACME_ERR_MSG20',(str(re.findall(r'for\s+"(.+)"',error)),))
return public.get_msg_gettext('Cannot issue a certificate for {}, cannot apply for a wildcard certificate with a domain name suffix directly!',(str(re.findall(r'for\s+"(.+)"',error)),))
elif error.find('too many failed authorizations recently'):
return public.getMsg('ACME_ERR_MSG21')
return public.get_msg_gettext('The account has more than 5 failed orders within 1 hour, please wait 1 hour and try again!')
elif error.find("Error creating new order") != -1:
return public.getMsg('ACME_ERR_MSG22')
return public.get_msg_gettext('Order creation failed, please try again later!')
elif error.find("Too Many Requests") != -1:
return public.getMsg('ACME_ERR_MSG23')
return public.get_msg_gettext('More than 5 verification failures in 1 hour, the application is temporarily banned, please try again later!')
elif error.find('HTTP Error 400: Bad Request') != -1:
return public.getMsg('ACME_ERR_MSG24')
return public.get_msg_gettext('CA server denied access, please try again later!')
elif error.find('Temporary failure in name resolution') != -1:
return public.getMsg('ACME_ERR_MSG25')
return public.get_msg_gettext('The DNS of the server is faulty and the domain name cannot be resolved. Please use the Linux toolbox to check the DNS configuration')
elif error.find('Too Many Requests') != -1:
return public.getMsg('ACME_ERR_MSG26')
return public.get_msg_gettext('Too many requests for this domain name. Please try again 3 hours later')
else:
return error
# 发送验证请求
def respond_to_challenge(self, auth):
payload = {"keyAuthorization": "{0}".format(
payload = {"keyAuthorization": "{}".format(
auth['acme_keyauthorization'])}
respond_to_challenge_response = self.acme_request(
auth['dns_challenge_url'], payload)
@@ -666,7 +668,7 @@ class acme_v2:
url=self._config['orders'][index]['finalize'], payload=payload)
if send_csr_response.status_code not in [200, 201]:
raise ValueError(
public.getMsg('ACME_SEND_CSR_ERR',(send_csr_response.status_code,send_csr_response.json()))
public.get_msg_gettext('Error: Sending CSR: Response status {} Response value: {}',(send_csr_response.status_code,send_csr_response.json()))
)
send_csr_response_json = send_csr_response.json()
certificate_url = send_csr_response_json["certificate"]
@@ -689,7 +691,7 @@ class acme_v2:
res = self.acme_request(
self._config['orders'][index]['certificate_url'], "")
if res.status_code not in [200, 201]:
raise Exception(public.getMsg('ACME_CERT_DOWNLOAD_ERR',(str(res.json()),)))
raise Exception(public.get_msg_gettext('Failed to download certificate: {}',(str(res.json()),)))
pem_certificate = res.content
if type(pem_certificate) == bytes:
@@ -781,8 +783,10 @@ fullchain.pem Paste into certificate input box
# 获取目标证书的基本信息
to_cert_init = self.get_cert_init(to_pem_file)
# 判断证书品牌是否一致
if to_cert_init['issuer'] != cert_init['issuer'] and to_cert_init['issuer'].find("Let's Encrypt") == -1:
continue
try:
if to_cert_init['issuer'] != cert_init['issuer'] and to_cert_init['issuer'].find("Let's Encrypt") == -1 and to_cert_init['issuer'] != 'R3':
continue
except: continue
# 判断目标证书的到期时间是否较早
if to_cert_init['notAfter'] > cert_init['notAfter']:
continue
@@ -802,7 +806,7 @@ fullchain.pem Paste into certificate input box
public.writeFile(
to_key_file, public.readFile(key_file, 'rb'), 'wb')
public.writeFile(to_info, json.dumps(cert_init))
write_log(public.getMsg('ACME_CERT_REPLACE',(to_path,)))
write_log(public.get_msg_gettext('|-Detected that the certificate under {} overlaps with the certificate of this application and has an earlier expiration time, and has been replaced with a new certificate!',(to_path,)))
# 重载web服务
public.serviceReload()
if is_panel: public.restart_panel()
@@ -818,7 +822,7 @@ fullchain.pem Paste into certificate input box
for domain in self._config['orders'][index]['domains']:
if domain in cert_init['dns']:
return index
if cert_init['issuer'].find("Let's Encrypt") != -1:
if cert_init['issuer'].find("Let's Encrypt") != -1 or cert_init['issuer'] == 'R3':
return pem_file
return None
except: return None
@@ -828,10 +832,10 @@ fullchain.pem Paste into certificate input box
if not os.path.exists(args.pem_file):
args.pem_file = 'vhost/cert/{}/fullchain.pem'.format(args.siteName)
if not os.path.exists(args.pem_file):
return public.returnMsg(False, 'ACME_CERT_FILE_ERR')
return public.return_msg_gettext(False, 'The specified certificate file does not exist!')
cert_init = self.get_cert_init(args.pem_file)
if not cert_init:
return public.returnMsg(False, 'ACME_CERT_GET_CERTINFO_ERR')
return public.return_msg_gettext(False, 'Certificate information acquisition failed!')
cert_init['dnsapi'] = json.loads(public.readFile(self._dnsapi_file))
return cert_init
@@ -922,7 +926,7 @@ fullchain.pem Paste into certificate input box
# 检查DNS记录
def check_dns(self, domain, value, s_type='TXT'):
write_log(public.getMsg('ACME_CHECK_DNS',(domain, s_type, value)))
write_log(public.get_msg_gettext('|-Attempt to verify DNS records locally, domain name: {}, type: {} record value: {}',(domain, s_type, value)))
time.sleep(10)
n = 0
while n < 20:
@@ -933,9 +937,9 @@ fullchain.pem Paste into certificate input box
for j in ns.response.answer:
for i in j.items:
txt_value = i.to_text().replace('"', '').strip()
write_log(public.getMsg('ACME_CHECK_DNS1',(str(n),txt_value)))
write_log(public.get_msg_gettext('|-Number of verifications: {}, value: {}',(str(n),txt_value)))
if txt_value == value:
write_log(public.getMsg('ACME_CHECK_DNS2'))
write_log(public.get_msg_gettext('|-Local authentication succeeded!'))
return True
except:
try:
@@ -943,7 +947,7 @@ fullchain.pem Paste into certificate input box
except:
return False
time.sleep(3)
write_log(public.getMsg('ACME_CHECK_DNS3'))
write_log(public.get_msg_gettext('|-Local authentication failed!'))
return True
# 创建CSR
@@ -954,11 +958,11 @@ fullchain.pem Paste into certificate input box
X509Req = OpenSSL.crypto.X509Req()
X509Req.get_subject().CN = domain_name
if domain_alt_names:
SAN = "DNS:{0}, ".format(domain_name).encode("utf8") + ", ".join(
SAN = "DNS:{}, ".format(domain_name).encode("utf8") + ", ".join(
"DNS:" + i for i in domain_alt_names
).encode("utf8")
else:
SAN = "DNS:{0}".format(domain_name).encode("utf8")
SAN = "DNS:{}".format(domain_name).encode("utf8")
X509Req.add_extensions(
[
@@ -984,7 +988,7 @@ fullchain.pem Paste into certificate input box
acme_thumbprint = self.calculate_safe_base64(
hashlib.sha256(acme_header_jwk_json.encode("utf8")).digest()
)
acme_keyauthorization = "{0}.{1}".format(token, acme_thumbprint)
acme_keyauthorization = "{}.{}".format(token, acme_thumbprint)
base64_of_acme_keyauthorization = self.calculate_safe_base64(
hashlib.sha256(acme_keyauthorization.encode("utf8")).digest()
)
@@ -994,7 +998,7 @@ fullchain.pem Paste into certificate input box
# 构造验证信息
def get_identifier_auth(self, index, url, auth_info):
s_type = self.get_auth_type(index)
write_log(public.getMsg('ACME_BUILD_AUTH',(s_type,)))
write_log(public.get_msg_gettext('|-Verification type: {}',(s_type,)))
domain = auth_info['identifier']['value']
wildcard = False
# 处理通配符
@@ -1019,7 +1023,7 @@ fullchain.pem Paste into certificate input box
# 获取域名验证方式
def get_auth_type(self, index):
if not index in self._config['orders']:
raise Exception(public.getMsg('ACME_ORDER_NOT_EXIST'))
raise Exception(public.get_msg_gettext('The specified order does not exist!'))
s_type = 'http-01'
if 'auth_type' in self._config['orders'][index]:
if self._config['orders'][index]['auth_type'] == 'dns':
@@ -1087,7 +1091,7 @@ fullchain.pem Paste into certificate input box
elif self._config['email']:
payload = {
"termsOfServiceAgreed": True,
"contact": ["mailto:{0}".format(self._config['email'])],
"contact": ["mailto:{}".format(self._config['email'])],
}
else:
payload = {"termsOfServiceAgreed": True}
@@ -1095,7 +1099,7 @@ fullchain.pem Paste into certificate input box
res = self.acme_request(url=self._apis['newAccount'], payload=payload)
if res.status_code not in [201, 200, 409]:
raise Exception(public.getMsg('ACME_REGISTERED_ERR',(str(res.json()),)))
raise Exception(public.get_msg_gettext('Registration for ACME account failed: {}',(str(res.json()),)))
kid = res.headers["Location"]
return kid
@@ -1111,7 +1115,7 @@ fullchain.pem Paste into certificate input box
protected = self.get_acme_header(url)
protected64 = self.calculate_safe_base64(json.dumps(protected))
signature = self.sign_message(
message="{0}.{1}".format(protected64, payload64)) # bytes
message="{}.{}".format(protected64, payload64)) # bytes
signature64 = self.calculate_safe_base64(signature) # str
data = json.dumps(
{"protected": protected64, "payload": payload64,
@@ -1172,7 +1176,7 @@ fullchain.pem Paste into certificate input box
public_key_public_numbers = private_key.public_key().public_numbers()
exponent = "{0:x}".format(public_key_public_numbers.e)
exponent = "0{0}".format(exponent) if len(
exponent = "0{}".format(exponent) if len(
exponent) % 2 else exponent
modulus = "{0:x}".format(public_key_public_numbers.n)
jwk = {
@@ -1268,23 +1272,25 @@ fullchain.pem Paste into certificate input box
index = None
if 'index' in args:
index = args['index']
if 'auto_wildcard' in args:
self._auto_wildcard = 1
if not index: # 判断是否只想验证域名
write_log(public.getMsg('ACME_CREAT_ORDER'))
write_log(public.get_msg_gettext('|-Creating order..'))
index = self.create_order(domains, auth_type, auth_to)
write_log(public.getMsg('ACME_GET_V'))
write_log(public.get_msg_gettext('|-Getting verification information..'))
self.get_auths(index)
if auth_to == 'dns' and len(self._config['orders'][index]['auths']) > 0:
return self._config['orders'][index]
write_log(public.getMsg('ACME_V_DOMAIN'))
write_log(public.get_msg_gettext('|-Verifying domain name..'))
self.auth_domain(index)
self.remove_dns_record()
write_log(public.getMsg('ACME_SEND_CSR'))
write_log(public.get_msg_gettext('|-Sending CSR..'))
self.send_csr(index)
write_log(public.getMsg('ACME_DOWNLOAD_CERT'))
write_log(public.get_msg_gettext('|-Downloading certificate..'))
cert = self.download_cert(index)
cert['status'] = True
cert['msg'] = public.getMsg('ACME_APPLY_SUCCESS')
write_log(public.getMsg('ACME_APPLY_SUCCESS1'))
cert['msg'] = public.get_msg_gettext('Application successful!')
write_log(public.get_msg_gettext('|-Successful application, deploying to site..'))
return cert
except Exception as ex:
self.remove_dns_record()
@@ -1295,7 +1301,7 @@ fullchain.pem Paste into certificate input box
else:
msg = ex
write_log(public.get_error_info())
return public.returnMsg(False, msg)
return public.return_msg_gettext(False, msg)
# 申请证书 - api
def apply_cert_api(self, args):
@@ -1307,7 +1313,7 @@ fullchain.pem Paste into certificate input box
try:
project_info = json.loads(project_info)
if not 'ssl_path' in project_info:
return public.returnMsg(False, 'There is a problem with the current Java project configuration file, please rebuild')
return public.return_msg_gettext(False, 'There is a problem with the current Java project configuration file, please rebuild')
if not os.path.exists(project_info['ssl_path']):
os.makedirs(project_info['ssl_path'])
path = project_info['ssl_path']
@@ -1319,7 +1325,7 @@ fullchain.pem Paste into certificate input box
self._auto_wildcard = True
return self.apply_cert(json.loads(args.domains), args.auth_type, args.auth_to)
except:
return public.returnMsg(False, 'There is a problem with the current Java project configuration file, please rebuild')
return public.return_msg_gettext(False, 'There is a problem with the current Java project configuration file, please rebuild')
else:
if re.match(r"^\d+$", args.auth_to):
import panelSite
@@ -1330,7 +1336,7 @@ fullchain.pem Paste into certificate input box
args.auth_to = args.auth_to[:-1]
if not os.path.exists(args.auth_to):
return public.returnMsg(False, 'ACME_DIR_ERR')
return public.return_msg_gettext(False, 'Invalid site directory, please check if the specified site exists!')
check_result = self.check_auth_env(args, check=True)
if check_result: return check_result
@@ -1423,8 +1429,8 @@ fullchain.pem Paste into certificate input box
return
for domain in json.loads(args.domains):
if public.checkIp(domain): continue
if domain.find('*.') >=0 and args.auth_type in ['http','tls']:
raise public.returnMsg(False, 'ACME_PAN_DOMAIN_ERR')
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']:
@@ -1460,7 +1466,7 @@ fullchain.pem Paste into certificate input box
s.ModifyRedirect(args)
redirect_tmp[args.sitename].append(x['redirectname'])
else:
if x['type']: return public.returnMsg(False, 'SITE_SSL_ERR_301')
if x['type']: return public.return_msg_gettext(False, 'Your site has 301 Redirect onPlease 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)
@@ -1486,13 +1492,13 @@ fullchain.pem Paste into certificate input box
write_log("|- Turning off proxy {}".format(args.proxyname))
proxy_tmp[args.sitename].append(x['proxyname'])
else:
if x['type']: return public.returnMsg(False,'ACME_PROXY_ERR')
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.returnMsg(False,'SITE_SSL_ERR_3011')
return public.return_msg_gettext(False,'The website has been redirected, please close it before applying!')
#判断是否强制HTTPS
if s.IsToHttps(args.siteName):
if os.path.exists(self._stop_rp_file):
@@ -1501,14 +1507,14 @@ fullchain.pem Paste into certificate input box
s.CloseToHttps(args)
public.writeFile('{}/data/stop_httptohttps.pl'.format(public.get_panel_path()), '')
else:
return public.returnMsg(False, 'ACME_FORCE_SSL_ERR')
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:
if args.auth_to.find('Dns_com') != -1:
if not os.path.exists('plugin/dns/dns_main.py'):
return public.returnMsg(False, 'ACME_DNS_ERR')
return public.return_msg_gettext(False, 'Please go to the software store to install [cloud analysis], and complete the domain name NS binding.')
return False
# DNS手动验证
@@ -1601,6 +1607,138 @@ fullchain.pem Paste into certificate input box
site_status = public.M('sites').where('id=?', (site_id,)).field('status').select()[0]['status']
return site_status
def get_index(self, domains):
'''
@name 获取标识
@author hwliang<2022-02-10>
@param domains<list> 域名列表
@return string
'''
identifiers = []
for domain_name in domains:
identifiers.append({"type": 'dns', "value": domain_name})
return public.md5(json.dumps(identifiers))
# 续签同品牌其它证书
def renew_cert_other(self):
'''
@name 续签同品牌其它证书
@author hwliang<2022-02-10>
@return void
'''
cert_path = "{}/vhost/cert".format(public.get_panel_path())
if not os.path.exists(cert_path): return
new_time = time.time() + (86400 * 30)
n = 0
if not 'orders' in self._config: self._config['orders'] = {}
import panelSite
siteObj = panelSite.panelSite()
args = public.dict_obj()
for siteName in os.listdir(cert_path):
try:
cert_file = '{}/{}/fullchain.pem'.format(cert_path, siteName)
if not os.path.exists(cert_file): continue # 无证书文件
siteInfo = public.M('sites').where('name=?', siteName).find()
if not siteInfo: continue # 无网站信息
cert_init = self.get_cert_init(cert_file)
if not cert_init: continue # 无法获取证书
end_time = time.mktime(time.strptime(cert_init['notAfter'], '%Y-%m-%d'))
if end_time > new_time: continue # 未到期
try:
if not cert_init['issuer'] in ['R3', "Let's Encrypt"] and cert_init['issuer'].find(
"Let's Encrypt") == -1:
continue # 非同品牌证书
except:
continue
if isinstance(cert_init['dns'], str): cert_init['dns'] = [cert_init['dns']]
index = self.get_index(cert_init['dns'])
if index in self._config['orders'].keys(): continue # 已在订单列表
n += 1
write_log("|-Renewing additional certificate {}, domain name:{}..".format(n, cert_init['subject']))
write_log("|-Creating order..")
args.id = siteInfo['id']
runPath = siteObj.GetRunPath(args)
if runPath and not runPath in ['/']:
path = siteInfo['path'] + '/' + runPath
else:
path = siteInfo['path']
self.renew_cert_to(cert_init['dns'],'http',path.replace('//','/'))
except:
write_log("|-Renewal failed:")
def renew_cert_to(self, domains, auth_type, auth_to, index=None):
siteName = None
cert = {}
args = public.dict_obj()
if auth_to[-1] == "/":
auth_to = auth_to[:-1]
site_id = public.M('sites').where('path=?', auth_to).getField('id')
args.id = site_id
if os.path.exists(auth_to):
if public.M('sites').where('path=?', auth_to).count() == 1:
# site_id = public.M('sites').where('path=?',auth_to).getField('id')
siteName = public.M('sites').where('path=?', auth_to).getField('name')
import panelSite
siteObj = panelSite.panelSite()
# args = public.dict_obj()
# args.id = site_id
runPath = siteObj.GetRunPath(args)
if runPath and not runPath in ['/']:
path = auth_to + '/' + runPath
if os.path.exists(path): auth_to = path.replace('//', '/')
else:
siteName = self.get_site_name_by_domains(domains)
try:
index = self.create_order(
domains,
auth_type,
auth_to.replace('//', '/'),
index
)
write_log("|-Getting verification information..")
self.get_auths(index)
write_log("|-Verifying domain name..")
self.auth_domain(index)
write_log("|-Sending CSR..")
self.remove_dns_record()
self.send_csr(index)
write_log("|-Downloading certificate..")
cert = self.download_cert(index)
self._config['orders'][index]['renew_time'] = int(time.time())
# 清理失败重试记录
self._config['orders'][index]['retry_count'] = 0
self._config['orders'][index]['next_retry_time'] = 0
# 保存证书配置
self.save_config()
cert['status'] = True
cert['msg'] = 'Renewed successfully!'
write_log("|-Renewed successfully!!")
except Exception as e:
if str(e).find('please try again later') == -1: # 受其它证书影响和连接CA失败的的不记录重试次数
if index:
# 设置下次重试时间
self._config['orders'][index]['next_retry_time'] = int(time.time() + (86400 * 2))
# 记录重试次数
if not 'retry_count' in self._config['orders'][index].keys():
self._config['orders'][index]['retry_count'] = 1
self._config['orders'][index]['retry_count'] += 1
# 保存证书配置
self.save_config()
msg = str(e).split('>>>>')[0]
write_log("|-" + msg)
return public.returnMsg(False, msg)
finally:
self.turnon_redirect_proxy_httptohttps(args)
write_log("-" * 70)
return cert
# 续签证书
def renew_cert(self, index):
write_log("", "wb+")
@@ -1612,10 +1750,11 @@ fullchain.pem Paste into certificate input box
# 在面板点击申请证书时不要重启面板以防后续请求出错
self._by_panel = True
if index not in self._config['orders']:
raise Exception(public.getMsg('ACME_RENEW_ERR'))
raise Exception(public.get_msg_gettext('The specified order number does not exist and cannot be renewed!'))
order_index.append(index)
else:
s_time = time.time() + (30 * 86400)
if not 'orders' in self._config: self._config['orders'] = {}
for i in self._config['orders'].keys():
if not 'save_path' in self._config['orders'][i]:
continue
@@ -1645,17 +1784,21 @@ fullchain.pem Paste into certificate input box
# 是否到了最大重试次数
if 'retry_count' in self._config['orders'][i]:
if self._config['orders'][i]['retry_count'] >= 3:
write_log('|-Skip the domain name this time: {}, this certificate will not be renewed due to failure to renew 3 times in a row, (The number of errors will be reset after manual renewal and success)'.format(self._config['orders'][i]['domains']))
if self._config['orders'][i]['retry_count'] >= 5:
write_log('|-Skip the domain name this time: {}, this certificate will not be renewed due to failure to renew 5 times in a row, (The number of errors will be reset after manual renewal and success)'.format(self._config['orders'][i]['domains']))
continue
# 加入到续签订单
order_index.append(i)
if not order_index:
write_log(public.getMsg('ACME_NO_NEED_RENEW'))
return public.returnMsg(False,public.getMsg('ACME_NO_NEED_RENEW'))
write_log(public.getMsg("ACME_NEED_RENEW",(str(len(order_index)),)))
write_log(public.get_msg_gettext('|-No SSL certificate found within 30 days!'))
self.get_apis()
self.renew_cert_other()
# return public.return_msg_gettext(False,public.get_msg_gettext('|-No SSL certificate found within 30 days!'))
write_log("|-All tasks have been processed!")
return
write_log(public.get_msg_gettext('|-A total of {} certificates need to be renewed',(str(len(order_index)),)))
n = 0
self.get_apis()
cert = None
@@ -1671,53 +1814,54 @@ fullchain.pem Paste into certificate input box
write_log('|-Renew the visa certificate and start checking the environment')
self.check_auth_env(args,check=True)
n += 1
write_log(public.getMsg("ACME_RENEWING",(str(n),str(self._config['orders'][index]['domains']))))
write_log(public.getMsg('ACME_CREAT_ORDER'))
try:
run_path = self.get_site_runpath(self._config['orders'][index]['domains'])
if run_path:
if self._config['orders'][index]['auth_to'] != run_path:
self._config['orders'][index]['auth_to'] = run_path
index = self.create_order(
self._config['orders'][index]['domains'],
self._config['orders'][index]['auth_type'],
self._config['orders'][index]['auth_to'],
index
)
write_log(public.getMsg('ACME_GET_V'))
self.get_auths(index)
write_log(public.getMsg('ACME_V_DOMAIN'))
self.auth_domain(index)
write_log(public.getMsg('ACME_SEND_CSR'))
self.remove_dns_record()
self.send_csr(index)
write_log(public.getMsg('ACME_DOWNLOAD_CERT'))
cert = self.download_cert(index)
self._config['orders'][index]['renew_time'] = int(time.time())
# 清理失败重试记录
self._config['orders'][index]['retry_count'] = 0
self._config['orders'][index]['next_retry_time'] = 0
# 保存证书配置
self.save_config()
cert['status'] = True
cert['msg'] = public.getMsg('ACME_RENEW_SUCCESS')
if os.path.exists(self._stop_rp_file):
self.turnon_redirect_proxy_httptohttps(args)
write_log(public.getMsg('ACME_RENEW_SUCCESS1'))
except Exception as e:
if str(e).find('请稍候重试') == -1: # 受其它证书影响和连接CA失败的的不记录重试次数
# 设置下次重试时间
self._config['orders'][index]['next_retry_time'] = int(time.time() + (86400 * 2))
# 记录重试次数
if not 'retry_count' in self._config['orders'][index].keys():
self._config['orders'][index]['retry_count'] = 1
self._config['orders'][index]['retry_count'] += 1
# 保存证书配置
self.save_config()
write_log("|-" + str(e).split('>>>>')[0])
write_log("-" * 70)
write_log(public.get_msg_gettext('|-Renewing certificate number of {}domain: {}..',(str(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)
# try:
# run_path = self.get_site_runpath(self._config['orders'][index]['domains'])
# if run_path:
# if self._config['orders'][index]['auth_to'] != run_path:
# self._config['orders'][index]['auth_to'] = run_path
# index = self.create_order(
# self._config['orders'][index]['domains'],
# self._config['orders'][index]['auth_type'],
# self._config['orders'][index]['auth_to'],
# index
# )
# write_log(public.get_msg_gettext('|-Getting verification information..'))
# self.get_auths(index)
# write_log(public.get_msg_gettext('|-Verifying domain name..'))
# self.auth_domain(index)
# write_log(public.get_msg_gettext('|-Sending CSR..'))
# self.remove_dns_record()
# self.send_csr(index)
# write_log(public.get_msg_gettext('|-Downloading certificate..'))
# cert = self.download_cert(index)
# self._config['orders'][index]['renew_time'] = int(time.time())
#
# # 清理失败重试记录
# self._config['orders'][index]['retry_count'] = 0
# self._config['orders'][index]['next_retry_time'] = 0
#
# # 保存证书配置
# self.save_config()
# cert['status'] = True
# cert['msg'] = public.get_msg_gettext('Renewed successfully!')
# if os.path.exists(self._stop_rp_file):
# self.turnon_redirect_proxy_httptohttps(args)
# write_log(public.get_msg_gettext('|-Renewed successfully!'))
# except Exception as e:
# if str(e).find('请稍候重试') == -1: # 受其它证书影响和连接CA失败的的不记录重试次数
# # 设置下次重试时间
# self._config['orders'][index]['next_retry_time'] = int(time.time() + (86400 * 2))
# # 记录重试次数
# if not 'retry_count' in self._config['orders'][index].keys():
# self._config['orders'][index]['retry_count'] = 1
# self._config['orders'][index]['retry_count'] += 1
# # 保存证书配置
# self.save_config()
# write_log("|-" + str(e).split('>>>>')[0])
# write_log("-" * 70)
return cert
except Exception as ex:
self.remove_dns_record()
@@ -1728,7 +1872,7 @@ fullchain.pem Paste into certificate input box
else:
msg = ex
write_log(public.get_error_info())
return public.returnMsg(False, msg)
return public.return_msg_gettext(False, msg)
def echo_err(msg):
@@ -1751,22 +1895,22 @@ def write_log(log_str, mode="ab+"):
if __name__ == "__main__":
import argparse
p = argparse.ArgumentParser(usage=public.getMsg('ACME_USE_TIPS'))
p = argparse.ArgumentParser(usage=public.get_msg_gettext('Required parameters: --domain list of domain names, multiple separated by commas!'))
p.add_argument('--domain', default=None,
help=public.getMsg('ACME_USE_TIPS1'), dest="domains")
p.add_argument('--type', default=None, help=public.getMsg('ACME_USE_TIPS2'), dest="auth_type")
p.add_argument('--path', default=None, help=public.getMsg('ACME_USE_TIPS3'), dest="path")
p.add_argument('--dnsapi', default=None, help=public.getMsg('ACME_USE_TIPS4'), dest="dnsapi")
p.add_argument('--dns_key', default=None, help=public.getMsg('ACME_USE_TIPS5'), dest="key")
p.add_argument('--dns_secret', default=None,help=public.getMsg('ACME_USE_TIPS6'), dest="secret")
p.add_argument('--index', default=None, help=public.getMsg('ACME_USE_TIPS7'), dest="index")
p.add_argument('--renew', default=None, help=public.getMsg('ACME_USE_TIPS8'), dest="renew")
p.add_argument('--revoke', default=None, help=public.getMsg('ACME_USE_TIPS9'), dest="revoke")
help=public.get_msg_gettext('Please specify the domain name to apply for a certificate'), dest="domains")
p.add_argument('--type', default=None, help=public.get_msg_gettext('Please specify verification type'), dest="auth_type")
p.add_argument('--path', default=None, help=public.get_msg_gettext('Please specify the website document root'), dest="path")
p.add_argument('--dnsapi', default=None, help=public.get_msg_gettext('Please specify DNSAPI'), dest="dnsapi")
p.add_argument('--dns_key', default=None, help=public.get_msg_gettext('Please specify DNSAPI key'), dest="key")
p.add_argument('--dns_secret', default=None,help=public.get_msg_gettext('Please specify DNSAPI secret'), dest="secret")
p.add_argument('--index', default=None, help=public.get_msg_gettext('Specify the order index'), dest="index")
p.add_argument('--renew', default=None, help=public.get_msg_gettext('renew certificate'), dest="renew")
p.add_argument('--revoke', default=None, help=public.get_msg_gettext('Revoke certificate'), dest="revoke")
args = p.parse_args()
cert = None
if args.revoke:
if not args.index:
echo_err(public.getMsg('ACME_USE_TIPS10'))
echo_err(public.get_msg_gettext('Please enter the index of the order to be revoked in the --index parameter'))
p = acme_v2()
result = p.revoke_order(args.index)
write_log(result)
@@ -1779,24 +1923,24 @@ if __name__ == "__main__":
try:
if not args.index:
if not args.domains:
echo_err(public.getMsg('ACME_USE_TIPS11'))
echo_err(public.get_msg_gettext('Please specify the domain name for which you want to apply for a certificate in the --domain parameter, multiple separated by commas (,)'))
if not args.auth_type in ['http', 'tls', 'dns']:
echo_err(public.getMsg('ACME_USE_TIPS12'))
echo_err(public.get_msg_gettext('Please specify the correct authentication type in the --type parameter, supporting dns and http'))
auth_to = ''
if args.auth_type in ['http', 'tls']:
if not args.path:
echo_err(public.getMsg('ACME_USE_TIPS13'))
echo_err(public.get_msg_gettext('Please specify the website document root in the --path parameter!'))
if not os.path.exists(args.path):
echo_err(public.getMsg('ACME_USE_TIPS14',(args.path,)))
echo_err(public.get_msg_gettext('The specified site root does not exist, please check: {}',(args.path,)))
auth_to = args.path
else:
if args.dnsapi == '0':
auth_to = 'dns'
else:
if not args.key:
echo_err(public.getMsg('ACME_USE_TIPS15'))
echo_err(public.get_msg_gettext('When applying using dnsapi, specify the dnsapi key in the --dns_key parameter!'))
if not args.secret:
echo_err(public.getMsg('ACME_USE_TIPS16'))
echo_err(public.get_msg_gettext('When applying using dnsapi, specify the secret of dnsapi in the --dns_secret parameter!'))
auth_to = "{}|{}|{}".format(
args.dnsapi, args.key, args.secret)
@@ -1808,27 +1952,27 @@ if __name__ == "__main__":
acme_txt = '_acme-challenge.'
acme_caa = '1 issue letsencrypt.org'
write_log("=" * 65)
write_log("\033[32m"+public.getMsg('ACME_USE_TIPS17')+"\033[0m")
write_log("\033[32m"+public.get_msg_gettext('|-Manual order submission is successful, please resolve DNS records according to the following tips: ')+"\033[0m")
write_log("=" * 65)
write_log(public.getMsg('ACME_USE_TIPS18',(cert['index'],)))
write_log(public.getMsg('ACME_USE_TIPS19')+": ./acme_v2.py --index=\"{}\"".format(cert['index']))
write_log(public.getMsg('ACME_USE_TIPS20',(len(cert['auths']),)))
write_log(public.get_msg_gettext('|-Order index: {}',(cert['index'],)))
write_log(public.get_msg_gettext('|-Retry the command')+": ./acme_v2.py --index=\"{}\"".format(cert['index']))
write_log(public.get_msg_gettext('|-A total of \033[36m{}\033[0m domain name records need to be resolved.',(len(cert['auths']),)))
for i in range(len(cert['auths'])):
write_log('-' * 70)
write_log(public.getMsg('ACME_USE_TIPS21',(str(i+1), cert['auths'][i]['domain'])))
write_log(public.getMsg('ACME_USE_TIPS22',(acme_txt + cert['auths'][i]['domain'].replace('*.', ''), cert['auths'][i]['auth_value'])))
write_log(public.getMsg('ACME_USE_TIPS23',(cert['auths'][i]['domain'].replace('*.', ''), acme_caa)))
write_log(public.get_msg_gettext('|-The \033[36m{}\033[0m domain names are: {}, please resolve the following information: ',(str(i+1), cert['auths'][i]['domain'])))
write_log(public.get_msg_gettext('|-Record Type: TXT Record Name: \033[41m{}\033[0m Record Value: \033[41m{}\033 [0m [Required]',(acme_txt + cert['auths'][i]['domain'].replace('*.', ''), cert['auths'][i]['auth_value'])))
write_log(public.get_msg_gettext('|-Record type: CAA Record name: \033[41m{}\033[0m Record value: \033[41m{}\033[0m [Optional]',(cert['auths'][i]['domain'].replace('*.', ''), acme_caa)))
write_log('-' * 70)
input_data = ""
while input_data not in ['y', 'Y', 'n', 'N']:
input_msg = public.getMsg('ACME_USE_TIPS24')
input_msg = public.get_msg_gettext('Please wait 2-3 minutes after completing the resolution and enter Y and press Enter to continue verifying the domain name: ')
if sys.version_info[0] == 2:
input_data = raw_input(input_msg)
else:
input_data = input(input_msg)
if input_data in ['n', 'N']:
write_log("=" * 65)
write_log(public.getMsg('ACME_USE_TIPS25'))
write_log(public.get_msg_gettext('|-The user abandons the application and exits the program!'))
exit()
cert = p.apply_cert(
[], auth_type=args.auth_type, auth_to='dns', index=cert['index'])
@@ -1843,8 +1987,8 @@ if __name__ == "__main__":
if not cert:
exit()
write_log("=" * 65)
write_log(public.getMsg('ACME_USE_TIPS26'))
write_log(public.get_msg_gettext('|-Certificate obtained successfully!'))
write_log("=" * 65)
write_log(public.getMsg('ACME_USE_TIPS27',(','.join(cert['domains']),)))
write_log(public.getMsg('ACME_USE_TIPS28',(public.format_date(times=cert['cert_timeout']),)))
write_log(public.getMsg('ACME_USE_TIPS29',(cert['save_path'],)))
write_log(public.get_msg_gettext('Certified Domain Name: {}',(','.join(cert['domains']),)))
write_log(public.get_msg_gettext('Certificate expiration time: {}',(public.format_date(times=cert['cert_timeout']),)))
write_log(public.get_msg_gettext('Certificate saved at: {}/',(cert['save_path'],)))
+347 -96
View File
@@ -6,7 +6,7 @@
# +-------------------------------------------------------------------
# | Author: hwliang <hwl@bt.cn>
# +-------------------------------------------------------------------
from BTPanel import session,request
from BTPanel import session,request,cache
import public,os,json,time,apache,psutil
class ajax:
__official_url = 'https://brandnew.aapanel.com'
@@ -25,7 +25,7 @@ class ajax:
pass
def GetNginxStatus(self,get):
try:
if not os.path.exists('/www/server/nginx/sbin/nginx'): return public.returnMsg(False,'NGINX_NOT_INSTALL')
if not os.path.exists('/www/server/nginx/sbin/nginx'): return public.return_msg_gettext(False,'Nginx is not install')
process_cpu = {}
worker = int(public.ExecShell("ps aux|grep nginx|grep 'worker process'|wc -l")[0])-1
workermen = int(public.ExecShell("ps aux|grep nginx|grep 'worker process'|awk '{memsum+=$6};END {print memsum}'")[0]) / 1024
@@ -66,8 +66,8 @@ class ajax:
data['workermen'] = "%s%s" % (int(workermen), "MB")
return data
except Exception as ex:
public.WriteLog('GET_INFO','NGINX_LOAD_ERR',(ex,))
return public.returnMsg(False,'GET_DATA_ERR')
public.write_log_gettext('Get Info','Nginx load status acquisition failed:{}',(ex,))
return public.return_msg_gettext(False,'Data acquisition failed!')
def GetPHPStatus(self,get):
#取指定PHP版本的负载状态
@@ -80,8 +80,8 @@ class ajax:
tmp['start time'] = time.strftime('%Y-%m-%d %H:%M:%S',fTime)
return tmp
except Exception as ex:
public.WriteLog('GET_INFO',"PHP_LOAD_ERR",(public.get_error_info(),))
return public.returnMsg(False,'PHP_LOAD_ERR1')
public.write_log_gettext('Get Info',"PHP load status acquisition failed: {}",(public.get_error_info(),))
return public.return_msg_gettext(False,'PHP load status acquisition failed!')
def CheckStatusConf(self):
if public.get_webserver() != 'nginx': return
@@ -152,19 +152,19 @@ class ajax:
def CheckLibInstall(self,checks):
for cFile in checks:
if os.path.exists(cFile): return public.GetMsg("ALREADY_INSTALLED")
return public.GetMsg("NOT_INSTALL")
if os.path.exists(cFile): return public.GetMsg('Already installed')
return public.GetMsg('Not installed')
#取插件操作选项
def GetLibOpt(self,status,libName):
optStr = ''
if status == public.GetMsg("NOT_INSTALL"):
optStr = '<a class="link" href="javascript:InstallLib(\''+libName+'\');">'+public.GetMsg("INSTALL")+'</a>'
if status == public.GetMsg('Not installed'):
optStr = '<a class="link" href="javascript:InstallLib(\''+libName+'\');">'+public.GetMsg('Uninstallaton succeeded')+'</a>'
else:
libConfig = public.GetMsg("CONF")
if(libName == 'beta'): libConfig = public.GetMsg("CLOSE_BETA")
libConfig = public.GetMsg('Old configuration')
if(libName == 'beta'): libConfig = public.GetMsg('Beta tester profile')
optStr = '<a class="link" href="javascript:SetLibConfig(\''+libName+'\');">'+libConfig+'</a> | <a class="link" href="javascript:UninstallLib(\''+libName+'\');">'+public.GetMsg("UNINSTALL")+'</a>';
optStr = '<a class="link" href="javascript:SetLibConfig(\''+libName+'\');">'+libConfig+'</a> | <a class="link" href="javascript:UninstallLib(\''+libName+'\');">'+public.get_msg_gettext("Uninstallaton succeeded")+'</a>';
return optStr
#取插件AS
@@ -189,9 +189,9 @@ class ajax:
result = public.ExecShell(public.get_python_bin() + " " + public.GetConfigValue('setup_path') + "/panel/script/backup_"+get.name+".py list")
if result[0].find("ERROR:") == -1:
public.WriteLog("PLUG_MAM","SET_PLUG[" +info['name']+ "]AS!")
return public.returnMsg(True, 'SET_SUCCESS')
return public.returnMsg(False,'AK_SK_CONNECT_ERROR',(info['name'],))
public.write_log_gettext("Plugin manager","Set plugin [" +info['name']+ "]AS!")
return public.return_msg_gettext(True, 'Successfully set')
return public.return_msg_gettext(False,'ERROR: Unable to connect to the {} server, please check if the [AK/SK/Storage] setting is correct!',(info['name'],))
#设置内测
def SetBeta(self,get):
@@ -229,7 +229,7 @@ class ajax:
result = public.ExecShell(public.get_python_bin() + " " + public.GetConfigValue('setup_path') + "/panel/script/backup_"+get.name+".py list")
return json.loads(result[0])
except:
return public.returnMsg(False, 'GET_QINIU_FILE_LIST')
return public.return_msg_gettext(False, 'Failed to get the list, please check if the [AK/SK/Storage] setting is correct!')
@@ -301,11 +301,11 @@ class ajax:
import psutil
p = psutil.Process(int(get.pid))
name = p.name()
if name == 'python': return public.returnMsg(False,'KILL_PROCESS_ERR')
if name == 'python': return public.return_msg_gettext(False,'Error, cannot end task processes!')
p.kill()
public.WriteLog('TYPE_PROCESS','KILL_PROCESS',(get.pid,name))
return public.returnMsg(True,'KILL_PROCESS',(get.pid,name))
public.write_log_gettext('Task manager','Ended processes[{}][{}] Successfully!',(get.pid,name))
return public.return_msg_gettext(True,'Ended processes[{}][{}] Successfully!',(get.pid,name))
def GoToProcess(self,name):
ps = ['sftp-server','login','nm-dispatcher','irqbalance','qmgr','wpa_supplicant','lvmetad','auditd','master','dbus-daemon','tapdisk','sshd','init','ksoftirqd','kworker','kmpathd','kmpath_handlerd','python','kdmflush','bioset','crond','kthreadd','migration','rcu_sched','kjournald','iptables','systemd','network','dhclient','systemd-journald','NetworkManager','systemd-logind','systemd-udevd','polkitd','tuned','rsyslogd']
@@ -445,8 +445,8 @@ class ajax:
public.writeFile('/www/server/panel/data/is_beta.pl','true')
try:
return {'status': True, 'msg': "Successful application!"}
except: return public.returnMsg(False,'AJAX_CONN_ERR')
except: return public.returnMsg(False,'AJAX_USER_BINDING_ERR')
except: return public.return_msg_gettext(False,'Fail to connect to the server!')
except: return public.return_msg_gettext(False,'Please bind your account first!')
def to_not_beta(self,get):
try:
@@ -461,8 +461,8 @@ class ajax:
if os.path.exists(beta_file):
os.remove(beta_file)
return {"status": True, "msg": "Successful application!"}
except: return public.returnMsg(False,'AJAX_CONN_ERR')
except: return public.returnMsg(False,'AJAX_USER_BINDING_ERR')
except: return public.return_msg_gettext(False,'Fail to connect to the server!')
except: return public.return_msg_gettext(False,'Please bind your account first!')
def to_beta(self):
try:
@@ -483,11 +483,10 @@ class ajax:
#获取最新的5条测试版更新日志
def get_beta_logs(self,get):
try:
# data = json.loads(public.HttpGet('https://console.aapanel.com/api/panel/get_beta_logs_en'))
data = json.loads(public.HttpGet('{}/api/panel/getBetaVersionLogs'.format(self.__official_url)))
return data
except:
return public.returnMsg(False,'AJAX_CONN_ERR')
return public.return_msg_gettext(False,'Fail to connect to the server!')
def get_other_info(self):
other = {}
@@ -502,13 +501,11 @@ class ajax:
def UpdatePanel(self,get):
try:
if not public.IsRestart(): return public.returnMsg(False,'EXEC_ERR_TASK')
if not public.IsRestart(): return public.return_msg_gettext(False,'Please run the program when all install tasks finished!')
import json
conf_status = public.M('config').where("id=?",('1',)).field('status').find()
if int(session['config']['status']) == 0 and int(conf_status['status']) == 0:
# public.HttpGet('{}/api/setupCount/setupPanel?type=Linux'.format(self.__official_url))
public.arequests('get', '{}/api/setupCount/setupPanel?type=Linux'.format(self.__official_url))
public.M('config').where("id=?",('1',)).setField('status',1)
#取回远程版本信息
@@ -535,21 +532,22 @@ class ajax:
data['oem'] = ''
data['intrusion'] = 0
data['uid'] = self.get_uid()
#msg = public.getMsg('PANEL_UPDATE_MSG');
#msg = public.getMsg('Current version is stable version and already latest. Update cycle of stable version is generally 2 monthswhile developer version will update every Wednesday!');
data['o'] = public.get_oem_name()
sUrl = '{}/api/panel/updateLinuxEn'.format(self.__official_url)
updateInfo = json.loads(public.httpPost(sUrl,data))
if not updateInfo: return public.returnMsg(False,"CONNECT_ERR")
if not updateInfo: return public.return_msg_gettext(False,'Failed to connect server!')
#updateInfo['msg'] = msg;
if os.path.exists('/www/server/panel/data/is_beta.pl'):
updateInfo['is_beta'] = 1
session['updateInfo'] = updateInfo
#检查是否需要升级
if updateInfo['is_beta'] == 1:
if updateInfo['beta']['version'] ==session['version']: return public.returnMsg(False,updateInfo)
else:
if updateInfo['version'] ==session['version']: return public.returnMsg(False,updateInfo)
if not hasattr(get,'toUpdate'):
if updateInfo['is_beta'] == 1:
if updateInfo['beta']['version'] == session['version']: return public.returnMsg(False,updateInfo)
else:
if updateInfo['version'] == session['version']: return public.returnMsg(False,updateInfo)
#是否执行升级程序
@@ -560,9 +558,9 @@ class ajax:
httpUrl = public.get_url()
if httpUrl: updateInfo['downUrl'] = httpUrl + '/install/' + uptype + '/LinuxPanel_EN-' + updateInfo['version'] + '.zip'
public.downloadFile(updateInfo['downUrl'],'panel.zip')
if os.path.getsize('panel.zip') < 1048576: return public.returnMsg(False,"PANEL_UPDATE_ERR_DOWN")
if os.path.getsize('panel.zip') < 1048576: return public.return_msg_gettext(False,'File download failed, please try again or update manually!')
public.ExecShell('unzip -o panel.zip -d ' + setupPath + '/')
import compileall
# import compileall
if os.path.exists('/www/server/panel/runserver.py'): public.ExecShell('rm -f /www/server/panel/*.pyc')
if os.path.exists('/www/server/panel/class/common.py'): public.ExecShell('rm -f /www/server/panel/class/*.pyc')
@@ -572,7 +570,7 @@ class ajax:
if updateInfo['is_beta'] == 1: self.to_beta()
public.ExecShell("/etc/init.d/bt start")
public.writeFile('data/restart.pl','True')
return public.returnMsg(True,'PANEL_UPDATE',(updateInfo['version'],))
return public.return_msg_gettext(True,'Successful to update to {}',(updateInfo['version'],))
#输出新版本信息
data = {
@@ -580,13 +578,20 @@ class ajax:
'version': updateInfo['version'],
'updateMsg' : updateInfo['updateMsg']
}
# 输出忽略的版本
updateInfo['ignore'] = []
no_path = '{}/data/no_update.pl'.format(public.get_panel_path())
if os.path.exists(no_path):
try:
updateInfo['ignore'] = json.loads(public.readFile(no_path))
except:
pass
public.ExecShell('rm -rf /www/server/phpinfo/*')
return public.returnMsg(True,updateInfo)
except Exception as ex:
return public.get_error_info()
return public.returnMsg(False,"CONNECT_ERR")
return public.return_msg_gettext(False,'Failed to connect server!')
#检查是否安装任何
def CheckInstalled(self,get):
checks = ['nginx','apache','php','pure-ftpd','mysql']
@@ -611,7 +616,7 @@ class ajax:
filename = '/usr/local/lsws/lsphp{}/etc/php/{}.{}/litespeed/php.ini'.format(get.version,get.version[0],get.version[1])
if os.path.exists('/etc/redhat-release'):
filename = '/usr/local/lsws/lsphp' + get.version + '/etc/php.ini'
if not os.path.exists(filename): return public.returnMsg(False,'PHP_NOT_EXISTS')
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"
@@ -698,7 +703,7 @@ class ajax:
# 下载云端php扩展配置
def _get_cloud_phplib(self):
if not session.get('download_url'): session['download_url'] = 'http://node.aapanel.com'
if not session.get('download_url'): session['download_url'] = 'https://node.aapanel.com'
download_url = session['download_url'] + '/install/lib/phplib_en.json'
tstr = public.httpGet(download_url)
data = json.loads(tstr)
@@ -723,13 +728,13 @@ class ajax:
#清理日志
def delClose(self,get):
if not 'uid' in session: session['uid'] = 1
if session['uid'] != 1: return public.returnMsg(False,'PERMISSION_DENIED')
if session['uid'] != 1: return public.return_msg_gettext(False,'Permission denied!')
if 'tmp_login_id' in session:
return public.returnMsg(False,'PERMISSION_DENIED')
return public.return_msg_gettext(False,'Permission denied!')
public.M('logs').where('id>?',(0,)).delete()
public.WriteLog('TYPE_CONFIG','LOG_CLOSE')
return public.returnMsg(True,'LOG_CLOSE')
public.write_log_gettext('Panel setting','Panel Logs emptied!')
return public.return_msg_gettext(True,'Panel Logs emptied!')
def __get_webserver_conffile(self):
webserver = public.get_webserver()
@@ -778,54 +783,54 @@ class ajax:
# 修改php ssl端口
def change_phpmyadmin_ssl_port(self,get):
if public.get_webserver() == "openlitespeed":
return public.returnMsg(False, 'NOT_SUPPORT_OLS')
return public.return_msg_gettext(False, 'The current web server is openlitespeed. This function is not supported yet.')
import re
try:
port = int(get.port)
if 1 > port > 65535:
return public.returnMsg(False, 'PORT_CHECK_RANGE')
return public.return_msg_gettext(False, 'Port range is incorrect!')
except:
return public.returnMsg(False, 'PORT_FORMAT_ERR')
return public.return_msg_gettext(False, 'Please enter the correct port number')
for i in ["nginx","apache"]:
file = "/www/server/panel/vhost/{}/phpmyadmin.conf".format(i)
conf = public.readFile(file)
if not conf:
return public.returnMsg(False,"PHPMYADMIN_SSL_ERR",(i,))
return public.return_msg_gettext(False,'Did not find the {} configuration file, please try to close the ssl port settings before opening',(i,))
rulePort = ['80', '443', '21', '20', '8080', '8081', '8089', '11211', '6379']
if get.port in rulePort:
return public.returnMsg(False, 'AJAX_PHPMYADMIN_PORT_ERR')
return public.return_msg_gettext(False, 'Please do NOT use the usual port as the phpMyAdmin port!')
if i == "nginx":
if not os.path.exists("/www/server/panel/vhost/apache/phpmyadmin.conf"):
return public.returnMsg(False, "PHPMYADMIN_SSL_ERR1")
return public.return_msg_gettext(False, 'Did not find the apache phpmyadmin ssl configuration file, please try to close the ssl port settings before opening')
rep = "listen\s*([0-9]+)\s*.*;"
oldPort = re.search(rep, conf)
if not oldPort:
return public.returnMsg(False, 'PHPMYADMIN_SSL_ERR2')
return public.return_msg_gettext(False, 'Did not detect the port that nginx phpmyadmin listens, please confirm whether the file has been manually modified.')
oldPort = oldPort.groups()[0]
conf = re.sub(rep, 'listen ' + get.port + ' ssl;', conf)
else:
rep = "Listen\s*([0-9]+)\s*\n"
oldPort = re.search(rep, conf)
if not oldPort:
return public.returnMsg(False, 'PHPMYADMIN_SSL_ERR3')
return public.return_msg_gettext(False, 'Did not detect the port that apache phpmyadmin listens, please confirm whether the file has been manually modified.')
oldPort = oldPort.groups()[0]
conf = re.sub(rep, "Listen " + get.port + "\n", conf, 1)
rep = "VirtualHost\s*\*:[0-9]+"
conf = re.sub(rep, "VirtualHost *:" + get.port, conf, 1)
if oldPort == get.port: return public.returnMsg(False, 'SOFT_PHPVERSION_ERR_PORT')
if oldPort == get.port: return public.return_msg_gettext(False, 'Port [{}] is in use!',(get.port,))
public.writeFile(file, conf)
public.serviceReload()
if i=="apache":
import firewalls
get.ps = public.getMsg('SOFT_PHPVERSION_PS')
get.ps = public.getMsg('New phpMyAdmin Port')
fw = firewalls.firewalls()
fw.AddAcceptPort(get)
public.serviceReload()
public.WriteLog('TYPE_SOFT', 'SOFT_PHPMYADMIN_PORT', (get.port,))
public.write_log_gettext('Software manager', 'Modified access port to {} for phpMyAdmin!', (get.port,))
get.id = public.M('firewall').where('port=?', (oldPort,)).getField('id')
get.port = oldPort
fw.DelAcceptPort(get)
return public.returnMsg(True, 'SET_PORT_SUCCESS')
return public.return_msg_gettext(True, 'Setup successfully!')
def _get_phpmyadmin_auth(self):
import re
@@ -846,9 +851,9 @@ class ajax:
# 设置phpmyadmin ssl
def set_phpmyadmin_ssl(self,get):
if public.get_webserver() == "openlitespeed":
return public.returnMsg(False, 'NOT_SUPPORT_OLS')
return public.return_msg_gettext(False, 'The current web server is openlitespeed. This function is not supported yet.')
if not os.path.exists("/www/server/panel/ssl/certificate.pem"):
return public.returnMsg(False,'PHPMYADMIN_SSL_ERR4')
return public.return_msg_gettext(False,'The panel certificate does not exist. Please apply for the panel certificate and try again.')
if get.v == "1":
# 获取auth信息
auth = ""
@@ -952,9 +957,9 @@ class ajax:
if os.path.exists("/www/server/panel/vhost/apache/phpmyadmin.conf"):
os.remove("/www/server/panel/vhost/apache/phpmyadmin.conf")
public.serviceReload()
return public.returnMsg(True, 'SET_SUCCESS')
return public.return_msg_gettext(True, 'Setup successfully!')
public.serviceReload()
return public.returnMsg(True,'PHPMYADMIN_SSL_ERR5')
return public.return_msg_gettext(True,'Open successfully, please manually release phpmyadmin ssl port')
#设置PHPMyAdmin
@@ -965,13 +970,13 @@ class ajax:
if public.get_webserver() == 'openlitespeed':
filename = "/www/server/panel/vhost/openlitespeed/detail/phpmyadmin.conf"
conf = public.readFile(filename)
if not conf: return public.returnMsg(False,'ERROR')
if not conf: return public.return_msg_gettext(False,'Operation failed')
if hasattr(get,'port'):
mainPort = public.readFile('data/port.pl').strip()
rulePort = ['80','443','21','20','8080','8081','8089','11211','6379']
oldPort = "888"
if get.port in rulePort:
return public.returnMsg(False,'AJAX_PHPMYADMIN_PORT_ERR')
return public.return_msg_gettext(False,'Please do NOT use the usual port as the phpMyAdmin port!')
if public.get_webserver() == 'nginx':
rep = r"listen\s+([0-9]+)\s*;"
oldPort = re.search(rep,conf).groups()[0]
@@ -990,19 +995,19 @@ class ajax:
if tmp:
oldPort = tmp.groups(1)
conf = re.sub(reg,"address *:{}".format(get.port),conf)
if oldPort == get.port: return public.returnMsg(False,'SOFT_PHPVERSION_ERR_PORT')
if oldPort == get.port: return public.returnMsg(False,'Port [{}] is in use!',(get.port,))
public.writeFile(filename,conf)
import firewalls
get.ps = public.getMsg('SOFT_PHPVERSION_PS')
get.ps = public.getMsg('New phpMyAdmin Port')
fw = firewalls.firewalls()
fw.AddAcceptPort(get)
public.serviceReload()
public.WriteLog('TYPE_SOFT','SOFT_PHPMYADMIN_PORT',(get.port,))
public.write_log_gettext('Software manager','Modified access port to {} for phpMyAdmin!',(get.port,))
get.id = public.M('firewall').where('port=?',(oldPort,)).getField('id')
get.port = oldPort
fw.DelAcceptPort(get)
return public.returnMsg(True,'SET_PORT_SUCCESS')
return public.returnMsg(True,'Setup successfully!')
if hasattr(get,'phpversion'):
if public.get_webserver() == 'nginx':
@@ -1018,8 +1023,8 @@ class ajax:
conf = re.sub(reg,'/usr/local/lsws/lsphp{}/bin/lsphp'.format(get.phpversion),conf)
public.writeFile(filename,conf)
public.serviceReload()
public.WriteLog('TYPE_SOFT','SOFT_PHPMYADMIN_PHP',(get.phpversion,))
return public.returnMsg(True,'SOFT_PHPVERSION_SET')
public.write_log_gettext('Software manager','Modified PHP runtime version to PHP-{} for phpMyAdmin!',(get.phpversion,))
return public.return_msg_gettext(True,'Setup successfully!')
if hasattr(get,'password'):
import panelSite
@@ -1029,17 +1034,49 @@ class ajax:
return panelSite.panelSite().SetHasPwd(get)
if hasattr(get,'status'):
if conf.find(public.GetConfigValue('setup_path') + '/stop') != -1:
conf = conf.replace(public.GetConfigValue('setup_path') + '/stop',public.GetConfigValue('setup_path') + '/phpmyadmin')
pma_path = public.GetConfigValue('setup_path') + '/phpmyadmin'
stop_path = public.GetConfigValue('setup_path') + '/stop'
webserver = public.get_webserver()
if conf.find(stop_path) != -1:
conf = conf.replace(stop_path,pma_path)
msg = public.getMsg('START')
if webserver == 'nginx':
sub_string = '''{};
allow 127.0.0.1;
allow ::1;
deny all'''.format(pma_path)
if conf.find(sub_string) != -1:
conf = conf.replace(sub_string,pma_path)
msg = public.getMsg('START')
else:
conf = conf.replace(pma_path,sub_string)
msg = public.getMsg('STOP')
elif webserver == 'apache':
src_string = 'AllowOverride All'
sub_string = '''{}
Deny from all
Allow from 127.0.0.1 ::1 localhost'''.format(src_string,pma_path)
if conf.find(sub_string) != -1:
conf = conf.replace(sub_string,src_string)
msg = public.getMsg('START')
else:
conf = conf.replace(src_string,sub_string)
msg = public.getMsg('STOP')
else:
conf = conf.replace(public.GetConfigValue('setup_path') + '/phpmyadmin',public.GetConfigValue('setup_path') + '/stop')
msg = public.getMsg('STOP')
if conf.find(stop_path) != -1:
conf = conf.replace(stop_path,pma_path)
msg = public.getMsg('START')
else:
conf = conf.replace(pma_path,stop_path)
msg = public.getMsg('STOP')
public.writeFile(filename,conf)
public.serviceReload()
public.WriteLog('TYPE_SOFT','SOFT_PHPMYADMIN_STATUS',(msg,))
return public.returnMsg(True,'SOFT_PHPMYADMIN_STATUS',(msg,))
public.write_log_gettext('Software manager','phpMyAdmin already {}!',(msg,))
return public.return_msg_gettext(True,'phpMyAdmin already {}!',(msg,))
#except:
#return public.returnMsg(False,'ERROR');
@@ -1060,8 +1097,8 @@ class ajax:
#保存PHP排序
def phpSort(self,get):
if public.writeFile('/www/server/php/sort.pl',get.ssort): return public.returnMsg(True,'SUCCESS')
return public.returnMsg(False,'ERROR')
if public.writeFile('/www/server/php/sort.pl',get.ssort): return public.return_msg_gettext(True,'Setup successfully!')
return public.return_msg_gettext(False,'Operation failed')
#获取广告代码
def GetAd(self,get):
@@ -1081,7 +1118,7 @@ class ajax:
#获取警告标识
def GetWarning(self,get):
warningFile = 'data/warning.json'
if not os.path.exists(warningFile): return public.returnMsg(False,'AJAX_WARNING_ERR')
if not os.path.exists(warningFile): return public.return_msg_gettext(False,'Warning list does NOT exist!')
import json,time;
wlist = json.loads(public.readFile(warningFile))
wlist['time'] = int(time.time())
@@ -1099,7 +1136,7 @@ class ajax:
warningFile = 'data/warning.json'
public.writeFile(warningFile,json.dumps(wlist))
return public.returnMsg(True,'SET_SUCCESS')
return public.return_msg_gettext(True,'Setup successfully!')
#获取memcached状态
def GetMemcachedStatus(self,get):
@@ -1139,7 +1176,7 @@ class ajax:
conf = re.sub('CACHESIZE=\d+','CACHESIZE='+get.cachesize,conf)
public.writeFile(confFile,conf)
public.ExecShell(confFile + ' reload')
return public.returnMsg(True,'SET_SUCCESS')
return public.return_msg_gettext(True,'Setup successfully!')
#取redis状态
def GetRedisStatus(self,get):
@@ -1180,10 +1217,10 @@ class ajax:
def GetFpmLogs(self,get):
import re
fpm_path = '/www/server/php/' + get.version + '/etc/php-fpm.conf'
if not os.path.exists(fpm_path): return public.returnMsg(False,'AJAX_LOG_FILR_NOT_EXISTS')
if not os.path.exists(fpm_path): return public.return_msg_gettext(False,'Log file does NOT exist!')
fpm_conf = public.readFile(fpm_path)
log_tmp = re.findall(r"error_log\s*=\s*(.+)",fpm_conf)
if not log_tmp: return public.returnMsg(False,'AJAX_LOG_FILR_NOT_EXISTS')
if not log_tmp: return public.return_msg_gettext(False,'Log file does NOT exist!')
log_file = log_tmp[0].strip()
if log_file.find('var/log') == 0:
log_file = '/www/server/php/' +get.version + '/'+ log_file
@@ -1193,10 +1230,10 @@ class ajax:
def GetFpmSlowLogs(self,get):
import re
fpm_path = '/www/server/php/' + get.version + '/etc/php-fpm.conf'
if not os.path.exists(fpm_path): return public.returnMsg(False,'AJAX_LOG_FILR_NOT_EXISTS')
if not os.path.exists(fpm_path): return public.return_msg_gettext(False,'Log file does NOT exist!')
fpm_conf = public.readFile(fpm_path)
log_tmp = re.findall(r"slowlog\s*=\s*(.+)",fpm_conf)
if not log_tmp: return public.returnMsg(False,'AJAX_LOG_FILR_NOT_EXISTS')
if not log_tmp: return public.return_msg_gettext(False,'Log file does NOT exist!')
log_file = log_tmp[0].strip()
if log_file.find('var/log') == 0:
log_file = '/www/server/php/' +get.version + '/'+ log_file
@@ -1204,12 +1241,120 @@ class ajax:
#取指定日志
def GetOpeLogs(self,get):
if not os.path.exists(get.path): return public.returnMsg(False,'AJAX_LOG_FILR_NOT_EXISTS')
if not os.path.exists(get.path): return public.return_msg_gettext(False,'Log file does NOT exist!')
return public.returnMsg(True,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([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, 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 check_user_auth(self,get):
import requests
# import requests
m_key = 'check_user_auth'
if m_key in session: return session[m_key]
u_path = 'data/userInfo.json'
@@ -1217,15 +1362,16 @@ class ajax:
userInfo = json.loads(public.ReadFile(u_path))
except:
if os.path.exists(u_path): os.remove(u_path)
return public.returnMsg(False,'AJAX_USER_BE_OVERDUE')
return public.return_msg_gettext(False,'Account binding has expired, please re-bind on the [Settings] page!')
url_headers = {"authorization":"bt {}".format(userInfo['token'])}
resp = requests.post('{}/api/user/verifyToken'.format(self.__official_url),headers=url_headers,verify=False)
# resp = requests.post('{}/api/user/verifyToken'.format(self.__official_url),headers=url_headers,verify=False)
resp = public.HttpPost.post('{}/api/user/verifyToken'.format(self.__official_url), headers=url_headers, verify=False)
resp = resp.json()
if not resp['success']:
if os.path.exists(u_path): os.remove(u_path)
return public.returnMsg(False,'AJAX_USER_BE_OVERDUE')
return public.return_msg_gettext(False,'Account binding has expired, please re-bind on the [Settings] page!')
else:
session[m_key] = public.returnMsg(True,'AJAX_USER_IS_VALID')
session[m_key] = public.return_msg_gettext(True,'Binding is valid!')
return session[m_key]
@@ -1239,7 +1385,7 @@ class ajax:
php_ini = php_path + php_version + '/etc/php.ini'
if not os.path.exists('/etc/redhat-release') and public.get_webserver() == 'openlitespeed':
php_ini = php_path + php_version + '/etc/php/'+args.php_version+'/litespeed/php.ini'
tmp = public.ExecShell(php_bin + ' /www/server/panel/class/php_info.php')[0]
tmp = public.ExecShell(php_bin + ' -c {} /www/server/panel/class/php_info.php'.format(php_ini))[0]
if tmp.find('Warning: JIT is incompatible') != -1:
tmp = tmp.strip().split('\n')[-1]
result = json.loads(tmp)
@@ -1258,8 +1404,113 @@ class ajax:
#取指定行
def get_lines(self,args):
if not os.path.exists(args.filename): return public.returnMsg(False,'LOG_EMPTY')
if not os.path.exists(args.filename): return public.returnMsg(False,'Logs emptied')
s_body = public.ExecShell("tail -n {} {}".format(args.num,args.filename))[0]
return public.returnMsg(True,s_body)
def log_analysis(self,get):
import log_analysis
log_analysis=log_analysis.log_analysis()
return log_analysis.log_analysis(get)
def speed_log(self,get):
import log_analysis
log_analysis=log_analysis.log_analysis()
return log_analysis.speed_log(get)
def get_result(self,get):
import log_analysis
log_analysis=log_analysis.log_analysis()
return log_analysis.get_result(get)
def get_detailed(self,get):
import log_analysis
log_analysis=log_analysis.log_analysis()
return log_analysis.get_detailed(get)
def download_pay_type(self, path):
public.downloadFile(public.get_url() + '/install/lib/pay_type_en.json', path)
return True
def get_pay_type(self, get):
"""
@name 获取推荐列表
"""
spath = '{}/data/pay_type.json'.format(public.get_panel_path())
down = cache.get('pay_type')
if not down:
public.run_thread(self.download_pay_type, (spath,))
cache.set('pay_type', 1, 86400)
try:
data = json.loads(public.readFile("data/pay_type.json"))
except:
public.run_thread(self.download_pay_type, (spath,))
data = {}
import panelPlugin
plu_panel = panelPlugin.panelPlugin()
plugin_list = plu_panel.get_cloud_list()
if not 'pro' in plugin_list: plugin_list['pro'] = -1
for item in data:
if 'list' in item:
item['list'] = self.__get_home_list(item['list'], item['type'], plugin_list, plu_panel)
if item['type'] == 1:
if len(item['list']) > 4: item['list'] = item['list'][:4]
# if item['type'] == 0 and plugin_list['pro'] >= 0:
# item['show'] = False
return data
def __get_home_list(self, sList, stype, plugin_list, plu_panel):
"""
@name 获取首页软件列表推荐
"""
nList = []
webserver = public.get_webserver()
for x in sList:
for plugin_info in plugin_list['list']:
if x['name'] == plugin_info['name']:
if not 'endtime' in plugin_info or plugin_info['endtime'] >= 0:
x['isBuy'] = True
is_check = False
if 'dependent' in x:
if x['dependent'] == webserver: is_check = True
else:
is_check = True
if is_check:
info = plu_panel.get_soft_find(x['name'])
if info:
if stype == 1:
# if plugin_list['pro'] >= 0: continue
if not info['setup']:
x['install'] = info['setup']
nList.append(x)
else:
x['install'] = info['setup']
nList.append(x)
return nList
def ignore_version(self, get):
"""
@忽略版本更新
:param version 忽略的版本号
"""
version = get.version
path = '{}/data/no_update.pl'.format(public.get_panel_path())
try:
data = json.loads(public.readFile(path))
except:
data = []
if not version in data: data.append(version)
public.writeFile(path, json.dumps(data))
try:
del (session['updateInfo'])
except:
pass
return public.return_msg_gettext(True, "Ignore success, this version will no longer be reminded to update.")
+36 -36
View File
@@ -43,7 +43,7 @@ class apache:
try:
workermen = int(public.ExecShell("ps aux|grep httpd|grep 'start'|awk '{memsum+=$6};END {print memsum}'")[0]) / 1024
except:
return public.returnMsg(False,"Get worker RAM False")
return public.return_msg_gettext(False,"Get worker RAM False")
for proc in psutil.process_iter():
if proc.name() == "httpd":
self.GetProcessCpuPercent(proc.pid,process_cpu)
@@ -54,7 +54,7 @@ class apache:
# 计算启动时间
Uptime = re.search("ServerUptimeSeconds:\s+(.*)",result)
if not Uptime:
return public.returnMsg(False, "Get worker Uptime False")
return public.return_msg_gettext(False, "Get worker Uptime False")
Uptime = int(Uptime.group(1))
min = Uptime / 60
hours = min / 60
@@ -65,16 +65,16 @@ class apache:
#格式化重启时间
restarttime = re.search("RestartTime:\s+(.*)",result)
if not restarttime:
return public.returnMsg(False, "Get worker Restart Time False")
return public.return_msg_gettext(False, "Get worker Restart Time False")
restarttime = restarttime.group(1)
rep = "\w+,\s([\w-]+)\s([\d\:]+)\s\w+"
date = re.search(rep,restarttime)
if not date:
return public.returnMsg(False, "Get worker date False")
return public.return_msg_gettext(False, "Get worker date False")
date = date.group(1)
timedetail = re.search(rep,restarttime)
if not timedetail:
return public.returnMsg(False, "Get worker time detail False")
return public.return_msg_gettext(False, "Get worker time detail False")
timedetail=timedetail.group(2)
monthen = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]
n = 0
@@ -87,7 +87,7 @@ class apache:
reqpersec = re.search("ReqPerSec:\s+(.*)", result)
if not reqpersec:
return public.returnMsg(False, "Get worker reqpersec False")
return public.return_msg_gettext(False, "Get worker reqpersec False")
reqpersec = reqpersec.group(1)
if re.match("^\.", reqpersec):
reqpersec = "%s%s" % (0,reqpersec)
@@ -95,20 +95,20 @@ class apache:
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)
if not total_acc:
return public.returnMsg(False, "Get worker TotalAccesses False")
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)
if not total_kb:
return public.returnMsg(False, "Get worker TotalKBytes False")
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)
if not busywork:
return public.returnMsg(False, "Get worker BusyWorkers False")
return public.return_msg_gettext(False, "Get worker BusyWorkers False")
data["BusyWorkers"] = busywork.group(1)
idlework = re.search("IdleWorkers:\s+(\d+)",result)
if not idlework:
return public.returnMsg(False, "Get worker IdleWorkers False")
return public.return_msg_gettext(False, "Get worker IdleWorkers False")
data["IdleWorkers"] = idlework.group(1)
data["workercpu"] = round(float(process_cpu["httpd"]),2)
data["workermem"] = "%s%s" % (int(workermen),"MB")
@@ -120,10 +120,10 @@ class apache:
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()
ps = ["%s%s" % (public.GetMsg("SECOND"),public.GetMsg("REQUEST_TIMEOUT_TIME")),
public.GetMsg("KEEP_ALIVE"),
"%s%s" % (public.GetMsg("SECOND"),public.GetMsg("CONNECT_TIMEOUT_TIME")),
public.GetMsg("MAX_KEEP_ALIVE_REQUESTS")]
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')),
public.get_msg_gettext('Max keep-alive requests per connection')]
gets = ["Timeout","KeepAlive","KeepAliveTimeout","MaxKeepAliveRequests"]
if public.get_webserver() == 'apache':
shutil.copyfile(self.apachedefaultfile, '/tmp/apdefault_file_bk.conf')
@@ -134,34 +134,34 @@ class apache:
rep = "(%s)\s+(\w+)" % i
k = re.search(rep, apachedefaultcontent)
if not k:
return public.returnMsg(False, "Get Key {} False".format(k))
return public.return_msg_gettext(False, "Get Key {} False",(i,))
k = k.group(1)
v = re.search(rep, apachedefaultcontent)
if not v:
return public.returnMsg(False, "Get Value {} False".format(v))
return public.return_msg_gettext(False, "Get Value {} False",(v,))
v = v.group(2)
psstr = ps[n]
kv = {"name":k,"value":v,"ps":psstr}
conflist.append(kv)
n += 1
ps = [public.GetMsg("DEFUALT_PROCESSES"),
public.GetMsg("MAX_SPARE_THREADS"),
public.GetMsg("MIN_SPARE_THREADS"),
public.GetMsg("THREADS_PER_CHILD"),
public.GetMsg("MAX_REQUEST_WORKERS"),
public.GetMsg("MaxConnectionsPerChild")]
ps = [public.get_msg_gettext('Default processes'),
public.get_msg_gettext('Maximum number of idle threads'),
public.get_msg_gettext('Minimum number of idle threads available to handle request spikes'),
public.get_msg_gettext('Number of threads created by each child process'),
public.get_msg_gettext('Maximum number of connections that will be processed simultaneously'),
public.get_msg_gettext('Limit on the number of connections that an individual child server will handle during its life')]
gets = ["StartServers","MaxSpareThreads","MinSpareThreads","ThreadsPerChild","MaxRequestWorkers","MaxConnectionsPerChild"]
n = 0
for i in gets:
rep = "(%s)\s+(\w+)" % i
k = re.search(rep, apachempmcontent)
if not k:
return public.returnMsg(False, "Get Key {} False".format(k))
return public.return_msg_gettext(False, "Get Key {} False",(i,))
k = k.group(1)
v = re.search(rep, apachempmcontent)
if not v:
return public.returnMsg(False, "Get Value {} False".format(v))
return public.return_msg_gettext(False, "Get Value {} False",(v,))
v = v.group(2)
psstr = ps[n]
kv = {"name": k, "value": v, "ps": psstr}
@@ -173,7 +173,7 @@ class apache:
apachedefaultcontent = public.readFile(self.apachedefaultfile)
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")
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__
for i in getdict.keys():
@@ -186,12 +186,12 @@ class apache:
for c in conflist:
if c["name"] == "KeepAlive":
if not re.search("on|off", c["value"]):
return public.returnMsg(False, "INIT_ARGS_ERR")
return public.return_msg_gettext(False, 'Parameter ERROR!')
else:
print(c["value"])
if not re.search("\d+", c["value"]):
print(c["name"],c["value"])
return public.returnMsg(False, 'INIT_ARGS_ERR')
return public.return_msg_gettext(False, 'Parameter ERROR!')
rep = "%s\s+\w+" % c["name"]
if re.search(rep,apachedefaultcontent):
@@ -206,10 +206,10 @@ class apache:
if (isError != True):
shutil.copyfile('/tmp/_file_bk.conf', self.apachedefaultfile)
shutil.copyfile('/tmp/proxyfile_bk.conf', self.apachempmfile)
return public.returnMsg(False, 'ERROR: %s<br><a style="color:red;">' % public.GetMsg("CONFIG_ERROR") + isError.replace("\n",
return public.returnMsg(False, 'ERROR: %s<br><a style="color:red;">' % public.get_msg_gettext('Configuration ERROR') + isError.replace("\n",
'<br>') + '</a>')
public.serviceReload()
return public.returnMsg(True, 'SET_SUCCESS')
return public.return_msg_gettext(True, 'Setup successfully!')
def add_httpd_access_log_format(self,args):
'''
@@ -232,12 +232,12 @@ class apache:
self.del_httpd_access_log_format(args)
conf = public.readFile(self.httpdconf)
if not conf:
return public.returnMsg(False,'CONF_FILE_NOT_EXISTS')
return public.return_msg_gettext(False,'Configuration file not exist')
reg = '<IfModule log_config_module>'
conf = re.sub(reg,'<IfModule log_config_module>'+data,conf)
public.writeFile(self.httpdconf,conf)
public.serviceReload()
return public.returnMsg(True, 'SET_SUCCESS')
return public.return_msg_gettext(True, 'Setup successfully!')
except:
return public.returnMsg(False, str(public.get_error_info()))
@@ -249,13 +249,13 @@ class apache:
'''
conf = public.readFile(self.httpdconf)
if not conf:
return public.returnMsg(False, 'CONF_FILE_NOT_EXISTS')
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)
conf = re.sub(reg,'',conf)
self._del_format_log_of_website(args.log_format_name)
public.writeFile(self.httpdconf,conf)
public.serviceReload()
return public.returnMsg(True, 'SET_SUCCESS')
return public.return_msg_gettext(True, 'Setup successfully!')
def del_all_log_format(self,args):
all_format = self.get_httpd_access_log_format(args)
@@ -318,7 +318,7 @@ class apache:
reg = "#LOG_FORMAT_BEGIN.*"
conf = public.readFile(self.httpdconf)
if not conf:
return public.returnMsg(False, 'CONF_FILE_NOT_EXISTS')
return public.return_msg_gettext(False, 'Configuration file not exist')
data = re.findall(reg,conf)
format_name = [i.split('LOG_FORMAT_BEGIN_')[-1] for i in data]
format_log = {}
@@ -349,7 +349,7 @@ class apache:
website_conf_file = '/www/server/panel/vhost/apache/{}.conf'.format(site['name'])
conf = public.readFile(website_conf_file)
if not conf:
return public.returnMsg(False, 'CONF_FILE_NOT_EXISTS')
return public.return_msg_gettext(False, 'Configuration file not exist')
format_exist_reg = '(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):
@@ -360,7 +360,7 @@ class apache:
conf = re.sub(format_exist_reg,access_log,conf)
public.writeFile(website_conf_file,conf)
public.serviceReload()
return public.returnMsg(True, 'SET_SUCCESS')
return public.return_msg_gettext(True, 'Setup successfully!')
except:
return public.returnMsg(False, str(public.get_error_info()))
+71 -44
View File
@@ -40,6 +40,7 @@ class SimpleCache(BaseCache):
toremove.append(key)
for key in toremove:
self._cache.pop(key, None)
self.del_session_by_file(key)
def _normalize_timeout(self, timeout):
@@ -48,70 +49,87 @@ class SimpleCache(BaseCache):
timeout = time() + timeout
return timeout
def get(self, key):
try:
expires, value = self._cache[key]
if expires == 0 or expires > time():
return pickle.loads(value)
except (KeyError, pickle.PickleError):
try:
if key[:4] == self.__session_key:
filename = '/'.join((self.__session_basedir,self.md5(key)))
if not os.path.exists(filename): return None
with open(filename, 'rb') as fp:
_val = fp.read()
fp.close()
expires = struct.unpack('f',_val[:4])[0]
if expires == 0 or expires > time():
value = _val[4:]
self._cache[key] = (expires,value)
return pickle.loads(value)
except :pass
return None
def set(self, key, value, timeout=None):
expires = self._normalize_timeout(timeout)
self._prune()
_val = pickle.dumps(value, pickle.HIGHEST_PROTOCOL)
self._cache[key] = (expires,_val)
def get_session_by_file(self,key):
try:
if key[:4] == self.__session_key:
filename = '/'.join((self.__session_basedir,self.md5(key)))
if not os.path.exists(filename): return None
with open(filename, 'rb') as fp:
_val = fp.read()
fp.close()
expires = struct.unpack('f',_val[:4])[0]
if expires == 0 or expires > time():
value = _val[4:]
self._cache[key] = (expires,value)
return pickle.loads(value)
except :pass
def set_session_by_file(self,key,_val,expires):
try:
if key[:4] == self.__session_key:
if len(_val) < 256: return True
if not os.path.exists(self.__session_basedir): os.makedirs(self.__session_basedir,384)
expires = struct.pack('f',expires)
filename = '/'.join((self.__session_basedir,self.md5(key)))
filename = '/'.join((self.__session_basedir,self.md5(key)))
fp = open(filename, 'wb+')
fp.write(expires + _val)
fp.close()
os.chmod(filename,384)
except :pass
def del_session_by_file(self,key):
try:
if key[:4] == self.__session_key:
filename = '/'.join((self.__session_basedir,self.md5(key)))
if os.path.exists(filename): os.remove(filename)
except : pass
def get(self, key):
if not isinstance(key,str): return None
try:
expires, value = self._cache[key]
if expires == 0 or expires > time():
return pickle.loads(value)
except (KeyError, pickle.PickleError):
return self.get_session_by_file(key)
def set(self, key, value, timeout=None):
# 类型判断
if not isinstance(key,str): return False
type_list=(int,float,bool,str,list,dict,tuple,set,bytes)
if not isinstance(value,type_list): return False
# 过期清理
expires = self._normalize_timeout(timeout)
self._prune()
# 转换
_val = pickle.dumps(value, pickle.HIGHEST_PROTOCOL)
self._cache[key] = (expires,_val)
self.set_session_by_file(key,_val,expires)
return True
def add(self, key, value, timeout=None):
# 类型判断
if not isinstance(key,str): return False
type_list=(int,float,bool,str,list,dict,tuple,set,bytes)
if not isinstance(value,type_list): return False
expires = self._normalize_timeout(timeout)
self._prune()
item = (expires, pickle.dumps(value,
pickle.HIGHEST_PROTOCOL))
item = (expires, pickle.dumps(value,pickle.HIGHEST_PROTOCOL))
if key in self._cache:
return False
self._cache.setdefault(key, item)
self.set_session_by_file(key,item[1],expires)
return True
def delete(self, key):
result = self._cache.pop(key, None) is not None
try:
if key[:4] == self.__session_key:
filename = '/'.join((self.__session_basedir,self.md5(key)))
if os.path.exists(filename): os.remove(filename)
except : pass
self.del_session_by_file(key)
return result
def has(self, key):
@@ -119,8 +137,17 @@ class SimpleCache(BaseCache):
expires, value = self._cache[key]
return expires == 0 or expires > time()
except KeyError:
if self.get_session_by_file(key): return True
return False
def get_expire_time(self, key):
try:
expires, value = self._cache[key]
return expires
except KeyError:
return 0
def md5(self,strings):
"""
生成MD5
@@ -129,7 +156,7 @@ class SimpleCache(BaseCache):
"""
import hashlib
m = hashlib.md5()
m.update(strings.encode('utf-8'))
return m.hexdigest()
+26 -19
View File
@@ -26,7 +26,7 @@ class panelSetup:
ua = g.ua.lower()
if ua.find('spider') != -1 or g.ua.find('bot') != -1:
return redirect('https://www.google.com')
g.version = '6.8.21'
g.version = '6.8.27'
g.title = public.GetConfigValue('title')
g.uri = request.path
g.debug = os.path.exists('data/debug.pl')
@@ -98,9 +98,9 @@ class panelAdmin(panelSetup):
if request.method == 'GET':
g.menus = public.get_menus()
g.yaer = datetime.now().year
session["top_tips"] = public.GetMsg("TOP_TIPS")
session["bt_help"] = public.GetMsg("BT_HELP")
session["download"] = public.GetMsg("DOWNLOAD")
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:
session['brand'] = public.GetConfigValue('brand')
session['product'] = public.GetConfigValue('product')
@@ -114,7 +114,7 @@ class panelAdmin(panelSetup):
if not 'lan' in session:
session['lan'] = public.GetLanguage()
if not 'home' in session:
session['home'] = 'https://brandnew.aapanel.com'
session['home'] = 'https://www.aapanel.com'
return False
# 检查Web服务器类型
@@ -150,7 +150,7 @@ class panelAdmin(panelSetup):
if not 'login' in session:
api_check = self.get_sk()
if api_check:
#session.clear()
session.clear()
return api_check
g.api_request = True
else:
@@ -203,54 +203,61 @@ class panelAdmin(panelSetup):
def get_sk(self):
save_path = '/www/server/panel/config/api.json'
if not os.path.exists(save_path):
return redirect('/login')
return public.error_not_login('/login')
try:
api_config = json.loads(public.ReadFile(save_path))
except:
os.remove(save_path)
return redirect('/login')
return public.error_not_login('/login')
if not api_config['open']:
return redirect('/login')
return public.error_not_login('/login')
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 redirect('/login')
return public.error_not_login('/login')
num_key = client_ip + '_api'
if not public.get_error_num(num_key,20):
return public.returnJson(False,'AUTH_FAILED1')
return public.returnJson(False,'20 consecutive verification failures, prohibited for 1 hour')
if not 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.GetMsg("AUTH_FAILED1")+client_ip+']')
return public.returnJson(False,'%s[' % public.get_msg_gettext("20 consecutive verification failures, prohibited for 1 hour")+client_ip+']')
else:
num_key = client_ip + '_app'
if not public.get_error_num(num_key,20):
return public.returnJson(False,'AUTH_FAILED1')
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):
public.set_error_num(num_key)
return public.returnJson(False, 'illegal request')
if not os.path.exists(a_file):
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')
return public.returnJson(False,'Unbound device')
public.writeFile(a_file,'')
if not 'key' in api_config:
public.set_error_num(num_key)
return public.returnJson(False, 'KEY_ERR')
return public.returnJson(False, 'Key verification failed')
if not 'form_data' in get:
public.set_error_num(num_key)
return public.returnJson(False, 'FORM_DATA_ERR')
return public.returnJson(False, 'No form_data data found')
g.form_data = json.loads(public.aes_decrypt(get.form_data, api_config['key']))
get = get_input()
if not 'request_token' in get or not 'request_time' in get:
return redirect('/login')
return public.error_not_login('/login')
g.is_aes = True
g.aes_key = api_config['key']
request_token = public.md5(get.request_time + api_config['token'])
@@ -258,7 +265,7 @@ class panelAdmin(panelSetup):
public.set_error_num(num_key,True)
return False
public.set_error_num(num_key)
return public.returnJson(False,'SECRET_KEY_CHECK_FALSE')
return public.returnJson(False,'Secret key verification failed')
# 检查系统配置
+534 -260
View File
File diff suppressed because it is too large Load Diff
+51 -51
View File
@@ -33,27 +33,27 @@ class crontab:
tmp = {}
tmp=cront[i]
if cront[i]['type']=="day":
tmp['type']=public.getMsg('CRONTAB_TODAY')
tmp['cycle']= public.getMsg('CRONTAB_TODAY_CYCLE',(str(cront[i]['where_hour']),str(cront[i]['where_minute'])))
tmp['type']=public.get_msg_gettext('Per Day')
tmp['cycle']= public.get_msg_gettext('Per Day, run at {} Hour {} Min',(str(cront[i]['where_hour']),str(cront[i]['where_minute'])))
elif cront[i]['type']=="day-n":
tmp['type']=public.getMsg('CRONTAB_N_TODAY',(str(cront[i]['where1']),))
tmp['cycle']=public.getMsg('CRONTAB_N_TODAY_CYCLE',(str(cront[i]['where1']),str(cront[i]['where_hour']),str(cront[i]['where_minute'])))
tmp['type']=public.get_msg_gettext('Every {} Days',(str(cront[i]['where1']),))
tmp['cycle']=public.get_msg_gettext('Every {} Days, run at {} Hour {} Min',(str(cront[i]['where1']),str(cront[i]['where_hour']),str(cront[i]['where_minute'])))
elif cront[i]['type']=="hour":
tmp['type']=public.getMsg('CRONTAB_HOUR')
tmp['cycle']=public.getMsg('CRONTAB_HOUR_CYCLE',(str(cront[i]['where_minute']),))
tmp['type']=public.get_msg_gettext('Per Hour')
tmp['cycle']=public.get_msg_gettext('Per Hour, run at {} Min',(str(cront[i]['where_minute']),))
elif cront[i]['type']=="hour-n":
tmp['type']=public.getMsg('CRONTAB_N_HOUR',(str(cront[i]['where1']),))
tmp['cycle']=public.getMsg('CRONTAB_N_HOUR_CYCLE',(str(cront[i]['where1']),str(cront[i]['where_minute'])))
tmp['type']=public.get_msg_gettext('Every {} Hours',(str(cront[i]['where1']),))
tmp['cycle']=public.get_msg_gettext('Every {} Hours, run at {} Min',(str(cront[i]['where1']),str(cront[i]['where_minute'])))
elif cront[i]['type']=="minute-n":
tmp['type']=public.getMsg('CRONTAB_N_MINUTE',(str(cront[i]['where1']),))
tmp['cycle']=public.getMsg('CRONTAB_N_MINUTE_CYCLE',(str(cront[i]['where1']),))
tmp['type']=public.get_msg_gettext('Every {} Minutes',(str(cront[i]['where1']),))
tmp['cycle']=public.get_msg_gettext('Run Every {} Minutes',(str(cront[i]['where1']),))
elif cront[i]['type']=="week":
tmp['type']=public.getMsg('CRONTAB_WEEK')
tmp['type']=public.get_msg_gettext('Weekly')
if not cront[i]['where1']: cront[i]['where1'] = '0'
tmp['cycle']= public.getMsg('CRONTAB_WEEK_CYCLE',(self.toWeek(int(cront[i]['where1'])),str(cront[i]['where_hour']),str(cront[i]['where_minute'])))
tmp['cycle']= public.get_msg_gettext('Every {}, run at {} Hour {} Min',(self.toWeek(int(cront[i]['where1'])),str(cront[i]['where_hour']),str(cront[i]['where_minute'])))
elif cront[i]['type']=="month":
tmp['type']=public.getMsg('CRONTAB_MONTH')
tmp['cycle']=public.getMsg('CRONTAB_MONTH_CYCLE',(str(cront[i]['where1']),str(cront[i]['where_hour']),str(cront[i]['where_minute'])))
tmp['type']=public.get_msg_gettext('Monthly')
tmp['cycle']=public.get_msg_gettext('Monthly, run on {}Day {} Hour {}Min',(str(cront[i]['where1']),str(cront[i]['where_hour']),str(cront[i]['where_minute'])))
log_file = '/www/server/cron/{}.log'.format(tmp['echo'])
if os.path.exists(log_file):
@@ -80,13 +80,13 @@ class crontab:
#转换大写星期
def toWeek(self,num):
wheres={
0 : public.getMsg('CRONTAB_SUNDAY'),
1 : public.getMsg('CRONTAB_MONDAY'),
2 : public.getMsg('CRONTAB_TUESDAY'),
3 : public.getMsg('CRONTAB_WEDNESDAY'),
4 : public.getMsg('CRONTAB_THURSDAY'),
5 : public.getMsg('CRONTAB_FRIDAY'),
6 : public.getMsg('CRONTAB_SATURDAY')
0 : public.get_msg_gettext('Sunday'),
1 : public.get_msg_gettext('Monday'),
2 : public.get_msg_gettext('Tuesday'),
3 : public.get_msg_gettext('Wednesday'),
4 : public.get_msg_gettext('Thursday'),
5 : public.get_msg_gettext('Friday'),
6 : public.get_msg_gettext('Saturday')
}
try:
return wheres[num]
@@ -132,12 +132,12 @@ class crontab:
public.M('crontab').where('id=?',(id,)).setField('status',status)
public.WriteLog('TYPE_CRON',"MODIFY_CRON_STATUS",(cronInfo['name'],str(status_msg[status])))
return public.returnMsg(True,'SET_SUCCESS')
return public.return_msg_gettext(True,'Setup successfully!')
#修改计划任务
def modify_crond(self,get):
if len(get['name'])<1:
return public.returnMsg(False,'CRONTAB_TASKNAME_EMPTY')
return public.return_msg_gettext(False,'Name of task cannot be empty!')
id = get['id']
cuonConfig,get,name = self.GetCrondCycle(get)
cronInfo = public.M('crontab').where('id=?',(id,)).field(self.field).find()
@@ -167,7 +167,7 @@ class crontab:
self.remove_for_crond(cronInfo['echo'])
self.sync_to_crond(cronInfo)
public.WriteLog('TYPE_CRON',"MODIFY_CRON",(cronInfo['name']))
return public.returnMsg(True,'EDIT_SUCCESS')
return public.return_msg_gettext(True,'Setup successfully!')
#获取指定任务数据
@@ -196,7 +196,7 @@ class crontab:
#添加计划任务
def AddCrontab(self,get):
if len(get['name'])<1:
return public.returnMsg(False,'CRONTAB_TASKNAME_EMPTY')
return public.return_msg_gettext(False,'Name of task cannot be empty!')
cuonConfig,get,name = self.GetCrondCycle(get)
cronPath=public.GetConfigValue('setup_path')+'/cron'
cronName=self.GetShell(get)
@@ -208,22 +208,22 @@ class crontab:
self.CrondReload()
columns = 'name,type,where1,where_hour,where_minute,echo,addtime,\
status,save,backupTo,sType,sName,sBody,urladdress'
values = (public.xssencode(get['name']),get['type'],get['where1'],get['hour'],
values = (public.xssencode2(get['name']),get['type'],get['where1'],get['hour'],
get['minute'],cronName,time.strftime('%Y-%m-%d %X',time.localtime()),
1,get['save'],get['backupTo'],get['sType'],get['sName'],get['sBody'],
get['urladdress'])
if "save_local" in get:
columns += ",save_local,notice,notice_channel"
values = (public.xssencode(get['name']),get['type'],get['where1'],get['hour'],
values = (public.xssencode2(get['name']),get['type'],get['where1'],get['hour'],
get['minute'],cronName,time.strftime('%Y-%m-%d %X',time.localtime()),
1,get['save'],get['backupTo'],get['sType'],get['sName'],get['sBody'],
get['urladdress'], get["save_local"], get['notice'], get['notice_channel'])
addData=public.M('crontab').add(columns,values)
if addData>0:
result = public.returnMsg(True,'ADD_SUCCESS')
result = public.return_msg_gettext(True,'Setup successfully!')
result['id'] = addData
return result
return public.returnMsg(False,'ADD_ERROR')
return public.return_msg_gettext(False,'Failed to add')
#构造周期
def GetCrondCycle(self,params):
@@ -231,16 +231,16 @@ class crontab:
name = ""
if params['type']=="day":
cuonConfig = self.GetDay(params)
name = public.getMsg('CRONTAB_TODAY')
name = public.get_msg_gettext('Per Day')
elif params['type']=="day-n":
cuonConfig = self.GetDay_N(params)
name = public.getMsg('CRONTAB_N_TODAY',(params['where1'],))
name = public.get_msg_gettext('Every {0} Days',(params['where1'],))
elif params['type']=="hour":
cuonConfig = self.GetHour(params)
name = public.getMsg('CRONTAB_HOUR')
name = public.get_msg_gettext('Per Hour')
elif params['type']=="hour-n":
cuonConfig = self.GetHour_N(params)
name = public.getMsg('CRONTAB_HOUR')
name = public.get_msg_gettext('Per Hour')
elif params['type']=="minute-n":
cuonConfig = self.Minute_N(params)
elif params['type']=="week":
@@ -252,36 +252,36 @@ class crontab:
#取任务构造Day
def GetDay(self,param):
cuonConfig ="{0} {1} * * * ".format(param['minute'],param['hour'])
cuonConfig ="{} {} * * * ".format(param['minute'],param['hour'])
return cuonConfig
#取任务构造Day_n
def GetDay_N(self,param):
cuonConfig ="{0} {1} */{2} * * ".format(param['minute'],param['hour'],param['where1'])
cuonConfig ="{} {} */{} * * ".format(param['minute'],param['hour'],param['where1'])
return cuonConfig
#取任务构造Hour
def GetHour(self,param):
cuonConfig ="{0} * * * * ".format(param['minute'])
cuonConfig ="{} * * * * ".format(param['minute'])
return cuonConfig
#取任务构造Hour-N
def GetHour_N(self,param):
cuonConfig ="{0} */{1} * * * ".format(param['minute'],param['where1'])
cuonConfig ="{} */{} * * * ".format(param['minute'],param['where1'])
return cuonConfig
#取任务构造Minute-N
def Minute_N(self,param):
cuonConfig ="*/{0} * * * * ".format(param['where1'])
cuonConfig ="*/{} * * * * ".format(param['where1'])
return cuonConfig
#取任务构造week
def Week(self,param):
cuonConfig ="{0} {1} * * {2}".format(param['minute'],param['hour'],param['week'])
cuonConfig ="{} {} * * {}".format(param['minute'],param['hour'],param['week'])
return cuonConfig
#取任务构造Month
def Month(self,param):
cuonConfig = "{0} {1} {2} * * ".format(param['minute'],param['hour'],param['where1'])
cuonConfig = "{} {} {} * * ".format(param['minute'],param['hour'],param['where1'])
return cuonConfig
#取数据列表
@@ -308,9 +308,9 @@ class crontab:
id = get['id']
echo = public.M('crontab').where("id=?",(id,)).field('echo').find()
logFile = public.GetConfigValue('setup_path')+'/cron/'+echo['echo']+'.log'
if not os.path.exists(logFile):return public.returnMsg(False, 'CRONTAB_TASKLOG_EMPTY')
if not os.path.exists(logFile):return public.return_msg_gettext(False, 'log is empty')
log = public.GetNumLines(logFile,2000)
return public.returnMsg(True, log)
return public.return_msg_gettext(True, log)
#清理任务日志
def DelLogs(self,get):
@@ -319,16 +319,16 @@ class crontab:
echo = public.M('crontab').where("id=?",(id,)).getField('echo')
logFile = public.GetConfigValue('setup_path')+'/cron/'+echo+'.log'
os.remove(logFile)
return public.returnMsg(True, 'CRONTAB_TASKLOG_CLOSE')
return public.return_msg_gettext(True, 'Logs emptied')
except:
return public.returnMsg(False, 'CRONTAB_TASKLOG_CLOSE_ERR')
return public.return_msg_gettext(False, 'Failed to empty task logs!')
#删除计划任务
def DelCrontab(self,get):
try:
id = get['id']
find = public.M('crontab').where("id=?",(id,)).field('name,echo').find()
if not self.remove_for_crond(find['echo']): return public.returnMsg(False,'SYSSAFE_CANT_WRITE_FILE')
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']
if os.path.exists(sfile): os.remove(sfile)
@@ -337,9 +337,9 @@ class crontab:
public.M('crontab').where("id=?",(id,)).delete()
public.WriteLog('TYPE_CRON', 'CRONTAB_DEL',(find['name'],))
return public.returnMsg(True, 'DEL_SUCCESS')
return public.return_msg_gettext(True, 'Successfully deleted')
except:
return public.returnMsg(False, 'DEL_ERROR')
return public.return_msg_gettext(False, 'Failed to delete')
#从crond删除
def remove_for_crond(self,echo):
@@ -419,7 +419,7 @@ echo "--------------------------------------------------------------------------
public.ExecShell('chmod 750 ' + file)
return cronName
#except Exception as ex:
#return public.returnMsg(False, 'FILE_WRITE_ERR' + str(ex))
#return public.return_msg_gettext(False, 'Failed to write in file!' + str(ex))
#检查脚本
def CheckScript(self,shell):
@@ -443,7 +443,7 @@ echo "--------------------------------------------------------------------------
file = self.get_cron_file()
if not os.path.exists(file): public.writeFile(file,'')
conf = public.readFile(file)
if type(conf)==bool:return public.returnMsg(False,'Failed to read file!')
if type(conf)==bool:return public.return_msg_gettext(False,'Failed to read file!')
conf += config + "\n"
if public.writeFile(file,conf):
if not os.path.exists(u_file):
@@ -451,7 +451,7 @@ echo "--------------------------------------------------------------------------
else:
public.ExecShell("chmod 600 '" + file + "' && chown root.crontab " + file)
return True
return public.returnMsg(False,'SYSSAFE_CANT_WRITE_FILE')
return public.return_msg_gettext(False,'Unable to write to file, please check if system hardening is enabled!')
#立即执行任务
def StartTask(self,get):
@@ -459,7 +459,7 @@ echo "--------------------------------------------------------------------------
execstr = public.GetConfigValue('setup_path') + '/cron/' + echo
public.ExecShell('chmod +x ' + execstr)
public.ExecShell('nohup ' + execstr + ' >> ' + execstr + '.log 2>&1 &')
return public.returnMsg(True,'CRONTAB_TASK_EXEC')
return public.return_msg_gettext(True,'Task has been executed!')
#获取计划任务文件位置
def get_cron_file(self):
+151 -59
View File
@@ -25,10 +25,10 @@ class data:
'''
def setPs(self,get):
id = get.id
get.ps = public.xssencode(get.ps)
get.ps = public.xssencode2(get.ps)
if public.M(get.table).where("id=?",(id,)).setField('ps',get.ps):
return public.returnMsg(True,'EDIT_SUCCESS')
return public.returnMsg(False,'EDIT_ERROR')
return public.return_msg_gettext(True,'Setup successfully!')
return public.return_msg_gettext(False,'Failed to modify')
#端口扫描
def CheckPort(self,port):
@@ -142,7 +142,7 @@ class data:
conf = public.readFile(
self.setupPath + '/panel/vhost/' + self.web_server + '/detail/' + siteName + '.conf')
if self.web_server == 'nginx':
rep = r"enable-php-(\w{2,5})\.conf"
rep = r"enable-php-(\w{2,5})[-\w]*\.conf"
elif self.web_server == 'apache':
rep = r"php-cgi-(\w{2,5})\.sock"
else:
@@ -172,6 +172,37 @@ class data:
except:
return 0
def get_site_quota(self,path):
'''
@name 获取网站目录配额信息
@author hwliang<2022-02-15>
@param path<string> 网站目录
@return dict
'''
res = {'size':0 ,'used':0 }
try:
from projectModel.quotaModel import main
quota_info = main().get_quota_path_list(get_path = path)
if isinstance(quota_info,dict):
return quota_info
return res
except: return res
def get_database_quota(self,db_name):
'''
@name 获取网站目录配额信息
@author hwliang<2022-02-15>
@param path<string> 网站目录
@return dict
'''
res = {'size':0 ,'used':0 }
try:
from projectModel.quotaModel import main
quota_info = main().get_quota_mysql_list(get_name = db_name)
if isinstance(quota_info,dict):
return quota_info
return res
except: return res
'''
* 取数据列表
@@ -181,6 +212,7 @@ class data:
* @return Json page.分页数 , count.总行数 data.取回的数据
'''
def getData(self,get):
import one_key_wp
try:
table = get.table
data = self.GetSql(get)
@@ -188,29 +220,55 @@ class data:
if table == 'backup':
import os
backup_path = public.M('config').where('id=?',(1,)).getField('backup_path')
for i in range(len(data['data'])):
if data['data'][i]['size'] == 0:
if os.path.exists(data['data'][i]['filename']): data['data'][i]['size'] = os.path.getsize(data['data'][i]['filename'])
if os.path.exists(data['data'][i]['filename']):
data['data'][i]['size'] = os.path.getsize(data['data'][i]['filename'])
else:
if not os.path.exists(data['data'][i]['filename']):
if (data['data'][i]['filename'].find('/www/') != -1 or data['data'][i]['filename'].find(backup_path) != -1) and data['data'][i]['filename'][0] == '/' and data['data'][i]['filename'].find('|') == -1:
data['data'][i]['size'] = 0
data['data'][i]['ps'] = public.get_msg_gettext("File does not exist!")
elif table == 'sites' or table == 'databases':
type = '0'
if table == 'databases': type = '1'
for i in range(len(data['data'])):
data['data'][i]['backup_count'] = SQL.table('backup').where("pid=? AND type=?",(data['data'][i]['id'],type)).count()
if table == 'databases': data['data'][i]['conn_config'] = json.loads(data['data'][i]['conn_config'])
data['data'][i]['quota'] = self.get_database_quota(data['data'][i]['name'])
if table == 'sites':
for i in range(len(data['data'])):
data['data'][i]['domain'] = SQL.table('domain').where("pid=?",(data['data'][i]['id'],)).count()
data['data'][i]['ssl'] = self.get_site_ssl_info(data['data'][i]['name'])
data['data'][i]['php_version'] = self.get_php_version(data['data'][i]['name'])
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':
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'
data['data'][i]['quota'] = self.get_site_quota(data['data'][i]['path'])
elif table == 'firewall':
for i in range(len(data['data'])):
if data['data'][i]['port'].find(':') != -1 or data['data'][i]['port'].find('.') != -1 or data['data'][i]['port'].find('-') != -1:
data['data'][i]['status'] = -1
else:
data['data'][i]['status'] = self.CheckPort(int(data['data'][i]['port']))
elif table == 'ftps':
for i in range(len(data['data'])):
data['data'][i]['quota'] = self.get_site_quota(data['data'][i]['path'])
try:
for _find in data['data']:
_keys = _find.keys()
for _key in _keys:
_find[_key] = public.xsssec(_find[_key])
except:
pass
#返回
return data
except:
@@ -229,15 +287,21 @@ class data:
SQL = public.M(tableName)
where = "id=?"
find = SQL.where(where,(id,)).field(field).find()
try:
_keys = find.keys()
for _key in _keys:
find[_key] = public.xsssec(find[_key])
except:
pass
return find
'''
* 取字段值
* @param String _GET['tab'] 数据库表名
* @param String _GET['key'] 字段
* @param String _GET['id'] 条件ID
* @return String
* @return String
'''
def getKey(self,get):
tableName = get.table
@@ -246,7 +310,7 @@ class data:
SQL = db.Sql().table(tableName)
where = "id=?"
retuls = SQL.where(where,(id,)).getField(keyName)
return retuls
return public.xsssec(retuls)
'''
* 获取数据与分页
@@ -259,117 +323,138 @@ class data:
def GetSql(self,get,result = '1,2,3,4,5,8'):
#判断前端是否传入参数
order = "id desc"
if hasattr(get,'order'):
order = get.order
if hasattr(get,'order'):
# 验证参数格式
if re.match(r"^[\w\s\-\.]+$",get.order):
order = get.order
limit = 20
if hasattr(get,'limit'):
if hasattr(get,'limit'):
limit = int(get.limit)
if hasattr(get,'result'):
result = get.result
if limit < 1: limit = 20
if hasattr(get,'result'):
# 验证参数格式
if re.match(r"^[\d\,]+$",get.result):
result = get.result
SQL = db.Sql()
data = {}
#取查询条件
where = ''
param = ()
if hasattr(get,'search'):
if sys.version_info[0] == 2: get.search = get.search.encode('utf-8')
where = self.GetWhere(get.table,get.search)
where,param = self.GetWhere(get.table,get.search)
if get.table == 'backup':
where += " and type='" + get.type+"'"
where += " and type='{}'".format(int(get.type))
if get.table == 'sites' and get.search:
pid = SQL.table('domain').where("name LIKE '%"+get.search+"%'",()).getField('pid')
pid = SQL.table('domain').where("name LIKE ?",("%{}%".format(get.search),)).getField('pid')
if pid:
if where:
where += " or id=" + str(pid)
else:
where += "id=" + str(pid)
if get.table == 'sites' and hasattr(get,'type'):
if get.type != '-1':
type_where = "type_id=%s" % get.type
if where == '':
where = type_where
else:
where += " and " + type_where
if get.table == 'sites':
if where:
where = "({}) AND project_type='PHP'".format(where)
else:
where = "project_type='PHP'"
where = "(project_type='PHP' OR project_type='WP')"
if hasattr(get,'type'):
if get.type != '-1':
where += " AND type_id={}".format(int(get.type))
if get.table == 'databases':
if hasattr(get,'db_type'):
if where:
where += " AND db_type='{}'".format(int(get.db_type))
else:
where = "db_type='{}'".format(int(get.db_type))
if hasattr(get,'sid'):
if where:
where += " AND sid='{}'".format(int(get.sid))
else:
where = "sid='{}'".format(int(get.sid))
field = self.GetField(get.table)
#实例化数据库对象
#是否直接返回所有列表
if hasattr(get,'list'):
data = SQL.table(get.table).where(where,()).field(field).order(order).select()
data = SQL.table(get.table).where(where,param).field(field).order(order).select()
return data
#取总行数
count = SQL.table(get.table).where(where,()).count()
count = SQL.table(get.table).where(where,param).count()
#get.uri = get
#包含分页类
import page
#实例化分页类
page = page.Page()
info = {}
info['count'] = count
info['row'] = limit
info['p'] = 1
if hasattr(get,'p'):
info['p'] = int(get['p'])
info['uri'] = get
if info['p'] <1: info['p'] = 1
try:
from flask import request
info['uri'] = public.url_encode(request.full_path)
except:
info['uri'] = ''
info['return_js'] = ''
if hasattr(get,'tojs'):
info['return_js'] = get.tojs
if re.match(r"^[\w\.\-]+$",get.tojs):
info['return_js'] = get.tojs
data['where'] = where
#获取分页数据
data['page'] = page.GetPage(info,result)
#取出数据
data['data'] = SQL.table(get.table).where(where,()).order(order).field(field).limit(str(page.SHIFT)+','+str(page.ROW)).select()
data['data'] = SQL.table(get.table).where(where,param).order(order).field(field).limit(str(page.SHIFT)+','+str(page.ROW)).select()
return data
#获取条件
def GetWhere(self,tableName,search):
if not search: return ""
def GetWhere(self,tableName,search):
if not search: return "",()
if type(search) == bytes: search = search.encode('utf-8').strip()
try:
search = re.search(r"[\w\x80-\xff\.]+",search).group()
search = re.search(r"[\w\x80-\xff\.\_\-]+",search).group()
except:
return ''
return '',()
wheres = {
'sites' : "id='"+search+"' or name like '%"+search+"%' or status like '%"+search+"%' or ps like '%"+search+"%'",
'ftps' : "id='"+search+"' or name like '%"+search+"%' or ps like '%"+search+"%'",
'databases' : "id='"+search+"' or name like '%"+search+"%' or ps like '%"+search+"%'",
'logs' : "uid='"+search+"' or username='"+search+"' or type like '%"+search+"%' or log like '%"+search+"%' or addtime like '%"+search+"%'",
'backup' : "pid="+search+"",
'users' : "id='"+search+"' or username='"+search+"'",
'domain' : "pid='"+search+"' or name='"+search+"'",
'tasks' : "status='"+search+"' or type='"+search+"'"
'sites' : ("name LIKE ? OR ps LIKE ?",('%'+search+'%','%'+search+'%')),
'ftps' : ("name LIKE ? OR ps LIKE ?",('%'+search+'%','%'+search+'%')),
'databases' : ("(name LIKE ? OR ps LIKE ?)",("%"+search+"%","%"+search+"%")),
'logs' : ("username=? OR type LIKE ? OR log LIKE ?",(search,'%'+search+'%','%'+search+'%')),
'backup' : ("pid=?",(search,)),
'users' : ("id='?' OR username=?",(search,search)),
'domain' : ("pid=? OR name=?",(search,search)),
'tasks' : ("status=? OR type=?",(search,search)),
}
try:
return wheres[tableName]
except:
return ''
return '',()
# 获取返回的字段
def GetField(self,tableName):
fields = {
'sites' : "id,name,path,status,ps,addtime,edate",
'ftps' : "id,pid,name,password,status,ps,addtime,path",
'databases' : "id,pid,name,username,password,accept,ps,addtime",
'databases' : "id,sid,pid,name,username,password,accept,ps,addtime,db_type,conn_config",
'logs' : "id,uid,username,type,log,addtime",
'backup' : "id,pid,name,filename,addtime,size",
'backup' : "id,pid,name,filename,addtime,size,ps",
'users' : "id,username,phone,email,login_ip,login_time",
'firewall' : "id,port,ps,addtime",
'domain' : "id,pid,name,port,addtime",
@@ -379,3 +464,10 @@ class data:
return fields[tableName]
except:
return ''
def get_analysis(self,get,i):
import log_analysis
get.path = '/www/wwwlogs/{}.log'.format(i['name'])
get.action = 'get_result'
data = log_analysis.log_analysis().get_result(get)
return int(data['php']) + int(data['san']) + int(data['sql']) + int(data['xss'])
+630 -287
View File
File diff suppressed because it is too large Load Diff
+10 -8
View File
@@ -25,17 +25,17 @@ class datatools:
for d in ds:
if size < 1024: return ('%.2f' % size) + d
size = size / 1024
return '0b';
return '0b'
# 获取当前数据库信息
def GetdataInfo(self,get):
'''
传递一个数据库名称即可 get.databases
'''
if not self.DB_MySQL:self.DB_MySQL = panelMysql.panelMysql()
db_name=get.db_name
db_name=get.db_name
if not db_name:return False
if not self.DB_MySQL:self.DB_MySQL = public.get_mysql_obj(db_name)
ret = {}
tables = self.map_to_list(self.DB_MySQL.query('show tables from `%s`' % db_name))
if type(tables) == list:
@@ -50,7 +50,7 @@ class datatools:
ret3 = []
for i in tables:
if i == 1049: return public.returnMsg(False,'DB_NOT_EXIST')
if i == 1049: return public.return_msg_gettext(False,'Database does NOT exist!')
if type(i) == int: continue
table = self.map_to_list(self.DB_MySQL.query("show table status from `%s` where name = '%s'" % (db_name, i[0])))
if not table: continue
@@ -80,7 +80,9 @@ class datatools:
db_name = get.db_name
tables = json.loads(get.tables)
if not db_name or not tables: return False
if not self.DB_MySQL:self.DB_MySQL = panelMysql.panelMysql()
if not self.DB_MySQL:self.DB_MySQL = public.get_mysql_obj(db_name)
m_version = self.DB_MySQL.query('select version();')[0][0]
if m_version.find('5.1.')!=-1:return public.return_msg_gettext(False,"Nonsupport mysql5.1!")
mysql_table = self.map_to_list(self.DB_MySQL.query('show tables from `%s`' % db_name))
ret=[]
if type(mysql_table)==list:
@@ -112,10 +114,11 @@ class datatools:
db_name=web
tables=['web1','web2']
'''
if not self.DB_MySQL:self.DB_MySQL = panelMysql.panelMysql()
db_name = get.db_name
tables = json.loads(get.tables)
if not db_name or not tables: return False
if not self.DB_MySQL:self.DB_MySQL = public.get_mysql_obj(db_name)
mysql_table = self.map_to_list(self.DB_MySQL.query('show tables from `%s`' % db_name))
ret=[]
if type(mysql_table) == list:
@@ -138,13 +141,12 @@ class datatools:
table_type=innodb
tables=['web1','web2']
'''
if not self.DB_MySQL:self.DB_MySQL = panelMysql.panelMysql()
db_name = get.db_name
table_type = get.table_type
tables = json.loads(get.tables)
if not db_name or not tables: return False
if not self.DB_MySQL:self.DB_MySQL = public.get_mysql_obj(db_name)
mysql_table = self.map_to_list(self.DB_MySQL.query('show tables from `%s`' % db_name))
ret=[]
if type(mysql_table)==list:
+15 -12
View File
@@ -304,23 +304,26 @@ class Sql():
#是否有锁
def is_lock(self):
n = 0
while os.path.exists(self.__LOCK):
n+=1
if n > 100:
self.rm_lock()
break
time.sleep(0.01)
return
# n = 0
# while os.path.exists(self.__LOCK):
# n+=1
# if n > 100:
# self.rm_lock()
# break
# time.sleep(0.01)
#写锁
def write_lock(self):
self.is_lock()
with open(self.__LOCK,'wb+') as f:
f.close()
return
# self.is_lock()
# with open(self.__LOCK,'wb+') as f:
# f.close()
#解锁
def rm_lock(self):
if os.path.exists(self.__LOCK):
os.remove(self.__LOCK)
return
# if os.path.exists(self.__LOCK):
# os.remove(self.__LOCK)
def query(self,sql,param = ()):
#执行SQL语句返回数据集
+54 -48
View File
@@ -6,73 +6,74 @@
# +-------------------------------------------------------------------
# | Author: hwliang <hwl@bt.cn>
# +-------------------------------------------------------------------
import re, os, sys, public, json
import re,os,sys,public,json
import pymysql
class mysql:
__DB_PASS = ''
__DB_USER = ''
__DB_NAME = ''
class panelMysql:
__DB_PASS = None
__DB_USER = 'root'
__DB_NAME = None
__DB_PORT = 3306
__DB_HOST = 'localhost'
__DB_PREFIX = ''
__DB_CONN = None
__DB_CUR = None
__DB_ERR = None
__DB_NET = None
__DB_TABLE = "" # 被操作的表名称
__OPT_WHERE = "" # where条件
__OPT_LIMIT = "" # limit条件
__OPT_ORDER = "" # order条件
__OPT_FIELD = "*" # field条件
__OPT_PARAM = () # where值
__DB_CUR = None
__DB_ERR = None
__DB_TABLE = "" # 被操作的表名称
__OPT_WHERE = "" # where条件
__OPT_LIMIT = "" # limit条件
__OPT_ORDER = "" # order条件
__OPT_FIELD = "*" # field条件
__OPT_PARAM = () # where值
_USER = None
def __init__(self):
pass
def set_name(self, name):
self.__DB_NAME = name
def set_name(self,name):
self.__DB_NAME = str(name)
return self
def set_host(self, host, port, name, username, password, prefix=''):
self.__DB_HOST = host
self.__DB_PORT = port
self.__DB_NAME = name
self.__DB_USER = username
self.__DB_PASS = password
def set_prefix(self,prefix):
self.__DB_PREFIX = prefix
return self
def set_host(self,host,port,name,username,password,prefix = ''):
self.__DB_HOST = host
self.__DB_PORT = int(port)
self.__DB_NAME = name
if self.__DB_NAME: self.__DB_NAME = str(self.__DB_NAME)
self.__DB_USER = str(username)
self._USER = str(username)
self.__DB_PASS = str(password)
self.__DB_PREFIX = prefix
self.__GetConn()
return self
#连接MYSQL数据库
def __GetConn(self):
if self.__DB_NET: return True
try:
self.__DB_CONN = pymysql.connect(host=self.__DB_HOST,
port=self.__DB_PORT,
user=self.__DB_USER,
passwd=self.__DB_PASS)
self.__DB_CONN = pymysql.connect(host=self.__DB_HOST,user=self.__DB_USER,passwd=str(self.__DB_PASS),db=self.__DB_NAME,port=self.__DB_PORT,connect_timeout=15,read_timeout=60,write_timeout=60)
except:
self.__DB_CONN = pymysql.connect(host=self.__DB_HOST,user=self.__DB_USER,passwd=str(self.__DB_PASS),db=self.__DB_NAME,port=self.__DB_PORT)
self.__DB_CUR = self.__DB_CONN.cursor()
return True
self.__DB_CUR = self.__DB_CONN.cursor()
self.__DB_NET = True
return True
except pymysql.Error as e:
self.__DB_ERR = e
return False
def table(self, table):
def table(self,table):
#设置表名
self.__DB_TABLE = self.__DB_PREFIX + table
return self
def where(self, where, param):
def where(self,where,param):
#WHERE条件
if where:
self.__OPT_WHERE = " WHERE " + where
self.__OPT_PARAM = self.__to_tuple(param)
return self
def __to_tuple(self, param):
def __to_tuple(self,param):
#将参数转换为tuple
if type(param) != tuple:
if type(param) == list:
@@ -103,6 +104,7 @@ class mysql:
def select(self):
#查询数据集
self.__GetConn()
if not self.__DB_CUR: return self.__DB_ERR
try:
self.__get_columns()
sql = "SELECT " + self.__OPT_FIELD + " FROM " + self.__DB_TABLE + self.__OPT_WHERE + self.__OPT_ORDER + self.__OPT_LIMIT
@@ -119,18 +121,18 @@ class mysql:
tmp1[key.strip('`')] = row[i]
i += 1
tmp.append(tmp1)
del (tmp1)
del(tmp1)
data = tmp
del (tmp)
del(tmp)
else:
#将元组转换成列表
tmp = list(map(list, data))
data = tmp
del (tmp)
del(tmp)
self.__close()
return data
except Exception as ex:
return public.get_error_info()
return "error: " + str(ex)
def get(self):
self.__get_columns()
@@ -291,30 +293,34 @@ class mysql:
except Exception as ex:
return "error: " + str(ex)
def execute(self, sql, is_close=True):
def execute(self,sql,param = ()):
#执行SQL语句返回受影响行
if not self.__GetConn(): return self.__DB_ERR
try:
result = self.__DB_CUR.execute(sql)
self.__OPT_PARAM = list(self.__to_tuple(param))
result = self.__DB_CUR.execute(sql,self.__OPT_PARAM)
self.__DB_CONN.commit()
if is_close: self.__close()
self.__close()
return result
except Exception as ex:
return ex
def query(self, sql, is_close=True):
def query(self,sql,is_close=True,param=()):
#执行SQL语句返回数据集
if not self.__GetConn(): return self.__DB_ERR
try:
self.__DB_CUR.execute(sql)
self.__OPT_PARAM = list(self.__to_tuple(param))
self.__DB_CUR.execute(sql,self.__OPT_PARAM)
result = self.__DB_CUR.fetchall()
#将元组转换成列表
data = list(map(list, result))
data = list(map(list,result))
if is_close: self.__Close()
return data
except Exception as ex:
return ex
#关闭连接
def __Close(self):
self.__DB_CUR.close()
+12 -10
View File
@@ -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)
reg = '#BEGIN_DENY_{}\n\s*location\s*\~\*\s*\^(.*)\.\*.*\((.*)\)\$'.format(i.replace("|","\|"))
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})
@@ -71,7 +71,7 @@ class FileExecuteDeny:
deny_name.append(tmp[-1])
result = []
for i in deny_name:
reg = '#BEGIN_DENY_{}\n\s*<Directory\s*\~\s*"(.*)\.\*.*\((.*)\)\$'.format(i)
reg = '#BEGIN_DENY_{}\n\s*<Directory\s*\~\s*"(.*)\.\*.*\((.*)\)\$'.format(i.replace("|","\|"))
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})
@@ -91,7 +91,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)
reg = '#BEGIN_DENY_{}\n\s*rules\s*RewriteRule\s*\^(.*)\.\*.*\((.*)\)\$'.format(i.replace("|","\|"))
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})
@@ -116,6 +116,8 @@ class FileExecuteDeny:
dir = args.dir
suffix = args.suffix
website = args.website
if suffix[-1] == "|":
suffix = suffix[:-1]
self._init_conf(website)
conf = public.readFile(self.ng_website_conf)
if not conf:
@@ -124,16 +126,16 @@ class FileExecuteDeny:
exist_deny_name = [i.split('_')[-1] for i in data]
if args.act == 'edit':
if deny_name not in exist_deny_name:
return public.returnMsg(False, 'The specify rule name is not exists! [ {} ]'.format(deny_name))
return public.return_msg_gettext(False, 'The specify rule name is not exists! [ {} ]'.format(deny_name))
self.del_file_deny(args)
else:
if deny_name in exist_deny_name:
return public.returnMsg(False,'The specify rule name is already exists! [ {} ]'.format(deny_name))
return public.return_msg_gettext(False,'The specify rule name is already exists! [ {} ]'.format(deny_name))
self._set_nginx_file_deny(deny_name,dir,suffix)
self._set_apache_file_deny(deny_name,dir,suffix)
self._set_ols_file_deny(deny_name,dir,suffix)
public.serviceReload()
return public.returnMsg(True,'Add Successfully')
return public.returnMsg(True,'Setup successfully!')
def _set_nginx_file_deny(self,name,dir=None,suffix=None):
conf = public.readFile(self.ng_website_conf)
@@ -216,16 +218,16 @@ class FileExecuteDeny:
self._set_apache_file_deny(deny_name)
self._set_ols_file_deny(deny_name)
public.serviceReload()
return public.returnMsg(True,'Delete Successfully')
return public.returnMsg(True,'Successfully deleted!')
# 检查传入参数
def _check_args(self,args):
if hasattr(args,'deny_name'):
if len(args.deny_name) < 3:
return public.returnMsg(False, 'Rule name needs to be greater than 3 bytes')
return public.return_msg_gettext(False, 'Rule name needs to be greater than 3 bytes')
if hasattr(args,'suffix'):
if not args.suffix:
return public.returnMsg(False, 'File suffix cannot be empty')
return public.return_msg_gettext(False, 'File suffix cannot be empty')
if hasattr(args,'dir'):
if not args.dir:
return public.returnMsg(False, 'Directory cannot be empty')
return public.return_msg_gettext(False, 'Directory cannot be empty')
+609 -333
View File
File diff suppressed because it is too large Load Diff
+43 -43
View File
@@ -139,9 +139,9 @@ class firewalls:
import time
import re
rep = "^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(\/\d{1,2})?$"
if not re.search(rep,get.port): return public.returnMsg(False,'FIREWALL_IP_FORMAT');
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.returnMsg(False,'FIREWALL_IP_EXISTS')
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!')
if self.__isUfw:
public.ExecShell('ufw deny from ' + address + ' to any');
else:
@@ -154,11 +154,11 @@ class firewalls:
else:
public.ExecShell('iptables -I INPUT -s '+address+' -j DROP')
public.WriteLog("TYPE_FIREWALL", 'FIREWALL_DROP_IP',(address,))
public.write_log_gettext("Firewall manager", 'Successfully blocked IP [{}]!',(address,))
addtime = time.strftime('%Y-%m-%d %X',time.localtime())
public.M('firewall').add('port,ps,addtime',(address,get.ps,addtime))
self.FirewallReload()
return public.returnMsg(True,'ADD_SUCCESS')
return public.return_msg_gettext(True,'Successfully added')
@@ -178,11 +178,11 @@ class firewalls:
else:
public.ExecShell('iptables -D INPUT -s '+address+' -j DROP')
public.WriteLog("TYPE_FIREWALL",'FIREWALL_ACCEPT_IP',(address,))
public.write_log_gettext("Firewall manager",'Unblocked IP [{}]!',(address,))
public.M('firewall').where("id=?",(id,)).delete()
self.FirewallReload();
return public.returnMsg(True,'DEL_SUCCESS')
return public.return_msg_gettext(True,'Successfully deleted')
#添加放行端口
@@ -190,28 +190,28 @@ class firewalls:
flag=False
import re
rep = "^\d{1,5}(:\d{1,5})?$"
if not re.search(rep,get.port): return public.returnMsg(False,'PORT_CHECK_RANGE');
if not re.search(rep,get.port): return public.return_msg_gettext(False,'Port range is incorrect!');
import time
port = get.port
ps = get.ps
types=get.type
type_list=['tcp','udp']
if types not in type_list:return public.returnMsg(False, 'FIREWALL_PORT_EXISTS')
notudps = ['80', '443', '8888', '888', '39000:40000', '21', '22', '7800']
if types not in type_list:return public.return_msg_gettext(False, 'The port exists, no need to repeat the release!')
notudps = ['80', '443', '8888', '888', '39000:40000', '21', '22']
if port in notudps:flag=True
#return public.M('firewall').where("port=?", (port,)).count()
if types=='tcp':
if flag:
if public.M('firewall').where("port=?", (port,)).count() > 0: return public.returnMsg(False, 'FIREWALL_PORT_EXISTS')
if public.M('firewall').where("port=?", (port,)).count() > 0: return public.return_msg_gettext(False, 'The port exists, no need to repeat the release!')
else:
if public.M('firewall').where("port=? and type='tcp'",(port,)).count() > 0: return public.returnMsg(False,'FIREWALL_PORT_EXISTS')
if public.M('firewall').where("port=? and type='tcp'",(port,)).count() > 0: return public.return_msg_gettext(False,'The port exists, no need to repeat the release!')
elif types=='udp':
if flag:
if public.M('firewall').where("port=?", (port,)).count() > 0: return public.returnMsg( False, 'FIREWALL_PORT_EXISTS')
if public.M('firewall').where("port=?", (port,)).count() > 0: return public.return_msg_gettext( False, 'The port exists, no need to repeat the release!')
else:
if public.M('firewall').where("port=? and type='udp'", (port,)).count() > 0: return public.returnMsg(False,'FIREWALL_PORT_EXISTS')
if public.M('firewall').where("port=? and type='udp'", (port,)).count() > 0: return public.return_msg_gettext(False,'The port exists, no need to repeat the release!')
else:
return public.returnMsg(False, 'FIREWALL_PORT_EXISTS')
return public.return_msg_gettext(False, 'The port exists, no need to repeat the release!')
if self.__isUfw:
if port in notudps:
@@ -231,12 +231,12 @@ class firewalls:
else:
public.ExecShell('iptables -I INPUT -p tcp -m state --state NEW -m ' + types +' --dport ' + port + ' -j ACCEPT' )
public.WriteLog("TYPE_FIREWALL", 'FIREWALL_ACCEPT_PORT',(port,))
public.write_log_gettext("Firewall manager", 'Successfully accepted port [{}]!',(port,))
addtime = time.strftime('%Y-%m-%d %X',time.localtime())
result = public.M('firewall').add('port,ps,addtime,types',(port,ps,addtime,types))
#return result
self.FirewallReload()
return public.returnMsg(True,'ADD_SUCCESS')
return public.return_msg_gettext(True,'Setup successfully!')
#删除放行端口
@@ -245,9 +245,9 @@ class firewalls:
id = get.id
types=get.type
type_list = ['tcp', 'udp']
if not types in type_list: return public.returnMsg(False, 'FIREWALL_PORT_EXISTS')
if not types in type_list: return public.return_msg_gettext(False, 'The port exists, no need to repeat the release!')
try:
if(port == public.GetHost(True)): return public.returnMsg(False,'FIREWALL_PORT_PANEL')
if(port == public.GetHost(True)): return public.return_msg_gettext(False,'Failedcannot delete current port of the panel!')
if self.__isUfw:
public.ExecShell('ufw delete allow ' + port + '/' + types+ '');
else:
@@ -255,13 +255,13 @@ class firewalls:
public.ExecShell('firewall-cmd --permanent --zone=public --remove-port='+port+'/' + types + '')
else:
public.ExecShell('iptables -D INPUT -p tcp -m state --state NEW -m ' + types +' --dport '+port+' -j ACCEPT')
public.WriteLog("TYPE_FIREWALL", 'FIREWALL_DROP_PORT',(port,))
public.write_log_gettext("Firewall manager", 'Successfully deleted accepted port [{}] on firewall!',(port,))
public.M('firewall').where("id=?",(id,)).delete()
self.FirewallReload()
return public.returnMsg(True,'DEL_SUCCESS')
return public.return_msg_gettext(True,'Successfully deleted')
except:
return public.returnMsg(False,'DEL_ERROR')
return public.return_msg_gettext(False,'Failed to delete')
@@ -269,10 +269,10 @@ class firewalls:
def SetSshStatus(self,get):
version = public.readFile('/etc/redhat-release')
if int(get['status'])==1:
msg = public.getMsg('FIREWALL_SSH_STOP')
msg = public.get_msg_gettext('SSH service turned off')
act = 'stop'
else:
msg = public.getMsg('FIREWALL_SSH_START')
msg = public.get_msg_gettext('SSH service turned on')
act = 'start'
if not os.path.exists('/etc/redhat-release'):
@@ -282,8 +282,8 @@ class firewalls:
else:
public.ExecShell("/etc/init.d/sshd "+act)
public.WriteLog("TYPE_FIREWALL", msg)
return public.returnMsg(True,'SUCCESS')
public.write_log_gettext("Firewall manager", msg)
return public.return_msg_gettext(True,'Setup successfully!')
@@ -305,7 +305,7 @@ class firewalls:
public.writeFile(filename,conf)
public.ExecShell('sysctl -p')
return public.returnMsg(True,'SUCCESS')
return public.return_msg_gettext(True,'Setup successfully!')
@@ -313,9 +313,9 @@ class firewalls:
def SetSshPort(self,get):
#return public.returnMsg(False,'演示服务器,禁止此操作!');
port = get.port
if int(port) < 22 or int(port) > 65535: return public.returnMsg(False,'FIREWALL_SSH_PORT_ERR');
ports = ['21','25','80','443','8080','888','8888', '7800']
if port in ports: return public.returnMsg(False,'');
if int(port) < 22 or int(port) > 65535: return public.return_msg_gettext(False,'Port range must be between 22 and 65535!');
ports = ['21','25','80','443','8080','888','8888'];
if port in ports: return public.return_msg_gettext(False,'');
file = '/etc/ssh/sshd_config'
conf = public.readFile(file)
@@ -337,9 +337,9 @@ class firewalls:
public.ExecShell("/etc/init.d/sshd restart")
self.FirewallReload()
public.M('firewall').where("ps=?",(public.GetMsg("SSH_SERVER"),)).setField('port',port)
public.WriteLog("TYPE_FIREWALL", "FIREWALL_SSH_PORT",(port,))
return public.returnMsg(True,'EDIT_SUCCESS')
public.M('firewall').where("ps=?",(public.get_msg_gettext('SSH Server'),)).setField('port',port)
public.write_log_gettext("Firewall manager", "Successfully changed SSH port to [{}]!",(port,))
return public.return_msg_gettext(True,'Setup successfully!')
#取SSH信息
def GetSshInfo(self,get):
@@ -398,11 +398,11 @@ class firewalls:
import re
# 判断端口是否正确
rep = "^\d{1,5}(:\d{1,5})?$"
if not re.search(rep, get.port): return public.returnMsg(False, 'PORT_CHECK_RANGE');
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})?$"
if not re.search(rep2, get.address): return public.returnMsg(False, 'FIREWALL_IP_FORMAT');
if not re.search(rep2, get.address): return public.return_msg_gettext(False, 'IP address is illegal!');
import time
ports = get.port
ps = get.ps
@@ -414,19 +414,19 @@ class firewalls:
type_list=['reject','accept']
# 判断type类型是否正确
if types not in type_list:return public.returnMsg(False, 'FIREWALL_PORT_EXISTS')
if types not in type_list:return public.return_msg_gettext(False, 'The port exists, no need to repeat the release!')
# 判断protocol 类型是否正确
if protocol not in protocol_list: return public.returnMsg(False, 'FIREWALL_PORT_EXISTS')
if protocol not in protocol_list: return public.return_msg_gettext(False, 'The port exists, no need to repeat the release!')
notudps = ['80', '443', '8888', '888', '39000:40000', '21', '22','7800']
notudps = ['80', '443', '8888', '888', '39000:40000', '21', '22']
if ports in notudps: flag = True
# sql 查询
#sql="select * from firewall where ports='%s' and address_ip='%s' and protocol='%s' and types='%s';" % (str(ports), str(address_ip), str(protocol), str(types))
query_result = public.M('firewall').where('ports=? and address_ip=? and protocol=? and types=?',(ports, address_ip, protocol, types)).count()
# 这里大于0 表示存在
if query_result > 0 : return public.returnMsg(False,'FIREWALL_PORT_EXISTS')
if query_result > 0 : return public.return_msg_gettext(False,'The port exists, no need to repeat the release!')
if self.__isUfw:
if type=='accept':
@@ -447,11 +447,11 @@ class firewalls:
'iptables -I INPUT -s ' + address_ip + ' -p ' + protocol + ' --dport ' + ports + ' -j DROP')
public.WriteLog("TYPE_FIREWALL", 'FIREWALL_ACCEPT_PORT', (ports,))
public.write_log_gettext("Firewall manager", 'Successfully accepted port [{}]!', (ports,))
addtime = time.strftime('%Y-%m-%d %X', time.localtime())
result = public.M('firewall').add('protocol,types,port,address_ip,ps,addtime', (protocol,types,ports,address_ip,ps,addtime))
self.FirewallReload()
return public.returnMsg(True, 'ADD_SUCCESS')
return public.return_msg_gettext(True, 'Setup successfully!')
# 删除指定放行端口
def DelSpecifiesIp(self, get):
@@ -470,7 +470,7 @@ class firewalls:
address_ip=get.address
protocol_list = ['tcp', 'udp']
id = get.id
if protocol not in protocol_list: return public.returnMsg(False, 'DESIGNATED_POROTOCOL_NOT_EXIST')
if protocol not in protocol_list: return public.return_msg_gettext(False, 'Specified protocol does NOT exist!')
if self.__isUfw:
if type=='accept':
public.ExecShell('ufw delete allow proto ' + protocol + ' from ' + address_ip + ' to any port ' + ports + '')
@@ -485,10 +485,10 @@ class firewalls:
public.ExecShell('iptables -D INPUT -s ' + address_ip + ' -p ' + protocol + ' --dport ' + ports + ' -j ACCEPT')
else:
public.ExecShell('iptables -D INPUT -s ' + address_ip + ' -p ' + protocol + ' --dport ' + ports + ' -j DROP')
public.WriteLog("TYPE_FIREWALL", 'FIREWALL_DROP_PORT', (ports,))
public.write_log_gettext("Firewall manager", 'FIREWALL_DROP_PORT', (ports,))
public.M('firewall').where("id=?", (id,)).delete()
self.FirewallReload()
return public.returnMsg(True, 'DEL_SUCCESS')
return public.return_msg_gettext(True, 'Successfully deleted')
+1 -1
View File
@@ -321,7 +321,7 @@ class firewalld:
# 服务控制
def FirewalldService(self, type):
public.ExecShell('systemctl ' + type + ' firewalld.service')
return public.returnMsg(True, 'SUCCESS')
return public.return_msg_gettext(True, 'Setup successfully!')
# 保存配置
def Save(self):
+135 -97
View File
@@ -11,10 +11,13 @@ class firewalls:
__isFirewalld = False
__isUfw = False
__Obj = None
__ufw_exec = 'ufw'
def __init__(self):
if os.path.exists('/usr/sbin/firewalld'): self.__isFirewalld = True
if os.path.exists('/usr/sbin/ufw'): self.__isUfw = True
if os.path.exists('/usr/sbin/ufw'):
self.__ufw_exec = '/usr/sbin/ufw'
self.__isUfw = True
if self.__isFirewalld:
try:
self.__Obj = firewalld.firewalld()
@@ -53,38 +56,76 @@ class firewalls:
#重载防火墙配置
def FirewallReload(self):
if self.__isUfw:
public.ExecShell('/usr/sbin/ufw reload')
public.ExecShell('{} reload &'.format(self.__ufw_exec))
return
if self.__isFirewalld:
public.ExecShell('firewall-cmd --reload')
else:
public.ExecShell('/etc/init.d/iptables save')
public.ExecShell('/etc/init.d/iptables restart')
public.ExecShell('/etc/init.d/iptables save &')
public.ExecShell('/etc/init.d/iptables restart &')
#取防火墙状态
def CheckFirewallStatus(self):
if self.__isUfw:
return 1
# if self.__isUfw:
# res = public.ExecShell('ufw status verbose')[0]
# if res.find('inactive') != -1: return False
# return True
# if self.__isFirewalld:
# res = public.ExecShell("systemctl status firewalld")[0]
# if res.find('active (running)') != -1: return True
# if res.find('disabled') != -1: return False
# if res.find('inactive (dead)') != -1: return False
# else:
# res = public.ExecShell("/etc/init.d/iptables status")[0]
# if res.find('not running') != -1: return False
# return True
return public.get_firewall_status() == 1
def SetFirewallStatus(self,get=None):
'''
@name 设置系统防火墙状态
@author hwliang<2022-01-13>
'''
status = not self.CheckFirewallStatus()
status_msg = {False: 'Close', True: 'Open'}
if self.__isUfw:
if status:
public.ExecShell('echo y|{} enable'.format(self.__ufw_exec))
else:
public.ExecShell('echo y|{} disable'.format(self.__ufw_exec))
if self.__isFirewalld:
res = public.ExecShell("systemctl status firewalld")[0]
if res.find('active (running)') != -1: return 1
if res.find('disabled') != -1: return -1
if res.find('inactive (dead)') != -1: return 0
if status:
public.ExecShell('systemctl enable firewalld')
public.ExecShell('systemctl start firewalld')
else:
public.ExecShell('systemctl disable firewalld')
public.ExecShell('systemctl stop firewalld')
else:
return 1
if status:
public.ExecShell("chkconfig iptables on")
public.ExecShell('/etc/init.d/iptables start')
else:
public.ExecShell("chkconfig iptables off")
public.ExecShell('/etc/init.d/iptables stop')
public.write_log_gettext('Firewall manager','{} system firewall!',(status_msg[status],))
return public.return_msg_gettext(True,'{} system firewall!',(status_msg[status],))
#添加屏蔽IP
def AddDropAddress(self,get):
if not self.CheckFirewallStatus(): return public.return_msg_gettext(False,'The system firewall is not open')
import time
import re
ip_format = get.port.split('/')[0]
if not public.check_ip(ip_format): return public.returnMsg(False,'FIREWALL_IP_FORMAT')
if ip_format in ['0.0.0.0','127.0.0.0',"::1"]: return public.returnMsg(False,'请不要花样作死!')
if not public.check_ip(ip_format): return public.return_msg_gettext(False,'IP address you entered is illegal!')
if ip_format in ['0.0.0.0','127.0.0.0',"::1"]: return public.return_msg_gettext(False,'Disabling this IP will cause your server to fail')
address = get.port
if public.M('firewall').where("port=?",(address,)).count() > 0: return public.returnMsg(False,'FIREWALL_IP_EXISTS')
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!')
if self.__isUfw:
public.ExecShell('ufw insert 1 deny from ' + address + ' to any')
if public.is_ipv6(ip_format):
public.ExecShell('{} deny from '.format(self.__ufw_exec) + address + ' to any')
else:
public.ExecShell('{} insert 1 deny from '.format(self.__ufw_exec) + address + ' to any')
else:
if self.__isFirewalld:
#self.__Obj.AddDropAddress(address)
@@ -93,26 +134,26 @@ class firewalls:
else:
public.ExecShell('firewall-cmd --permanent --add-rich-rule=\'rule family=ipv4 source address="'+ address +'" drop\'')
else:
if public.is_ipv6(ip_format): return public.returnMsg(False,'FIREWALL_IP_FORMAT')
if public.is_ipv6(ip_format): return public.return_msg_gettext(False,'IP address is illegal!')
public.ExecShell('iptables -I INPUT -s '+address+' -j DROP')
public.WriteLog("TYPE_FIREWALL", 'FIREWALL_DROP_IP',(address,))
addtime = time.strftime('%Y-%m-%d %X',time.localtime())
public.M('firewall').add('port,ps,addtime',(address,get.ps,addtime))
self.FirewallReload()
return public.returnMsg(True,'ADD_SUCCESS')
return public.return_msg_gettext(True,'Setup successfully!')
#删除IP屏蔽
def DelDropAddress(self,get):
if not self.CheckFirewallStatus(): return public.return_msg_gettext(False,'The system firewall is not open')
address = get.port
id = get.id
ip_format = get.port.split('/')[0]
if self.__isUfw:
public.ExecShell('ufw delete deny from ' + address + ' to any')
public.ExecShell('{} delete deny from '.format(self.__ufw_exec) + address + ' to any')
else:
if self.__isFirewalld:
#self.__Obj.DelDropAddress(address)
if public.is_ipv6(ip_format):
public.ExecShell('firewall-cmd --permanent --remove-rich-rule=\'rule family=ipv6 source address="'+ address +'" drop\'')
else:
@@ -124,73 +165,81 @@ class firewalls:
public.M('firewall').where("id=?",(id,)).delete()
self.FirewallReload()
return public.returnMsg(True,'DEL_SUCCESS')
return public.return_msg_gettext(True,'Successfully deleted')
#添加放行端口
def AddAcceptPort(self,get):
if not self.CheckFirewallStatus(): return public.return_msg_gettext(False,'The system firewall is not open')
import re
src_port = get.port
get.port = get.port.replace('-',':')
rep = r"^\d{1,5}(:\d{1,5})?$"
if not re.search(rep,get.port):
return public.returnMsg(False,'PORT_CHECK_RANGE')
return public.return_msg_gettext(False,'Port range must be between 22 and 65535!')
import time
port = get.port
ps = public.xssencode(get.ps)
ps = ""
if get.ps:
ps = public.xssencode2(get.ps)
is_exists = public.M('firewall').where("port=? or port=?",(port,src_port)).count()
if is_exists: return public.returnMsg(False,'FIREWALL_PORT_EXISTS')
notudps = ['80','443','8888','888','39000:40000','21','22','7800']
if is_exists: return public.return_msg_gettext(False,'The port exists, no need to repeat the release!')
notudps = ['80','443','8888','888','39000:40000','21','22']
if self.__isUfw:
public.ExecShell('ufw allow ' + port + '/tcp')
if not port in notudps: public.ExecShell('ufw allow ' + port + '/udp')
public.ExecShell('{} allow '.format(self.__ufw_exec) + port + '/tcp')
# if not port in notudps: public.ExecShell('ufw allow ' + port + '/udp')
else:
if self.__isFirewalld:
#self.__Obj.AddAcceptPort(port)
port = port.replace(':','-')
public.ExecShell('firewall-cmd --permanent --zone=public --add-port='+port+'/tcp')
if not port in notudps: public.ExecShell('firewall-cmd --permanent --zone=public --add-port='+port+'/udp')
# if not port in notudps: public.ExecShell('firewall-cmd --permanent --zone=public --add-port='+port+'/udp')
else:
public.ExecShell('iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport '+port+' -j ACCEPT')
if not port in notudps: public.ExecShell('iptables -I INPUT -p tcp -m state --state NEW -m udp --dport '+port+' -j ACCEPT')
# if not port in notudps: public.ExecShell('iptables -I INPUT -p tcp -m state --state NEW -m udp --dport '+port+' -j ACCEPT')
public.WriteLog("TYPE_FIREWALL", 'FIREWALL_ACCEPT_PORT',(port,))
addtime = time.strftime('%Y-%m-%d %X',time.localtime())
if not is_exists: public.M('firewall').add('port,ps,addtime',(port,ps,addtime))
self.FirewallReload()
return public.returnMsg(True,'ADD_SUCCESS')
return public.return_msg_gettext(True,'Setup successfully!')
#添加放行端口
def AddAcceptPortAll(self,port,ps):
if not self.CheckFirewallStatus(): return public.return_msg_gettext(False,'The system firewall is not open')
import re
port = port.replace('-',':')
rep = r"^\d{1,5}(:\d{1,5})?$"
if not re.search(rep,port):
return False
if self.__isUfw:
public.ExecShell('ufw allow ' + port + '/tcp')
public.ExecShell('ufw allow ' + port + '/udp')
public.ExecShell('{} allow '.format(self.__ufw_exec) + port + '/tcp')
# public.ExecShell('ufw allow ' + port + '/udp')
else:
if self.__isFirewalld:
port = port.replace(':','-')
public.ExecShell('firewall-cmd --permanent --zone=public --add-port='+port+'/tcp')
public.ExecShell('firewall-cmd --permanent --zone=public --add-port='+port+'/udp')
# public.ExecShell('firewall-cmd --permanent --zone=public --add-port='+port+'/udp')
else:
public.ExecShell('iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport '+port+' -j ACCEPT')
public.ExecShell('iptables -I INPUT -p tcp -m state --state NEW -m udp --dport '+port+' -j ACCEPT')
# public.ExecShell('iptables -I INPUT -p tcp -m state --state NEW -m udp --dport '+port+' -j ACCEPT')
return True
#删除放行端口
def DelAcceptPort(self,get):
if not self.CheckFirewallStatus(): return public.return_msg_gettext(False,'The system firewall is not open')
port = get.port
id = get.id
if public.is_ipv6(str(port)): return self.DelDropAddress(get) # 如果是ipv6地址,则调用DelDropAddress
try:
if(port == public.GetHost(True) or port == public.readFile('data/port.pl').strip()):
return public.returnMsg(False,'FIREWALL_PORT_PANEL')
return public.return_msg_gettext(False,'Failed,cannot delete current port of the panel')
if self.__isUfw:
public.ExecShell('ufw delete allow ' + port + '/tcp')
public.ExecShell('ufw delete allow ' + port + '/udp')
public.ExecShell('{} delete allow '.format(self.__ufw_exec) + port + '/tcp')
public.ExecShell('{} delete allow '.format(self.__ufw_exec) + port + '/udp')
else:
if self.__isFirewalld:
#self.__Obj.DelAcceptPort(port)
@@ -201,35 +250,42 @@ class firewalls:
public.ExecShell('iptables -D INPUT -p tcp -m state --state NEW -m udp --dport '+port+' -j ACCEPT')
public.WriteLog("TYPE_FIREWALL", 'FIREWALL_DROP_PORT',(port,))
public.M('firewall').where("id=?",(id,)).delete()
self.FirewallReload()
return public.returnMsg(True,'DEL_SUCCESS')
return public.return_msg_gettext(True,'Successfully deleted')
except:
return public.returnMsg(False,'DEL_ERROR')
return public.return_msg_gettext(False,'Failed to delete')
#设置远程端口状态
def SetSshStatus(self,get):
version = public.readFile('/etc/redhat-release')
# version = public.readFile('/etc/redhat-release')
if int(get['status'])==1:
msg = public.getMsg('FIREWALL_SSH_STOP')
msg = public.get_msg_gettext('SSH service turned off')
act = 'stop'
else:
msg = public.getMsg('FIREWALL_SSH_START')
msg = public.get_msg_gettext('SSH service turned on')
act = 'start'
if not os.path.exists('/etc/redhat-release'):
public.ExecShell('service ssh ' + act)
elif version.find(' 7.') != -1 or version.find(' 8.') != -1 or version.find('Fedora') != -1:
public.ExecShell("systemctl "+act+" sshd.service")
else:
public.ExecShell("/etc/init.d/sshd "+act)
public.WriteLog("TYPE_FIREWALL", msg)
return public.returnMsg(True,'SUCCESS')
# if not os.path.exists('/etc/redhat-release'):
# public.ExecShell('service ssh ' + act)
# elif version.find(' 7.') != -1 or version.find(' 8.') != -1 or version.find('Fedora') != -1:
# public.ExecShell("systemctl "+act+" sshd")
# else:
# 全试一次?
public.ExecShell("/etc/init.d/sshd "+act)
public.ExecShell('service ssh ' + act)
public.ExecShell("systemctl "+act+" sshd")
public.ExecShell("systemctl "+act+" ssh")
if act in ['start'] and not public.get_sshd_status():
msg = 'Service SSHD start failed!'
public.WriteLog("TYPE_FIREWALL", msg)
return public.returnMsg(False,msg)
public.WriteLog("TYPE_FIREWALL", msg)
return public.return_msg_gettext(True,'Setup successfully!')
#设置ping
def SetPing(self,get):
if get.status == '1':
@@ -243,20 +299,27 @@ class firewalls:
conf = re.sub(rep,'net.ipv4.icmp_echo_ignore_all='+get.status,conf)
else:
conf += "\nnet.ipv4.icmp_echo_ignore_all="+get.status
public.writeFile(filename,conf)
public.ExecShell('sysctl -p')
return public.returnMsg(True,'SUCCESS')
if public.writeFile(filename,conf):
public.ExecShell('sysctl -p')
return public.return_msg_gettext(True,'Setup successfully!')
else:
return public.returnMsg(False,'Setup failed!')
#改远程端口
def SetSshPort(self,get):
port = get.port
if int(port) < 22 or int(port) > 65535: return public.returnMsg(False,'FIREWALL_SSH_PORT_ERR')
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.returnMsg(False,'DONT_USE_PORT')
if port in ports: return public.return_msg_gettext(False,'Do NOT use common default port!')
file = '/etc/ssh/sshd_config'
conf = public.readFile(file)
@@ -270,47 +333,22 @@ class firewalls:
public.ExecShell('sed -i "s#SELINUX=enforcing#SELINUX=disabled#" /etc/selinux/config')
public.ExecShell("systemctl restart sshd.service")
elif self.__isUfw:
public.ExecShell('ufw allow ' + port + '/tcp')
public.ExecShell('{} allow '.format(self.__ufw_exec) + port + '/tcp')
public.ExecShell("service ssh restart")
else:
public.ExecShell('iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport '+port+' -j ACCEPT')
public.ExecShell("/etc/init.d/sshd restart")
self.FirewallReload()
public.M('firewall').where("ps=? or ps=? or port=?",('SSH remote management service','SSH remote service',port)).delete()
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.returnMsg(True,'EDIT_SUCCESS')
return public.return_msg_gettext(True,'Setup successfully!')
#取SSH信息
def GetSshInfo(self,get):
port = public.get_ssh_port()
pid_file = '/run/sshd.pid'
if os.path.exists(pid_file):
pid = int(public.readFile(pid_file))
status = public.pid_exists(pid)
else:
import system
panelsys = system.system()
version = panelsys.GetSystemVersion()
if os.path.exists('/usr/bin/apt-get'):
if os.path.exists('/etc/init.d/sshd'):
status = public.ExecShell("service sshd status | grep -P '(dead|stop)'|grep -v grep")
else:
status = public.ExecShell("service ssh status | grep -P '(dead|stop)'|grep -v grep")
else:
if version.find(' 7.') != -1 or version.find(' 8.') != -1 or version.find('Fedora') != -1:
status = public.ExecShell("systemctl status sshd.service | grep 'dead'|grep -v grep")
else:
status = public.ExecShell("/etc/init.d/sshd status | grep -e 'stopped' -e '已停'|grep -v grep")
# return status;
if len(status[0]) > 3:
status = False
else:
status = True
port = public.get_sshd_port()
status = public.get_sshd_status()
isPing = True
try:
file = '/etc/sysctl.conf'
@@ -325,6 +363,6 @@ class firewalls:
data['port'] = port
data['status'] = status
data['ping'] = isPing
data['firewall_status'] = self.CheckFirewallStatus()
return data
+20 -2
View File
@@ -2,7 +2,7 @@ import sys,os
from gzip import GzipFile
from io import BytesIO
from flask import request, current_app,session,Response,g
from flask import request, current_app,session,Response,g,abort
if sys.version_info[:2] == (2, 6):
@@ -80,7 +80,8 @@ class Compress(object):
accept_encoding = request.headers.get('Accept-Encoding', '')
response.headers['Server'] = 'nginx'
response.headers['Connection'] = 'keep-alive'
if not 'tmp_login' in session:
response.headers["X-Frame-Options"] = "SAMEORIGIN"
if 'dologin' in g and app.config['SSL']:
try:
for k,v in request.cookies.items():
@@ -104,6 +105,23 @@ class Compress(object):
if request_token:
response.set_cookie('request_token',request_token,path='/',max_age=86400 * 30)
if response.content_length is not None:
if response.content_length < 512:
if not session.get('login',None) or g.get('api_request',None):
import public
default_pl = "{}/default.pl".format(public.get_panel_path())
default_body = public.readFile(default_pl,'rb')
if default_body:
if not default_body: default_body = b""
resp_body = response.get_data()
if default_body and resp_body.find(default_body.strip()) != -1:
result = b'{"status":false,"msg":"Error: 403 Forbidden"}'
response.set_data(result)
response.headers['Content-Length'] = len(result)
return response
if (response.mimetype not in app.config['COMPRESS_MIMETYPES'] or
'gzip' not in accept_encoding.lower() or
+5 -9
View File
@@ -286,25 +286,21 @@ class MemcachedSessionInterface(SessionInterface):
session_id = self._get_signer(app).sign(want_bytes(session.sid))
else:
session_id = session.sid
from BTPanel import request, g, get_input
from BTPanel import request,g,get_input
if 'auth_error' in g: return
if request.path in ['/', '/tips','/robots.txt']: return
if request.path in ['/', '/tips', '/robots.txt', '/favicon.ico', '/hook', '/close', '/down/']: return
if request.path in ['/public']:
get = get_input()
if 'get_ping' in get: return
if not 'get_ping' in get: return
if response.status_code in [401]: return
if request.full_path.find('/login?tmp_token=') != 0:
if response.status_code not in [200, 308]: return
if response.status_code not in [200,308]: return
else:
if response.status_code not in [302, 301]: return
if response.status_code not in [302,301]: return
if secure: samesite = 'None'
if response.status_code not in [200,302]: return
if not request.cookies.get(app.session_cookie_name):
if request.full_path.find('/login?tmp_token=') == 0:
samesite = 'None'
secure = True
response.set_cookie(app.session_cookie_name, session_id,
expires=expires, httponly=httponly,
domain=domain, path=path, secure=secure,samesite=samesite)
+96 -42
View File
@@ -20,94 +20,100 @@ class ftp:
#添加FTP
def AddUser(self,get):
try:
if not os.path.exists('/www/server/pure-ftpd/sbin/pure-ftpd'): return public.returnMsg(False,'Please install the Pure-FTPd service in the software store first.')
if not os.path.exists('/www/server/pure-ftpd/sbin/pure-ftpd'): return public.return_msg_gettext(False,'Please install the Pure-FTPd service in the software store first.')
import files,time
fileObj=files.files()
if re.search("\W + ",get['ftp_username']): return {'status':False,'code':501,'msg':public.getMsg('FTP_USERNAME_ERR_T')}
if len(get['ftp_username']) < 3: return {'status':False,'code':501,'msg':public.getMsg('FTP_USERNAME_ERR_LEN')}
if not fileObj.CheckDir(get['path']): return {'status':False,'code':501,'msg':public.getMsg('FTP_USERNAME_ERR_DIR')}
if public.M('ftps').where('name=?',(get.ftp_username.strip(),)).count(): return public.returnMsg(False,'FTP_USERNAME_ERR_EXISTS',(get.ftp_username,))
username = get['ftp_username'].replace(' ','')
password = get['ftp_password']
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 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")
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(' ','')
get.path = get.path.replace("\\", "/")
fileObj.CreateDir(get)
public.ExecShell('chown www.www ' + get.path)
public.ExecShell(self.__runPath + '/pure-pw useradd ' + username + ' -u www -d ' + get.path + '<<EOF \n' + password + '\n' + password + '\nEOF')
public.ExecShell(self.__runPath + '/pure-pw useradd "' + username + '" -u www -d ' + get.path + '<<EOF \n' + password + '\n' + password + '\nEOF')
self.FtpReload()
ps=public.xssencode(get['ps'])
if get['ps']=='': ps= public.getMsg('INPUT_PS');
ps = public.xssencode2(get['ps'])
if get['ps']=='': ps= public.get_msg_gettext('Edit notes');
addtime=time.strftime('%Y-%m-%d %X',time.localtime())
pid = 0
if hasattr(get,'pid'): pid = get.pid
public.M('ftps').add('pid,name,password,path,status,ps,addtime',(pid,username,password,get.path,1,ps,addtime))
public.WriteLog('TYPE_FTP', 'FTP_ADD_SUCCESS',(username,))
return public.returnMsg(True,'ADD_SUCCESS')
public.write_log_gettext('FTP manager', 'Successfully added FTP user [{}]!',(username,))
return public.return_msg_gettext(True,'Setup successfully!')
except Exception as ex:
public.WriteLog('TYPE_FTP', 'FTP_ADD_ERR',(username,str(ex)))
return public.returnMsg(False,'ADD_ERROR')
public.write_log_gettext('FTP manager', 'Failed to add FTP user[{}]! => {}',(username,str(ex)))
return public.return_msg_gettext(False,'Failed to add')
#删除用户
def DeleteUser(self,get):
try:
username = get['username']
id = get['id']
public.ExecShell(self.__runPath + '/pure-pw userdel ' + username)
public.ExecShell(self.__runPath + '/pure-pw userdel "' + username + '"')
self.FtpReload()
public.M('ftps').where("id=?",(id,)).delete()
public.WriteLog('TYPE_FTP', 'FTP_DEL_SUCCESS',(username,))
return public.returnMsg(True, "DEL_SUCCESS")
public.write_log_gettext('FTP manager', 'Successfully deleted FTP user[{}]!',(username,))
return public.return_msg_gettext(True, 'Successfully deleted')
except Exception as ex:
public.WriteLog('TYPE_FTP', 'FTP_DEL_ERR',(username,str(ex)))
return public.returnMsg(False,'DEL_ERROR')
public.write_log_gettext('FTP manager', 'Faided to delete FTP user[{}]! => {}',(username,str(ex)))
return public.return_msg_gettext(False,'Failed to delete')
#修改用户密码
def SetUserPassword(self,get):
try:
id = get['id']
username = get['ftp_username']
password = get['new_password']
public.ExecShell(self.__runPath + '/pure-pw passwd ' + username + '<<EOF \n' + password + '\n' + password + '\nEOF')
username = get['ftp_username'].strip()
password = get['new_password'].strip()
if len(password) < 6: return public.return_msg_gettext(False,'Password must be at least [{}] characters',("6",))
public.ExecShell(self.__runPath + '/pure-pw passwd "' + username + '"<<EOF \n' + password + '\n' + password + '\nEOF')
self.FtpReload()
public.M('ftps').where("id=?",(id,)).setField('password',password)
public.WriteLog('TYPE_FTP', 'FTP_PASS_SUCCESS',(username,))
return public.returnMsg(True,'EDIT_SUCCESS')
public.write_log_gettext('FTP manager', 'Successfully changed password for FTP user[{}]!',(username,))
return public.return_msg_gettext(True,'Setup successfully!')
except Exception as ex:
public.WriteLog('TYPE_FTP', 'FTP_PASS_ERR',(username,str(ex)))
return public.returnMsg(False,'EDIT_ERROR')
public.write_log_gettext('FTP manager', 'Failed to change password FTP user[{}]! => {}',(username,str(ex)))
return public.return_msg_gettext(False,'Failed to modify')
#设置用户状态
def SetStatus(self,get):
msg = public.getMsg('OFF');
if get.status != '0': msg = public.getMsg('ON');
msg = public.get_msg_gettext('Turn off');
if get.status != '0': msg = public.get_msg_gettext('Turn on');
try:
id = get['id']
username = get['username']
status = get['status']
if int(status)==0:
public.ExecShell(self.__runPath + '/pure-pw usermod ' + username + ' -r 1')
public.ExecShell(self.__runPath + '/pure-pw usermod "' + username + '" -r 1')
else:
public.ExecShell(self.__runPath + '/pure-pw usermod ' + username + " -r ''")
public.ExecShell(self.__runPath + '/pure-pw usermod "' + username + "\" -r ''")
self.FtpReload()
public.M('ftps').where("id=?",(id,)).setField('status',status)
public.WriteLog('TYPE_FTP','FTP_STATUS', (msg,username))
return public.returnMsg(True, 'SUCCESS')
public.write_log_gettext('FTP manager','Successfully {} FTP user [{}]!', (msg,username))
return public.return_msg_gettext(True, 'Setup successfully!')
except Exception as ex:
public.WriteLog('TYPE_FTP','FTP_STATUS_ERR', (msg,username,str(ex)))
return public.returnMsg(False,'FTP_STATUS_ERR',(msg,))
public.write_log_gettext('FTP manager','Failed to {} FTP user [{}]! => {}', (msg,username,str(ex)))
return public.return_msg_gettext(False,'{} FTP user failed!',(msg,))
'''
* 设置FTP端口
* @param Int _GET['port'] 端口号
* @param Int _GET['port'] 端口号
* @return bool
'''
def setPort(self,get):
try:
port = get['port']
if int(port) < 1 or int(port) > 65535: return public.returnMsg(False,'PORT_CHECK_RANGE')
port = get['port'].strip()
if not port: return public.returnMsg(False,'Please enter an integer for the port')
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]+)"
@@ -115,18 +121,66 @@ class ftp:
conf = re.sub(rep,"\nBind 0.0.0.0," + port,conf)
public.writeFile(file,conf)
public.ExecShell('/etc/init.d/pure-ftpd restart')
public.WriteLog('TYPE_FTP', "FTP_PORT",(port,))
public.write_log_gettext('FTP manager', "Successfully modified FTP port to [{}]!",(port,))
#添加防火墙
#data = ftpinfo(port=port,ps = 'FTP端口')
get.port=port
get.ps = public.getMsg('FTP_PORT_PS');
get.ps = public.get_msg_gettext('FTP port');
firewalls.firewalls().AddAcceptPort(get)
session['port']=port
return public.returnMsg(True, 'EDIT_SUCCESS')
return public.return_msg_gettext(True, 'Setup successfully!')
except Exception as ex:
public.WriteLog('TYPE_FTP', 'FTP_PORT_ERR',(str(ex),))
return public.returnMsg(False,'EDIT_ERROR')
public.write_log_gettext('FTP manager', 'Failed to modify FTP port! => {}',(str(ex),))
return public.return_msg_gettext(False,'Failed to modify')
#重载配置
def FtpReload(self):
public.ExecShell(self.__runPath + '/pure-pw mkdb /www/server/pure-ftpd/etc/pureftpd.pdb')
#修改用户密码
def set_user_home(self,get):
"""
change user home
id: ftp id
path: the new ftp user home
ftp_username: ftp username
migrate: migrate ftp user data to the new home
"""
try:
id = get['id']
path = get['path']
username = get['ftp_username']
# get the old path in the panel sqlite db
old_path = public.M("ftps").where("id=?",(id,)).getField('path')
# check the auth ftp user if exists
auth_conf_file = '/www/server/pure-ftpd/etc/pureftpd.passwd'
auth_conf = public.readFile(auth_conf_file)
if not auth_conf:
return public.returnMsg(False,'FTP account has not been set up')
# get the user specified conf
auth_conf_list = [i for i in auth_conf.split('\n')]
rep = '^{}:.*'.format(username)
macth_conf = [i for i in auth_conf_list if re.search(rep,i)]
if not macth_conf:
return public.returnMsg(False, 'FTP account has not been set up1')
if len(macth_conf) > 1:
return public.returnMsg(False, 'Matching multiple configurations, this operation has been stopped!')
if not os.path.exists(path):
os.makedirs(path)
public.ExecShell('chown www.www ' + path)
# replace the old path
result = macth_conf[0]
specified_user_conf = result.replace(old_path,path)
auth_conf = auth_conf.replace(result,specified_user_conf)
public.writeFile(auth_conf_file,auth_conf)
if get.migrate == '1':
public.ExecShell('cp -rp {}/* {}'.format(old_path,path))
self.FtpReload()
public.M('ftps').where("id=?",(id,)).setField('path',path)
public.write_log_gettext('FTP manager', 'Successfully changed password for FTP user[{}]!',(path,))
return public.return_msg_gettext(True,'Setup successfully!')
except Exception as ex:
return public.get_error_info()
public.write_log_gettext('FTP manager', 'FTP_PASS_ERR',(path,str(ex)))
return public.returnMsg(False,'EDIT_ERROR')
+83 -29
View File
@@ -14,22 +14,31 @@ import os,sys,re
import ssl
import public
import json
import socket
import requests
import requests.packages.urllib3.util.connection as urllib3_conn
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
class http:
def __init__(self):
pass
def get(self,url,timeout = 60,headers = {},verify = False,type = 'python'):
url = self.quote(url)
if type == 'python':
old_family = urllib3_conn.allowed_gai_family
try:
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
from requests import get as req_get
return req_get(url,timeout=timeout,headers=get_headers(headers),verify=verify)
# 默认使用IPv4
urllib3_conn.allowed_gai_family = lambda: socket.AF_INET
return requests.get(url,timeout=timeout,headers=get_headers(headers),verify=verify)
except:
result = self._get_curl(url,timeout,headers,verify)
try:
# IPV6
urllib3_conn.allowed_gai_family = lambda: socket.AF_INET6
return requests.get(url,timeout=timeout,headers=get_headers(headers),verify=verify)
except:
# 使用CURL
result = self._get_curl(url,timeout,headers,verify)
urllib3_conn.allowed_gai_family = old_family
elif type == 'curl':
result = self._get_curl(url,timeout,headers,verify)
elif type == 'php':
@@ -44,14 +53,20 @@ class http:
def post(self,url,data,timeout = 60,headers = {},verify = False,type = 'python'):
url = self.quote(url)
if type == 'python':
old_family = urllib3_conn.allowed_gai_family
try:
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
from requests import post as req_post
return req_post(url,data,timeout=timeout,headers=headers,verify=verify)
urllib3_conn.allowed_gai_family = lambda: socket.AF_INET
return requests.post(url,data,timeout=timeout,headers=headers,verify=verify)
except:
result = self._post_curl(url,data,timeout,headers,verify)
try:
# IPV6
urllib3_conn.allowed_gai_family = lambda: socket.AF_INET6
return requests.post(url,data,timeout=timeout,headers=headers,verify=verify)
except:
# 使用CURL
result = self._post_curl(url,data,timeout,headers,verify)
urllib3_conn.allowed_gai_family = old_family
elif type == 'curl':
result = self._post_curl(url,data,timeout,headers,verify)
elif type == 'php':
@@ -63,6 +78,30 @@ class http:
result = self._post_py3(url,data,timeout,headers,verify)
return result
def download_file(self,url,filename,data = None,timeout = 1800,speed_file='/dev/shm/download_speed.pl'):
'''
@name 下载文件
@author hwliang<2021-07-08>
@param url<string> 下载地址
@param filename<string> 保存路径
@param data<dict> POST参数不传则使用GET方法否则使用POST方法
@param timeout<int> 超时时间,默认1800秒
@param speed_file<string>
'''
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
headers = public.get_requests_headers()
if data is None:
res = requests.get(url,headers=headers,timeout=timeout,stream=True)
else:
res = requests.post(url,data,headers=headers,timeout=timeout,stream=True)
with open(filename,"wb") as f:
for _chunk in res.iter_content(chunk_size=8192):
f.write(_chunk)
#POST请求 Python2
def _post_py2(self,url,data,timeout,headers,verify):
import urllib2
@@ -114,18 +153,21 @@ class http:
raise Exception('No PHP version available!')
tmp_file = '/dev/shm/http.php'
http_php = '''<?php
if(isset($_POST['data'])){
error_reporting(E_ERROR);
if(isset($_POST['data'])){{
$data = json_decode($_POST['data'],1);
}else{
$data = json_decode(getopt('',array('post:'))['post'],1);
}
}}else{{
$s = getopt('',array('post:'));
$data = json_decode($s['post'],1);
}}
$url = $data['url'];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER,$data['headers']);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data['data']));
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data['data']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $data['verify']);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $data['verify']);
@@ -145,10 +187,13 @@ exit($header."\r\n\r\n".json_encode($body));
# data = json.dumps(pdata)
data = json.dumps({"url":url,"timeout":timeout,"verify":verify,"headers":self._php_headers(headers),"data":data})
if php_version in ['53']:
php_version = '/www/server/php/' + php_version + '/bin/php'
if php_version.find('/www/server/php') != -1:
result = public.ExecShell(php_version + ' ' + tmp_file + " --post='" + data + "'" )[0]
else:
result = public.request_php(php_version,'/http.php','/dev/shm','POST',{"data":data})
if isinstance(result,bytes): result = result.decode('utf-8')
if os.path.exists(tmp_file): os.remove(tmp_file)
r_body,r_headers,r_status_code = self._curl_format(result)
@@ -209,7 +254,7 @@ exit($header."\r\n\r\n".json_encode($body));
headers_str = self._str_headers(headers)
_ssl_verify = ''
if not verify: _ssl_verify = ' -k'
result = public.ExecShell("{} -sS -i --connect-timeout {} {} {} 2>&1".format(self._curl_bin() + _ssl_verify,timeout,headers_str,url))[0]
result = public.ExecShell("{} -sS -i --connect-timeout {} {} {} 2>&1".format(self._curl_bin() + ' ' + str(_ssl_verify),timeout,headers_str,url))[0]
r_body,r_headers,r_status_code = self._curl_format(result)
return response(r_body,r_status_code,r_headers)
@@ -220,11 +265,13 @@ exit($header."\r\n\r\n".json_encode($body));
raise Exception('No PHP version available!')
tmp_file = '/dev/shm/http.php'
http_php = '''<?php
if(isset($_POST['data'])){
error_reporting(E_ERROR);
if(isset($_POST['data'])){{
$data = json_decode($_POST['data'],1);
}else{
$data = json_decode(getopt('',array('post:'))['post'],1);
}
}}else{{
$s = getopt('',array('post:'));
$data = json_decode($s['post'],1);
}}
$url = $data['url'];
$ch = curl_init();
$user_agent = "BT-Panel";
@@ -247,10 +294,14 @@ exit($header."\r\n\r\n".json_encode($body));
?>'''
public.writeFile(tmp_file,http_php)
data = json.dumps({"url":url,"timeout":timeout,"verify":verify,"headers":self._php_headers(headers)})
if php_version in ['53']:
php_version = '/www/server/php/' + php_version + '/bin/php'
if php_version.find('/www/server/php') != -1:
result = public.ExecShell(php_version + ' ' + tmp_file + " --post='" + data + "'" )[0]
else:
result = public.request_php(php_version,'/http.php','/dev/shm','POST',{"data":data})
if isinstance(result,bytes): result = result.decode('utf-8')
if os.path.exists(tmp_file): os.remove(tmp_file)
r_body,r_headers,r_status_code = self._curl_format(result)
return response(json.loads(r_body).strip(),r_status_code,r_headers)
@@ -259,7 +310,8 @@ exit($header."\r\n\r\n".json_encode($body));
#取可用的PHP版本
def _get_php_version(self):
php_versions = ['52','53','54','55','56','70','71','72','73','74','80']
php_versions = public.get_php_versions()
php_versions = sorted(php_versions,reverse=True)
php_path = '/www/server/php/{}/sbin/php-fpm'
php_sock = '/tmp/php-cgi-{}.sock'
for pv in php_versions:
@@ -276,9 +328,11 @@ exit($header."\r\n\r\n".json_encode($body));
#取CURL路径
def _curl_bin(self):
c_bin = ['/usr/local/curl2/bin/curl','/usr/local/curl/bin/curl','/usr/local/bin/curl','/usr/bin/curl']
curl_bin = 'curl'
for cb in c_bin:
if os.path.exists(cb): curl_bin = cb
if os.path.exists(cb): return cb
return 'curl'
return curl_bin
#格式化CURL响应头
def _curl_format(self,req):
@@ -396,7 +450,7 @@ class response:
return self.text
DEFAULT_HEADERS = {"Content-type":"application/x-www-form-urlencoded","User-Agent":"BT-Panel"}
s_types = ['python','php','curl']
s_types = ['python','php','curl','src']
DEFAULT_TYPE = 'python'
__version__ = 1.0
+75 -4
View File
@@ -48,6 +48,19 @@ def control_init():
if not public.M('sqlite_master').where('type=? AND name=? AND sql LIKE ?', ('table', 'sites','%project_config%')).count():
public.M('sites').execute("alter TABLE sites add project_config STRING DEFAULT '{}'",())
if not public.M('sqlite_master').where('type=? AND name=? AND sql LIKE ?', ('table', 'backup','%ps%')).count():
public.M('backup').execute("alter TABLE backup add ps STRING DEFAULT 'No'",())
if not public.M('sqlite_master').where('type=? AND name=? AND sql LIKE ?', ('table', 'databases','%db_type%')).count():
public.M('databases').execute("alter TABLE databases add db_type integer DEFAULT '0'",())
if not public.M('sqlite_master').where('type=? AND name=? AND sql LIKE ?', ('table', 'databases','%conn_config%')).count():
public.M('databases').execute("alter TABLE databases add conn_config STRING DEFAULT '{}'",())
if not public.M('sqlite_master').where('type=? AND name=? AND sql LIKE ?', ('table', 'databases','%sid%')).count():
public.M('databases').execute("alter TABLE databases add sid integer DEFAULT 0",())
sql = db.Sql()
if not sql.table('sqlite_master').where('type=? AND name=?', ('table', 'site_types')).count():
csql = '''CREATE TABLE IF NOT EXISTS `site_types` (
@@ -94,6 +107,18 @@ def control_init():
`logout_time` INTEGER,
`expire` INTEGER,
`addtime` INTEGER
)'''
sql.execute(csql,())
if not sql.table('sqlite_master').where('type=? AND name=?', ('table', 'database_servers')).count():
csql = '''CREATE TABLE IF NOT EXISTS `database_servers` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`db_host` REAL,
`db_port` REAL,
`db_user` INTEGER,
`db_password` INTEGER,
`ps` REAL,
`addtime` INTEGER
)'''
sql.execute(csql,())
@@ -161,10 +186,19 @@ def control_init():
public.ExecShell("rm -rf /www/server/panel/adminer")
if os.path.exists('/dev/shm/session.db'):
os.remove('/dev/shm/session.db')
node_service_bin = '/usr/bin/nodejs-service'
node_service_src = '/www/server/panel/script/nodejs-service.py'
if os.path.exists(node_service_src): public.ExecShell("chmod 700 " + node_service_src)
if not os.path.exists(node_service_bin):
if os.path.exists(node_service_src):
public.ExecShell("ln -sf {} {}".format(node_service_src,node_service_bin))
#disable_putenv('putenv')
#clean_session()
#set_crond()
test_ping()
set_wp_cache_dir()
clean_max_log('/www/server/panel/plugin/rsync/lsyncd.log')
clean_max_log('/var/log/rsyncd.log',1024*1024*10)
clean_max_log('/root/.pm2/pm2.log',1024*1024*20)
@@ -182,7 +216,12 @@ def control_init():
update_py37()
run_script()
set_php_cli_env()
check_enable_php()
def set_wp_cache_dir():
import one_key_wp
one_key_wp.fast_cgi().set_nginx_conf()
public.ExecShell("/etc/init.d/nginx restart")
def set_php_cli_env():
'''
@@ -209,7 +248,7 @@ def set_php_cli_env():
# 设置所有已安装的PHP版本环境变量和别名
php_versions_list = ['52','53','54','55','56','70','71','72','73','74','80','81','82','83','84','90','91']
php_versions_list = public.get_php_versions()
for php_version in php_versions_list:
php_ini = "{}/{}/etc/php.ini".format(php_path,php_version)
php_cli_ini = "{}/{}/etc/php-cli.ini".format(php_path,php_version)
@@ -244,6 +283,30 @@ def set_php_cli_env():
public.writeFile(bashrc,bashrc_body)
def check_enable_php():
'''
@name 检查nginx下的php配置文件
'''
php_versions = public.get_php_versions()
ngx_php_conf = public.get_setup_path() + '/nginx/conf/enable-php-00.conf'
public.writeFile(ngx_php_conf,'')
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 = '''
location ~ [^/]\.php(/|$)
{{
try_files $uri =404;
fastcgi_pass unix:/tmp/php-cgi-{}.sock;
fastcgi_index index.php;
include fastcgi.conf;
include pathinfo.conf;
}}
'''.format(php_v)
public.writeFile(ngx_php_conf,enable_conf)
def write_run_script_log(_log,rn='\n'):
_log_file = '/www/server/panel/logs/run_script.log'
public.writeFile(_log_file,_log + rn,'a+')
@@ -319,7 +382,6 @@ def files_set_mode():
["/www/server/stop","","root",755,True],
["/www/server/redis","","redis",700,True],
["/www/server/redis/redis.conf","","redis",600,False],
["/www/Recycle_bin","","root",600,True],
["/www/server/panel/class","","root",600,True],
["/www/server/panel/data","","root",600,True],
["/www/server/panel/plugin","","root",600,False],
@@ -345,6 +407,10 @@ def files_set_mode():
["/www/server/coll","","root",700,True]
]
recycle_list = public.get_recycle_bin_list()
for recycle_path in recycle_list:
m_paths.append([recycle_path,'','root',600,True])
for m in m_paths:
if not os.path.exists(m[0]): continue
path = m[0] + m[1]
@@ -409,7 +475,7 @@ def set_pma_access():
#尝试升级到独立环境
def update_py37():
pyenv='/www/server/panel/pyenv/bin/python'
pyenv='/www/server/panel/pyenv/bin/python3'
pyenv_exists='/www/server/panel/data/pyenv_exists.pl'
if os.path.exists(pyenv) or os.path.exists(pyenv_exists): return False
download_url = public.get_url()
@@ -552,7 +618,7 @@ def disable_putenv(fun_name):
try:
is_set_disable = '/www/server/panel/data/disable_%s' % fun_name
if os.path.exists(is_set_disable): return True
php_vs = ('52','53','54','55','56','70','71','72','73','74')
php_vs = public.get_php_versions()
php_ini = "/www/server/php/{0}/etc/php.ini"
rep = "disable_functions\s*=\s*.*"
for pv in php_vs:
@@ -619,3 +685,8 @@ def clean_session():
except:return False
if __name__ == '__main__':
control_init()
+130 -6
View File
@@ -12,6 +12,7 @@ import json
import time
import datetime
import re
import sqlite3
import public
@@ -40,6 +41,43 @@ class Monitor:
return sites
def _statuscode_distribute_site(self, site_name):
try:
day_401 = 0
day_500 = 0
day_502 = 0
day_503 = 0
conn = None
ts = None
start_date, end_date = self.get_time_interval(time.localtime())
select_sql = "select time/100 as time1, sum(status_401), sum(status_500), sum(status_502), sum(status_503) from request_stat where time between {} and {}"\
.format(start_date, end_date)
db_path = os.path.join("/www/server/total/", "logs/{}/logs.db".format(site_name))
if os.path.isfile(db_path):
conn = sqlite3.connect(db_path)
ts = conn.cursor()
ts.execute(select_sql)
results = ts.fetchall()
if type(results) == list:
for result in results:
time_key = str(result[0])
day_401 = result[1]
day_500 = result[2]
day_502 = result[3]
day_503 = result[4]
except:
pass
finally:
if ts:
ts.close()
if conn:
conn.close()
return day_401, day_500, day_502, day_503
def _statuscode_distribute_site_old(self, site_name):
today = time.strftime('%Y-%m-%d', time.localtime())
path = '/www/server/total/total/' + site_name + '/request/' + today + '.json'
@@ -52,10 +90,10 @@ class Monitor:
for c in spdata.values():
for d in c:
if '401' == d: day_401 += c['401']
if '500' == d: day_500 += c['500']
if '502' == d: day_502 += c['502']
if '503' == d: day_503 += c['503']
if '401' == d: day_401 += c['401'] or 0
if '500' == d: day_500 += c['500'] or 0
if '502' == d: day_502 += c['502'] or 0
if '503' == d: day_503 += c['503'] or 0
return day_401, day_500, day_502, day_503
@@ -66,6 +104,10 @@ class Monitor:
for site in sites:
site_name = site['name']
day_401, day_500, day_502, day_503 = self._statuscode_distribute_site(site_name)
day_401 = day_401 or 0
day_500 = day_500 or 0
day_502 = day_502 or 0
day_503 = day_503 or 0
count_401 += day_401
count_500 += day_500
count_502 += day_502
@@ -177,8 +219,45 @@ class Monitor:
data.update(statuscode_distribute)
return data
# 获取蜘蛛数量分布
def get_spider(self, args):
request_data = {}
sites = public.M('sites').field('name').order("addtime").select();
for site_info in sites:
ts = None
conn = None
try:
site_name = site_info["name"]
start_date, end_date = self.get_time_interval(time.localtime())
select_sql = "select time, spider from request_stat where time between {} and {}"\
.format(start_date, end_date)
db_path = os.path.join("/www/server/total/", "logs/{}/logs.db".format(site_name))
if not os.path.isfile(db_path): continue
conn = sqlite3.connect(db_path)
ts = conn.cursor()
ts.execute(select_sql)
results = ts.fetchall()
if type(results) == list:
for result in results:
time_key = str(result[0])
hour = time_key[len(time_key)-2:]
value = result[1]
if hour not in request_data:
request_data[hour] = value
else:
request_data[hour] += value
except:
pass
finally:
if ts:
ts.close()
if conn:
conn.close()
return request_data
# 获取蜘蛛数量分布
def get_spider_old(self, args):
today = time.strftime('%Y-%m-%d', time.localtime())
sites = self._get_site_list()
@@ -210,8 +289,53 @@ class Monitor:
return {'load_five': load_five, 'cpu_count': cpu_count, 'up_flow': up_flow}
# 取每小时的请求数
def get_time_interval(self, local_time):
start = None
end = None
time_key_format = "%Y%m%d00"
start = int(time.strftime(time_key_format, local_time))
time_key_format = "%Y%m%d23"
end = int(time.strftime(time_key_format, local_time))
return start, end
def get_request_count_by_hour(self, args):
# 获取站点每小时的请求数据
request_data = {}
import sqlite3
sites = public.M('sites').field('name').order("addtime").select();
for site_info in sites:
ts = None
conn = None
try:
site_name = site_info["name"]
start_date, end_date = self.get_time_interval(time.localtime())
select_sql = "select time, req from request_stat where time between {} and {}"\
.format(start_date, end_date)
db_path = os.path.join("/www/server/total/", "logs/{}/logs.db".format(site_name))
if not os.path.isfile(db_path): continue
conn = sqlite3.connect(db_path)
ts = conn.cursor()
ts.execute(select_sql)
results = ts.fetchall()
if type(results) == list:
for result in results:
time_key = str(result[0])
hour = time_key[len(time_key)-2:]
value = result[1]
if hour not in request_data:
request_data[hour] = value
else:
request_data[hour] += value
except: pass
finally:
if ts:
ts.close()
if conn:
conn.close()
return request_data
# 取每小时的请求数
def get_request_count_by_hour_old(self, args):
today = time.strftime('%Y-%m-%d', time.localtime())
request_data = {}
+29 -30
View File
@@ -23,29 +23,29 @@ class nginx:
proxycontent = public.readFile(self.proxyfile)
for i in [[ngconfcontent,self.nginxconf],[proxycontent,self.proxyfile]]:
if not i[0]:
return public.returnMsg(False,"Can not find nginx config file [ {} ]".format(i[1]))
return public.return_msg_gettext(False,"Can not find nginx config file [ {} ]".format(i[1]))
unitrep = "[kmgKMG]"
conflist = []
ps = ["%s,%s" % (public.GetMsg("WORKER_PROCESSES"),public.GetMsg("WORKER_PROCESSES_AUTO")),
public.GetMsg("WORKER_CONNECTIONS"),
public.GetMsg("CONNECT_TIMEOUT_TIME"),
public.GetMsg("NGINX_ZIP"),
public.GetMsg("NGINX_ZIP_MIN"),
public.GetMsg("ZIP_COMP_LEVEL"),
public.GetMsg("UPLOAD_MAX_FILE"),
public.GetMsg("SERVER_NAME_HASH"),
public.GetMsg("CLIENT_HEADER_BUFF")]
ps = ["%s,%s" % (public.get_msg_gettext('Worker processes'),public.get_msg_gettext('Auto means automatic')),
public.get_msg_gettext('Worker connections'),
public.get_msg_gettext('Connection timeout'),
public.get_msg_gettext('Whether to enable compressed transmission'),
public.get_msg_gettext('Minimum file to compress'),
public.get_msg_gettext('Compression level'),
public.get_msg_gettext('Maximum file to upload'),
public.get_msg_gettext('Hash table size of server name'),
public.get_msg_gettext('Client header buffer size')]
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
k = re.search(rep, ngconfcontent)
if not k:
return public.returnMsg(False,"Get key {} False".format(k))
return public.return_msg_gettext(False,"Get key {} False".format(k))
k = k.group(1)
v = re.search(rep, ngconfcontent)
if not v:
return public.returnMsg(False,"Get value {} False".format(v))
return public.return_msg_gettext(False,"Get value {} False".format(v))
v = v.group(2)
if re.search(unitrep,v):
u = str.upper(v[-1])
@@ -60,18 +60,18 @@ class nginx:
kv = {"name":k,"value":v,"unit":u,"ps":psstr}
conflist.append(kv)
n += 1
ps = [public.GetMsg("CLIENT_BODY_BUFF")]
ps = [public.get_msg_gettext('Client body buffer')]
gets = ["client_body_buffer_size"]
n = 0
for i in gets:
rep = "(%s)\s+(\w+)" % i
k = re.search(rep, proxycontent)
if not k:
return public.returnMsg(False,"Get key {} False".format(k))
return public.return_msg_gettext(False,"Get key {} False".format(k))
k=k.group(1)
v = re.search(rep, proxycontent)
if not v:
return public.returnMsg(False,"Get value {} False".format(v))
return public.return_msg_gettext(False,"Get value {} False".format(v))
v = v.group(2)
if re.search(unitrep, v):
u = str.upper(v[-1])
@@ -86,7 +86,6 @@ class nginx:
kv = {"name":k, "value":v, "unit":u,"ps":psstr}
conflist.append(kv)
n+=1
print(conflist)
return conflist
def SetNginxValue(self,get):
@@ -109,10 +108,10 @@ class nginx:
rep = "%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.returnMsg(False, 'INIT_ARGS_ERR')
return public.return_msg_gettext(False, 'Parameter ERROR!')
else:
if not re.search("\d+", c["value"]):
return public.returnMsg(False, 'INIT_ARGS_ERR')
return public.return_msg_gettext(False, 'Parameter ERROR!')
if re.search(rep,ngconfcontent):
newconf = "%s %s" % (c["name"],c["value"])
ngconfcontent = re.sub(rep,newconf,ngconfcontent)
@@ -125,10 +124,10 @@ class nginx:
if (isError != True):
shutil.copyfile('/tmp/ng_file_bk.conf', self.nginxconf)
shutil.copyfile('/tmp/proxyfile_bk.conf', self.proxyfile)
return public.returnMsg(False, 'ERROR: <br><a style="color:red;">' + isError.replace("\n",
return public.return_msg_gettext(False, 'ERROR: <br><a style="color:red;">' + isError.replace("\n",
'<br>') + '</a>')
public.serviceReload()
return public.returnMsg(True, 'SET_SUCCESS')
return public.return_msg_gettext(True, 'Setup successfully!')
def add_nginx_access_log_format(self,args):
'''
@@ -151,14 +150,14 @@ class nginx:
self.del_nginx_access_log_format(args)
conf = public.readFile(self.nginxconf)
if not conf:
return public.returnMsg(False,'NGINX_CONF_NOT_EXISTS')
return public.return_msg_gettext(False,'Nginx configuration file does not exist!')
reg = 'http(\n|\s)+{'
conf = re.sub(reg,'http\n\t{'+data,conf)
public.writeFile(self.nginxconf,conf)
public.serviceReload()
return public.returnMsg(True, 'SET_SUCCESS')
return public.return_msg_gettext(True, 'Setup successfully!')
except:
return public.returnMsg(False, str(public.get_error_info()))
return public.return_msg_gettext(False, str(public.get_error_info()))
def del_nginx_access_log_format(self,args):
'''
@@ -169,13 +168,13 @@ class nginx:
log_format_name = args.log_format_name
conf = public.readFile(self.nginxconf)
if not conf:
return public.returnMsg(False, 'NGINX_CONF_NOT_EXISTS')
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)
conf = re.sub(reg,'',conf)
self._del_format_log_of_website(log_format_name)
public.writeFile(self.nginxconf,conf)
public.serviceReload()
return public.returnMsg(True, 'SET_SUCCESS')
return public.return_msg_gettext(True, 'Setup successfully!')
def del_all_log_format(self,args):
all_format = self.get_nginx_access_log_format(args)
@@ -223,7 +222,7 @@ class nginx:
reg = "#LOG_FORMAT_BEGIN.*"
conf = public.readFile(self.nginxconf)
if not conf:
return public.returnMsg(False, 'NGINX_CONF_NOT_EXISTS')
return public.return_msg_gettext(False, 'Nginx configuration file does not exist!')
data = re.findall(reg,conf)
format_name = [i.split('LOG_FORMAT_BEGIN_')[-1] for i in data]
format_log = {}
@@ -236,7 +235,7 @@ class nginx:
format_log[i] = self._process_log_format(tmp)
return format_log
except:
return public.returnMsg(False,public.get_error_info())
return public.return_msg_gettext(False,public.get_error_info())
def set_format_log_to_website(self,args):
'''
@@ -254,7 +253,7 @@ class nginx:
website_conf_file = '/www/server/panel/vhost/nginx/{}.conf'.format(site['name'])
conf = public.readFile(website_conf_file)
if not conf:
return public.returnMsg(False, 'NGINX_CONF_NOT_EXISTS')
return public.return_msg_gettext(False, 'Nginx configuration file does not exist!')
format_exist_reg = '(access_log\s+/www.*\.log).*;'
access_log = self.get_nginx_access_log(conf)
if not access_log:
@@ -267,9 +266,9 @@ class nginx:
continue
conf = re.sub(format_exist_reg,access_log,conf)
public.writeFile(website_conf_file,conf)
return public.returnMsg(True, 'SET_SUCCESS')
return public.return_msg_gettext(True, 'Setup successfully!')
except:
return public.returnMsg(False, str(public.get_error_info()))
return public.return_msg_gettext(False, str(public.get_error_info()))
def get_nginx_access_log(self,nginx_conf):
try:
+5 -5
View File
@@ -51,7 +51,7 @@ class ols:
conf = conf + '\n{} {}'.format(k,data[k])
public.writeFile(self._main_conf_path,conf)
public.serviceReload()
return public.returnMsg(True,"Setup Successfully")
return public.return_msg_gettext(True,"Setup Successfully!")
# 获取站点静态文件缓存配置
def get_static_cache(self,get):
@@ -101,7 +101,7 @@ class ols:
conf = conf.replace(old_cache,new_cache)
public.writeFile(self._detail_conf_path.format(sitename),conf)
public.serviceReload()
return public.returnMsg(True,'Setup Successfully')
return public.return_msg_gettext(True,'Setup Successfully!')
except Exception as e:
return e
@@ -180,14 +180,14 @@ RewriteRule (.*\.php)?$ - [E=Cache-Control:private]
f.write(conf)
f.close()
public.serviceReload()
return public.returnMsg(True,'Open successfully')
return public.return_msg_gettext(True,'Setup successfully!')
else:
bt_conf_rep = '#.*BTLSCACHE_BEGIN(.|\n)+BTLSCACHE_END#*\n'
conf = re.sub(bt_conf_rep,'',conf)
print(conf)
public.writeFile(file,conf)
public.serviceReload()
return public.returnMsg(True,'Close successfully')
return public.return_msg_gettext(True,'Setup successfully!')
def set_private_cache(self,get):
"""
@@ -215,7 +215,7 @@ RewriteRule (.*\.php)?$ - [E=Cache-Control:private]
conf = re.sub(bt_conf_rep,bt_conf,conf)
public.writeFile(file_name,conf)
public.serviceReload()
return public.returnMsg(True,'Setup Successfully')
return public.return_msg_gettext(True,'Setup successfully!')
def _get_site_domain(self):
site = []
+43 -43
View File
@@ -12,14 +12,14 @@ class Page():
#--------------------------
# 分页类 - JS回调版
#--------------------------
__PREV = public.GetMsg("PAGE")["PREV"]
__NEXT = public.GetMsg("PAGE")["NEXT"]
__START = public.GetMsg("PAGE")["START"]
__END = public.GetMsg("PAGE")["END"]
__COUNT_START = public.GetMsg("PAGE")["COUNT_START"]
__COUNT_END = public.GetMsg("PAGE")["COUNT_END"]
__FO = public.GetMsg("PAGE")["FO"]
__LINE = public.GetMsg("PAGE")["LINE"]
__PREV = public.get_msg_gettext('Prev')
__NEXT = public.get_msg_gettext('Next')
__START = public.get_msg_gettext('Start')
__END = public.get_msg_gettext('Last')
__COUNT_START = public.get_msg_gettext('Total')
__COUNT_END = ''
__FO = public.get_msg_gettext('From')
__LINE = ''
__LIST_NUM = 4
SHIFT = None #偏移量
ROW = None #每页行数
@@ -30,18 +30,19 @@ class Page():
__RTURN_JS = False #是否返回JS回调
__START_NUM = None #起始行
__END_NUM = None #结束行
def __init__(self):
tmp = public.GetMsg('PAGE');
if tmp:
self.__PREV = tmp['PREV'];
self.__NEXT = tmp['NEXT'];
self.__START = tmp['START'];
self.__END = tmp['END'];
self.__COUNT_START = tmp['COUNT_START'];
self.__COUNT_END = tmp['COUNT_END'];
self.__FO = tmp['FO'];
self.__LINE = tmp['LINE'];
pass
# tmp = public.get_msg_gettext('Depends on the following software, please install [{1}] first')
# if tmp:
# self.__PREV = tmp['Prev']
# self.__NEXT = tmp['Next']
# self.__START = tmp['Start']
# self.__END = tmp['Last']
# self.__COUNT_START = tmp['Total']
# self.__COUNT_END = tmp['']
# self.__FO = tmp['From']
# self.__LINE = tmp['']
def GetPage(self,pageInfo,limit = '1,2,3,4,5,6,7,8'):
# 取分页信息
@@ -56,9 +57,9 @@ class Page():
self.__COUNT_PAGE = self.__GetCountPage()
self.__URI = self.__SetUri(pageInfo['uri'])
self.SHIFT = self.__START_NUM - 1
keys = limit.split(',')
pages = {}
#起始页
pages['1'] = self.__GetStart()
@@ -70,23 +71,22 @@ class Page():
pages['4'] = self.__GetNext()
#尾页
pages['5'] = self.__GetEnd()
#当前显示页与总页数
pages['6'] = "<span class='Pnumber'>" + str(self.__C_PAGE) + "/" + str(self.__COUNT_PAGE) + "</span>"
#本页显示开始与结束行
pages['7'] = "<span class='Pline'>" + self.__FO + str(self.__START_NUM) + "-" + str(self.__END_NUM) + self.__LINE + "</span>"
#行数
pages['8'] = "<span class='Pcount'>" + self.__COUNT_START + str(self.__COUNT_ROW) + self.__COUNT_END + "</span>"
pages['8'] = "<span class='Pcount'>" + self.__COUNT_START +' '+ str(self.__COUNT_ROW) + self.__COUNT_END + "</span>"
#构造返回数据
retuls = '<div>';
for value in keys:
retuls += pages[value]
retuls +='</div>';
#返回分页数据
return retuls;
def __GetEnd(self):
#构造尾页
endStr = ""
@@ -98,7 +98,7 @@ class Page():
else:
endStr = "<a class='Pend' onclick='" + self.__RTURN_JS + "(" + str(self.__COUNT_PAGE) + ")'>" + self.__END + "</a>"
return endStr
def __GetNext(self):
#构造下一页
nextStr = ""
@@ -107,11 +107,11 @@ class Page():
else:
if self.__RTURN_JS == "":
nextStr = "<a class='Pnext' href='" + self.__URI + "p=" + str(self.__C_PAGE + 1) + "'>" + self.__NEXT + "</a>"
else:
else:
nextStr = "<a class='Pnext' onclick='" + self.__RTURN_JS + "(" + str(self.__C_PAGE + 1) + ")'>" + self.__NEXT + "</a>"
return nextStr
def __GetPages(self):
#构造分页
pages = ''
@@ -130,11 +130,11 @@ class Page():
pages += "<a class='Pnum' href='" + self.__URI + "p=" + str(page) + "'>" + str(page) + "</a>"
else:
pages += "<a class='Pnum' onclick='" + self.__RTURN_JS + "(" + str(page) + ")'>" + str(page) + "</a>"
#当前页
if self.__C_PAGE > 0:
pages += "<span class='Pcurrent'>" + str(self.__C_PAGE) + "</span>"
#当前页之后
if self.__C_PAGE <= self.__LIST_NUM:
num = self.__LIST_NUM + (self.__LIST_NUM - self.__C_PAGE) + 1
@@ -148,11 +148,11 @@ class Page():
break;
if self.__RTURN_JS == "":
pages += "<a class='Pnum' href='" + self.__URI + "p=" + str(page) + "'>" + str(page) + "</a>"
else:
else:
pages += "<a class='Pnum' onclick='" + self.__RTURN_JS + "(" + str(page) + ")'>" + str(page) + "</a>"
return pages;
def __GetPrev(self):
#构造上一页
startStr = ''
@@ -161,10 +161,10 @@ class Page():
else:
if self.__RTURN_JS == "":
startStr = "<a class='Ppren' href='" + self.__URI + "p=" + str(self.__C_PAGE - 1) + "'>" + self.__PREV + "</a>"
else:
else:
startStr = "<a class='Ppren' onclick='" + self.__RTURN_JS + "(" + str(self.__C_PAGE - 1) + ")'>" + self.__PREV + "</a>"
return startStr
def __GetStart(self):
#构造起始分页
startStr = ''
@@ -176,27 +176,27 @@ class Page():
else:
startStr = "<a class='Pstart' onclick='" + self.__RTURN_JS + "(1)'>" + self.__START + "</a>"
return startStr;
def __GetCpage(self,p):
#取当前页
if p:
return p
return 1
def __StartRow(self):
#从多少行开始
return (self.__C_PAGE - 1) * self.ROW + 1
def __EndRow(self):
#从多少行结束
if self.ROW > self.__COUNT_ROW:
return self.__COUNT_ROW
return self.__C_PAGE * self.ROW
def __GetCountPage(self):
#取总页数
return int(math.ceil(self.__COUNT_ROW / float(self.ROW)))
def __SetUri(self,request_uri):
#构造URI
try:
@@ -207,4 +207,4 @@ class Page():
else:
if request_uri[-1] != '&': request_uri += '&'
return request_uri
except: return '';
except: return ''
+34 -20
View File
@@ -33,13 +33,27 @@ class panelApi:
def login_for_app(self,get):
from BTPanel import cache
import uuid
tid = get.tid
if(len(tid) != 12): return public.returnMsg(False,'Invalid login key')
if(len(tid) != 32): return public.return_msg_gettext(False,'Invalid login key1')
session_id = cache.get(tid)
if not session_id: return public.returnMsg(False,'The specified key does not exist or has expired')
if(len(session_id) != 64): return public.returnMsg(False,'Invalid login key')
cache.set(session_id,'True',120)
return public.returnMsg(True,'Scan code successfully, log in!')
if not session_id: return public.return_msg_gettext(False,'The specified key does not exist or has expired1')
if(len(session_id) != 64): return public.return_msg_gettext(False,'Invalid login key2')
try:
if not os.path.exists('/www/server/panel/data/app_login_check.pl'):return public.returnMsg(False,'Invalid login key3')
key, init_time, tid2, status = public.readFile('/www/server/panel/data/app_login_check.pl').split(':')
if session_id!=key:return public.returnMsg(False,'Invalid login key4')
if tid != tid2: return public.returnMsg(False, 'The specified key does not exist or has expired5')
if time.time() - float(init_time) > 60:
return public.returnMsg(False, 'QR code validity time expired6')
cache.set(session_id,public.md5(uuid.UUID(int=uuid.getnode()).hex),120)
import uuid
data = key + ':' + init_time + ':' + tid2 + ':' + uuid.UUID(int=uuid.getnode()).hex[-12:]
public.writeFile("/www/server/panel/data/app_login_check.pl", data)
return public.return_msg_gettext(True,'Scan code successfully, log in!')
except:
os.remove("/www/server/panel/data/app_login_check.pl")
return public.return_msg_gettext(False, 'Invalid login key')
def get_api_config(self):
tmp = public.ReadFile(self.save_path)
@@ -81,11 +95,11 @@ class panelApi:
bind = self.get_bind_token(args.bind_token)
if bind['token'] != args.bind_token:
return 'The current QR code has expired, please refresh the page and rescan the code!'
return public.get_msg_gettext('The current QR code has expired, please refresh the page and rescan the code!')
apps = self.get_apps()
if len(apps) >= self.max_bind:
return 'This server is bound to a maximum of {} devices, which has reached the limit!'.format(self.max_bind)
return public.get_msg_gettext('This server is bound to a maximum of {} devices, which has reached the limit!',(self.max_bind,))
bind['status'] = 1
bind['brand'] = args.client_brand
@@ -94,8 +108,8 @@ class panelApi:
return 1
def get_bind_status(self,args):
if not public.cache_get("get_bind_status"):
public.cache_set("get_bind_status",1,60)
if not public.cache_get(public.Md5(os.uname().version)):
public.cache_set(public.Md5(os.uname().version),1,60)
bind = self.get_bind_token(args.bind_token)
return bind
@@ -133,10 +147,10 @@ class panelApi:
def add_bind_app(self,args):
bind = self.get_bind_token(args.bind_token)
if bind['status'] == 0:
return public.returnMsg(False,'Failed verification!')
return public.return_msg_gettext(False,'Failed verification!')
apps = self.get_apps()
if len(apps) >= self.max_bind:
return public.returnMsg(False,'A server allows up to {} device bindings!'.format(self.max_bind))
return public.return_msg_gettext(False,'A server allows up to {} device bindings!'.format(self.max_bind))
args.bind_app = args.bind_token
self.remove_bind_app(args)
@@ -144,7 +158,7 @@ class panelApi:
data['apps'].append(bind)
self.save_api_config(data)
self.remove_bind_token(args.bind_token)
return public.returnMsg(True,'Bind successfully!')
return public.return_msg_gettext(True,'Bind successfully!')
def remove_bind_token(self,bind_token):
data = self.get_api_config()
@@ -168,7 +182,7 @@ class panelApi:
s_file = '/dev/shm/{}'.format(args.bind_app)
if os.path.exists(s_file):
os.remove(s_file)
return public.returnMsg(True,'successfully deleted!')
return public.return_msg_gettext(True,'Successfully deleted!')
def get_bind_token(self,token = None):
data = self.get_api_config()
@@ -203,13 +217,13 @@ class panelApi:
def set_token(self,get):
if 'request_token' in get: return public.returnMsg(False,'Cannot configure API through API interface')
if 'request_token' in get: return public.return_msg_gettext(False,'Cannot configure API through API interface')
data = self.get_api_config()
if get.t_type == '1':
token = public.GetRandomString(32)
data['token'] = public.md5(token)
data['token_crypt'] = public.en_crypt(data['token'],token).decode('utf-8')
public.WriteLog('SET_API','Regenerate API-Token')
public.write_log_gettext('API configuration','Regenerate API-Token')
elif get.t_type == '2':
data['open'] = not data['open']
stats = {True:'Open',False:'Close'}
@@ -217,19 +231,19 @@ class panelApi:
token = public.GetRandomString(32)
data['token'] = public.md5(token)
data['token_crypt'] = public.en_crypt(data['token'],token).decode('utf-8')
public.WriteLog('SET_API','%s API interface' % stats[data['open']])
public.write_log_gettext('API configuration','{} API interface',(stats[data['open']],))
token = stats[data['open']] + ' success!'
elif get.t_type == '3':
data['limit_addr'] = get.limit_addr.split('\n')
public.WriteLog('SET_API','Change IP limit to [%s]' % get.limit_addr)
public.write_log_gettext('API configuration','Change IP limit to [{}]',(get.limit_addr,))
token ='Saved successfully!'
self.save_api_config(data)
return public.returnMsg(True,token)
return public.return_msg_gettext(True,token)
def get_tmp_token(self,get):
if not 'request_token' in get: return public.returnMsg(False,'Temporary keys can only be obtained through the API interface')
if not 'request_token' in get: return public.return_msg_gettext(False,'Temporary keys can only be obtained through the API interface')
data = self.get_api_config()
data['tmp_token'] = public.GetRandomString(64)
data['tmp_time'] = time.time()
self.save_api_config(data)
return public.returnMsg(True,data['tmp_token'])
return public.return_msg_gettext(True,data['tmp_token'])
+30 -21
View File
@@ -23,12 +23,12 @@ class panelAuth:
def create_serverid(self,get):
try:
userPath = 'data/userInfo.json'
if not os.path.exists(userPath): return public.returnMsg(False,'LOGIN_FIRST')
if not os.path.exists(userPath): return public.return_msg_gettext(False,'Please login with account first')
tmp = public.readFile(userPath)
if len(tmp) < 2: tmp = '{}'
data = json.loads(tmp)
data['uid'] = data['id']
if not data: return public.returnMsg(False,'LOGIN_FIRST')
if not data: return public.return_msg_gettext(False,'Please login with account first')
if not 'server_id' in data:
s1 = public.get_mac_address() + public.get_hostname()
s2 = self.get_cpuname()
@@ -36,7 +36,7 @@ class panelAuth:
data['server_id'] = serverid
public.writeFile(userPath,json.dumps(data))
return data
except: return public.returnMsg(False,'LOGIN_FIRST')
except: return public.return_msg_gettext(False,'Please login with account first')
def create_plugin_other_order(self,get):
@@ -63,22 +63,24 @@ class panelAuth:
def get_plugin_price(self, get):
try:
userPath = 'data/userInfo.json'
if not 'pluginName' in get and not 'product_id' in get: return public.returnMsg(False,'INIT_ARGS_ERR')
if not os.path.exists(userPath): return public.returnMsg(False,'LOGIN_FIRST')
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/prices'.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.returnMsg(False,data['msg'])
return public.return_msg_gettext(False,data['msg'])
# if len(data['res']) == 6:
# return data['res'][3:]
return data['res']
except:
del(session['get_product_list'])
return public.returnMsg(False,'Syncing information, please try again!\n' + public.get_error_info())
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)
@@ -104,6 +106,7 @@ class panelAuth:
params['cycle_unit'] = get.cycle_unit
params['product_id'] = get.pid
params['src'] = 2
params['trigger_entry'] = get.source
params['pay_channel'] = 2
params['charge_type'] = get.charge_type
env_info = public.fetch_env_info()
@@ -111,7 +114,7 @@ class panelAuth:
params['server_id'] = env_info['install_code']
data = self.send_cloud('{}/api/order/product/create'.format(self.__official_url), params)
if not data['success']:
return public.returnMsg(False,data['res'])
return public.return_msg_gettext(False,data['res'])
return data['res']
def get_stripe_session_id(self,get):
@@ -125,7 +128,7 @@ class panelAuth:
params = {}
params['id'] = get.id
data = self.send_cloud('check_product_pays', params)
if not data: return public.returnMsg(False,'AJAX_CONN_ERR')
if not data: return public.return_msg_gettext(False,'Fail to connect to the server!')
if data['status'] == True:
self.flush_pay_status(get)
if 'get_product_bay' in session: del(session['get_product_bay'])
@@ -134,8 +137,8 @@ class panelAuth:
def flush_pay_status(self,get):
if 'get_product_bay' in session: del(session['get_product_bay'])
data = self.get_plugin_list(get)
if not data: return public.returnMsg(False,'AJAX_CONN_ERR')
return public.returnMsg(True,'FLUSH_STATUS_SUCCESS')
if not data: return public.return_msg_gettext(False,'Fail to connect to the server!')
return public.return_msg_gettext(True,'Flush status success')
def get_renew_code(self):
pass
@@ -163,7 +166,7 @@ class panelAuth:
params = {}
params['pid'] = getattr(get,'pid',0)
data = self.send_cloud('get_re_order_status', params)
if not data: return public.returnMsg(False,'AJAX_CONN_ERR')
if not data: return public.return_msg_gettext(False,'Fail to connect to the server!')
if data['status'] == True:
self.flush_pay_status(get)
if 'get_product_bay' in session: del(session['get_product_bay'])
@@ -192,8 +195,8 @@ class panelAuth:
data = self.send_cloud('{}/api/order/product/create'.format(self.__official_url), params)
session['focre_cloud'] = True
if data['success']:
return public.returnMsg(True,'Activate successfully')
return public.returnMsg(False, 'Activate failed')
return public.return_msg_gettext(True,'Activate successfully')
return public.return_msg_gettext(False, 'Activate failed')
def send_cloud(self,cloudURL,params):
try:
@@ -293,16 +296,21 @@ class panelAuth:
return []
if not data['success']: return []
data = data['res']
return [i for i in data['list'] if i['status'] != 'activated']
# return [i for i in data['list'] if i['status'] != 'activated' and get.pid == i['product_id']]
res = list()
for i in data['list']:
if i['status'] != 'activated' and str(get.pid) == str(i['product_id']):
res.append(i)
return res
def auth_activate(self,get):
params = {}
params['serial_no'] = get.serial_no
params['environment_info'] = json.dumps(public.fetch_env_info())
data = self.send_cloud('{}/api/authorize/product/activate'.format(self.__official_url), params)
if not data['success']: return public.returnMsg(False,'Activate Failed')
if not data['success']: return public.return_msg_gettext(False,'Activate Failed')
session['focre_cloud'] = True
return public.returnMsg(True,'Activate successfully')
return public.return_msg_gettext(True,'Activate successfully')
def renew_product_auth(self,get):
params = {}
@@ -311,6 +319,7 @@ class panelAuth:
params['cycle'] = get.cycle
params['cycle_unit'] = get.cycle_unit
params['src'] = 2
params['trigger_entry'] = get.source
params['environment_info'] = json.dumps(public.fetch_env_info())
if hasattr(get,'coupon_id') and get.pay_channel == '10':
params['coupon_id'] = get.coupon_id
@@ -319,8 +328,8 @@ class panelAuth:
# 使用抵扣券续费直接返回续费结果
if get.pay_channel == '10':
if not data['success']:
return public.returnMsg(False, 'Renew Failed')
return public.returnMsg(True,'Renew successfully')
return public.return_msg_gettext(False, 'Renew Failed')
return public.return_msg_gettext(True,'Renew successfully')
# 使用支付续费返回stripe的请求数据
return data['res']
@@ -335,5 +344,5 @@ class panelAuth:
session['focre_cloud'] = True
# 使用抵扣券续费直接返回续费结果
if not data['success']:
return public.returnMsg(False, 'Apply Failed')
return public.returnMsg(True,'Apply successfully')
return public.return_msg_gettext(False, 'Apply Failed')
return public.return_msg_gettext(True,'Apply successfully')
+117 -82
View File
@@ -56,12 +56,12 @@ class backup:
def echo_start(self):
print("="*90)
print("|-"+public.getMsg('START_BACKUP')+"[{}]".format(public.format_date()))
print("|-"+public.get_msg_gettext('Start backup')+"[{}]".format(public.format_date()))
print("="*90)
def echo_end(self):
print("="*90)
print("|-"+public.getMsg('BACKUP_COMPLETED')+"[{}]".format(public.format_date()))
print("|-"+public.get_msg_gettext('Backup completed')+"[{}]".format(public.format_date()))
print("="*90)
print("\n")
@@ -98,8 +98,8 @@ class backup:
def GetDiskInfo2(self):
#取磁盘分区信息
temp = public.ExecShell("df -T -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev")[0]
tempInodes = public.ExecShell("df -i -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev")[0]
temp = public.ExecShell("df -T -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev|grep -v overlay")[0]
tempInodes = public.ExecShell("df -i -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev|grep -v overlay")[0]
temp1 = temp.split('\n')
tempInodes1 = tempInodes.split('\n')
diskInfo = []
@@ -154,9 +154,9 @@ class backup:
error_msg = ""
self.echo_start()
if not os.path.exists(spath):
error_msg= public.getMsg('BACKUP_DIR_NOT_EXIST',(spath,))
error_msg= public.get_msg_gettext('The specified directory {} does not exist!',(spath,))
self.echo_error(error_msg)
self.send_failture_notification(error_msg)
self.send_failture_notification(error_msg, target=spath)
return False
if spath[-1] == '/':
@@ -170,25 +170,25 @@ class backup:
if not self.backup_path_to(spath,dfile,exclude):
if self._error_msg:
error_msg = self._error_msg
self.send_failture_notification(error_msg)
self.send_failture_notification(error_msg, target=spath)
return False
if self._cloud:
self.echo_info(public.getMsg("BACKUP_UPLOADING",(self._cloud._title,)))
self.echo_info(public.get_msg_gettext('Uploading to {}, please wait ...',(self._cloud._title,)))
if self._cloud.upload_file(dfile,'path'):
self.echo_info(public.getMsg("BACKUP_UPLOAD_SUCCESS",(self._cloud._title,)))
self.echo_info(public.get_msg_gettext('Successfully uploaded to {}',(self._cloud._title,)))
else:
if hasattr(self._cloud, "error_msg"):
if self._cloud.error_msg:
error_msg = self._cloud.error_msg
if not error_msg:
error_msg = public.getMsg('BACKUP_UPLOAD_FAILED')
error_msg = public.get_msg_gettext('File upload failed, skip this backup!')
self.echo_error(error_msg)
if os.path.exists(dfile):
os.remove(dfile)
remark = "Backup to " + self._cloud._title
self.send_failture_notification(error_msg, remark=remark)
self.send_failture_notification(error_msg, target=spath, remark=remark)
return False
filename = dfile
@@ -228,9 +228,9 @@ class backup:
if _not_save_local:
if os.path.exists(dfile):
os.remove(dfile)
self.echo_info(public.getMsg("BACKUP_DEL",(dfile,)))
self.echo_info(public.get_msg_gettext('User settings do not retain local backups, deleted {}',(dfile,)))
else:
self.echo_info(public.getMsg('KEEP_LOCAL'))
self.echo_info(public.get_msg_gettext('Local backup has been kept'))
if not self._cloud:
backups = public.M('backup').where("type=? and pid=? and name=? and filename NOT LIKE '%|%'",('2',0,spath)).field('id,name,filename').select()
@@ -239,15 +239,16 @@ class backup:
self.delete_old(backups,save,'path')
self.echo_end()
self.save_backup_status(True, target=spath)
return dfile
#清理过期备份文件
def delete_old(self,backups,save,data_type = None):
if type(backups) == str:
self.echo_info(public.getMsg('BACKUP_CLEAN_ERR',(backups,)))
self.echo_info(public.get_msg_gettext('Failed to clean expired backup, error: {}',(backups,)))
return
self.echo_info(public.getMsg('BACKUP_KEEP',(str(save),)))
self.echo_info(public.get_msg_gettext('Keep the latest number of backups: {} copies',(str(save),)))
num = len(backups) - int(save)
if num > 0:
self._get_local_backdir()
@@ -264,11 +265,11 @@ class backup:
os.remove(backup['filename'])
except:
pass
self.echo_info(public.getMsg("BACKUP_CLEAN",(backup['filename'],)))
self.echo_info(public.get_msg_gettext('Expired backup files have been cleaned from disk: {}',(backup['filename'],)))
#尝试删除远程文件
if self._cloud:
self._cloud.delete_file(backup['name'],data_type)
self.echo_info(public.getMsg("BACKUP_CLEAN_REMOVE",(self._cloud._title,backup['name'])))
self.echo_info(public.get_msg_gettext('Expired backup files have been cleaned from {}: {}',(self._cloud._title,backup['name'])))
#从数据库清理
public.M('backup').where('id=?',(backup['id'],)).delete()
@@ -282,7 +283,7 @@ class backup:
#压缩目录
def backup_path_to(self,spath,dfile,exclude = [],siteName = None):
if not os.path.exists(spath):
self.echo_error(public.getMsg('BACKUP_DIR_NOT_EXIST',(spath,)))
self.echo_error(public.get_msg_gettext('The specified directory {} does not exist!',(spath,)))
return False
if spath[-1] == '/':
@@ -301,55 +302,55 @@ class backup:
exclude_config = "Not set"
if siteName:
self.echo_info(public.getMsg('BACKUP_SITE',(siteName,)))
self.echo_info(public.getMsg('WEBSITE_DIR',(spath,)))
self.echo_info(public.get_msg_gettext('Backup site: {}',(siteName,)))
self.echo_info(public.get_msg_gettext('Website document root: {}',(spath,)))
else:
self.echo_info(public.getMsg('BACKUP_DIR',(spath,)))
self.echo_info(public.get_msg_gettext('Backup directory: {}',(spath,)))
self.echo_info(public.getMsg(
"DIR_SIZE",
self.echo_info(public.get_msg_gettext(
'Directory size: {}',
(str(public.to_size(p_size),))
))
self.echo_info(public.getMsg('BACKUP_EXCLUSION',(exclude_config,)))
self.echo_info(public.get_msg_gettext('Exclusion setting: {}',(exclude_config,)))
disk_path,disk_free,disk_inode = self.get_disk_free(dfile)
self.echo_info(public.getMsg(
"PARTITION_INFO",
self.echo_info(public.get_msg_gettext(
'Partition {} available disk space is: {}, available Inode is: {}',
(disk_path,str(public.to_size(disk_free)),str(disk_inode))
))
if disk_path:
if disk_free < p_size:
self.echo_error(public.getMsg(
"PARTITION_LESS_THEN",
self.echo_error(public.get_msg_gettext(
'The available disk space of the target partition is less than {}, and the backup cannot be completed. Please increase the disk capacity or change the default backup directory on the settings page!',
(str(public.to_size(p_size)),)
))
return False
if disk_inode < self._inode_min:
self.echo_error(public.getMsg(
"INODE_LESS_THEN",
self.echo_error(public.get_msg_gettext(
'The available Inode of the target partition is less than {}, and the backup cannot be completed. Please increase the disk capacity or change the default backup directory on the settings page!',
(str(self._inode_min,))
))
return False
stime = time.time()
self.echo_info(public.getMsg("START_COMPRESS",(public.format_date(times=stime),)))
self.echo_info(public.get_msg_gettext('Start compressing files: {}',(public.format_date(times=stime),)))
if os.path.exists(dfile):
os.remove(dfile)
public.ExecShell("cd " + os.path.dirname(spath) + " && tar zcvf '" + dfile + "' " + self._exclude + " '" + dirname + "' 2>{err_log} 1> /dev/null".format(err_log = self._err_log))
tar_size = os.path.getsize(dfile)
if tar_size < 1:
self.echo_error(public.getMsg('ZIP_ERR'))
self.echo_error(public.get_msg_gettext('Compression failed!'))
self.echo_info(public.readFile(self._err_log))
return False
compression_time = str('{:.2f}'.format(time.time() - stime))
self.echo_info(public.getMsg(
'COMPRESS_TIME',
self.echo_info(public.get_msg_gettext(
'Compression completed, took {} seconds, compressed package size: {}',
(compression_time,str(public.to_size(tar_size)))
))
if siteName:
self.echo_info(public.getMsg("WEBSITE_BACKUP_TO",(dfile,)))
self.echo_info(public.get_msg_gettext('Site backed up to: {}',(dfile,)))
else:
self.echo_info(public.getMsg("DIR_BACKUP_TO",(dfile,)))
self.echo_info(public.get_msg_gettext('Directory has been backed up to: {}',(dfile,)))
if os.path.exists(self._err_log):
os.remove(self._err_log)
return dfile
@@ -366,25 +367,25 @@ class backup:
if not self.backup_path_to(spath,dfile,exclude,siteName=siteName):
if self._error_msg:
error_msg = self._error_msg
self.send_failture_notification(error_msg)
self.send_failture_notification(error_msg, target=siteName)
return False
if self._cloud:
self.echo_info(public.getMsg("BACKUP_UPLOADING",(self._cloud._title,)))
self.echo_info(public.get_msg_gettext('Uploading to {}, please wait ...',(self._cloud._title,)))
if self._cloud.upload_file(dfile,'site'):
self.echo_info(public.getMsg("BACKUP_UPLOAD_SUCCESS",(self._cloud._title,)))
self.echo_info(public.get_msg_gettext('Successfully uploaded to {}',(self._cloud._title,)))
else:
if hasattr(self._cloud, "error_msg"):
if self._cloud.error_msg:
error_msg = self._cloud.error_msg
if not error_msg:
error_msg = public.getMsg('BACKUP_UPLOAD_FAILED')
error_msg = public.get_msg_gettext('File upload failed, skip this backup!')
self.echo_error(error_msg)
if os.path.exists(dfile):
os.remove(dfile)
remark = "Backup to " + self._cloud._title
self.send_failture_notification(error_msg, remark=remark)
self.send_failture_notification(error_msg, target=siteName, remark=remark)
return False
filename = dfile
@@ -424,9 +425,9 @@ class backup:
if _not_save_local:
if os.path.exists(dfile):
os.remove(dfile)
self.echo_info(public.getMsg("BACKUP_DEL",(dfile,)))
self.echo_info(public.get_msg_gettext('User settings do not retain local backups, deleted {}',(dfile,)))
else:
self.echo_info(public.getMsg('KEEP_LOCAL'))
self.echo_info(public.get_msg_gettext('Local backup has been kept'))
#清理多余备份
if not self._cloud:
@@ -450,6 +451,7 @@ class backup:
if not result:
failture_count += 1
results.append((database['name'], result, self._error_msg,))
self.save_backup_status(result, target=database['name'], msg=self._error_msg)
if failture_count > 0:
self.send_all_failture_notification("database", results)
@@ -467,6 +469,7 @@ class backup:
if not result:
failture_count += 1
results.append((site['name'], result, self._error_msg,))
self.save_backup_status(result, target=site['name'], msg=self._error_msg)
if failture_count > 0:
self.send_all_failture_notification("site", results)
@@ -519,58 +522,78 @@ class backup:
os.makedirs(dpath,384)
error_msg = ""
import panelMysql
if not self._db_mysql:self._db_mysql = panelMysql.panelMysql()
# ----- 判断是否为远程数据库START @author hwliang<2021-01-08>--------
db_find = public.M('databases').where("name=?",(db_name,)).find()
conn_config = {}
self._db_mysql = public.get_mysql_obj(db_name)
is_cloud_db = db_find['db_type'] in ['1',1,'2',2]
if is_cloud_db:
# 连接远程数据库
if db_find['sid']:
conn_config = public.M('database_servers').where('id=?',db_find['sid']).find()
if not 'db_name' in conn_config: conn_config['db_name'] = None
else:
conn_config = json.loads(db_find['conn_config'])
conn_config['db_port'] = str(int(conn_config['db_port']))
self._db_mysql.set_host(conn_config['db_host'],int(conn_config['db_port']),conn_config['db_name'],conn_config['db_user'],conn_config['db_password'])
# ----- 判断是否为远程数据库END @author hwliang<2021-01-08>------------
d_tmp = self._db_mysql.query("select sum(DATA_LENGTH)+sum(INDEX_LENGTH) from information_schema.tables where table_schema='%s'" % db_name)
try:
p_size = self.map_to_list(d_tmp)[0][0]
except:
error_msg = public.getMsg('DB_CONN_ERR')
error_msg = public.get_msg_gettext('The database connection is abnormal. Please check whether the root user authority or database configuration parameters are correct.')
self.echo_error(error_msg)
self.send_failture_notification(error_msg)
self.send_failture_notification(error_msg, target=db_name)
return False
if p_size == None:
error_msg = public.getMsg('DB_BACKUP_ERR',(db_name,))
error_msg = public.get_msg_gettext('The specified database [ {} ] has no data!',(db_name,))
self.echo_error(error_msg)
self.send_failture_notification(error_msg)
self.send_failture_notification(error_msg, target=db_name)
return False
character = public.get_database_character(db_name)
self.echo_info(public.getMsg('DB_BACKUP',(db_name,)))
self.echo_info(public.getMsg("DB_SIZE",(public.to_size(p_size),)))
self.echo_info(public.getMsg("DB_CHARACTER",(character,)))
self.echo_info(public.get_msg_gettext('Backup database:{}',(db_name,)))
self.echo_info(public.get_msg_gettext('Database size: {}',(public.to_size(p_size),)))
self.echo_info(public.get_msg_gettext('Database character set: {}',(character,)))
disk_path,disk_free,disk_inode = self.get_disk_free(dfile)
self.echo_info(public.getMsg(
"PARTITION_INFO",(
self.echo_info(public.get_msg_gettext(
'Partition {} available disk space is: {}, available Inode is: {}',(
disk_path,str(public.to_size(disk_free)),str(disk_inode)
)
))
if disk_path:
if disk_free < p_size:
error_msg = public.getMsg("PARTITION_LESS_THEN",(
error_msg = public.get_msg_gettext('The available disk space of the target partition is less than {}, and the backup cannot be completed. Please increase the disk capacity or change the default backup directory on the settings page!',(
str(public.to_size(p_size),)
))
self.echo_error(error_msg)
self.send_failture_notification(error_msg)
self.send_failture_notification(error_msg, target=db_name)
return False
if disk_inode < self._inode_min:
error_msg = public.getMsg("INODE_LESS_THEN",(self._inode_min,))
error_msg = public.get_msg_gettext('The available Inode of the target partition is less than {}, and the backup cannot be completed. Please increase the disk capacity or change the default backup directory on the settings page!',(self._inode_min,))
self.echo_error(error_msg)
self.send_failture_notification(error_msg)
self.send_failture_notification(error_msg, target=db_name)
return False
stime = time.time()
self.echo_info(public.getMsg("EXPORT_DB",(public.format_date(times=stime),)))
self.echo_info(public.get_msg_gettext('Start exporting database: {}',(public.format_date(times=stime),)))
if os.path.exists(dfile):
os.remove(dfile)
#self.mypass(True)
mysqldump_bin = public.get_mysqldump_bin()
try:
password = public.M('config').where('id=?',(1,)).getField('mysql_root')
os.environ["MYSQL_PWD"] = password
backup_cmd = "/www/server/mysql/bin/mysqldump -E -R --default-character-set="+ character +" --force --hex-blob --opt " + db_name + " -u root" + " 2>"+self._err_log+"| gzip > " + dfile
if not is_cloud_db:
# 本地数据库 @author hwliang<2021-01-08>
password = public.M('config').where('id=?',(1,)).getField('mysql_root')
os.environ["MYSQL_PWD"] = password
backup_cmd = mysqldump_bin + " -E -R --default-character-set="+ character +" --force --hex-blob --opt " + db_name + " -u root" + " 2>"+self._err_log+"| gzip > " + dfile
else:
# 远程数据库 @author hwliang<2021-01-08>
os.environ["MYSQL_PWD"] = conn_config['db_password']
backup_cmd = mysqldump_bin + " -h " + conn_config['db_host'] + " -P " + conn_config['db_port'] + " -E -R --default-character-set="+ character +" --force --hex-blob --opt " + db_name + " -u " + conn_config['db_user'] + " 2>"+self._err_log+"| gzip > " + dfile
public.ExecShell(backup_cmd)
except Exception as e:
raise
@@ -580,27 +603,27 @@ class backup:
#self.mypass(False)
gz_size = os.path.getsize(dfile)
if gz_size < 400:
error_msg = public.getMsg("EXPORT_DB_ERR")
error_msg = public.get_msg_gettext('Database export failed!')
self.echo_error(error_msg)
self.send_failture_notification(error_msg)
self.send_failture_notification(error_msg, target=db_name)
self.echo_info(public.readFile(self._err_log))
return False
compressed_time = str('{:.2f}'.format(time.time() - stime))
self.echo_info(
public.getMsg("COMPRESS_TIME",(str(compressed_time),
public.get_msg_gettext('Compression completed, took {} seconds, compressed package size: {}',(str(compressed_time),
str(public.to_size(gz_size))
))
)
if self._cloud:
self.echo_info(public.getMsg("BACKUP_UPLOADING",(self._cloud._title,)))
self.echo_info(public.get_msg_gettext('Uploading to {}, please wait ...',(self._cloud._title,)))
if self._cloud.upload_file(dfile, 'database'):
self.echo_info(public.getMsg("BACKUP_UPLOAD_SUCCESS",(self._cloud._title,)))
self.echo_info(public.get_msg_gettext('Successfully uploaded to {}',(self._cloud._title,)))
else:
if hasattr(self._cloud, "error_msg"):
if self._cloud.error_msg:
error_msg = self._cloud.error_msg
if not error_msg:
error_msg = public.getMsg('BACKUP_UPLOAD_FAILED')
error_msg = public.get_msg_gettext('File upload failed, skip this backup!')
self.echo_error(error_msg)
if os.path.exists(dfile):
os.remove(dfile)
@@ -612,7 +635,7 @@ class backup:
filename = dfile
if self._cloud:
filename = dfile + '|' + self._cloud._name + '|' + fname
self.echo_info(public.getMsg("DB_BACKUP_TO",(dfile,)))
self.echo_info(public.get_msg_gettext('Database has been backed up to: {}',(dfile,)))
if os.path.exists(self._err_log):
os.remove(self._err_log)
@@ -651,9 +674,9 @@ class backup:
if _not_save_local:
if os.path.exists(dfile):
os.remove(dfile)
self.echo_info(public.getMsg("BACKUP_DEL",(dfile,)))
self.echo_info(public.get_msg_gettext('User settings do not retain local backups, deleted {}',(dfile,)))
else:
self.echo_info(public.getMsg('KEEP_LOCAL'))
self.echo_info(public.get_msg_gettext('Local backup has been kept'))
#清理多余备份
if not self._cloud:
@@ -662,6 +685,7 @@ class backup:
backups = public.M('backup').where('type=? and pid=? and filename LIKE "%{}%"'.format(self._cloud._name),('1',pid)).field('id,name,filename').select()
self.delete_old(backups,save,'database')
self.echo_end()
self.save_backup_status(True, target=db_name)
return dfile
def generate_success_title(self, task_name):
@@ -669,10 +693,10 @@ class backup:
sm = send_mail()
now = public.format_date(format="%Y-%m-%d %H:%M")
server_ip = sm.GetLocalIp()
title = public.getMsg("BACKUP_TASK_TITLE",(server_ip, task_name))
title = public.get_msg_gettext('{}-{} The task was executed successfully',(server_ip, task_name))
return title
def generate_failture_title(self):
def generate_failture_title(self, task_name):
title = "aaPanel backup task failed reminder"
return title
@@ -743,13 +767,13 @@ class backup:
""" 通过计划任务名称查找计划任务配置参数 """
try:
cron_info = public.M('crontab').where('echo=?',(cron_name,))\
.field('name,save_local,notice,notice_channel').find()
.field('name,save_local,notice,notice_channel,id').find()
return cron_info
except Exception as e:
pass
return {}
def send_failture_notification(self, error_msg, remark=""):
def send_failture_notification(self, error_msg, target="", remark=""):
"""发送任务失败消息
:error_msg 错误信息
@@ -764,16 +788,18 @@ class backup:
save_local = cron_info["save_local"]
notice = cron_info["notice"]
notice_channel = cron_info["notice_channel"]
self.save_backup_status(False, target, msg=error_msg)
if notice == 0 or not notice_channel:
return
if notice == 1 or notice == 2:
title = self.generate_failture_title(cron_title)
title = self.generate_failture_title()
task_name = cron_title
msg = self.generate_failture_notice(task_name, error_msg, remark)
res = self.send_notification(notice_channel, title, msg)
if res:
self.echo_info(public.getMsg('NOTIFICATION_SENT'))
self.echo_info(public.get_msg_gettext('Notification has been sent'))
def send_all_failture_notification(self, backup_type, results, remark=""):
"""统一发送任务失败消息
@@ -813,18 +839,18 @@ class backup:
if failture_count > 0:
if self._cloud:
remark = public.getMsg("BACKUP_MSG"),(
remark = public.get_msg_gettext('Backup to {}, a total of {} {}, and failures {}.'),(
self._cloud._title, total, backup_type_desc, failture_count)
else:
remark = public.getMsg("BACKUP_MSG1"),(
remark = public.get_msg_gettext('Backup failed {}/total {} sites'),(
failture_count, total, backup_type_desc)
msg = self.generate_all_failture_notice(task_name, content, backup_type_desc, remark)
res = self.send_notification(notice_channel, title, msg)
if res:
self.echo_info(public.getMsg('NOTIFICATION_SENT'))
self.echo_info(public.get_msg_gettext('Notification has been sent'))
else:
self.echo_error(public.getMsg('NOTIFICATION_ERR'))
self.echo_error(public.get_msg_gettext('Failed to send notification'))
def send_notification(self, channel, title, msg = {}):
try:
@@ -876,5 +902,14 @@ class backup:
except Exception as e:
print(e)
return False
def save_backup_status(self, status, target="", msg=""):
"""保存备份的状态"""
try:
if not self.cron_info:
return
cron_id = self.cron_info["id"]
sql = public.M("system").dbfile("system").table("backup_status")
sql.add("id,target,status,msg,addtime", (cron_id, target, status, msg, time.time(),))
except Exception as e:
print("Backup status saving error :{}.".format(e))
+32 -28
View File
@@ -34,12 +34,12 @@ import hmac
try:
import requests
except:
public.ExecShell('pip install requests')
public.ExecShell('btpip install requests')
import requests
try:
import OpenSSL
except:
public.ExecShell('pip install pyopenssl')
public.ExecShell('btpip install pyOpenSSL')
import OpenSSL
import random
import datetime
@@ -97,7 +97,7 @@ class BaseDns(object):
class DNSPodDns(BaseDns):
dns_provider_name = "dnspod"
_type = 0 # 0:lest 1:锐成
def __init__(self, DNSPOD_ID, DNSPOD_API_KEY, DNSPOD_API_BASE_URL="https://dnsapi.cn/"):
self.DNSPOD_ID = DNSPOD_ID
self.DNSPOD_API_KEY = DNSPOD_API_KEY
@@ -113,7 +113,10 @@ class DNSPodDns(BaseDns):
def create_dns_record(self, domain_name, domain_dns_value):
domain_name,_,subd = extract_zone(domain_name)
self.add_record(domain_name,subd,domain_dns_value,'TXT')
if self._type == 1:
self.add_record(domain_name,subd.replace('_acme-challenge.',''),domain_dns_value,'CNAME')
else:
self.add_record(domain_name,subd,domain_dns_value,'TXT')
@@ -177,7 +180,7 @@ class DNSPodDns(BaseDns):
class CloudFlareDns(BaseDns):
dns_provider_name = "cloudflare"
_type = 0 # 0:lest 1:锐成
def __init__(
self,
CLOUDFLARE_EMAIL,
@@ -278,6 +281,12 @@ class CloudFlareDns(BaseDns):
"name": "_acme-challenge" + "." + domain_name + ".",
"content": "{0}".format(domain_dns_value),
}
if self._type == 1:
body['type'] = 'CNAME'
root, _, acme_txt = extract_zone(domain_name)
body['name'] = acme_txt.replace('_acme-challenge.','')
create_cloudflare_dns_record_response = requests.post(
url, headers=headers, json=body, timeout=self.HTTP_TIMEOUT
)
@@ -326,6 +335,7 @@ class CloudFlareDns(BaseDns):
class AliyunDns(object):
_type = 0 # 0:lest 1:锐成
def __init__(self, key, secret, ):
self.key = str(key).strip()
self.secret = str(secret).strip()
@@ -359,11 +369,14 @@ class AliyunDns(object):
def create_dns_record(self, domain_name, domain_dns_value):
root, _, acme_txt = extract_zone(domain_name)
self.add_record(root,'TXT',acme_txt,domain_dns_value)
try:
self.add_record(root,'CAA','@',caa_value)
except:
pass
if self._type == 1:
acme_txt = acme_txt.replace('_acme-challenge.','')
self.add_record(root,'CNAME',acme_txt,domain_dns_value)
else:
try:
self.add_record(root,'CAA','@',caa_value)
except: pass
self.add_record(root,'TXT',acme_txt,domain_dns_value)
def add_record(self,domain,s_type,host,value):
@@ -493,17 +506,6 @@ class CloudxnsDns(object):
req = requests.post(url=url, headers=headers, data=parameter,verify=False)
req = req.json()
data = {
"domain_id": int(domain),
"host": '@',
"value": caa_value,
"type": "CAA",
"line_id": 1,
}
parameter = json.dumps(data)
headers = self.get_headers(url, parameter)
requests.post(url=url, headers=headers, data=parameter,verify=False)
return req
def delete_dns_record(self, domain_name, domain_dns_value):
@@ -513,10 +515,6 @@ class CloudxnsDns(object):
headers = self.get_headers(url, )
req = requests.delete(url=url, headers=headers, verify=False)
req = req.json()
url = "https://www.cloudxns.net/api2/record/{}/{}".format(self.get_record_id(root,'CAA'), self.get_domain_id(root))
headers = self.get_headers(url, )
req = requests.delete(url=url, headers=headers, verify=False)
return req
def get_record_id(self, domain_name,s_type = 'TXT'):
@@ -530,12 +528,12 @@ class CloudxnsDns(object):
return False
class Dns_com(object):
_type = 0 # 0:lest 1:锐成
def __init__(self, key, secret, ):
pass
def get_dns_obj(self):
p_path = '/www/server/panel/plugin/model'
p_path = '/www/server/panel/plugin/dns'
if not os.path.exists(p_path +'/dns_main.py'): return None
sys.path.insert(0,p_path)
import dns_main
@@ -544,7 +542,13 @@ class Dns_com(object):
def create_dns_record(self, domain_name, domain_dns_value):
root, _, acme_txt = extract_zone(domain_name)
result = self.get_dns_obj().add_txt(acme_txt + '.' + root,domain_dns_value)
if self._type == 1:
acme_txt = acme_txt.replace('_acme-challenge.','')
result = self.add_record(acme_txt + '.' + root,domain_dns_value)
else:
result = self.get_dns_obj().add_txt(acme_txt + '.' + root,domain_dns_value)
if result == "False":
raise ValueError('[DNS] This domain name does not exist in the currently bound Pagoda DNS cloud resolution account. Adding parsing failed!')
time.sleep(5)
+88 -88
View File
@@ -135,51 +135,51 @@ class panelLets:
#格式化错误输出
def get_error(self,error):
if error.find("Max checks allowed") >= 0 :
return "CA can't verify your domain name, please check if the domain name resolution is correct, or wait 5-10 minutes and try again."
return public.get_msg_gettext("CA can't verify your domain name, please check if the domain name resolution is correct, or wait 5-10 minutes and try again.")
elif error.find("Max retries exceeded with") >= 0 or error.find('status_code=0 ') != -1:
return "The CA server connection timed out, please try again later."
return public.get_msg_gettext("The CA server connection timed out, please try again later.")
elif error.find("The domain name belongs") >= 0:
return "The domain name does not belong to this DNS service provider. Please ensure that the domain name is filled in correctly."
return public.get_msg_gettext("The domain name does not belong to this DNS service provider. Please ensure that the domain name is filled in correctly.")
elif error.find('login token ID is invalid') >=0:
return 'The DNS server connection failed. Please check if the key is correct.'
return public.get_msg_gettext('The DNS server connection failed. Please check if the key is correct.')
elif "too many certificates already issued for exact set of domains" in error:
return 'The signing failed, the domain name %s exceeded the weekly number of repeated issuances!' % re.findall("exact set of domains: (.+):", error)
return public.get_msg_gettext('The signing failed, the domain name exact set of domains: (.+): {} exceeded the weekly number of repeated issuances!',(error,))
elif "Error creating new account :: too many registrations for this IP" in error:
return 'The signing failed, the current server IP has reached the limit of creating up to 10 accounts every 3 hours..'
return public.get_msg_gettext('The signing failed, the current server IP has reached the limit of creating up to 10 accounts every 3 hours..')
elif "DNS problem: NXDOMAIN looking up A for" in error:
return 'The verification failed, the domain name was not resolved, or the resolution did not take effect.!'
return public.get_msg_gettext('The verification failed, the domain name was not resolved, or the resolution did not take effect.!')
elif "Invalid response from" in error:
return 'Authentication failed, domain name resolution error or verification URL could not be accessed!'
return public.get_msg_gettext('Authentication failed, domain name resolution error or verification URL could not be accessed!')
elif error.find('TLS Web Server Authentication') != -1:
public.restart_panel()
return "Failed to connect to CA server, please try again later."
return public.get_msg_gettext("Failed to connect to CA server, please try again later.")
elif error.find('Name does not end in a public suffix') != -1:
return "Unsupported domain name %s, please check if the domain name is correct!" % re.findall("Cannot issue for \"(.+)\":", error)
return public.get_msg_gettext("Unsupported domain name {}, please check if the domain name is correct!",(re.findall("Cannot issue for \"(.+)\":", error),))
elif error.find('No valid IP addresses found for') != -1:
return "The domain name %s did not find a resolution record. Please check if the domain name is resolved.!" % re.findall("No valid IP addresses found for (.+)", error)
return public.get_msg_gettext("The domain name {} did not find a resolution record. Please check if the domain name is resolved.!",(re.findall("No valid IP addresses found for (.+)", error),))
elif error.find('No TXT record found at') != -1:
return "If a valid TXT resolution record is not found in the domain name %s, please check if the TXT record is correctly parsed. If it is applied by DNSAPI, please try again in 10 minutes.!" % re.findall(
"No TXT record found at (.+)", error)
return public.get_msg_gettext("If a valid TXT resolution record is not found in the domain name {}, please check if the TXT record is correctly parsed. If it is applied by DNSAPI, please try again in 10 minutes.!",(re.findall(
"No TXT record found at (.+)", error),))
elif error.find('Incorrect TXT record') != -1:
return "Found the wrong TXT record on %s: %s, please check if the TXT resolution is correct. If it is applied by DNSAPI, please try again in 10 minutes.!" % (
re.findall("found at (.+)", error), re.findall("Incorrect TXT record \"(.+)\"", error))
return public.get_msg_gettext("Found the wrong TXT record on {}: {}, please check if the TXT resolution is correct. If it is applied by DNSAPI, please try again in 10 minutes.!",(
re.findall("found at (.+)", error), re.findall("Incorrect TXT record \"(.+)\"", error)))
elif error.find('Domain not under you or your user') != -1:
return "This domain name does not exist under this dnspod account. Adding parsing failed.!"
return public.get_msg_gettext("This domain name does not exist under this dnspod account. Adding parsing failed.!")
elif error.find('SERVFAIL looking up TXT for') != -1:
return "If a valid TXT resolution record is not found in the domain name %s, please check if the TXT record is correctly parsed. If it is applied by DNSAPI, please try again in 10 minutes.!" % re.findall(
"looking up TXT for (.+)", error)
return public.get_msg_gettext("If a valid TXT resolution record is not found in the domain name {}, please check if the TXT record is correctly parsed. If it is applied by DNSAPI, please try again in 10 minutes.!",(re.findall(
"looking up TXT for (.+)", error),))
elif error.find('Timeout during connect') != -1:
return "Connection timed out, CA server could not access your website!"
return public.get_msg_gettext("Connection timed out, CA server could not access your website!")
elif error.find("DNS problem: SERVFAIL looking up CAA for") != -1:
return "The domain name %s is currently required to verify the CAA record. Please manually resolve the CAA record, or try again after 1 hour.!" % re.findall("looking up CAA for (.+)", error)
return public.get_msg_gettext("The domain name {} is currently required to verify the CAA record. Please manually resolve the CAA record, or try again after 1 hour.!" , (re.findall("looking up CAA for (.+)", error),))
elif error.find("Read timed out.") != -1:
return "Verification timeout, please check whether the domain name is correctly resolved. If dns is resolved, the connection between the server and Let'sEncrypt may be abnormal. Please try again later!"
return public.get_msg_gettext("Verification timeout, please check whether the domain name is correctly resolved. If dns is resolved, the connection between the server and Let'sEncrypt may be abnormal. Please try again later!")
elif error.find("Error creating new order") != -1:
return "Order creation failed, please try again later!"
return public.get_msg_gettext("Order creation failed, please try again later!")
elif error.find("Too Many Requests") != -1:
return "More than 5 verification failures in 1 hour, application is temporarily banned, please try again later!"
return public.get_msg_gettext("More than 5 verification failures in 1 hour, application is temporarily banned, please try again later!")
elif error.find('HTTP Error 400: Bad Request') != -1:
return "CA server denied access, please try again later!"
return public.get_msg_gettext("CA server denied access, please try again later!")
else:
return error;
@@ -211,10 +211,10 @@ class panelLets:
def renew_lest_cert(self,data):
#续签网站
path = self.setupPath + '/panel/vhost/cert/'+ data['siteName']
if not os.path.exists(path): return public.returnMsg(False, 'RENEW_FAILED')
if not os.path.exists(path): return public.return_msg_gettext(False, 'The renewal failed and the certificate directory does not exist.')
account_path = path + "/account_key.key"
if not os.path.exists(account_path): return public.returnMsg(False, 'RENEW_FAILED1')
if not os.path.exists(account_path): return public.return_msg_gettext(False, 'Renewal failed, missing account_key.')
#续签
data['account_key'] = public.readFile(account_path)
@@ -226,7 +226,7 @@ class panelLets:
else:
certificate = self.crate_let_by_file(data)
if not certificate['status']: return public.returnMsg(False, certificate['msg'])
if not certificate['status']: return public.return_msg_gettext(False, certificate['msg'])
#存储证书
public.writeFile(path + "/privkey.pem",certificate['key'])
@@ -238,7 +238,7 @@ class panelLets:
pfx_buffer = p12.export()
public.writeFile(path + "/fullchain.pfx",pfx_buffer,'wb+')
return public.returnMsg(True, 'RENEW_SUCCESS1',(data['siteName'],))
return public.return_msg_gettext(True, '[ {} ] The certificate renewal was successful.',(data['siteName'],))
@@ -249,9 +249,9 @@ class panelLets:
data['domains'] = json.loads(get.domains)
data['email'] = get.email
data['dnssleep'] = get.dnssleep
self.write_log(public.getMsg("APPLY_SSL",(data['domains'],)))
self.write_log(public.get_msg_gettext('Ready to apply for SSL, domain name {}',(data['domains'],)))
self.write_log("="*50)
if len(data['domains']) <=0 : return public.returnMsg(False, 'APPLY_SSL_DOMAIN_ERR')
if len(data['domains']) <=0 : return public.return_msg_gettext(False, 'The list of applied domain names cannot be empty.')
data['first_domain'] = data['domains'][0]
@@ -296,7 +296,7 @@ class panelLets:
if 'status' in result and not result['status']: return result
result['status'] = True
public.writeFile(domain_path, json.dumps(result))
result['msg'] = public.getMsg('MANUALLY_RESOLVE_DOMAIN')
result['msg'] = public.get_msg_gettext('Get successful, please manually resolve the domain name')
result['code'] = 2
return result
elif get.dnsapi == 'dns_bt':
@@ -314,10 +314,10 @@ class panelLets:
data['site_dir'] = get.site_dir
certificate = self.crate_let_by_file(data)
if not certificate['status']: return public.returnMsg(False, certificate['msg'])
if not certificate['status']: return public.return_msg_gettext(False, certificate['msg'])
#保存续签
self.write_log(public.getMsg("SAVEING_SSL"))
self.write_log(public.get_msg_gettext('|-Saving certificate..'))
cpath = self.setupPath + '/panel/vhost/cert/crontab.json'
config = {}
if os.path.exists(cpath):
@@ -341,11 +341,11 @@ class panelLets:
public.writeFile(path + "/README","let")
#计划任务续签
self.write_log(public.getMsg("SET_AUTORENEW"))
self.write_log(public.get_msg_gettext('|-Setting up auto-renewal configuration..'))
self.set_crond()
self.write_log(public.getMsg("DEPLOY_SSL_TO_SITE"))
self.write_log(public.get_msg_gettext('|-The application is successful and it is being automatically deployed to the website!'))
self.write_log("="*50)
return public.returnMsg(True, 'APPLY_SSL_SUCCESS')
return public.return_msg_gettext(True, 'Application successful.')
#创建计划任务
def set_crond(self):
@@ -380,15 +380,15 @@ class panelLets:
#手动解析记录值
if not 'renew' in data:
self.write_log(public.getMsg("INIT_ACME"))
self.write_log(public.get_msg_gettext('|-Initializing ACME protocol...'))
BTPanel.dns_client = sewer.Client(domain_name = data['first_domain'],dns_class = None,account_key = data['account_key'],domain_alt_names = data['domains'],contact_email = str(data['email']) ,ACME_AUTH_STATUS_WAIT_PERIOD = 15,ACME_AUTH_STATUS_MAX_CHECKS = 5,ACME_REQUEST_TIMEOUT = 20,ACME_DIRECTORY_URL = self.let_url)
domain_dns_value = "placeholder"
dns_names_to_delete = []
self.write_log(public.getMsg("REGISTER_ACCOUNT"))
self.write_log(public.get_msg_gettext('|-Registering account...'))
BTPanel.dns_client.acme_register()
authorizations, finalize_url = BTPanel.dns_client.apply_for_cert_issuance()
responders = []
self.write_log(public.getMsg("GET_VERIFICATION_INFO"))
self.write_log(public.get_msg_gettext('|-Getting verification information...'))
for url in authorizations:
identifier_auth = BTPanel.dns_client.get_identifier_authorization(url)
authorization_url = identifier_auth["url"]
@@ -413,25 +413,25 @@ class panelLets:
dns['dns_names'] = dns_names_to_delete
dns['responders'] = responders
dns['finalize_url'] = finalize_url
self.write_log(public.getMsg("RETURN_VERIFICATION_INFO"))
self.write_log(public.get_msg_gettext('|-Return the verification information to the front end, wait for the user to manually resolve the domain name and complete the verification...'))
return dns
else:
self.write_log(public.getMsg("SUBMIT_V_REQUEST"))
self.write_log(public.get_msg_gettext('|-User submits verification request...'))
responders = data['dns']['responders']
dns_names_to_delete = data['dns']['dns_names']
finalize_url = data['dns']['finalize_url']
for i in responders:
self.write_log(public.getMsg("CA_V_DOMAIN",(i['dns_name'],)))
self.write_log(public.get_msg_gettext('|-Requesting CA to verify domain name [{}]...',(i['dns_name'],)))
auth_status_response = BTPanel.dns_client.check_authorization_status(i["authorization_url"])
if auth_status_response.json()["status"] == "pending":
BTPanel.dns_client.respond_to_challenge(i["acme_keyauthorization"], i["dns_challenge_url"])
for i in responders:
self.write_log(public.getMsg("GET_CA_V_RES",(i['dns_name'],)))
self.write_log(public.get_msg_gettext('|-Get CA verification results [{}]...',(i['dns_name'],)))
BTPanel.dns_client.check_authorization_status(i["authorization_url"], ["valid","invalid"])
self.write_log(public.getMsg("ALL_DOMAIN_V_PASS"))
self.write_log(public.get_msg_gettext('|-All domain names are verified and CSR is being sent...'))
certificate_url = BTPanel.dns_client.send_csr(finalize_url)
self.write_log(public.getMsg("GET_CERT_CONTENT"))
self.write_log(public.get_msg_gettext('|-Getting certificate content...'))
certificate = BTPanel.dns_client.download_certificate(certificate_url)
if certificate:
@@ -443,10 +443,10 @@ class panelLets:
result['status'] = True
BTPanel.dns_client = None
else:
result['msg'] = public.getMsg('CERT_APPLY_ERR')
result['msg'] = public.get_msg_gettext('Certificate acquisition failed, please try again later.')
except Exception as e:
self.write_log(public.getMsg("CERT_APPLY_ERR1",(e,)))
self.write_log(public.get_msg_gettext('|-Error: {}, exited the application process.',(e,)))
self.write_log("=" * 50)
res = str(e).split('>>>>')
err = False
@@ -461,10 +461,10 @@ class panelLets:
def crate_let_by_dns(self,data):
dns_class = self.get_dns_class(data)
if not dns_class:
self.write_log(public.getMsg("DNS_APPLY_ERR"))
self.write_log(public.getMsg("EXIT_APPLY_PROCESS"))
self.write_log(public.get_msg_gettext('|-Error: {}, exit the application process.'))
self.write_log(public.get_msg_gettext('|-Exited the application process!'))
self.write_log("="*50)
return public.returnMsg(False, 'DNS_APPLY_ERR1')
return public.return_msg_gettext(False, 'An error occurred while requesting a certificate using dns')
result = {}
result['status'] = False
@@ -472,16 +472,16 @@ class panelLets:
log_level = "INFO"
if data['account_key']: log_level = 'ERROR'
if not data['email']: data['email'] = public.M('users').getField('email')
self.write_log(public.getMsg("INIT_ACME"))
self.write_log(public.get_msg_gettext('|-Initializing ACME protocol...'))
client = sewer.Client(domain_name = data['first_domain'],domain_alt_names = data['domains'],account_key = data['account_key'],contact_email = str(data['email']),LOG_LEVEL = log_level,ACME_AUTH_STATUS_WAIT_PERIOD = 15,ACME_AUTH_STATUS_MAX_CHECKS = 5,ACME_REQUEST_TIMEOUT = 20, dns_class = dns_class,ACME_DIRECTORY_URL = self.let_url)
domain_dns_value = "placeholder"
dns_names_to_delete = []
try:
self.write_log(public.getMsg("REGISTER_ACCOUNT"))
self.write_log(public.get_msg_gettext('|-Registering account...'))
client.acme_register()
authorizations, finalize_url = client.apply_for_cert_issuance()
responders = []
self.write_log(public.getMsg("GET_VERIFICATION_INFO"))
self.write_log(public.get_msg_gettext('|-Getting verification information...'))
for url in authorizations:
identifier_auth = client.get_identifier_authorization(url)
authorization_url = identifier_auth["url"]
@@ -489,7 +489,7 @@ class panelLets:
dns_token = identifier_auth["dns_token"]
dns_challenge_url = identifier_auth["dns_challenge_url"]
acme_keyauthorization, domain_dns_value = client.get_keyauthorization(dns_token)
self.write_log(public.getMsg("ADD_TXT_RECORD",(dns_name,domain_dns_value)))
self.write_log(public.get_msg_gettext('|-Adding resolution record, domain name [{}], record value [{}]...',(dns_name,domain_dns_value)))
dns_class.create_dns_record(public.de_punycode(dns_name), domain_dns_value)
dns_names_to_delete.append({"dns_name": public.de_punycode(dns_name), "domain_dns_value": domain_dns_value})
responders.append({"dns_name":dns_name,"domain_dns_value":domain_dns_value,"authorization_url": authorization_url, "acme_keyauthorization": acme_keyauthorization,"dns_challenge_url": dns_challenge_url} )
@@ -498,33 +498,33 @@ class panelLets:
try:
for i in responders:
self.write_log(public.getMsg("CHECK_TXT_RECORD",(i['dns_name'],i['domain_dns_value'])))
self.write_log(public.get_msg_gettext('|-Attempt to verify the resolution result, domain name [{}], record value [{}]...',(i['dns_name'],i['domain_dns_value'])))
self.check_dns(self.get_acme_name(i['dns_name']),i['domain_dns_value'])
self.write_log(public.getMsg("CA_CHECK_RECORD",(i['dns_name'])))
self.write_log(public.get_msg_gettext('|-Request CA to verify domain name [{}]...',(i['dns_name'])))
auth_status_response = client.check_authorization_status(i["authorization_url"])
r_data = auth_status_response.json()
if r_data["status"] == "pending":
client.respond_to_challenge(i["acme_keyauthorization"], i["dns_challenge_url"])
for i in responders:
self.write_log(public.getMsg("CHECK_CA_RES",(i['dns_name'],)))
self.write_log(public.get_msg_gettext('|-Check CA verification results [{}]...',(i['dns_name'],)))
client.check_authorization_status(i["authorization_url"], ["valid","invalid"])
except Exception as ex:
self.write_log(public.getMsg("APPLY_WITH_DNS_ERR",(str(ex),)))
self.write_log(public.get_msg_gettext('|-An error occurred, try again [{}]',(str(ex),)))
for i in responders:
self.write_log(public.getMsg("CHECK_TXT_RECORD",(i['dns_name'],i['domain_dns_value'])))
self.write_log(public.get_msg_gettext('|-Attempt to verify the resolution result, domain name [{}], record value [{}]...',(i['dns_name'],i['domain_dns_value'])))
self.check_dns(self.get_acme_name(i['dns_name']),i['domain_dns_value'])
self.write_log(public.getMsg("CA_CHECK_RECORD",(i['dns_name'])))
self.write_log(public.get_msg_gettext('|-Request CA to verify domain name [{}]...',(i['dns_name'])))
auth_status_response = client.check_authorization_status(i["authorization_url"])
r_data = auth_status_response.json()
if r_data["status"] == "pending":
client.respond_to_challenge(i["acme_keyauthorization"], i["dns_challenge_url"])
for i in responders:
self.write_log(public.getMsg("CHECK_CA_RES",(i['dns_name'],)))
self.write_log(public.get_msg_gettext('|-Check CA verification results [{}]...',(i['dns_name'],)))
client.check_authorization_status(i["authorization_url"], ["valid","invalid"])
self.write_log(public.getMsg("ALL_DOMAIN_V_PASS"))
self.write_log(public.get_msg_gettext('|-All domain names are verified and CSR is being sent...'))
certificate_url = client.send_csr(finalize_url)
self.write_log(public.getMsg("FETCH_CERT_CONTENT"))
self.write_log(public.get_msg_gettext('|-Fetching certificate content...'))
certificate = client.download_certificate(certificate_url)
if certificate:
certificate = self.split_ca_data(certificate)
@@ -539,7 +539,7 @@ class panelLets:
finally:
try:
for i in dns_names_to_delete:
self.write_log(public.getMsg("CLEAR_RESOLVE_HISTORY",(i["dns_name"])))
self.write_log(public.get_msg_gettext('|-Clearing resolve history [{}]',(i["dns_name"])))
dns_class.delete_dns_record(i["dns_name"], i["domain_dns_value"])
except :
pass
@@ -547,10 +547,10 @@ class panelLets:
except Exception as e:
try:
for i in dns_names_to_delete:
self.write_log(public.getMsg("CLEAR_RESOLVE_HISTORY",(i["dns_name"])))
self.write_log(public.get_msg_gettext('|-Clearing resolve history [{}]',(i["dns_name"])))
dns_class.delete_dns_record(i["dns_name"], i["domain_dns_value"])
except:pass
self.write_log(public.getMsg("DNS_APPLY_ERR",(str(public.get_error_info()),)))
self.write_log(public.get_msg_gettext('|-Error: {}, exit the application process.',(str(public.get_error_info()),)))
self.write_log("=" * 50)
res = str(e).split('>>>>')
err = False
@@ -566,17 +566,17 @@ class panelLets:
result['status'] = False
result['clecks'] = []
try:
self.write_log(public.getMsg("INIT_ACME"))
self.write_log(public.get_msg_gettext('|-Initializing ACME protocol...'))
log_level = "INFO"
if data['account_key']: log_level = 'ERROR'
if not data['email']: data['email'] = public.M('users').getField('email')
client = sewer.Client(domain_name = data['first_domain'],dns_class = None,account_key = data['account_key'],domain_alt_names = data['domains'],contact_email = str(data['email']),LOG_LEVEL = log_level,ACME_AUTH_STATUS_WAIT_PERIOD = 15,ACME_AUTH_STATUS_MAX_CHECKS = 5,ACME_REQUEST_TIMEOUT = 20,ACME_DIRECTORY_URL = self.let_url)
self.write_log(public.getMsg("REGISTER_ACCOUNT"))
self.write_log(public.get_msg_gettext('|-Registering account...'))
client.acme_register()
authorizations, finalize_url = client.apply_for_cert_issuance()
responders = []
sucess_domains = []
self.write_log(public.getMsg("GET_VERIFICATION_INFO"))
self.write_log(public.get_msg_gettext('|-Getting verification information...'))
for url in authorizations:
identifier_auth = self.get_identifier_authorization(client,url)
@@ -591,21 +591,21 @@ class panelLets:
#写入token
wellknown_path = acme_dir + '/' + http_token
self.write_log(public.getMsg("CREATE_V_FILE",(wellknown_path,)))
self.write_log(public.get_msg_gettext('|-Writing verification file [{}]...',(wellknown_path,)))
public.writeFile(wellknown_path,acme_keyauthorization)
wellknown_url = "http://{0}/.well-known/acme-challenge/{1}".format(http_name, http_token)
wellknown_url = "http://{}/.well-known/acme-challenge/{}".format(http_name, http_token)
result['clecks'].append({'wellknown_url':wellknown_url,'http_token':http_token})
is_check = False
n = 0
self.write_log(public.getMsg("CHECK_FILE_CONTENT",(wellknown_url)))
self.write_log(public.get_msg_gettext('|-Attempt to verify file contents via HTTP [{}]...',(wellknown_url)))
while n < 5:
print("wait_check_authorization_status")
try:
retkey = public.httpGet(wellknown_url,20)
if retkey == acme_keyauthorization:
is_check = True
self.write_log(public.getMsg("CHECK_FILE_CONTENT1",(retkey,)))
self.write_log(public.get_msg_gettext('|-Verified, content [{}]...',(retkey,)))
break
except :
pass
@@ -617,18 +617,18 @@ class panelLets:
if len(sucess_domains) > 0:
#验证
for i in responders:
self.write_log(public.getMsg("CA_CHECK_RECORD",(i['http_name'],)))
self.write_log(public.get_msg_gettext('|-Request CA to verify domain name [{}]...',(i['http_name'],)))
auth_status_response = client.check_authorization_status(i["authorization_url"])
if auth_status_response.json()["status"] == "pending":
client.respond_to_challenge(i["acme_keyauthorization"], i["http_challenge_url"]).json()
for i in responders:
self.write_log(public.getMsg("CHECK_CA_RES",(i['http_name'],)))
self.write_log(public.get_msg_gettext('|-Check CA verification results [{}]...',(i['http_name'],)))
client.check_authorization_status(i["authorization_url"], ["valid","invalid"])
self.write_log(public.getMsg("ALL_DOMAIN_V_PASS"))
self.write_log(public.get_msg_gettext('|-All domain names are verified and CSR is being sent...'))
certificate_url = client.send_csr(finalize_url)
self.write_log(public.getMsg("GET_CERT_CONTENT"))
self.write_log(public.get_msg_gettext('|-Getting certificate content...'))
certificate = client.download_certificate(certificate_url)
if certificate:
@@ -640,11 +640,11 @@ class panelLets:
result['status'] = True
else:
result['msg'] = public.getMsg('CERT_APPLY_ERR')
result['msg'] = public.get_msg_gettext('Certificate acquisition failed, please try again later.')
else:
result['msg'] = public.getMsg("APPLY_SSL_ERROR_MSG")
result['msg'] = public.get_msg_gettext('The signing failed, we were unable to verify your domain name:<p>1. Check if the domain name is bound to the corresponding site.</p><p>2. Check if the domain name is correctly resolved to the server, or the resolution is not fully effective.</p><p>3. If your site has a reverse proxy set up, or if you are using a CDN, please turn it off first.</p><p>4. If your site has a 301 redirect, please turn it off first</p><p>5. If the above checks confirm that there is no problem, please try to change the DNS service provider.</p>')
except Exception as e:
self.write_log(public.getMsg("DNS_APPLY_ERR",(str(public.get_error_info()),)))
self.write_log(public.get_msg_gettext('|-Error: {}, exit the application process.',(str(public.get_error_info()),)))
self.write_log("=" * 50)
res = str(e).split('>>>>')
err = False
@@ -693,7 +693,7 @@ class panelLets:
for i in j.items:
txt_value = i.to_text().replace('"','').strip()
if txt_value == value:
self.write_log(public.getMsg("SUCCESS_V",(domain,type,txt_value)))
self.write_log(public.get_msg_gettext('|-Successful verification, domain name [{}], record type [{}], record value [{}]!',(domain,type,txt_value)))
print("Verification succeeded: %s" % txt_value)
return True
except:
@@ -753,18 +753,18 @@ class panelLets:
def renew_lets_ssl(self):
cpath = self.setupPath + '/panel/vhost/cert/crontab.json'
if not os.path.exists(cpath):
print(public.getMsg("NO_ORDER_RENEW") )
print(public.get_msg_gettext('|-There are currently no certificates to renew.') )
else:
old_list = json.loads(public.ReadFile(cpath))
print('=======================================================================')
print(public.getMsg('TOTAL_RENEW',(time.strftime('%Y-%m-%d %X',time.localtime()),str(len(old_list)))))
print(public.get_msg_gettext('|-{} Total [{}] renewal of visa tasks',(time.strftime('%Y-%m-%d %X',time.localtime()),str(len(old_list)))))
cron_list = self.get_renew_lets_bytimeout(old_list)
tlist = []
for siteName in old_list:
if not siteName in cron_list: tlist.append(siteName)
print(public.getMsg('SSL_NOT_EXPIRED_OR_NOT_USE',(','.join(tlist),)))
print(public.getMsg('WAIT_RENEW1',(time.strftime('%Y-%m-%d %X',time.localtime()),str(len(cron_list)))))
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('|-{} Waiting for renewal [{}].',(time.strftime('%Y-%m-%d %X',time.localtime()),str(len(cron_list)))))
sucess_list = []
err_list = []
@@ -775,11 +775,11 @@ class panelLets:
sucess_list.append(siteName)
else:
err_list.append({"siteName":siteName,"msg":ret['msg']})
print(public.getMsg("RENEW_COMPLETED",(str(len(cron_list)),str(len(sucess_list)),str(len(err_list)))))
print(public.get_msg_gettext('|-After the task is completed, a total of renewals are required.[{}], renewal success [%s], renewal failed [{}]. ',(str(len(cron_list)),str(len(sucess_list)),str(len(err_list)))))
if len(sucess_list) > 0:
print(public.getMsg("RENEW_SUCCESS2",(','.join(sucess_list),)))
print(public.get_msg_gettext('|-Renewal success{}',(','.join(sucess_list),)))
if len(err_list) > 0:
print(public.getMsg("RENEW_FAILED2"))
print(public.get_msg_gettext('|-Renewal failed'))
for x in err_list:
print(" %s ->> %s" % (x['siteName'],x['msg']))
+29 -26
View File
@@ -44,33 +44,36 @@ class panelMessage:
"""
获取官网推送消息小时获取一次
获取官网推送消息获取一次
"""
def get_cloud_messages(self,args):
#ret = cache.get('get_cloud_messages')
#if ret: return public.returnMsg(True,'同步成功1!')
data = {}
data['version'] = public.version()
data['os'] = self.os
sUrl = public.GetConfigValue('home') + '/api/wpanel/get_messages'
import http_requests
http_requests.DEFAULT_TYPE = 'src'
info = http_requests.post(sUrl,data).json()
# info = json.loads(public.httpPost(sUrl,data))
for x in info:
count = public.M('messages').where('level=? and msg=?',(x['level'],x['msg'],)).count()
if count: continue
try:
ret = cache.get('get_cloud_messages')
if ret: return public.returnMsg(True,'同步成功1!')
data = {}
data['version'] = public.version()
data['os'] = self.os
sUrl = public.GetConfigValue('home') + '/api/wpanel/get_messages'
import http_requests
http_requests.DEFAULT_TYPE = 'src'
info = http_requests.post(sUrl,data).json()
# info = json.loads(public.httpPost(sUrl,data))
for x in info:
count = public.M('messages').where('level=? and msg=?',(x['level'],x['msg'],)).count()
if count: continue
pdata = {
"level":x['level'],
"msg":x['msg'],
"state":1,
"expire":int(time.time()) + (int(x['expire']) * 86400),
"addtime": int(time.time())
}
public.M('messages').insert(pdata)
#cache.set('get_cloud_messages',3600)
return public.returnMsg(True,'同步成功!')
pdata = {
"level":x['level'],
"msg":x['msg'],
"state":1,
"expire":int(time.time()) + (int(x['expire']) * 86400),
"addtime": int(time.time())
}
public.M('messages').insert(pdata)
cache.set('get_cloud_messages',86400)
return public.returnMsg(True,'同步成功!')
except:
return public.returnMsg(False,'同步失败!')
def get_messages(self,args = None):
'''
@@ -78,7 +81,7 @@ class panelMessage:
@author hwliang <2020-05-18>
@return list
'''
self.get_cloud_messages(args)
public.run_thread(self.get_cloud_messages,args=(args,))
data = public.M('messages').where('state=? and expire>?',(1,int(time.time()))).order("id desc").select()
return data
@@ -88,7 +91,7 @@ class panelMessage:
@author hwliang <2020-05-18>
@return list
'''
self.get_cloud_messages(args)
public.run_thread(self.get_cloud_messages,args=(args,))
data = public.M('messages').order("id desc").select()
return data
+32 -3
View File
@@ -22,7 +22,13 @@ class panelMysql:
def __Conn(self):
if self.__DB_NET: return True
try:
socket = '/tmp/mysql.sock'
myconf = public.readFile('/etc/my.cnf')
socket_re = re.search(r"socket\s*=\s*(.+)",myconf)
if socket_re:
socket = socket_re.groups()[0]
else:
socket = '/tmp/mysql.sock'
try:
if sys.version_info[0] != 2:
try:
@@ -34,7 +40,7 @@ class panelMysql:
import MySQLdb
if sys.version_info[0] == 2:
reload(MySQLdb)
except Exception as ex:
except:
try:
import pymysql
pymysql.install_as_MySQLdb()
@@ -43,7 +49,7 @@ class panelMysql:
self.__DB_ERR = e
return False
try:
myconf = public.readFile('/etc/my.cnf')
rep = r"port\s*=\s*([0-9]+)"
self.__DB_PORT = int(re.search(rep,myconf).groups()[0])
except:
@@ -65,12 +71,34 @@ class panelMysql:
def connect_network(self,host,port,username,password):
self.__DB_NET = True
try:
try:
if sys.version_info[0] != 2:
try:
import pymysql
except:
public.ExecShell("pip install pymysql")
import pymysql
pymysql.install_as_MySQLdb()
import MySQLdb
if sys.version_info[0] == 2:
reload(MySQLdb)
except:
try:
import pymysql
pymysql.install_as_MySQLdb()
import MySQLdb
except Exception as e:
self.__DB_ERR = e
return False
self.__DB_CONN = MySQLdb.connect(host = host,user = username,passwd = password,port = port,charset="utf8",connect_timeout=10)
self.__DB_CUR = self.__DB_CONN.cursor()
return True
except MySQLdb.Error as e:
self.__DB_ERR = e
return False
def execute(self,sql):
#执行SQL语句返回受影响行
if not self.__Conn(): return self.__DB_ERR
@@ -99,6 +127,7 @@ class panelMysql:
except Exception as ex:
return ex
#关闭连接
def __Close(self):
self.__DB_CUR.close()
+3 -10
View File
@@ -61,15 +61,8 @@ class panelPHP:
data = {}
data['GET'] = request.args.to_dict()
data['POST'] = {}
x_token = request.headers.get('x-http-token')
if x_token:
aes_pwd = x_token[:8] + x_token[40:48]
for key in request.form.keys():
data['POST'][key] = str(request.form.get(key,''))
if x_token:
if len(data['POST'][key]) > 5:
if data['POST'][key][:6] == 'BT-CRT':
data['POST'][key] = public.aes_decrypt(data['POST'][key][6:],aes_pwd)
data['POST']['client_ip'] = public.GetClientIp()
data = json.dumps(data)
public.writeFile(self.__args_tmp,data)
@@ -93,7 +86,7 @@ class panelPHP:
php_vs = json.loads(public.readFile(php_v_file).replace('.',''))
else:
#否则兼容所有版本
php_vs = ["80","74","73","72","71","70","56","55","54","53","52"]
php_vs = public.get_php_versions(True)
#判段兼容的PHP版本是否安装
php_path = "/www/server/php/"
php_v = None
@@ -125,7 +118,7 @@ class panelPHP:
else:
php_vs = sorted(php_version,reverse=True)
else:
php_vs = ["80","74","73","72","71","70","56","55","54","53","52"]
php_vs = public.get_php_versions(True)
php_path = "/www/server/php/"
php_v = None
for pv in php_vs:
@@ -601,7 +594,7 @@ class FPM(object):
'DOCUMENT_ROOT': self.document_root,
'SERVER_PROTOCOL' : 'HTTP/1.1',
'REMOTE_ADDR': '127.0.0.1',
'REMOTE_PORT': '7800',
'REMOTE_PORT': '8888',
'SERVER_ADDR': '127.0.0.1',
'SERVER_PORT': '80',
'SERVER_NAME': 'BT-Panel'
+261 -207
View File
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -29,11 +29,11 @@ class ProjectController:
}
'''
try: # 表单验证
if args['mod_name'] in ['base']: return public.return_status_code(1000,'错误的调用!')
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,'调用的方法名称中不能包含“__”字符')
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 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')
except:
return public.get_error_object()
# 参数处理
@@ -59,7 +59,7 @@ class ProjectController:
else:
pdata = args.data
else:
pdata = public.dict_obj()
pdata = args
# 前置HOOK
hook_index = '{}_{}_LAST'.format(mod_name.upper(),def_name.upper())
+30 -30
View File
@@ -83,7 +83,7 @@ class panelRedirect:
else:
sk.connect((d, 443))
except:
return public.returnMsg(False, "CANT_GET_URL")
return public.return_msg_gettext(False, 'Can NOT get target URL')
# 计算proxyname md5
def __calc_md5(self,redirectname):
import hashlib
@@ -112,7 +112,7 @@ class panelRedirect:
if get.sitename in sitenamelist:
rep = "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.GetMsg("NGINX_REDIRECT_REP") + "include " + ng_redirectfile + ";")
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:
@@ -130,18 +130,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.GetMsg("NGINX_REDIRECT_REP")
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.GetMsg("NGINX_REDIRECT_REP1")
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.GetMsg("NGINX_REDIRECT_REP") +"\n\tIncludeOptional " + ap_redirectfile)
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.GetMsg("NGINX_REDIRECT_REP")
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)
@@ -149,52 +149,52 @@ class panelRedirect:
def __CheckRedirectStart(self,get,action=""):
isError = public.checkWebConfig()
if (isError != True):
return public.returnMsg(False, 'GET_ERR_IN_CONFILE')
return public.return_msg_gettext(False, 'An error was detected in the configuration file. Please solve it before proceeding')
if action == "create":
#检测名称是否重复
if sys.version_info.major < 3:
if len(get.redirectname) < 3 or len(get.redirectname) > 15:
return public.returnMsg(False, 'NAME_LEN')
return public.return_msg_gettext(False, 'Database name cannot be more than 16 characters!')
else:
if len(get.redirectname.encode("utf-8")) < 3 or len(get.redirectname.encode("utf-8")) > 15:
return public.returnMsg(False, 'NAME_LEN')
return public.return_msg_gettext(False, 'Database name cannot be more than 16 characters!')
if self.__CheckRedirect(get.sitename,get.redirectname):
return public.returnMsg(False, 'REDIRECT_EXIST')
return public.return_msg_gettext(False, 'Specified redirect name already exists')
#检测是否选择域名
if get.domainorpath == "domain":
if not json.loads(get.redirectdomain):
return public.returnMsg(False, 'SELECT_RED_DOMAIN')
return public.return_msg_gettext(False, 'Please select redirected domain')
else:
if not get.redirectpath:
return public.returnMsg(False, 'INPUT_RED_DOMAIN')
return public.return_msg_gettext(False, 'Please enter redirected path')
#repte = "[\?\=\[\]\)\(\*\&\^\%\$\#\@\!\~\`{\}\>\<\,\',\"]+"
# 检测路径格式
if "/" not in get.redirectpath:
return public.returnMsg(False, "PATH_ERR")
return public.return_msg_gettext(False, 'Path format is incorrect, the format is /xxx')
#if re.search(repte, get.redirectpath):
# return public.returnMsg(False, "代理目录不能有以下特殊符号 ?,=,[,],),(,*,&,^,%,$,#,@,!,~,`,{,},>,<,\,',\"]")
# return public.return_msg_gettext(False, "代理目录不能有以下特殊符号 ?,=,[,],),(,*,&,^,%,$,#,@,!,~,`,{,},>,<,\,',\"]")
#检测域名是否已经存在配置文件
repeatdomain = self.__CheckRepeatDomain(get,action)
if repeatdomain:
return public.returnMsg(False, 'RED_DOMAIN_EXIST' , (repeatdomain,))
return public.return_msg_gettext(False, 'Redirected domain already exists {}' , (repeatdomain,))
#检测路径是否有存在配置文件
repeatpath = self.__CheckRepeatPath(get)
if repeatpath:
return public.returnMsg(False, 'RED_DOMAIN_EXIST' , (repeatpath,))
return public.return_msg_gettext(False, 'Redirected domain already exists {}' , (repeatpath,))
#检测目标URL格式
rep = "http(s)?\:\/\/([a-zA-Z0-9][-a-zA-Z0-9]{0,62}\.)+([a-zA-Z0-9][a-zA-Z0-9]{0,62})+.?"
if not re.match(rep, get.tourl):
return public.returnMsg(False, 'URL_FORMAT_ERR' ,(get.tourl,))
return public.return_msg_gettext(False, 'The target URL format is incorrect {}' ,(get.tourl,))
#检测目标URL是否可用
#if self.__CheckRedirectUrl(get):
# return public.returnMsg(False, '目标URL无法访问')
# return public.return_msg_gettext(False, '目标URL无法访问')
#检查目标URL的域名和被重定向的域名是否一样
if get.domainorpath == "domain":
for d in json.loads(get.redirectdomain):
tu = self.GetToDomain(get.tourl)
if d == tu:
return public.returnMsg(False,public.GetMsg("DOMAIN_SAMEAS_URL",(d,)))
return public.return_msg_gettext(False,public.get_msg_gettext('Domain name {} is the same as the target domain name, please deselect it',(d,)))
if get.domainorpath == "path":
domains = self.GetAllDomain(get.sitename)
@@ -203,7 +203,7 @@ class panelRedirect:
for d in domains:
ad = "%s%s" % (d,get.redirectpath) #站点域名+重定向路径
if tu == ad:
return public.GetMsg("URL_SAMEAS_REDPATH",(tu,))
return public.get_msg_gettext('{}, the target URL is the same as the redirected path',(tu,))
#创建重定向
def CreateRedirect(self,get):
@@ -226,7 +226,7 @@ class panelRedirect:
self.SetRedirectApache(get.sitename)
self.SetRedirect(get)
public.serviceReload()
return public.returnMsg(True, 'CREATE_SUCCESS')
return public.return_msg_gettext(True, 'Successfully created file!')
# 设置重定向
def SetRedirect(self,get):
@@ -331,7 +331,7 @@ class panelRedirect:
for i in range(len(p_conf) - 1, -1, -1):
if get.sitename == p_conf[i]["sitename"] and p_conf[i]["redirectname"]:
del(p_conf[i])
return public.returnMsg(False, '%s<br><a style="color:red;">' % public.GetMsg("HAVE_ERR") + isError.replace("\n",'<br>') + '</a>')
return public.return_msg_gettext(False, '%s<br><a style="color:red;">' % public.get_msg_gettext('Sorry, something went wrong') + isError.replace("\n",'<br>') + '</a>')
else:
redirectname_md5 = self.__calc_md5(get.redirectname)
@@ -361,7 +361,7 @@ class panelRedirect:
self.SetRedirectApache(get.sitename)
if not hasattr(get,'notreload'):
public.serviceReload()
return public.returnMsg(True, 'EDIT_SUCCESS')
return public.return_msg_gettext(True, 'Setup successfully!')
def del_redirect_multiple(self,get):
'''
@@ -384,9 +384,9 @@ class panelRedirect:
continue
del_successfully.append(redirectname)
except:
del_failed[redirectname]=public.getMsg('DEL_ERROR1')
del_failed[redirectname]=public.get_msg_gettext('There was an error deleting, please try again.')
public.serviceReload()
return {'status': True, 'msg': public.getMsg('DEL_REDIRECT_MULTIPLE',(','.join(del_successfully),)), 'error': del_failed,
return {'status': True, 'msg': public.get_msg_gettext('Delete redirects [{}] successfully',(','.join(del_successfully),)), 'error': del_failed,
'success': del_successfully}
def DeleteRedirect(self,get,multiple=None):
@@ -404,7 +404,7 @@ class panelRedirect:
self.SetRedirectApache(get.sitename)
if not multiple:
public.serviceReload()
return public.returnMsg(True, 'DEL_SUCCESS')
return public.return_msg_gettext(True, 'Successfully deleted')
def GetRedirectList(self,get):
redirectconf = self.__read_config(self.__redirectfile)
@@ -433,7 +433,7 @@ class panelRedirect:
# get.redirectpath = "/"
# get.redirectdomain = "[]"
# get.sitename = sitename
# get.redirectname = public.GetMsg("OLD_CONF")
# get.redirectname = public.get_msg_gettext('Old configuration')
# get.type = 1
# get.holdpath = 1
@@ -470,7 +470,7 @@ class panelRedirect:
conf = re.sub(rep, "", old_conf)
public.writeFile(conf_path, conf)
public.serviceReload()
return public.returnMsg(False, 'CLEAR_OLD_RED')
return public.return_msg_gettext(False, 'Old redirection cleaned')
# 取重定向配置文件
def GetRedirectFile(self,get):
@@ -484,7 +484,7 @@ class panelRedirect:
get.path = "%s/panel/vhost/%s/redirect/%s/%s_%s.conf" % (self.setupPath, get.webserver, sitename,proxyname_md5,sitename)
for i in conf:
if redirectname == i["redirectname"] and sitename == i["sitename"] and i["type"] != 1:
return public.returnMsg(False, 'RED_ALREADY_STOP')
return public.return_msg_gettext(False, 'Redirection suspended')
f = files.files()
return f.GetFileBody(get),get.path
@@ -493,7 +493,7 @@ class panelRedirect:
import files
f = files.files()
return f.SaveFileBody(get)
# return public.returnMsg(True, '保存成功')
# return public.return_msg_gettext(True, '保存成功')
def __CheckRedirect(self,sitename,redirectname):
conf_data = self.__read_config(self.__redirectfile)
+23 -23
View File
@@ -20,7 +20,7 @@ class panelRun:
__run_config_path = '{}/config/run_config'.format(__panel_path)
__run_pids_path = '{}/logs/run_pids'.format(__panel_path)
__run_logs_path = '{}/logs/run_logs'.format(__panel_path)
__log_name = '开机启动项'
__log_name = 'Startup items'
def __init__(self):
@@ -69,7 +69,7 @@ class panelRun:
if get: run_name = get['run_name']
run_file = '{}/{}'.format(self.__run_config_path,run_name)
if not os.path.isfile(run_file):
return public.returnMsg(False,'启动配置不存在!')
return public.return_msg_gettext(False,'Configuration file not exist')
run_info = json.loads(public.readFile(run_file))
return run_info
@@ -98,14 +98,14 @@ class panelRun:
run_script_args = get['run_script_args']
run_env = json.loads(get['run_env'])
if not os.path.exists(run_path):
return public.returnMsg(False,'指定运行目录{}不存在!'.format(run_path))
return public.return_msg_gettext(False,'The specified run directory {} does not exist!'.format(run_path))
if not re.match(r'^\w+$',run_name):
return public.returnMsg(False, '启动项名称格式不正确,支持:[a-zA-Z0-9_]!')
return public.return_msg_gettext(False, 'The startup item name format is incorrect, support: [a-zA-Z0-9_]!')
run_file = '{}/{}'.format(self.__run_config_path,run_name)
if os.path.exists(run_file):
return public.returnMsg(False,'启动配置已存在!')
return public.return_msg_gettext(False,'Launch configuration already exists!')
run_info = {
'run_title': run_title,
@@ -117,8 +117,8 @@ class panelRun:
}
run_info = json.dumps(run_info)
public.writeFile(run_file,run_info)
public.WriteLog(self.__log_name,'创建启动项[]成功!'.format(run_title))
return public.returnMsg(True,'创建成功!')
public.write_log_gettext(self.__log_name,'Create startup item [] successful!'.format(run_title))
return public.return_msg_gettext(True,'Successfully created')
def modify_run(self,get):
@@ -145,15 +145,15 @@ class panelRun:
run_env = json.loads(get['run_env'])
if not os.path.exists(run_path):
return public.returnMsg(False,'指定运行目录{}不存在!'.format(run_path))
return public.return_msg_gettext(False,'The specified run directory {} does not exist!',(run_path,))
if not re.match(r'^\w+$',run_name):
return public.returnMsg(False, '启动项名称格式不正确,支持:[a-zA-Z0-9_]!')
return public.return_msg_gettext(False, 'The startup item name format is incorrect, support: [a-zA-Z0-9_]!')
run_file = '{}/{}'.format(self.__run_config_path,run_name)
if not os.path.exists(run_file):
return public.returnMsg(False,'启动配置不存在!')
return public.return_msg_gettext(False,'The launch configuration does not exist!')
run_info = json.loads(public.readFile(run_file))
run_info['run_title'] = run_title
@@ -162,8 +162,8 @@ class panelRun:
run_info['run_env'] = run_env
run_info = json.dumps(run_info)
public.writeFile(run_file,run_info)
public.WriteLog(self.__log_name,'修改启动项[]成功!'.format(run_title))
return public.returnMsg(True,'修改成功!')
public.write_log_gettext(self.__log_name,'Modify startup item [{}] successful!',(run_title,))
return public.return_msg_gettext(True,'Successfully modified')
def remove_run(self,get):
@@ -178,11 +178,11 @@ class panelRun:
run_name = get['run_name']
run_file = '{}/{}'.format(self.__run_config_path,run_name)
if not os.path.isfile(run_file):
return public.returnMsg(False,'启动配置不存在!')
return public.return_msg_gettext(False,'The launch configuration does not exist!')
os.remove(run_file)
public.WriteLog(self.__log_name,'删除启动项[]成功!'.format(run_name))
return public.returnMsg(True,'删除成功!')
public.write_log_gettext(self.__log_name,'Delete startup item [{}] successful!',(run_name,))
return public.return_msg_gettext(True,'successfully deleted')
def set_run_status(self,get):
'''
@@ -199,14 +199,14 @@ class panelRun:
run_file = '{}/{}'.format(self.__run_config_path,run_name)
if not os.path.isfile(run_file):
return public.returnMsg(False,'启动配置不存在!')
return public.return_msg_gettext(False,'launch configuration does not exist!')
run_info = json.loads(public.readFile(run_file))
run_info['run_status'] = run_status
run_info = json.dumps(run_info)
public.writeFile(run_file,run_info)
public.WriteLog(self.__log_name,'设置启动项[]状态成功!'.format(run_info['title']))
return public.returnMsg(True,'设置成功!')
public.write_log_gettext(self.__log_name,'Setting startup item [{}] status succeeded!',(run_info['title'],))
return public.return_msg_gettext(True,'Setup successfully!')
def stop_run(self,run_name = None):
@@ -219,7 +219,7 @@ class panelRun:
pid = self.get_run_pid(run_name)
if not pid: return True
os.kill(pid,signal.SIGKILL)
public.WriteLog(self.__log_name,'关闭启动项[]成功!'.format(run_name))
public.write_log_gettext(self.__log_name,'Close startup item [{}] successful!',(run_name,))
return True
@@ -267,9 +267,9 @@ class panelRun:
@return dict
'''
pid = self.get_run_pid(run_name)
if not pid: return public.returnMsg(False,'未启动')
if not pid: return public.return_msg_gettext(False,'Not run')
process_info = self.get_process_info(pid)
if not process_info: return public.returnMsg(False,'无法获取进程信息')
if not process_info: return public.return_msg_gettext(False,'Unable to get process information')
return process_info
def get_process_info(self,pid):
@@ -281,7 +281,7 @@ class panelRun:
'''
process_info = {}
p = psutil.Process(pid)
status_ps = {'sleeping':'睡眠','running':'活动'}
status_ps = {'sleeping':'sleeping','running':'running'}
with p.oneshot():
p_mem = p.memory_full_info()
if p_mem.uss + p_mem.rss + p_mem.pss + p_mem.data == 0: return False
@@ -368,7 +368,7 @@ class panelRun:
time.sleep(1)
pid = self.get_script_pid(run_info)
public.writeFile(pid_file,str(pid))
public.WriteLog(self.__log_name, '开机启动{}成功, PID: {}'.format(run_name,pid))
public.write_log_gettext(self.__log_name, 'Startup {} successful, PID:{}',(run_name,pid,))
return True
+39 -39
View File
@@ -20,7 +20,7 @@ try:
except:
pass
class panelSSL:
__APIURL = 'https://brandnew.aapanel.com/api/user'
__APIURL = 'https://www.aapanel.com/api/user'
__APIURL2 = 'http://www.bt.cn/api/Cert'
__UPATH = 'data/userInfo.json'
__PUBKEY = 'data/public.key'
@@ -65,13 +65,13 @@ class panelSSL:
userinfo['token'] = result['res']['access_token']
public.writeFile(self.__UPATH, json.dumps(userinfo))
session['focre_cloud'] = True
return public.returnMsg(True,'Bind successfully')
return public.return_msg_gettext(True,'Bind successfully')
else:
return public.returnMsg(False,'Invalid username or email or password! please check and try again!')
return public.return_msg_gettext(False,'Invalid username or email or password! please check and try again!')
except Exception as ex:
bind = 'data/bind.pl'
if os.path.exists(bind): os.remove(bind)
return public.returnMsg(False, '%s<br>%s' % (public.GetMsg("CONNECT_ERR"), str(rtmp)))
return public.return_msg_gettext(False, '%s<br>%s' % (public.get_msg_gettext('Failed to connect server!'), str(rtmp)))
#删除Token
def DelToken(self,get):
@@ -83,7 +83,7 @@ class panelSSL:
public.ExecShell("rm -f " + self.__UPATH)
session['focre_cloud'] = True
return public.returnMsg(True,"SSL_BTUSER_UN")
return public.return_msg_gettext(True,'Unbound!')
#获取用户信息
def GetUserInfo(self,get):
@@ -93,19 +93,19 @@ class panelSSL:
userTmp = {}
userTmp['username'] = self.__userInfo['email'][0:3]+'****'+self.__userInfo['email'][-4:]
result['status'] = True
result['msg'] = public.getMsg('SSL_GET_SUCCESS')
result['msg'] = public.get_msg_gettext('Got successfully!')
result['data'] = userTmp
else:
userTmp = {}
userTmp['username'] = public.getMsg('SSL_NOT_BTUSER')
userTmp['username'] = public.get_msg_gettext('Please bind your account!')
result['status'] = False
result['msg'] = public.getMsg('SSL_NOT_BTUSER')
result['msg'] = public.get_msg_gettext('Please bind your account!')
result['data'] = userTmp
except:
userTmp = {}
userTmp['username'] = public.getMsg('SSL_NOT_BTUSER')
userTmp['username'] = public.get_msg_gettext('Please bind your account!')
result['status'] = False
result['msg'] = public.getMsg('SSL_NOT_BTUSER')
result['msg'] = public.get_msg_gettext('Please bind your account!')
result['data'] = userTmp
return result
@@ -153,7 +153,7 @@ class panelSSL:
import panelSite
panelSite.panelSite().SetSSLConf(get)
public.serviceReload()
return public.returnMsg(True,'SET_SUCCESS')
return public.return_msg_gettext(True,'Setup successfully!')
#生成商业证书支付订单
def apply_order_pay(self,args):
@@ -311,7 +311,7 @@ class panelSSL:
verify_info['paths'] = []
verify_info['hosts'] = []
if verify_info['data']['application']['status'] == 'ongoing':
return public.returnMsg(False,'订单出现问题,CA正在人工验证,若24小时内依然出现此提示,请联系宝塔')
return public.return_msg_gettext(False,'订单出现问题,CA正在人工验证,若24小时内依然出现此提示,请联系宝塔')
for dinfo in verify_info['data']['dcvList']:
is_https = dinfo['dcvMethod'] == 'HTTPS_CSR_HASH'
if is_https:
@@ -356,7 +356,7 @@ class panelSSL:
#发送请求
def request(self,dname):
self.__PDATA['data'] = json.dumps(self.__PDATA['data'])
result= public.returnMsg(False,'The request failed, please try again later!')
result= public.return_msg_gettext(False,'The request failed, please try again later!')
try:
result = public.httpPost(self.__APIURL2 + '/' + dname,self.__PDATA)
result = json.loads(result)
@@ -378,7 +378,7 @@ class panelSSL:
rs = public.httpPost(self.__APIURL + '/GetSSLList',self.__PDATA)
try:
result = json.loads(rs)
except: return public.returnMsg(False,'SSL_ORDER_GET_FAILED')
except: return public.return_msg_gettext(False,'Failed to get, please try again later!')
result['data'] = self.En_Code(result['data'])
for i in range(len(result['data'])):
@@ -408,11 +408,11 @@ class panelSSL:
#当申请二级域名为www时,检测主域名是否绑定到同一网站
if get.domain[:4] == 'www.':
if not public.M('domain').where('name=? AND pid=?',(get.domain[4:],get.id)).count():
return public.returnMsg(False,"Apply for [%s] certificate to verify [%s] Please bind [%s] and resolve to the site!" % (get.domain,get.domain[4:],get.domain[4:]))
return public.return_msg_gettext(False,"Apply for [{}] certificate to verify [{}] Please bind [{}] and resolve to the site!",(get.domain,get.domain[4:],get.domain[4:]))
#检测是否开启强制HTTPS
if not self.CheckForceHTTPS(get.siteName):
return public.returnMsg(False,'SSL_ORDER_HTTPS_ERR')
return public.return_msg_gettext(False,'[Force HTTPS] is enabled on the current website, please turn off this function before applying for an SSL certificate!')
#获取真实网站运行目录
runPath = self.GetRunPath(get)
@@ -423,19 +423,19 @@ class panelSSL:
authfile = get.path + '/.well-known/pki-validation/fileauth.txt'
if not self.CheckDomain(get):
if not os.path.exists(authfile):
return public.returnMsg(False,'CANT_CREATE',(authfile,))
return public.return_msg_gettext(False,'Cannot create [{}]',(authfile,))
else:
msg = '''{err_msg}<br><a class="btlink" href="{c_url}" target="_blank">{c_url}</a> <br><br>
<p></b>{err_msg1}</b></p>
{err_msg2}<br>
{err_msg3}<br>
{err_msg4}'''.format(c_url = self._check_url,
err_msg=public.getMsg('SSL_ERR_MSG'),
err_msg1=public.getMsg('SSL_ERR_MSG1'),
err_msg2=public.getMsg('SSL_ERR_MSG2'),
err_msg3=public.getMsg('SSL_ERR_MSG3'),
err_msg4=public.getMsg('SSL_ERR_MSG4'))
return public.returnMsg(False,msg)
err_msg=public.get_msg_gettext('Cannot access verification file correctly'),
err_msg1=public.get_msg_gettext('Possible reason:'),
err_msg2=public.get_msg_gettext('1. The resolution is not correct, or the resolution is not effective [Please resolve the domain name correctly, or wait for the resolution to take effect and try again]'),
err_msg3=public.get_msg_gettext('2. Check if there is 301/302 redirection set up [please temporarily turn off the redirection related configuration]'),
err_msg4=public.get_msg_gettext('3. Check whether the website is set to force HTTPS [please turn off the force HTTPS function temporarily]'))
return public.return_msg_gettext(False,msg)
action = 'GetDVSSL'
if hasattr(get,'partnerOrderId'):
@@ -523,7 +523,7 @@ class panelSSL:
try:
sslInfo = json.loads(tmp)
except:
return public.returnMsg(False,tmp)
return public.return_msg_gettext(False,tmp)
sslInfo['data'] = self.En_Code(sslInfo['data'])
try:
@@ -531,13 +531,13 @@ class panelSSL:
if not os.path.exists(spath): public.ExecShell("mkdir -p '" + spath + "'")
public.writeFile(spath + '/fileauth.txt',sslInfo['data']['authValue'])
except:
return public.returnMsg(False,'SSL_CHECK_WRITE_ERR')
return public.return_msg_gettext(False,'Verification error!')
try:
result = json.loads(public.httpPost(self.__APIURL + '/Completed',self.__PDATA))
if 'data' in result:
result['data'] = self.En_Code(result['data'])
except:
result = public.returnMsg(True,'CHECKING')
result = public.return_msg_gettext(True,'Checking...')
n = 0;
my_ok = False
while True:
@@ -598,9 +598,9 @@ class panelSSL:
import panelSite
panelSite.panelSite().SetSSLConf(get)
public.serviceReload()
return public.returnMsg(True,'SET_SUCCESS')
return public.return_msg_gettext(True,'Setup successfully!')
except:
return public.returnMsg(False,'SET_ERROR')
return public.return_msg_gettext(False,'Failed to set')
result['data'] = self.En_Code(result['data'])
return result
@@ -632,9 +632,9 @@ class panelSSL:
import panelSite
panelSite.panelSite().SetSSLConf(get)
public.serviceReload()
return public.returnMsg(True,'SET_SUCCESS')
return public.return_msg_gettext(True,'Setup successfully!')
except Exception as ex:
return public.returnMsg(False,'SET_ERROR,' + public.get_error_info())
return public.return_msg_gettext(False,'Failed to set \n{}',(public.get_error_info(),))
#获取证书列表
def GetCertList(self,get):
@@ -657,17 +657,17 @@ class panelSSL:
def RemoveCert(self,get):
try:
vpath = '/www/server/panel/vhost/ssl/' + get.certName.replace("*.",'')
if not os.path.exists(vpath): return public.returnMsg(False,'CRET_NOT_EXIST')
if not os.path.exists(vpath): return public.return_msg_gettext(False,'Certificate does NOT exist!')
public.ExecShell("rm -rf " + vpath)
return public.returnMsg(True,'CRET_DEL')
return public.return_msg_gettext(True,'Certificate deleted!')
except:
return public.returnMsg(False,'CRET_DEL_FAIL')
return public.return_msg_gettext(False,'Failed to delete!')
#保存证书
def SaveCert(self,get):
try:
certInfo = self.GetCertName(get)
if not certInfo: return public.returnMsg(False,'CRET_RESOLVE_FAIL')
if not certInfo: return public.return_msg_gettext(False,'Certificate parsing failed')
vpath = '/www/server/panel/vhost/ssl/' + certInfo['subject']
vpath=vpath.replace("*.",'')
if not os.path.exists(vpath):
@@ -675,14 +675,14 @@ class panelSSL:
public.writeFile(vpath + '/privkey.pem',public.readFile(get.keyPath))
public.writeFile(vpath + '/fullchain.pem',public.readFile(get.certPath))
public.writeFile(vpath + '/info.json',json.dumps(certInfo))
return public.returnMsg(True,'CRET_SAVE_SUSSESS')
return public.return_msg_gettext(True,'Successfully saved certificate!')
except:
return public.returnMsg(False,'CRET_SAVE_FAIL')
return public.return_msg_gettext(False,'Failed to save certificate!')
#读取证书
def GetCert(self,get):
vpath = os.path.join('/www/server/panel/vhost/ssl' , get.certName.replace("*.",''))
if not os.path.exists(vpath): return public.returnMsg(False,'CRET_NOT_EXIST')
if not os.path.exists(vpath): return public.return_msg_gettext(False,'Certificate does NOT exist!')
data = {}
data['privkey'] = public.readFile(vpath + '/privkey.pem')
data['fullchain'] = public.readFile(vpath + '/fullchain.pem')
@@ -822,13 +822,13 @@ class panelSSL:
# 手动一键续签
def renew_lets_ssl(self, get):
if not os.path.exists('vhost/cert/crontab.json'):
return public.returnMsg(False,'SSL_RENEW_ERR')
return public.return_msg_gettext(False,'There are currently no certificates to renew!')
old_list = json.loads(public.ReadFile("vhost/cert/crontab.json"))
cron_list = old_list
if hasattr(get, 'siteName'):
if not get.siteName in old_list:
return public.returnMsg(False,'WEBSITE_SSL_RENEW_ERR')
return public.return_msg_gettext(False,'There is no certificate that can be renewed on the current website..')
cron_list = {}
cron_list[get.siteName] = old_list[get.siteName]
+1 -1
View File
@@ -100,7 +100,7 @@ class safe:
def checkPHPINI(self):
setupPath = '/www/server';
phps = ['52','53','54','55','56','70','71']
phps = public.get_php_versions()
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 = []
+9 -9
View File
@@ -189,10 +189,10 @@ class panelSearch:
noword 1 不输出行信息 0 默认
'''
def get_search(self, args):
if 'text' not in args or not args.text: return {'error': 'Search content cannot be empty'}
if 'exts' not in args or not args.exts: return {'error': 'The suffix cannot be empty; please enter [ *.* ] to search all files'}
if 'path' not in args or not args.path or args.path == '/': return {'error': 'The directory cannot be empty or /'}
if not os.path.isdir(args.path): return {'error': 'Directory does not exist'}
if 'text' not in args or not args.text: return {'error': public.get_msg_gettext('Search content cannot be empty')}
if 'exts' not in args or not args.exts: return {'error': public.get_msg_gettext('The suffix cannot be empty; please enter [ *.* ] to search all files')}
if 'path' not in args or not args.path or args.path == '/': return {'error': public.get_msg_gettext('The directory cannot be empty or /')}
if not os.path.isdir(args.path): return {'error': public.get_msg_gettext('Directory does not exist')}
text=args.text
exts=args.exts
path=args.path
@@ -217,11 +217,11 @@ class panelSearch:
noword 1 不输出行信息 0 默认
'''
def get_replace(self, args):
if 'text' not in args or not args.text: return {'error': 'Search content cannot be empty'}
if 'rtext' not in args or not args.text: return {'error': 'The content to be replaced cannot be empty'}
if 'exts' not in args or not args.exts: return {'error': 'The suffix cannot be empty; please enter [ *.* ] to search all files'}
if 'path' not in args or not args.path or args.path == '/': return {'error': 'The directory cannot be empty or /'}
if not os.path.isdir(args.path): return {'error': 'Directory does not exist'}
if 'text' not in args or not args.text: return {'error': public.get_msg_gettext('Search content cannot be empty')}
if 'rtext' not in args or not args.text: return {'error': public.get_msg_gettext('The content to be replaced cannot be empty')}
if 'exts' not in args or not args.exts: return {'error': public.get_msg_gettext('The suffix cannot be empty; please enter [ *.* ] to search all files')}
if 'path' not in args or not args.path or args.path == '/': return {'error': public.get_msg_gettext('The directory cannot be empty or /')}
if not os.path.isdir(args.path): return {'error': public.get_msg_gettext('Directory does not exist')}
is_backup = int(args.isbackup) if 'isbackup' in args else 0
text = args.text
rtext = args.rtext
+710 -318
View File
File diff suppressed because it is too large Load Diff
+20 -19
View File
@@ -140,7 +140,7 @@ class bt_task:
"kill -9 $(ps aux|grep '"+task_info['shell']+"'|grep -v grep|awk '{print $2}')")
public.ExecShell("/etc/init.d/bt start")
return public.returnMsg(True, 'TASK_CANCEL')
return public.return_msg_gettext(True, 'Task cancelled!')
# 取一条任务
def get_task_find(self, id):
@@ -187,7 +187,6 @@ class bt_task:
self.backup_site(task_shell, log_file)
elif task_type == 7: # 恢复网站
pass
# 标记状态与结束时间
self.modify_task(id, 'status', 1)
self.modify_task(id, 'endtime', int(time.time()))
@@ -235,7 +234,7 @@ class bt_task:
if not os.path.exists(log_file):
data = ''
if(task_type == '1'):
data = {'name': public.GetMsg("DOWNLOAD_FILE"), 'total': 0, 'used': 0,
data = {'name': public.get_msg_gettext('Download file'), 'total': 0, 'used': 0,
'pre': 0, 'speed': 0, 'time': 0}
return data
@@ -262,7 +261,7 @@ class bt_task:
speed_total = re.findall(
r"([\d\.]+[BbKkMmGg]).+\s+(\d+)%\s+([\d\.]+[KMBGkmbg])\s+(\w+[sS])", speed_tmp)
if not speed_total:
data = {'name':public.getMsg('DOWNLOAD_FILE1',(filename,)),'total':0,'used':0,'pre':0,'speed':0,'time':0}
data = {'name':public.get_msg_gettext('Download file {}',(filename,)),'total':0,'used':0,'pre':0,'speed':0,'time':0}
else:
speed_total = speed_total[0]
used = speed_total[0]
@@ -271,11 +270,13 @@ class bt_task:
float(speed_total[0].lower().replace('k', '')) * 1024)
u_time = speed_total[3].replace(
'h', 'Hour').replace('m', 'Minute').replace('s', 'Second')
data = {'name': public.getMsg('DOWNLOAD_FILE1',(filename,)),'total': total, 'used': used, 'pre': speed_total[1], 'speed': speed_total[2], 'time': u_time}
data = {'name': public.get_msg_gettext('Download file {}',(filename,)),'total': total, 'used': used, 'pre': speed_total[1], 'speed': speed_total[2], 'time': u_time}
else:
data = public.ExecShell("tail -n {} {}".format(num, log_file))[0]
if type(data) == list:
return ''
if isinstance(data,bytes):
data = data.decode('utf-8')
data = data.replace('\x08', '').replace('\n', '<br>')
return data
@@ -303,7 +304,7 @@ class bt_task:
path = path.encode('utf-8')
if sfile.find(',') == -1:
if not os.path.exists(path+'/'+sfile):
return public.returnMsg(False, 'FILE_NOT_EXISTS')
return public.return_msg_gettext(False, 'Configuration file not exist')
# 处理多文件压缩
sfiles = ''
for sfile in sfile.split(','):
@@ -325,11 +326,11 @@ class bt_task:
public.ExecShell("cd '" + path + "' && "+rar_file +
" a -r '" + dfile + "' " + sfiles + " &> " + log_file)
else:
return public.returnMsg(False,'NOT_SUP_COMP_FORMAT')
return public.return_msg_gettext(False,'Specified compression format is not supported!')
self.set_file_accept(dfile)
#public.WriteLog("TYPE_FILE", 'ZIP_SUCCESS', (sfiles, dfile),not_web = self.not_web)
return public.returnMsg(True, 'ZIP_SUCCESS')
#public.WriteLog("TYPE_FILE", 'Compression succeeded!', (sfiles, dfile),not_web = self.not_web)
return public.return_msg_gettext(True, 'Compression succeeded!')
# 文件解压
def _unzip(self, sfile, dfile, password, log_file):
@@ -337,7 +338,7 @@ class bt_task:
sfile = sfile.encode('utf-8')
dfile = dfile.encode('utf-8')
if not os.path.exists(sfile):
return public.returnMsg(False, 'FILE_NOT_EXISTS')
return public.return_msg_gettext(False, 'Configuration file not exist')
# 判断压缩包格式
if sfile[-4:] == '.zip':
@@ -372,8 +373,8 @@ class bt_task:
user = pwd.getpwuid(os.stat(dfile).st_uid).pw_name
public.ExecShell("chown %s:%s %s" % (user, user, dfile))
#public.WriteLog("TYPE_FILE", 'UNZIP_SUCCESS', (sfile, dfile),not_web = self.not_web)
return public.returnMsg(True, 'UNZIP_SUCCESS')
#public.WriteLog("TYPE_FILE", 'Uncompression succeeded!', (sfile, dfile),not_web = self.not_web)
return public.return_msg_gettext(True, 'Uncompression succeeded!')
# 备份网站
def backup_site(self, id, log_file):
@@ -395,7 +396,7 @@ class bt_task:
sql = public.M('backup').add('type,name,pid,filename,size,addtime',
(0, fileName, find['id'], zipName, 0, public.getDate()))
public.WriteLog('TYPE_SITE', 'SITE_BACKUP_SUCCESS', (find['name'],),not_web = self.not_web)
return public.returnMsg(True, 'BACKUP_SUCCESS')
return public.return_msg_gettext(True, 'Backup Succeeded!')
# 备份数据库
def backup_database(self, id, log_file):
@@ -413,7 +414,7 @@ class bt_task:
public.ExecShell("/www/server/mysql/bin/mysqldump --force --opt \"" +
name + "\" | gzip > " + backupName)
if not os.path.exists(backupName):
return public.returnMsg(False, 'BACKUP_ERROR')
return public.return_msg_gettext(False, 'Backup error!')
self.mypass(False, find['mysql_root'])
@@ -422,7 +423,7 @@ class bt_task:
sql.add('type,name,pid,filename,size,addtime',
(1, fileName, id, backupName, 0, addTime))
public.WriteLog("TYPE_DATABASE", "DATABASE_BACKUP_SUCCESS", (name,),not_web = self.not_web)
return public.returnMsg(True, 'BACKUP_SUCCESS')
return public.return_msg_gettext(True, 'Backup Succeeded!')
# 导入数据库
def input_database(self, id, file, log_file):
@@ -432,7 +433,7 @@ class bt_task:
exts = ['sql', 'gz', 'zip']
ext = tmp[len(tmp) - 1]
if ext not in exts:
return public.returnMsg(False, 'DATABASE_INPUT_ERR_FORMAT')
return public.return_msg_gettext(False, 'Select sql/gz/zip file!')
isgzip = False
if ext != 'sql':
@@ -454,7 +455,7 @@ class bt_task:
isgzip = True
if not os.path.exists(backupPath + '/' + tmpFile) or tmpFile == '':
return public.returnMsg(False, 'FILE_NOT_EXISTS', (tmpFile,))
return public.return_msg_gettext(False, 'Configuration file not exist', (tmpFile,))
self.mypass(True, root)
public.ExecShell(public.GetConfigValue('setup_path') + "/mysql/bin/mysql -uroot -p" +
root + " --force \"" + name + "\" < " + backupPath + '/' + tmpFile)
@@ -470,8 +471,8 @@ class bt_task:
'setup_path') + "/mysql/bin/mysql -uroot -p" + root + " --force \"" + name + "\" < " + file)
self.mypass(False, root)
public.WriteLog("TYPE_DATABASE", 'DATABASE_INPUT_SUCCESS', (name,),not_web = self.not_web)
return public.returnMsg(True, 'DATABASE_INPUT_SUCCESS')
public.WriteLog("TYPE_DATABASE", 'Successfully imported database [{}]', (name,),not_web = self.not_web)
return public.return_msg_gettext(True, 'Successfully imported database!')
# 配置
def mypass(self, act, root):
+1 -7
View File
@@ -18,14 +18,8 @@ from BTPanel import Response
def get_buff_size(file_size):
buff_size = 2097152
if file_size < 104857600:
buff_size = 2097152
elif file_size < 524288000:
if file_size > 1073741824:
buff_size = 4194304
elif file_size < 1073741824:
buff_size = 8388608
else:
buff_size = 10485760
return buff_size
def partial_response(path, start, end=None):
+1 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/python
#coding: utf-8
# Author: <lkqiang>lkq@bt.cn
# Author: lkqiang<lkq@bt.cn>
# panelWaf.py
# code: 面板基础安全类
# +-------------------------------------------------------------------
+18 -14
View File
@@ -48,21 +48,25 @@ class panelWarning:
}
result_file = self.__result + '/' + m_name + '.pl'
not_force = True
if 'force' in args:
not_force = m_info['ignore']
# not_force = True
# if 'force' in args:
# not_force = m_info['ignore']
if os.path.exists(result_file) and not_force:
m_info['status'],m_info['msg'],m_info['check_time'],m_info['taking'] = json.loads(public.readFile(result_file))
else:
try:
s_time = time.time()
m_info['status'],m_info['msg'] = p[m_name].check_run()
m_info['taking'] = round(time.time() - s_time,6)
m_info['check_time'] = int(time.time())
public.writeFile(result_file,json.dumps([m_info['status'],m_info['msg'],m_info['check_time'],m_info['taking']],))
except:
continue
# if os.path.exists(result_file) and not_force:
# try:
# m_info['status'],m_info['msg'],m_info['check_time'],m_info['taking'] = json.loads(public.readFile(result_file))
# except:
# if os.path.exists(result_file): os.remove(result_file)
# continue
# else:
try:
s_time = time.time()
m_info['status'],m_info['msg'] = p[m_name].check_run()
m_info['taking'] = round(time.time() - s_time,6)
m_info['check_time'] = int(time.time())
public.writeFile(result_file,json.dumps([m_info['status'],m_info['msg'],m_info['check_time'],m_info['taking']],))
except:
continue
if m_info['ignore']:
+8 -5
View File
@@ -60,7 +60,7 @@ class panel_restore:
# 判断备份文件是否存在,如果不存在继续检查是否远程备份
if not os.path.exists(local_backup_file_path):
self._progress_rewrite('No backup file found: {}'.format(str(local_backup_file_path)))
return public.returnMsg(False, 'Panel does not find the backup file: {}'.format(local_backup_file_path))
return public.return_msg_gettext(False, 'Panel does not find the backup file: {}'.format(local_backup_file_path))
# 将网站目录移至回收站
self._progress_rewrite('Move the current website directory to the recycle bin: {}'.format(str(args.path)))
self._remove_old_website_file_to_trush(args)
@@ -158,14 +158,14 @@ class panel_restore:
self._download_google_drive_file(args)
result = self._restore_backup(self._local_file, site_info, args)
else:
return public.ExecShell(False,'Currently only supports restoring local, Google storage and AWS S3 backups')
return public.return_msg_gettext(False,'Currently only supports restoring local, Google storage and AWS S3 backups')
if os.path.exists(self._local_file):
os.remove(self._local_file)
if result:
self._progress_rewrite('Recovery failed: {}'.format(str(site_info['site_path'])))
return result
self._progress_rewrite('Successful recovery: {}'.format(str(site_info['site_path'])))
return public.returnMsg(True,'Restore Successful')
return public.return_msg_gettext(True,'Restore Successful')
# 取任务进度
def get_progress(self, get):
@@ -187,6 +187,8 @@ class panel_restore:
@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 数据库名
"""
if "|" not in args.file:
return public.returnMsg(True,'success')
try:
backup_info = args.file.split('|')
args.file_name = backup_info[-1]
@@ -202,7 +204,8 @@ class panel_restore:
elif backup_method == 'Google Drive':
self._download_google_drive_file(args)
else:
return public.ExecShell(False,'Currently only supports restoring local, Google storage and AWS S3 backups')
return public.returnMsg(False,'Currently only supports restoring local, Google storage and AWS S3 backups')
public.ExecShell('mv {} {}/database'.format(self._local_file, self._get_local_backup_path()))
return public.returnMsg(True,'success')
except:
return False
return public.returnMsg(False,"Download error!")
+1 -1
View File
@@ -17,7 +17,7 @@ pip = public.get_pip_bin()
try:
import telegram
except:
public.ExecShell('{} install telegram'.format(pip))
public.ExecShell('{} install python-telegram-bot'.format(pip))
import telegram
class panel_telegram_bot:
+6 -5
View File
@@ -12,7 +12,7 @@
#+--------------------------------------------------------------------
import public,json,os,time,sys,re
from BTPanel import session
from BTPanel import session,cache
class obj: id=0
class plugin_deployment:
__setupPath = 'data'
@@ -21,6 +21,7 @@ class plugin_deployment:
__tmp = '/www/server/panel/temp/'
timeoutCount = 0
oldTime = 0
_speed_key = 'dep_download_speed'
#获取列表
def GetList(self,get):
@@ -76,7 +77,7 @@ class plugin_deployment:
if sys.version_info[0] == 2: filename = filename.encode('utf-8')
if os.path.exists(filename):
if os.path.getsize(filename) > 100: return pinfo
public.ExecShell("wget -O " + filename + ' http://www.bt.cn' + m_uri + " &")
public.ExecShell("wget -O " + filename + ' https://www.bt.cn' + m_uri + " &")
return pinfo
#获取插件列表
@@ -103,7 +104,7 @@ class plugin_deployment:
try:
jsonFile = self.__setupPath + '/deployment_list.json'
if not 'package' in session or not os.path.exists(jsonFile) or hasattr(get,'force'):
downloadUrl = 'http://www.bt.cn/api/panel/get_deplist'
downloadUrl = 'https://www.bt.cn/api/panel/get_deplist'
pdata = public.get_pdata()
tmp = json.loads(public.httpPost(downloadUrl,pdata,3))
if not tmp: return public.returnMsg(False,'Failed to get from the cloud!')
@@ -269,7 +270,7 @@ class plugin_deployment:
#下载文件
if isDownload:
self.WriteLogs(json.dumps({'name':'Downloading file ...','total':0,'used':0,'pre':0,'speed':0}))
if pinfo['versions'][0]['download']: self.DownloadFile('http://www.bt.cn/api/Pluginother/get_file?fname=' + pinfo['versions'][0]['download'], packageZip)
if pinfo['versions'][0]['download']: self.DownloadFile('https://www.bt.cn/api/Pluginother/get_file?fname=' + pinfo['versions'][0]['download'], packageZip)
if not os.path.exists(packageZip): return public.returnMsg(False,'File download failed!' + packageZip)
@@ -470,7 +471,7 @@ class plugin_deployment:
p = panelAuth.panelAuth()
pdata = p.create_serverid(None);
pdata['pid'] = id;
p_url = 'http://www.bt.cn/api/pluginother/create_order_okey'
p_url = 'https://www.bt.cn/api/pluginother/create_order_okey'
public.httpPost(p_url,pdata)
#获取进度
+62 -1
View File
@@ -1,2 +1,63 @@
#coding: utf-8
import public,re
class projectBase:
pass
def check_port(self, port):
'''
@name 检查端口是否被占用
@args port:端口号
@return: 被占用返回True否则返回False
@author: lkq 2021-08-28
'''
a = public.ExecShell("netstat -nltp|awk '{print $4}'")
if a[0]:
if re.search(':' + port + '\n', a[0]):
return True
else:
return False
else:
return False
def is_domain(self, domain):
'''
@name 验证域名合法性
@args domain:域名
@return: 合法返回True否则返回False
@author: lkq 2021-08-28
'''
import re
domain_regex = re.compile(r'(?:[A-Z0-9_](?:[A-Z0-9-_]{0,247}[A-Z0-9])?\.)+(?:[A-Z]{2,6}|[A-Z0-9-]{2,}(?<!-))\Z', re.IGNORECASE)
return True if domain_regex.match(domain) else False
def generate_random_port(self):
'''
@name 生成随机端口
@args
@return: 端口号
@author: lkq 2021-08-28
'''
import random
port = str(random.randint(5000, 10000))
while True:
if not self.check_port(port): break
port = str(random.randint(5000, 10000))
return port
def IsOpen(self, port):
'''
@name 检查端口是否被占用
@args port:端口号
@return: 被占用返回True否则返回False
@author: lkq 2021-08-28
'''
ip = '0.0.0.0'
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, int(port)))
s.shutdown(2)
return True
except:
return False
+118 -24
View File
@@ -666,6 +666,7 @@ export PATH
error_list = []
for domain in domains:
domain = domain.strip()
if not domain: return public.return_error('Domain name cannot be empty',data='')
domain_arr = domain.split(':')
if len(domain_arr) == 1:
domain_arr.append(80)
@@ -683,8 +684,8 @@ export PATH
if success_list:
public.M('sites').where('id=?',(project_id,)).save('project_config',json.dumps(project_find['project_config']))
self.set_config(get.project_name)
return public.return_data(True,"[{}] domain names added successfully, [{}] failed!".format(len(success_list),len(error_list)),error_msg=error_list)
return public.return_data(True,"[{}] domain names added successfully, [{}] failed!".format(len(success_list),len(error_list)),error_msg=error_list)
return public.return_data(False,"[{}] domain names added successfully, [{}] failed!".format(len(success_list),len(error_list)),error_msg=error_list)
def project_remove_domain(self,get):
@@ -1093,26 +1094,71 @@ export PATH
@param pid: string<项目pid>
@return list
'''
plugin_name = None
project_name = None
for pid_name in os.listdir(self._node_pid_path):
pid_file = '{}/{}'.format(self._node_pid_path,pid_name)
s_pid = int(public.readFile(pid_file))
#s_pid = int(public.readFile(pid_file))
data = public.readFile(pid_file)
if isinstance(data,str) and data:
s_pid = int(data)
else:
return []
if pid == s_pid:
plugin_name = pid_name[:-4]
project_name = pid_name[:-4]
break
project_find = self.get_project_find(plugin_name)
project_find = self.get_project_find(project_name)
if not project_find: return []
if not self._pids: self._pids = psutil.pids()
all_pids = []
for i in self._pids:
try:
p = psutil.Process(i)
if p.cwd() == project_find['path'] and p.username() == project_find['project_config']['run_user']:
if p.name() in ['node','npm','pm2']:
if p.cwd() == project_find['path']:
pname = p.name()
if pname in ['node','npm','pm2','yarn'] or pname.find('node ') == 0:
cmdline = ','.join(p.cmdline())
if cmdline.find('God Daemon') != -1:continue
env_list = p.environ()
if 'name' in env_list:
if not env_list['name'] == project_name: continue
if 'NODE_PROJECT_NAME' in env_list:
if not env_list['NODE_PROJECT_NAME'] == project_name: continue
all_pids.append(i)
except: continue
return all_pids
def get_project_state_by_cwd(self,project_name):
'''
@name 通过cwd获取项目状态
@author hwliang<2022-01-17>
@param project_name<string> 项目名称
@return bool or list
'''
project_find = self.get_project_find(project_name)
self._pids = psutil.pids()
if not project_find: return []
all_pids = []
for i in self._pids:
try:
p = psutil.Process(i)
if p.cwd() == project_find['path']:
pname = p.name()
if pname in ['node','npm','pm2','yarn'] or pname.find('node ') == 0:
cmdline = ','.join(p.cmdline())
if cmdline.find('God Daemon') != -1:continue
env_list = p.environ()
if 'name' in env_list:
if not env_list['name'] == project_name: continue
if 'NODE_PROJECT_NAME' in env_list:
if not env_list['NODE_PROJECT_NAME'] == project_name: continue
all_pids.append(i)
except: continue
if all_pids:
pid_file = "{}/{}.pid".format(self._node_pid_path,project_name)
public.writeFile(pid_file,str(all_pids[0]))
return all_pids
return False
def kill_pids(self,get=None,pids = None):
'''
@name 结束进程列表
@@ -1175,7 +1221,10 @@ export PATH
nodejs_version = project_find['project_config']['nodejs_version']
node_bin = self.get_node_bin(nodejs_version)
npm_bin = self.get_npm_bin(nodejs_version)
project_script = project_find['project_config']['project_script'].strip()
project_script = project_find['project_config']['project_script'].strip().replace(' ',' ')
if project_script[:3] == 'pm2': # PM2启动方式处理
project_script = project_script.replace('pm2 ','pm2 -u {} -n {} '.format(project_find['project_config']['run_user'],get.project_name))
project_find['project_config']['run_user'] = 'root'
log_file = "{}/{}.log".format(self._node_logs_path,get.project_name)
if not project_script: return public.return_error('No startup script configured')
@@ -1184,6 +1233,7 @@ export PATH
# 生成启动脚本
if os.path.exists(project_script):
start_cmd = '''{last_env}
export NODE_PROJECT_NAME="{project_name}"
cd {project_cwd}
nohup {node_bin} {project_script} 2>&1 >> {log_file} &
echo $! > {pid_file}
@@ -1193,10 +1243,12 @@ echo $! > {pid_file}
project_script = project_script,
log_file = log_file,
pid_file = pid_file,
last_env = last_env
last_env = last_env,
project_name = get.project_name
)
elif project_script in scripts_keys:
start_cmd = '''{last_env}
export NODE_PROJECT_NAME="{project_name}"
cd {project_cwd}
nohup {npm_bin} run {project_script} 2>&1 >> {log_file} &
echo $! > {pid_file}
@@ -1206,10 +1258,12 @@ echo $! > {pid_file}
project_script = project_script,
pid_file = pid_file,
log_file = log_file,
last_env = last_env
last_env = last_env,
project_name = get.project_name
)
else:
start_cmd = '''{last_env}
export NODE_PROJECT_NAME="{project_name}"
cd {project_cwd}
nohup {project_script} 2>&1 >> {log_file} &
echo $! > {pid_file}
@@ -1218,7 +1272,8 @@ echo $! > {pid_file}
project_script = project_script,
pid_file = pid_file,
log_file = log_file,
last_env = last_env
last_env = last_env,
project_name = get.project_name
)
script_file = "{}/{}.sh".format(self._node_run_scripts,get.project_name)
@@ -1236,6 +1291,10 @@ echo $! > {pid_file}
# 执行脚本文件
p = public.ExecShell("bash {}".format(script_file),user=project_find['project_config']['run_user'])
time.sleep(1)
n = 0
while n < 5:
if self.get_project_state_by_cwd(get.project_name): break
n+=1
if not os.path.exists(pid_file):
p = '\n'.join(p)
if p.find('[Errno 0]') != -1:
@@ -1245,7 +1304,10 @@ echo $! > {pid_file}
return public.return_error('failed to activate<pre>{}</pre>'.format(p))
# 获取PID
pid = int(public.readFile(pid_file))
try:
pid = int(public.readFile(pid_file))
except:
return public.return_error('Startup failed <br>{}'.format(public.GetNumLines(log_file,20)))
pids = self.get_project_pids(pid=pid)
if not pids:
if os.path.exists(pid_file): os.remove(pid_file)
@@ -1263,13 +1325,33 @@ echo $! > {pid_file}
}
@return dict
'''
project_find = self.get_project_find(get.project_name)
if not project_find: return public.return_error('Project does not exist')
project_script = project_find['project_config']['project_script'].strip().replace(' ',' ')
pid_file = "{}/{}.pid".format(self._node_pid_path,get.project_name)
if not os.path.exists(pid_file): return public.return_error('Project did not start')
pid = int(public.readFile(pid_file))
pids = self.get_project_pids(pid=pid)
if not pids: return public.return_error('Project did not start')
self.kill_pids(pids=pids)
if project_script.find('pm2 start') != -1: # 处理PM2启动的项目
nodejs_version = project_find['project_config']['nodejs_version']
last_env = self.get_last_env(nodejs_version,project_find['path'])
project_script = project_script.replace('pm2 start','pm2 stop')
public.ExecShell('''{}
cd {}
{}'''.format(last_env,project_find['path'],project_script))
else:
pid_file = "{}/{}.pid".format(self._node_pid_path,get.project_name)
if not os.path.exists(pid_file): return public.return_error('Project did not start')
data = public.readFile(pid_file)
if isinstance(data,str) and data:
pid = int(data)
pids = self.get_project_pids(pid=pid)
else:
return public.return_error('Project did not start')
if not pids: return public.return_error('Project did not start')
self.kill_pids(pids=pids)
if os.path.exists(pid_file): os.remove(pid_file)
time.sleep(0.5)
pids = self.get_project_state_by_cwd(get.project_name)
if pids: self.kill_pids(pids=pids)
return public.return_data(True, 'Stopped successfully')
def restart_project(self,get):
@@ -1314,8 +1396,12 @@ echo $! > {pid_file}
load_info = {}
pid_file = "{}/{}.pid".format(self._node_pid_path,project_name)
if not os.path.exists(pid_file): return load_info
pid = int(public.readFile(pid_file))
pids = self.get_project_pids(pid=pid)
data = public.readFile(pid_file)
if isinstance(data,str) and data:
pid = int(data)
pids = self.get_project_pids(pid=pid)
else:
return load_info
if not pids: return load_info
for i in pids:
process_info = self.get_process_info_by_pid(i)
@@ -1514,9 +1600,13 @@ echo $! > {pid_file}
if get: project_name = get.project_name.strip()
pid_file = "{}/{}.pid".format(self._node_pid_path,project_name)
if not os.path.exists(pid_file): return False
pid = int(public.readFile(pid_file))
pids = self.get_project_pids(pid=pid)
if not pids: return False
data=public.readFile(pid_file)
if isinstance(data,str) and data:
pid = int(data)
pids = self.get_project_pids(pid=pid)
else:
return self.get_project_state_by_cwd(project_name)
if not pids: return self.get_project_state_by_cwd(project_name)
return True
def get_project_find(self,project_name):
@@ -1556,12 +1646,16 @@ echo $! > {pid_file}
'''
project_info['project_config'] = json.loads(project_info['project_config'])
project_info['run'] = self.get_project_run_state(project_name = project_info['name'])
project_info['load_info'] = self.get_project_load_info(project_name = project_info['name'])
project_info['load_info'] = {}
if project_info['run']:
project_info['load_info'] = self.get_project_load_info(project_name = project_info['name'])
project_info['ssl'] = self.get_ssl_end_date(project_name = project_info['name'])
project_info['listen'] = []
project_info['listen_ok'] = True
if project_info['load_info']:
for pid in project_info['load_info'].keys():
if not 'connections' in project_info['load_info'][pid]:
project_info['load_info'][pid]['connections'] = []
for conn in project_info['load_info'][pid]['connections']:
if not conn['status'] == 'LISTEN': continue
if not conn['local_port'] in project_info['listen']:
+2112 -214
View File
File diff suppressed because it is too large Load Diff
+17 -2
View File
@@ -51,8 +51,23 @@ def check_run():
if not public.ExecShell("lsof -i :{}".format(port_tmp[0]))[0]:
return True,'MySQL is not installed'
result = public.check_port_stat(int(port_tmp[0]),public.GetLocalIp())
if result == 0:
return True,'Risk-free'
#兼容socket能连通但实际端口不通情况
if result != 0:
res=''
if os.path.exists('/usr/sbin/firewalld'):
res=public.ExecShell('firewall-cmd --list-all')
elif os.path.exists('/usr/sbin/ufw'):
try:
res=public.ExecShell('sudo ufw status verbose')
except:
res=public.ExecShell('ufw status verbose')
else:
pass
check_str=' '+port_tmp[0]+'/'
if res[0].find(check_str) == -1:
return True,'Risk-free'
else:return True,'Risk-free'
fail2ban_file = '/www/server/panel/plugin/fail2ban/config.json'
if os.path.exists(fail2ban_file):
+1 -1
View File
@@ -37,7 +37,7 @@ def check_run():
port = public.readFile(port_file)
if not port: return True,'Rick-free'
port = int(port)
if port != 8888 and port != 7800:
if port != 8888:
return True,'Rick-free'
return False,'The panel port is the default port ({}), which may cause unnecessary security risks'.format(port)
+1 -1
View File
@@ -35,7 +35,7 @@ def check_run():
@return tuple (status<bool>,msg<string>)
'''
not_uini = []
site_list = public.M('sites').where('status=?',(1,)).field('name,path').select()
site_list = public.M('sites').where('status=? AND project_type=?',(1,'PHP')).field('name,path').select()
for s in site_list:
path = get_site_run_path(s['name'],s['path'])
user_ini = path + '/.user.ini'
+19 -39
View File
@@ -109,7 +109,6 @@ class send_to_user:
def read_thread(self):
if not public.M('send_settings').count():return False
send_data=public.M('send_settings').field('id,name,type,path,send_type,inser_time,last_time,time_frame').select()
print(send_data)
for i in send_data:
if (int(time.time())-int(i['last_time']))<int(i['time_frame']):continue
if i['type']=='json':
@@ -118,23 +117,21 @@ class send_to_user:
if not read_file:continue
if not read_file[0]:continue
for i2 in read_file:
self.inser_send_msg(i['name'],i['send_type'],self.get_ip()+'服务器存在问题-->'+i2[1]+',触发告警时间:'+self.dtchg(int(time.time())),'json',i2[0])
self.inser_send_msg(i['name'],i['send_type'],self.get_ip()+"服务器触发告警信息为: "+i2[1]+',触发告警时间:'+self.dtchg(int(time.time())),'json',i2[0])
public.writeFile(i['path'], '')
public.M('send_settings').where("id=?", (i['id'],)).update({"last_time": int(time.time())})
continue
if i['type']=='file':
if os.path.exists(i['path']):
self.inser_send_msg(i['name'], i['send_type'], '堡塔'+i['name']+'提醒您服务器'+self.get_ip()+'存在异常,详情请登陆面板查看'+i['name']+',触发告警时间:'+self.dtchg(int(time.time())), 'file', int(time.time()))
public.M('send_settings').where("id=?", (i['id'],)).update({"last_time": int(time.time())})
os.system('rm -rf %s'%i['path'])
if os.path.exists(i['path']):os.system('rm -rf %s'%i['path'])
else:
continue
def send(self,title,body):
tongdao = self.mail.get_settings()
return self.mail.qq_smtp_send(tongdao['user_mail']['mail_list'], title=title, body=body)
def send_dingding(self,count):
return self.mail.dingding_send(count)
try:
f=open(i['path'],'r')
for i2 in f:
i2 =i2.strip()
if i2:
self.inser_send_msg(i['name'], i['send_type'],self.get_ip()+"服务器触发告警信息为: "+i2+',触发告警时间:'+self.dtchg(int(time.time())), 'file', int(time.time()))
os.remove(i['path'])
public.M('send_settings').where("id=?", (i['id'],)).update({"last_time": int(time.time())})
except:
os.remove(i['path'])
def __write_log(self,name, msg):
public.WriteLog(name+'告警', msg)
@@ -146,34 +143,17 @@ class send_to_user:
count=1
for i in send_msg:
if count>=4:break
settings=self.mail.get_settings()
if i['send_type']=='mail':
if not settings['user_mail']['user_name']:continue
if i['name']=='Nginx防火墙' or i['name'] == 'Apache防火墙':
if self.send(i['name'] + '提醒您' + self.get_ip() + '服务器正在遭受攻击', i['msg']):
self.__write_log(i['name'], i['msg'])
public.M('send_msg').where("id=?", (i['id'],)).update({"is_send": True})
else:
if self.send(i['name']+'提醒您'+self.get_ip()+'服务器存在风险', i['msg']):
self.__write_log(i['name'],i['msg'])
public.M('send_msg').where("id=?", (i['id'],)).update({"is_send":True})
if public.send_mail(i['name'], i['msg']):
self.__write_log(i['name'], i['msg'])
public.M('send_msg').where("id=?", (i['id'],)).update({"is_send":True})
if i['send_type']=='dingding':
if not settings['dingding']['dingding']: continue
if i['name'] == 'Nginx防火墙' or i['name'] == 'Apache防火墙':
if self.send(i['name'] + '提醒您' + self.get_ip() + '服务器正在遭受攻击', i['msg']):
self.__write_log(i['name'], i['msg'])
public.M('send_msg').where("id=?", (i['id'],)).update({"is_send": True})
else:
if self.send_dingding(i['msg']):
self.__write_log(i['name'], i['msg'])
public.M('send_msg').where("id=?", (i['id'],)).update({"is_send": True})
if public.send_dingding(i['msg']):
self.__write_log(i['name'], i['msg'])
public.M('send_msg').where("id=?", (i['id'],)).update({"is_send": True})
count += 1
public.M('send_msg').where("is_send=?", (True,)).delete()
def main(self):
try:
self.read_thread()
self.send_msg()
except:
pass
self.read_thread()
self.send_msg()
+12 -11
View File
@@ -93,6 +93,7 @@ class setPanelLets:
now = time.time()
if time_stamp > int(now):
return i
for i in gcl:
for d in i['dns']:
d = d.split('.')
if '*' in d and d[1:] == get.domain.split('.')[1:]:
@@ -139,8 +140,8 @@ class setPanelLets:
public.writeFile(self.__panel_cert_path + "certificate.pem", self.__tmp_cert)
# 记录证书源
def __save_cert_source(self,domain,email):
public.writeFile(self.__panel_cert_path+"lets.info",json.dumps({"domain":domain,"cert_type":"2","email":email}))
def __save_cert_source(self,domain):
public.writeFile(self.__panel_cert_path+"lets.info",json.dumps({"domain":domain,"cert_type":"2"}))
# 获取证书源
def get_cert_source(self):
@@ -192,10 +193,10 @@ class setPanelLets:
panel_cert_data = self.__check_panel_cert()
if not panel_cert_data:
self.__write_panel_cert()
return public.returnMsg(True,'')
return public.returnMsg(True,'1')
if panel_cert_data["key"] != self.__tmp_key and panel_cert_data["cert"] != self.__tmp_cert:
self.__write_panel_cert()
return public.returnMsg(True,'')
return public.returnMsg(True,'1')
return public.returnMsg(True, '')
# 设置lets证书
@@ -209,7 +210,7 @@ class setPanelLets:
domain = self.__check_panel_domain()
get.domain = domain
if not domain:
return public.returnMsg(False, "You need to bind the domain name to the panel before you can apply for the Let\'s Encrypt certificate.")
return public.returnMsg(False, "You need to bind the domain name to the panel before you can apply for the Lets Encrypt certificate.")
if not self.__check_host_name(domain):
create_site = self.__create_site_of_panel_lets(get)
domain_cert = self.__check_cert_dir(get)
@@ -218,9 +219,9 @@ class setPanelLets:
if not res['status']:
return res
public.writeFile("/www/server/panel/data/ssl.pl", "True")
public.writeFile("/www/server/panel/data/reload.pl","1")
self.__save_cert_source(domain,get.email)
return public.returnMsg(True, 'Panel lets set successfully')
# public.writeFile("/www/server/panel/data/reload.pl","1")
self.__save_cert_source(domain)
return public.returnMsg(True, 'Setup successfully!')
if not create_site:
create_lets = self.__create_lets(get)
if not create_lets['status']:
@@ -229,9 +230,9 @@ class setPanelLets:
domain_cert = self.__check_cert_dir(get)
self.copy_cert(domain_cert)
public.writeFile("/www/server/panel/data/ssl.pl", "True")
public.writeFile("/www/server/panel/data/reload.pl", "1")
self.__save_cert_source(domain, get.email)
return public.returnMsg(True, 'Panel lets set successfully')
# public.writeFile("/www/server/panel/data/reload.pl", "1")
self.__save_cert_source(domain)
return public.returnMsg(True, 'Setup successfully!')
else:
return public.returnMsg(False, create_lets)
else:
+2 -2
View File
@@ -42,7 +42,7 @@ class CloudFlareDns(common.BaseDns):
)
if find_dns_zone_response.status_code != 200:
raise ValueError(
"Error creating cloudflare dns record: status_code={status_code} response={response}".format(
"Error creating cloudflare model record: status_code={status_code} response={response}".format(
status_code=find_dns_zone_response.status_code,
response=self.log_response(find_dns_zone_response),
)
@@ -92,7 +92,7 @@ class CloudFlareDns(common.BaseDns):
# raise error so that we do not continue to make calls to ACME
# server
raise ValueError(
"Error creating cloudflare dns record: status_code={status_code} response={response}".format(
"Error creating cloudflare model record: status_code={status_code} response={response}".format(
status_code=create_cloudflare_dns_record_response.status_code,
response=self.log_response(create_cloudflare_dns_record_response),
)
+9 -9
View File
@@ -44,12 +44,12 @@ import hmac
try:
import requests
except:
os.system('pip install requests')
os.system('btpip install requests')
import requests
try:
import OpenSSL
except:
os.system('pip install pyopenssl')
os.system('btpip install pyOpenSSL')
import OpenSSL
import random
import datetime
@@ -252,7 +252,7 @@ class ACMEclient(object):
print("Apply for a certificate")
identifiers = []
for domain_name in self.all_domain_names:
identifiers.append({"type": "model", "value": domain_name})
identifiers.append({"type": "dns", "value": domain_name})
payload = {"identifiers": identifiers}
url = self.ACME_NEW_ORDER_URL
apply_for_cert_issuance_response = self.make_signed_acme_request(url=url, payload=payload)
@@ -299,7 +299,7 @@ class ACMEclient(object):
if wildcard:
domain = "*." + domain
for i in res["challenges"]:
if i["type"] == "model-01":
if i["type"] == "dns-01":
dns_challenge = i
dns_token = dns_challenge["token"]
dns_challenge_url = dns_challenge["url"]
@@ -806,7 +806,7 @@ class AliyunDns(object):
msg = public.GetMsg("CANT_FIND_RECORDID"), domain_name
print(msg)
return
print("start to delete model record, id: ", record_id)
print("start to delete dns record, id: ", record_id)
randomint = random.randint(11111111111111, 99999999999999)
now = datetime.datetime.utcnow()
otherStyleTime = now.strftime("%Y-%m-%dT%H:%M:%SZ")
@@ -901,7 +901,7 @@ class Dns_com(object):
def create_dns_record(self, domain_name, domain_dns_value):
root, _, acme_txt = extract_zone(domain_name)
print("create_dns_record,", acme_txt, domain_dns_value)
result = public.ExecShell('''{} /www/server/panel/plugin/model/dns_main.py add_txt {} {}'''.format(public.get_python_bin(),acme_txt + '.' + root, domain_dns_value))
result = public.ExecShell('''{} /www/server/panel/plugin/dns/dns_main.py add_txt {} {}'''.format(public.get_python_bin(),acme_txt + '.' + root, domain_dns_value))
if result[0].strip() == "False":
sys.exit(json.dumps({"data": public.GetMsg("BT_DNSRES_ERR")}))
print("create_dns_record_end")
@@ -909,7 +909,7 @@ class Dns_com(object):
def delete_dns_record(self, domain_name, domain_dns_value):
root, _, acme_txt = extract_zone(domain_name)
print("delete_dns_record start: ", acme_txt, domain_dns_value)
public.ExecShell('''{} /www/server/panel/plugin/model/dns_main.py remove_txt {} {}'''.format(public.get_python_bin() ,acme_txt + '.' + root, domain_dns_value))
public.ExecShell('''{} /www/server/panel/plugin/dns/dns_main.py remove_txt {} {}'''.format(public.get_python_bin() ,acme_txt + '.' + root, domain_dns_value))
print("delete_dns_record_success")
@@ -939,9 +939,9 @@ if __name__ == "__main__":#dns调用验证脚本
dns_class = AliyunDns(key=key, secret=secret)
elif dnsapi == "dns_cx": # CloudXns
dns_class = CloudxnsDns(key=key, secret=secret)
elif dnsapi == "dns_bt": # model.com
elif dnsapi == "dns_bt": # dns.com
dns_class = Dns_com()
elif dnsapi == "model": # 手动的
elif dnsapi == "dns": # 手动的
dns_class = Dns_Manual()
Manual = 1
domain_alt_names = data['domain_alt_names'].split(",")
+80 -27
View File
@@ -62,31 +62,32 @@ class SiteDirAuth:
:param get:
:return:
'''
if len(get.username) < 3 or len(get.password) < 3:
return public.returnMsg(False, 'The account number or password cannot be less than 3 characters')
name = get.name
# if len(get.username) < 3 or len(get.password) < 3:
# return public.return_msg_gettext(False, 'Username or password cannot be less than 3 characters')
# name = get.name
param = self.__check_param(get)
if not param['status']:
return param
param = param['msg']
password = param['password']
username = param['username']
name = param['name']
site_dir = get.site_dir
if public.get_webserver() == "openlitespeed":
return public.returnMsg(False,"OpenLiteSpeed is currently not supported")
if not hasattr(get,"password") or not get.password or not hasattr(get,"username") or not get.username:
return public.returnMsg(False, 'Please enter an account or password')
return public.return_msg_gettext(False,"OpenLiteSpeed is currently not supported")
# if not hasattr(get,"password") or not get.password or not hasattr(get,"username") or not get.username:
# return public.return_msg_gettext(False, 'Please enter an account or password')
if not get.site_dir:
return public.returnMsg(False, 'Please enter the directory to be protected')
return public.return_msg_gettext(False, 'Please enter the directory to be protected')
if not get.name:
return public.returnMsg(False, 'Please enter the Name')
# if site_dir[0] != "/" or site_dir[-1] != "/":
# return public.returnMsg(False, 'Directory format is incorrect')
# site_dir = site_dir[1:]
# if site_dir[-1] == "/":
# site_dir = site_dir[:-1]
passwd = public.hasPwd(get.password)
return public.return_msg_gettext(False, 'Please enter the Name')
passwd = public.hasPwd(password)
site_info = self.get_site_info(get.id)
site_name = site_info["site_name"]
if self._check_site_authorization(site_name):
return public.returnMsg(False, 'Site password protection has been set, please cancel and then set. Site directory --> Password access')
return public.return_msg_gettext(False, 'Site password protection has been set, please cancel and then set. Site directory --> Password access')
if self._check_dir_auth(site_name, name,site_dir):
return public.returnMsg(False, 'Directory has been protected')
return public.return_msg_gettext(False, 'Directory has been protected')
auth = "{user}:{passwd}".format(user=get.username,passwd=passwd)
auth_file = '{setup_path}/pass/{site_name}'.format(setup_path=self.setup_path,site_name=site_name)
if not os.path.exists(auth_file):
@@ -108,7 +109,7 @@ class SiteDirAuth:
conf = {"name":name,"site_dir":get.site_dir,"auth_file":auth_file}
self._write_conf(conf,site_name)
public.serviceReload()
return public.returnMsg(True,"Created successfully")
return public.return_msg_gettext(True,"Successfully created")
# 检查配置是否存在
def _check_dir_auth(self, site_name, name,site_dir):
@@ -126,6 +127,10 @@ class SiteDirAuth:
conf = public.readFile(self.setup_path + '/panel/vhost/'+public.get_webserver()+'/'+siteName+'.conf');
if public.get_webserver() == 'nginx':
rep = "enable-php-(\w{2,5})\.conf"
tmp = re.search(rep,conf)
if not tmp:
rep = "enable-php-(\d+-wpfastcgi).conf"
re.search(rep, conf)
else:
rep = "php-cgi-(\w{2,5})\.sock"
tmp = re.search(rep,conf).groups()
@@ -134,7 +139,7 @@ class SiteDirAuth:
else:
return ""
except:
return public.returnMsg(False, 'SITE_PHPVERSION_ERR_A22')
return public.return_msg_gettext(False, 'Apache2.2 does NOT support MultiPHP!')
# 获取站点名
def get_site_info(self,id):
@@ -179,6 +184,8 @@ class SiteDirAuth:
%s
#AUTH_END
}''' % (site_dir,auth_file,php_conf)
public.writeFile("/tmp/2", conf)
else:
# 设置apache
conf = '''<Directory "{site_path}{site_dir}">
@@ -211,10 +218,12 @@ class SiteDirAuth:
conf = public.readFile(file)
if i == "apache":
if act == "create":
rep = "combined(\n|.)+IncludeOptional.*\/dir_auth\/.*conf"
rep1 = "combined"
if not re.search(rep,conf):
conf = conf.replace(rep1, rep1 + "\n\t#Directory protection rules, do not manually delete\n\tIncludeOptional {}".format(dir_auth_file))
rep = "IncludeOptional.*\/dir_auth\/.*conf(\n|.)+<\/VirtualHost>"
rep1 = "</VirtualHost>"
if not re.search(rep, conf):
conf = conf.replace(rep1,
"\n\t#Directory protection rules, do not manually delete\n\tIncludeOptional {}\n</VirtualHost>".format(
dir_auth_file))
else:
rep = "\n*#Directory protection rules, do not manually delete\n+\s+IncludeOptional[\s\w\/\.\*]+"
conf = re.sub(rep, '', conf)
@@ -240,7 +249,7 @@ class SiteDirAuth:
# for i in range(len(a_conf)-1,-1,-1):
# if site_name == a_conf[i]["sitename"] and a_conf[i]["proxyname"]:
# del a_conf[i]
return public.returnMsg(False, 'ERROR: %s<br><a style="color:red;">' % public.GetMsg("CONFIG_ERROR") + isError.replace("\n",
return public.return_msg_gettext(False, 'ERROR: %s<br><a style="color:red;">' % public.get_msg_gettext('Configuration ERROR') + isError.replace("\n",
'<br>') + '</a>')
# 删除密码保护
@@ -256,7 +265,7 @@ class SiteDirAuth:
site_name = site_info["site_name"]
conf = self._read_conf()
if site_name not in conf:
return public.returnMsg(False,"The website does not exist in the configuration{}".format(site_name))
return public.return_msg_gettext(False,"The website does not exist in the configuration{}",(site_name,))
for i in range(len(conf[site_name])):
if name in conf[site_name][i].values():
print(conf[site_name][i])
@@ -275,7 +284,7 @@ class SiteDirAuth:
self.set_conf(site_name,"delete")
if not hasattr(get,'multiple'):
public.serviceReload()
return public.returnMsg(True,"DEL_SUCCESS")
return public.return_msg_gettext(True,'Successfully deleted!')
# 修改目录保护密码
def modify_dir_auth_pass(self,get):
@@ -287,6 +296,14 @@ class SiteDirAuth:
:param get:
:return:
'''
# if not hasattr(get,"password") or not get.password or not hasattr(get,"username") or not get.username:
# return public.return_msg_gettext(False, 'Username or password cannot be less than 3 characters')
param = self.__check_param(get)
if not param['status']:
return param
param = param['msg']
password = param['password']
username = param['username']
name = get.name
site_info = self.get_site_info(get.id)
site_name = site_info["site_name"]
@@ -295,7 +312,7 @@ class SiteDirAuth:
auth_file = '{setup_path}/pass/{site_name}/{name}.pass'.format(setup_path=self.setup_path,site_name=site_name,name=name)
public.writeFile(auth_file,auth)
public.serviceReload()
return public.returnMsg(True,"EDIT_SUCCESS")
return public.return_msg_gettext(True,'Setup successfully!')
# 获取目录保护列表
def get_dir_auth(self,get):
@@ -314,3 +331,39 @@ class SiteDirAuth:
if site_name in conf:
return {site_name:conf[site_name]}
return {}
def __check_param(self, get):
values = {}
if hasattr(get, "password"):
if not get.password:
return public.returnMsg(False, 'Please enter password!')
password = get.password.strip()
if len(password) < 3:
return public.returnMsg(False, 'Password cannot be less than 3 characters')
if re.search('\s', password):
return public.returnMsg(False, 'Password cannot contain spaces')
values['password'] = password
if hasattr(get, "username"):
if not get.username:
return public.returnMsg(False, 'Please enter username!')
username = get.username.strip()
if len(username) < 3:
return public.returnMsg(False, 'Username cannot be less than 3 characters')
if re.search('\s', username):
return public.returnMsg(False, 'Username cannot contain spaces')
values['username'] = username
if hasattr(get, "name"):
if not get.name:
return public.returnMsg(False, 'Please enter a name!')
name = get.name.strip()
if len(name) < 3:
return public.returnMsg(False, 'Name cannot be less than 3 characters')
if re.search('\s', name):
return public.returnMsg(False, 'Name cannot contain spaces')
if re.search('[\/\"\'\!@#$%^&*()+={}\[\]\:\;\?><,./\\\]+', name):
return public.returnMsg(False, 'Name format must be [ aaa_bbb ]')
values['name'] = name
return public.returnMsg(True, values)
+1 -1
View File
@@ -200,7 +200,7 @@ server
}],
"proxy": {
"open": False,
"url": "http://www.bt.cn",
"url": "https://www.bt.cn",
"host": "www.bt.cn",
"subOpen": False,
"src": "",
+1 -1
View File
@@ -100,7 +100,7 @@ class ssh_authentication:
def install_pam_python(self,check):
so_path=check[2]
so_name=check[2].split('/')[-1]
public.ExecShell('/usr/local/curl/bin/curl -o %s http://download.bt.cn/btwaf_rule/pam_python_so/%s'%(so_path,so_name))
public.ExecShell('/usr/local/curl/bin/curl -o %s https://download.bt.cn/btwaf_rule/pam_python_so/%s'%(so_path,so_name))
public.ExecShell("chmod 600 " + so_path)
return True
+25 -11
View File
@@ -378,16 +378,28 @@ class ssh_security:
关闭key
无需参数传递
'''
file = ['/root/.ssh/id_rsa.pub', '/root/.ssh/id_rsa', '/root/.ssh/authorized_keys']
rec = '\n#?RSAAuthentication\s\w+'
rec2 = '\n#?PubkeyAuthentication\s\w+'
file = public.readFile(self.__SSH_CONFIG)
file_ssh = re.sub(rec, '\nRSAAuthentication no', file)
file_result = re.sub(rec2, '\nPubkeyAuthentication no', file_ssh)
self.wirte(self.__SSH_CONFIG, file_result)
self.set_password(get)
self.restart_ssh()
return public.returnMsg(True, 'Closed successfully')
is_ssh_status=public.get_sshd_status()
if is_ssh_status:
file = ['/root/.ssh/id_rsa.pub', '/root/.ssh/id_rsa', '/root/.ssh/authorized_keys']
rec = '\n#?RSAAuthentication\s\w+'
rec2 = '\n#?PubkeyAuthentication\s\w+'
file = public.readFile(self.__SSH_CONFIG)
file_ssh = re.sub(rec, '\nRSAAuthentication no', file)
file_result = re.sub(rec2, '\nPubkeyAuthentication no', file_ssh)
self.wirte(self.__SSH_CONFIG, file_result)
self.set_password(get)
self.restart_ssh()
return public.returnMsg(True, 'Closed successfully')
else:
file = ['/root/.ssh/id_rsa.pub', '/root/.ssh/id_rsa', '/root/.ssh/authorized_keys']
rec = '\n#?RSAAuthentication\s\w+'
rec2 = '\n#?PubkeyAuthentication\s\w+'
file = public.readFile(self.__SSH_CONFIG)
file_ssh = re.sub(rec, '\nRSAAuthentication no', file)
file_result = re.sub(rec2, '\nPubkeyAuthentication no', file_ssh)
self.wirte(self.__SSH_CONFIG, file_result)
#self.set_password(get)
return public.returnMsg(True, 'Closed successfully')
def get_config(self, get):
'''
@@ -514,6 +526,8 @@ if __name__ == '__main__':
try:
aa = ssh_security()
aa.login()
except:pass
except:
print(111)
pass
else:
pass
+208 -111
View File
@@ -21,7 +21,7 @@ from io import BytesIO, StringIO
def returnMsg(status,msg,value=None):
if value:
msg = public.getMsg(msg,value)
msg = public.get_msg_gettext(msg,value)
return {'status':status,'msg':msg}
import public
@@ -38,7 +38,7 @@ class ssh_terminal:
_ssh = None
_last_cmd = ""
_last_cmd_tip = 0
_log_type = public.getMsg('TYPE_TERMINAL')
_log_type = public.get_msg_gettext('aaPanel terminal')
_history_len = 0
_client = ""
_rep_ssh_config = False
@@ -48,6 +48,8 @@ class ssh_terminal:
_old_conf = None
_debug_file = 'logs/terminal.log'
_s_code = None
_last_num = 0
_key_passwd = None
def connect(self):
'''
@@ -58,7 +60,7 @@ class ssh_terminal:
msg: string 详情
}
'''
if not self._host: return returnMsg(False,'WRONG_CONN_ADDR')
if not self._host: return public.return_msg_gettext(False,'Wrong connection address')
if not self._user: self._user = 'root'
if not self._port: self._port = 22
@@ -71,7 +73,7 @@ class ssh_terminal:
while num < 5:
num +=1
try:
self.debug(public.getMsg('RECONN_TIMES',(num,)))
self.debug(public.get_msg_gettext('Reconnection attempts:{}',(num,)))
if self._rep_ssh_config: time.sleep(0.1)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(2 + num)
@@ -81,10 +83,10 @@ class ssh_terminal:
except Exception as e:
if num == 5:
self.set_sshd_config(True)
self.debug(public.getMsg('RECONN_FAILED',(e,)))
self.debug(public.get_msg_gettext('Retry connection failed, {}',(e,)))
if self._host in ['127.0.0.1','localhost']:
return returnMsg(False,'CONN_FAIL',("Authentication failed ," + self._user + "@" + self._host + ":" +str(self._port),))
return returnMsg(False,'CONN_FAIL1',(self._host,self._port))
return returnMsg(False,'Connection failure: {}',("Authentication failed ," + self._user + "@" + self._host + ":" +str(self._port),))
return returnMsg(False,'Connection failure: {}',(self._host,self._port))
else:
time.sleep(0.2)
@@ -92,15 +94,15 @@ class ssh_terminal:
import paramiko
self._tp = paramiko.Transport(sock)
pkey = None
try:
self._tp.start_client()
if not self._pass and not self._pkey:
self.set_sshd_config(True)
return public.returnMsg(False,'SSH_LOGIN_INFO_ERR',(self._host,str(self._port)))
return public.return_msg_gettext(False,'Password or private key cannot both be empty: {}:{}',(self._host,str(self._port)))
self._tp.banner_timeout=60
if self._pkey:
self.debug(public.getMsg('AUTH_PRI_KEY'))
self.debug(public.get_msg_gettext('Authenticating private key'))
if sys.version_info[0] == 2:
try:
self._pkey = self._pkey.encode('utf-8')
@@ -110,18 +112,43 @@ class ssh_terminal:
else:
p_file = StringIO(self._pkey)
try:
pkey = paramiko.RSAKey.from_private_key(p_file)
except:
if self._key_passwd:
pkey = paramiko.RSAKey.from_private_key(p_file,password=self._key_passwd)
else:
pkey = paramiko.RSAKey.from_private_key(p_file)
self.debug("尝试使用RSA私钥认证")
except Exception as ex:
try:
p_file.seek(0)
pkey = paramiko.Ed25519Key.from_private_key(p_file)
if self._key_passwd:
pkey = paramiko.Ed25519Key.from_private_key(p_file,password=self._key_passwd)
else:
pkey = paramiko.Ed25519Key.from_private_key(p_file)
self.debug("尝试使用Ed25519私钥认证")
except:
try:
p_file.seek(0)
pkey = paramiko.ECDSAKey.from_private_key(p_file)
if self._key_passwd:
pkey = paramiko.ECDSAKey.from_private_key(p_file,password=self._key_passwd)
else:
pkey = paramiko.ECDSAKey.from_private_key(p_file)
self.debug("尝试使用ECDSA私钥认证")
except:
p_file.seek(0)
pkey = paramiko.DSSKey.from_private_key(p_file)
if self._key_passwd:
try:
pkey = paramiko.DSSKey.from_private_key(p_file,password=self._key_passwd)
except Exception as ex:
ex = str(ex)
if ex.find('OpenSSH private key file checkints do not match') != -1:
return public.returnMsg(False,'Incorrect private key password: {}'.format(ex))
elif ex.find('encountered RSA key, expected DSA key') != -1:
pkey = paramiko.RSAKey.from_private_key(p_file,password=self._key_passwd)
else:
return public.returnMsg(False,'private key error: {}'.format(ex))
else:
pkey = paramiko.DSSKey.from_private_key(p_file)
if not pkey: return public.returnMsg(False,'Incorrect private key!')
self._tp.auth_publickey(username=self._user, key=pkey)
else:
try:
@@ -142,32 +169,43 @@ class ssh_terminal:
self._tp.close()
e = str(e)
if e.find('websocket error!') != -1:
return returnMsg(True,'connection succeeded')
return public.return_msg_gettext(True,'connection succeeded')
if e.find('Authentication timeout') != -1:
self.debug("认证超时{}".format(e))
return returnMsg(False,'Authentication timed out, please press enter to try again!{}'.format(e))
return public.return_msg_gettext(False,'Authentication timed out, please press enter to try again!{}',(e,))
if e.find('Authentication failed') != -1:
self.debug(public.getMsg('AUTH_FAIL',(str(e),)))
return returnMsg(False,'SSH_LOGIN_ERR1',(str(e + "," + self._user + "@" + self._host + ":" +str(self._port)),))
self.debug(public.get_msg_gettext('Authentication failed {}',(str(e),)))
if self._key_passwd:
sshd_config = public.readFile('/etc/ssh/sshd_config')
if sshd_config and sshd_config.find('ssh-dss') == -1:
return returnMsg(False,'The private key verification fails, the private key may be incorrect, or the ssh-dss private key authentication type may not be enabled in the /etc/ssh/sshd_config configuration file')
return returnMsg(False,'Authentication failed, please check whether the private key is correct: {}'.format(e + "," + self._user + "@" + self._host + ":" +str(self._port)))
return returnMsg(False,'account or password incorrect:{}'.format(e + "," + self._user + "@" + self._host + ":" +str(self._port)))
if e.find('Bad authentication type; allowed types') != -1:
self.debug(public.getMsg('AUTH_FAIL',(str(e),)))
self.debug(public.get_msg_gettext('Authentication failed {}',(str(e),)))
if self._host in ['127.0.0.1','localhost'] and self._pass == 'none':
return returnMsg(False,'USER_OR_PASSWD_ERR',(str("Authentication failed ," + self._user + "@" + self._host + ":" +str(self._port)),))
return returnMsg(False,'SSH_LOGIN_ERR2',(str(e)))
return public.return_msg_gettext(False,'Username or Password incorrect: {}',(str("Authentication failed ," + self._user + "@" + self._host + ":" +str(self._port)),))
return public.return_msg_gettext(False,'Unsupported authentication type: {}',(str(e)))
if e.find('Connection reset by peer') != -1:
self.debug(public.getMsg('SSH_LOGIN_ERR3'))
return returnMsg(False,public.getMsg('SSH_LOGIN_ERR3'))
self.debug(public.get_msg_gettext('The target server actively refused the connection'))
return public.return_msg_gettext(False,public.get_msg_gettext('The target server actively refused the connection'))
if e.find('Error reading SSH protocol banner') != -1:
self.debug('SSH_LOGIN_ERR10')
return returnMsg(False,public.getMsg('SSH_LOGIN_ERR4',(str(e),)))
self.debug('The protocol header response timed out')
return public.return_msg_gettext(False,public.get_msg_gettext('The protocol header response timed out, and the network quality with the target server was too bad: {}',(str(e),)))
if e.find('encountered RSA key, expected DSA key') != -1:
self.debug('Private keys may require password access')
return public.return_msg_gettext(False,public.get_msg_gettext('Private keys may require password access: {}',(str(e),)))
if e.find('password and salt must not be empty') != -1:
self.debug('Private keys may require password access')
return public.return_msg_gettext(False,public.get_msg_gettext('Private keys may require password access: {}',(str(e),)))
if not e:
self.debug('SSH_LOGIN_ERR11')
return returnMsg(False,"SSH_LOGIN_ERR5")
self.debug('The SSH protocol handshake timed out')
return public.return_msg_gettext(False,"The SSH protocol handshake timed out, and the network quality with the target server is too bad")
err = public.get_error_info()
self.debug(err)
return returnMsg(False,public.getMsg("SSH_LOGIN_ERR6",(str(err),)))
return public.return_msg_gettext(False,public.get_msg_gettext('unknown error: {}',(str(err),)))
self.debug('SSH_LOGIN_INFO3')
self.debug(public.get_msg_gettext('The authentication is successful and the session channel is being constructed'))
self._ssh = self._tp.open_session()
self._ssh.get_pty(term='xterm', width=100, height=34)
self._ssh.invoke_shell()
@@ -175,11 +213,11 @@ class ssh_terminal:
self._last_send = []
from BTPanel import request
self._client = public.GetClientIp() +':' + str(request.environ.get('REMOTE_PORT'))
public.WriteLog(self._log_type,'SSH_LOGIN',(self._host,str(self._port)))
self.history_send("LOGIN_SUCCESS2")
public.write_log_gettext(self._log_type,'Successfully logged in to the SSH server [{}:{}]',(self._host,str(self._port)))
self.history_send(public.get_msg_gettext("Login success\n"))
self.set_sshd_config(True)
self.debug('SSH_LOGIN_INFO2')
return returnMsg(True,'CONNECTION_SUCCEEDED')
self.debug(public.get_msg_gettext('Login success'))
return public.return_msg_gettext(True,'connection succeeded')
def _auth_interactive(self):
self.debug('Verification Code')
@@ -216,6 +254,8 @@ class ssh_terminal:
self._tp.auth_interactive(self._user, handler)
def get_login_user(self):
'''
@name 获取本地登录用户
@@ -288,10 +328,15 @@ class ssh_terminal:
self._pass = ssh_info['password']
self._old_conf = True
return
ssh_key_type_file = '{}/data/ssh_key_type.pl'.format(public.get_panel_path())
ssh_key_type = ''
if os.path.exists(ssh_key_type_file):
ssh_key_type_new = public.readFile(ssh_key_type_file)
if ssh_key_type_new: ssh_key_type = ssh_key_type_new.strip()
login_user = self.get_login_user()
if self._user == 'root' and login_user == 'root':
id_rsa_file = ['/root/.ssh/id_rsa','/root/.ssh/id_rsa_bt']
id_rsa_file = ['/root/.ssh/id_ed25519','/root/.ssh/id_ecdsa','/root/.ssh/id_rsa','/root/.ssh/id_rsa_bt']
if ssh_key_type: id_rsa_file.insert(0,'/root/.ssh/id_{}'.format(ssh_key_type))
for ifile in id_rsa_file:
if os.path.exists(ifile):
self._pkey = public.readFile(ifile)
@@ -301,12 +346,14 @@ class ssh_terminal:
return
if not self._pass or not self._pkey or not self._user:
home_path = '/home/' + login_user
if login_user == 'root':
home_path = '/root'
self._user = login_user
id_rsa_file = [home_path + '/.ssh/id_rsa',home_path + '/.ssh/id_rsa_bt']
id_rsa_file = [home_path + '/.ssh/id_ed25519',home_path + '/.ssh/id_ecdsa',home_path + '/.ssh/id_rsa',home_path + '/.ssh/id_rsa_bt']
if ssh_key_type: id_rsa_file.insert(0,home_path + '/.ssh/id_{}'.format(ssh_key_type))
for ifile in id_rsa_file:
if os.path.exists(ifile):
self._pkey = public.readFile(ifile)
@@ -314,19 +361,6 @@ class ssh_terminal:
self._pass = 'none'
return
# _ssh_ks = home_path + '/.ssh'
# if not os.path.exists(_ssh_ks):
# os.makedirs(_ssh_ks,384)
# os.system("ssh-keygen -t rsa -P '' -f {}/.ssh/id_rsa |echo y".format(home_path))
# pub_file = home_path + '/.ssh/id_rsa.pub'
# az_file = home_path + '/.ssh/authorized_keys'
# rsa_file = home_path + '/.ssh/id_rsa'
# public.ExecShell('cat {} >> {} && chmod 600 {} {}'.format(pub_file, az_file, az_file,rsa_file))
# os.remove(pub_file)
# public.ExecShell("chown -R {}:{} {}".format(self._user,self._user,_ssh_ks))
# public.ExecShell("chmod -R 600 {}".format(_ssh_ks))
# self._pkey = public.readFile(rsa_file)
except:
return
@@ -416,6 +450,8 @@ class ssh_terminal:
self.restart_ssh()
return True
pin = r'^\s*PubkeyAuthentication\s+(yes|no)'
pubkey_status = re.findall(pin,sshd_config,re.I)
if pubkey_status:
@@ -491,12 +527,12 @@ class ssh_terminal:
'''
n = 0
try:
while not self._ws.closed:
while self._ws.connected:
resp_line = self._ssh.recv(1024)
if not resp_line:
if not self._tp.is_active():
self.debug(public.getMsg('SSH_LOGIN_ERR14'))
self._ws.send(public.getMsg('RECONNECT_SSH'))
self.debug(public.get_msg_gettext('Channel disconnected'))
self._ws.send(public.get_msg_gettext('The connection is disconnected, press enter to try to reconnect!'))
self.close()
return
@@ -505,7 +541,7 @@ class ssh_terminal:
if n > 5: break
continue
n = 0
if self._ws.closed:
if not self._ws.connected:
return
try:
result = resp_line.decode('utf-8','ignore')
@@ -517,16 +553,16 @@ class ssh_terminal:
self._ws.send(result)
self.history_recv(result)
# self.history_recv(result)
except Exception as e:
e = str(e)
if e.find('closed') != -1:
self.debug('SSH_LOGIN_INFO')
elif not self._ws.closed:
self.debug(public.getMsg('SSH_LOGIN_ERR15',(str(e),)))
self.debug(public.getMsg('SSH_LOGIN_INFO'))
elif self._ws.connected:
self.debug(public.get_msg_gettext('Error reading tty buffer data, {}',(str(e),)))
if self._ws.closed:
self.debug(public.getMsg('SSH_LOGIN_INFO1'))
if not self._ws.connected:
self.debug(public.get_msg_gettext('The client has actively disconnected'))
self.close()
def send(self):
@@ -536,12 +572,13 @@ class ssh_terminal:
@return void
'''
try:
while not self._ws.closed:
while self._ws.connected:
if self._s_code:
time.sleep(0.1)
continue
client_data = self._ws.receive()
if not client_data: continue
if client_data == '{}': continue
if len(client_data) > 10:
if client_data.find('{"host":"') != -1:
continue
@@ -549,20 +586,21 @@ class ssh_terminal:
self.resize(client_data)
continue
self._ssh.send(client_data)
self.history_send(client_data)
# self.history_send(client_data)
except Exception as ex:
ex = str(ex)
if ex.find('_io.BufferedReader') != -1:
self.debug(public.getMsg('SSH_LOGIN_ERR16'))
self.debug(public.get_msg_gettext('An error occurred while reading data from websocket. Retrying'))
self.send()
return
elif ex.find('closed') != -1:
self.debug('SSH_LOGIN_INFO')
self.debug(public.get_msg_gettext('SSH_LOGIN_INFO'))
else:
self.debug(public.getMsg('SSH_LOGIN_ERR17',(str(ex),)))
self.debug(public.get_msg_gettext('An error occurred while writing data to the buffer: {}',(str(ex),)))
if self._ws.closed:
self.debug(public.getMsg('SSH_LOGIN_INFO1'))
if not self._ws.connected:
self.debug(public.get_msg_gettext('The client has actively disconnected'))
self.close()
@@ -576,7 +614,7 @@ class ssh_terminal:
#处理TAB补登
if self._last_cmd_tip == 1:
if not recv_data.startswith('\r\n'):
self._last_cmd += recv_data.replace('\u0007','').strip()
self._last_cmd += recv_data.replace('\u0007','').replace("\x07","").strip()
self._last_cmd_tip = 0
#上下切换命令
@@ -601,32 +639,49 @@ class ssh_terminal:
self._last_cmd_tip = 2
return
#左移光标
if send_data in ["\x1b[C"]:
self._last_num -= 1
return
# 右移光标
if send_data in ["\x1b[D"]:
self._last_num += 1
return
#退格
if send_data == "\x7f":
self._last_cmd = self._last_cmd[:-1]
return
#过滤特殊符号
if send_data in ["\x1b[C","\x1b[D","\x1b[K","\x07","\x08","\x03","\x01","\x02","\x04","\x05","\x06","\u0007"]:
if send_data in ["\x1b[C","\x1b[D","\x1b[K","\x07","\x08","\x03","\x01","\x02","\x04","\x05","\x06","\x1bOB","\x1bOA","\x1b[8P","\x1b","\x1b[4P","\x1b[6P","\x1b[5P"]:
return
#Tab补全处理
if send_data == '\t':
if send_data == "\t":
self._last_cmd_tip = 1
return
if str(send_data).find("\x1b") != -1:
return
if send_data[-1] in ['\r','\n']:
if not self._last_cmd: return
his_shell = [int(time.time()),self._client,self._user,self._last_cmd]
public.writeFile(his_file, json.dumps(his_shell) + "\n","a+")
self._last_cmd = ""
#超过5M则保留最新的200行
if os.stat(his_file).st_size > 5242880:
his_tmp = public.GetNumLines(his_file,200)
#超过50M则保留最新的20000
if os.stat(his_file).st_size > 52428800:
his_tmp = public.GetNumLines(his_file,20000)
public.writeFile(his_file, his_tmp)
else:
self._last_cmd += send_data
if self._last_num >= 0:
self._last_cmd += send_data
else:
self._last_cmd.insert(len(self._last_cmd) + self._last_num, send_data)
def close(self):
@@ -640,7 +695,7 @@ class ssh_terminal:
self._ssh.close()
if self._tp: # 关闭宿主服务
self._tp.close()
if not self._ws.closed:
if self._ws.connected:
self._ws.close()
except:
pass
@@ -660,6 +715,8 @@ class ssh_terminal:
self._pkey = ssh_info['pkey']
if 'password' in ssh_info:
self._pass = ssh_info['password']
if 'pkey_passwd' in ssh_info:
self._key_passwd = ssh_info['pkey_passwd']
try:
result = self.connect()
except Exception as ex:
@@ -680,7 +737,7 @@ class ssh_terminal:
self._tp.send_ignore()
else:
break
if not self._ws.closed:
if self._ws.connected:
self._ws.send("")
else:
break
@@ -692,6 +749,7 @@ class ssh_terminal:
@return void
'''
msg = "{} - {}:{} => {} \n".format(public.format_date(),self._host,self._port,msg)
self.history_send(msg)
public.writeFile(self._debug_file,msg,'a+')
def run(self,web_socket, ssh_info=None):
@@ -714,7 +772,8 @@ class ssh_terminal:
return
result = self.set_attr(ssh_info)
else:
result = returnMsg(True,'ALREADY_CONNECTED')
result = public.get_msg_gettext(True,'ALREADY_CONNECTED')
if result['status']:
sendt = threading.Thread(target=self.send)
recvt = threading.Thread(target=self.recv)
@@ -728,6 +787,7 @@ class ssh_terminal:
self.close()
else:
self._ws.send(result['msg'])
self.close()
def __del__(self):
'''
@@ -746,6 +806,14 @@ class ssh_host_admin(ssh_terminal):
_pass_str = None
def __init__(self):
self.__create_aes_pass()
def __create_aes_pass(self):
'''
@name 创建AES密码
@author
@return string
'''
if not os.path.exists(self._save_path):
os.makedirs(self._save_path,384)
if not os.path.exists(self._pass_file):
@@ -753,6 +821,10 @@ class ssh_host_admin(ssh_terminal):
public.set_mode(self._pass_file,600)
if not self._pass_str:
self._pass_str = public.readFile(self._pass_file)
if not self._pass_str:
self._pass_str = public.GetRandomString(16)
public.writeFile(self._pass_file,self._pass_str)
public.set_mode(self._pass_file,600)
def get_host_list(self,args = None):
'''
@@ -766,12 +838,17 @@ class ssh_host_admin(ssh_terminal):
for name in os.listdir(self._save_path):
info_file = self._save_path + name +'/info.json'
if not os.path.exists(info_file): continue
info_tmp = self.get_ssh_info(name)
host_info = {}
host_info['host'] = name
host_info['port'] = info_tmp['port']
host_info['ps'] = info_tmp['ps']
host_info['sort'] = int(info_tmp['sort'])
try:
info_tmp = self.get_ssh_info(name)
host_info = {}
host_info['host'] = name
host_info['port'] = info_tmp['port']
host_info['ps'] = info_tmp['ps']
host_info['sort'] = int(info_tmp['sort'])
except:
if os.path.exists(info_file):
os.remove(info_file)
continue
host_list.append(host_info)
@@ -790,7 +867,7 @@ class ssh_host_admin(ssh_terminal):
args.host = args.host.strip()
info_file = self._save_path + args.host +'/info.json'
if not os.path.exists(info_file):
return public.returnMsg(False,'SSH_LOGIN_ERR7')
return public.return_msg_gettext(False,'The specified SSH information does not exist!')
info_tmp = self.get_ssh_info(args.host)
host_info = {}
host_info['host'] = args.host
@@ -800,6 +877,9 @@ class ssh_host_admin(ssh_terminal):
host_info['username'] = info_tmp['username']
host_info['password'] = info_tmp['password']
host_info['pkey'] = info_tmp['pkey']
host_info['pkey_passwd'] = ''
if 'pkey_passwd' in info_tmp:
host_info['pkey_passwd'] = info_tmp['pkey_passwd']
return host_info
def modify_host(self,args):
@@ -815,6 +895,7 @@ class ssh_host_admin(ssh_terminal):
username: 用户名
password: 密码
pkey: 密钥(如果不为空将使用密钥连接)
pkey_passwd: 密钥的密码
}
@return dict
'''
@@ -823,12 +904,12 @@ class ssh_host_admin(ssh_terminal):
if args.host != args.new_host:
info_file = self._save_path + args.new_host +'/info.json'
if os.path.exists(info_file):
return public.returnMsg(False,'SSH_LOGIN_ERR8')
return public.return_msg_gettext(False,'The specified host address has been added to other SSH information!')
info_file = self._save_path + args.host +'/info.json'
if not os.path.exists(info_file):
return public.returnMsg(False,'SSH_LOGIN_ERR7')
return public.return_msg_gettext(False,'The specified SSH information does not exist!')
if not 'sort' in args:
r_data = public.aes_decrypt(public.readFile(info_file),self._pass_str)
@@ -843,14 +924,18 @@ class ssh_host_admin(ssh_terminal):
host_info['username'] = args['username']
host_info['password'] = args['password']
host_info['pkey'] = args['pkey']
if 'pkey_passwd' in args:
host_info['pkey_passwd'] = args['pkey_passwd']
else:
host_info['pkey_passwd'] = ''
if not host_info['pkey']: host_info['pkey'] = ''
result = self.set_attr(host_info)
if not result['status']: return result
self.save_ssh_info(args.host,host_info)
if args.host != args.new_host:
public.ExecShell('mv {} {}'.format(self._save_path + args.host,self._save_path + args.new_host))
public.WriteLog(self._log_type,'MODIFY_SSH_INFO',(args.host,))
return public.returnMsg(True,'EDIT_SUCCESS')
public.write_log_gettext(self._log_type,'Modify the SSH information of HOST: {}',(args.host,))
return public.return_msg_gettext(True,'Setup successfully!')
def create_host(self,args):
'''
@@ -864,6 +949,7 @@ class ssh_host_admin(ssh_terminal):
username: 用户名
password: 密码
pkey: 密钥(如果不为空将使用密钥连接)
pkey_passwd 密钥的密码
}
@return dict
'''
@@ -886,11 +972,14 @@ class ssh_host_admin(ssh_terminal):
host_info['username'] = args['username']
host_info['password'] = args['password']
host_info['pkey'] = args['pkey']
host_info['pkey_passwd'] = ''
if 'pkey_passwd' in args:
host_info['pkey_passwd'] = args['pkey_passwd']
result = self.set_attr(host_info)
if not result['status']: return result
self.save_ssh_info(args.host,host_info)
public.WriteLog(self._log_type,'ADD_SSH_INFO',(str(args.host),))
return public.returnMsg(True,'SET_SUCCESS')
public.write_log_gettext(self._log_type,'Add the SSH information of HOST: {}',(str(args.host),))
return public.return_msg_gettext(True,'Setup successfully!')
def remove_host(self,args):
@@ -903,13 +992,13 @@ class ssh_host_admin(ssh_terminal):
@return dict
'''
args.host = args.host.strip()
if not args.host: return public.returnMsg(False,'INIT_ARGS_ERR')
if not args.host: return public.return_msg_gettext(False,'Parameter ERROR!')
host_path = self._save_path + args.host
if not os.path.exists(host_path):
return public.returnMsg(False,'SSH_LOGIN_ERR7!')
return public.return_msg_gettext(False,'The specified SSH information does not exist!')
public.ExecShell("rm -rf {}".format(host_path))
public.WriteLog(self._log_type,'DEL_SSH_INFO',(str(args.host),))
return public.returnMsg(True,'SET_SUCCESS')
public.write_log_gettext(self._log_type,'Delete the SSH information of HOST: {}',(str(args.host),))
return public.return_msg_gettext(True,'Setup successfully!')
def get_ssh_info(self,host):
@@ -921,7 +1010,15 @@ class ssh_host_admin(ssh_terminal):
'''
info_file = self._save_path + host + '/info.json'
if not os.path.exists(info_file): return False
r_data = public.aes_decrypt(public.readFile(info_file),self._pass_str)
try:
r_data = public.aes_decrypt(public.readFile(info_file),self._pass_str)
except ValueError as ex:
if str(ex).find('Incorrect AES key length') != -1:
if os.path.exists(self._pass_file):
os.remove(self._pass_file)
self.__create_aes_pass()
r_data = public.aes_decrypt(public.readFile(info_file),self._pass_str)
return json.loads(r_data)
def save_ssh_info(self,host,host_info):
@@ -954,7 +1051,7 @@ class ssh_host_admin(ssh_terminal):
@return bool
'''
if not 'sort_list' in args:
return public.returnMsg(False,'SSH_LOGIN_ERR9')
return public.return_msg_gettext(False,'Please pass in the [sort_list] field')
sort_list = json.loads(args.sort_list)
for name in sort_list.keys():
info_file = self._save_path + name + '/info.json'
@@ -963,7 +1060,7 @@ class ssh_host_admin(ssh_terminal):
ssh_info = self.get_ssh_info(name)
ssh_info['sort'] = int(sort_list[name])
self.save_ssh_info(name,ssh_info)
return public.returnMsg(True,'SET_SUCCESS')
return public.return_msg_gettext(True,'Setup successfully!')
def get_command_list(self,args = None, user_cmd = False , sys_cmd = False):
'''
@@ -1028,7 +1125,7 @@ class ssh_host_admin(ssh_terminal):
command = self.get_command_list(sys_cmd=True)
if self.command_exists(command,args.title):
return public.returnMsg(False,'COMMAND_NAME_EXIST')
return public.return_msg_gettext(False,'The specified command name already exists')
cmd = {
"title": args.title,
@@ -1037,8 +1134,8 @@ class ssh_host_admin(ssh_terminal):
command.append(cmd)
self.save_command(command)
public.WriteLog(self._log_type,'ADD_COMMAND_COMMAND',(str(args.title),))
return public.returnMsg(True,'SET_SUCCESS')
public.write_log_gettext(self._log_type,'Add common commands [{}]',(str(args.title),))
return public.return_msg_gettext(True,'Setup successfully!')
def get_command_find(self,args = None, title=None):
'''
@@ -1053,9 +1150,9 @@ class ssh_host_admin(ssh_terminal):
if args: title = args.title.strip()
command = self.get_command_list()
for cmd in command:
if cmd['title'] == title:
if cmd['title'] == title or cmd['title'] == args.title:
return cmd
return public.returnMsg(False,'COMMAND_NOTEXIST')
return public.return_msg_gettext(False,'The specified command does not exist')
def modify_command(self,args):
'''
@@ -1068,18 +1165,18 @@ class ssh_host_admin(ssh_terminal):
}
@return dict
'''
args.title = args.title.strip()
title = args.title.strip()
command = self.get_command_list(sys_cmd=True)
if not self.command_exists(command,args.title):
return public.returnMsg(False,'COMMAND_NOTEXIST')
return public.return_msg_gettext(False,'The specified command does not exist')
for i in range(len(command)):
if command[i]['title'] == args.title:
command[i]['title'] = args.new_title
if command[i]['title'] == args.title or command[i]['title'] == title:
command[i]['title'] = args.new_title.strip()
command[i]['shell'] = args.shell.strip()
break
self.save_command(command)
public.WriteLog(self._log_type,'EDIT_COMMAND_COMMAND',(str(args.title),))
return public.returnMsg(True,'SET_SUCCESS')
public.write_log_gettext(self._log_type,'Modify common commands [{}]',(str(args.title),))
return public.return_msg_gettext(True,'Setup successfully!')
def remove_command(self,args):
'''
@@ -1093,12 +1190,12 @@ class ssh_host_admin(ssh_terminal):
args.title = args.title.strip()
command = self.get_command_list(sys_cmd=True)
if not self.command_exists(command,args.title):
return public.returnMsg(False,'COMMAND_NOTEXIST')
return public.return_msg_gettext(False,'The specified command does not exist')
for i in range(len(command)):
if command[i]['title'] == args.title:
del(command[i])
break
self.save_command(command)
public.WriteLog(self._log_type,'DEL_COMMAND_COMMAND',(str(args.title),))
return public.returnMsg(True,'SET_SUCCESS')
public.write_log_gettext(self._log_type,'Delete common commands [{}]',(str(args.title),))
return public.return_msg_gettext(True,'Setup successfully!')
+33 -34
View File
@@ -28,7 +28,7 @@ class system:
data = session['config']
data['webserver'] = public.get_webserver()
#PHP版本
phpVersions = ('52','53','54','55','56','70','71','72','73','74')
phpVersions = public.get_php_versions()
data['php'] = []
@@ -120,7 +120,7 @@ class system:
tmp['type'] = data['webserver']
tmp['version'] = public.readFile(self.setupPath + '/'+data['webserver']+'/version.pl');
tmp['version'] = public.xss_version(public.readFile(self.setupPath + '/'+data['webserver']+'/version.pl'))
tmp['status'] = False
result = public.ExecShell('/etc/init.d/' + serviceName + ' status')
if result[0].find('running') != -1: tmp['status'] = True
@@ -128,7 +128,7 @@ class system:
tmp = {}
vfile = self.setupPath + '/phpmyadmin/version.pl'
tmp['version'] = public.readFile(vfile)
tmp['version'] = public.xss_version(public.readFile(vfile))
if tmp['version']: tmp['version'] = tmp['version'].strip()
tmp['setup'] = os.path.exists(vfile)
tmp['status'] = pstatus
@@ -141,12 +141,12 @@ class system:
tmp['setup'] = os.path.exists('/etc/init.d/tomcat')
tmp['status'] = tmp['setup']
#if public.ExecShell('ps -aux|grep tomcat|grep -v grep')[0] == "": tmp['status'] = False
tmp['version'] = public.readFile(self.setupPath + '/tomcat/version.pl')
tmp['version'] = public.xss_version(public.readFile(self.setupPath + '/tomcat/version.pl'))
data['tomcat'] = tmp
tmp = {}
tmp['setup'] = os.path.exists(self.setupPath +'/mysql/bin/mysql')
tmp['version'] = public.readFile(self.setupPath + '/mysql/version.pl')
tmp['version'] = public.xss_version(public.readFile(self.setupPath + '/mysql/version.pl'))
tmp['status'] = os.path.exists('/tmp/mysql.sock')
data['mysql'] = tmp
@@ -162,7 +162,7 @@ class system:
tmp = {}
tmp['setup'] = os.path.exists(self.setupPath +'/pure-ftpd/bin/pure-pw')
tmp['version'] = public.readFile(self.setupPath + '/pure-ftpd/version.pl')
tmp['version'] = public.xss_version(public.readFile(self.setupPath + '/pure-ftpd/version.pl'))
tmp['status'] = os.path.exists('/var/run/pure-ftpd.pid')
data['pure-ftpd'] = tmp
data['panel'] = self.GetPanelInfo()
@@ -281,14 +281,7 @@ class system:
key = 'sys_version'
version = cache.get(key)
if version: return version
import public
version = public.readFile('/etc/redhat-release')
if not version:
version = public.readFile('/etc/issue').strip().split("\n")[0].replace('\\n','').replace('\l','').strip()
else:
version = version.replace('release ','').replace('Linux','').replace('(Core)','').strip()
v_info = sys.version_info
version = version + '(Py' + str(v_info.major) + '.' + str(v_info.minor) + '.' + str(v_info.micro) + ')'
version = public.get_os_version()
cache.set(key,version,600)
return version
@@ -396,13 +389,17 @@ class system:
diskInfo.append(tmp)
return diskInfo
def GetDiskInfo2(self):
def GetDiskInfo2(self, human=True):
#取磁盘分区信息
key = 'sys_disk'
diskInfo = cache.get(key)
if diskInfo: return diskInfo
temp = public.ExecShell("df -hT -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev")[0]
tempInodes = public.ExecShell("df -i -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev")[0]
if human:
temp = public.ExecShell("df -hT -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev|grep -v overlay")[0]
else:
temp = public.ExecShell("df -T -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev|grep -v overlay")[0]
tempInodes = public.ExecShell("df -i -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev|grep -v overlay")[0]
temp1 = temp.split('\n')
tempInodes1 = tempInodes.split('\n')
diskInfo = []
@@ -432,7 +429,7 @@ class system:
arr['inodes'] = [inodes[1],inodes[2],inodes[3],inodes[4]]
diskInfo.append(arr)
except Exception as ex:
public.WriteLog('GET_INFO',str(ex))
public.write_log_gettext('Get Info',str(ex))
continue
cache.set(key,diskInfo,10)
return diskInfo
@@ -809,7 +806,7 @@ class system:
import ajax
get.status = 'True'
ajax.ajax().setPHPMyAdmin(get)
return public.returnMsg(True,'SYS_EXEC_SUCCESS')
return public.return_msg_gettext(True,'Executed successfully!')
if get.name == 'openlitespeed':
if get.type == 'stop':
@@ -818,12 +815,12 @@ class system:
public.ExecShell('rm -f /tmp/lshttpd/*.sock* && /usr/local/lsws/bin/lswsctrl start')
else:
public.ExecShell('rm -f /tmp/lshttpd/*.sock* && /usr/local/lsws/bin/lswsctrl restart')
return public.returnMsg(True,'SYS_EXEC_SUCCESS')
return public.return_msg_gettext(True,'Executed successfully!')
#检查httpd配置文件
if get.name == 'apache' or get.name == 'httpd':
get.name = 'httpd'
if not os.path.exists(self.setupPath+'/apache/bin/apachectl'): return public.returnMsg(True,'SYS_NOT_INSTALL_APACHE')
if not os.path.exists(self.setupPath+'/apache/bin/apachectl'): return public.return_msg_gettext(True,'Execution failed, check if Apache installed')
vhostPath = self.setupPath + '/panel/vhost/apache'
if not os.path.exists(vhostPath):
public.ExecShell('mkdir ' + vhostPath)
@@ -835,8 +832,8 @@ class system:
result = public.ExecShell('ulimit -n 8192 ; ' + self.setupPath+'/apache/bin/apachectl -t')
if result[1].find('Syntax OK') == -1:
public.WriteLog("TYPE_SOFT",'SYS_EXEC_ERR', (str(result),))
return public.returnMsg(False,'SYS_CONF_APACHE_ERR',(result[1].replace("\n",'<br>'),))
public.write_log_gettext("Software manager",'Execution failed: {}', (str(result),))
return public.return_msg_gettext(False,"Apache rule configuration error: <br><a style='color:red;'>{}</a>",(result[1].replace("\n",'<br>'),))
if get.type == 'restart':
public.ExecShell('pkill -9 httpd')
@@ -847,12 +844,14 @@ class system:
elif get.name == 'nginx':
vhostPath = self.setupPath + '/panel/vhost/rewrite'
if not os.path.exists(vhostPath): public.ExecShell('mkdir ' + vhostPath)
if not os.path.exists("/dev/shm/nginx-cache/wp"):
public.ExecShell('mkdir -p /dev/shm/nginx-cache/wp && chown -R www.www /dev/shm/nginx-cache')
vhostPath = self.setupPath + '/panel/vhost/nginx'
if not os.path.exists(vhostPath):
public.ExecShell('mkdir ' + vhostPath)
public.ExecShell('/etc/init.d/nginx start')
result = public.ExecShell('ulimit -n 8192 ; nginx -t -c '+self.setupPath+'/nginx/conf/nginx.conf')
result = public.ExecShell('ulimit -n 8192 ; '+self.setupPath+'/nginx/sbin/nginx -t -c '+self.setupPath+'/nginx/conf/nginx.conf')
if result[1].find('perserver') != -1:
limit = self.setupPath + '/nginx/conf/nginx.conf'
nginxConf = public.readFile(limit)
@@ -860,18 +859,18 @@ class system:
nginxConf = nginxConf.replace("#limit_conn_zone $binary_remote_addr zone=perip:10m;",limitConf)
public.writeFile(limit,nginxConf)
public.ExecShell('/etc/init.d/nginx start')
return public.returnMsg(True,'SYS_CONF_NGINX_REP')
return public.return_msg_gettext(True,'Configuration file mismatch caused by reinstalling Nginx fixed')
if result[1].find('proxy') != -1:
import panelSite
panelSite.panelSite().CheckProxy(get)
public.ExecShell('/etc/init.d/nginx start')
return public.returnMsg(True,'SYS_CONF_NGINX_REP')
return public.return_msg_gettext(True,'Configuration file mismatch caused by reinstalling Nginx fixed')
#return result
if result[1].find('successful') == -1:
public.WriteLog("TYPE_SOFT",'SYS_EXEC_ERR', (str(result),))
return public.returnMsg(False,'SYS_CONF_NGINX_ERR',(result[1].replace("\n",'<br>'),))
public.write_log_gettext("Software manager",'Execution failed: {}', (str(result),))
return public.return_msg_gettext(False,"Nginx rule configuration error: <br><a style='color:red;'>{}</a>",(result[1].replace("\n",'<br>'),))
if get.type == 'start':
self.kill_port()
@@ -903,14 +902,14 @@ class system:
public.ExecShell('pkill -9 nginx && sleep 1')
public.ExecShell('/etc/init.d/nginx start')
if get.type != 'test':
public.WriteLog("TYPE_SOFT", 'SYS_EXEC_SUCCESS',(execStr,))
if len(result[1]) > 1 and get.name != 'pure-ftpd' and get.name != 'redis': return public.returnMsg(False, '<p>Warning message: <p>' + result[1].replace('\n','<br>'))
return public.returnMsg(True,'SYS_EXEC_SUCCESS')
public.write_log_gettext("Software manager", 'Executed successfully!',(execStr,))
if len(result[1]) > 1 and get.name != 'pure-ftpd' and get.name != 'redis': return public.return_msg_gettext(False, '<p>Warning message: <p>' + result[1].replace('\n','<br>'))
return public.return_msg_gettext(True,'Executed successfully!')
def RestartServer(self,get):
if not public.IsRestart(): return public.returnMsg(False,'EXEC_ERR_TASK')
if not public.IsRestart(): return public.return_msg_gettext(False,'Please run the program when all install tasks finished!')
public.ExecShell("sync && init 6 &")
return public.returnMsg(True,'SYS_REBOOT')
return public.return_msg_gettext(True,'Command sent successfully!')
def kill_port(self):
public.ExecShell('pkill -9 httpd')
@@ -931,7 +930,7 @@ class system:
def ReWeb(self,get):
public.ExecShell("/etc/init.d/bt start")
public.writeFile('data/restart.pl','True')
return public.returnMsg(True,'PANEL_WAS_RESTART')
return public.return_msg_gettext(True,'Panel restarted')
#修复面板
+9 -3
View File
@@ -27,8 +27,11 @@ class tomcat:
self.__ENGINE = self.__TREE.findall('Service/Engine')[0];
#获取虚拟主机列表
def GetVhosts(self):
Hosts = self.__ENGINE.getchildren();
def GetVhosts(self):
try:
Hosts = self.__ENGINE.getchildren()
except:
Hosts = list(self.__ENGINE)
data = []
for host in Hosts:
if host.tag != 'Host': continue;
@@ -63,7 +66,10 @@ class tomcat:
#获取指定虚拟主机
def GetVhost(self,name):
Hosts = self.__ENGINE.getchildren();
try:
Hosts = self.__ENGINE.getchildren()
except:
Hosts = list(self.__ENGINE)
for host in Hosts:
if host.tag != 'Host': continue;
if host.attrib['name'] == name:
+73 -73
View File
@@ -65,8 +65,8 @@ def set_panel_pwd(password,ncli = False):
result = sql.table('users').where('id=?',(1,)).setField('password',public.md5(password))
username = sql.table('users').where('id=?',(1,)).getField('username')
if ncli:
print("|-%s: " % public.GetMsg("USER_NAME") + username)
print("|-%s: " % public.GetMsg("NEW_PASS") + password)
print("|-%s: " % public.get_msg_gettext('Username') + username)
print("|-%s: " % public.get_msg_gettext('New password') + password)
else:
print(username)
@@ -107,28 +107,28 @@ echo '---------------------------------------------------------------------'
#封装
def PackagePanel():
print('========================================================')
print('|-%s...' % public.GetMsg("CLEARING_LOG")),
public.M('logs').where('id!=?',(0,)).delete();
print('|-%s...' % public.get_msg_gettext('Clearing log info')),
public.M('logs').where('id!=?',(0,)).delete()
print('\t\t\033[1;32m[done]\033[0m')
print('|-%s...' % public.GetMsg("CLEARING_TASK_HISTORY")),
public.M('tasks').where('id!=?',(0,)).delete();
print('|-%s...' % public.get_msg_gettext('Clearing task history')),
public.M('tasks').where('id!=?',(0,)).delete()
print('\t\t\033[1;32m[done]\033[0m')
print('|-%s...' % public.GetMsg("CLEARING_NET_MO")),
public.M('network').dbfile('system').where('id!=?',(0,)).delete();
print('|-%s...' % public.get_msg_gettext('Clearing network monitoring records')),
public.M('network').dbfile('system').where('id!=?',(0,)).delete()
print('\t\033[1;32m[done]\033[0m')
print('|-%s...' % public.GetMsg("CLEARING_CPU_MO")),
public.M('cpuio').dbfile('system').where('id!=?',(0,)).delete();
print('|-%s...' % public.get_msg_gettext('Clearing CPU monitoring records')),
public.M('cpuio').dbfile('system').where('id!=?',(0,)).delete()
print('\t\033[1;32m[done]\033[0m')
print('|-%s...' % public.GetMsg("CLEARING_DISK_MO")),
public.M('diskio').dbfile('system').where('id!=?',(0,)).delete();
print('|-%s...' % public.get_msg_gettext('Clearing disk monitoring records')),
public.M('diskio').dbfile('system').where('id!=?',(0,)).delete()
print('\t\033[1;32m[done]\033[0m')
print('|-%s...' % public.GetMsg('CLEARING_IP')),
print('|-%s...' % public.get_msg_gettext('Clearing IP info')),
os.system('rm -f /www/server/panel/data/iplist.txt')
os.system('rm -f /www/server/panel/data/address.pl')
os.system('rm -f /www/server/panel/data/*.login')
os.system('rm -f /www/server/panel/data/domain.conf')
print('\t\033[1;32m[done]\033[0m')
print('|-%s...' % public.GetMsg("CLEARING_SYS_HISTORY")),
print('|-%s...' % public.get_msg_gettext('Clearing system history')),
command = '''cat /dev/null > /var/log/boot.log
cat /dev/null > /var/log/btmp
cat /dev/null > /var/log/cron
@@ -154,8 +154,8 @@ history -c
port = public.readFile('data/port.pl').strip();
public.M('config').where("id=?",('1',)).setField('status',0);
print('========================================================')
print('\033[1;32m|-%s\033[0m' % public.GetMsg("PANEL_TIPS"))
print('\033[1;41m|-%s: http://{SERVERIP}:' % public.GetMsg("PANEL_INIT_ADD")+port+'/install\033[0m')
print('\033[1;32m|-%s\033[0m' % public.get_msg_gettext('The panel is packaged successfully. Please do NOT log in to the panel to do any other operations!'))
print('\033[1;41m|-%s: http://{SERVERIP}:' % public.get_msg_gettext('Panel initialization address')+port+'/install\033[0m')
#清空正在执行的任务
def CloseTask():
@@ -163,7 +163,7 @@ def CloseTask():
os.system("kill `ps -ef |grep 'python panelSafe.pyc'|grep -v grep|grep -v panelExec|awk '{print $2}'`");
os.system("kill `ps -ef |grep 'install_soft.sh'|grep -v grep|grep -v panelExec|awk '{print $2}'`");
os.system('/etc/init.d/bt restart');
print(public.GetMsg("CLEAR_TASK",(int(ncount),)))
print(public.get_msg_gettext('Successfully cleared {} tasks!',(int(ncount),)))
#自签证书
def CreateSSL():
@@ -217,7 +217,7 @@ def ClearSystem():
count += tmp_count;
total += tmp_total;
print('=======================================================================')
print('\033[1;32m|-%s\033[0m' % public.GetMsg("CLEAR_RUBBISH",(str(count),ToSize(total))));
print('\033[1;32m|-%s\033[0m' % public.get_msg_gettext('System rubbish cleared, totally deleted [{}] files, freed disk space [{}]',(str(count),ToSize(total))));
#清理邮件日志
def ClearMail():
@@ -242,11 +242,11 @@ def ClearMail():
os.remove(filename)
print('\t\033[1;32m[OK]\033[0m')
num += 1
print(public.GetMsg("CLEAR_RUBBISH1",(dpath,str(num),ToSize(size))))
print(public.get_msg_gettext('|-Cleared [{}], deleted [{}] files, freed disk space [{}]',(dpath,str(num),ToSize(size))))
total += size;
count += num;
print('=======================================================================')
print(public.GetMsg('CLEAR_RUBBISH2',(str(count),ToSize(total))))
print(public.get_msg_gettext('|-Spool cleared, deleted [{}] files, freed disk space [{}]',(str(count),ToSize(total))))
return total,count
#清理php_session文件
@@ -254,7 +254,7 @@ def ClearSession():
spath = '/tmp'
total = count = 0;
import shutil
print(public.GetMsg("CLEAR_PHP_SESSION"));
print(public.get_msg_gettext('|-Clearing PHP Session ...'));
for d in os.listdir(spath):
if d.find('sess_') == -1: continue;
filename = spath + '/' + d;
@@ -267,7 +267,7 @@ def ClearSession():
os.remove(filename)
print('\t\033[1;32m[OK]\033[0m')
count += 1;
print(public.GetMsg("CLEAR_PHP_SESSION1",(str(count),ToSize(total))))
print(public.get_msg_gettext('|-PHP session cleared, deleted [{}] files, freed disk space [{}]',(str(count),ToSize(total))))
return total,count
#清空回收站
@@ -288,7 +288,7 @@ def ClearOther():
]
total = count = 0;
print(public.GetMsg('CLEAR_RUBBISH3'));
print(public.get_msg_gettext('|-Clearing up temporary files and site logs...'));
for c in clearPath:
for d in os.listdir(c['path']):
if d.find(c['find']) == -1: continue;
@@ -304,7 +304,7 @@ def ClearOther():
count += 1;
public.serviceReload();
os.system('sleep 1 && /etc/init.d/bt reload > /dev/null &');
print(public.GetMsg("CLEAR_RUBBISH4",(str(count),ToSize(total))))
print(public.get_msg_gettext('|-Temporary files and site logs cleared, deleted [{}] files, freed disk space [{}]',(str(count),ToSize(total))))
return total,count
#关闭普通日志
@@ -336,14 +336,14 @@ def set_panel_username(username = None):
sql = db.Sql()
if username:
if len(username) < 5:
print(public.GetMsg("USER_NAME_LEN_ERR"))
print(public.get_msg_gettext('|-ERROR, username cannot be less than 5 characters'))
return;
if username in ['admin','root']:
print(public.GetMsg("EASY_NAME"))
print(public.get_msg_gettext('|-ERROR, cannot use too simple username'))
return;
sql.table('users').where('id=?',(1,)).setField('username',username)
print(public.GetMsg("NEW_NAME",(username,)))
print(public.get_msg_gettext('|-New username: {}',(username,)))
return;
username = sql.table('users').where('id=?',(1,)).getField('username')
@@ -365,14 +365,14 @@ def setup_idc():
pFile = panelPath + '/static/language/Simplified_Chinese/public.json'
pInfo = json.loads(public.readFile(pFile))
pInfo['BRAND'] = idcInfo['msg']['name']
pInfo['PRODUCT'] = public.GetMsg("WITH_BT_CUSTOM_EDITION")
pInfo['PRODUCT'] = public.get_msg_gettext('Customized edition with aaPanel')
pInfo['NANE'] = pInfo['BRAND'] + pInfo['PRODUCT']
public.writeFile(pFile,json.dumps(pInfo))
tFile = panelPath + '/data/title.pl'
titleNew = (pInfo['BRAND'] + public.GetMsg("PANEL")).encode('utf-8')
titleNew = (pInfo['BRAND'] + public.get_msg_gettext('Failedcannot delete current port of the panel!')).encode('utf-8')
if os.path.exists(tFile):
title = public.readFile(tFile).strip()
if title == public.GetMsg("NAME") or title == '': public.writeFile(tFile,titleNew)
if title == public.get_msg_gettext('aaPanel') or title == '': public.writeFile(tFile,titleNew)
else:
public.writeFile(tFile,titleNew)
return True
@@ -381,48 +381,48 @@ def setup_idc():
#将插件升级到6.0
def update_to6():
print("====================================================")
print(public.GetMsg("PLUG_UPDATEING"))
print(public.get_msg_gettext('Updating plugin...'))
print("====================================================")
download_address = public.get_url()
exlodes = ['gitlab','pm2','mongodb','deployment_jd','logs','docker','beta','btyw']
for pname in os.listdir('plugin/'):
if not os.path.isdir('plugin/' + pname): continue
if pname in exlodes: continue
print("|-正在升级【%s..." % pname),
download_url = download_address + '/install/plugin/' + pname + '/install.sh';
print(public.get_msg_gettext("|-Upgrading [{}]...",(pname,))),
download_url = download_address + '/install/plugin/' + pname + '/install.sh'
to_file = '/tmp/%s.sh' % pname
public.downloadFile(download_url,to_file);
os.system('/bin/bash ' + to_file + ' install &> /tmp/plugin_update.log 2>&1');
print(" \033[32m[%s]\033[0m" % public.GetMsg("SUCCESS"))
public.downloadFile(download_url,to_file)
os.system('/bin/bash ' + to_file + ' install &> /tmp/plugin_update.log 2>&1')
print(" \033[32m[%s]\033[0m" % public.get_msg_gettext('Login succeeded, loading...'))
print("====================================================")
print("\033[32m%s\033[0m" % public.GetMsg("PLUG_UPDATE_TO_6"))
print("\033[32m%s\033[0m" % public.get_msg_gettext('All plugins successfully updated to 6.0 compatible!'))
print("====================================================")
#命令行菜单
def bt_cli():
raw_tip = "==============================================="
print("===============%s==================" % public.GetMsg("PANEL_SHELL"))
print("(01) %s (08) %s" % (public.GetMsg("RESTART_PANEL"),public.GetMsg("CHANGE_PANEL_PORT")))
print("(02) %s (09) %s" % (public.GetMsg("STOP_PANEL"),public.GetMsg("CLEAR_PANEL_CACHE")))
print("(03) %s (10) %s" % (public.GetMsg("START_PANEL"),public.GetMsg("CLEAR_PANEL_LIMIT")))
print("(04) %s (11) %s" % (public.GetMsg("RELOAD_PANEL"),public.GetMsg("CANCEL_ENTRY")))
print("(05) %s (12) %s" % (public.GetMsg("CHANGE_PANEL_PASS"),public.GetMsg("CANCEL_DOMAIN_BIND")))
print("(06) %s (13) %s" % (public.GetMsg("CHANGE_PANEL_USER"),public.GetMsg("CANCEL_IP_LIMIT")))
print("(07) %s (14) %s" % (public.GetMsg("CHANGE_MYSQL_PASS_FORCE"),public.GetMsg("GET_PANEL_DEFAULT_MSG")))
print("(00) %s (15) %s" % (public.GetMsg("CANCEL"),public.GetMsg("CLEAR_SYS_RUBBISH")))
print("===============%s==================" % public.get_msg_gettext('aaPanel CLI'))
print("(01) %s (08) %s" % (public.get_msg_gettext('Restart panel'),public.get_msg_gettext('Change panel port')))
print("(02) %s (09) %s" % (public.get_msg_gettext('Stop panel'),public.get_msg_gettext('Clear panel cache')))
print("(03) %s (10) %s" % (public.get_msg_gettext('Restart panel'),public.get_msg_gettext('Clear login limit')))
print("(04) %s (11) %s" % (public.get_msg_gettext('Reload panel'),public.get_msg_gettext('Cancel entrance limit')))
print("(05) %s (12) %s" % (public.get_msg_gettext('Change panel password'),public.get_msg_gettext('Cancel domain binding limit')))
print("(06) %s (13) %s" % (public.get_msg_gettext('Change panel username'),public.get_msg_gettext('Cacel IP access limit')))
print("(07) %s (14) %s" % (public.get_msg_gettext('Forcibly change MySQL root password'),public.get_msg_gettext('View panel default info')))
print("(00) %s (15) %s" % (public.get_msg_gettext('Task cancelled!'),public.get_msg_gettext('Clear system rubbish')))
print(raw_tip)
try:
u_input = input(public.GetMsg("INPUT_CMD_NUM"))
u_input = input(public.get_msg_gettext('Pls enter command number'))
if sys.version_info[0] == 3: u_input = int(u_input)
except: u_input = 0
nums = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
if not u_input in nums:
print(raw_tip)
print(public.GetMsg("CANCELLED"))
print(public.get_msg_gettext('Cacelled!'))
exit()
print(raw_tip)
print(public.GetMsg("EXECUTING",(u_input,)))
print(public.get_msg_gettext('Executing ({})...',(u_input,)))
print(raw_tip)
if u_input == 1:
@@ -435,55 +435,55 @@ def bt_cli():
os.system("/etc/init.d/bt reload")
elif u_input == 5:
if sys.version_info[0] == 2:
input_pwd = raw_input(public.GetMsg("INPUT_NEW_PASS"))
input_pwd = raw_input(public.get_msg_gettext('Pls enter new password: '))
else:
input_pwd = input(public.GetMsg("INPUT_NEW_PASS"))
input_pwd = input(public.get_msg_gettext('Pls enter new password: '))
set_panel_pwd(input_pwd.strip(),True)
elif u_input == 6:
if sys.version_info[0] == 2:
input_user = raw_input(public.GetMsg("INPUT_NEW_USER"))
input_user = raw_input(public.get_msg_gettext('Pls enter new username(>5 characters): '))
else:
input_user = input(public.GetMsg("INPUT_NEW_USER"))
input_user = input(public.get_msg_gettext('Pls enter new username(>5 characters): '))
set_panel_username(input_user.strip())
elif u_input == 7:
if sys.version_info[0] == 2:
input_mysql = raw_input(public.GetMsg("INPUT_NEW_MYSQL_PASS"))
input_mysql = raw_input(public.get_msg_gettext('Pls enter new MySQL root password'))
else:
input_mysql = input(public.GetMsg("INPUT_NEW_MYSQL_PASS"))
input_mysql = input(public.get_msg_gettext('Pls enter new MySQL root password'))
if not input_mysql:
print(public.GetMsg("PASS_NOT_EMPTY"))
return;
print(public.get_msg_gettext('|-ERROR, password cannot be empty'))
return
if len(input_mysql) < 8:
print(public.GetMsg("PASS_LEN_ERR"))
return;
print(public.get_msg_gettext('|-ERROR, password cannot be less than 8 characters'))
return
import re
rep = "^[\w@\._]+$"
if not re.match(rep, input_mysql):
print(public.GetMsg("PASS_SPECIAL_CHARACTRES_ERR"))
return;
print(public.get_msg_gettext('|-ERROR, password cannot contain special characters'))
return
print(input_mysql)
set_mysql_root(input_mysql.strip())
elif u_input == 8:
input_port = input(public.GetMsg("INPUT_NEW_PANEL_PORT"))
input_port = input(public.get_msg_gettext('Pls enter new panel port: '))
if sys.version_info[0] == 3: input_port = int(input_port)
if not input_port:
print(public.GetMsg("INPUT_PANEL_PORT_ERR"))
return;
print(public.get_msg_gettext('|-ERROR, no valid port entered'))
return
if input_port in [80,443,21,20,22]:
print(public.GetMsg("CANT_USE_USUALLY_PORT_ERR"))
return;
print(public.get_msg_gettext('|-ERROR, pls do NOT use the common port as panel port'))
return
old_port = int(public.readFile('data/port.pl'))
if old_port == input_port:
print(public.GetMsg("NEW_PORT_SAMEAS_OLD"))
return;
print(public.get_msg_gettext('|-ERROR, new port is the same as current panel port, no need to change'))
return
is_exists = public.ExecShell("lsof -i:%s" % input_port)
if len(is_exists[0]) > 5:
print(public.GetMsg("PORT_ALREADY_IN_USE"))
return;
print(public.get_msg_gettext('|-ERROR, specified port is already in use'))
return
public.writeFile('data/port.pl',str(input_port))
if os.path.exists("/usr/bin/firewall-cmd"):
@@ -507,17 +507,17 @@ def bt_cli():
auth_file = 'data/admin_path.pl'
if os.path.exists(auth_file): os.remove(auth_file)
os.system("/etc/init.d/bt reload")
print(public.GetMsg("CHANGE_LIMITED_CANCEL"))
print(public.get_msg_gettext('|-Entrance limit cancelled'))
elif u_input == 12:
auth_file = 'data/domain.conf'
if os.path.exists(auth_file): os.remove(auth_file)
os.system("/etc/init.d/bt reload")
print(public.GetMsg("CHANGE_DOMAIN_CANCEL"))
print(public.get_msg_gettext('|-Domain limit cancelled'))
elif u_input == 13:
auth_file = 'data/limitip.conf'
if os.path.exists(auth_file): os.remove(auth_file)
os.system("/etc/init.d/bt reload")
print(public.GetMsg("CHANGE_IP_CANCEL"))
print(public.get_msg_gettext('|-IP access limit cancelled'))
elif u_input == 14:
os.system("/etc/init.d/bt default")
elif u_input == 15:
+120 -70
View File
@@ -12,43 +12,74 @@ from BTPanel import session,cache,json_header
from flask import request,redirect,g
class userlogin:
limit_expire_time = 0
def request_post(self,post):
if not hasattr(post, 'username') or not hasattr(post, 'password'):
return public.returnJson(False,'LOGIN_USER_EMPTY'),json_header
return public.returnJson(False,'User name or password cannot be empty!'),json_header
self.error_num(False)
if self.limit_address('?') < 1: return public.returnJson(False,'LOGIN_ERR_LIMIT'),json_header
if self.limit_address('?') < 1: return public.returnJson(False,'You have failed to log in many times。 Please wait for {} seconds and try again!'.format(int(self.limit_expire_time - time.time()))),json_header
# if self.limit_address('?') < 1: return public.returnJson(False,'You cannot login now because login failed too many times!'),json_header
post.username = post.username.strip()
# 核验用户名密码格式
if len(post.username) != 32: return public.return_msg_gettext(False,'Disk inode has been exhausted, the panel has attempted to release the inode. Please try again ...'),json_header
if len(post.password) != 32: return public.return_msg_gettext(False,'Disk inode has been exhausted, the panel has attempted to release the inode. Please try again ...'),json_header
if not re.match(r"^\w+$",post.username): return public.return_msg_gettext(False,'Disk inode has been exhausted, the panel has attempted to release the inode. Please try again ...'),json_header
if not re.match(r"^\w+$",post.password): return public.return_msg_gettext(False,'Disk inode has been exhausted, the panel has attempted to release the inode. Please try again ...'),json_header
last_login_token = session.get('last_login_token',None)
if not last_login_token:
public.write_log_gettext('Login','Verification code error, account number: {}, verification code: {}, login IP: {}',('****','****',public.GetClientIp()))
return public.returnJson(False,"Verification failed, please refresh the page and log in again!"),json_header
public.chdck_salt()
sql = db.Sql()
user_list = sql.table('users').field('id,username,password,salt').select()
userInfo = None
for u_info in user_list:
if public.md5(u_info['username']) == post.username:
userInfo = u_info
user_plugin_file = '{}/users_main.py'.format(public.get_plugin_path('users'))
if os.path.exists(user_plugin_file):
user_list = sql.table('users').field('id,username,password,salt').select()
for u_info in user_list:
if public.md5(public.md5(u_info['username'] + last_login_token)) == post.username:
userInfo = u_info
else:
userInfo = sql.table('users').where('id=?',1).field('id,username,password,salt').find()
if 'code' in session:
if session['code'] and not 'is_verify_password' in session:
if not hasattr(post, 'code'): return public.returnJson(False,'Verification code can not be empty!'),json_header
if not re.match(r"^\w+$",post.code): return public.returnJson(False,'Verification code is incorrect, please try again!'),json_header
if not public.checkCode(post.code):
public.WriteLog('TYPE_LOGIN','LOGIN_ERR_CODE',('****','****',public.GetClientIp()))
return public.returnJson(False,'CODE_ERR'),json_header
public.write_log_gettext('Login','Verification code is incorrect, Username:{}, Verification Code:{}, Login IP:{}',('****','****',public.GetClientIp()))
return public.returnJson(False,'Verification code is incorrect, please try again!'),json_header
try:
if not userInfo['salt']:
if not userInfo:
public.write_log_gettext('Login','Wrong password, account: {}, password: {}, login IP: {}',('****','******',public.GetClientIp()))
num = self.limit_address('+')
if not num: return public.returnJson(False,'You have failed to log in many times, please wait {} seconds and try again!'.format(int(self.limit_expire_time - time.time()))),json_header
return public.returnJson(False,'Username or password is wrong, <span style="color:red;">Please refresh the page and try again</span>, you can try again [{}] times'.format(num)),json_header
if userInfo and not userInfo['salt']:
public.chdck_salt()
userInfo = sql.table('users').where('id=?',(userInfo['id'],)).field('id,username,password,salt').find()
password = public.md5(post.password.strip() + userInfo['salt'])
if public.md5(userInfo['username']) != post.username or userInfo['password'] != password:
public.WriteLog('TYPE_LOGIN','LOGIN_ERR_PASS',('****','******',public.GetClientIp()))
s_username = public.md5(public.md5(userInfo['username'] + last_login_token))
if s_username != post.username or userInfo['password'] != password:
public.write_log_gettext('Login','Password is incorrect, Username:{}, Password:{}, Login IP:{}',('****','******',public.GetClientIp()))
num = self.limit_address('+')
return public.returnJson(False,'LOGIN_USER_ERR',(str(num),)),json_header
if not num: return public.returnJson(False,'You have failed to log in many times, please wait {} seconds and try again!'.format(int(self.limit_expire_time - time.time()))),json_header
return public.returnJson(False,'Invalid username or password. You have [{}] times left to try!',(str(num),)),json_header
_key_file = "/www/server/panel/data/two_step_auth.txt"
#登陆告警
public.run_thread(public.login_send_body,("Userinfo",userInfo['username'],public.GetClientIp(),str(request.environ.get('REMOTE_PORT'))))
# 密码过期检测
if sys.path[0] != 'class/': sys.path.insert(0,'class/')
if not public.password_expire_check():
session['password_expire'] = True
# public.login_send_body("Userinfo",userInfo['username'],public.GetClientIp(),str(request.environ.get('REMOTE_PORT')))
if hasattr(post,'vcode'):
if not re.match(r"^\d+$",post.vcode): return public.returnJson(False,'Incorrect format of verification code'),json_header
if self.limit_address('?',v="vcode") < 1: return public.returnJson(False,'You have failed verification many times, forbidden for 10 minutes'),json_header
import pyotp
secret_key = public.readFile(_key_file)
@@ -62,6 +93,7 @@ class userlogin:
num = self.limit_address('++',v="vcode")
return public.returnJson(False, 'Invalid Verification code. You have [{}] times left to try!'.format(num)), json_header
now = int(time.time())
# public.run_thread(public.login_send_body,("account",userInfo['username'],public.GetClientIp(),str(int(request.environ.get('REMOTE_PORT')))))
public.writeFile("/www/server/panel/data/dont_vcode_ip.txt",json.dumps({"client_ip":public.GetClientIp(),"add_time":now}))
self.limit_address('--',v="vcode")
self.set_cdn_host(post)
@@ -70,6 +102,7 @@ class userlogin:
acc_client_ip = self.check_two_step_auth()
if not os.path.exists(_key_file) or acc_client_ip:
# public.run_thread(public.login_send_body,("account",userInfo['username'],public.GetClientIp(),str(int(request.environ.get('REMOTE_PORT')))))
self.set_cdn_host(post)
return self._set_login_session(userInfo)
self.limit_address('-')
@@ -82,28 +115,30 @@ class userlogin:
public.ExecShell("rm -f /www/wwwlogs/*log")
public.ServiceReload()
return public.returnJson(False,'USER_INODE_ERR'),json_header
public.WriteLog('TYPE_LOGIN','LOGIN_ERR_PASS',('****','******',public.GetClientIp()))
public.write_log_gettext('Login','Password is incorrect, Username:{}, Password:{}, Login IP:{}',('****','******',public.GetClientIp()))
num = self.limit_address('+')
return public.returnJson(False,'LOGIN_USER_ERR',(str(num),)),json_header
if not num: return public.returnJson(False,'You have failed to log in many times, please wait {} seconds and try again!'.format(int(self.limit_expire_time - time.time()))),json_header
return public.returnJson(False,'Invalid username or password. You have [{}] times left to try!',(str(num),)),json_header
def request_tmp(self,get):
try:
if not hasattr(get,'tmp_token'): return public.returnJson(False,'INIT_ARGS_ERR'),json_header
if not hasattr(get,'tmp_token'): return public.returnJson(False,'Parameter ERROR!'),json_header
if len(get.tmp_token) == 48:
return self.request_temp(get)
if len(get.tmp_token) != 64: return public.returnJson(False,'INIT_ARGS_ERR'),json_header
if not re.match(r"^\w+$",get.tmp_token):return public.returnJson(False,'INIT_ARGS_ERR'),json_header
if len(get.tmp_token) != 64: return public.returnJson(False,'Parameter ERROR!'),json_header
if not re.match(r"^\w+$",get.tmp_token):return public.returnJson(False,'Parameter ERROR!'),json_header
save_path = '/www/server/panel/config/api.json'
data = json.loads(public.ReadFile(save_path))
if not 'tmp_token' in data or not 'tmp_time' in data: return public.returnJson(False,'VERIFICATION_FAILED'),json_header
if (time.time() - data['tmp_time']) > 120: return public.returnJson(False,'EXPIRED_TOKEN'),json_header
if get.tmp_token != data['tmp_token']: return public.returnJson(False,'INIT_TOKEN_ERR'),json_header
if not 'tmp_token' in data or not 'tmp_time' in data: return public.returnJson(False,'Verification failed'),json_header
if (time.time() - data['tmp_time']) > 120: return public.returnJson(False,'Expired Token'),json_header
if get.tmp_token != data['tmp_token']: return public.returnJson(False,'Invalid Token!'),json_header
userInfo = public.M('users').where("id=?",(1,)).field('id,username').find()
session['login'] = True
session['username'] = userInfo['username']
session['tmp_login'] = True
session['uid'] = userInfo['id']
public.WriteLog('TYPE_LOGIN','LOGIN_SUCCESS',(userInfo['username'],public.GetClientIp()+ ":" + str(request.environ.get('REMOTE_PORT'))))
ids = public.write_log_gettext('Login','Login success',(userInfo['username'],public.GetClientIp()+ ":" + str(request.environ.get('REMOTE_PORT'))))
public.cache_set(public.GetClientIp() + ":" + str(request.environ.get('REMOTE_PORT')), ids)
self.limit_address('-')
cache.delete('panelNum')
cache.delete('dologin')
@@ -121,28 +156,32 @@ class userlogin:
def request_temp(self,get):
try:
if len(get.__dict__.keys()) > 2: return public.getMsg('INIT_ARGS_ERR')
if not hasattr(get,'tmp_token'): return public.getMsg('INIT_ARGS_ERR')
if len(get.tmp_token) != 48: return public.getMsg('INIT_ARGS_ERR')
if not re.match(r"^\w+$",get.tmp_token):return public.getMsg('INIT_ARGS_ERR')
if len(get.__dict__.keys()) > 2: return public.get_msg_gettext('Parameter ERROR!')
if not hasattr(get,'tmp_token'): return public.get_msg_gettext('Parameter ERROR!')
if len(get.tmp_token) != 48: return public.get_msg_gettext('Parameter ERROR!')
if not re.match(r"^\w+$",get.tmp_token):return public.get_msg_gettext('Parameter ERROR!')
skey = public.GetClientIp() + '_temp_login'
if not public.get_error_num(skey,10): return public.getMsg('AUTH_FAILED')
if not public.get_error_num(skey,10): return public.get_msg_gettext('10 consecutive authentication failures are prohibited for 1 hour')
s_time = int(time.time())
if public.M('temp_login').where('state=? and expire>?',(0,s_time)).field('id,token,salt,expire').count()==0:
public.set_error_num(skey)
return public.get_msg_gettext('Verification failed')
data = public.M('temp_login').where('state=? and expire>?',(0,s_time)).field('id,token,salt,expire').find()
if not data:
public.set_error_num(skey)
return public.getMsg('VERIFICATION_FAILED')
return public.get_msg_gettext('Verification failed')
if not isinstance(data,dict):
public.set_error_num(skey)
return public.getMsg('VERIFICATION_FAILED')
return public.get_msg_gettext('Verification failed')
r_token = public.md5(get.tmp_token + data['salt'])
if r_token != data['token']:
public.set_error_num(skey)
return public.getMsg('VERIFICATION_FAILED')
return public.get_msg_gettext('Verification failed')
public.set_error_num(skey,True)
userInfo = public.M('users').where("id=?",(1,)).field('id,username').find()
session['login'] = True
session['username'] = public.getMsg('TEMPORARY_ID',(data['id'],))
session['username'] = public.get_msg_gettext('TEMPORARY_ID',(data['id'],))
session['tmp_login'] = True
session['tmp_login_id'] = str(data['id'])
session['tmp_login_expire'] = time.time() + 3600
@@ -152,7 +191,8 @@ class userlogin:
os.makedirs(sess_path,384)
public.writeFile(sess_path + '/' + str(data['id']),'')
login_addr = public.GetClientIp()+ ":" + str(request.environ.get('REMOTE_PORT'))
public.WriteLog('TYPE_LOGIN','LOGIN_SUCCESS',(userInfo['username'],login_addr))
ids = public.write_log_gettext('Login','Login succeed, Username: {}, Login IP: {}',(userInfo['username'],login_addr))
public.cache_set(public.GetClientIp()+ ":" + str(request.environ.get('REMOTE_PORT')),ids)
public.M('temp_login').where('id=?',(data['id'],)).update({"login_time":s_time,'state':1,'login_addr':login_addr})
self.limit_address('-')
cache.delete('panelNum')
@@ -161,10 +201,10 @@ class userlogin:
self.set_request_token()
self.login_token()
self.set_cdn_host(get)
public.login_send_body("Temporary authorization",userInfo['username'],public.GetClientIp(),str(request.environ.get('REMOTE_PORT')))
public.run_thread(public.login_send_body("Temporary authorization",userInfo['username'],public.GetClientIp(),str(request.environ.get('REMOTE_PORT'))))
return redirect('/')
except:
return public.getMsg('LOGIN_FAIL')
return public.get_msg_gettext('Login failed')
def login_token(self):
@@ -172,40 +212,40 @@ class userlogin:
config.config().reload_session()
def request_get(self,get):
#if os.path.exists('/www/server/panel/install.pl'): raise redirect('/install');
'''
@name 验证登录页面请求权限
@author hwliang
@return False | Response
'''
# 获取标题
if not 'title' in session: session['title'] = public.getMsg('NAME')
domain = public.readFile('data/domain.conf')
if domain:
if(public.GetHost().lower() != domain.strip().lower()):
return 404
# errorStr = public.ReadFile('./BTPanel/templates/' + public.GetConfigValue('template') + '/error2.html')
# try:
# errorStr = errorStr.format(public.getMsg('PAGE_ERR_TITLE'),public.getMsg('PAGE_ERR_DOMAIN_H1'),public.getMsg('PAGE_ERR_DOMAIN_P1'),public.getMsg('PAGE_ERR_DOMAIN_P2'),public.getMsg('PAGE_ERR_DOMAIN_P3'),public.getMsg('NAME'),public.getMsg('PAGE_ERR_HELP'))
# except IndexError:pass
# return errorStr
if os.path.exists('data/limitip.conf'):
iplist = public.readFile('data/limitip.conf')
if iplist:
iplist = iplist.strip()
if not public.GetClientIp() in iplist.split(','):
errorStr = public.ReadFile('./BTPanel/templates/' + public.GetConfigValue('template') + '/error2.html')
try:
errorStr = errorStr.format(public.getMsg('PAGE_ERR_TITLE'),public.getMsg('PAGE_ERR_IP_H1'),public.getMsg('PAGE_ERR_IP_P1',(public.GetClientIp(),)),public.getMsg('PAGE_ERR_IP_P2'),public.getMsg('PAGE_ERR_IP_P3'),public.getMsg('NAME'),public.getMsg('PAGE_ERR_HELP'))
except IndexError:pass
return errorStr
# 验证是否使用限制的域名访问
domain_check = public.check_domain_panel()
if domain_check: return domain_check
# 验证是否使用限制的IP地址访问
ip_check = public.check_ip_panel()
if ip_check: return ip_check
# 验证是否已经登录
if 'login' in session:
if session['login'] == True:
return redirect('/')
# 复位验证码
if not 'code' in session:
session['code'] = False
# 记录错误次数
self.error_num(False)
#生成request_token
def set_request_token(self):
session['request_token_head'] = public.GetRandomString(48)
html_token_key = public.get_csrf_html_token_key()
session[html_token_key] = public.GetRandomString(48)
session[html_token_key.replace("https_","")] = public.GetRandomString(48)
def set_cdn_host(self,get):
try:
@@ -227,21 +267,22 @@ class userlogin:
num = 1
if s: cache.inc(nKey,1)
if num > 6: session['code'] = True
#IP限制
def limit_address(self,type,v=""):
import time
clientIp = public.GetClientIp()
numKey = 'limitIpNum_' + v + clientIp
limit = 6
outTime = 600
limit = 5
outTime = 300
try:
#初始化
num1 = cache.get(numKey)
if not num1:
cache.set(numKey,1,outTime)
num1 = 1
cache.set(numKey,0,outTime)
num1 = 0
self.limit_expire_time = cache.get_expire_time(numKey)
#计数
if type == '+':
cache.inc(numKey,1)
@@ -278,27 +319,36 @@ class userlogin:
session['username'] = userInfo['username']
session['uid'] = userInfo['id']
session['login_user_agent'] = public.md5(request.headers.get('User-Agent',''))
public.WriteLog('TYPE_LOGIN','LOGIN_SUCCESS',(userInfo['username'],public.GetClientIp()+ ":" + str(request.environ.get('REMOTE_PORT'))))
ids = public.write_log_gettext('Login','Login succeed, Username: {}, Login IP: {}',(userInfo['username'],public.GetClientIp()+ ":" + str(request.environ.get('REMOTE_PORT'))))
public.cache_set(public.GetClientIp()+ ":" + str(request.environ.get('REMOTE_PORT')),ids)
self.limit_address('-')
cache.delete('panelNum')
cache.delete('dologin')
session['session_timeout'] = time.time() + public.get_session_timeout()
if 'last_login_token' in session: del(session['last_login_token'])
self.set_request_token()
self.login_token()
login_type = 'data/app_login.pl'
if os.path.exists(login_type):
os.remove(login_type)
return public.returnJson(True,'LOGIN_SUCCESS'),json_header
try:
default_pl = "{}/default.pl".format(public.get_panel_path())
public.writeFile(default_pl,"********")
public.run_thread(public.login_send_body, (
"Userinfo", userInfo['username'], public.GetClientIp(), str(request.environ.get('REMOTE_PORT'))))
except:
pass
return public.returnJson(True,'Login succeeded, loading...'),json_header
except Exception as ex:
stringEx = str(ex)
if stringEx.find('unsupported') != -1 or stringEx.find('-1') != -1:
public.ExecShell("rm -f /tmp/sess_*")
public.ExecShell("rm -f /www/wwwlogs/*log")
public.ServiceReload()
return public.returnJson(False,'USER_INODE_ERR'),json_header
public.WriteLog('TYPE_LOGIN','LOGIN_ERR_PASS',('****','******',public.GetClientIp()))
return public.returnJson(False,'Disk inode has been exhausted, the panel has attempted to release the inode. Please try again ...'),json_header
public.write_log_gettext('Login','Password is incorrect, Username:{}, Password:{}, Login IP:{}',('****','******',public.GetClientIp()))
num = self.limit_address('+')
return public.returnJson(False,'LOGIN_USER_ERR',(str(num),)),json_header
return public.returnJson(False,'Invalid username or password. You have [{}] times left to try!',(str(num),)),json_header
# 检查是否需要进行二次验证
Binary file not shown.
+29 -16
View File
@@ -13,6 +13,7 @@ if not 'class/' in sys.path:
import public
import json
import time
import uuid
from BTPanel import session,cache,request
class wxapp():
@@ -24,24 +25,28 @@ class wxapp():
def _check(self, get):
if get['fun'] in ['set_login', 'is_scan_ok', 'login_qrcode']:
return True
return public.returnMsg(False, 'UNAUTHORIZED')
return public.returnMsg(False, 'Unauthorized')
# 验证是否扫码成功
def is_scan_ok(self, get):
if os.path.exists(self.app_path+"app_login_check.pl"):
key, init_time = public.readFile(self.app_path+'app_login_check.pl').split(':')
if time.time() - float(init_time) > 60:
return public.returnMsg(False, 'QRCORE_EXPIRE')
session_id = public.get_session_id()
if cache.get(session_id) == 'True':
return public.returnMsg(True, 'Scan QRCORE successfully')
try:
key, init_time, tid, status = public.readFile(self.app_path+'app_login_check.pl').split(':')
if time.time() - float(init_time) > 60:
return public.returnMsg(False, 'QR code expired')
session_id = public.get_session_id()
if cache.get(session_id) == public.md5(uuid.UUID(int=uuid.getnode()).hex):
return public.returnMsg(True, 'Scan QRCORE successfully')
except:
os.remove(self.app_path + "app_login_check.pl")
return public.returnMsg(False, '')
return public.returnMsg(False, '')
# 返回二维码地址
def login_qrcode(self, get):
tid = public.GetRandomString(12)
tid = public.GetRandomString(32)
qrcode_str = 'https://app.bt.cn/app.html?&panel_url='+public.getPanelAddr()+'&v=' + public.GetRandomString(3)+'?login&tid=' + tid
data = public.get_session_id() + ':' + str(time.time())
data = public.get_session_id() + ':' + str(time.time()) + ':' + tid + ':' + tid
public.writeFile(self.app_path + "app_login_check.pl", data)
cache.set(tid,public.get_session_id(),360)
cache.set(public.get_session_id(),tid,360)
@@ -50,15 +55,20 @@ class wxapp():
# 设置登录状态
def set_login(self, get):
session_id = public.get_session_id()
if cache.get(session_id) == 'True':
return self.check_app_login(get)
if cache.get(session_id):
if cache.get(session_id) == public.md5(uuid.UUID(int=uuid.getnode()).hex):
return self.check_app_login(get)
else:
cache.delete(cache.get(session_id))
cache.delete(session_id)
return public.returnMsg(False, 'Login failed 2')
return public.returnMsg(False, 'Login failed 1')
#验证APP是否登录成功
def check_app_login(self,get):
#判断是否存在绑定
btapp_info = json.loads(public.readFile('/www/server/panel/config/api.json'))
if not btapp_info:return public.returnMsg(False,'Unbound')
if not btapp_info:return public.returnMsg(False,'Unbound!')
if not btapp_info['open']:return public.returnMsg(False,'API is not turned on')
if not 'apps' in btapp_info:return public.returnMsg(False,'Unbound phone')
if not btapp_info['apps']:return public.returnMsg(False,'Unbound phone')
@@ -67,19 +77,22 @@ class wxapp():
if not os.path.exists(self.app_path+'app_login_check.pl'):return public.returnMsg(False,'Waiting for APP scan code login 1')
data = public.readFile(self.app_path+'app_login_check.pl')
public.ExecShell('rm ' + self.app_path+"app_login_check.pl")
secret_key, init_time = data.split(':')
secret_key, init_time, tid, status = data.split(':')
if len(session_id)!=64:return public.returnMsg(False,'Waiting for APP scan code login 2')
if len(secret_key)!=64:return public.returnMsg(False,'Waiting for APP scan code login 2')
if session_id != secret_key:
return public.returnMsg(False,'QR code expired')
if time.time() - float(init_time) > 60:
return public.returnMsg(False,'Waiting for APP scan code login')
if session_id != secret_key:
return public.returnMsg(False,'Waiting for APP scan code login')
import uuid
if status != uuid.UUID(int=uuid.getnode()).hex[-12:]: return public.returnMsg(False, '当前二维码失效222')
cache.delete(session_id)
cache.delete(tid)
userInfo = public.M('users').where("id=?",(1,)).field('id,username').find()
session['login'] = True
session['username'] = userInfo['username']
session['tmp_login'] = True
public.WriteLog('TYPE_LOGIN','APP scan code login, account: {}, login IP: {}'.format(userInfo['username'],public.GetClientIp()+ ":" + str(request.environ.get('REMOTE_PORT'))))
public.WriteLog('Login','APP scan code login, account: {}, login IP: {}'.format(userInfo['username'],public.GetClientIp()+ ":" + str(request.environ.get('REMOTE_PORT'))))
cache.delete('panelNum')
cache.delete('dologin')
session['session_timeout'] = time.time() + public.get_session_timeout()