diff --git a/BTPanel/__init__.py b/BTPanel/__init__.py
index f9840470..af8c98db 100644
--- a/BTPanel/__init__.py
+++ b/BTPanel/__init__.py
@@ -20,6 +20,7 @@
from werkzeug.wrappers import Response
from flask_socketio import SocketIO,emit,send
dns_client = None
+app.config['DEBUG'] = os.path.exists('data/debug.pl')
#设置BasicAuth
basic_auth_conf = 'config/basic_auth.json'
@@ -413,9 +414,11 @@ def config(pdata = None):
data['basic_auth'] = c_obj.get_basic_auth_stat(None)
data['basic_auth']['value'] = public.GetMsg("CLOSE")
if data['basic_auth']['open']: data['basic_auth']['value'] = public.GetMsg("OPEN")
+ data['debug'] = ''
+ if app.config['DEBUG']: data['debug'] = 'checked'
return render_template( 'config.html',data=data)
import config
- defs = ('get_panel_error_logs','clean_panel_error_logs','get_basic_auth_stat','set_basic_auth','get_cli_php_version','get_tmp_token','set_cli_php_version','DelOldSession', 'GetSessionCount', 'SetSessionConf', 'GetSessionConf','get_ipv6_listen','set_ipv6_status','GetApacheValue','SetApacheValue','GetNginxValue','SetNginxValue','get_token','set_token','set_admin_path','is_pro','get_php_config','get_config','SavePanelSSL','GetPanelSSL','GetPHPConf','SetPHPConf','GetPanelList','AddPanelInfo','SetPanelInfo','DelPanelInfo','ClickPanelInfo','SetPanelSSL','SetTemplates','Set502','setPassword','setUsername','setPanel','setPathInfo','setPHPMaxSize','getFpmConfig','setFpmConfig','setPHPMaxTime','syncDate','setPHPDisable','SetControl','ClosePanel','AutoUpdatePanel','SetPanelLock')
+ defs = ('get_cert_source','set_debug','get_panel_error_logs','clean_panel_error_logs','get_basic_auth_stat','set_basic_auth','get_cli_php_version','get_tmp_token','set_cli_php_version','DelOldSession', 'GetSessionCount', 'SetSessionConf', 'GetSessionConf','get_ipv6_listen','set_ipv6_status','GetApacheValue','SetApacheValue','GetNginxValue','SetNginxValue','get_token','set_token','set_admin_path','is_pro','get_php_config','get_config','SavePanelSSL','GetPanelSSL','GetPHPConf','SetPHPConf','GetPanelList','AddPanelInfo','SetPanelInfo','DelPanelInfo','ClickPanelInfo','SetPanelSSL','SetTemplates','Set502','setPassword','setUsername','setPanel','setPathInfo','setPHPMaxSize','getFpmConfig','setFpmConfig','setPHPMaxTime','syncDate','setPHPDisable','SetControl','ClosePanel','AutoUpdatePanel','SetPanelLock')
return publicObject(config.config(),defs,None,pdata);
@app.route('/ajax',methods=method_all)
@@ -918,6 +921,7 @@ def connected_msg(msg):
def check_csrf():
+ if app.config['DEBUG']: return True
request_token = request.cookies.get('request_token')
if session['request_token'] != request_token: return False
http_token = request.headers.get('x-http-token')
diff --git a/BTPanel/static/css/site.css b/BTPanel/static/css/site.css
index b37ce6ba..7e26395b 100644
--- a/BTPanel/static/css/site.css
+++ b/BTPanel/static/css/site.css
@@ -582,74 +582,6 @@ html {
overflow: hidden
}
-.sidebar-auto {
- overflow: auto;
- height: 100%;
- margin-right: -18px
-}
-
-.mypcip {
- display: block;
- padding: 0 10px;
- position: relative;
- transition-duration: 500ms;
- transition-property: background;
- transition-timing-function: ease;
- width: 100%;
- cursor: pointer;
- margin: 1px 0
-}
-
-.mypcip:hover {
- background: #20a53a;
- opacity: 1
-}
-
-.mypcip span {
- background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAQCAYAAAAS7Y8mAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAdgAAAHYBTnsmCAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAGPSURBVDiNldQ9ixRBEAbgZ3Zn1fVOuQU/wK9AMDDS1MvuRxj5CwTBP2CiYmYmGBsYGRsaa2qkkSiCgRd4y3ri3XqzbdDV7Lgs7uwLRc90V1dXv29VVymluxiiRoVkNaoYG7wN+9chpTTBBn7jKA5YhYR+JPQEDxYd6rAPeIwDnOgQuMEIz3F8mUMdC9/wqkPAxb1P0Yv/6ziLX/hTy9c6jXPYXSPwBQywF+Mz7GCCSRGMbqK1Ufwbmb4beI9TuNZFqFWoZCH7Mp0XcaX33y3dUDKfmRdD1bM+BYuoWtaEKeIdyqSvg5+RZSWX6Ri3ZUqmRbxjcqnsx3cyF7Utbpmf4YxcapXcWFNcjiSbOk7Yxhu5BocRaGBeoyXYNII32MTJsJ7cvR/D92aN1xFsFA6HYZ/iiiWjTVyVGyrhBz7jXSQxxq3wPahxJ7JuX30sd9IoshviC77KzdSmag+XYm4QNq0tF+0e7sc1SwPs4xFeLPHvt2ibsfwl24rFl/KLV/jdCho2ZC3a+I6HOB9rR38B10ZjDE49T6kAAAAASUVORK5CYII=") no-repeat 0 center;
- display: inline-block;
- line-height: 46px;
- padding-left: 30px;
- white-space: nowrap;
- max-width: 146px;
- overflow: hidden;
-}
-
-.btpc-plus {
- line-height: 40px;
- color: #aaa;
- font-family: arial;
- font-size: 26px;
- cursor: pointer;
- padding-left: 80px;
- transition-duration: 500ms;
- transition-property: background;
- transition-timing-function: ease
-}
-
-.btpc-plus:hover {
- background-color: #20a53a;
- color: #fff
-}
-
-.mypcip .btedit {
- background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAFVSURBVDiNndO/ahRRFMfxz+zOav6goKC1S54gBBUECy0lIKTeyrXwFcROyBuENCHdNhaCoCgiWoggGPAJxFgIsbEJJBmTrCfFnBFZNjHrDy4z5849935/Z84tIsJ/6gneFhFR4AHuYHjM4jN4iZWM13ALSyWWcR+rOERrzAYFNvP9Ka7jKrZExKeIWI8IpxivIuJrRFxo5lqJXfzDbwfvcQU3cAnTUOIsfif6zeYDfuEDzuM5LuIatrGBu/hcInCAy1mH2STawyLmknI+56bykFZDsJsUP7CAdhIMUeELXo9YGmbOn4o3Nah6vd5Ot9vd6ff7lfr3dXKMVZnIVVp4MRgMZtLW6LpneJhxpB1lJnfwE49yblRtfPsrLhoLpbqA7fT15jjUERXNQeO6biK11DXYnyCnymdIjI+4jXuJdlJXHqq7cArf620izkXEu5hMj5u7cAQCwbENi6a1WQAAAABJRU5ErkJggg==) no-repeat center center;
- width: 16px;
- height: 16px;
- display: none;
- position: absolute;
- left: 156px;
- top: 14px
-}
-
-.mypcip:hover .btedit {
- display: block
-}
-
-
-
-
-
.task {
position: absolute;
right: 6px;
@@ -5209,4 +5141,85 @@ select[disabled]{
border-bottom: 2px solid #20a53a;
color: #20a53a;
font-weight: bold;
-}
\ No newline at end of file
+}
+
+.ssl_cert_from .layui-layer-ico{
+ width: 30px;
+ height: 30px;
+ display: inline-block;
+ position: absolute;
+ left: 50px;
+}
+.ssl_cert_from h3{
+ font-weight: bolder;
+ font-size: 18px;
+ margin-left: 75px;
+ display: inline-block;
+ height: 30px;
+ line-height: 30px;
+}
+
+.ssl_cert_from ul{
+ border: 1px solid #ececec;
+ border-radius: 10px;
+ margin: 0 auto;
+ margin-top: 20px;
+ margin-bottom: 20px;
+ background: #f7f7f7;
+ width: 80%;
+ padding: 15px;
+ list-style-type: inherit;
+}
+
+.ssl_cert_from ul li:nth-child(0){
+ margin-top: 12px;
+ color:red;
+}
+.ssl_cert_from ul li{
+ margin-left: 20px;
+ height: 25px;
+ line-height: 25px;
+}
+.ssl_cert_from>.line{
+ padding-top: 15px;
+ border-top: 1px solid #ececec;
+ width: 81%;
+ margin: 0 auto;
+ margin-top: 15px;
+ padding-bottom: 15px;
+ border-bottom: 1px solid #ececec;
+}
+.ssl_cert_from>.line .tname{
+ width:105px;
+}
+
+.ssl_cert_from>.line .info-r{
+ margin-left:70px;
+ height:30px;
+ line-height:30px;
+}
+
+
+
+.ssl_cert_from label{
+ font-weight: 400;
+ margin: 3px 5px 0px;
+ vertical-align: top;
+}
+.ssl_cert_from .details{
+ padding-top:10px;
+ width:80%;
+ margin:0 auto;
+}
+.ssl_cert_from .details a{
+ float: right;
+ position: relative;
+ top: 3px;
+}
+
+.ssl_cert_from>.line .line {
+ padding-bottom:0;
+}
+.ssl_cert_from>.line .line .info-r{
+ margin-bottom:0;
+}
diff --git a/BTPanel/static/js/config.js b/BTPanel/static/js/config.js
index 2580eb15..740c2747 100644
--- a/BTPanel/static/js/config.js
+++ b/BTPanel/static/js/config.js
@@ -176,41 +176,111 @@ function setTemplate(){
//设置面板SSL
function setPanelSSL(){
- var status = $("#sshswitch").prop("checked")==true?1:0;
- var msg = $("#panelSSL").attr('checked')?lan.config.ssl_close_msg:''+lan.config.ssl_open_ps+'
+
+
Developer mode
+
+
+
+
+
diff --git a/class/common.py b/class/common.py
index ae50a4fd..abb7ef80 100644
--- a/class/common.py
+++ b/class/common.py
@@ -27,7 +27,7 @@ def init(self):
if ua:
ua = ua.lower();
if ua.find('spider') != -1 or ua.find('bot') != -1: return redirect('https://www.baidu.com');
- g.version = '6.1.4'
+ g.version = '6.1.5'
g.title = public.GetConfigValue('title')
g.uri = request.path
session['version'] = g.version;
diff --git a/class/config.py b/class/config.py
index 57307fb8..b3813924 100644
--- a/class/config.py
+++ b/class/config.py
@@ -416,20 +416,29 @@ def SetTemplates(self,get):
#设置面板SSL
def SetPanelSSL(self,get):
- sslConf = '/www/server/panel/data/ssl.pl';
- if os.path.exists(sslConf):
- os.system('rm -f ' + sslConf);
- return public.returnMsg(True,'PANEL_SSL_CLOSE');
+ if hasattr(get,"email"):
+ rep_mail = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$"
+ if not re.search(rep_mail,get.email):
+ return public.returnMsg(False,'The E-Mail format is illegal')
+ import setPanelLets
+ sp = setPanelLets.setPanelLets()
+ sps = sp.set_lets(get)
+ return sps
else:
- os.system('pip install cffi');
- os.system('pip install cryptography');
- os.system('pip install pyOpenSSL');
- try:
- if not self.CreateSSL(): return public.returnMsg(False,'PANEL_SSL_ERR');
- public.writeFile(sslConf,'True')
- except Exception as ex:
- return public.returnMsg(False,'PANEL_SSL_ERR');
- return public.returnMsg(True,'PANEL_SSL_OPEN');
+ sslConf = '/www/server/panel/data/ssl.pl';
+ if os.path.exists(sslConf):
+ os.system('rm -f ' + sslConf);
+ return public.returnMsg(True,'PANEL_SSL_CLOSE');
+ else:
+ os.system('pip install cffi');
+ os.system('pip install cryptography');
+ os.system('pip install pyOpenSSL');
+ try:
+ if not self.CreateSSL(): return public.returnMsg(False,'PANEL_SSL_ERR');
+ public.writeFile(sslConf,'True')
+ except Exception as ex:
+ return public.returnMsg(False,'PANEL_SSL_ERR');
+ return public.returnMsg(True,'PANEL_SSL_OPEN');
#自签证书
def CreateSSL(self):
if os.path.exists('ssl/input.pl'): return True;
@@ -447,8 +456,8 @@ def CreateSSL(self):
cert_ca = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
private_key = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key)
if len(cert_ca) > 100 and len(private_key) > 100:
- public.writeFile('ssl/certificate.pem',cert_ca)
- public.writeFile('ssl/privateKey.pem',private_key)
+ public.writeFile('ssl/certificate.pem',cert_ca,'wb+')
+ public.writeFile('ssl/privateKey.pem',private_key,'wb+')
return True
return False
@@ -912,4 +921,24 @@ def clean_panel_error_logs(self,get):
filename = 'logs/error.log'
public.writeFile(filename,'')
public.WriteLog('P_CONF','CLEARING_LOG')
- return public.returnMsg(True,'CLEARED')
\ No newline at end of file
+ return public.returnMsg(True,'CLEARED')
+
+ # 获取lets证书
+ def get_cert_source(self,get):
+ import setPanelLets
+ sp = setPanelLets.setPanelLets()
+ spg = sp.get_cert_source()
+ return spg
+
+ #设置debug模式
+ def set_debug(self,get):
+ debug_path = 'data/debug.pl'
+ if os.path.exists(debug_path):
+ t_str = 'Close'
+ os.remove(debug_path)
+ else:
+ t_str = 'Open'
+ public.writeFile(debug_path,'True')
+ public.WriteLog('TYPE_PANEL','%sDeveloper mode(debug)' % t_str)
+ public.restart_panel()
+ return public.returnMsg(True,'Successful setup!')
\ No newline at end of file
diff --git a/class/files.py b/class/files.py
index 0f7698e6..118f06f9 100644
--- a/class/files.py
+++ b/class/files.py
@@ -135,9 +135,11 @@ def set_mode(self,path):
s_path = os.path.dirname(path)
p_stat = os.stat(s_path)
os.chown(path,p_stat.st_uid,p_stat.st_gid)
- os.chmod(path,p_stat.st_mode)
+ if os.path.isfile(path):
+ os.chmod(path,0644)
+ else:
+ os.chmod(path,p_stat.st_mode)
-
#取文件/目录列表
def GetDir(self,get):
if not hasattr(get,'path'):
@@ -796,7 +798,7 @@ def GetFileAccess(self,get):
data['chmod'] = str(oct(stat.st_mode)[-3:])
data['chown'] = pwd.getpwuid(stat.st_uid).pw_name
except:
- data['chmod'] = 755
+ data['chmod'] = 644
data['chown'] = 'www'
return data
@@ -819,7 +821,7 @@ def SetFileAccess(self,get,all = '-R'):
def SetFileAccept(self,filename):
os.system('chown -R www:www ' + filename)
- os.system('chmod -R 755 ' + filename)
+ os.system('chmod -R 644 ' + filename)
diff --git a/class/panelSite.py b/class/panelSite.py
index a4884f2a..4b9c023e 100644
--- a/class/panelSite.py
+++ b/class/panelSite.py
@@ -151,7 +151,7 @@ def apacheAdd(self):
htaccess = self.sitePath+'/.htaccess'
if not os.path.exists(htaccess): public.writeFile(htaccess, ' ');
- public.ExecShell('chmod -R 755 ' + htaccess);
+ public.ExecShell('chmod -R 644 ' + htaccess);
public.ExecShell('chown -R www:www ' + htaccess);
filename = self.setupPath+'/panel/vhost/apache/'+self.siteName+'.conf'
@@ -298,21 +298,21 @@ def AddSite(self,get):
if not os.path.exists(userIni):
public.writeFile(userIni, 'open_basedir='+self.sitePath+'/:/tmp/:/proc/');
public.ExecShell('chmod 644 ' + userIni);
- public.ExecShell('chown root:root ' + userIni);
+ public.ExecShell('chown www:www ' + userIni);
public.ExecShell('chattr +i '+userIni);
#创建默认文档
index = self.sitePath+'/index.html'
if not os.path.exists(index):
public.writeFile(index, public.readFile('data/defaultDoc.html'))
- public.ExecShell('chmod -R 755 ' + index);
+ public.ExecShell('chmod -R 644 ' + index);
public.ExecShell('chown -R www:www ' + index);
#创建自定义404页
doc404 = self.sitePath+'/404.html'
if not os.path.exists(doc404):
public.writeFile(doc404, public.readFile('data/404.html'));
- public.ExecShell('chmod -R 755 ' + doc404);
+ public.ExecShell('chmod -R 644 ' + doc404);
public.ExecShell('chown -R www:www ' + doc404);
#写入配置
@@ -864,7 +864,15 @@ def CreateLet(self,get):
if self.GetRedirectList(get): return public.returnMsg(False, 'SITE_SSL_ERR_301');
if self.GetProxyList(get): return public.returnMsg(False,'Sites that have reverse proxy turned on cannot request SSL!');
data = self.get_site_info(get.siteName)
- get.site_dir = data['path']
+ get.id = data['id']
+ runPath = self.GetRunPath(get)
+ if runPath != '/':
+ if runPath[:1] != '/': runPath = '/' + runPath
+ else:
+ runPath = ''
+ get.site_dir = data['path'] + runPath
+ print(get.site_dir)
+
else:
dns_api_list = self.GetDnsApi(get)
get.dns_param = None
@@ -2084,7 +2092,9 @@ def GetProxyList(self, get):
n = 0
for w in ["nginx", "apache"]:
conf_path = "%s/panel/vhost/%s/%s.conf" % (self.setupPath, w, get.sitename)
- old_conf = public.readFile(conf_path)
+ old_conf = ""
+ if os.path.exists(conf_path):
+ old_conf = public.readFile(conf_path)
rep = "(#PROXY-START(\n|.)+#PROXY-END)"
url_rep = "proxy_pass (.*);|ProxyPass\s/\s(.*)|Host\s(.*);"
host_rep = "Host\s(.*);"
diff --git a/class/public.py b/class/public.py
index 4523ffb1..800d37b7 100644
--- a/class/public.py
+++ b/class/public.py
@@ -1,4 +1,4 @@
-#coding: utf-8
+# coding: utf-8
# +-------------------------------------------------------------------
# | 宝塔Linux面板
# +-------------------------------------------------------------------
@@ -7,11 +7,11 @@
# | Author: 黄文良 <287962566@qq.com>
# +-------------------------------------------------------------------
-#--------------------------------
+# --------------------------------
# 宝塔公共库
-#--------------------------------
+# --------------------------------
-import json,os,sys,time,re,socket
+import json, os, sys, time, re, socket
if sys.version_info[0] == 2:
reload(sys)
@@ -110,7 +110,7 @@ def HttpPost(url,data,timeout = 6,headers = {}):
if url.find(home) != -1:
if os.path.exists(host_home):
headers['host'] = home
- url = url.replace(home,readFile(host_home))
+ url = url.replace(home, readFile(host_home))
if sys.version_info[0] == 2:
try:
@@ -123,50 +123,56 @@ def HttpPost(url,data,timeout = 6,headers = {}):
response = urllib2.urlopen(req,timeout=timeout)
return response.read()
except Exception as ex:
- if old_url.find(home) != -1: return http_post_home(old_url,data,timeout,str(ex))
+ if old_url.find(home) != -1: return http_post_home(old_url, data, timeout, str(ex))
if headers: return False
return str(ex);
else:
try:
- import urllib.request,ssl
+ import urllib.request, ssl
try:
ssl._create_default_https_context = ssl._create_unverified_context
- except:pass;
+ except:
+ pass;
data2 = urllib.parse.urlencode(data).encode('utf-8')
- req = urllib.request.Request(url, data2,headers = headers)
- response = urllib.request.urlopen(req,timeout = timeout)
+ req = urllib.request.Request(url, data2, headers=headers)
+ response = urllib.request.urlopen(req, timeout=timeout)
result = response.read()
if type(result) == bytes: result = result.decode('utf-8')
return result
except Exception as ex:
- if old_url.find(home) != -1: return http_post_home(old_url,data,timeout,str(ex))
+ if old_url.find(home) != -1: return http_post_home(old_url, data, timeout, str(ex))
if headers: return False
return str(ex);
-def http_post_home(url,data,timeout,ex):
+
+def http_post_home(url, data, timeout, ex):
try:
home = 'www.bt.cn'
if url.find(home) == -1: return ex
hosts_file = "config/hosts.json"
if not os.path.exists(hosts_file): return ex
hosts = json.loads(readFile(hosts_file))
- headers = {"host":home}
+ headers = {"host": home}
for host in hosts:
- new_url = url.replace(home,host)
- res = HttpPost(new_url,data,timeout,headers)
+ new_url = url.replace(home, host)
+ res = HttpPost(new_url, data, timeout, headers)
if res:
- writeFile("data/home_host.pl",host)
+ writeFile("data/home_host.pl", host)
set_home_host(host)
return res
return ex
- except: return ex
+ except:
+ return ex
+
+
+def httpPost(url, data, timeout=6):
+ return HttpPost(url, data, timeout)
-def httpPost(url,data,timeout=6):
- return HttpPost(url,data,timeout)
def check_home():
return True
+
def Md5(strings):
"""
生成MD5
@@ -178,9 +184,11 @@ def Md5(strings):
m.update(strings.encode('utf-8'))
return m.hexdigest()
+
def md5(strings):
return Md5(strings)
+
def FileMd5(filename):
"""
生成文件的MD5
@@ -190,10 +198,10 @@ def FileMd5(filename):
if not os.path.isfile(filename): return False;
import hashlib;
my_hash = hashlib.md5()
- f = open(filename,'rb')
+ f = open(filename, 'rb')
while True:
b = f.read(8096)
- if not b :
+ if not b:
break
my_hash.update(b)
f.close()
@@ -215,31 +223,35 @@ def GetRandomString(length):
strings += chars[random.randint(0, chrlen)]
return strings
-def ReturnJson(status,msg,args=()):
+
+def ReturnJson(status, msg, args=()):
"""
取通用Json返回
@status 返回状态
@msg 返回消息
return string(json)
"""
- return GetJson(ReturnMsg(status,msg,args));
+ return GetJson(ReturnMsg(status, msg, args));
+
-def returnJson(status,msg,args=()):
- return ReturnJson(status,msg,args)
+def returnJson(status, msg, args=()):
+ return ReturnJson(status, msg, args)
-def ReturnMsg(status,msg,args = ()):
+
+def ReturnMsg(status, msg, args=()):
log_message = json.loads(ReadFile('BTPanel/static/language/' + GetLanguage() + '/public.json'));
keys = log_message.keys();
if type(msg) == str:
if msg in keys:
msg = log_message[msg];
for i in range(len(args)):
- rep = '{'+str(i+1)+'}'
- msg = msg.replace(rep,args[i]);
- return {'status':status,'msg':msg}
+ rep = '{' + str(i + 1) + '}'
+ msg = msg.replace(rep, args[i]);
+ return {'status': status, 'msg': msg}
+
-def returnMsg(status,msg,args = ()):
- return ReturnMsg(status,msg,args)
+def returnMsg(status, msg, args=()):
+ return ReturnMsg(status, msg, args)
def GetFileMode(filename):
@@ -248,6 +260,7 @@ def GetFileMode(filename):
accept = str(oct(stat.st_mode)[-3:]);
return accept
+
def get_mode_and_user(path):
'''取文件或目录权限信息'''
import pwd
@@ -271,10 +284,12 @@ def GetJson(data):
if data == bytes: data = data.decode('utf-8')
return dumps(data)
+
def getJson(data):
return GetJson(data)
-def ReadFile(filename,mode = 'r'):
+
+def ReadFile(filename, mode='r'):
"""
读取文件内容
@filename 文件名
@@ -287,16 +302,18 @@ def ReadFile(filename,mode = 'r'):
f_body = fp.read()
fp.close()
except:
- fp = open(filename, mode,encoding="utf-8")
+ fp = open(filename, mode, encoding="utf-8")
f_body = fp.read()
fp.close()
return f_body
-def readFile(filename,mode='r'):
- return ReadFile(filename,mode)
-def WriteFile(filename,s_body,mode='w+'):
+def readFile(filename, mode='r'):
+ return ReadFile(filename, mode)
+
+
+def WriteFile(filename, s_body, mode='w+'):
"""
写入文件内容
@filename 文件名
@@ -310,34 +327,37 @@ def WriteFile(filename,s_body,mode='w+'):
return True
except:
try:
- fp = open(filename, mode,encoding="utf-8");
+ fp = open(filename, mode, encoding="utf-8");
fp.write(s_body)
fp.close()
return True
except:
return False
-def writeFile(filename,s_body,mode='w+'):
- return WriteFile(filename,s_body,mode)
-def WriteLog(type,logMsg,args=()):
- #写日志
- #try:
- import time,db,json
+def writeFile(filename, s_body, mode='w+'):
+ return WriteFile(filename, s_body, mode)
+
+
+def WriteLog(type, logMsg, args=()):
+ # 写日志
+ # try:
+ import time, db, json
logMessage = json.loads(readFile('BTPanel/static/language/' + get_language() + '/log.json'));
keys = logMessage.keys();
if logMsg in keys:
logMsg = logMessage[logMsg];
for i in range(len(args)):
- rep = '{'+str(i+1)+'}'
- logMsg = logMsg.replace(rep,args[i]);
+ rep = '{' + str(i + 1) + '}'
+ logMsg = logMsg.replace(rep, args[i]);
if type in keys: type = logMessage[type];
sql = db.Sql()
- mDate = time.strftime('%Y-%m-%d %X',time.localtime());
- data = (type,logMsg,mDate);
- result = sql.table('logs').add('type,log,addtime',data);
- #except:
- #pass
+ mDate = time.strftime('%Y-%m-%d %X', time.localtime());
+ data = (type, logMsg, mDate);
+ result = sql.table('logs').add('type,log,addtime', data);
+ # except:
+ # pass
+
def GetLanguage():
'''
@@ -345,9 +365,11 @@ def GetLanguage():
'''
return GetConfigValue("language")
+
def get_language():
return GetLanguage()
+
def GetConfigValue(key):
'''
取配置值
@@ -356,11 +378,13 @@ def GetConfigValue(key):
if not key in config.keys(): return None
return config[key]
-def SetConfigValue(key,value):
+
+def SetConfigValue(key, value):
config = GetConfig()
config[key] = value
WriteConfig(config)
+
def GetConfig():
'''
取所有配置项
@@ -371,9 +395,10 @@ def GetConfig():
if not f_body: return {}
return json.loads(f_body)
+
def WriteConfig(config):
path = "config/config.json"
- WriteFile(path,json.dumps(config))
+ WriteFile(path, json.dumps(config))
def GetLan(key):
@@ -386,10 +411,13 @@ def GetLan(key):
if key in keys:
msg = log_message[key];
return msg;
+
+
def getLan(key):
return GetLan(key)
-def GetMsg(key,args = ()):
+
+def GetMsg(key, args=()):
try:
log_message = json.loads(ReadFile('BTPanel/static/language/' + GetLanguage() + '/public.json'));
keys = log_message.keys();
@@ -397,27 +425,30 @@ def GetMsg(key,args = ()):
if key in keys:
msg = log_message[key];
for i in range(len(args)):
- rep = '{'+str(i+1)+'}'
- msg = msg.replace(rep,args[i]);
+ rep = '{' + str(i + 1) + '}'
+ msg = msg.replace(rep, args[i]);
return msg;
except:
return key
-def getMsg(key,args = ()):
- return GetMsg(key,args)
-#获取Web服务器
+def getMsg(key, args=()):
+ return GetMsg(key, args)
+
+
+# 获取Web服务器
def GetWebServer():
webserver = 'nginx';
if not os.path.exists('/www/server/nginx/sbin/nginx'): webserver = 'apache';
return webserver;
+
def get_webserver():
return GetWebServer()
def ServiceReload():
- #重载Web服务配置
+ # 重载Web服务配置
if os.path.exists('/www/server/nginx/sbin/nginx'):
result = ExecShell('/etc/init.d/nginx reload')
if result[1].find('nginx.pid') != -1:
@@ -426,12 +457,14 @@ def ServiceReload():
else:
result = ExecShell('/etc/init.d/httpd reload')
return result;
+
+
def serviceReload():
return ServiceReload()
def ExecShell(cmdstring, cwd=None, timeout=None, shell=True):
- #通过管道执行SHELL
+ # 通过管道执行SHELL
import shlex
import datetime
import subprocess
@@ -443,23 +476,26 @@ def ExecShell(cmdstring, cwd=None, timeout=None, shell=True):
cmdstring_list = shlex.split(cmdstring)
if timeout:
end_time = datetime.datetime.now() + datetime.timedelta(seconds=timeout)
-
- sub = subprocess.Popen(cmdstring_list, cwd=cwd, stdin=subprocess.PIPE,shell=shell,bufsize=4096,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
-
+
+ sub = subprocess.Popen(cmdstring_list, cwd=cwd, stdin=subprocess.PIPE, shell=shell, bufsize=4096,
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
while sub.poll() is None:
time.sleep(0.1)
if timeout:
if end_time <= datetime.datetime.now():
- raise Exception("Timeout:%s"%cmdstring)
- a,e = sub.communicate()
+ raise Exception("Timeout:%s" % cmdstring)
+ a, e = sub.communicate()
try:
if type(a) == bytes: a = a.decode('utf-8')
if type(e) == bytes: e = e.decode('utf-8')
- except:pass
- return a,e
+ except:
+ pass
+ return a, e
+
def GetLocalIp():
- #取本地外网IP
+ # 取本地外网IP
try:
filename = 'data/iplist.txt'
ipaddress = readFile(filename)
@@ -468,8 +504,8 @@ def GetLocalIp():
url = 'http://pv.sohu.com/cityjson?ie=utf-8'
opener = urllib2.urlopen(url)
m_str = opener.read()
- ipaddress = re.search('\d+.\d+.\d+.\d+',m_str).group(0)
- WriteFile(filename,ipaddress)
+ ipaddress = re.search('\d+.\d+.\d+.\d+', m_str).group(0)
+ WriteFile(filename, ipaddress)
c_ip = check_ip(ipaddress)
if not c_ip: return GetHost()
return ipaddress
@@ -481,6 +517,7 @@ def GetLocalIp():
except:
return GetHost();
+
def is_ipv4(ip):
try:
socket.inet_pton(socket.AF_INET, ip)
@@ -493,20 +530,21 @@ def is_ipv4(ip):
except socket.error:
return False
return True
-
-
+
+
def is_ipv6(ip):
try:
socket.inet_pton(socket.AF_INET6, ip)
except socket.error:
return False
return True
-
-
+
+
def check_ip(ip):
return is_ipv4(ip) or is_ipv6(ip)
-def GetHost(port = False):
+
+def GetHost(port=False):
from flask import request
host_tmp = request.headers.get('host')
if host_tmp.find(':') == -1: host_tmp += ':80';
@@ -514,19 +552,22 @@ def GetHost(port = False):
if port: return h[1]
return h[0]
+
def GetClientIp():
from flask import request
- return request.remote_addr.replace('::ffff:','')
+ return request.remote_addr.replace('::ffff:', '')
+
def phpReload(version):
- #重载PHP配置
+ # 重载PHP配置
import os
if os.path.exists('/www/server/php/' + version + '/libphp5.so'):
ExecShell('/etc/init.d/httpd reload');
else:
- ExecShell('/etc/init.d/php-fpm-'+version+' reload');
+ ExecShell('/etc/init.d/php-fpm-' + version + ' reload');
+
-def get_url(timeout = 0.5):
+def get_url(timeout=0.5):
import json
try:
nodeFile = 'data/node.json';
@@ -543,32 +584,33 @@ def get_url(timeout = 0.5):
return 'http://download.bt.cn';
-#过滤输入
+# 过滤输入
def checkInput(data):
- if not data: return data;
- if type(data) != str: return data;
- checkList = [
- {'d':'<','r':'<'},
- {'d':'>','r':'>'},
- {'d':'\'','r':'‘'},
- {'d':'"','r':'“'},
- {'d':'&','r':'&'},
- {'d':'#','r':'#'},
- {'d':'<','r':'<'}
- ]
- for v in checkList:
- data = data.replace(v['d'],v['r']);
- return data;
-
-#取文件指定尾行数
-def GetNumLines(path,num,p=1):
+ if not data: return data;
+ if type(data) != str: return data;
+ checkList = [
+ {'d': '<', 'r': '<'},
+ {'d': '>', 'r': '>'},
+ {'d': '\'', 'r': '‘'},
+ {'d': '"', 'r': '“'},
+ {'d': '&', 'r': '&'},
+ {'d': '#', 'r': '#'},
+ {'d': '<', 'r': '<'}
+ ]
+ for v in checkList:
+ data = data.replace(v['d'], v['r']);
+ return data;
+
+
+# 取文件指定尾行数
+def GetNumLines(path, num, p=1):
pyVersion = sys.version_info[0]
try:
import cgi
if not os.path.exists(path): return "";
start_line = (p - 1) * num;
count = start_line + num;
- fp = open(path,'rb')
+ fp = open(path, 'rb')
buf = ""
fp.seek(-1, 2)
if fp.read(1) == "\n": fp.seek(-1, 2)
@@ -583,8 +625,9 @@ def GetNumLines(path,num,p=1):
if n >= start_line:
line = buf[newline_pos + 1:]
try:
- data.insert(0,cgi.escape(line))
- except: pass
+ data.insert(0, cgi.escape(line))
+ except:
+ pass
buf = buf[:newline_pos]
n += 1;
break;
@@ -598,18 +641,20 @@ def GetNumLines(path,num,p=1):
if pyVersion == 3:
try:
if type(t_buf) == bytes: t_buf = t_buf.decode('utf-8')
- except:t_buf = str(t_buf)
+ except:
+ t_buf = str(t_buf)
buf = t_buf + buf
fp.seek(-to_read, 1)
if pos - to_read == 0:
buf = "\n" + buf
if not b: break;
fp.close()
- except: return []
+ except: return ""
return "\n".join(data)
-#验证证书
-def CheckCert(certPath = 'ssl/certificate.pem'):
+
+# 验证证书
+def CheckCert(certPath='ssl/certificate.pem'):
openssl = '/usr/local/openssl/bin/openssl';
if not os.path.exists(openssl): openssl = 'openssl';
certPem = readFile(certPath);
@@ -617,8 +662,8 @@ def CheckCert(certPath = 'ssl/certificate.pem'):
tmp = certPem.strip().split(s)
for tmp1 in tmp:
if tmp1.find('-----BEGIN CERTIFICATE-----') == -1: tmp1 = s + tmp1;
- writeFile(certPath,tmp1);
- result = ExecShell(openssl + " x509 -in "+certPath+" -noout -subject")
+ writeFile(certPath, tmp1);
+ result = ExecShell(openssl + " x509 -in " + certPath + " -noout -subject")
if result[1].find('-bash:') != -1: return True
if len(result[1]) > 2: return False
if result[0].find('error:') != -1: return False;
@@ -632,9 +677,9 @@ def getPanelAddr():
return protocol + request.headers.get('host')
-#字节单位转换
+# 字节单位转换
def to_size(size):
- d = ('b','KB','MB','GB','TB');
+ d = ('b', 'KB', 'MB', 'GB', 'TB');
s = d[0];
for b in d:
if size < 1024: return str(size) + ' ' + b;
@@ -643,9 +688,9 @@ def to_size(size):
return str(size) + ' ' + b;
-def checkCode(code,outime = 120):
- #校验验证码
- from BTPanel import session,cache
+def checkCode(code, outime=120):
+ # 校验验证码
+ from BTPanel import session, cache
try:
codeStr = cache.get('codeStr')
cache.delete('codeStr')
@@ -661,61 +706,68 @@ def checkCode(code,outime = 120):
session['login_error'] = GetMsg('CODE_NOT_EXISTS')
return False
-#写进度
-def writeSpeed(title,used,total,speed = 0):
+
+# 写进度
+def writeSpeed(title, used, total, speed=0):
import json
if not title:
- data = {'title':None,'progress':0,'total':0,'used':0,'speed':0}
+ data = {'title': None, 'progress': 0, 'total': 0, 'used': 0, 'speed': 0}
else:
progress = int((100.0 * used / total));
- data = {'title':title,'progress':progress,'total':total,'used':used,'speed':speed}
- writeFile('/tmp/panelSpeed.pl',json.dumps(data));
+ data = {'title': title, 'progress': progress, 'total': total, 'used': used, 'speed': speed}
+ writeFile('/tmp/panelSpeed.pl', json.dumps(data));
return True;
-#取进度
+
+# 取进度
def getSpeed():
import json;
data = readFile('/tmp/panelSpeed.pl');
- if not data:
- data = json.dumps({'title':None,'progress':0,'total':0,'used':0,'speed':0})
- writeFile('/tmp/panelSpeed.pl',data);
+ if not data:
+ data = json.dumps({'title': None, 'progress': 0, 'total': 0, 'used': 0, 'speed': 0})
+ writeFile('/tmp/panelSpeed.pl', data);
return json.loads(data);
-def downloadFile(url,filename):
+
+def downloadFile(url, filename):
try:
if sys.version_info[0] == 2:
import urllib
- urllib.urlretrieve(url,filename=filename ,reporthook= downloadHook)
+ urllib.urlretrieve(url, filename=filename, reporthook=downloadHook)
else:
import urllib.request
- urllib.request.urlretrieve(url,filename=filename ,reporthook= downloadHook)
+ urllib.request.urlretrieve(url, filename=filename, reporthook=downloadHook)
except:
return False
-
+
+
def downloadHook(count, blockSize, totalSize):
- speed = {'total':totalSize,'block':blockSize,'count':count}
- #print('%02d%%'%(100.0 * count * blockSize / totalSize))
+ speed = {'total': totalSize, 'block': blockSize, 'count': count}
+ # print('%02d%%'%(100.0 * count * blockSize / totalSize))
+
def get_error_info():
import traceback
errorMsg = traceback.format_exc();
return errorMsg
-#搜索数据中是否存在
-def inArray(arrays,searchStr):
+
+# 搜索数据中是否存在
+def inArray(arrays, searchStr):
for key in arrays:
if key == searchStr: return True
-
+
return False
-#格式化指定时间戳
-def format_date(format="%Y-%m-%d %H:%M:%S",times = None):
+
+# 格式化指定时间戳
+def format_date(format="%Y-%m-%d %H:%M:%S", times=None):
if not times: times = int(time.time())
time_local = time.localtime(times)
return time.strftime(format, time_local)
-#检查Web服务器配置文件是否有错误
+# 检查Web服务器配置文件是否有错误
def checkWebConfig():
f1 = '/www/server/panel/vhost/'
f2 = '/www/server/panel/plugin/'
@@ -732,9 +784,9 @@ def checkWebConfig():
f3 = f1 + 'nginx/total.conf'
if os.path.exists(f3): os.remove(f3)
else:
- if os.path.exists('/www/server/apache/modules/mod_lua.so'):
- writeFile(f1 + 'apache/btwaf.conf','LoadModule lua_module modules/mod_lua.so')
- writeFile(f1 + 'apache/total.conf','LuaHookLog /www/server/total/httpd_log.lua run_logs')
+ if os.path.exists('/www/server/apache/modules/mod_lua.so'):
+ writeFile(f1 + 'apache/btwaf.conf', 'LoadModule lua_module modules/mod_lua.so')
+ writeFile(f1 + 'apache/total.conf', 'LuaHookLog /www/server/total/httpd_log.lua run_logs')
else:
f3 = f1 + 'apache/total.conf'
if os.path.exists(f3): os.remove(f3)
@@ -745,94 +797,101 @@ def checkWebConfig():
else:
result = ExecShell("ulimit -n 8192 ; /www/server/apache/bin/apachectl -t");
searchStr = 'Syntax OK'
-
+
if result[1].find(searchStr) == -1:
- WriteLog("TYPE_SOFT", 'CONF_CHECK_ERR',(result[1],));
+ WriteLog("TYPE_SOFT", 'CONF_CHECK_ERR', (result[1],));
return result[1];
return True;
-#检查是否为IPv4地址
+# 检查是否为IPv4地址
def checkIp(ip):
- p = re.compile('^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$')
- if p.match(ip):
- return True
- else:
+ p = re.compile('^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$')
+ if p.match(ip):
+ return True
+ else:
return False
-
-#检查端口是否合法
+
+
+# 检查端口是否合法
def checkPort(port):
- ports = ['21','25','443','8080','888','8888','8443'];
+ ports = ['21', '25', '443', '8080', '888', '8888', '8443'];
if port in ports: return False;
intport = int(port);
if intport < 1 or intport > 65535: return False;
return True;
-#字符串取中间
-def getStrBetween(startStr,endStr,srcStr):
+
+# 字符串取中间
+def getStrBetween(startStr, endStr, srcStr):
start = srcStr.find(startStr)
if start == -1: return None
end = srcStr.find(endStr)
if end == -1: return None
- return srcStr[start+1:end]
+ return srcStr[start + 1:end]
+
-#取CPU类型
+# 取CPU类型
def getCpuType():
- cpuinfo = open('/proc/cpuinfo','r').read()
+ cpuinfo = open('/proc/cpuinfo', 'r').read()
rep = "model\s+name\s+:\s+(.+)"
- tmp = re.search(rep,cpuinfo,re.I);
+ tmp = re.search(rep, cpuinfo, re.I);
cpuType = ''
if tmp:
cpuType = tmp.groups()[0]
else:
cpuinfo = ExecShell('LANG="en_US.UTF-8" && lscpu')[0]
rep = "Model\s+name:\s+(.+)"
- tmp = re.search(rep,cpuinfo,re.I)
+ tmp = re.search(rep, cpuinfo, re.I)
if tmp: cpuType = tmp.groups()[0]
return cpuType;
-#检查是否允许重启
+# 检查是否允许重启
def IsRestart():
- num = M('tasks').where('status!=?',('1',)).count();
+ num = M('tasks').where('status!=?', ('1',)).count();
if num > 0: return False;
return True;
-#加密密码字符
+
+# 加密密码字符
def hasPwd(password):
import crypt;
- return crypt.crypt(password,password);
+ return crypt.crypt(password, password);
-def get_timeout(url,timeout=3):
+
+def get_timeout(url, timeout=3):
try:
start = time.time();
- result = httpGet(url,timeout);
+ result = httpGet(url, timeout);
if result != 'True': return False;
return int((time.time() - start) * 1000);
- except: return False
+ except:
+ return False
+
def getDate(format='%Y-%m-%d %X'):
- #取格式时间
- return time.strftime(format,time.localtime())
+ # 取格式时间
+ return time.strftime(format, time.localtime())
-#处理MySQL配置文件
+# 处理MySQL配置文件
def CheckMyCnf():
import os;
confFile = '/etc/my.cnf'
- if os.path.exists(confFile):
+ if os.path.exists(confFile):
conf = readFile(confFile)
if len(conf) > 100: return True;
versionFile = '/www/server/mysql/version.pl';
if not os.path.exists(versionFile): return False;
-
- versions = ['5.1','5.5','5.6','5.7','AliSQL']
+
+ versions = ['5.1', '5.5', '5.6', '5.7', 'AliSQL']
version = readFile(versionFile);
for key in versions:
if key in version:
version = key;
break;
-
+
shellStr = '''
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
@@ -935,13 +994,13 @@ def CheckMyCnf():
wget -O /etc/my.cnf $Download_Url/install/conf/mysql-%s.conf -T 5
MySQL_Opt
''' % (version,)
- #判断是否迁移目录
+ # 判断是否迁移目录
if os.path.exists('data/datadir.pl'):
newPath = readFile('data/datadir.pl');
mycnf = readFile('/etc/my.cnf');
- mycnf = mycnf.replace('/www/server/data',newPath);
- writeFile('/etc/my.cnf',mycnf);
-
+ mycnf = mycnf.replace('/www/server/data', newPath);
+ writeFile('/etc/my.cnf', mycnf);
+
os.system(shellStr);
WriteLog('TYPE_SOFE', 'MYSQL_CHECK_ERR');
return True;
@@ -952,14 +1011,15 @@ def GetSSHPort():
file = '/etc/ssh/sshd_config'
conf = ReadFile(file)
rep = "#*Port\s+([0-9]+)\s*\n"
- port = re.search(rep,conf).groups(0)[0]
+ port = re.search(rep, conf).groups(0)[0]
return int(port)
except:
return 22
+
def GetSSHStatus():
if os.path.exists('/usr/bin/apt-get'):
- status = ExecShell("service ssh status | grep -P '(dead|stop)'")
+ status = ExecShell("service ssh status | grep -P '(dead|stop)'")
else:
import system
panelsys = system.system();
@@ -974,16 +1034,18 @@ def GetSSHStatus():
status = True
return status
-#检查端口是否合法
-def CheckPort(port,other=None):
+
+# 检查端口是否合法
+def CheckPort(port, other=None):
if type(port) == str: port = int(port)
if port < 1 or port > 65535: return False
if other:
- checks = [22,20,21,8888,3306,11211,888,25]
+ checks = [22, 20, 21, 8888, 3306, 11211, 888, 25]
if port in checks: return False
return True
-#获取Token
+
+# 获取Token
def GetToken():
try:
from json import loads
@@ -994,134 +1056,142 @@ def GetToken():
except:
return False
+
def to_btint(string):
m_list = []
for s in string:
m_list.append(ord(s))
return m_list;
+
def load_module(pluginCode):
from imp import new_module
from BTPanel import cache
p_tk = 'data/%s' % md5(pluginCode + get_uuid())
pluginInfo = None
- if cache: pluginInfo = cache.get(pluginCode+'code')
+ if cache: pluginInfo = cache.get(pluginCode + 'code')
if not pluginInfo:
import panelAuth
pdata = panelAuth.panelAuth().create_serverid(None)
pdata['pid'] = pluginCode
url = GetConfigValue('home') + '/api/panel/get_py_module'
- pluginTmp = httpPost(url,pdata)
+ pluginTmp = httpPost(url, pdata)
try:
pluginInfo = json.loads(pluginTmp)
except:
if not os.path.exists(p_tk): return False
pluginInfo = json.loads(ReadFile(p_tk))
if pluginInfo['status'] == False: return False
- WriteFile(p_tk,json.dumps(pluginInfo))
- os.chmod(p_tk,384)
- if cache: cache.set(pluginCode+'code',pluginInfo,1800)
+ WriteFile(p_tk, json.dumps(pluginInfo))
+ os.chmod(p_tk, 384)
+ if cache: cache.set(pluginCode + 'code', pluginInfo, 1800)
mod = sys.modules.setdefault(pluginCode, new_module(pluginCode))
- code = compile(pluginInfo['msg'].encode('utf-8'),pluginCode, 'exec')
+ code = compile(pluginInfo['msg'].encode('utf-8'), pluginCode, 'exec')
mod.__file__ = pluginCode
mod.__package__ = ''
- exec(code, mod.__dict__)
+ exec (code, mod.__dict__)
return mod
-#解密数据
+
+# 解密数据
def auth_decode(data):
token = GetToken()
- #是否有生成Token
- if not token: return returnMsg(False,'REQUEST_ERR')
-
- #校验access_key是否正确
- if token['access_key'] != data['btauth_key']: return returnMsg(False,'REQUEST_ERR')
-
- #解码数据
- import binascii,hashlib,urllib,hmac,json
+ # 是否有生成Token
+ if not token: return returnMsg(False, 'REQUEST_ERR')
+
+ # 校验access_key是否正确
+ if token['access_key'] != data['btauth_key']: return returnMsg(False, 'REQUEST_ERR')
+
+ # 解码数据
+ import binascii, hashlib, urllib, hmac, json
tdata = binascii.unhexlify(data['data']);
-
- #校验signature是否正确
+
+ # 校验signature是否正确
signature = binascii.hexlify(hmac.new(token['secret_key'], tdata, digestmod=hashlib.sha256).digest());
- if signature != data['signature']: return returnMsg(False,'REQUEST_ERR');
-
- #返回
+ if signature != data['signature']: return returnMsg(False, 'REQUEST_ERR');
+
+ # 返回
return json.loads(urllib.unquote(tdata));
-
-#数据加密
+
+# 数据加密
def auth_encode(data):
token = GetToken()
pdata = {}
-
- #是否有生成Token
- if not token: return returnMsg(False,'REQUEST_ERR')
-
- #生成signature
- import binascii,hashlib,urllib,hmac,json
+
+ # 是否有生成Token
+ if not token: return returnMsg(False, 'REQUEST_ERR')
+
+ # 生成signature
+ import binascii, hashlib, urllib, hmac, json
tdata = urllib.quote(json.dumps(data));
- #公式 hex(hmac_sha256(data))
+ # 公式 hex(hmac_sha256(data))
pdata['signature'] = binascii.hexlify(hmac.new(token['secret_key'], tdata, digestmod=hashlib.sha256).digest());
-
- #加密数据
+
+ # 加密数据
pdata['btauth_key'] = token['access_key'];
pdata['data'] = binascii.hexlify(tdata);
pdata['timestamp'] = time.time()
-
- #返回
+
+ # 返回
return pdata;
-#检查Token
+
+# 检查Token
def checkToken(get):
tempFile = 'data/tempToken.json'
if not os.path.exists(tempFile): return False
- import json,time
+ import json, time
tempToken = json.loads(readFile(tempFile))
if time.time() > tempToken['timeout']: return False
if get.token != tempToken['token']: return False
return True;
-#获取识别码
+
+# 获取识别码
def get_uuid():
import uuid
return uuid.UUID(int=uuid.getnode()).hex[-12:]
-#进程是否存在
-def process_exists(pname,exe = None,cmdline = None):
+# 进程是否存在
+def process_exists(pname, exe=None, cmdline=None):
try:
import psutil
pids = psutil.pids()
for pid in pids:
try:
p = psutil.Process(pid)
- if p.name() == pname:
+ if p.name() == pname:
if not exe and not cmdline:
return True;
else:
if exe:
if p.exe() == exe: return True
if cmdline:
- if cmdline in p.cmdline(): return True
- except:pass
+ if cmdline in p.cmdline(): return True
+ except:
+ pass
return False
- except: return True
+ except:
+ return True
-#重启面板
+# 重启面板
def restart_panel():
import system
return system.system().ReWeb(None)
-#获取mac
+
+# 获取mac
def get_mac_address():
import uuid
- mac=uuid.UUID(int = uuid.getnode()).hex[-12:]
- return ":".join([mac[e:e+2] for e in range(0,11,2)])
+ mac = uuid.UUID(int=uuid.getnode()).hex[-12:]
+ return ":".join([mac[e:e + 2] for e in range(0, 11, 2)])
-#转码
+# 转码
def to_string(lites):
if type(lites) != list: lites = [lites]
m_str = ''
@@ -1132,61 +1202,70 @@ def to_string(lites):
m_str += chr(mu)
return m_str
-#xss 防御
+
+# xss 防御
def xssencode(text):
import cgi
- list=['`','~','&','#','/','*','$','@','<','>','\"','\'',';','%',',','.','\\u']
- ret=[]
+ list = ['`', '~', '&', '#', '/', '*', '$', '@', '<', '>', '\"', '\'', ';', '%', ',', '.', '\\u']
+ ret = []
for i in text:
if i in list:
- i=''
+ i = ''
ret.append(i)
str_convert = ''.join(ret)
- text2=cgi.escape(str_convert, quote=True)
+ text2 = cgi.escape(str_convert, quote=True)
return text2
+
# 取缓存
def cache_get(key):
from BTPanel import cache
return cache.get(key)
+
# 设置缓存
-def cache_set(key,value,timeout = None):
+def cache_set(key, value, timeout=None):
from BTPanel import cache
- return cache.set(key,value,timeout)
+ return cache.set(key, value, timeout)
+
# 删除缓存
def cache_remove(key):
from BTPanel import cache
return cache.delete(key)
+
# 取session值
def sess_get(key):
from BTPanel import session
if key in session: return session[key]
return None
+
# 设置或修改session值
-def sess_set(key,value):
+def sess_set(key, value):
from BTPanel import session
session[key] = value
return True
+
# 删除指定session值
def sess_remove(key):
from BTPanel import session
- if key in session: del(session[key])
+ if key in session: del (session[key])
return True
+
# 构造分页
-def get_page(count,p=1,rows=12,callback='',result='1,2,3,4,5,8'):
+def get_page(count, p=1, rows=12, callback='', result='1,2,3,4,5,8'):
import page
from BTPanel import request
page = page.Page();
- info = { 'count':count, 'row':rows, 'p':p, 'return_js':callback ,'uri':request.full_path}
- data = { 'page': page.GetPage(info,result), 'shift': str(page.SHIFT), 'row': str(page.ROW) }
+ info = {'count': count, 'row': rows, 'p': p, 'return_js': callback, 'uri': request.full_path}
+ data = {'page': page.GetPage(info, result), 'shift': str(page.SHIFT), 'row': str(page.ROW)}
return data
+
# 取面板版本
def version():
from BTPanel import g
@@ -1194,10 +1273,10 @@ def version():
return g.version
except:
comm = ReadFile('/www/server/panel/class/common.py')
- return re.search("g\.version\s*=\s*'(\d+\.\d+\.\d+)'",comm).groups()[0]
+ return re.search("g\.version\s*=\s*'(\d+\.\d+\.\d+)'", comm).groups()[0]
-#取文件或目录大小
+# 取文件或目录大小
def get_path_size(path):
if not os.path.exists(path): return 0;
if not os.path.isdir(path): return os.path.getsize(path)
@@ -1210,7 +1289,8 @@ def get_path_size(path):
size_total += os.path.getsize(filename)
return size_total
-#写关键请求日志
+
+# 写关键请求日志
def write_request_log():
try:
log_path = '/www/server/panel/logs/request'
@@ -1224,10 +1304,12 @@ def write_request_log():
log_data['method'] = request.method
log_data['uri'] = request.full_path
log_data['user-agent'] = request.headers.get('User-Agent')
- WriteFile(log_path + '/' + log_file,json.dumps(log_data) + "\n",'a+')
- except: pass
+ WriteFile(log_path + '/' + log_file, json.dumps(log_data) + "\n", 'a+')
+ except:
+ pass
-#重载模块
+
+# 重载模块
def mod_reload(mode):
if not mode: return False
try:
@@ -1237,18 +1319,20 @@ def mod_reload(mode):
import imp
imp.reload(module)
return True
- except: return False
+ except:
+ return False
+
-#设置权限
-def set_mode(filename,mode):
+# 设置权限
+def set_mode(filename, mode):
if not os.path.exists(filename): return False
- mode = int(str(mode),8)
- os.chmod(filename,mode)
+ mode = int(str(mode), 8)
+ os.chmod(filename, mode)
return True
-#设置用户组
-def set_own(filename,user,group=None):
+# 设置用户组
+def set_own(filename, user, group=None):
if not os.path.exists(filename): return False
from pwd import getpwnam
try:
@@ -1258,71 +1342,109 @@ def set_own(filename,user,group=None):
user_info = getpwnam(group)
group = user_info.pw_gid
except:
- #如果指定用户或组不存在,则使用www
+ # 如果指定用户或组不存在,则使用www
user_info = getpwnam('www')
user = user_info.pw_uid
group = user_info.pw_gid
- os.chown(filename,user,group)
+ os.chown(filename, user, group)
return True
-#校验路径安全
+
+# 校验路径安全
def path_safe_check(path):
- checks = ['..','./','\\','%','$','^','&','*','~','@','#']
+ checks = ['..', './', '\\', '%', '$', '^', '&', '*', '~', '@', '#']
for c in checks:
if path.find(c) != -1: return False
rep = "^[\w\s\.\/-]+$"
- if not re.match(rep,path): return False
+ if not re.match(rep, path): return False
return True
-#取数据库字符集
+
+# 取数据库字符集
def get_database_character(db_name):
try:
import panelMysql
tmp = panelMysql.panelMysql().query("show create database `%s`" % db_name.strip())
- return str(re.findall("SET\s+(.+)\s",tmp[0][1])[0])
+ c_type = str(re.findall("SET\s+([\w\d-]+)\s", tmp[0][1])[0])
+ c_types = ['utf8', 'utf-8', 'gbk', 'big5', 'utf8mb4']
+ if not c_type.lower() in c_types: return 'utf8'
+ return c_type
except:
return 'utf8'
+
def en_punycode(domain):
- tmp = domain.split('.');
- newdomain = '';
- for dkey in tmp:
- #匹配非ascii字符
- match = re.search(u"[\x80-\xff]+",dkey);
- if not match: match = re.search(u"[\u4e00-\u9fa5]+",dkey);
- if not match:
- newdomain += dkey + '.';
- else:
- newdomain += 'xn--' + dkey.encode('punycode').decode('utf-8') + '.'
- return newdomain[0:-1];
-
-#punycode 转中文
+ tmp = domain.split('.');
+ newdomain = '';
+ for dkey in tmp:
+ # 匹配非ascii字符
+ match = re.search(u"[\x80-\xff]+", dkey);
+ if not match: match = re.search(u"[\u4e00-\u9fa5]+", dkey);
+ if not match:
+ newdomain += dkey + '.';
+ else:
+ newdomain += 'xn--' + dkey.encode('punycode').decode('utf-8') + '.'
+ return newdomain[0:-1];
+
+
+# punycode 转中文
def de_punycode(domain):
tmp = domain.split('.');
newdomain = '';
for dkey in tmp:
- if dkey.find('xn--') >=0:
- newdomain += dkey.replace('xn--','').encode('utf-8').decode('punycode') + '.'
+ if dkey.find('xn--') >= 0:
+ newdomain += dkey.replace('xn--', '').encode('utf-8').decode('punycode') + '.'
else:
newdomain += dkey + '.'
return newdomain[0:-1];
-#取计划任务文件路径
+
+# 取计划任务文件路径
def get_cron_path():
u_file = '/var/spool/cron/crontabs/root'
if not os.path.exists(u_file):
- file='/var/spool/cron/root'
+ file = '/var/spool/cron/root'
else:
- file=u_file
+ file = u_file
return file
-#取通用对象
+#加密字符串
+def en_crypt(key,strings):
+ try:
+ if type(strings) != bytes: strings = strings.encode('utf-8')
+ from cryptography.fernet import Fernet
+ f = Fernet(key)
+ result = f.encrypt(strings)
+ return result.decode('utf-8')
+ except:
+ print(get_error_info())
+ return strings
+
+#解密字符串
+def de_crypt(key,strings):
+ try:
+ if type(strings) != bytes: strings = strings.encode('utf-8')
+ from cryptography.fernet import Fernet
+ f = Fernet(key)
+ result = f.decrypt(strings).decode('utf-8')
+ return result
+ except:
+ print(get_error_info())
+ return strings
+
+
+# 取通用对象
class dict_obj:
def __contains__(self, key):
- return getattr(self,key,None)
- def __setitem__(self, key, value): setattr(self,key,value)
- def __getitem__(self, key): return getattr(self,key,None)
- def __delitem__(self,key): delattr(self,key)
- def __delattr__(self, key): delattr(self,key)
+ return getattr(self, key, None)
+
+ def __setitem__(self, key, value): setattr(self, key, value)
+
+ def __getitem__(self, key): return getattr(self, key, None)
+
+ def __delitem__(self, key): delattr(self, key)
+
+ def __delattr__(self, key): delattr(self, key)
+
def get_items(self): return self
diff --git a/class/setPanelLets.py b/class/setPanelLets.py
new file mode 100644
index 00000000..e5380146
--- /dev/null
+++ b/class/setPanelLets.py
@@ -0,0 +1,165 @@
+#coding: utf-8
+# +-------------------------------------------------------------------
+# | 宝塔Linux面板
+# +-------------------------------------------------------------------
+# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
+# +-------------------------------------------------------------------
+# | Author: 邹浩文 <627622230@qq.com>
+# +-------------------------------------------------------------------
+import os
+os.chdir("/www/server/panel")
+import public,db,panelSSL,json
+
+
+class setPanelLets:
+ __vhost_cert_path = "/www/server/panel/vhost/ssl/"
+ __panel_cert_path = "/www/server/panel/ssl/"
+ __tmp_key = ""
+ __tmp_cert = ""
+ def __init__(self):
+ pass
+
+ # 保存面板证书
+ def __save_panel_cert(self,cert,key):
+ keyPath = 'ssl/privateKey.pem'
+ certPath = 'ssl/certificate.pem'
+ checkCert = '/tmp/cert.pl'
+ public.writeFile(checkCert,cert)
+ if key:
+ public.writeFile(keyPath,key)
+ if cert:
+ public.writeFile(certPath,cert)
+ if not public.CheckCert(checkCert): return public.returnMsg(False,'Certificate error, please check!')
+ public.writeFile('ssl/input.pl','True')
+ return public.returnMsg(True,'The certificate has been saved!')
+
+ # 检查是否存在站点aapanel主机名站点
+ def __check_host_name(self, domain):
+ sql = db.Sql()
+ path = sql.table('sites').where('name=?', (domain,)).getField('path')
+ return path
+
+ # 创建证书使用的站点
+ def __create_site_of_panel_lets(self,get):
+ import panelSite
+ ps = panelSite.panelSite()
+ get.webname = json.dumps({"domain":get.domain,"domainlist":[],"count":0})
+ get.ps = "For panel Let's Encrypt certificate request and renewal, please do not delete"
+ get.path = "/www/wwwroot/panel_ssl_site"
+ get.ftp = "false"
+ get.sql = "false"
+ get.codeing = "utf8"
+ get.type = "PHP"
+ get.version = "00"
+ get.type_id = "0"
+ get.port = "80"
+ psa = ps.AddSite(get)
+ if "status" in psa.keys():
+ return psa
+
+ # 申请面板域名证书
+ def __create_lets(self,get):
+ import panelSite
+ ps = panelSite.panelSite()
+ get.siteName = get.domain
+ get.updateOf = "1"
+ get.domains = json.dumps([get.domain])
+ get.force = "true"
+ psc = ps.CreateLet(get)
+ if "False" in psc.values():
+ return psc
+
+ # 检查证书夹是否存在可用证书
+ def __check_cert_dir(self,get):
+ pssl = panelSSL.panelSSL()
+ gcl = pssl.GetCertList(get)
+ for i in gcl:
+ if get.domain in i.values():
+ return i
+
+ # 读取可用站点证书
+ def __read_site_cert(self,domain_cert):
+ self.__tmp_key = public.readFile("{path}{domain}/{key}".format(path=self.__vhost_cert_path,domain=domain_cert["subject"],key="privkey.pem"))
+ self.__tmp_cert = public.readFile(
+ "{path}{domain}/{cert}".format(path=self.__vhost_cert_path, domain=domain_cert["subject"],
+ cert="fullchain.pem"))
+ public.writeFile("/tmp/2",str(self.__tmp_cert))
+
+ # 检查面板证书是否存在
+ def __check_panel_cert(self):
+ key = public.readFile(self.__panel_cert_path+"privateKey.pem")
+ cert = public.readFile(self.__panel_cert_path+"certificate.pem")
+ if key and cert:
+ return {"key":key,"cert":cert}
+
+ # 写面板证书
+ def __write_panel_cert(self):
+ public.writeFile(self.__panel_cert_path + "privateKey.pem", self.__tmp_key)
+ 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 get_cert_source(self):
+ data = public.readFile(self.__panel_cert_path+"lets.info")
+ if not data:
+ return {"cert_type":"","email":"","domain":""}
+ return json.loads(data)
+
+ # 检查面板是否绑定域名
+ def __check_panel_domain(self):
+ domain = public.readFile("/www/server/panel/data/domain.conf")
+ if not domain:
+ return False
+ return domain
+
+ # 复制证书
+ def copy_cert(self,domain_cert):
+ self.__read_site_cert(domain_cert)
+ panel_cert_data = self.__check_panel_cert()
+ if not panel_cert_data:
+ self.__write_panel_cert()
+ return True
+ else:
+ if panel_cert_data["key"] == self.__tmp_key and panel_cert_data["cert"] == self.__tmp_cert:
+ pass
+ else:
+ self.__write_panel_cert()
+ return True
+
+ # 设置lets证书
+ def set_lets(self,get):
+ """
+ 传入参数
+ get.domain 面板域名
+ get.email 管理员email
+ """
+ create_site = ""
+ 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.")
+ if not self.__check_host_name(domain):
+ create_site = self.__create_site_of_panel_lets(get)
+ domain_cert = self.__check_cert_dir(get)
+ if domain_cert:
+ 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')
+ if not create_site:
+ create_lets = self.__create_lets(get)
+ if not create_lets:
+ 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')
+ else:
+ return create_lets
+ else:
+ return create_site
diff --git a/class/sewer/client.py b/class/sewer/client.py
index 2eb4ab4f..30a6f103 100644
--- a/class/sewer/client.py
+++ b/class/sewer/client.py
@@ -13,7 +13,9 @@
from . import __version__ as sewer_version
from .config import ACME_DIRECTORY_URL_PRODUCTION
-requests.packages.urllib3.disable_warnings()
+try:
+ requests.packages.urllib3.disable_warnings()
+except:pass
class Client(object):
@@ -585,6 +587,7 @@ def get_acme_header(self, url):
"""
self.logger.debug("get_acme_header")
header = {"alg": "RS256", "nonce": self.get_nonce(), "url": url}
+
if url in [self.ACME_NEW_ACCOUNT_URL, self.ACME_REVOKE_CERT_URL, "GET_THUMBPRINT"]:
private_key = cryptography.hazmat.primitives.serialization.load_pem_private_key(
self.account_key.encode(),
@@ -605,6 +608,7 @@ def get_acme_header(self, url):
header["jwk"] = jwk
else:
header["kid"] = self.kid
+ print('h:',url,header)
return header
def make_signed_acme_request(self, url, payload):
diff --git a/runconfig.py b/runconfig.py
index 05846b8e..96faf0ed 100644
--- a/runconfig.py
+++ b/runconfig.py
@@ -8,22 +8,30 @@
bind.append('[0:0:0:0:0:0:0:0]:%s' % bt_port)
else:
bind.append('0.0.0.0:%s' % bt_port)
-workers = 1
-threads = 4
+
+w_num = 'data/workers.pl'
+if not os.path.exists(w_num): public.writeFile(w_num,'1')
+workers = int(public.readFile(w_num))
+if not workers: workers = 1
+threads = 3
backlog = 512
-reload = False
daemon = True
timeout = 7200
keepalive = 60
-preload_app = True
+debug = os.path.exists('data/debug.pl')
+reload = debug
+preload_app = not debug
worker_class = 'geventwebsocket.gunicorn.workers.GeventWebSocketWorker'
chdir = '/www/server/panel'
capture_output = True
-access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"'
-loglevel = 'info'
+graceful_timeout=0
+loglevel = 'debug'
+access_log_format = '%(h) - %(t)s - %(u)s - %(s)s %(H)s'
errorlog = chdir + '/logs/error.log'
accesslog = chdir + '/logs/access.log'
pidfile = chdir + '/logs/panel.pid'
if os.path.exists(chdir + '/data/ssl.pl'):
certfile = 'ssl/certificate.pem'
- keyfile = 'ssl/privateKey.pem'
\ No newline at end of file
+ keyfile = 'ssl/privateKey.pem'
+ ciphers = 'TLSv1 TLSv1.1 TLSv1.2'
+ ssl_version = 2
\ No newline at end of file
diff --git a/tools.py b/tools.py
index 33a653cc..b663eb97 100644
--- a/tools.py
+++ b/tools.py
@@ -25,14 +25,12 @@ def set_mysql_root(password):
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
pwd=$1
-service mysqld stop
+/etc/init.d/mysqld stop
mysqld_safe --skip-grant-tables&
echo 'Changing password...';
sleep 6
-m_version=$(cat /www/server/mysql/version.pl|grep -E "(5.1.|5.5.|5.6.|mariadb)")
+m_version=$(cat /www/server/mysql/version.pl|grep -E "(5.1.|5.5.|5.6.|mariadb|10.)")
if [ "$m_version" != "" ];then
- mysql -uroot -e "insert into mysql.user(Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Reload_priv,Shutdown_priv,Process_priv,File_priv,Grant_priv,References_priv,Index_priv,Alter_priv,Show_db_priv,Super_priv,Create_tmp_table_priv,Lock_tables_priv,Execute_priv,Repl_slave_priv,Repl_client_priv,Create_view_priv,Show_view_priv,Create_routine_priv,Alter_routine_priv,Create_user_priv,Event_priv,Trigger_priv,Create_tablespace_priv,User,Password,host)values('Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','root',password('${pwd}'),'127.0.0.1')"
- mysql -uroot -e "insert into mysql.user(Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Reload_priv,Shutdown_priv,Process_priv,File_priv,Grant_priv,References_priv,Index_priv,Alter_priv,Show_db_priv,Super_priv,Create_tmp_table_priv,Lock_tables_priv,Execute_priv,Repl_slave_priv,Repl_client_priv,Create_view_priv,Show_view_priv,Create_routine_priv,Alter_routine_priv,Create_user_priv,Event_priv,Trigger_priv,Create_tablespace_priv,User,Password,host)values('Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','root',password('${pwd}'),'localhost')"
mysql -uroot -e "UPDATE mysql.user SET password=PASSWORD('${pwd}') WHERE user='root'";
else
mysql -uroot -e "UPDATE mysql.user SET authentication_string='' WHERE user='root'";
@@ -43,7 +41,7 @@ def set_mysql_root(password):
pkill -9 mysqld_safe
pkill -9 mysqld
sleep 2
-service mysqld start
+/etc/init.d/mysqld start
echo '==========================================='
echo "The root password set ${pwd} successuful"''';
@@ -80,7 +78,7 @@ def set_mysql_dir(path):
exit
fi
echo "Stopping MySQL service..."
-service mysqld stop
+/etc/init.d/mysqld stop
echo "Copying files, please wait..."
\cp -r -a $oldDir/* $newDir
@@ -88,7 +86,7 @@ def set_mysql_dir(path):
sed -i "s#$oldDir#$newDir#" /etc/my.cnf
echo "Starting MySQL service..."
-service mysqld start
+/etc/init.d/mysqld start
echo ''
echo 'Successful'
echo '---------------------------------------------------------------------'