mirror of
https://github.com/aaPanel/aaPanel.git
synced 2026-09-17 15:07:41 +02:00
1.Part of the log output function uses websocket to enhance the interactive experience
2.The page is displayed when the adjustment panel is wrong 3.App store add common plug-in display 4.Adjust the sessionid name to a non-fixed name 5.Panel CSRF defense mechanism covers panel websocket communication 6.Adjust the font size of the panel list 7.Adjust the panel pop-up window (add a close button to cancel the automatic closing time) 8.Optimize the front/back end of the file manager 9.Add the entrance of the MailServer Rspamd 10.Refactor the debug module 11.Other known bug fixes
This commit is contained in:
@@ -10,14 +10,79 @@
|
||||
from gevent import monkey
|
||||
monkey.patch_all()
|
||||
import os,sys,ssl
|
||||
if os.path.exists("/www/server/panel/class/BTPanel"):
|
||||
os.system("rm -rf /www/server/panel/class/BTPanel")
|
||||
os.chdir('/www/server/panel')
|
||||
_PATH = '/www/server/panel'
|
||||
os.chdir(_PATH)
|
||||
if not 'class/' in sys.path:
|
||||
sys.path.insert(0,'class/')
|
||||
from BTPanel import app,sys,public
|
||||
is_debug = os.path.exists('data/debug.pl')
|
||||
|
||||
if is_debug:
|
||||
import pyinotify,time,logging,re
|
||||
logging.basicConfig(level=logging.DEBUG,format="[%(asctime)s][%(levelname)s] - %(message)s")
|
||||
logger = logging.getLogger()
|
||||
|
||||
class PanelEventHandler(pyinotify.ProcessEvent):
|
||||
_exts = ['py','html','BT-Panel','so']
|
||||
_explude_patts = [
|
||||
re.compile('{}/plugin/.+'.format(_PATH)),
|
||||
re.compile('{}/(tmp|temp)/.+'.format(_PATH))
|
||||
]
|
||||
_lsat_time = 0
|
||||
|
||||
|
||||
def is_ext(self,filename):
|
||||
fname = os.path.basename(filename)
|
||||
result = fname.split('.')[-1] in self._exts
|
||||
if not result: return False
|
||||
for e in self._explude_patts:
|
||||
if e.match(filename): return False
|
||||
return True
|
||||
|
||||
def panel_reload(self,filename,in_type):
|
||||
stime = time.time()
|
||||
if stime - self._lsat_time < 2:
|
||||
return
|
||||
self._lsat_time = stime
|
||||
logger.debug('File detected: {} -> {}'.format(filename,in_type))
|
||||
|
||||
fname = os.path.basename(filename)
|
||||
if fname in ['task.py','BT-Task']:
|
||||
logger.debug('Background task...')
|
||||
public.ExecShell("{} {}/BT-Task".format(public.get_python_bin(),_PATH))
|
||||
logger.debug('Background task started!')
|
||||
else:
|
||||
logger.debug('Restarting panel...')
|
||||
public.ExecShell("bash {}/init.sh reload &>/dev/null &".format(_PATH))
|
||||
|
||||
def process_IN_CREATE(self, event):
|
||||
if not self.is_ext(event.pathname): return
|
||||
self.panel_reload(event.pathname,'[Create]')
|
||||
|
||||
def process_IN_DELETE(self,event):
|
||||
if not self.is_ext(event.pathname): return
|
||||
self.panel_reload(event.pathname,'[Delete]')
|
||||
|
||||
def process_IN_MODIFY(self,event):
|
||||
|
||||
if not self.is_ext(event.pathname): return
|
||||
self.panel_reload(event.pathname,'[Modify]')
|
||||
|
||||
def debug_event():
|
||||
logger.debug('Launch the panel in debug mode')
|
||||
logger.debug('Listening port:0.0.0.0:{}'.format(public.readFile('data/port.pl')))
|
||||
|
||||
event = PanelEventHandler()
|
||||
watchManager = pyinotify.WatchManager()
|
||||
mode = pyinotify.IN_CREATE | pyinotify.IN_DELETE | pyinotify.IN_MODIFY
|
||||
watchManager.add_watch(_PATH, mode, auto_add=True, rec=True)
|
||||
notifier = pyinotify.Notifier(watchManager, event)
|
||||
notifier.loop()
|
||||
|
||||
if __name__ == '__main__':
|
||||
pid_file = "{}/logs/panel.pid".format(_PATH)
|
||||
if os.path.exists(pid_file):
|
||||
public.ExecShell("kill -9 {}".format(public.readFile(pid_file)))
|
||||
pid = os.fork()
|
||||
if pid: sys.exit(0)
|
||||
|
||||
@@ -25,7 +90,7 @@ if __name__ == '__main__':
|
||||
|
||||
_pid = os.fork()
|
||||
if _pid:
|
||||
public.writeFile('logs/panel.pid',str(_pid))
|
||||
public.writeFile(pid_file,str(_pid))
|
||||
sys.exit(0)
|
||||
|
||||
sys.stdout.flush()
|
||||
@@ -38,7 +103,7 @@ if __name__ == '__main__':
|
||||
HOST = "0:0:0:0:0:0:0:0"
|
||||
f.close()
|
||||
|
||||
is_debug = os.path.exists('data/debug.pl')
|
||||
|
||||
keyfile = 'ssl/privateKey.pem'
|
||||
certfile = 'ssl/certificate.pem'
|
||||
is_ssl = False
|
||||
@@ -57,21 +122,30 @@ if __name__ == '__main__':
|
||||
job.setDaemon(True)
|
||||
job.start()
|
||||
|
||||
if is_debug:
|
||||
ssl_context = None
|
||||
if is_ssl: ssl_context=(certfile,keyfile)
|
||||
app.run(host=HOST,port=PORT,threaded=True,debug=True,ssl_context=ssl_context)
|
||||
|
||||
if is_ssl:
|
||||
ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
||||
ssl_context.load_cert_chain(certfile=certfile,keyfile=keyfile)
|
||||
ssl_context.options = (ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1)
|
||||
ssl_context.set_ciphers("ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE")
|
||||
|
||||
|
||||
from gevent.pywsgi import WSGIServer
|
||||
from geventwebsocket.handler import WebSocketHandler
|
||||
|
||||
if is_ssl:
|
||||
http_server = WSGIServer((HOST, PORT), app,handler_class=WebSocketHandler,ssl_context = ssl_context)
|
||||
else:
|
||||
from gevent.pywsgi import WSGIServer
|
||||
from geventwebsocket.handler import WebSocketHandler
|
||||
http_server = WSGIServer((HOST, PORT), app,handler_class=WebSocketHandler)
|
||||
|
||||
if is_debug:
|
||||
try:
|
||||
dev = threading.Thread(target=debug_event)
|
||||
dev.setDaemon(True)
|
||||
dev.start()
|
||||
except:
|
||||
pass
|
||||
|
||||
http_server.serve_forever()
|
||||
|
||||
if is_ssl:
|
||||
ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
||||
ssl_context.load_cert_chain(certfile=certfile,keyfile=keyfile)
|
||||
ssl_context.options |= (ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
|
||||
ssl_context.set_ciphers("ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE")
|
||||
http_server = WSGIServer((HOST, PORT), app,handler_class=WebSocketHandler,ssl_context = ssl_context)
|
||||
else:
|
||||
http_server = WSGIServer((HOST, PORT), app,handler_class=WebSocketHandler)
|
||||
|
||||
http_server.serve_forever()
|
||||
+492
-147
@@ -6,9 +6,11 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
import logging
|
||||
import sys
|
||||
import json
|
||||
import os
|
||||
import threading
|
||||
import time
|
||||
import re
|
||||
import uuid
|
||||
@@ -18,7 +20,7 @@ if not 'class/' in sys.path:
|
||||
sys.path.insert(0,'class/')
|
||||
|
||||
from flask import Config, Flask, session, render_template, send_file, request, redirect, g, make_response, \
|
||||
render_template_string, abort, Response as Resp
|
||||
render_template_string, abort, stream_with_context,Response as Resp
|
||||
from cachelib import SimpleCache
|
||||
from werkzeug.wrappers import Response
|
||||
from flask_session import Session
|
||||
@@ -32,8 +34,11 @@ import public
|
||||
app = Flask(__name__, template_folder="templates/{}".format(public.GetConfigValue('template')))
|
||||
Compress(app)
|
||||
sockets = Sockets(app)
|
||||
|
||||
#import db
|
||||
# 注册HOOK
|
||||
hooks = {}
|
||||
if not hooks:
|
||||
public.check_hooks()
|
||||
# import db
|
||||
dns_client = None
|
||||
app.config['DEBUG'] = os.path.exists('data/debug.pl')
|
||||
|
||||
@@ -52,12 +57,12 @@ if os.path.exists(basic_auth_conf):
|
||||
app.secret_key = uuid.UUID(int=uuid.getnode()).hex[-12:]
|
||||
local_ip = None
|
||||
my_terms = {}
|
||||
app.config['SESSION_MEMCACHED'] = SimpleCache()
|
||||
app.config['SESSION_MEMCACHED'] = SimpleCache(1000,86400)
|
||||
app.config['SESSION_TYPE'] = 'memcached'
|
||||
app.config['SESSION_PERMANENT'] = True
|
||||
app.config['SESSION_USE_SIGNER'] = True
|
||||
app.config['SESSION_KEY_PREFIX'] = 'BT_:'
|
||||
app.config['SESSION_COOKIE_NAME'] = "SESSIONID"
|
||||
app.config['SESSION_COOKIE_NAME'] = public.md5(app.secret_key)
|
||||
app.config['PERMANENT_SESSION_LIFETIME'] = 86400 * 30
|
||||
Session(app)
|
||||
|
||||
@@ -130,8 +135,8 @@ if admin_path in admin_path_checks: admin_path = '/bt'
|
||||
@app.before_request
|
||||
def request_check():
|
||||
g.request_time = time.time()
|
||||
#路由和URI长度过滤
|
||||
if len(request.path) > 128: return abort(403)
|
||||
# 路由和URI长度过滤
|
||||
if len(request.path) > 256: return abort(403)
|
||||
if len(request.url) > 1024: return abort(403)
|
||||
|
||||
if request.path in ['/service_status']: return
|
||||
@@ -143,13 +148,24 @@ def request_check():
|
||||
if len(k) > 48: return abort(403)
|
||||
if len(pdata[k]) > 256: return abort(403)
|
||||
if session.get('debug') == 1: return
|
||||
|
||||
if app.config['BASIC_AUTH_OPEN']:
|
||||
if request.path in ['/public', '/download', '/mail_sys', '/hook', '/down', '/check_bind',
|
||||
'/get_app_bind_status']: return
|
||||
auth = request.authorization
|
||||
if not comm.get_sk(): return
|
||||
if not auth: return send_authenticated()
|
||||
tips = '_bt.cn'
|
||||
if public.md5(auth.username.strip() + tips) != app.config['BASIC_AUTH_USERNAME'] \
|
||||
or public.md5(auth.password.strip() + tips) != app.config['BASIC_AUTH_PASSWORD']:
|
||||
return send_authenticated()
|
||||
|
||||
if not request.path in ['/safe', '/hook', '/public', '/mail_sys', '/down']:
|
||||
ip_check = public.check_ip_panel()
|
||||
if ip_check: return ip_check
|
||||
|
||||
if request.path.find('/static/') != -1 or request.path == '/code':
|
||||
if not 'login' in session and not 'admin_auth' in session and not 'down' in session:
|
||||
session.clear()
|
||||
return abort(401)
|
||||
domain_check = public.check_domain_panel()
|
||||
if domain_check: return domain_check
|
||||
@@ -158,15 +174,14 @@ def request_check():
|
||||
if request.args.get('action') in not_networks:
|
||||
return public.returnJson(False,'INIT_REQUEST_CHECK_LOCAL_ERR'),json_header
|
||||
|
||||
if app.config['BASIC_AUTH_OPEN']:
|
||||
if request.path in ['/public','/download','/mail_sys','/hook','/down','/check_bind','/get_app_bind_status']: return
|
||||
auth = request.authorization
|
||||
if not comm.get_sk(): return
|
||||
if not auth: return send_authenticated()
|
||||
tips = '_bt.cn'
|
||||
if public.md5(auth.username.strip() + tips) != app.config['BASIC_AUTH_USERNAME'] \
|
||||
or public.md5(auth.password.strip() + tips) != app.config['BASIC_AUTH_PASSWORD']:
|
||||
return send_authenticated()
|
||||
if request.path in ['/','/site','/ftp','/database','/soft','/control','/firewall','/files','/xterm','/crontab','/config']:
|
||||
licenes = 'data/licenes.pl'
|
||||
if request.path in ['/'] and not os.path.exists(licenes):
|
||||
return
|
||||
|
||||
# if not public.is_bind():
|
||||
# return redirect('/bind',302)
|
||||
|
||||
|
||||
#Flask 请求结束勾子
|
||||
@app.teardown_request
|
||||
@@ -180,9 +195,10 @@ def request_end(reques = None):
|
||||
if g.api_request:
|
||||
session.clear()
|
||||
|
||||
#Flask 404页面勾子
|
||||
|
||||
# Flask 404页面勾子
|
||||
@app.errorhandler(404)
|
||||
def notfound(e):
|
||||
def error_404(e):
|
||||
errorStr = '''<html>
|
||||
<head><title>404 Not Found</title></head>
|
||||
<body>
|
||||
@@ -195,6 +211,36 @@ def notfound(e):
|
||||
}
|
||||
return Response(errorStr,status=404,headers=headers)
|
||||
|
||||
# Flask 500页面勾子
|
||||
@app.errorhandler(500)
|
||||
def error_500(e):
|
||||
ss = '''404 Not Found: The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
|
||||
|
||||
During handling of the above exception, another exception occurred:'''
|
||||
error_info = public.get_error_info().strip().split(ss)[-1].strip()
|
||||
if error_info.find("`GLIBC_2.14'") != -1:
|
||||
public.downloadFile('https://download.bt.cn/auth/libAuth_gcc_4.4.7_x{}.so'.format(public.get_sysbit()),'/www/server/panel/class/libAuth.x86-64.so')
|
||||
error_info += "\n已尝试自动修复此问题,请刷新页面重试!"
|
||||
request_info = '''REQUEST_DATE: {request_date}
|
||||
PAN_VERSION: {panel_version}
|
||||
OS_VERSION: {os_version}
|
||||
REMOTE_ADDR: {remote_addr}
|
||||
REQUEST_URI: {method} {full_path}
|
||||
REQUEST_FORM: {request_form}
|
||||
USER_AGENT: {user_agent}'''.format(
|
||||
request_date = public.getDate(),
|
||||
remote_addr = public.GetClientIp(),
|
||||
method = request.method,
|
||||
full_path = request.full_path,
|
||||
request_form = request.form.to_dict(),
|
||||
user_agent = request.headers.get('User-Agent'),
|
||||
panel_version = public.get_panel_version(),
|
||||
os_version = public.get_os_version()
|
||||
)
|
||||
|
||||
result = public.readFile('/www/server/panel/BTPanel/templates/default/panel_error.html').format(error_title=error_info.split("\n")[-1],request_info = request_info,error_msg=error_info)
|
||||
return Resp(result,500)
|
||||
|
||||
# ===================================Flask HOOK========================#
|
||||
|
||||
|
||||
@@ -227,55 +273,6 @@ def xterm():
|
||||
defs = ('get_host_list','get_host_find','modify_host','create_host','remove_host','set_sort','get_command_list','create_command','get_command_find','modify_command','remove_command')
|
||||
return publicObject(ssh_host_admin,defs,None)
|
||||
|
||||
#@app.route('/webssh')
|
||||
@sockets.route('/webssh')
|
||||
def webssh(ws):
|
||||
#宝塔终端连接
|
||||
comReturn = comm.local()
|
||||
if comReturn: return comReturn
|
||||
#ws = request.environ.get('wsgi.websocket')
|
||||
if not ws: return 'False'
|
||||
get = ws.receive()
|
||||
if not get: return
|
||||
get = json.loads(get)
|
||||
import ssh_terminal
|
||||
sp = ssh_terminal.ssh_host_admin()
|
||||
if 'host' in get:
|
||||
ssh_info = {}
|
||||
ssh_info['host'] = get['host'].strip()
|
||||
if 'port' in get:
|
||||
ssh_info['port'] = int(get['port'])
|
||||
if 'username' in get:
|
||||
ssh_info['username'] = get['username'].strip()
|
||||
if 'password' in get:
|
||||
ssh_info['password'] = get['password'].strip()
|
||||
if 'pkey' in get:
|
||||
ssh_info['pkey'] = get['pkey'].strip()
|
||||
|
||||
if get['host'] in ['127.0.0.1','localhost'] and 'port' not in ssh_info:
|
||||
ssh_info = sp.get_ssh_info('127.0.0.1')
|
||||
if not ssh_info: ssh_info = sp.get_ssh_info('localhost')
|
||||
if not ssh_info: ssh_info = {"host":"127.0.0.1"}
|
||||
ssh_info['port'] = public.get_ssh_port()
|
||||
else:
|
||||
ssh_info = sp.get_ssh_info('127.0.0.1')
|
||||
if not ssh_info: ssh_info = sp.get_ssh_info('localhost')
|
||||
if not ssh_info: ssh_info = {"host":"127.0.0.1"}
|
||||
ssh_info['port'] = public.get_ssh_port()
|
||||
|
||||
if not ssh_info['host'] in ['127.0.0.1','localhost']:
|
||||
if not 'username' in ssh_info:
|
||||
ssh_info = sp.get_ssh_info(ssh_info['host'])
|
||||
if not ssh_info:
|
||||
ws.send(public.getMsg('SSH_LOGIN_ERR7'))
|
||||
return
|
||||
p = ssh_terminal.ssh_terminal()
|
||||
p.run(ws,ssh_info)
|
||||
del(p)
|
||||
if not ws.closed:
|
||||
ws.close()
|
||||
return 'False'
|
||||
|
||||
|
||||
@app.route('/site',methods=method_all)
|
||||
def site(pdata = None):
|
||||
@@ -483,21 +480,22 @@ def firewall(pdata = None):
|
||||
'AddAcceptPort','DelAcceptPort','SetSshStatus','SetPing','SetSshPort','GetSshInfo')
|
||||
return publicObject(firewallObject,defs,None,pdata)
|
||||
|
||||
@app.route('/ssh_security',methods=method_all)
|
||||
def ssh_security(pdata = None):
|
||||
#SSH安全
|
||||
|
||||
@app.route('/ssh_security', methods=method_all)
|
||||
def ssh_security(pdata=None):
|
||||
# SSH安全
|
||||
comReturn = comm.local()
|
||||
if comReturn: return comReturn
|
||||
if request.method == method_get[0] and not pdata:
|
||||
data = {}
|
||||
data['lan'] = public.GetLan('firewall')
|
||||
data['js_random'] = get_js_random()
|
||||
return render_template( 'firewall.html',data=data)
|
||||
return render_template('firewall.html', data=data)
|
||||
import ssh_security
|
||||
firewallObject = ssh_security.ssh_security()
|
||||
defs = ('san_ssh_security', 'set_password', 'set_sshkey', 'stop_key', 'get_config',
|
||||
'stop_password', 'get_key', 'return_ip', 'add_return_ip', 'del_return_ip', 'start_jian', 'stop_jian',
|
||||
'get_jian', 'get_logs','set_root','stop_root')
|
||||
'get_jian', 'get_logs','set_root','stop_root','start_auth_method','stop_auth_method','get_auth_method','check_so_file','get_so_file')
|
||||
return publicObject(firewallObject, defs, None, pdata)
|
||||
|
||||
|
||||
@@ -573,6 +571,20 @@ def abnormal(pdata=None):
|
||||
)
|
||||
return publicObject(dataObject, defs, None, pdata)
|
||||
|
||||
@app.route('/project/<mod_name>/<def_name>', methods=method_all)
|
||||
def project(mod_name,def_name):
|
||||
comReturn = comm.local()
|
||||
if comReturn: return comReturn
|
||||
from panelProjectController import ProjectController
|
||||
project_obj = ProjectController()
|
||||
defs = ('model',)
|
||||
get = get_input()
|
||||
get.action = 'model'
|
||||
get.mod_name = mod_name
|
||||
get.def_name = def_name
|
||||
|
||||
return publicObject(project_obj,defs,None,get)
|
||||
|
||||
@app.route('/files',methods=method_all)
|
||||
def files(pdata = None):
|
||||
#文件管理
|
||||
@@ -662,7 +674,7 @@ def config(pdata = None):
|
||||
return render_template( 'config.html',data=data)
|
||||
import config
|
||||
defs = (
|
||||
'set_backup_notification','get_panel_ssl_status','set_file_deny', 'del_file_deny', 'get_file_deny',
|
||||
'set_empty','set_backup_notification','get_panel_ssl_status','set_file_deny', 'del_file_deny', 'get_file_deny',
|
||||
'get_httpd_access_log_format_parameter','set_httpd_format_log_to_website','get_httpd_access_log_format',
|
||||
'del_httpd_access_log_format','add_httpd_access_log_format','get_nginx_access_log_format_parameter',
|
||||
'set_format_log_to_website','get_nginx_access_log_format','del_nginx_access_log_format',
|
||||
@@ -775,7 +787,7 @@ def plugin(pdata = None):
|
||||
if comReturn: return comReturn
|
||||
import panelPlugin
|
||||
pluginObject = panelPlugin.panelPlugin()
|
||||
defs = ('check_install_limit','set_score','get_score','update_zip','input_zip','export_zip','add_index','remove_index','sort_index',
|
||||
defs = ('get_usually_plugin','check_install_limit','set_score','get_score','update_zip','input_zip','export_zip','add_index','remove_index','sort_index',
|
||||
'install_plugin','uninstall_plugin','get_soft_find','get_index_list','get_soft_list','get_cloud_list',
|
||||
'check_deps','flush_cache','GetCloudWarning','install','unInstall','getPluginList','getPluginInfo','get_make_args','add_make_args',
|
||||
'getPluginStatus','setPluginStatus','a','getCloudPlugin','getConfigHtml','savePluginSort','del_make_args','set_make_args')
|
||||
@@ -889,9 +901,7 @@ def login():
|
||||
is_auth_path = False
|
||||
if admin_path != '/bt' and os.path.exists(admin_path_file) and not 'admin_auth' in session:
|
||||
is_auth_path = True
|
||||
num_key = public.md5(public.GetClientIp() + '_auth_path')
|
||||
# if not public.get_error_num(num_key,20): return public.returnMsg(False,'AUTH_FAILED1')
|
||||
#登录输入验证
|
||||
# 登录输入验证
|
||||
if request.method == method_post[0]:
|
||||
v_list = ['username','password','code','vcode','cdn_url']
|
||||
for v in v_list:
|
||||
@@ -949,14 +959,12 @@ def login():
|
||||
referer_path = referer_tmp[-1]
|
||||
if referer_path == '':
|
||||
referer_path = referer_tmp[-2]
|
||||
if route_path != '/'+referer_path:
|
||||
public.set_error_num(num_key)
|
||||
#return abort(404)
|
||||
if route_path != '/' + referer_path:
|
||||
data = {}
|
||||
data['lan'] = public.getLan('close')
|
||||
return render_template('autherr.html',data=data)
|
||||
return render_template('autherr.html', data=data)
|
||||
|
||||
session['admin_auth'] = True
|
||||
public.set_error_num(num_key,True)
|
||||
comReturn = common.panelSetup().init()
|
||||
if comReturn: return comReturn
|
||||
|
||||
@@ -1071,20 +1079,22 @@ def down(token=None,fname=None):
|
||||
if not re.match(r"^\w+$",args.file_password):
|
||||
return public.ReturnJson(False,'WRONG_PASSWD'),json_header
|
||||
if re.match(r"^\d+$",args.file_password):
|
||||
args.file_password += '.0'
|
||||
args.file_password = str(int(args.file_password))
|
||||
args.file_password += ".0"
|
||||
if args.file_password != str(find['password']):
|
||||
return public.ReturnJson(False,'WRONG_PASSWD'),json_header
|
||||
session[token] = 1
|
||||
session['down'] = True
|
||||
else:
|
||||
pdata = {
|
||||
"to_path":"",
|
||||
"src_path": find['filename'],
|
||||
"password":True,
|
||||
"filename":find['filename'].split('/')[-1],
|
||||
"total":find['total'],
|
||||
"token":find['token'],
|
||||
"expire":public.format_date(times=find['expire'])
|
||||
"to_path":"",
|
||||
"src_path": find['filename'],
|
||||
"password":True,
|
||||
"filename":find['filename'].split('/')[-1],
|
||||
"ps": find['ps'],
|
||||
"total":find['total'],
|
||||
"token":find['token'],
|
||||
"expire":public.format_date(times=find['expire'])
|
||||
}
|
||||
session['down'] = True
|
||||
return render_template('down.html',data = pdata)
|
||||
@@ -1291,7 +1301,8 @@ def panel_other(name=None,fun = None,stype=None):
|
||||
data = panelPHP.panelPHP(name).exec_php_script(args)
|
||||
|
||||
r_type = type(data)
|
||||
if r_type == Response: return data
|
||||
if r_type in [Response,Resp]:
|
||||
return data
|
||||
|
||||
#处理响应
|
||||
if stype == 'json': #响应JSON
|
||||
@@ -1383,6 +1394,38 @@ Disallow: /
|
||||
'''
|
||||
return robots,{'Content-Type':'text/plain'}
|
||||
|
||||
|
||||
@app.route('/rspamd', defaults={'path': ''},methods=method_all)
|
||||
@app.route('/rspamd/<path:path>',methods=method_all)
|
||||
def proxy_rspamd_requests(path):
|
||||
comReturn = comm.local()
|
||||
if comReturn: return comReturn
|
||||
param = str(request.url).split('?')
|
||||
param = "" if len(param) < 2 else param[-1]
|
||||
import requests
|
||||
headers = {}
|
||||
for h in request.headers.keys():
|
||||
headers[h] = request.headers[h]
|
||||
if request.method == "GET":
|
||||
if re.search("\.(js|css)$",path):
|
||||
return send_file('/usr/share/rspamd/www/rspamd/'+path,conditional=True,add_etags=True)
|
||||
if path == "/":
|
||||
return send_file('/usr/share/rspamd/www/rspamd/',conditional=True,add_etags=True)
|
||||
url = "http://127.0.0.1:11334/rspamd/" + path + "?" +param
|
||||
for i in ['stat','auth','neighbours','list_extractors','list_transforms','graph','maps','actions','symbols','history','errors','check_selector','saveactions','savesymbols','getmap']:
|
||||
if i in path:
|
||||
url = "http://127.0.0.1:11334/" + path + "?" +param
|
||||
req = requests.get(url, headers=headers,stream = True)
|
||||
return Resp(stream_with_context(req.iter_content()), content_type = req.headers['content-type'])
|
||||
else:
|
||||
url = "http://127.0.0.1:11334/" + path
|
||||
for i in request.form.keys():
|
||||
data = '{}='.format(i)
|
||||
# public.writeFile('/tmp/2',data+"\n","a+")
|
||||
req = requests.post(url,data=data,headers=headers,stream = True)
|
||||
|
||||
return Resp(stream_with_context(req.iter_content()), content_type = req.headers['content-type'])
|
||||
|
||||
#==================================================#
|
||||
|
||||
|
||||
@@ -1405,6 +1448,7 @@ def get_dir_down(filename,token,find):
|
||||
|
||||
pdata = files.files().GetDir(args)
|
||||
pdata['token'] = token
|
||||
pdata['ps'] = find['ps']
|
||||
pdata['src_path'] = find['filename']
|
||||
pdata['to_path'] = to_path
|
||||
if find['expire'] < (time.time() + (86400 * 365 * 10)):
|
||||
@@ -1455,34 +1499,19 @@ def get_phpmyadmin_dir():
|
||||
|
||||
|
||||
class run_exec:
|
||||
#模块访问对像
|
||||
def run(self,toObject,defs,get):
|
||||
# 模块访问对像
|
||||
def run(self, toObject, defs, get):
|
||||
result = None
|
||||
for key in defs:
|
||||
if key == get.action:
|
||||
fun = 'toObject.'+key+'(get)'
|
||||
if hasattr(get,'html') or hasattr(get,'s_module'):
|
||||
result = eval(fun)
|
||||
else:
|
||||
result = eval(fun)
|
||||
r_type = type(result)
|
||||
if r_type == Resp: return result
|
||||
result = public.GetJson(result),json_header
|
||||
break
|
||||
if not result:
|
||||
result = public.ReturnJson(False,'ARGS_ERR'),json_header
|
||||
if g.is_aes:
|
||||
result = public.aes_encrypt(result[0],g.aes_key),json_header
|
||||
else:
|
||||
# if os.path.exists('pyenv/bin/python') and sys.version_info[0] == 3:
|
||||
# if not os.path.exists('data/debug.pl'):
|
||||
# x_token = request.headers.get('x-http-token')
|
||||
# if x_token:
|
||||
# aes_pwd = x_token[:8] + x_token[40:48]
|
||||
# result = "BT-CRT"+public.aes_encrypt(result[0],aes_pwd),{'Content-Type':'text/plain; charset=utf-8'}
|
||||
pass
|
||||
return result
|
||||
if not get.action in defs: return public.ReturnJson(False, 'ARGS_ERR'), json_header
|
||||
result = getattr(toObject,get.action)(get)
|
||||
if not hasattr(get, 'html') and not hasattr(get, 's_module'):
|
||||
r_type = type(result)
|
||||
if r_type in [Response,Resp]: return result
|
||||
result = public.GetJson(result), json_header
|
||||
|
||||
if g.is_aes:
|
||||
result = public.aes_encrypt(result[0], g.aes_key), json_header
|
||||
return result
|
||||
|
||||
|
||||
def check_csrf():
|
||||
@@ -1497,29 +1526,39 @@ def check_csrf():
|
||||
if cookie_token != session['request_token']: return False
|
||||
return True
|
||||
|
||||
def publicObject(toObject,defs,action=None,get = None):
|
||||
#模块访问前置检查
|
||||
if 'request_token' in session and 'login' in session:
|
||||
if not check_csrf(): return public.ReturnJson(False,'INIT_CSRF_ERR'),json_header
|
||||
|
||||
if not get: get = get_input()
|
||||
if action: get.action = action
|
||||
def publicObject(toObject, defs, action=None, get=None):
|
||||
try:
|
||||
# 模块访问前置检查
|
||||
if 'request_token' in session and 'login' in session:
|
||||
if not check_csrf(): return public.ReturnJson(False, 'INIT_CSRF_ERR'), json_header
|
||||
|
||||
if hasattr(get,'path'):
|
||||
get.path = get.path.replace('//','/').replace('\\','/')
|
||||
if get.path.find('./') != -1: return public.ReturnJson(False,'INIT_PATH_NOT_SAFE'),json_header
|
||||
if not get: get = get_input()
|
||||
if action: get.action = action
|
||||
|
||||
if hasattr(get, 'path'):
|
||||
get.path = get.path.replace('//', '/').replace('\\', '/')
|
||||
if get.path.find('./') != -1: return public.ReturnJson(False, 'INIT_PATH_NOT_SAFE'), json_header
|
||||
if get.path.find('->') != -1:
|
||||
get.path = get.path.split('->')[0].strip()
|
||||
if hasattr(get,'sfile'):
|
||||
get.sfile = get.sfile.replace('//','/').replace('\\','/')
|
||||
if hasattr(get,'dfile'):
|
||||
get.dfile = get.dfile.replace('//','/').replace('\\','/')
|
||||
get.path = public.xssdecode(get.path)
|
||||
if hasattr(get, 'filename'):
|
||||
get.filename = public.xssdecode(get.filename)
|
||||
|
||||
if hasattr(toObject,'site_path_check'):
|
||||
if not toObject.site_path_check(get): return public.ReturnJson(False,'INIT_ACCEPT_NOT'),json_header
|
||||
return run_exec().run(toObject,defs,get)
|
||||
if hasattr(get, 'sfile'):
|
||||
get.sfile = get.sfile.replace('//', '/').replace('\\', '/')
|
||||
get.sfile = public.xssdecode(get.sfile)
|
||||
if hasattr(get, 'dfile'):
|
||||
get.dfile = get.dfile.replace('//', '/').replace('\\', '/')
|
||||
get.dfile = public.xssdecode(get.dfile)
|
||||
|
||||
|
||||
if hasattr(toObject, 'site_path_check'):
|
||||
if not toObject.site_path_check(get): return public.ReturnJson(False, 'INIT_ACCEPT_NOT'), json_header
|
||||
return run_exec().run(toObject, defs, get)
|
||||
except:
|
||||
return error_500(None)
|
||||
|
||||
|
||||
def check_login(http_token=None):
|
||||
#检查是否登录面板
|
||||
@@ -1569,8 +1608,8 @@ def get_pd():
|
||||
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, 28857, 20987, 21319, 32423,
|
||||
21040, 21830, 19994, 29256, 34, 62, 20813, 36153, 29256, 60, 47, 115, 112, 97, 110, 62])
|
||||
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,
|
||||
@@ -1609,8 +1648,8 @@ def get_pd():
|
||||
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, 114, 101, 110, 101, 119, 95, 112,
|
||||
114, 111, 40, 41, 34, 32, 116, 105, 116, 108, 101, 61, 34, 28857,
|
||||
20987, 21319, 32423, 21040, 19987, 19994, 29256, 34, 62, 70, 82,
|
||||
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,
|
||||
@@ -1675,17 +1714,9 @@ def get_input():
|
||||
for key in request.args.keys():
|
||||
data[key] = str(request.args.get(key,''))
|
||||
try:
|
||||
# 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():
|
||||
if key in exludes: continue
|
||||
data[key] = str(request.form.get(key,''))
|
||||
# if x_token:
|
||||
# if len(data[key]) > 5:
|
||||
# if data[key][:6] == 'BT-CRT':
|
||||
# data[key] = public.aes_decrypt(data[key][6:],aes_pwd)
|
||||
data[key] = str(request.form.get(key, ''))
|
||||
except:
|
||||
try:
|
||||
post = request.form.to_dict()
|
||||
@@ -1728,6 +1759,320 @@ def check_token(data):
|
||||
|
||||
#======================公共方法区域END============================#
|
||||
|
||||
# --------------------- websocket START -------------------------- #
|
||||
|
||||
|
||||
@sockets.route('/workorder_client')
|
||||
def workorder_client(ws):
|
||||
comReturn = comm.local()
|
||||
if comReturn: return comReturn
|
||||
|
||||
get = ws.receive()
|
||||
get = json.loads(get)
|
||||
if not check_csrf_websocket(ws,get):
|
||||
return
|
||||
|
||||
import panelWorkorder
|
||||
toObject = panelWorkorder.panelWorkorder()
|
||||
get = get_input()
|
||||
toObject.client(ws, get)
|
||||
|
||||
@sockets.route('/ws_panel')
|
||||
def ws_panel(ws):
|
||||
'''
|
||||
@name 面板接口ws入口
|
||||
@author hwliang<2021-07-24>
|
||||
@param ws<ws_parameter> websocket会话对像
|
||||
@return void
|
||||
'''
|
||||
comReturn = comm.local()
|
||||
if comReturn: return comReturn
|
||||
|
||||
get = ws.receive()
|
||||
get = json.loads(get)
|
||||
if not check_csrf_websocket(ws,get): return
|
||||
|
||||
while True:
|
||||
pdata = ws.receive()
|
||||
if pdata is '{}': break
|
||||
data = json.loads(pdata)
|
||||
get = public.to_dict_obj(data)
|
||||
get._ws = ws
|
||||
p = threading.Thread(target=ws_panel_thread,args=(get,))
|
||||
p.start()
|
||||
|
||||
def ws_panel_thread(get):
|
||||
'''
|
||||
@name 面板管理ws线程
|
||||
@author hwliang<2021-07-24>
|
||||
@param get<dict> 请求参数
|
||||
@return void
|
||||
'''
|
||||
|
||||
if not hasattr(get, 'ws_callback'):
|
||||
get._ws.send(public.getJson(public.return_status_code(1001, 'ws_callback')))
|
||||
return
|
||||
if not hasattr(get, 'mod_name'):
|
||||
get._ws.send(public.getJson(public.return_status_code(1001, 'mod_name')))
|
||||
return
|
||||
if not hasattr(get, 'def_name'):
|
||||
get._ws.send(public.getJson(public.return_status_code(1001, 'def_name')))
|
||||
return
|
||||
get.mod_name = get.mod_name.strip()
|
||||
get.def_name = get.def_name.strip()
|
||||
check_str = '{}{}'.format(get.mod_name, get.def_name)
|
||||
if not re.match("^\w+$", check_str) or get.mod_name in ['public', 'common', 'db', 'db_mysql', 'downloadFile',
|
||||
'jobs']:
|
||||
get._ws.send(public.getJson(public.return_status_code(1000, '不安全的mod_name,def_name参数内容')))
|
||||
return
|
||||
if not hasattr(get, 'args'):
|
||||
get._ws.send(public.getJson(public.return_status_code(1001, 'args')))
|
||||
return
|
||||
|
||||
mod_file = '{}/{}.py'.format(public.get_class_path(), get.mod_name)
|
||||
if not os.path.exists(mod_file):
|
||||
get._ws.send(public.getJson(public.return_status_code(1000, '指定模块{}不存在'.format(get.mod_name))))
|
||||
return
|
||||
_obj = public.get_script_object(mod_file)
|
||||
if not _obj:
|
||||
get._ws.send(public.getJson(public.return_status_code(1000, '指定模块{}不存在'.format(get.mod_name))))
|
||||
return
|
||||
_cls = getattr(_obj, get.mod_name)
|
||||
if not _cls:
|
||||
get._ws.send(
|
||||
public.getJson(public.return_status_code(1000, '在{}模块中没有找到{}对像'.format(get.mod_name, get.mod_name))))
|
||||
return
|
||||
_def = getattr(_cls(), get.def_name)
|
||||
if not _def:
|
||||
get._ws.send(
|
||||
public.getJson(public.return_status_code(1000, '在{}对像中没有找到{}方法'.format(get.mod_name, get.def_name))))
|
||||
return
|
||||
result = {
|
||||
'callback': get.ws_callback,
|
||||
'result': _def(public.to_dict_obj(get.args))
|
||||
}
|
||||
get._ws.send(public.getJson(result))
|
||||
|
||||
|
||||
@sockets.route('/ws_project')
|
||||
def ws_project(ws):
|
||||
'''
|
||||
@name 项目管理ws入口
|
||||
@author hwliang<2021-07-24>
|
||||
@param ws<ws_parameter> websocket会话对像
|
||||
@return void
|
||||
'''
|
||||
comReturn = comm.local()
|
||||
if comReturn: return comReturn
|
||||
get = ws.receive()
|
||||
get = json.loads(get)
|
||||
if not check_csrf_websocket(ws,get): return
|
||||
|
||||
from panelProjectController import ProjectController
|
||||
project_obj = ProjectController()
|
||||
while True:
|
||||
pdata = ws.receive()
|
||||
if pdata in '{}': break
|
||||
get = public.to_dict_obj(json.loads(pdata))
|
||||
get._ws = ws
|
||||
p = threading.Thread(target=ws_project_thread, args=(project_obj, get))
|
||||
p.start()
|
||||
|
||||
|
||||
def ws_project_thread(_obj, get):
|
||||
'''
|
||||
@name 项目管理ws线程
|
||||
@author hwliang<2021-07-24>
|
||||
@param _obj<ProjectController> 项目管理控制器对像
|
||||
@param get<dict> 请求参数
|
||||
@return void
|
||||
'''
|
||||
if not hasattr(get, 'ws_callback'):
|
||||
get._ws.send(public.getJson(public.return_status_code(1001, 'ws_callback')))
|
||||
return
|
||||
result = {
|
||||
'callback': get.ws_callback,
|
||||
'result': _obj.model(get)
|
||||
}
|
||||
get._ws.send(public.getJson(result))
|
||||
|
||||
|
||||
import subprocess
|
||||
sock_pids = {}
|
||||
@sockets.route('/sock_shell')
|
||||
def sock_shell(ws):
|
||||
'''
|
||||
@name 执行指定命令,实时输出命令执行结果
|
||||
@author hwliang<2021-07-19>
|
||||
@return void
|
||||
|
||||
示例:
|
||||
p = new WebSocket('ws://192.168.1.247:8888/sock_shell')
|
||||
p.send('ping www.bt.cn -c 100')
|
||||
'''
|
||||
comReturn = comm.local()
|
||||
if comReturn:
|
||||
ws.send(str(comReturn))
|
||||
return
|
||||
kill_closed()
|
||||
get = ws.receive()
|
||||
get = json.loads(get)
|
||||
if not check_csrf_websocket(ws,get): return
|
||||
|
||||
t = None
|
||||
try:
|
||||
while True:
|
||||
cmdstring = ws.receive()
|
||||
if cmdstring in ['stop', 'error'] or not cmdstring:
|
||||
break
|
||||
t = threading.Thread(target=sock_recv, args=(cmdstring, ws))
|
||||
t.start()
|
||||
kill_closed()
|
||||
except:
|
||||
kill_closed()
|
||||
|
||||
def kill_closed():
|
||||
'''
|
||||
@name 关闭已关闭的连接
|
||||
@author hwliang<2021-07-24>
|
||||
@return void
|
||||
'''
|
||||
global sock_pids
|
||||
import psutil
|
||||
pids = psutil.pids()
|
||||
keys = sock_pids.copy().keys()
|
||||
for pid in keys:
|
||||
logging.debug("PID: {} , sock_stat: {}".format(pid, sock_pids[pid].closed))
|
||||
if not sock_pids[pid].closed: continue
|
||||
|
||||
if pid in pids:
|
||||
try:
|
||||
p = psutil.Process(pid)
|
||||
for cp in p.children():
|
||||
cp.kill()
|
||||
p.kill()
|
||||
logging.debug("killed: {}".format(pid))
|
||||
sock_pids.pop(pid)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
sock_pids.pop(pid)
|
||||
|
||||
|
||||
def sock_recv(cmdstring, ws):
|
||||
global sock_pids
|
||||
try:
|
||||
p = subprocess.Popen(cmdstring + " 2>&1", close_fds=True, shell=True, bufsize=4096, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
sock_pids[p.pid] = ws
|
||||
kill_closed()
|
||||
while p.poll() is None:
|
||||
ws.send(p.stdout.readline().decode())
|
||||
ws.send(p.stdout.read().decode())
|
||||
except:
|
||||
kill_closed()
|
||||
|
||||
|
||||
@app.route('/close_sock_shell', methods=method_all)
|
||||
def close_sock_shell():
|
||||
'''
|
||||
@name 关闭指定命令
|
||||
@author hwliang<2021-07-19>
|
||||
@param cmdstring<string> 完整命令行
|
||||
@return dict
|
||||
示例:
|
||||
$.post('/close_sock_shell',{cmdstring:'ping www.bt.cn -c 100'})
|
||||
'''
|
||||
comReturn = comm.local()
|
||||
if comReturn: return comReturn
|
||||
args = get_input()
|
||||
cmdstring = args.cmdstring.strip()
|
||||
skey = public.md5(cmdstring)
|
||||
pid = cache.get(skey)
|
||||
if not pid:
|
||||
return json.dumps(public.return_data(False, [], error_msg='指定sock已终止!')), json_header
|
||||
os.kill(pid, 9)
|
||||
cache.delete(skey)
|
||||
return json.dumps(public.return_data(True, '操作成功!')), json_header
|
||||
|
||||
def check_csrf_websocket(ws,args):
|
||||
'''
|
||||
@name 检查websocket是否被csrf攻击
|
||||
@author hwliang<2021-07-24>
|
||||
@param ws<WebSocket> websocket对像
|
||||
@return void
|
||||
'''
|
||||
if g.is_aes: return True
|
||||
is_success = True
|
||||
if not 'x-http-token' in args:
|
||||
is_success = False
|
||||
|
||||
if is_success:
|
||||
if session['request_token_head'] != args['x-http-token']:
|
||||
is_success = False
|
||||
|
||||
# if is_success:
|
||||
# cookie_token = request.cookies.get('request_token')
|
||||
# if cookie_token != session['request_token']:
|
||||
# is_success = False
|
||||
|
||||
if not is_success:
|
||||
ws.send('token error')
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
@sockets.route('/webssh')
|
||||
def webssh(ws):
|
||||
# 宝塔终端连接
|
||||
comReturn = comm.local()
|
||||
if comReturn:
|
||||
ws.send(str(comReturn))
|
||||
return
|
||||
if not ws: return 'False'
|
||||
get = ws.receive()
|
||||
if not get: return
|
||||
get = json.loads(get)
|
||||
if not check_csrf_websocket(ws,get):
|
||||
return
|
||||
|
||||
import ssh_terminal
|
||||
sp = ssh_terminal.ssh_host_admin()
|
||||
if 'host' in get:
|
||||
ssh_info = {}
|
||||
ssh_info['host'] = get['host'].strip()
|
||||
if 'port' in get:
|
||||
ssh_info['port'] = int(get['port'])
|
||||
if 'username' in get:
|
||||
ssh_info['username'] = get['username'].strip()
|
||||
if 'password' in get:
|
||||
ssh_info['password'] = get['password'].strip()
|
||||
if 'pkey' in get:
|
||||
ssh_info['pkey'] = get['pkey'].strip()
|
||||
|
||||
if get['host'] in ['127.0.0.1', 'localhost'] and 'port' not in ssh_info:
|
||||
ssh_info = sp.get_ssh_info('127.0.0.1')
|
||||
if not ssh_info: ssh_info = sp.get_ssh_info('localhost')
|
||||
if not ssh_info: ssh_info = {"host": "127.0.0.1"}
|
||||
ssh_info['port'] = public.get_ssh_port()
|
||||
else:
|
||||
ssh_info = sp.get_ssh_info('127.0.0.1')
|
||||
if not ssh_info: ssh_info = sp.get_ssh_info('localhost')
|
||||
if not ssh_info: ssh_info = {"host": "127.0.0.1"}
|
||||
ssh_info['port'] = public.get_ssh_port()
|
||||
|
||||
if not ssh_info['host'] in ['127.0.0.1', 'localhost']:
|
||||
if not 'username' in ssh_info:
|
||||
ssh_info = sp.get_ssh_info(ssh_info['host'])
|
||||
if not ssh_info:
|
||||
ws.send('The specified host information is not found, please add it again!')
|
||||
return
|
||||
p = ssh_terminal.ssh_terminal()
|
||||
p.run(ws, ssh_info)
|
||||
del (p)
|
||||
if not ws.closed:
|
||||
ws.close()
|
||||
return 'False'
|
||||
|
||||
|
||||
# --------------------- websocket END -------------------------- #
|
||||
|
||||
@@ -1815,7 +1815,19 @@ html .menu .menu_exit:hover {
|
||||
|
||||
.bt-w-con {
|
||||
margin-left: 170px;
|
||||
position: relative
|
||||
position: relative;
|
||||
padding: 7px 15px;
|
||||
}
|
||||
.bt-w-con .bt-w-item{
|
||||
height: 100%;
|
||||
display:none;
|
||||
}
|
||||
.bt-w-con .bt-w-item.active{
|
||||
display:block;
|
||||
}
|
||||
.taskcon{
|
||||
height: 500px;
|
||||
overflow: auto;
|
||||
}
|
||||
.mes_channel .bt-w-con {
|
||||
margin-left: 110px;
|
||||
@@ -3115,7 +3127,6 @@ html .menu .menu_exit:hover {
|
||||
vertical-align: middle;
|
||||
padding: 5px 10px;
|
||||
height: 40px;
|
||||
font-size: 12.5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.table>tbody{
|
||||
@@ -9934,6 +9945,16 @@ select[name="network-io"]{
|
||||
margin-left: 5px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.command_output_pre{
|
||||
white-space: pre-line;
|
||||
background: rgb(51, 51, 51);
|
||||
color: rgb(236, 236, 236);
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
border: none;
|
||||
border-radius: 1px;
|
||||
}
|
||||
/*批量创建站点end*/
|
||||
|
||||
.custom_layer .layui-layer-content .tab-body .tab-con{
|
||||
@@ -10288,3 +10309,63 @@ background:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODIiIGhlaWdodD0iODIiIHh
|
||||
margin-right: 10px;
|
||||
}
|
||||
/* 企业版支付end */
|
||||
.commonly_software{
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
margin-bottom: 15px;
|
||||
color:#666;
|
||||
}
|
||||
.commonly_software .commonly_software_title{
|
||||
display: inline-block;
|
||||
padding-left: 5px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
.commonly_software .commonly_software_list{
|
||||
display: inline-block;
|
||||
|
||||
}
|
||||
.commonly_software .commonly_software_list .item{
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
padding: 0 10px;
|
||||
cursor: pointer;
|
||||
border-radius: 3px;
|
||||
transition: all 500ms;
|
||||
position: relative;
|
||||
}
|
||||
.commonly_software .commonly_software_list .item:hover{
|
||||
color: #20A53A;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.commonly_software .commonly_software_list .item img{
|
||||
max-width: 22px;
|
||||
margin-right: 5px;
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
vertical-align: middle;
|
||||
margin-top: -2.5px;
|
||||
}
|
||||
|
||||
.commonly_software .commonly_software_list .item span{
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
color:#666;
|
||||
}
|
||||
.pro_introduce_content .item{
|
||||
position: relative;
|
||||
}
|
||||
.pro_introduce_content .item .success_icon{
|
||||
position: absolute;
|
||||
display: block;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
margin-top: -8px;
|
||||
width: 6px;
|
||||
height: 12px;
|
||||
border: solid #20a532;
|
||||
border-width: 0 1.5px 1.5px 0;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
.pro_introduce_content .item span:nth-child(2){
|
||||
padding-left: 14px;
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
+163
-167
@@ -883,177 +883,173 @@ $(".dropdown ul li a").click(function(){
|
||||
})
|
||||
|
||||
|
||||
|
||||
//备份
|
||||
function toBackup(type){
|
||||
var sMsg = "";
|
||||
switch(type){
|
||||
case 'sites':
|
||||
sMsg = lan.crontab.backup_site;
|
||||
sType = "sites";
|
||||
break;
|
||||
case 'databases':
|
||||
sMsg = lan.crontab.backup_database;
|
||||
sType = "databases";
|
||||
break;
|
||||
case 'logs':
|
||||
sMsg = lan.crontab.backup_log;
|
||||
sType = "sites";
|
||||
break;
|
||||
case 'path':
|
||||
sMsg = lan.crontab.dir_bak;
|
||||
sType = "sites";
|
||||
break;
|
||||
}
|
||||
var data='type='+sType
|
||||
$.post('/crontab?action=GetDataList',data,function(rdata){
|
||||
$(".planname input[name='name']").attr('readonly','true').css({"background-color":"#f6f6f6","color":"#666"});
|
||||
if(type != 'path'){
|
||||
var sOpt = "",sOptBody = '';
|
||||
if(rdata.data.length == 0){
|
||||
$(".planname input[name='name']").val('');
|
||||
layer.msg(lan.public.list_empty,{icon:2})
|
||||
return
|
||||
}
|
||||
for(var i=0;i<rdata.data.length;i++){
|
||||
if(i==0){
|
||||
$(".planname input[name='name']").val(sMsg+'['+rdata.data[i].name+']');
|
||||
}
|
||||
sOpt += '<li><a role="menuitem" tabindex="-1" href="javascript:;" value="'+rdata.data[i].name+'">'+rdata.data[i].name+'['+rdata.data[i].ps+']</a></li>';
|
||||
}
|
||||
sOptBody ='<div class="dropdown pull-left mr20">\
|
||||
<button class="btn btn-default dropdown-toggle" type="button" id="backdata" data-toggle="dropdown" style="width:auto">\
|
||||
<b id="sName" val="'+rdata.data[0].name+'">'+rdata.data[0].name+'['+rdata.data[0].ps+']</b> <span class="caret"></span>\
|
||||
</button>\
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="backdata">\
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="ALL">'+lan.public.all+'</a></li>\
|
||||
'+sOpt+'\
|
||||
</ul>\
|
||||
</div>'
|
||||
}else{
|
||||
$(".planname input[name='name']").val(sMsg+'[/www/wwwroot/]');
|
||||
sOptBody = '<div class="info-r" style="display: inline-block;float: left;margin-right: 25px;"><input id="inputPath" class="bt-input-text mr5" type="text" name="path" value="/www/wwwroot/" placeholder="'+lan.crontab.dir_bak+'" style="width:208px;height:33px;"><span class="glyphicon glyphicon-folder-open cursor" onclick="bt.select_path(\'inputPath\')"></span></div>'
|
||||
setCookie('default_dir_path','/www/wwwroot/');
|
||||
setCookie('path_dir_change','/www/wwwroot/');
|
||||
setInterval(function(){
|
||||
if(getCookie('path_dir_change') != getCookie('default_dir_path')){
|
||||
var path_dir_change = getCookie('path_dir_change')
|
||||
$(".planname input").val(lan.crontab.dir_bak+'['+getCookie('path_dir_change')+']');
|
||||
setCookie('default_dir_path',path_dir_change);
|
||||
}
|
||||
},500);
|
||||
}
|
||||
var orderOpt = ''
|
||||
for (var i=0;i<rdata.orderOpt.length;i++){
|
||||
orderOpt += '<li><a role="menuitem" tabindex="-1" href="javascript:;" value="'+rdata.orderOpt[i].value+'">'+rdata.orderOpt[i].name+'</a></li>'
|
||||
}
|
||||
|
||||
|
||||
|
||||
var sBody = sOptBody + '<div class="textname pull-left mr20">'+lan.crontab.backup_to+'</div>\
|
||||
<div class="dropdown planBackupTo pull-left mr20">\
|
||||
<button class="btn btn-default dropdown-toggle" type="button" id="excode" data-toggle="dropdown" style="width:auto;">\
|
||||
<b val="localhost">'+lan.crontab.disk+'</b> <span class="caret"></span>\
|
||||
</button>\
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="excode">\
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="localhost">'+lan.crontab.disk+'</a></li>\
|
||||
'+ orderOpt +'\
|
||||
</ul>\
|
||||
</div>\
|
||||
<div class="textname pull-left mr20">'+lan.crontab.save_new+'</div><div class="plan_hms pull-left mr20 bt-input-text">\
|
||||
<span><input type="number" name="save" id="save" value="3" maxlength="4" max="100" min="1"></span>\
|
||||
<span class="name">'+lan.crontab.copies+'</span>\
|
||||
</div>';
|
||||
if (type == 'sites' || type == 'path' || type == 'databases') {
|
||||
$.post('/config?action=get_settings',data,function(rdata){
|
||||
var messageChannelDom = '', messageChannelBtnText = '', channelInitVal = ''
|
||||
if(rdata.user_mail.user_name && rdata.dingding.dingding) {
|
||||
messageChannelBtnText = 'All'
|
||||
channelInitVal= 'user_name,dingding'
|
||||
messageChannelDom = '<li><a role="menuitem" tabindex="-1" href="javascript:;" value="dingding,mail">All</a></li><li><a role="menuitem" tabindex="-1" href="javascript:;" value="dingding">钉钉</a></li><li><a role="menuitem" tabindex="-1" href="javascript:;" value="mail">Email</a></li>'
|
||||
} else if(!rdata.user_mail.user_name && !rdata.dingding.dingding){
|
||||
messageChannelBtnText = 'No Data'
|
||||
channelInitVal= ''
|
||||
messageChannelDom += '<li><a role="menuitem" tabindex="-1" href="javascript:;" value="">No Data</a></li>'
|
||||
} else if(rdata.dingding.dingding) {
|
||||
messageChannelBtnText = '钉钉'
|
||||
channelInitVal= 'dingding'
|
||||
messageChannelDom += '<li><a role="menuitem" tabindex="-1" href="javascript:;" value="dingding">钉钉</a></li>'
|
||||
} else if(rdata.user_mail.user_name) {
|
||||
messageChannelBtnText = 'Email'
|
||||
channelInitVal= 'mail'
|
||||
messageChannelDom += '<li><a role="menuitem" tabindex="-1" href="javascript:;" value="mail">Email</a></li>'
|
||||
}
|
||||
sBody += '<p class="clearfix plan">\
|
||||
<div class="typename pull-left mr20 text-right" style="font-size: 14px;">Backup reminder</div>\
|
||||
<div class="dropdown planBackupTo pull-left mr20" style="display:'+ (type === 'logs'?'none':'inline-block') +'" id="notice">\
|
||||
<button class="btn btn-default dropdown-toggle" type="button" id="excode" data-toggle="dropdown" style="width:180px;">\
|
||||
<b val="0">No notice</b> <span class="caret"></span>\
|
||||
</button>\
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="excode">\
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="0">No notice</a></li>\
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="1">Notify on failure</a></li>\
|
||||
</ul>\
|
||||
</div>\
|
||||
var sMsg = "";
|
||||
switch(type){
|
||||
case 'sites':
|
||||
sMsg = lan.crontab.backup_site;
|
||||
sType = "sites";
|
||||
break;
|
||||
case 'databases':
|
||||
sMsg = lan.crontab.backup_database;
|
||||
sType = "databases";
|
||||
break;
|
||||
case 'logs':
|
||||
sMsg = lan.crontab.backup_log;
|
||||
sType = "sites";
|
||||
break;
|
||||
case 'path':
|
||||
sMsg = lan.crontab.dir_bak;
|
||||
sType = "sites";
|
||||
break;
|
||||
}
|
||||
var data='type='+sType
|
||||
$.post('/crontab?action=GetDataList',data,function(rdata){
|
||||
$(".planname input[name='name']").attr('readonly','true').css({"background-color":"#f6f6f6","color":"#666"});
|
||||
if(type != 'path'){
|
||||
var sOpt = "",sOptBody = '';
|
||||
if(rdata.data.length == 0){
|
||||
layer.msg(lan.public.list_empty,{icon:2})
|
||||
return
|
||||
}
|
||||
for(var i=0;i<rdata.data.length;i++){
|
||||
if(type === 'logs'){
|
||||
$(".planname input[name='name']").val(sMsg+'[ALL]');
|
||||
}else{
|
||||
if(i ==0){
|
||||
$(".planname input[name='name']").val(sMsg+'['+rdata.data[i].name+']');
|
||||
}
|
||||
}
|
||||
sOpt += '<li><a role="menuitem" tabindex="-1" href="javascript:;" value="'+rdata.data[i].name+'">'+rdata.data[i].name+'['+rdata.data[i].ps+']</a></li>';
|
||||
}
|
||||
sOptBody ='<div class="dropdown pull-left mr20">\
|
||||
<button class="btn btn-default dropdown-toggle" type="button" id="backdata" data-toggle="dropdown" style="width:auto">\
|
||||
<b id="sName" val="'+ (type === 'logs'?'ALL':rdata.data[0].name) +'">'+ (type === 'logs'?'ALL':(rdata.data[0].name +'['+rdata.data[0].ps+']')) +'</b> <span class="caret"></span>\
|
||||
</button>\
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="backdata">\
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="ALL">'+lan.public.all+'</a></li>\
|
||||
'+sOpt+'\
|
||||
</ul>\
|
||||
</div>'
|
||||
}else{
|
||||
$(".planname input[name='name']").val(sMsg+'[/www/wwwroot/]');
|
||||
sOptBody = '<div class="info-r" style="display: inline-block;float: left;margin-right: 25px;"><input id="inputPath" class="bt-input-text mr5" type="text" name="path" value="/www/wwwroot/" placeholder="'+lan.crontab.dir_bak+'" style="width:208px;height:33px;"><span class="glyphicon glyphicon-folder-open cursor" onclick="ChangePath("inputPath")"></span></div>'
|
||||
setCookie('default_dir_path','/www/wwwroot/');
|
||||
setCookie('path_dir_change','/www/wwwroot/');
|
||||
setInterval(function(){
|
||||
if(getCookie('path_dir_change') != getCookie('default_dir_path')){
|
||||
var path_dir_change = getCookie('path_dir_change')
|
||||
$(".planname input").val(lan.crontab.dir_bak+'['+getCookie('path_dir_change')+']');
|
||||
setCookie('default_dir_path',path_dir_change);
|
||||
}
|
||||
},500);
|
||||
}
|
||||
var orderOpt = ''
|
||||
for (var i=0;i<rdata.orderOpt.length;i++){
|
||||
orderOpt += '<li><a role="menuitem" tabindex="-1" href="javascript:;" value="'+rdata.orderOpt[i].value+'">'+rdata.orderOpt[i].name+'</a></li>'
|
||||
}
|
||||
var save_num = 3;
|
||||
if(type === 'logs'){
|
||||
$('#cycle b').attr('val','day').text(lan.crontab.daily);
|
||||
$('.planweek').hide();
|
||||
$('[name="hour"]').val(0);
|
||||
$('[name="minute"]').val(1);
|
||||
// $('#implement').parent().after('<div class="clearfix plan" id="logs_tips"><span class="typename controls c4 pull-left f14 text-right mr20">提示</span><div style="line-height:34px">根据网络安全法第二十一条规定,网络日志应留存不少于六个月。</div></div>')
|
||||
save_num = 180;
|
||||
}else{
|
||||
$('#logs_tips').remove();
|
||||
}
|
||||
var sBody = sOptBody + '<div class="textname pull-left mr20" style="display:'+ (type === 'logs'?'none':'inline-block') +'">'+lan.crontab.backup_to+'</div>\
|
||||
<div class="dropdown planBackupTo pull-left mr20" style="display:'+ (type === 'logs'?'none':'inline-block') +'" id="saveAddServerDiskToLocal">\
|
||||
<button class="btn btn-default dropdown-toggle" type="button" id="excode" data-toggle="dropdown" style="width:auto;">\
|
||||
<b val="localhost">'+lan.crontab.disk+'</b> <span class="caret"></span>\
|
||||
</button>\
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="excode">\
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="localhost">'+lan.crontab.disk+'</a></li>\
|
||||
'+ orderOpt +'\
|
||||
</ul>\
|
||||
</div>\
|
||||
<div class="textname pull-left mr20">'+lan.crontab.save_new+'</div><div class="plan_hms pull-left mr20 bt-input-text">\
|
||||
<span><input type="number" name="save" id="save" value="'+save_num+'" maxlength="4" max="100" min="1"></span>\
|
||||
</div>';
|
||||
if (type == 'sites' || type == 'path' || type == 'databases') {
|
||||
$.post('/config?action=get_settings',data,function(rdata){
|
||||
var messageChannelDom = '', messageChannelBtnText = '', channelInitVal = ''
|
||||
if(rdata.user_mail.user_name && rdata.dingding.dingding) {
|
||||
messageChannelBtnText = 'ALL'
|
||||
channelInitVal= 'user_name,dingding'
|
||||
messageChannelDom = '<li><a role="menuitem" tabindex="-1" href="javascript:;" value="dingding,mail">ALL</a></li><li><a role="menuitem" tabindex="-1" href="javascript:;" value="dingding">钉钉</a></li><li><a role="menuitem" tabindex="-1" href="javascript:;" value="mail">邮箱</a></li>'
|
||||
} else if(!rdata.user_mail.user_name && !rdata.dingding.dingding){
|
||||
messageChannelBtnText = 'No Data'
|
||||
channelInitVal= ''
|
||||
messageChannelDom += '<li><a role="menuitem" tabindex="-1" href="javascript:;" value="">No Data</a></li>'
|
||||
} else if(rdata.dingding.dingding) {
|
||||
messageChannelBtnText = '钉钉'
|
||||
channelInitVal= 'dingding'
|
||||
messageChannelDom += '<li><a role="menuitem" tabindex="-1" href="javascript:;" value="dingding">钉钉</a></li>'
|
||||
} else if(rdata.user_mail.user_name) {
|
||||
messageChannelBtnText = 'Email'
|
||||
channelInitVal= 'mail'
|
||||
messageChannelDom += '<li><a role="menuitem" tabindex="-1" href="javascript:;" value="mail">Email</a></li>'
|
||||
}
|
||||
sBody += '<p class="clearfix plan">\
|
||||
<div class="textname pull-left mr20" style="width: 120px;text-align: right; font-size: 14px;">Backup reminder</div>\
|
||||
<div class="dropdown planBackupTo pull-left mr20" style="display:'+ (type === 'logs'?'none':'inline-block') +'" id="notice">\
|
||||
<button class="btn btn-default dropdown-toggle" type="button" id="excode" data-toggle="dropdown" style="width:180px;">\
|
||||
<b val="0">No notice</b> <span class="caret"></span>\
|
||||
</button>\
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="excode">\
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="0">No notice</a></li>\
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="1">Notify on failure</a></li>\
|
||||
</ul>\
|
||||
</div>\
|
||||
<div class="textname pull-left mr20" style="font-size: 14px;display:none;" id="messageChannelBox">Notification</div>\
|
||||
<div class="dropdown planBackupTo pull-left mr20" style="display:none;" id="notice_channel">\
|
||||
<button class="btn btn-default dropdown-toggle" type="button" id="excode" data-toggle="dropdown" style="width:auto;">\
|
||||
<b val="'+channelInitVal+'">'+ messageChannelBtnText +'</b> <span class="caret"></span>\
|
||||
</button>\
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="excode">\
|
||||
'+messageChannelDom+'\
|
||||
</ul>\
|
||||
</div>\
|
||||
</div>\
|
||||
<a role="menuitem" tabindex="-1" href="javascript:;" onclick="open_three_channel_auth()" value="0" style="color: #20a53a;">Set notifications</a>\
|
||||
<span id="selnoticeBox" onclick="selSave_local()"><input type="checkbox" value="0" style="margin-left: 20px;margin-right: 10px;" id="save_local">Keep local backup</span>\
|
||||
</p>';
|
||||
if(type == 'sites' || type == "path") {
|
||||
sBody += '<p class="clearfix plan">\
|
||||
<div class="typename pull-left mr20 text-right" style="font-size: 14px;">'+lan.crontab.exclusion_rule+'</div>\
|
||||
<div class="dropdown planBackupTo pull-left mr20">\
|
||||
<span><textarea style=" height: 120px;width:500px;line-height:22px;" class="bt-input-text" type="text" name="sBody" id="exclude" placeholder="'+lan.crontab.exclusion_rule_tips+'\ndata/config.php\nstatic/upload\n *.log\n"></textarea></span>\
|
||||
</div>\
|
||||
</p>';
|
||||
}
|
||||
$("#implement").html(sBody);
|
||||
getselectname();
|
||||
})
|
||||
}else{
|
||||
$("#implement").html('<div></div>');
|
||||
sBody += '<p class="clearfix plan">\
|
||||
<div class="typename pull-left mr20 text-right" style="font-size: 14px;">'+lan.crontab.exclusion_rule+'</div>\
|
||||
<div class="dropdown planBackupTo pull-left mr20">\
|
||||
<span><textarea style=" height: 120px;width:500px;line-height:22px;" class="bt-input-text" type="text" name="sBody" id="exclude" placeholder="'+lan.crontab.exclusion_rule_tips+'\ndata/config.php\nstatic/upload\n *.log\n"></textarea></span>\
|
||||
</div>\
|
||||
</p>';
|
||||
$("#implement").html(sBody);
|
||||
}
|
||||
$("#implement").on('click','.dropdown ul li a',function(ev){
|
||||
var val = $(this).attr('value');
|
||||
console.log(val)
|
||||
$("#sName").attr({'value':val}).text($(this).text())
|
||||
$(".planname input[name='name']").val(sMsg+'['+val+']');
|
||||
});
|
||||
if(type == "path"){
|
||||
$('.planname input').attr('readonly',false).removeAttr('style');
|
||||
}
|
||||
$("#exclude").focus(function(){
|
||||
var _this = $(this), tips = _this.attr('placeholder'),
|
||||
tipss = ''+lan.crontab.exclusion_rule_tips+'</br>data/config.php</br>static/upload</br> *.log</br>';
|
||||
_this.attr('placeholder', '');
|
||||
var loadT = layer.tips(tipss, _this, {
|
||||
tips: [1, '#20a53a'],
|
||||
time: 0,
|
||||
area: _this[0].clientWidth + 'px'
|
||||
});
|
||||
$(this).one('blur', function () {
|
||||
$(this).attr('placeholder', tips);
|
||||
layer.close(loadT);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
<div class="textname pull-left mr20" style="font-size: 14px;display:none;" id="messageChannelBox">Notification</div>\
|
||||
<div class="dropdown planBackupTo pull-left mr20" style="display:none;" id="notice_channel">\
|
||||
<button class="btn btn-default dropdown-toggle" type="button" id="excode" data-toggle="dropdown" style="width:auto;">\
|
||||
<b val="'+channelInitVal+'">'+ messageChannelBtnText +'</b> <span class="caret"></span>\
|
||||
</button>\
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="excode">\
|
||||
'+messageChannelDom+'\
|
||||
</ul>\
|
||||
</div>\
|
||||
</div>\
|
||||
<a role="menuitem" tabindex="-1" href="javascript:;" onclick="open_three_channel_auth()" value="0" style="color: #20a53a;">Set notifications</a>\
|
||||
<span id="selnoticeBox" onclick="selSave_local()" style="display:none;"><input type="checkbox" value="0" style="margin-left: 20px;margin-right: 10px;" id="save_local">Keep local backup</span>\
|
||||
</p>';
|
||||
if(type == 'sites' || type == "path") {
|
||||
sBody += '<p class="clearfix plan">\
|
||||
<div class="textname pull-left mr20" style="width: 120px;text-align: right; font-size: 14px;">'+lan.crontab.exclusion_rule+'</div>\
|
||||
<div class="dropdown planBackupTo pull-left mr20">\
|
||||
<span><textarea style=" height: 100px;width:300px;line-height:22px;" class="bt-input-text" type="text" name="sBody" id="exclude" placeholder="'+lan.crontab.exclusion_rule_tips+'\ndata/config.php\nstatic/upload\n *.log\n"></textarea></span>\
|
||||
</div>\
|
||||
</p>';
|
||||
}
|
||||
$("#implement").html(sBody);
|
||||
getselectnoticename();
|
||||
})
|
||||
} else {
|
||||
$("#implement").html('<div></div>');
|
||||
sBody += '<p class="clearfix plan">\
|
||||
<div class="textname pull-left mr20" style="width: 120px;text-align: right; font-size: 14px;">'+lan.crontab.exclusion_rule+'</div>\
|
||||
<div class="dropdown planBackupTo pull-left mr20">\
|
||||
<span><textarea style=" height: 100px;width:300px;line-height:22px;" class="bt-input-text" type="text" name="sBody" id="exclude" placeholder="'+lan.crontab.exclusion_rule_tips+'\ndata/config.php\nstatic/upload\n *.log\n"></textarea></span>\
|
||||
</div>\
|
||||
</p>';
|
||||
$("#implement").html(sBody);
|
||||
getselectname();
|
||||
}
|
||||
$("#implement").on('click','.dropdown ul li a',function(ev){
|
||||
var sName = $("#sName").attr("val");
|
||||
if(!sName) return;
|
||||
$(".planname input[name='name']").val(sMsg+'['+sName+']');
|
||||
});
|
||||
if(type == "path"){
|
||||
$('.planname input').attr('readonly',false).removeAttr('style');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//下拉菜单名称
|
||||
|
||||
@@ -298,12 +298,14 @@ var bt_file = {
|
||||
if(that.uploading){
|
||||
layer.confirm('Do you want to cancel the upload of files? It need to delete the uploaded files manually. Continue?',{title:'Cancel file upload',icon:0},function(indexs){
|
||||
$('.upload_file_body').addClass('active').html('<span>Please drag the file here</span>')
|
||||
$('.file_upload_info').css('display','none').siblings().css('display','block')
|
||||
that.filesList.length = 0
|
||||
});
|
||||
return false;
|
||||
}else{
|
||||
$('.upload_file_body').addClass('active').html('<span>Please drag the file here</span>')
|
||||
that.filesList.length = 0
|
||||
$('.file_upload_info').css('display','none').siblings().css('display','block')
|
||||
return false;
|
||||
}
|
||||
},
|
||||
@@ -609,7 +611,6 @@ var bt_file = {
|
||||
that.loadT.close();
|
||||
}
|
||||
})
|
||||
$('.file_search_config').addClass('hide')
|
||||
e.stopPropagation();
|
||||
})
|
||||
$('.search_path_views').on('click','.file_search_config label',function(e){
|
||||
@@ -4416,13 +4417,13 @@ var bt_file = {
|
||||
});
|
||||
return (paths+path).replace('//','/');
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @descripttion 取扩展名
|
||||
* @return: 返回扩展名
|
||||
*/
|
||||
get_ext_name:function(fileName){
|
||||
var extArr = fileName.split(".");
|
||||
var extArr = fileName.split(".");
|
||||
var exts = ["folder", "folder-unempty", "sql", "c", "cpp", "cs", "flv", "css", "js", "htm", "html", "java", "log", "mht", "php", "url", "xml", "ai", "bmp", "cdr", "gif", "ico", "jpeg", "jpg", "JPG", "png", "psd", "webp", "ape", "avi", "mkv", "mov", "mp3", "mp4", "mpeg", "mpg", "rm", "rmvb", "swf", "wav", "webm", "wma", "wmv", "rtf", "docx", "fdf", "potm", "pptx", "txt", "xlsb", "xlsx", "7z", "cab", "iso", "rar", "zip", "gz", "bt", "file", "apk", "bookfolder", "folder-empty", "fromchromefolder", "documentfolder", "fromphonefolder", "mix", "musicfolder", "picturefolder", "videofolder", "sefolder", "access", "mdb", "accdb", "fla", "doc", "docm", "dotx", "dotm", "dot", "pdf", "ppt", "pptm", "pot", "xls", "csv", "xlsm"];
|
||||
var extLastName = extArr[extArr.length - 1];
|
||||
for(var i=0; i<exts.length; i++){
|
||||
@@ -4457,7 +4458,7 @@ var bt_file = {
|
||||
/**
|
||||
* @descripttion: 路径过滤
|
||||
* @return: 无返回值
|
||||
*/
|
||||
*/
|
||||
path_check:function(path) {
|
||||
path = path.replace('//', '/');
|
||||
if (path === '/') return path;
|
||||
@@ -4524,7 +4525,7 @@ var bt_file = {
|
||||
if (callback) callback(res);
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
Vendored
+1
-5
File diff suppressed because one or more lines are too long
+268
-46
@@ -1386,7 +1386,7 @@ var aceEditor = {
|
||||
},
|
||||
// 获取文件列表
|
||||
get_file_dir_list:function(obj,callback){
|
||||
var loadT = layer.msg('正在获取文件内容,请稍后...',{time: 0,icon: 16,shade: [0.3, '#000']}),_this = this;
|
||||
var loadT = layer.msg('Getting file content, please wait...',{time: 0,icon: 16,shade: [0.3, '#000']}),_this = this;
|
||||
if(obj['p'] === undefined) obj['p'] = 1;
|
||||
if(obj['showRow'] === undefined) obj['showRow'] = 200;
|
||||
if(obj['sort'] === undefined) obj['sort'] = 'name';
|
||||
@@ -2219,6 +2219,28 @@ function ajax_encrypt(request){
|
||||
}
|
||||
}
|
||||
|
||||
// function ajaxSetup() {
|
||||
// var my_headers = {};
|
||||
// var request_token_ele = document.getElementById("request_token_head");
|
||||
// if (request_token_ele) {
|
||||
// var request_token = request_token_ele.getAttribute('token');
|
||||
// if (request_token) {
|
||||
// my_headers['x-http-token'] = request_token
|
||||
// }
|
||||
// }
|
||||
// request_token_cookie = getCookie('request_token');
|
||||
// if (request_token_cookie) {
|
||||
// my_headers['x-cookie-token'] = request_token_cookie
|
||||
// }
|
||||
//
|
||||
// if (my_headers) {
|
||||
// $.ajaxSetup({
|
||||
// headers: my_headers,
|
||||
// // dataFilter: ajax_decrypt,
|
||||
// // beforeSend: ajax_encrypt
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
function ajaxSetup() {
|
||||
var my_headers = {};
|
||||
var request_token_ele = document.getElementById("request_token_head");
|
||||
@@ -2234,12 +2256,65 @@ function ajaxSetup() {
|
||||
}
|
||||
|
||||
if (my_headers) {
|
||||
$.ajaxSetup({
|
||||
$.ajaxSetup({
|
||||
headers: my_headers,
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
if(!jqXHR.responseText) return;
|
||||
if(typeof(String.prototype.trim) === "undefined"){
|
||||
String.prototype.trim = function()
|
||||
{
|
||||
return String(this).replace(/^\s+|\s+$/g, '');
|
||||
};
|
||||
}
|
||||
|
||||
error_key = 'We need to make sure this has a favicon so that the debugger does';
|
||||
error_find = jqXHR.responseText.indexOf(error_key)
|
||||
if(jqXHR.status == 500 && (jqXHR.responseText.indexOf('An error occurred while the panel was running') != -1 || error_find != -1)){
|
||||
// if(jqXHR.responseText.indexOf('请先绑定宝塔帐号!') != -1){
|
||||
// bt.pub.bind_btname(function(){
|
||||
// window.location.reload();
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
if(error_find != -1){
|
||||
var error_body = jqXHR.responseText.split('<!--')[2].replace('-->','')
|
||||
var tmp = error_body.split('During handling of the above exception, another exception occurred:')
|
||||
error_body = tmp[tmp.length-1];
|
||||
var error_msg = '<div>\
|
||||
<h3 style="margin-bottom: 10px;">出错了,面板运行时发生错误!</h3>\
|
||||
<pre style="height:635px;word-wrap: break-word;white-space: pre-wrap;margin: 0 0 0px">'+error_body.trim()+'</pre>\
|
||||
<ul class="help-info-text">\
|
||||
<li style="list-style: none;"><b>很抱歉,面板运行时意外发生错误,请尝试按以下顺序尝试解除此错误:</b></li>\
|
||||
<li style="list-style: none;">1、在[首页]右上角点击修复面板,并退出面板重新登录。</li>\
|
||||
<li style="list-style: none;">2、如上述尝试未能解除此错误,请截图此窗口到宝塔论坛发贴寻求帮助, 论坛地址:<a class="btlink" href="https://www.bt.cn/bbs" target="_blank">https://www.bt.cn/bbs</a></li>\
|
||||
</ul>\
|
||||
</div>'
|
||||
|
||||
}else{
|
||||
var error_msg = jqXHR.responseText;
|
||||
}
|
||||
$(".layui-layer-padding").parents('.layer-anim').remove();
|
||||
$(".layui-layer-shade").remove();
|
||||
setTimeout(function(){
|
||||
layer.open({
|
||||
title: false,
|
||||
content: error_msg,
|
||||
closeBtn:2,
|
||||
area: ["1000px","800px"],
|
||||
btn:false,
|
||||
shadeClose:false,
|
||||
shade:0.3,
|
||||
success:function(){
|
||||
$('pre').scrollTop(100000000000)
|
||||
}
|
||||
});
|
||||
},100)
|
||||
}
|
||||
}
|
||||
// dataFilter: ajax_decrypt,
|
||||
// beforeSend: ajax_encrypt
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
ajaxSetup();
|
||||
|
||||
@@ -3171,20 +3246,12 @@ function ActionTask() {
|
||||
})
|
||||
}
|
||||
|
||||
function RemoveTask(b) {
|
||||
var a = layer.msg(lan.public.the_del, {
|
||||
icon: 16,
|
||||
time: 0,
|
||||
shade: [0.3, "#000"]
|
||||
});
|
||||
$.post("/files?action=RemoveTask", "id=" + b, function(c) {
|
||||
layer.close(a);
|
||||
layer.msg(c.msg, {
|
||||
icon: c.status ? 1 : 5
|
||||
});
|
||||
}).error(function() {
|
||||
layer.msg(lan.bt.task_close, { icon: 1 });
|
||||
});
|
||||
function RemoveTask(id) {
|
||||
var loadT = bt.load(lan.public.the_del);
|
||||
bt.send('RemoveTask','files/RemoveTask',{id:id},function(res){
|
||||
bt.msg(res)
|
||||
reader_realtime_tasks()
|
||||
})
|
||||
}
|
||||
|
||||
function GetTaskList(a) {
|
||||
@@ -3692,30 +3759,183 @@ function getSpeed(sele) {
|
||||
});
|
||||
}
|
||||
//消息盒子
|
||||
function messagebox() {
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: lan.bt.task_title,
|
||||
area: "750px",
|
||||
closeBtn: 2,
|
||||
shadeClose: false,
|
||||
content: '<div class="bt-form">\
|
||||
<div class="bt-w-main">\
|
||||
<div class="bt-w-menu">\
|
||||
<p class="bgw" id="taskList" onclick="tasklist()">' + lan.bt.task_list + '(<span class="task_count">0</span>)</p>\
|
||||
<p onclick="remind()">' + lan.bt.task_msg + '(<span class="msg_count">0</span>)</p>\
|
||||
<p onclick="execLog()">' + lan.public.exec_log + '</p>\
|
||||
</div>\
|
||||
<div class="bt-w-con pd15">\
|
||||
<div class="taskcon"></div>\
|
||||
</div>\
|
||||
</div>\
|
||||
</div>'
|
||||
});
|
||||
$(".bt-w-menu p").click(function() {
|
||||
$(this).addClass("bgw").siblings().removeClass("bgw");
|
||||
});
|
||||
tasklist();
|
||||
function messagebox(){
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: lan.bt.task_title,
|
||||
area: "680px",
|
||||
closeBtn: 2,
|
||||
shadeClose: false,
|
||||
content: '<div class="bt-form">' +
|
||||
'<div class="bt-w-main">' +
|
||||
'<div class="bt-w-menu">' +
|
||||
'<p class="bgw">'+ lan.bt.task_list +' (<span id="taskNum">0</span>)</p>' +
|
||||
'<p>'+ lan.bt.task_msg +' (<span id="taskCompleteNum">0</span>)</p>' +
|
||||
'<p>'+lan.public.exec_log+'</p>' +
|
||||
'</div>' +
|
||||
'<div class="bt-w-con pd15">' +
|
||||
'<div class="bt-w-item active" id="command_install_list"><ul class="cmdlist"></ul></div>'+
|
||||
'<div class="bt-w-item" id="messageContent"></div>'+
|
||||
'<div class="bt-w-item"><pre id="execLog" class="command_output_pre" style="height: 530px;"></pre></div>'+
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
success: function(layers,indexs){
|
||||
$(layers).find('.bt-w-menu p').on('click',function(){
|
||||
var index = $(this).index()
|
||||
$(this).addClass('bgw').siblings().removeClass('bgw');
|
||||
$(layers).find('.bt-w-con .bt-w-item:eq('+ index +')').addClass('active').siblings().removeClass('active');
|
||||
switch (index) {
|
||||
case 0:
|
||||
reader_realtime_tasks()
|
||||
break;
|
||||
case 1:
|
||||
reader_message_list()
|
||||
break;
|
||||
case 2:
|
||||
var loadT = bt.load('正在获取执行日志,请稍后...')
|
||||
bt.send('GetExecLog','files/GetExecLog',{},function(res){
|
||||
loadT.close();
|
||||
var exec_log = $('#execLog');
|
||||
console.log(exec_log)
|
||||
exec_log.html(res)
|
||||
exec_log[0].scrollTop = exec_log[0].scrollHeight
|
||||
})
|
||||
break;
|
||||
}
|
||||
})
|
||||
reader_realtime_tasks()
|
||||
setTimeout(function(){
|
||||
reader_realtime_tasks()
|
||||
},1000)
|
||||
reader_message_list()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function get_message_data(page,callback){
|
||||
if(typeof page === "function") callback = page,page = 1;
|
||||
var loadT = bt.load('正在获取消息列表,请稍后...');
|
||||
bt.send("getData","data/getData",{
|
||||
tojs:'reader_message_list',
|
||||
table:'tasks',
|
||||
result:'2,4,6,8',
|
||||
limit:'11',
|
||||
search:'1',
|
||||
p:page
|
||||
},function(res){
|
||||
loadT.close();
|
||||
if(callback) callback(res);
|
||||
})
|
||||
}
|
||||
|
||||
function reader_message_list(page){
|
||||
get_message_data(page,function(res){
|
||||
var html = "",f = false,task_count = 0;
|
||||
for (var i = 0; i < res.data.length; i++) {
|
||||
var item = res.data[i];
|
||||
if (item.status !== '1') {
|
||||
task_count ++;
|
||||
continue;
|
||||
}
|
||||
html += '<tr><td><div class="titlename c3">' + item.name + '</span><span class="rs-status">【' + lan.bt.task_ok + '】<span><span class="rs-time">' + lan.bt.time + (item.end - item.start) + lan.bt.s + '</span></div></td><td class="text-right c3">' + item.addtime + '</td></tr>'
|
||||
}
|
||||
var con = '<div class="divtable"><table class="table table-hover">\
|
||||
<thead><tr><th>'+ lan.bt.task_name + '</th><th class="text-right">' + lan.bt.task_time + '</th></tr></thead>\
|
||||
<tbody id="remind">'+ html + '</tbody>\
|
||||
</table></div>\
|
||||
<div class="mtb15" style="height:32px">\
|
||||
<div class="pull-left buttongroup" style="display:none;"><button class="btn btn-default btn-sm mr5 rs-del" disabled="disabled">'+ lan.public.del + '</button><button class="btn btn-default btn-sm mr5 rs-read" disabled="disabled">' + lan.bt.task_tip_read + '</button><button class="btn btn-default btn-sm">' + lan.bt.task_tip_all + '</button></div>\
|
||||
<div id="taskPage" class="page"></div>\
|
||||
</div>';
|
||||
|
||||
|
||||
var msg_count = res.page.match(/\'Pcount\'>.+<\/span>/)[0].replace(/[^0-9]/ig, "");
|
||||
$("#taskCompleteNum").text(parseInt(msg_count) - task_count);
|
||||
$("#messageContent").html(con);
|
||||
$("#taskPage").html(res.page);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function get_realtime_tasks(callback){
|
||||
bt.send('GetTaskSpeed','files/GetTaskSpeed',{},function(res){
|
||||
if(callback) callback(res)
|
||||
})
|
||||
}
|
||||
|
||||
var initTime = null,messageBoxWssock = null;
|
||||
|
||||
function reader_realtime_tasks(refresh){
|
||||
get_realtime_tasks(function(res){
|
||||
var command_install_list = $('#command_install_list'),
|
||||
loading = 'data:image/gif;base64,R0lGODlhDgACAIAAAHNzcwAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFDgABACwAAAAAAgACAAACAoRRACH5BAUOAAEALAQAAAACAAIAAAIChFEAIfkEBQ4AAQAsCAAAAAIAAgAAAgKEUQAh+QQJDgABACwAAAAADgACAAACBoyPBpu9BQA7',
|
||||
html = '',
|
||||
message = res.msg,
|
||||
task = res.task;
|
||||
$('#taskNum').html(typeof res.task === "undefined"?0:res.task.length);
|
||||
if(typeof res.task === "undefined"){
|
||||
html = '<div style="padding:5px;">'+lan.bt.task_not_list+'</div><div style="position: fixed;bottom: 15px;">' + lan.public.task_long_time_not_exec + '</div>'
|
||||
command_install_list.html(html)
|
||||
}else{
|
||||
var shell = '', message_split = message.split("\n");
|
||||
for(var j = 0; j < message_split.length; j++) {
|
||||
shell += message_split[j] + "</br>";
|
||||
}
|
||||
if(command_install_list.find('li').length){
|
||||
if(command_install_list.find('li').length > res.task.length) command_install_list.find('li:eq(0)').remove();
|
||||
if(task[0].status !== '0' && !command_install_list.find('pre').length) command_install_list.find('li:eq(0)').append('<pre class=\'cmd command_output_pre\'>' + shell +'</pre>')
|
||||
messageBoxWssock.el = command_install_list.find('pre');
|
||||
}else{
|
||||
for (var i = 0; i < task.length; i++) {
|
||||
var item = task[i], task_html = '', del_task = '<a style="color:green" onclick="RemoveTask(' + item.id + ')" href="javascript:;">'+ lan.public.del +'</a>',loading_img = "<img src='"+ loading +"'/>";
|
||||
if(item.status === '-1' && item.type === 'download'){
|
||||
task_html = "<div class='line-progress' style='width:" + message.pre + "%'></div><span class='titlename'>" + item.name + "<a style='margin-left:130px;'>" + (ToSize(message.used) + "/" + ToSize(message.total)) + "</a></span><span class='com-progress'>" + message.pre + "%</span><span class='state'>"+ lan.bt.task_downloading +" "+ loading_img +" | "+ del_task +"</span>";
|
||||
}else{
|
||||
task_html += '<span class="titlename">' + item.name + '</span>';
|
||||
task_html += '<span class="state">';
|
||||
if(item.status !== "-1"){
|
||||
task_html += lan.bt.task_sleep + ' | ' + del_task;
|
||||
}else{
|
||||
var is_scan = item.name.indexOf("扫描") !== -1;
|
||||
task_html += (is_scan?lan.bt.task_scan:lan.bt.task_install) + ' ' + loading_img + ' | ' + del_task;
|
||||
}
|
||||
task_html += "</span>";
|
||||
if(item.type !== "download" && item.status === "-1"){
|
||||
task_html += '<pre class=\'cmd command_output_pre\'>' + shell +'</pre>'
|
||||
}
|
||||
}
|
||||
html += "<li>"+ task_html +"</li>";
|
||||
}
|
||||
command_install_list.find('ul').append(html);
|
||||
}
|
||||
if(task[0].status === '0'){
|
||||
setTimeout(function(){
|
||||
reader_realtime_tasks(true)
|
||||
},100)
|
||||
}
|
||||
if(command_install_list.find('pre').length){
|
||||
var pre = command_install_list.find('pre')
|
||||
pre.scrollTop(pre[0].scrollHeight)
|
||||
}
|
||||
if(!refresh){
|
||||
messageBoxWssock = bt_tools.command_line_output({
|
||||
el:'#command_install_list .command_output_pre',
|
||||
area:['100%','200px'],
|
||||
shell:'tail -n 100 -f /tmp/panelExec.log',
|
||||
message:function(res){
|
||||
if(res.indexOf('|-Successify ---Script execution completed---') > -1){
|
||||
setTimeout(function(){
|
||||
reader_realtime_tasks(true)
|
||||
reader_message_list()
|
||||
},100)
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//取执行日志
|
||||
@@ -3986,7 +4206,9 @@ var Term = {
|
||||
},
|
||||
//连接服务器成功
|
||||
on_open:function(ws_event){
|
||||
Term.send(JSON.stringify(Term.ssh_info || {}))
|
||||
var http_token = $("#request_token_head").attr('token');
|
||||
Term.send(JSON.stringify({'x-http-token':http_token}))
|
||||
if(JSON.stringify(Term.ssh_info) !== '{}') Term.send(JSON.stringify(Term.ssh_info))
|
||||
// Term.term.FitAddon.fit();
|
||||
// Term.resize();
|
||||
// var f_path = $("#fileInputPath").val();
|
||||
@@ -4166,10 +4388,10 @@ var Term = {
|
||||
|
||||
// },
|
||||
run: function (ssh_info) {
|
||||
if($("#panel_debug").attr("data") == 'True') {
|
||||
layer.msg('Error: unable to create websocket connection, please close 【Developer mode】 on the settings page!',{icon:2,time:5000});
|
||||
return;
|
||||
}
|
||||
// if($("#panel_debug").attr("data") == 'True') {
|
||||
// layer.msg('Error: unable to create websocket connection, please close 【Developer mode】 on the settings page!',{icon:2,time:5000});
|
||||
// return;
|
||||
// }
|
||||
var loadT = layer.msg('It is loading the files required by the terminal. Please wait...', { icon: 16, time: 0, shade: 0.3 });
|
||||
loadScript([
|
||||
"/static/js/xterm.js"
|
||||
|
||||
@@ -517,9 +517,7 @@ var bt = {
|
||||
}
|
||||
|
||||
if (callback) callback(rdata);
|
||||
}).error(function(e, f) {
|
||||
if (callback) callback('error');
|
||||
});
|
||||
})
|
||||
}
|
||||
},
|
||||
linux_format_param: function(param) {
|
||||
@@ -551,11 +549,11 @@ var bt = {
|
||||
var btnObj = {
|
||||
title: config.title ? config.title : false,
|
||||
shadeClose: config.shadeClose ? config.shadeClose : true,
|
||||
closeBtn: config.closeBtn ? config.closeBtn : 0,
|
||||
closeBtn: config.closeBtn ? config.closeBtn : 2,
|
||||
scrollbar: true,
|
||||
shade: 0.3,
|
||||
shade: 0.3
|
||||
};
|
||||
if (!config.hasOwnProperty('time')) config.time = 2000;
|
||||
if (!config.hasOwnProperty('time')) config.time = 0;
|
||||
if (typeof config.msg == 'string' && bt.contains(config.msg, 'ERROR')) config.time = 0;
|
||||
|
||||
if (config.hasOwnProperty('icon')) {
|
||||
@@ -572,7 +570,7 @@ var bt = {
|
||||
if (config.msg) msg += config.msg;
|
||||
if (config.msg_error) msg += config.msg_error;
|
||||
if (config.msg_solve) msg += config.msg_solve;
|
||||
|
||||
if(config.status) $.extend(btnObj,{closeBtn:0,time:2000});
|
||||
layer.msg(msg, btnObj);
|
||||
},
|
||||
confirm: function(config, callback, callback1) {
|
||||
@@ -3886,7 +3884,10 @@ bt.soft = {
|
||||
bt.soft.pro.get_product_discount_by(config.pid,function(rdata){
|
||||
//rdata = {"36": {"discount": 1, "did": 0, "price": 3564, "name": "正常", "sprice": 3564}, "24": {"discount": 1, "did": 0, "price": 2376, "name": "正常", "sprice": 2376}, "12": {"discount": 1, "did": 0, "price": 1188, "name": "正常", "sprice": 1188}, "6": {"discount": 1, "did": 0, "price": 594, "name": "正常", "sprice": 594}, "3": {"discount": 1, "did": 0, "price": 297, "name": "正常", "sprice": 297}, "1": {"discount": 1, "did": 0, "price": 99, "name": "正常", "sprice": 99}, "pid": "100000045"};
|
||||
if(typeof rdata.status === "boolean"){
|
||||
if(!rdata.status) return false;
|
||||
if(!rdata.status) {
|
||||
bt.msg({status:false, msg:rdata.msg})
|
||||
return false;
|
||||
}
|
||||
}
|
||||
that.product_cache[config.pid] = rdata;
|
||||
setTimeout(function(){ delete that.product_cache[config.pid] },60000);
|
||||
@@ -4020,7 +4021,8 @@ bt.soft = {
|
||||
if (rdata.status === false){
|
||||
bt.set_cookie('force', 1);
|
||||
if (soft) soft.flush_cache();
|
||||
layer.msg(rdata.msg, { icon: 2 });
|
||||
// layer.msg(rdata.msg, { icon: 2 });
|
||||
bt.msg({status:false,msg:rdata.msg})
|
||||
return;
|
||||
}
|
||||
config.pay = parseInt($('#libPay-mode .pay-cycle-btn.active').data('condition'));
|
||||
@@ -4484,7 +4486,8 @@ bt.soft = {
|
||||
if (rdata.status === false) {
|
||||
bt.set_cookie('force', 1);
|
||||
if (soft) soft.flush_cache();
|
||||
layer.msg(rdata.msg, { icon: 2 });
|
||||
// layer.msg(rdata.msg, { icon: 2 });
|
||||
bt.msg({status:false,msg:rdata.msg})
|
||||
return;
|
||||
}
|
||||
$(".pay-wx").html('');
|
||||
@@ -5833,6 +5836,17 @@ bt.site = {
|
||||
if (callback) callback(rdata);
|
||||
})
|
||||
},
|
||||
get_site_error_logs: function (siteName, callback) {
|
||||
var loading = bt.load();
|
||||
bt.send('get_site_errlog', 'site/get_site_errlog', {
|
||||
siteName: siteName
|
||||
}, function (rdata) {
|
||||
loading.close();
|
||||
if (rdata.status !== true) rdata.msg = '';
|
||||
if (rdata.msg == '') rdata.msg = lan.public_backup.no_log;
|
||||
if (callback) callback(rdata);
|
||||
})
|
||||
},
|
||||
get_site_ssl: function(siteName, callback) {
|
||||
var loadT = bt.load(lan.site.the_msg);
|
||||
bt.send('GetSSL', 'site/GetSSL', { siteName: siteName }, function(rdata) {
|
||||
|
||||
+151
-82
@@ -68,7 +68,7 @@ var site_table = bt_tools.table({
|
||||
$('.site-menu p:eq(8)').click();
|
||||
},500);
|
||||
}},
|
||||
{title:lan.site.operate,type:'group',width:118,align:'right',group:[
|
||||
{title:lan.site.operate,type:'group',width:119,align:'right',group:[
|
||||
{
|
||||
title:'WAF',
|
||||
event:function(row,index,ev,key,that){
|
||||
@@ -302,7 +302,7 @@ var site_table = bt_tools.table({
|
||||
if(checked) param[$(this).attr('name')] = checked?1:0;
|
||||
})
|
||||
if(callback) callback(param);
|
||||
},"<div class='options bacth_options'><span class='item'><label><input type='checkbox' name='ftp'><span>FTP</span></label></span><span class='item'><label><input type='checkbox' name='database'><span>" + lan.site.database + "</span></label></span><span class='item'><label><input type='checkbox' name='path'><span>" + lan.site.root_dir + "</span></label></span></div>");
|
||||
},"<div class='options bacth_options'><span class='item'><label><input type='checkbox' name='ftp'><span>FTP</span></label></span><span class='item'><label><input type='checkbox' name='database'><span>" + lan.site.database + "</span></label></span><span class='item' ><label style='margin-right:0'><input type='checkbox' name='path'><span>" + lan.site.root_dir + "</span></label></span></div>");
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -662,54 +662,9 @@ var site = {
|
||||
})
|
||||
}, 1000);
|
||||
},
|
||||
// add_site: function(callback) {
|
||||
// bt.site.add_site(function(rdata) {
|
||||
// if (rdata.siteStatus) {
|
||||
// if(callback) callback(rdata);
|
||||
// //site.get_list();
|
||||
// var html = '';
|
||||
// var ftpData = '';
|
||||
// if (rdata.ftpStatus) {
|
||||
// var list = [];
|
||||
// list.push({ title: lan.site.user, val: rdata.ftpUser });
|
||||
// list.push({ title: lan.site.password, val: rdata.ftpPass });
|
||||
// var item = {};
|
||||
// item.title = lan.site.ftp;
|
||||
// item.list = list;
|
||||
// ftpData = bt.render_ps(item);
|
||||
// }
|
||||
// var sqlData = '';
|
||||
// if (rdata.databaseStatus) {
|
||||
// var list = [];
|
||||
// list.push({ title: lan.site.database_name, val: rdata.databaseUser });
|
||||
// list.push({ title: lan.site.user, val: rdata.databaseUser });
|
||||
// list.push({ title: lan.site.password, val: rdata.databasePass });
|
||||
// var item = {};
|
||||
// item.title = lan.site.database_txt;
|
||||
// item.list = list;
|
||||
// sqlData = bt.render_ps(item);
|
||||
// }
|
||||
// if (ftpData == '' && sqlData == '') {
|
||||
// bt.msg({ msg: lan.site.success_txt, icon: 1 })
|
||||
// } else {
|
||||
// bt.open({
|
||||
// type: 1,
|
||||
// area: '600px',
|
||||
// title: lan.site.success_txt,
|
||||
// closeBtn: 2,
|
||||
// shadeClose: false,
|
||||
// content: "<div class='success-msg'><div class='pic'><img src='/static/img/success-pic.png'></div><div class='suc-con'>" + ftpData + sqlData + "</div></div>"
|
||||
// });
|
||||
|
||||
// if ($(".success-msg").height() < 150) {
|
||||
// $(".success-msg").find("img").css({ "width": "150px", "margin-top": "30px" });
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// bt.msg(rdata);
|
||||
// }
|
||||
// })
|
||||
// },
|
||||
/**
|
||||
* @description 添加站点
|
||||
*/
|
||||
add_site: function (callback) {
|
||||
var add_web = bt_tools.form({
|
||||
data:{}, //用于存储初始值和编辑时的赋值内容
|
||||
@@ -1032,6 +987,11 @@ var site = {
|
||||
},
|
||||
yes:function(indexs){
|
||||
var formValue = !web_tab.active?add_web.$get_form_value():bath_web.$get_form_value();
|
||||
console.log(formValue)
|
||||
if(formValue.webname === ''){
|
||||
bt.msg({status:false,msg:'The website domain name cannot be empty!'})
|
||||
return false;
|
||||
}
|
||||
if(!web_tab.active){ // 创建站点
|
||||
var loading = bt.load();
|
||||
add_web.$get_form_element(true);
|
||||
@@ -1866,6 +1826,7 @@ var site = {
|
||||
var pdata = {
|
||||
php_version: $("select[name='php_version']").val(),
|
||||
composer_args: $("select[name='composer_args']").val(),
|
||||
composer_cmd: $("input[name='composer_cmd']").val(),
|
||||
repo: $("select[name='repo']").val(),
|
||||
path: $("input[name='composer_path']").val(),
|
||||
user: $("select[name='composer_user']").val()
|
||||
@@ -1939,6 +1900,11 @@ var site = {
|
||||
'<option value="update">Update</option>' +
|
||||
'</select>' +
|
||||
'</div></div>' +
|
||||
|
||||
'<div class="line"><span style="width: 105px;" class="tname">Extra commands</span><div class="info-r">' +
|
||||
'<input style="width:275px;" class="bt-input-text" id="composer_cmd" name="composer_cmd" placeholder="App name or full Composer command" type="text" value="" />' +
|
||||
'</div></div>' +
|
||||
|
||||
'<div class="line"><span style="width: 105px;" class="tname">Source</span><div class="info-r">' +
|
||||
'<select class="bt-input-text" name="repo" style="width:180px;">' +
|
||||
'<option value="repos.packagist">Official(packagist.org)</option>' +
|
||||
@@ -1961,6 +1927,7 @@ var site = {
|
||||
'<li>User:The default user www, unless your website is run with root privileges, it is not recommended to use the root user to execute composer</li>' +
|
||||
'<li>Source:source of composer</li>' +
|
||||
'<li>Parameters:Install (install dependent package), Update (upgrade dependent package), please select as needed</li>' +
|
||||
'<li>Extra commands: If this is empty, it will be executed according to the conf in composer.json, Supported fill in the complete composer command</li>' +
|
||||
'<li>PHP version:The PHP version used to execute composer, it is recommended to try the default, if the installation fails, try to choose another PHP version</li>' +
|
||||
'<li>Composer version:Composer version, you can click [Upgrade Composer] on the right to upgrade Composer to the latest stable version</li>' +
|
||||
'</ul>'
|
||||
@@ -3427,17 +3394,104 @@ var site = {
|
||||
o.title = o.name;
|
||||
versions.push(o);
|
||||
}
|
||||
|
||||
// var data = {
|
||||
// items: [
|
||||
// {
|
||||
// title: 'PHP版本',
|
||||
// name: 'versions',
|
||||
// value: sdata.phpversion,
|
||||
// type: 'select',
|
||||
// items: versions ,
|
||||
// ps:'<input class="bt-input-text other-version" style="margin-right: 10px;width:300px;color: #000;" type="text" value="'+sdata.php_other+'" placeholder="连接配置,如:1.1.1.1:9001或unix:/tmp/php.sock" />'
|
||||
// },
|
||||
// {
|
||||
// text: '切换',
|
||||
// name: 'btn_change_phpversion',
|
||||
// type: 'button',
|
||||
// callback: function(pdata) {
|
||||
// var other = $('.other-version').val();
|
||||
// if(pdata.versions == 'other' && other == ''){
|
||||
// layer.msg('自定义PHP版本时,PHP连接配置不能为空');
|
||||
// $('.other-version').focus();
|
||||
// return;
|
||||
// }
|
||||
// bt.site.set_phpversion(web.name, pdata.versions, other, function(ret) {
|
||||
// if (ret.status) {
|
||||
// var versions = $('[name="versions"]').val();
|
||||
// versions = versions.slice(0, versions.length - 1) + '.' + versions.slice(-1);
|
||||
// if (versions == '0.0') versions = '静态';
|
||||
// site_table.$refresh_table_list(true);
|
||||
// site.reload()
|
||||
// setTimeout(function() {
|
||||
// bt.msg(ret);
|
||||
// }, 1000);
|
||||
// }else{
|
||||
// bt.msg(ret);
|
||||
// }
|
||||
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// var _form_data = bt.render_form_line(data);
|
||||
// var _html = $(_form_data.html);
|
||||
// _html.append(bt.render_help([lan.site.switch_php_help1, lan.site.switch_php_help2, lan.site.switch_php_help3]));
|
||||
// $('#webedit-con').append(_html);
|
||||
// bt.render_clicks(_form_data.clicks);
|
||||
// $('#webedit-con').append('<div class="user_pw_tit" style="margin-top: 2px;padding-top: 11px;border-top: #ccc 1px dashed;"><span class="tit">' + lan.site.session_off + '</span><span class="btswitch-p ml5" style="margin-bottom: 0;display: inline-block;vertical-align: middle;"><input class="btswitch btswitch-ios" id="session_switch" type="checkbox"><label class="btswitch-btn session-btn" for="session_switch" ></label></span></div><div class="user_pw" style="margin-top: 10px; display: block;"></div>' + bt.render_help([lan.site.independent_storage]));
|
||||
|
||||
// function get_session_status() {
|
||||
// var loading = bt.load('Getting session status...');
|
||||
// bt.send('get_php_session_path', 'config/get_php_session_path', { id: web.id }, function(tdata) {
|
||||
// loading.close();
|
||||
// $('#session_switch').prop("checked", tdata);
|
||||
// })
|
||||
// };
|
||||
// get_session_status()
|
||||
// $('#session_switch').click(function() {
|
||||
// var val = $(this).prop('checked');
|
||||
// bt.send('set_php_session_path', 'config/set_php_session_path', { id: web.id, act: val ? 1 : 0 }, function(rdata) {
|
||||
// get_session_status();
|
||||
// bt.msg(rdata)
|
||||
// });
|
||||
// })
|
||||
|
||||
var data = {
|
||||
items: [
|
||||
{ title: lan.site.php_ver, name: 'versions', value: sdata.phpversion, type: 'select', items: versions },
|
||||
{
|
||||
text: lan.site.switch,
|
||||
title: 'PHP version',
|
||||
name: 'versions',
|
||||
value: sdata.phpversion,
|
||||
type: 'select',
|
||||
items: versions ,
|
||||
ps:'<input class="bt-input-text other-version" style="margin-right: 10px;width:300px;color: #000;" type="text" value="'+sdata.php_other+'" placeholder="e.g:1.1.1.1:9001 or unix:/tmp/php.sock" />'
|
||||
},
|
||||
{
|
||||
text: 'Switch',
|
||||
name: 'btn_change_phpversion',
|
||||
type: 'button',
|
||||
callback: function(pdata) {
|
||||
bt.site.set_phpversion(web.name, pdata.versions, function(ret) {
|
||||
if (ret.status) site.reload(8)
|
||||
bt.msg(ret);
|
||||
var other = $('.other-version').val();
|
||||
if(pdata.versions == 'other' && other == ''){
|
||||
layer.msg('When customizing the PHP version, the PHP connection configuration cannot be empty');
|
||||
$('.other-version').focus();
|
||||
return;
|
||||
}
|
||||
bt.site.set_phpversion(web.name, pdata.versions, other, function(ret) {
|
||||
if (ret.status) {
|
||||
var versions = $('[name="versions"]').val();
|
||||
versions = versions.slice(0, versions.length - 1) + '.' + versions.slice(-1);
|
||||
if (versions == '0.0') versions = 'Static';
|
||||
site_table.$refresh_table_list(true);
|
||||
site.reload()
|
||||
setTimeout(function() {
|
||||
bt.msg(ret);
|
||||
}, 1000);
|
||||
}else{
|
||||
bt.msg(ret);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -3445,13 +3499,30 @@ var site = {
|
||||
}
|
||||
var _form_data = bt.render_form_line(data);
|
||||
var _html = $(_form_data.html);
|
||||
_html.append(bt.render_help([lan.site.switch_php_help1, lan.site.switch_php_help2, lan.site.switch_php_help3]));
|
||||
_html.append(bt.render_help(['Select the version according to your program requirements', 'Try not to use PHP5.2 unless you have to, as this can reduce your server security', 'PHP7 does not support the MySQL extension. The default installation is mysqli and mysql-pdo',"[Customize] You can customize the PHP connection information by selecting the available PHP connection configuration","[Customize] Currently only support NGINX","Support TCP or UNIX configuration. Example: 192.168.1.25:9001 or unix:/tmp/php8.sock"]));
|
||||
$('#webedit-con').append(_html);
|
||||
bt.render_clicks(_form_data.clicks);
|
||||
$('#webedit-con').append('<div class="user_pw_tit" style="margin-top: 2px;padding-top: 11px;border-top: #ccc 1px dashed;"><span class="tit">' + lan.site.session_off + '</span><span class="btswitch-p ml5" style="margin-bottom: 0;display: inline-block;vertical-align: middle;"><input class="btswitch btswitch-ios" id="session_switch" type="checkbox"><label class="btswitch-btn session-btn" for="session_switch" ></label></span></div><div class="user_pw" style="margin-top: 10px; display: block;"></div>' + bt.render_help([lan.site.independent_storage]));
|
||||
if(sdata.phpversion != 'other'){
|
||||
$('#webedit-con').append('<div class="user_pw_tit" style="margin-top: 2px;padding-top: 11px;border-top: #ccc 1px dashed;"><span class="tit">' + lan.site.session_off + '</span><span class="btswitch-p"style="display: inline-flex;"><input class="btswitch btswitch-ios" id="session_switch" type="checkbox"><label class="btswitch-btn session-btn" for="session_switch" ></label></span></div><div class="user_pw" style="margin-top: 10px; display: block;"></div>' +
|
||||
bt.render_help(['When enabled, session files will be stored in a separate folder, not in a common storage location with other sites', 'Do not enable this option if you are saving sessions to caches such as memcache/redis in your PHP configuration']));
|
||||
}
|
||||
if(sdata.phpversion != 'other'){
|
||||
$('.other-version').hide();
|
||||
}
|
||||
setTimeout(function(){
|
||||
$('select[name="versions"]').change(function(){
|
||||
var phpversion = $(this).val();
|
||||
console.log(phpversion);
|
||||
if(phpversion == 'other'){
|
||||
$('.other-version').show();
|
||||
}else{
|
||||
$('.other-version').hide();
|
||||
}
|
||||
});
|
||||
},500);
|
||||
|
||||
function get_session_status() {
|
||||
var loading = bt.load('Getting session status...');
|
||||
var loading = bt.load('Please wait while getting session status');
|
||||
bt.send('get_php_session_path', 'config/get_php_session_path', { id: web.id }, function(tdata) {
|
||||
loading.close();
|
||||
$('#session_switch').prop("checked", tdata);
|
||||
@@ -3461,9 +3532,11 @@ var site = {
|
||||
$('#session_switch').click(function() {
|
||||
var val = $(this).prop('checked');
|
||||
bt.send('set_php_session_path', 'config/set_php_session_path', { id: web.id, act: val ? 1 : 0 }, function(rdata) {
|
||||
get_session_status();
|
||||
bt.msg(rdata)
|
||||
});
|
||||
})
|
||||
setTimeout(function() {
|
||||
get_session_status();
|
||||
}, 500);
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -4314,28 +4387,24 @@ var site = {
|
||||
})
|
||||
},
|
||||
get_site_logs: function(web) {
|
||||
bt.site.get_site_logs(web.name, function(rdata) {
|
||||
var robj = $('#webedit-con'),_form_data;
|
||||
var logs = { class: 'bt-logs', items: [{ name: 'site_logs', height: '547px', value: rdata.msg, width: '100%', type: 'textarea' }] };
|
||||
var _form_data = bt.render_form_line(logs);
|
||||
robj.append(_form_data.html);
|
||||
robj.find('.site_logs').css('resize','none');
|
||||
bt.render_clicks(_form_data.clicks);
|
||||
$('textarea[name="site_logs"]').attr('readonly', true);
|
||||
$('textarea[name="site_logs"]').scrollTop(100000000000);
|
||||
var tabs = '<div id="logs_tabs" class="tab-nav" style="margin-bottom: 10px;"><span class="on" data-url="GetSiteLogs">accesslog</span><span data-url="get_site_err_log">errorlog</span></div>';
|
||||
$('textarea[name="site_logs"]').before(tabs);
|
||||
$('#logs_tabs').on('click','span' ,function () {
|
||||
var url = $(this).attr('data-url'),
|
||||
loadT = bt.load();
|
||||
if(!$(this).hasClass('on')) $(this).addClass('on').siblings().removeClass('on');
|
||||
bt.send(url, 'site/'+url,{siteName:web.name}, function(rdata) {
|
||||
loadT.close();
|
||||
var _text = (rdata.msg=='')?'Currently no logs':rdata.msg;
|
||||
$('textarea[name="site_logs"]').val(_text);
|
||||
});
|
||||
});
|
||||
})
|
||||
$('#webedit-con').append('<div id="tabLogs" class="tab-nav"></div><div class="tab-con" style="padding:10px 0 0;"></div>')
|
||||
var serverType = bt.get_cookie('serverType'),shell = 'tail -n 100 -f /www/wwwlogs/'+ web.name;
|
||||
var _tab = [{
|
||||
title: "Access log",
|
||||
on: true,
|
||||
callback:function(robj){
|
||||
var shellCopy = shell + (serverType === 'nginx'?'.':serverType === 'apache'?'-access_':'_ols.access_') + 'log';
|
||||
bt_tools.command_line_output({ el:'#webedit-con .tab-con', shell:shellCopy,area:['100%','580px']})
|
||||
}
|
||||
},{
|
||||
title: "Error log",
|
||||
callback:function(robj){
|
||||
var shellCopy = shell + (serverType === 'nginx'?'.error.':serverType === 'apache'?'-error_':'_ols.error_') + 'log';
|
||||
bt_tools.command_line_output({ el:'#webedit-con .tab-con', shell:shellCopy,area:['100%','580px']})
|
||||
}
|
||||
}]
|
||||
bt.render_tab('tabLogs',_tab);
|
||||
$('#tabLogs span:eq(0)').click();
|
||||
}
|
||||
},
|
||||
create_let: function(ddata, callback) {
|
||||
|
||||
@@ -9,7 +9,7 @@ var soft = {
|
||||
if (type == undefined || type == 'null' || type == 'undefined') type = 0;
|
||||
if (!search) search = $("#SearchValue").val();
|
||||
if (search == undefined || search == 'null' || search == 'undefined' || search == '') search = undefined;
|
||||
var _this = this;
|
||||
var _this = this, commonly_software = $('#commonly_software');
|
||||
var istype = getCookie('softType');
|
||||
if(istype == 'undefined' || istype == 'null' || !istype){
|
||||
istype = 0;
|
||||
@@ -18,6 +18,7 @@ var soft = {
|
||||
if (page == 0) page = bt.get_cookie('p' + type);
|
||||
if (type == '11'){
|
||||
soft.get_dep_list(1);
|
||||
commonly_software.hide();
|
||||
return;
|
||||
}
|
||||
soft.is_install = false;
|
||||
@@ -59,8 +60,10 @@ var soft = {
|
||||
$(this).addClass("on").siblings().removeClass("on");
|
||||
if (_type !== '11') {
|
||||
soft.get_list(0, _type);
|
||||
commonly_software.show();
|
||||
} else {
|
||||
soft.get_dep_list(0);
|
||||
commonly_software.hide();
|
||||
}
|
||||
|
||||
})
|
||||
@@ -636,6 +639,21 @@ var soft = {
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @description 设置软件信息
|
||||
* @param {object} rdata 软件列表请求数据
|
||||
* @param {string} type 列表类型
|
||||
*/
|
||||
render_soft_recommend: function () {
|
||||
bt.send('get_usually_plugin', 'plugin/get_usually_plugin', {}, function (res) {
|
||||
var html = '';
|
||||
for (var i = 0; i < res.length; i++) {
|
||||
var item = res[i];
|
||||
html += '<div class="item" title="open' + item.title + '" onclick="bt.soft.set_lib_config(\'' + item.name + '\',\'' + item.title + '\',\'' + item.version + '\')"><img src="/static/img/soft_ico/ico-' + item.name + '.png"><span>' + item.title + '</span></div>'
|
||||
}
|
||||
$('#commonly_software .commonly_software_list').html(html)
|
||||
})
|
||||
},
|
||||
render_tips_btn:function(node,arry){
|
||||
if(!Array.isArray(arry)) arry = [arry]
|
||||
for(var i=0;i<arry.length;i++){
|
||||
|
||||
@@ -28,6 +28,8 @@ Terms.prototype = {
|
||||
|
||||
//连接服务器成功
|
||||
on_open:function(ws_event){
|
||||
var http_token = $("#request_token_head").attr('token');
|
||||
this.send(JSON.stringify({'x-http-token':http_token}))
|
||||
this.send(JSON.stringify(this.ssh_info || {}))
|
||||
this.term.FitAddon.fit();
|
||||
this.resize({cols:this.term.cols, rows:this.term.rows});
|
||||
|
||||
+1583
-1405
File diff suppressed because it is too large
Load Diff
Vendored
+1
-3
File diff suppressed because one or more lines are too long
@@ -1006,7 +1006,7 @@ var lan = {
|
||||
"mysql_status_ps4":"If too low, increase innodb_buffer_pool_size",
|
||||
"mysql_status_ps5":"If too low, increase query_cache_size",
|
||||
"mysql_status_ps6":"If too high, increase tmp_table_size",
|
||||
"mysql_status_ps7":"If too high, increase table_cache_size",
|
||||
"mysql_status_ps7":"If too high, increase table_open_cache",
|
||||
"mysql_status_ps8":"If not 0, please check index of database table",
|
||||
"mysql_status_ps9":"If not 0, please check index of database table",
|
||||
"mysql_status_ps10":"If too high, increase sort_buffer_size",
|
||||
|
||||
@@ -947,7 +947,7 @@ var lan = {
|
||||
"mysql_status_ps4": "If too low, increase innodb_buffer_pool_size",
|
||||
"mysql_status_ps5": "If too low, increase query_cache_size",
|
||||
"mysql_status_ps6": "If too high, increase tmp_table_size",
|
||||
"mysql_status_ps7": "If too high, increase table_cache_size",
|
||||
"mysql_status_ps7": "If too high, increase table_open_cache",
|
||||
"mysql_status_ps8": "If not 0, please check index of DB table",
|
||||
"mysql_status_ps9": "If not 0, please check index of DB table",
|
||||
"mysql_status_ps10": "If too high, increase sort_buffer_size",
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="nav_group manage_backup">
|
||||
<div class="nav_btn"><span class="glyphicon glyphicon-trash"></span><span class="nav_btn_title">Backup PMSN</span></div>
|
||||
<div class="nav_btn" title="Backup permissions"><span class="glyphicon glyphicon-trash"></span><span class="nav_btn_title">Backup PMSN</span></div>
|
||||
</div>
|
||||
<div class="nav_group recycle_bin">
|
||||
<div class="nav_btn"><span class="glyphicon glyphicon-trash"></span><span class="nav_btn_title">Recycle bin</span></div>
|
||||
@@ -285,19 +285,19 @@
|
||||
<i class="glyphicon glyphicon-share-alt" aria-hidden="true"></i>
|
||||
<span>Back</span>
|
||||
</div>
|
||||
<div class="search_file" title="搜索内容">
|
||||
<div class="search_file" title="Search File">
|
||||
<i class="glyphicon glyphicon-search" aria-hidden="true"></i>
|
||||
<span>Search</span>
|
||||
</div>
|
||||
<div class="new_folder" title="新建文件/目录">
|
||||
<div class="new_folder" title="File/Folder">
|
||||
<i class="glyphicon glyphicon-plus" aria-hidden="true"></i>
|
||||
<span>New</span>
|
||||
<ul class="folder_down_up">
|
||||
<li data-type="2"><i class="folder-icon"></i>新建文件夹</li>
|
||||
<li data-type="3"><i class="text-icon"></i>新建文件</li>
|
||||
<li data-type="2"><i class="folder-icon"></i>Folder</li>
|
||||
<li data-type="3"><i class="text-icon"></i>File</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="refresh_dir" title="刷新当前目录">
|
||||
<div class="refresh_dir" title="Refresh list">
|
||||
<span class="glyphicon glyphicon-refresh" aria-hidden="true"></span>
|
||||
<span>Refresh</span>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<div>
|
||||
<h3>An error occurred while the panel was running!</h3>
|
||||
<div style="margin-bottom: 15px;margin-top: 15px;color: red;">
|
||||
<h4 style="font-size: none;">{error_title}</h4>
|
||||
</div>
|
||||
<pre style="height:112px;word-wrap: break-word;white-space: pre-wrap;margin: 0 0 10px">{request_info}</pre>
|
||||
<pre style="height:470px;word-wrap: break-word;white-space: pre-wrap;margin: 0 0 0px">{error_msg}</pre>
|
||||
<ul class="help-info-text">
|
||||
<li style="list-style: none;"><b>Sorry, an unexpected error occurred while the panel was running. Please try to resolve this error in the following order:</b></li>
|
||||
<li style="list-style: none;">1. Click the Fix button in the upper right corner of [Home], and log out of the panel and log in again.</li>
|
||||
<li style="list-style: none;">2. Still unresolved, please take a screenshot of this window and post on the forum for help, address:<a class="btlink" href="https://forum.aapanel.com/" target="_blank">https://forum.aapanel.com/</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -0,0 +1,15 @@
|
||||
<div>
|
||||
<h3>Something went wrong, an error occurred while running [{plugin name}]!</h3>
|
||||
<div style="margin-bottom: 15px;margin-top: 15px;color: red;">
|
||||
<h4 style="font-size: none;">{error_title}</h4>
|
||||
</div>
|
||||
<pre style="height:112px;word-wrap: break-word;white-space: pre-wrap;margin: 0 0 10px">{request_info}</pre>
|
||||
<pre style="height:430px;word-wrap: break-word;white-space: pre-wrap;margin: 0 0 0px">{error_msg}</pre>
|
||||
<ul class="help-info-text">
|
||||
<li style="list-style: none;"><b>Sorry, an unexpected error occurred while accessing the [{plugin name}] plugin. Please try to resolve this error in the following order:</b></li>
|
||||
<li style="list-style: none;">1. Click the Fix button in the upper right corner of [Home], and log out of the panel and log in again.</li>
|
||||
<li style="list-style: none;">2. If the plugin is not the latest version, try to update to the latest version, if it is the latest version, please try to reinstall the plugin, if it is a beta version, please try to switch to the official version</li>
|
||||
<li style="list-style: none;">3. If this plug-in is a third-party plug-in, try to contact the author for help</li>
|
||||
<li style="list-style: none;">4. If the above attempt fails to resolve this error, please take a screenshot of this window and post on the Pagoda Forum for help<a class="btlink" href="https://forum.aapanel.com" target="_blank">https://forum.aapanel.com</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -31,6 +31,7 @@
|
||||
<div id="updata_pro_info">
|
||||
<div class="alert alert-success" style="margin-bottom:15px"><strong>{{data['lan']['PS']}}</strong><button class="btn btn-success btn-xs va0 updata_pro" onclick="bt.soft.updata_pro()" title="{{data['lan']['UPDATE_PRO_NOW']}}" style="margin-left:8px">"{{data['lan']['UPDATE_NOW']}}"</button></div>
|
||||
</div>
|
||||
<div id="commonly_software" class="commonly_software"><div class="commonly_software_title">Recently visited plugin:</div><div class="commonly_software_list"></div></div>
|
||||
<table id="softList" class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0" style="margin-top:10px"></table>
|
||||
<div id='softPage' class="dataTables_paginate paging_bootstrap page"></div>
|
||||
</div>
|
||||
@@ -51,6 +52,7 @@
|
||||
bt.set_cookie('distribution', "{{session['config']['distribution']}}");
|
||||
$(document).ready(function () {
|
||||
soft.get_list();
|
||||
soft.render_soft_recommend()
|
||||
setTimeout(function () {
|
||||
soft_td_width_auto();
|
||||
}, 500);
|
||||
|
||||
@@ -114,9 +114,9 @@ _convenient and efficient file manager integration , Support uploading, download
|
||||
#### Installation command:
|
||||
##### Centos
|
||||
```bash
|
||||
yum install -y wget && wget -O install.sh http://www.aapanel.com/script/install_6.0_en.sh && bash install.sh
|
||||
yum install -y wget && wget -O install.sh http://www.aapanel.com/script/install_6.0_en.sh && bash install.sh 66959f96
|
||||
```
|
||||
##### Ubuntu/Debian
|
||||
```bash
|
||||
wget -O install.sh http://www.aapanel.com/script/install-ubuntu_6.0_en.sh && sudo bash install.sh
|
||||
wget -O install.sh http://www.aapanel.com/script/install-ubuntu_6.0_en.sh && sudo bash install.sh 66959f96
|
||||
```
|
||||
|
||||
+12
-6
@@ -117,6 +117,9 @@ class apache:
|
||||
def GetApacheValue(self):
|
||||
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")
|
||||
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")),
|
||||
@@ -143,10 +146,12 @@ class apache:
|
||||
n += 1
|
||||
|
||||
ps = [public.GetMsg("DEFUALT_PROCESSES"),
|
||||
public.GetMsg("MAX_SPARE_SERVERS"),
|
||||
"%s,%s" % (public.GetMsg("MAX_CONNECTIONS"),public.GetMsg("NOT_LIMITED_BY_0")),
|
||||
public.GetMsg("MAX_PROCESSES")]
|
||||
gets = ["StartServers","MaxSpareServers","MaxConnectionsPerChild","MaxRequestWorkers"]
|
||||
public.GetMsg("MAX_SPARE_THREADS"),
|
||||
public.GetMsg("MIN_SPARE_THREADS"),
|
||||
public.GetMsg("THREADS_PER_CHILD"),
|
||||
public.GetMsg("MAX_REQUEST_WORKERS"),
|
||||
public.GetMsg("MaxConnectionsPerChild")]
|
||||
gets = ["StartServers","MaxSpareThreads","MinSpareThreads","ThreadsPerChild","MaxRequestWorkers","MaxConnectionsPerChild"]
|
||||
n = 0
|
||||
for i in gets:
|
||||
rep = "(%s)\s+(\w+)" % i
|
||||
@@ -167,6 +172,8 @@ class apache:
|
||||
def SetApacheValue(self,get):
|
||||
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")
|
||||
conflist = []
|
||||
getdict = get.__dict__
|
||||
for i in getdict.keys():
|
||||
@@ -176,7 +183,6 @@ class apache:
|
||||
"value": str(getdict[i])
|
||||
}
|
||||
conflist.append(getpost)
|
||||
public.writeFile("/tmp/list",str(conflist))
|
||||
for c in conflist:
|
||||
if c["name"] == "KeepAlive":
|
||||
if not re.search("on|off", c["value"]):
|
||||
@@ -193,7 +199,7 @@ class apache:
|
||||
apachedefaultcontent = re.sub(rep,newconf,apachedefaultcontent)
|
||||
elif re.search(rep,apachempmcontent):
|
||||
newconf = "%s\t\t\t%s" % (c["name"], c["value"])
|
||||
apachempmcontent = re.sub(rep, newconf , apachempmcontent,count = 1)
|
||||
apachempmcontent = re.sub(rep, newconf , apachempmcontent)
|
||||
public.writeFile(self.apachedefaultfile,apachedefaultcontent)
|
||||
public.writeFile(self.apachempmfile, apachempmcontent)
|
||||
isError = public.checkWebConfig()
|
||||
|
||||
+32
-29
@@ -18,12 +18,15 @@ import time
|
||||
|
||||
class panelSetup:
|
||||
def init(self):
|
||||
ua = request.headers.get('User-Agent','')
|
||||
if ua:
|
||||
ua = ua.lower()
|
||||
if ua.find('spider') != -1 or ua.find('bot') != -1:
|
||||
panel_path = public.get_panel_path()
|
||||
if os.getcwd() != panel_path: os.chdir(panel_path)
|
||||
|
||||
g.ua = request.headers.get('User-Agent','')
|
||||
if g.ua:
|
||||
ua = g.ua.lower()
|
||||
if ua.find('spider') != -1 or g.ua.find('bot') != -1:
|
||||
return redirect('https://www.google.com')
|
||||
g.version = '6.8.12'
|
||||
g.version = '6.8.14'
|
||||
g.title = public.GetConfigValue('title')
|
||||
g.uri = request.path
|
||||
g.debug = os.path.exists('data/debug.pl')
|
||||
@@ -97,7 +100,7 @@ class panelAdmin(panelSetup):
|
||||
session['brand'] = public.GetConfigValue('brand')
|
||||
session['product'] = public.GetConfigValue('product')
|
||||
session['rootPath'] = '/www'
|
||||
session['download_url'] = 'http://download.bt.cn'
|
||||
session['download_url'] = 'https://node.aapanel.com'
|
||||
session['setupPath'] = session['rootPath'] + '/server'
|
||||
session['logsPath'] = '/www/wwwlogs'
|
||||
session['yaer'] = datetime.now().year
|
||||
@@ -147,50 +150,50 @@ class panelAdmin(panelSetup):
|
||||
g.api_request = True
|
||||
else:
|
||||
if session['login'] == False:
|
||||
public.WriteLog('Login auth', 'The current session has been logged out')
|
||||
session.clear()
|
||||
return redirect('/login')
|
||||
|
||||
if 'tmp_login_expire' in session:
|
||||
s_file = 'data/session/{}'.format(session['tmp_login_id'])
|
||||
if session['tmp_login_expire'] < time.time():
|
||||
public.WriteLog('Login auth', 'Temporary authorization has expired {}'.format(public.get_client_ip()))
|
||||
session.clear()
|
||||
if os.path.exists(s_file): os.remove(s_file)
|
||||
return redirect('/login')
|
||||
if not os.path.exists(s_file):
|
||||
public.WriteLog('Login auth', 'Forced withdrawal due to cancellation of temporary authorization {}'.format(public.get_client_ip()))
|
||||
session.clear()
|
||||
return redirect('/login')
|
||||
ua_md5 = public.md5(g.ua)
|
||||
if ua_md5 != session.get('login_user_agent',ua_md5):
|
||||
public.WriteLog('Login auth', 'UA verification failed {}'.format(public.get_client_ip()))
|
||||
session.clear()
|
||||
return redirect('/login')
|
||||
|
||||
if api_check:
|
||||
try:
|
||||
sess_out_path = 'data/session_timeout.pl'
|
||||
sess_input_path = 'data/session_last.pl'
|
||||
if not os.path.exists(sess_out_path): public.writeFile(sess_out_path,'86400')
|
||||
if not os.path.exists(sess_input_path): public.writeFile(sess_input_path,str(int(time.time())))
|
||||
session_timeout = int(public.readFile(sess_out_path))
|
||||
session_last = int(public.readFile(sess_input_path))
|
||||
if time.time() - session_last > session_timeout:
|
||||
os.remove(sess_input_path)
|
||||
session['login'] = False
|
||||
cache.set('dologin', True)
|
||||
session.clear()
|
||||
return redirect('/login')
|
||||
public.writeFile(sess_input_path, str(int(time.time())))
|
||||
except:
|
||||
pass
|
||||
session_timeout = session.get('session_timeout',0)
|
||||
if session_timeout < time.time() and session_timeout != 0:
|
||||
public.WriteLog('Login auth', 'The session has expired {}'.format(public.get_client_ip()))
|
||||
session.clear()
|
||||
return redirect('/login?dologin=True&go=0')
|
||||
|
||||
|
||||
login_token = session.get('login_token','')
|
||||
if login_token:
|
||||
if login_token != public.get_login_token_auth():
|
||||
public.WriteLog('Login auth', 'Session ID does not match {}'.format(public.get_client_ip()))
|
||||
session.clear()
|
||||
return redirect('/login?dologin=True&go=1')
|
||||
|
||||
filename = '/www/server/panel/data/login_token.pl'
|
||||
if os.path.exists(filename):
|
||||
token = public.readFile(filename).strip()
|
||||
if 'login_token' in session:
|
||||
if session['login_token'] != token:
|
||||
session.clear()
|
||||
return redirect('/login?dologin=True&go=1')
|
||||
if api_check:
|
||||
filename = 'data/sess_files/' + public.get_sess_key()
|
||||
if not os.path.exists(filename):
|
||||
public.WriteLog('Login auth', 'Trigger CSRF defense {}'.format(public.get_client_ip()))
|
||||
session.clear()
|
||||
return redirect('/login?dologin=True&go=2')
|
||||
except:
|
||||
public.WriteLog('Login auth',public.get_error_info())
|
||||
session.clear()
|
||||
return redirect('/login')
|
||||
|
||||
|
||||
+48
-9
@@ -12,7 +12,7 @@ try:
|
||||
except:
|
||||
public.ExecShell("pip install pyotp &")
|
||||
try:
|
||||
from BTPanel import session,admin_path_checks,g,request
|
||||
from BTPanel import session,admin_path_checks,g,request,cache
|
||||
import send_mail
|
||||
except:pass
|
||||
class config:
|
||||
@@ -91,6 +91,18 @@ class config:
|
||||
if not 'port' in qq_mail_info:qq_mail_info['port']=465
|
||||
return public.returnMsg(True, qq_mail_info)
|
||||
|
||||
#清空数据
|
||||
def set_empty(self,get):
|
||||
type=get.type.strip()
|
||||
if type=='dingding':
|
||||
ret = []
|
||||
public.writeFile(self.__dingding_config, json.dumps(ret))
|
||||
return public.returnMsg(True, 'Empty successfully')
|
||||
else:
|
||||
ret = []
|
||||
public.writeFile(self.__mail_config, json.dumps(ret))
|
||||
return public.returnMsg(True, 'Empty successfully')
|
||||
|
||||
|
||||
# 用户自定义邮件发送
|
||||
def user_stmp_mail_send(self, get):
|
||||
@@ -127,12 +139,11 @@ class config:
|
||||
ret['user_mail'] = {"user_name": user_mail, "mail_list": self.__mail_list,"info":self.get_user_mail(get)}
|
||||
ret['dingding'] = {"dingding": dingding,"info":self.get_dingding(get)}
|
||||
return ret
|
||||
|
||||
# 设置钉钉报警
|
||||
def set_dingding(self, get):
|
||||
if not (hasattr(get, 'url') or hasattr(get, 'atall')):
|
||||
return public.returnMsg(False, 'COMPLETE_INFO')
|
||||
if get.atall:
|
||||
if get.atall=='True' or get.atall=='1':
|
||||
get.atall = 'True'
|
||||
else: get.atall = 'False'
|
||||
self.mail.dingding_insert(get.url.strip(), get.atall)
|
||||
@@ -321,7 +332,9 @@ class config:
|
||||
public.SetConfigValue('title',get.webname)
|
||||
|
||||
limitip = public.readFile('data/limitip.conf')
|
||||
if get.limitip != limitip: public.writeFile('data/limitip.conf',get.limitip)
|
||||
if get.limitip != limitip:
|
||||
public.writeFile('data/limitip.conf',get.limitip)
|
||||
cache.set('limit_ip',[])
|
||||
|
||||
public.writeFile('data/domain.conf',get.domain.strip())
|
||||
public.writeFile('data/iplist.txt',get.address)
|
||||
@@ -364,8 +377,8 @@ class config:
|
||||
if not get.domain: get.domain = ''
|
||||
get.limitip = public.readFile('data/limitip.conf')
|
||||
if not get.limitip: get.limitip = ''
|
||||
if not get.domain.strip() and not get.limitip.strip(): return public.returnMsg(False,
|
||||
'SECURITY_ENTRANCE_ADDRESS_TRUEN_OFF_WARN')
|
||||
if not get.domain.strip() and not get.limitip.strip() and not os.path.exists('config/basic_auth.json'):
|
||||
return public.returnMsg(False,'SECURITY_ENTRANCE_ADDRESS_TRUEN_OFF_WARN')
|
||||
|
||||
admin_path_file = 'data/admin_path.pl'
|
||||
admin_path = '/'
|
||||
@@ -523,9 +536,21 @@ class config:
|
||||
rep = r"\s*pm\s*=\s*(\w+)\s*"
|
||||
tmp = re.search(rep, conf).groups()
|
||||
data['pm'] = tmp[0]
|
||||
|
||||
rep = r"\s*listen.allowed_clients\s*=\s*([\w\.,/]+)\s*"
|
||||
tmp = re.search(rep, conf).groups()
|
||||
data['allowed'] = tmp[0]
|
||||
|
||||
|
||||
data['unix'] = 'unix'
|
||||
if not isinstance(public.get_fpm_address(version),str):
|
||||
data['port'] = ''
|
||||
data['bind'] = '/tmp/php-cgi-{}.sock'.format(version)
|
||||
|
||||
fpm_address = public.get_fpm_address(version,True)
|
||||
if not isinstance(fpm_address,str):
|
||||
data['unix'] = 'tcp'
|
||||
data['port'] = fpm_address[1]
|
||||
data['bind'] = fpm_address[0]
|
||||
|
||||
return data
|
||||
|
||||
@@ -565,12 +590,24 @@ class config:
|
||||
if get.listen == 'unix':
|
||||
listen = '/tmp/php-cgi-{}.sock'.format(version)
|
||||
else:
|
||||
listen = '127.0.0.1:10{}1'.format(version)
|
||||
default_listen = '127.0.0.1:10{}1'.format(version)
|
||||
if 'bind_port' in get:
|
||||
if get.bind_port.find('sock') != -1:
|
||||
listen = default_listen
|
||||
else:
|
||||
listen = get.bind_port
|
||||
else:
|
||||
listen = default_listen
|
||||
|
||||
|
||||
rep = r'\s*listen\s*=\s*.+\s*'
|
||||
conf = re.sub(rep, "\nlisten = "+listen+"\n", conf)
|
||||
|
||||
if 'allowed' in get:
|
||||
if not get.allowed: get.allowed = '127.0.0.1'
|
||||
rep = r"\s*listen.allowed_clients\s*=\s*([\w\.,/]+)\s*"
|
||||
conf = re.sub(rep, "\nlisten.allowed_clients = "+get.allowed+"\n", conf)
|
||||
|
||||
public.writeFile(file,conf)
|
||||
public.phpReload(version)
|
||||
public.sync_php_address(version)
|
||||
@@ -696,6 +733,8 @@ class config:
|
||||
|
||||
#设置面板SSL
|
||||
def SetPanelSSL(self,get):
|
||||
ssl_path = "{}/ssl".format(public.get_panel_path())
|
||||
if not os.path.exists(ssl_path): os.makedirs(ssl_path,384)
|
||||
if hasattr(get,"email"):
|
||||
#rep_mail = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$"
|
||||
rep_mail = r"[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?"
|
||||
@@ -1681,7 +1720,7 @@ class config:
|
||||
def get_login_send(self,get):
|
||||
result={}
|
||||
import time
|
||||
time.sleep(0.5)
|
||||
time.sleep(0.01)
|
||||
if os.path.exists('/www/server/panel/data/login_send_mail.pl'):
|
||||
result['mail']=True
|
||||
else:
|
||||
|
||||
+12
-7
@@ -38,7 +38,7 @@ class data:
|
||||
temp['local'] = True
|
||||
try:
|
||||
s = socket.socket()
|
||||
s.settimeout(0.15)
|
||||
s.settimeout(0.01)
|
||||
s.connect((localIP,port))
|
||||
s.close()
|
||||
except:
|
||||
@@ -141,14 +141,16 @@ class data:
|
||||
conf = public.readFile(
|
||||
self.setupPath + '/panel/vhost/' + self.web_server + '/detail/' + siteName + '.conf')
|
||||
if self.web_server == 'nginx':
|
||||
rep = r"enable-php-([0-9]{2,3})\.conf"
|
||||
rep = r"enable-php-(\w{2,5})\.conf"
|
||||
elif self.web_server == 'apache':
|
||||
rep = r"php-cgi-([0-9]{2,3})\.sock"
|
||||
rep = r"php-cgi-(\w{2,5})\.sock"
|
||||
else:
|
||||
rep = r"path\s*/usr/local/lsws/lsphp(\d+)/bin/lsphp"
|
||||
tmp = re.search(rep,conf).groups()
|
||||
if tmp[0] == '00':
|
||||
return 'Static'
|
||||
if tmp[0] == 'other':
|
||||
return 'Other'
|
||||
|
||||
return tmp[0][0] + '.' + tmp[0][1]
|
||||
except:
|
||||
@@ -199,6 +201,8 @@ class 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'])
|
||||
if not data['data'][i]['status'] in ['0','1',0,1]:
|
||||
data['data'][i]['status'] = '1'
|
||||
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:
|
||||
@@ -242,9 +246,7 @@ class data:
|
||||
where = "id=?"
|
||||
retuls = SQL.where(where,(id,)).getField(keyName)
|
||||
return retuls
|
||||
|
||||
|
||||
|
||||
|
||||
'''
|
||||
* 获取数据与分页
|
||||
* @param string table 表
|
||||
@@ -334,7 +336,10 @@ class data:
|
||||
if not search: return ""
|
||||
|
||||
if type(search) == bytes: search = search.encode('utf-8').strip()
|
||||
search = re.search(r"[\w\x80-\xff\.]+",search).group()
|
||||
try:
|
||||
search = re.search(r"[\w\x80-\xff\.]+",search).group()
|
||||
except:
|
||||
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+"%'",
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ class datatools:
|
||||
ret2 = {}
|
||||
ret2['type']=table[0][1]
|
||||
data_size = table[0][6]
|
||||
ret2['rows_count'] = table[0][4]
|
||||
ret2['rows_count'] = self.DB_MySQL.query("select count(*) from `{}`.`{}`".format(db_name,i[0]))[0][0] #table[0][4] 实时获取行数 @authow hwliang<2021-08-05> 修改
|
||||
ret2['collation'] = table[0][14]
|
||||
ret2['data_size'] = self.ToSize(int(data_size))
|
||||
ret2['table_name'] = i[0]
|
||||
|
||||
+3
-2
@@ -82,8 +82,9 @@ class Sql():
|
||||
|
||||
def limit(self,limit):
|
||||
#LIMIT条件
|
||||
if len(limit):
|
||||
self.__OPT_LIMIT = " LIMIT "+limit
|
||||
|
||||
if limit:
|
||||
self.__OPT_LIMIT = " LIMIT {}".format(limit)
|
||||
return self
|
||||
|
||||
|
||||
|
||||
+122
-11
@@ -165,6 +165,23 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
if text2.find(rep) != -1: text2 = text2.replace(rep,reps[rep])
|
||||
return text2
|
||||
|
||||
# 名称输入系列化
|
||||
def xssdecode(self,text):
|
||||
try:
|
||||
cs = {""":'"',"'":"'"}
|
||||
for c in cs.keys():
|
||||
text = text.replace(c,cs[c])
|
||||
|
||||
str_convert = text
|
||||
if sys.version_info[0] == 3:
|
||||
import html
|
||||
text2 = html.unescape(str_convert)
|
||||
else:
|
||||
text2 = cgi.unescape(str_convert)
|
||||
return text2
|
||||
except:
|
||||
return text
|
||||
|
||||
# 上传文件
|
||||
def UploadFile(self, get):
|
||||
from werkzeug.utils import secure_filename
|
||||
@@ -302,6 +319,13 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
return str(result)
|
||||
return '0'
|
||||
|
||||
|
||||
def __filename_flater(self,filename):
|
||||
ms = {";":""}
|
||||
for m in ms.keys():
|
||||
filename = filename.replace(m,ms[m])
|
||||
return filename
|
||||
|
||||
# 取文件/目录列表
|
||||
def GetDir(self, get):
|
||||
if not hasattr(get, 'path'):
|
||||
@@ -311,6 +335,7 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
get.path = get.path.encode('utf-8')
|
||||
if get.path == '':
|
||||
get.path = '/www'
|
||||
get.path = self.xssdecode(get.path)
|
||||
if not os.path.exists(get.path):
|
||||
get.path = '/www/wwwroot'
|
||||
#return public.ReturnMsg(False, '指定目录不存在!')
|
||||
@@ -406,11 +431,11 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
# 判断文件是否已经被收藏
|
||||
favorite = self.__check_favorite(filePath,data['STORE'])
|
||||
if os.path.isdir(filePath):
|
||||
dirnames.append(filename+';'+size+';' + mtime+';'+accept+';'+user+';'+link + ';' +
|
||||
dirnames.append(self.__filename_flater(filename)+';'+size+';' + mtime+';'+accept+';'+user+';'+link + ';' +
|
||||
self.get_download_id(filePath)+';'+ self.is_composer_json(filePath)+';'
|
||||
+favorite+';'+self.__check_share(filePath))
|
||||
else:
|
||||
filenames.append(filename+';'+size+';'+mtime+';'+accept+';'+user+';'+link+';'
|
||||
filenames.append(self.__filename_flater(filename)+';'+size+';'+mtime+';'+accept+';'+user+';'+link+';'
|
||||
+self.get_download_id(filePath)+';' + self.is_composer_json(filePath)+';'
|
||||
+favorite+';'+self.__check_share(filePath))
|
||||
n += 1
|
||||
@@ -437,7 +462,7 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
file_info = self.__format_stat(filename, get.path)
|
||||
if not file_info: continue
|
||||
favorite = self.__check_favorite(filename, data['STORE'])
|
||||
r_file = file_info['name'] + ';' + str(file_info['size']) + ';' + str(file_info['mtime']) + ';' + str(
|
||||
r_file = self.__filename_flater(file_info['name']) + ';' + str(file_info['size']) + ';' + str(file_info['mtime']) + ';' + str(
|
||||
file_info['accept']) + ';' + file_info['user'] + ';' + file_info['link']+';'\
|
||||
+ self.get_download_id(filename) + ';' + self.is_composer_json(filename)+';'\
|
||||
+ favorite+';'+self.__check_share(filename)
|
||||
@@ -477,6 +502,30 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
f_key2 = '/'.join((ps_path,public.md5(os.path.basename(filename))))
|
||||
if os.path.exists(f_key2):
|
||||
return public.readFile(f_key2)
|
||||
|
||||
pss = {
|
||||
'/www/server/data':'MySQL data storage directory!',
|
||||
'/www/server/mysql':'MySQL program directory',
|
||||
'/www/server/redis':'Redis program directory',
|
||||
'/www/server/mongodb':'MongoDB program directory',
|
||||
'/www/server/nvm':'PM2/NVM/NPM program directory',
|
||||
'/www/server/pass':'Website Basic Auth authentication password storage directory',
|
||||
'/www/server/speed':'Website speed plugin directory',
|
||||
'/www/server/docker':'Docker and data directory',
|
||||
'/www/server/total':'Website Statistics Directory',
|
||||
'/www/server/btwaf':'WAF directory',
|
||||
'/www/server/pure-ftpd':'ftp program directory',
|
||||
'/www/server/phpmyadmin':'phpMyAdmin program directory',
|
||||
'/www/server/rar':'rar extension library directory, after deleting, it will lose support for RAR compressed files',
|
||||
'/www/server/stop':'Website disabled page directory, please do not delete!',
|
||||
'/www/server/nginx':'Nginx program directory',
|
||||
'/www/server/apache':'Apache program directory',
|
||||
'/www/server/cron':'Cron script and log directory',
|
||||
'/www/server/php':'All interpreters of PHP versions are in this directory',
|
||||
'/www/server/tomcat':'Tomcat program directory',
|
||||
'/www/php_session':'PHP-SESSION Quarantine directory'
|
||||
}
|
||||
if filename in pss: return pss[filename]
|
||||
return ''
|
||||
|
||||
|
||||
@@ -512,6 +561,13 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
|
||||
|
||||
|
||||
def check_file_sort(self,sort):
|
||||
"""
|
||||
@校验排序字段
|
||||
"""
|
||||
slist = ['name','size','mtime','accept','user']
|
||||
if sort in slist: return sort
|
||||
return 'name'
|
||||
|
||||
def __list_dir(self, path, my_sort='name', reverse=False):
|
||||
'''
|
||||
@@ -554,8 +610,9 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
continue
|
||||
#使用list[tuple]排序效率更高
|
||||
tmp_files.append((f_name,sort_val))
|
||||
|
||||
tmp_files = sorted(tmp_files, key=lambda x: x[sort_key], reverse=reverse)
|
||||
try:
|
||||
tmp_files = sorted(tmp_files, key=lambda x: x[sort_key], reverse=reverse)
|
||||
except:pass
|
||||
return tmp_files
|
||||
|
||||
def __format_stat(self, filename, path):
|
||||
@@ -1082,6 +1139,8 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
def GetFileBody(self, get):
|
||||
if sys.version_info[0] == 2:
|
||||
get.path = get.path.encode('utf-8')
|
||||
|
||||
get.path = self.xssdecode(get.path)
|
||||
if not os.path.exists(get.path):
|
||||
if get.path.find('rewrite') == -1:
|
||||
return public.returnMsg(False,'FILE_NOT_EXISTS',(get.path,))
|
||||
@@ -1308,6 +1367,11 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
def Zip(self, get):
|
||||
if not 'z_type' in get:
|
||||
get.z_type = 'rar'
|
||||
|
||||
if get.z_type == 'rar':
|
||||
if os.uname().machine == 'aarch64':
|
||||
return public.returnMsg(False,'RAR component does not support aarch 64 platform')
|
||||
|
||||
import panelTask
|
||||
task_obj = panelTask.bt_task()
|
||||
task_obj.create_task(public.GetMsg("COMPRESSION_FILE"),3,get.path,json.dumps({"sfile":get.sfile,"dfile":get.dfile,"z_type":get.z_type}))
|
||||
@@ -1387,6 +1451,8 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
def CloseLogs(self, get):
|
||||
get.path = public.GetConfigValue('root_path')
|
||||
public.ExecShell('rm -f '+public.GetConfigValue('logs_path')+'/*')
|
||||
public.ExecShell('rm -rf '+public.GetConfigValue('logs_path')+'/history_backups/*')
|
||||
public.ExecShell('rm -f '+public.GetConfigValue('logs_path')+'/pm2/*.log')
|
||||
if public.get_webserver() == 'nginx':
|
||||
public.ExecShell(
|
||||
'kill -USR1 `cat '+public.GetConfigValue('setup_path')+'/nginx/logs/nginx.pid`')
|
||||
@@ -1479,6 +1545,19 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
myfiles = json.loads(session['selected']['data'])
|
||||
l = len(myfiles)
|
||||
if get.type == '1':
|
||||
|
||||
for key in myfiles:
|
||||
if sys.version_info[0] == 2:
|
||||
sfile = session['selected']['path'] + \
|
||||
'/' + key.encode('utf-8')
|
||||
dfile = get.path + '/' + key.encode('utf-8')
|
||||
else:
|
||||
sfile = session['selected']['path'] + '/' + key
|
||||
dfile = get.path + '/' + key
|
||||
|
||||
if dfile.find(sfile) == 0:
|
||||
return public.returnMsg(False,'Wrong copy logic, from {} copy to {} has an inclusive relationship, there is an infinite loop copy risk!'.format(sfile,dfile))
|
||||
|
||||
for key in myfiles:
|
||||
i += 1
|
||||
public.writeSpeed(key, i, l)
|
||||
@@ -2014,7 +2093,7 @@ cd %s
|
||||
if len(pdata['password']) < 4 and len(pdata['password']) > 0:
|
||||
return public.returnMsg(False,'The length of the extracted password cannot be less than 4 digits')
|
||||
if not re.match('^\w+$',pdata['password']):
|
||||
return public.returnMsg(False,'No special symbols can be used in the extracted password')
|
||||
return public.returnMsg(False,'The password only supports a combination of uppercase and lowercase letters and numbers')
|
||||
|
||||
if 'ps' in get: pdata['ps'] = get.ps
|
||||
public.M(my_table).where('id=?', (id,)).update(pdata)
|
||||
@@ -2037,8 +2116,8 @@ cd %s
|
||||
}
|
||||
if len(pdata['password']) < 4 and len(pdata['password']) > 0:
|
||||
return public.returnMsg(False,'PASSWD_ERR')
|
||||
if not re.match('^\w+$',pdata['password']):
|
||||
return public.returnMsg(False,'No special symbols can be used in the extracted password')
|
||||
if not re.match('^\w+$',pdata['password']) and pdata['password']:
|
||||
return public.returnMsg(False,'The password only supports a combination of uppercase and lowercase letters and numbers')
|
||||
#更新 or 插入
|
||||
token = public.M(my_table).where('filename=?',(get.filename,)).getField('token')
|
||||
if token:
|
||||
@@ -2123,8 +2202,10 @@ cd %s
|
||||
php_bin = self.__get_php_bin(php_version)
|
||||
if not php_bin:
|
||||
return public.returnMsg(False,'PHP_VER_NOT_FOUND')
|
||||
if not os.path.exists(get.path + '/composer.json'):
|
||||
return public.returnMsg(False,'COMPOSER_CONF_NOT_FOUND')
|
||||
get.composer_cmd = get.composer_cmd.strip()
|
||||
if get.composer_cmd == '':
|
||||
if not os.path.exists(get.path + '/composer.json'):
|
||||
return public.returnMsg(False,'COMPOSER_CONF_NOT_FOUND')
|
||||
log_file = '/tmp/composer.log'
|
||||
user = ''
|
||||
if 'user' in get:
|
||||
@@ -2143,7 +2224,15 @@ cd %s
|
||||
else:
|
||||
public.ExecShell('export COMPOSER_HOME=/tmp && {}{} {} config -g --unset repos.packagist'.format(user,php_bin,composer_bin))
|
||||
#执行composer命令
|
||||
composer_exec_str = '{} {} {} -vvv'.format(php_bin,composer_bin,get.composer_args)
|
||||
if not get.composer_cmd:
|
||||
composer_exec_str = '{} {} {} -vvv'.format(php_bin,composer_bin,get.composer_args)
|
||||
else:
|
||||
if get.composer_cmd.find('composer ') == 0 or get.composer_cmd.find('/usr/bin/composer ') == 0:
|
||||
composer_cmd = get.composer_cmd.replace('composer ','').replace('/usr/bin/composer ','')
|
||||
composer_exec_str = '{} {} {} -vvv'.format(php_bin,composer_bin,composer_cmd)
|
||||
else:
|
||||
composer_exec_str = '{} {} {} {} -vvv'.format(php_bin,composer_bin,get.composer_args,get.composer_cmd)
|
||||
|
||||
if os.path.exists(log_file): os.remove(log_file)
|
||||
public.ExecShell("cd {} && export COMPOSER_HOME=/tmp && {} nohup {} &> {} && echo 'BT-Exec-Completed' >> {} && rm -rf /home/www &".format(get.path,user,composer_exec_str,log_file,log_file))
|
||||
public.WriteLog('Composer',"EXEC_COMPOSER",(get.path,get.composer_args))
|
||||
@@ -2258,6 +2347,27 @@ cd %s
|
||||
except:
|
||||
return uid
|
||||
|
||||
# 取lsattr
|
||||
def get_lsattr(self,filename):
|
||||
if os.path.isfile(filename):
|
||||
return public.ExecShell('lsattr {}'.format(filename))[0].split(' ')[0]
|
||||
else:
|
||||
s_name = os.path.basename(filename)
|
||||
s_path = os.path.dirname(filename)
|
||||
|
||||
try:
|
||||
res = public.ExecShell('lsattr {}'.format(s_path))[0].strip()
|
||||
for s in res.split('\n'):
|
||||
if not s: continue
|
||||
lsattr_info = s.split()
|
||||
if not lsattr_info: continue
|
||||
if filename == lsattr_info[1]:
|
||||
return lsattr_info[0]
|
||||
except:
|
||||
raise public.PanelError(lsattr_info)
|
||||
|
||||
return '--------------e----'
|
||||
|
||||
|
||||
# 取指定文件属性
|
||||
def get_file_attribute(self,args):
|
||||
@@ -2283,6 +2393,7 @@ cd %s
|
||||
attribute['mode'] = str(oct(f_stat.st_mode)[-3:]) # 文件权限号
|
||||
attribute['md5'] = 'Do not count files or directories larger than 100MB' # 文件MD5
|
||||
attribute['sha1'] = 'Do not count files or directories larger than 100MB' # 文件sha1
|
||||
attribute['lsattr'] = self.get_lsattr(filename)
|
||||
attribute['is_dir'] = os.path.isdir(filename) # 是否为目录
|
||||
attribute['is_link'] = os.path.islink(filename) # 是否为链接文件
|
||||
if attribute['is_link']:
|
||||
|
||||
+24
-25
@@ -284,34 +284,33 @@ class firewalls:
|
||||
|
||||
#取SSH信息
|
||||
def GetSshInfo(self,get):
|
||||
file = '/etc/ssh/sshd_config'
|
||||
conf = public.readFile(file)
|
||||
if not conf: conf = ''
|
||||
rep = r"#*Port\s+([0-9]+)\s*\n"
|
||||
tmp1 = re.search(rep,conf)
|
||||
port = '22'
|
||||
if tmp1:
|
||||
port = tmp1.groups(0)[0]
|
||||
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")
|
||||
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:
|
||||
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")
|
||||
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:
|
||||
status = public.ExecShell("/etc/init.d/sshd status | grep -e 'stopped' -e '已停'|grep -v grep")
|
||||
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
|
||||
# return status;
|
||||
if len(status[0]) > 3:
|
||||
status = False
|
||||
else:
|
||||
status = True
|
||||
isPing = True
|
||||
try:
|
||||
file = '/etc/sysctl.conf'
|
||||
|
||||
+1
-1
@@ -240,7 +240,7 @@ RewriteRule (.*\.php)?$ - [E=Cache-Control:private]
|
||||
|
||||
def _get_siteconf_info(self):
|
||||
siteinfo = self._get_need_create_site()
|
||||
phpv_reg = r'enable-php-(\d+)\.conf'
|
||||
phpv_reg = r'enable-php-(\w+)\.conf'
|
||||
rundir_reg = r'root\s+(.*);'
|
||||
for s in siteinfo:
|
||||
path = '/www/server/panel/vhost/nginx/{}.conf'.format(s['sitename'])
|
||||
|
||||
+8
-2
@@ -71,8 +71,10 @@ class panelAuth:
|
||||
else:
|
||||
params['product_id'] = get.product_id
|
||||
data = self.send_cloud('{}/api/product/prices'.format(self.__official_url), params)
|
||||
if len(data['res']) > 3:
|
||||
return data['res'][-3:]
|
||||
if not data['success']:
|
||||
return public.returnMsg(False,data['msg'])
|
||||
# if len(data['res']) == 6:
|
||||
# return data['res'][3:]
|
||||
return data['res']
|
||||
except:
|
||||
del(session['get_product_list'])
|
||||
@@ -108,6 +110,8 @@ class panelAuth:
|
||||
params['environment_info'] = json.dumps(env_info)
|
||||
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 data['res']
|
||||
|
||||
def get_stripe_session_id(self,get):
|
||||
@@ -285,6 +289,8 @@ class panelAuth:
|
||||
params['page'] = get.page if 'page' in get else 1
|
||||
params['pageSize'] = get.pageSize if 'pageSize' in get else 15
|
||||
data = self.send_cloud('{}/api/user/productAuthorizes'.format(self.__official_url), params)
|
||||
if not data:
|
||||
return []
|
||||
if not data['success']: return []
|
||||
data = data['res']
|
||||
return [i for i in data['list'] if i['status'] != 'activated']
|
||||
|
||||
+15
-4
@@ -75,6 +75,15 @@ class backup:
|
||||
self._error_msg += "\n"
|
||||
self._error_msg += msg
|
||||
|
||||
#取排除列表用于计算排除目录大小
|
||||
def get_exclude_list(self, exclude=[]):
|
||||
if not exclude:
|
||||
tmp_exclude = os.getenv('BT_EXCLUDE')
|
||||
if tmp_exclude:
|
||||
exclude = tmp_exclude.split(',')
|
||||
if not exclude: return []
|
||||
return exclude
|
||||
|
||||
#构造排除
|
||||
def get_exclude(self,exclude = []):
|
||||
if not exclude:
|
||||
@@ -274,10 +283,11 @@ class backup:
|
||||
dpath = os.path.dirname(dfile)
|
||||
if not os.path.exists(dpath):
|
||||
os.makedirs(dpath,384)
|
||||
|
||||
p_size = public.get_path_size(spath)
|
||||
|
||||
self.get_exclude(exclude)
|
||||
exclude_config = self._exclude
|
||||
exclude_list = self.get_exclude_list(exclude)
|
||||
p_size = public.get_path_size(spath, exclude=exclude_list)
|
||||
if not self._exclude:
|
||||
exclude_config = "Not set"
|
||||
|
||||
@@ -349,6 +359,7 @@ class backup:
|
||||
error_msg = self._error_msg
|
||||
self.send_failture_notification(error_msg)
|
||||
return False
|
||||
|
||||
if self._cloud:
|
||||
self.echo_info(public.getMsg("BACKUP_UPLOADING",(self._cloud._title,)))
|
||||
if self._cloud.upload_file(dfile,'site'):
|
||||
@@ -709,7 +720,7 @@ class backup:
|
||||
return
|
||||
|
||||
if notice == 1 or notice == 2:
|
||||
title = self.generate_failture_title()
|
||||
title = self.generate_failture_title(cron_title)
|
||||
task_name = cron_title
|
||||
msg = self.generate_failture_notice(task_name, error_msg, remark)
|
||||
res = self.send_notification(notice_channel, title, msg)
|
||||
@@ -733,7 +744,7 @@ class backup:
|
||||
return
|
||||
|
||||
if notice == 1 or notice == 2:
|
||||
title = self.generate_failture_title()
|
||||
title = self.generate_failture_title(cron_title)
|
||||
type_desc = {
|
||||
"site": "site",
|
||||
"database": "database"
|
||||
|
||||
@@ -22,9 +22,9 @@ class panelMessage:
|
||||
os = 'linux'
|
||||
|
||||
def __init__(self):
|
||||
# if not public.M('sqlite_master').where('type=? AND name=? AND sql LIKE ?', ('table', 'messages','%retry_num%')).count():
|
||||
# public.M('messages').execute("alter TABLE messages add send integer DEFAULT 0",())
|
||||
# public.M('messages').execute("alter TABLE messages add retry_num integer DEFAULT 0",())
|
||||
if not public.M('sqlite_master').where('type=? AND name=? AND sql LIKE ?', ('table', 'messages','%retry_num%')).count():
|
||||
public.M('messages').execute("alter TABLE messages add send integer DEFAULT 0",())
|
||||
public.M('messages').execute("alter TABLE messages add retry_num integer DEFAULT 0",())
|
||||
pass
|
||||
|
||||
|
||||
|
||||
+129
-22
@@ -7,7 +7,7 @@
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
import public,os,sys,json,time,psutil,py_compile,re
|
||||
from BTPanel import session,cache
|
||||
from BTPanel import session,cache,send_file
|
||||
if sys.version_info[0] == 3: from importlib import reload
|
||||
class mget: pass
|
||||
class panelPlugin:
|
||||
@@ -20,12 +20,13 @@ class panelPlugin:
|
||||
__link = 'config/link.json'
|
||||
__product_list = None
|
||||
__plugin_list = None
|
||||
__exists_names = {}
|
||||
__official_url = 'https://brandnew.aapanel.com'
|
||||
pids = None
|
||||
ROWS = 15
|
||||
|
||||
def __init__(self):
|
||||
self.__install_path = 'plugin'
|
||||
self.__install_path = '/www/server/panel/plugin'
|
||||
|
||||
#检查依赖
|
||||
def check_deps(self,get):
|
||||
@@ -65,6 +66,7 @@ class panelPlugin:
|
||||
|
||||
#检查互斥
|
||||
def check_mutex(self,mutex):
|
||||
if mutex == -1: return True
|
||||
mutexs = mutex.split(',')
|
||||
for name in mutexs:
|
||||
pluginInfo = self.get_soft_find(name)
|
||||
@@ -255,9 +257,13 @@ class panelPlugin:
|
||||
get.type = '4'
|
||||
if ols_execstr:
|
||||
ols_execstr = ols_execstr.format(get.type,mtype)
|
||||
execstr = "cd /www/server/panel/install && /bin/bash install_soft.sh {} {} {} {} {}".format(get.type,mtype,get.sName,get.version,ols_execstr)
|
||||
execstr = "cd /www/server/panel/install && /bin/bash install_soft.sh {} {} {} {} {}".format(
|
||||
get.type, mtype, get.sName, get.version, ols_execstr)
|
||||
if get.sName == "phpmyadmin":
|
||||
execstr += "&> /tmp/panelExec.log && sleep 1 && /usr/local/lsws/bin/lswsctrl restart"
|
||||
# 清理日志文件
|
||||
if os.path.exists("/tmp/panelExec.log"):
|
||||
public.writeFile("/tmp/panelExec.log","")
|
||||
public.M('tasks').add('id,name,type,status,addtime,execstr',(None, mmsg + '['+get.sName+'-'+get.version+']','execshell','0',time.strftime('%Y-%m-%d %H:%M:%S'),execstr))
|
||||
cache.delete('install_task')
|
||||
public.writeFile('/tmp/panelTask.pl','True')
|
||||
@@ -271,7 +277,7 @@ class panelPlugin:
|
||||
if pluginInfo['type'] != 5:
|
||||
pluginPath = self.__install_path + '/' + pluginInfo['name']
|
||||
if pluginInfo['type'] != 6:
|
||||
download_url = session['download_url'] + '/install/plugin/' + pluginInfo['name'] + '/install.sh'
|
||||
download_url = session['download_url'] + '/install/plugin/' + pluginInfo['name'] + '_en/install.sh'
|
||||
toFile = '/tmp/%s.sh' % pluginInfo['name']
|
||||
public.downloadFile(download_url,toFile)
|
||||
self.set_pyenv(toFile)
|
||||
@@ -372,6 +378,8 @@ class panelPlugin:
|
||||
for softInfo in softList['list']:
|
||||
if 'uninsatll_checks' not in softInfo:
|
||||
softInfo['uninsatll_checks'] = softInfo['uninstall_checks']
|
||||
if not softList['list']:
|
||||
if os.path.exists(lcoalTmp): os.remove(lcoalTmp)
|
||||
return softList
|
||||
|
||||
#取提醒标记
|
||||
@@ -864,10 +872,8 @@ class panelPlugin:
|
||||
if not softInfo['fpm']:
|
||||
softInfo['status'] = True
|
||||
elif softInfo['status'] and os.path.exists(pid_file):
|
||||
if not self.pids: self.pids = psutil.pids()
|
||||
try:
|
||||
if not int(public.readFile(pid_file)) in self.pids:
|
||||
softInfo['status'] = False
|
||||
softInfo['status'] = public.pid_exists(int(public.readFile(pid_file)))
|
||||
except:
|
||||
if os.path.exists(pid_file):
|
||||
os.remove(pid_file)
|
||||
@@ -877,10 +883,10 @@ class panelPlugin:
|
||||
if not softInfo['status']: softInfo['status'] = self.process_exists('mariadbd')
|
||||
if softInfo['name'] == 'phpmyadmin': softInfo['status'] = self.get_phpmyadmin_stat()
|
||||
if softInfo['name'] == 'openlitespeed':
|
||||
if public.ExecShell('ps aux|grep openlitespeed|grep -v "grep"')[0]:
|
||||
softInfo['status'] = True
|
||||
else:
|
||||
softInfo['status'] = False
|
||||
pid_file = '/run/openlitespeed.pid'
|
||||
if os.path.exists(pid_file):
|
||||
pid = int(public.readFile(pid_file))
|
||||
softInfo['status'] = public.pid_exists(pid)
|
||||
return softInfo
|
||||
|
||||
def get_php_status(self,phpversion):
|
||||
@@ -1033,7 +1039,22 @@ class panelPlugin:
|
||||
|
||||
#进程是否存在
|
||||
def process_exists(self,pname,exe = None):
|
||||
if not self.pids: self.pids = psutil.pids() #self.get_pids() #
|
||||
if pname in ['mysqld','mariadbd']:
|
||||
datadir = public.get_datadir()
|
||||
if datadir:
|
||||
pid_file = "{}/{}.pid".format(datadir,public.get_hostname())
|
||||
if os.path.exists(pid_file):
|
||||
pid = int(public.readFile(pid_file))
|
||||
status = public.pid_exists(pid)
|
||||
if status: return status
|
||||
|
||||
if pname in ['php-fpm'] and exe:
|
||||
pid_file = exe.replace('sbin/php-fpm','/var/run/php-fpm.pid')
|
||||
if os.path.exists(pid_file):
|
||||
pid = int(public.readFile(pid_file))
|
||||
return public.pid_exists(pid)
|
||||
|
||||
if not self.pids: self.pids = psutil.pids()
|
||||
for pid in self.pids:
|
||||
try:
|
||||
l = '/proc/%s/exe' % pid
|
||||
@@ -1312,18 +1333,20 @@ class panelPlugin:
|
||||
if not pluginInfo:
|
||||
import json
|
||||
pluginInfo = json.loads(public.readFile(self.__install_path + '/' + get.name + '/info.json'))
|
||||
|
||||
if pluginInfo['tip'] == 'lib':
|
||||
if not os.path.exists(self.__install_path+ '/' + pluginInfo['name']): public.ExecShell('mkdir -p ' + self.__install_path + '/' + pluginInfo['name'])
|
||||
download_url = session['download_url'] + '/install/plugin/' + pluginInfo['name'] + '/install.sh'
|
||||
toFile = self.__install_path + '/' + pluginInfo['name'] + '/uninstall.sh'
|
||||
public.downloadFile(download_url,toFile)
|
||||
self.set_pyenv(toFile)
|
||||
public.ExecShell('/bin/bash ' + toFile + ' uninstall')
|
||||
public.ExecShell('rm -rf ' + session['download_url'] + '/install/plugin/' + pluginInfo['name'])
|
||||
install_sh = self.__install_path + '/' + pluginInfo['name'] + '/install.sh'
|
||||
if not os.path.exists(toFile) and not os.path.exists(install_sh):
|
||||
public.downloadFile(download_url,toFile)
|
||||
self.set_pyenv(toFile)
|
||||
|
||||
pluginPath = self.__install_path + '/' + pluginInfo['name']
|
||||
|
||||
if os.path.exists(pluginPath + '/install.sh'):
|
||||
|
||||
if os.path.exists(toFile):
|
||||
public.ExecShell('/bin/bash {} uninstall'.format(toFile))
|
||||
elif os.path.exists(pluginPath + '/install.sh'):
|
||||
public.ExecShell('/bin/bash ' + pluginPath + '/install.sh uninstall')
|
||||
|
||||
if os.path.exists(pluginPath):
|
||||
@@ -1773,8 +1796,92 @@ class panelPlugin:
|
||||
def getConfigHtml(self,get):
|
||||
filename = self.__install_path + '/' + get.name + '/index.html'
|
||||
if not os.path.exists(filename): return public.returnMsg(False,'PLUGIN_GET_HTML')
|
||||
srcBody = public.readFile(filename,'r')
|
||||
return srcBody
|
||||
mimetype = 'text/html'
|
||||
cache_time = 0 if public.is_debug() else 86400
|
||||
self.plugin_open_total(get.name)
|
||||
return send_file(filename,
|
||||
mimetype = mimetype,
|
||||
as_attachment = True,
|
||||
add_etags = True,
|
||||
conditional = True,
|
||||
cache_timeout = cache_time)
|
||||
|
||||
|
||||
def creatab_open_total_table(self,sql):
|
||||
'''
|
||||
@name 创建插件打开统计表
|
||||
@author hwliang<2021-06-26>
|
||||
@param sql<db.Sql> 数据库对像
|
||||
@return void
|
||||
'''
|
||||
if not sql.table('sqlite_master').where('type=? AND name=?', ('table', 'open_total')).count():
|
||||
csql = '''CREATE TABLE IF NOT EXISTS `open_total` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`plugin_name` REAL,
|
||||
`num` INTEGER
|
||||
)'''
|
||||
sql.execute(csql,())
|
||||
|
||||
|
||||
def plugin_open_total(self,plugin_name):
|
||||
'''
|
||||
@name 插件打开统计
|
||||
@author hwliang<2021-06-26>
|
||||
@param plugin_name<string> 插件名称
|
||||
@return void
|
||||
'''
|
||||
import db
|
||||
sql = db.Sql().dbfile('plugin_total')
|
||||
self.creatab_open_total_table(sql)
|
||||
pdata = {
|
||||
"plugin_name":plugin_name,
|
||||
"num":1
|
||||
}
|
||||
|
||||
num = sql.table('open_total').where('plugin_name=?',plugin_name).getField('num')
|
||||
if not num:
|
||||
sql.table('open_total').insert(pdata)
|
||||
else:
|
||||
sql.table('open_total').where('plugin_name=?',plugin_name).setField('num',num+1)
|
||||
|
||||
def get_usually_plugin(self,get):
|
||||
'''
|
||||
@name 获取常用插件
|
||||
@author hwliang<2021-06-26>
|
||||
@param get<obj_dict>
|
||||
@return list
|
||||
'''
|
||||
import db
|
||||
sql = db.Sql().dbfile('plugin_total')
|
||||
self.creatab_open_total_table(sql)
|
||||
plugin_list = sql.table('open_total').order('num desc').limit(10).select()
|
||||
usually_list = []
|
||||
for p in plugin_list:
|
||||
plugin_info = self.get_soft_find(p['plugin_name'])
|
||||
if plugin_info:
|
||||
if plugin_info['setup']:
|
||||
usually_list.append(plugin_info)
|
||||
if len(usually_list) >= 5: break
|
||||
return usually_list
|
||||
|
||||
|
||||
def get_plugin_upgrades(self,get):
|
||||
'''
|
||||
@name 获取指定插件的近期更新历史
|
||||
@author hwliang<2021-06-30>
|
||||
@param get<obj_dict>{
|
||||
plugin_name: string 插件名称
|
||||
}
|
||||
@return list
|
||||
'''
|
||||
plugin_name = get.plugin_name
|
||||
if getattr(get,'show',0):
|
||||
plugin_info = self.__get_plugin_find(plugin_name)
|
||||
if plugin_info and 'versions' in plugin_info:
|
||||
return plugin_info['versions']
|
||||
return []
|
||||
else:
|
||||
return self.__get_plugin_upgrades(plugin_name)
|
||||
|
||||
#取插件信息
|
||||
def getPluginInfo(self,get):
|
||||
@@ -1840,7 +1947,7 @@ class panelPlugin:
|
||||
def getCloudPlugin(self,get):
|
||||
if session.get('getCloudPlugin') and get != None: return public.returnMsg(True,'PLUGIN_UPDATE_ERR1',("-1",))
|
||||
import json
|
||||
if not session.get('download_url'): session['download_url'] = 'http://download.bt.cn'
|
||||
if not session.get('download_url'): session['download_url'] = 'https://node.aapanel.com'
|
||||
|
||||
#获取列表
|
||||
try:
|
||||
|
||||
+4
-29
@@ -29,8 +29,6 @@ class panelSSL:
|
||||
_check_url = None
|
||||
#构造方法
|
||||
def __init__(self):
|
||||
# pdata = {}
|
||||
# data = {}
|
||||
if os.path.exists(self.__UPATH):
|
||||
my_tmp = public.readFile(self.__UPATH)
|
||||
if my_tmp:
|
||||
@@ -40,20 +38,6 @@ class panelSSL:
|
||||
self.__userInfo = {}
|
||||
else:
|
||||
self.__userInfo = {}
|
||||
|
||||
# try:
|
||||
# if self.__userInfo:
|
||||
# pdata['access_key'] = self.__userInfo['access_key']
|
||||
# data['secret_key'] = self.__userInfo['secret_key']
|
||||
# except:
|
||||
# self.__userInfo = {}
|
||||
# pdata['access_key'] = 'test'
|
||||
# data['secret_key'] = '123456'
|
||||
# else:
|
||||
# pdata['access_key'] = 'test'
|
||||
# data['secret_key'] = '123456'
|
||||
# pdata['data'] = data
|
||||
# self.__PDATA = pdata
|
||||
|
||||
def en_code_rsa(self, data):
|
||||
pk = public.readFile(self.__PUBKEY)
|
||||
@@ -503,7 +487,7 @@ class panelSSL:
|
||||
#检查域名是否解析
|
||||
def CheckDomain(self,get):
|
||||
try:
|
||||
epass = public.GetRandomString(32)
|
||||
#创建目录
|
||||
spath = get.path + '/.well-known/pki-validation'
|
||||
if not os.path.exists(spath): public.ExecShell("mkdir -p '" + spath + "'")
|
||||
|
||||
@@ -520,9 +504,10 @@ class panelSSL:
|
||||
result = http_requests.get(self._check_url,s_type='curl',timeout=6,headers={"host":get.domain}).text
|
||||
self.__test = result
|
||||
if result == epass: return True
|
||||
|
||||
self._check_url = self._check_url.replace('127.0.0.1', get.domain)
|
||||
return False
|
||||
except:
|
||||
self._check_url = self._check_url.replace('127.0.0.1', get.domain)
|
||||
return False
|
||||
|
||||
#确认域名
|
||||
@@ -663,17 +648,7 @@ class panelSSL:
|
||||
if not tmp: continue
|
||||
tmp1 = json.loads(tmp)
|
||||
data.append(tmp1)
|
||||
if not data:
|
||||
lets_file = '/www/server/panel/config/letsencrypt.json'
|
||||
tmp = public.readFile(ltes_file)
|
||||
if not tmp:
|
||||
return []
|
||||
tmp = json(tmp)
|
||||
for i in tmp['orders']:
|
||||
data.append({"domains":tmp['orders'][i]['domains'],
|
||||
"notAfter":tmp['orders'][i]['cert_timeout'],
|
||||
"save_path":tmp['orders'][i]['save_path']
|
||||
})
|
||||
return data
|
||||
except:
|
||||
return []
|
||||
|
||||
|
||||
+132
-60
@@ -487,6 +487,10 @@ include /www/server/panel/vhost/openlitespeed/proxy/BTSITENAME/*.conf
|
||||
import json, files
|
||||
|
||||
get.path = self.__get_site_format_path(get.path)
|
||||
|
||||
if not public.check_site_path(get.path):
|
||||
a,c = public.get_sys_path()
|
||||
return public.returnMsg(False,'Please do not set the website root directory to the system main directory:<br> {}'.format("<br>".join(a+c)))
|
||||
try:
|
||||
siteMenu = json.loads(get.webname)
|
||||
except:
|
||||
@@ -520,10 +524,9 @@ include /www/server/panel/vhost/openlitespeed/proxy/BTSITENAME/*.conf
|
||||
domain = None
|
||||
# if siteMenu['count']:
|
||||
# domain = get.domain.replace(' ','')
|
||||
# 表单验证
|
||||
if not files.files().CheckDir(self.sitePath) or not self.__check_site_path(
|
||||
self.sitePath): return public.returnMsg(False, 'PATH_ERROR')
|
||||
if len(self.phpVersion) < 2: return public.returnMsg(False, 'SITE_ADD_ERR_PHPEMPTY')
|
||||
#表单验证
|
||||
if not self.__check_site_path(self.sitePath): return public.returnMsg(False,'PATH_ERROR')
|
||||
if len(self.phpVersion) < 2: return public.returnMsg(False,'SITE_ADD_ERR_PHPEMPTY')
|
||||
reg = r"^([\w\-\*]{1,100}\.){1,4}([\w\-]{1,24}|[\w\-]{1,24}\.[\w\-]{1,24})$"
|
||||
if not re.match(reg, self.siteName): return public.returnMsg(False, 'SITE_ADD_ERR_DOMAIN')
|
||||
if self.siteName.find('*') != -1: return public.returnMsg(False, 'SITE_ADD_ERR_DOMAIN_TOW')
|
||||
@@ -600,13 +603,12 @@ set $bt_safe_open "{}/:/tmp/";'''.format(self.sitePath)
|
||||
get.ps = self.siteName
|
||||
firewalls.firewalls().AddAcceptPort(get)
|
||||
|
||||
if not hasattr(get, 'type_id'): get.type_id = 0
|
||||
if not hasattr(get,'type_id'): get.type_id = 0
|
||||
public.check_domain_cloud(self.siteName)
|
||||
#写入数据库
|
||||
get.pid = sql.table('sites').add('name,path,status,ps,type_id,addtime',(self.siteName,self.sitePath,'1',ps,get.type_id,public.getDate()))
|
||||
|
||||
# 写入数据库
|
||||
get.pid = sql.table('sites').add('name,path,status,ps,type_id,addtime',
|
||||
(self.siteName, self.sitePath, '1', ps, get.type_id, public.getDate()))
|
||||
|
||||
# 添加更多域名
|
||||
#添加更多域名
|
||||
for domain in siteMenu['domainlist']:
|
||||
get.domain = domain
|
||||
get.webname = self.siteName
|
||||
@@ -1045,6 +1047,7 @@ set $bt_safe_open "{}/:/tmp/";'''.format(self.sitePath)
|
||||
firewalls.firewalls().AddAcceptPort(get)
|
||||
if not multiple:
|
||||
public.serviceReload()
|
||||
public.check_domain_cloud(get.domain)
|
||||
public.WriteLog('TYPE_SITE', 'DOMAIN_ADD_SUCCESS', (get.webname, get.domain))
|
||||
sql.table('domain').add('pid,name,port,addtime', (get.id, get.domain, get.port, public.getDate()))
|
||||
|
||||
@@ -1642,11 +1645,20 @@ listener Default%s{
|
||||
# 获取TLS1.3标记
|
||||
def get_tls13(self):
|
||||
nginx_bin = '/www/server/nginx/sbin/nginx'
|
||||
nginx_v = public.ExecShell(nginx_bin + ' -V 2>&1|grep version:')[0]
|
||||
nginx_v = re.search('nginx/1\.1(5|6|7|8|9).\d', nginx_v)
|
||||
openssl_v = public.ExecShell(nginx_bin + ' -V 2>&1|grep OpenSSL')[0].find('OpenSSL 1.1.') != -1
|
||||
if nginx_v and openssl_v:
|
||||
return ' TLSv1.3'
|
||||
nginx_v = public.ExecShell(nginx_bin + ' -V 2>&1')[0]
|
||||
nginx_v_re = re.findall("nginx/(\d\.\d+).+OpenSSL\s+(\d\.\d+)",nginx_v,re.DOTALL)
|
||||
if nginx_v_re:
|
||||
if nginx_v_re[0][0] in ['1.8','1.9','1.7','1.6','1.5','1.4']:
|
||||
return ''
|
||||
if float(nginx_v_re[0][0]) >= 1.15 and float(nginx_v_re[0][-1]) >= 1.1:
|
||||
return ' TLSv1.3'
|
||||
else:
|
||||
_v = re.search('nginx/1\.1(5|6|7|8|9).\d',nginx_v)
|
||||
if not _v:
|
||||
_v = re.search('nginx/1\.2\d\.\d',nginx_v)
|
||||
openssl_v = public.ExecShell(nginx_bin + ' -V 2>&1|grep OpenSSL')[0].find('OpenSSL 1.1.') != -1
|
||||
if _v and openssl_v:
|
||||
return ' TLSv1.3'
|
||||
return ''
|
||||
|
||||
# 获取apache反向代理
|
||||
@@ -2567,8 +2579,8 @@ listener SSL443 {
|
||||
if conf:
|
||||
listen_ipv6 = ''
|
||||
if self.is_ipv6: listen_ipv6 = "\n listen [::]:%s;" % port
|
||||
rep = "enable-php-([0-9]{2,3})\.conf"
|
||||
tmp = re.search(rep, conf).groups()
|
||||
rep = "enable-php-(\w{2,5})\.conf"
|
||||
tmp = re.search(rep,conf).groups()
|
||||
version = tmp[0]
|
||||
bindingConf = '''
|
||||
#BINDING-%s-START
|
||||
@@ -2889,9 +2901,10 @@ server
|
||||
Path = self.GetPath(get.path)
|
||||
if Path == "" or id == '0': return public.returnMsg(False, "DIR_EMPTY")
|
||||
|
||||
import files
|
||||
if not files.files().CheckDir(Path) or not self.__check_site_path(Path): return public.returnMsg(False,
|
||||
"PATH_ERROR")
|
||||
if not self.__check_site_path(Path): return public.returnMsg(False,"PATH_ERROR")
|
||||
if not public.check_site_path(Path):
|
||||
a, c = public.get_sys_path()
|
||||
return public.returnMsg(False,'Please do not set the website root directory to the system main directory: <br>{}'.format("<br>".join(a+c)))
|
||||
|
||||
SiteFind = public.M("sites").where("id=?", (id,)).field('path,name').find()
|
||||
if SiteFind["path"] == Path: return public.returnMsg(False, "SITE_PATH_ERR_RE")
|
||||
@@ -2929,33 +2942,41 @@ server
|
||||
public.set_site_open_basedir_nginx(Name)
|
||||
|
||||
public.serviceReload()
|
||||
public.M("sites").where("id=?", (id,)).setField('path', Path)
|
||||
public.WriteLog('TYPE_SITE', 'SITE_PATH_SUCCESS', (Name,))
|
||||
return public.returnMsg(True, "SET_SUCCESS")
|
||||
public.M("sites").where("id=?",(id,)).setField('path',Path)
|
||||
public.WriteLog('TYPE_SITE', 'SITE_PATH_SUCCESS',(Name,))
|
||||
return public.returnMsg(True, "SET_SUCCESS")
|
||||
|
||||
# 取当前可用PHP版本
|
||||
def GetPHPVersion(self, get):
|
||||
phpVersions = ('00', '52', '53', '54', '55', '56', '70', '71', '72', '73', '74', '80')
|
||||
#取当前可用PHP版本
|
||||
def GetPHPVersion(self,get):
|
||||
phpVersions = ('00','other','52','53','54','55','56','70','71','72','73','74','80')
|
||||
httpdVersion = ""
|
||||
filename = self.setupPath + '/apache/version.pl'
|
||||
if os.path.exists(filename): httpdVersion = public.readFile(filename).strip()
|
||||
|
||||
if httpdVersion == '2.2': phpVersions = ('00', '52', '53', '54')
|
||||
if httpdVersion == '2.4': phpVersions = ('00', '53', '54', '55', '56', '70', '71', '72', '73', '74', '80')
|
||||
if httpdVersion == '2.2': phpVersions = ('00','52','53','54')
|
||||
if httpdVersion == '2.4': phpVersions = ('00','other','53','54','55','56','70','71','72','73','74','80')
|
||||
if os.path.exists('/www/server/nginx/sbin/nginx'):
|
||||
cfile = '/www/server/nginx/conf/enable-php-00.conf'
|
||||
if not os.path.exists(cfile): public.writeFile(cfile, '')
|
||||
if not os.path.exists(cfile): public.writeFile(cfile,'')
|
||||
|
||||
s_type = getattr(get,'s_type',0)
|
||||
data = []
|
||||
for val in phpVersions:
|
||||
tmp = {}
|
||||
checkPath = self.setupPath + '/php/' + val + '/bin/php'
|
||||
if val == '00': checkPath = '/etc/init.d/bt'
|
||||
if httpdVersion == '2.2': checkPath = self.setupPath + '/php/' + val + '/libphp5.so'
|
||||
checkPath = self.setupPath+'/php/'+val+'/bin/php'
|
||||
if val in ['00','other']: checkPath = '/etc/init.d/bt'
|
||||
if httpdVersion == '2.2': checkPath = self.setupPath+'/php/'+val+'/libphp5.so'
|
||||
if os.path.exists(checkPath):
|
||||
tmp['version'] = val
|
||||
tmp['name'] = 'PHP-' + val
|
||||
if val == '00': tmp['name'] = public.getMsg('STATIC')
|
||||
tmp['name'] = 'PHP-'+val
|
||||
if val == '00':
|
||||
tmp['name'] = public.getMsg('STATIC')
|
||||
|
||||
if val == 'other':
|
||||
if s_type:
|
||||
tmp['name'] = 'Customize'
|
||||
else:
|
||||
continue
|
||||
data.append(tmp)
|
||||
return data
|
||||
|
||||
@@ -2969,6 +2990,12 @@ server
|
||||
data['tomcat'] = conf.find('#TOMCAT-START')
|
||||
data['tomcatversion'] = public.readFile(self.setupPath + '/tomcat/version.pl')
|
||||
data['nodejsversion'] = public.readFile(self.setupPath + '/node.js/version.pl')
|
||||
data['php_other'] = ''
|
||||
if data['phpversion'] == 'other':
|
||||
other_file = '/www/server/panel/vhost/other_php/{}/enable-php-other.conf'.format(siteName)
|
||||
if os.path.exists(other_file):
|
||||
conf = public.readFile(other_file)
|
||||
data['php_other'] = re.findall(r"fastcgi_pass\s+(.+);",conf)[0]
|
||||
return data
|
||||
except:
|
||||
return public.returnMsg(False, 'SITE_PHPVERSION_ERR_A22,{}'.format(public.get_error_info()))
|
||||
@@ -3006,15 +3033,57 @@ server
|
||||
def SetPHPVersion(self, get, multiple=None):
|
||||
siteName = get.siteName
|
||||
version = get.version
|
||||
if version == 'other' and not public.get_webserver() in ['nginx','tengine']:
|
||||
return public.returnMsg(False,'Custom PHP configuration only supports Nginx')
|
||||
try:
|
||||
# nginx
|
||||
file = self.setupPath + '/panel/vhost/nginx/' + siteName + '.conf'
|
||||
conf = public.readFile(file)
|
||||
if conf:
|
||||
rep = "enable-php-([0-9]{2,3})\.conf"
|
||||
tmp = re.search(rep, conf).group()
|
||||
conf = conf.replace(tmp, 'enable-php-' + version + '.conf')
|
||||
public.writeFile(file, conf)
|
||||
other_path = '/www/server/panel/vhost/other_php/{}'.format(siteName)
|
||||
if not os.path.exists(other_path): os.makedirs(other_path)
|
||||
other_rep = "{}/enable-php-other.conf".format(other_path)
|
||||
|
||||
|
||||
if version == 'other':
|
||||
dst = other_rep
|
||||
get.other = get.other.strip()
|
||||
|
||||
if not get.other:
|
||||
return public.returnMsg(False,'The PHP connection configuration cannot be empty when customizing the version!')
|
||||
|
||||
if not re.match(r"^(\d+\.\d+\.\d+\.\d+:\d+|unix:[\w/\.-]+)$",get.other):
|
||||
return public.returnMsg(False,'The PHP connection configuration format is incorrect, please refer to the example!')
|
||||
|
||||
other_tmp = get.other.split(':')
|
||||
if other_tmp[0] == 'unix':
|
||||
if not os.path.exists(other_tmp[1]):
|
||||
return public.returnMsg(False,'The specified unix socket [{}] does not exist!'.format(other_tmp[1]))
|
||||
else:
|
||||
if not public.check_tcp(other_tmp[0],int(other_tmp[1])):
|
||||
return public.returnMsg(False,'Unable to connect to [{}], please check whether the machine can connect to the target server'.format(get.other))
|
||||
|
||||
other_conf = '''location ~ [^/]\.php(/|$)
|
||||
{{
|
||||
try_files $uri =404;
|
||||
fastcgi_pass {};
|
||||
fastcgi_index index.php;
|
||||
include fastcgi.conf;
|
||||
include pathinfo.conf;
|
||||
}}'''.format(get.other)
|
||||
public.writeFile(other_rep,other_conf)
|
||||
conf = conf.replace(other_rep,dst)
|
||||
rep = "include\s+enable-php-(\w{2,5})\.conf"
|
||||
tmp = re.search(rep,conf)
|
||||
if tmp: conf = conf.replace(tmp.group(),'include ' + dst)
|
||||
else:
|
||||
dst = 'enable-php-'+version+'.conf'
|
||||
conf = conf.replace(other_rep,dst)
|
||||
rep = "enable-php-(\w{2,5})\.conf"
|
||||
tmp = re.search(rep,conf)
|
||||
if tmp: conf = conf.replace(tmp.group(),dst)
|
||||
|
||||
public.writeFile(file,conf)
|
||||
try:
|
||||
import site_dir_auth
|
||||
site_dir_auth_module = site_dir_auth.SiteDirAuth()
|
||||
@@ -3028,23 +3097,25 @@ server
|
||||
site_dir_auth_module.change_dir_auth_file_nginx_phpver(siteName,version,auth_name)
|
||||
except:
|
||||
pass
|
||||
# apache
|
||||
file = self.setupPath + '/panel/vhost/apache/' + siteName + '.conf'
|
||||
|
||||
#apache
|
||||
file = self.setupPath + '/panel/vhost/apache/'+siteName+'.conf'
|
||||
conf = public.readFile(file)
|
||||
if conf:
|
||||
rep = "(unix:/tmp/php-cgi-([0-9]{2,3})\.sock\|fcgi://localhost|fcgi://127.0.0.1:\d+)"
|
||||
tmp = re.search(rep, conf).group()
|
||||
conf = conf.replace(tmp, public.get_php_proxy(version, 'apache'))
|
||||
public.writeFile(file, conf)
|
||||
# OLS
|
||||
file = self.setupPath + '/panel/vhost/openlitespeed/detail/' + siteName + '.conf'
|
||||
conf = public.readFile(file)
|
||||
if conf:
|
||||
rep = 'lsphp\d+'
|
||||
tmp = re.search(rep, conf)
|
||||
if tmp:
|
||||
conf = conf.replace(tmp.group(), 'lsphp' + version)
|
||||
public.writeFile(file, conf)
|
||||
if conf and version != 'other':
|
||||
rep = "(unix:/tmp/php-cgi-(\w{2,5})\.sock\|fcgi://localhost|fcgi://127.0.0.1:\d+)"
|
||||
tmp = re.search(rep,conf).group()
|
||||
conf = conf.replace(tmp,public.get_php_proxy(version,'apache'))
|
||||
public.writeFile(file,conf)
|
||||
#OLS
|
||||
if version != 'other':
|
||||
file = self.setupPath + '/panel/vhost/openlitespeed/detail/'+siteName+'.conf'
|
||||
conf = public.readFile(file)
|
||||
if conf:
|
||||
rep = 'lsphp\d+'
|
||||
tmp = re.search(rep, conf)
|
||||
if tmp:
|
||||
conf = conf.replace(tmp.group(), 'lsphp' + version)
|
||||
public.writeFile(file, conf)
|
||||
if not multiple:
|
||||
public.serviceReload()
|
||||
public.WriteLog("TYPE_SITE", "SITE_PHPVERSION_SUCCESS", (siteName, version))
|
||||
@@ -3162,12 +3233,10 @@ server
|
||||
return json.loads(upBody)
|
||||
|
||||
# 写配置
|
||||
|
||||
def __write_config(self, path, data):
|
||||
return public.writeFile(path, json.dumps(data))
|
||||
|
||||
# 取某个站点某条反向代理详情
|
||||
|
||||
def GetProxyDetals(self, get):
|
||||
proxyUrl = self.__read_config(self.__proxyfile)
|
||||
sitename = get.sitename
|
||||
@@ -3306,7 +3375,6 @@ server
|
||||
if i["sitename"] == get.sitename:
|
||||
if i["advanced"] != int(get.advanced):
|
||||
return i
|
||||
|
||||
# 计算proxyname md5
|
||||
def __calc_md5(self, proxyname):
|
||||
md5 = hashlib.md5()
|
||||
@@ -3368,8 +3436,8 @@ server
|
||||
return public.returnMsg(False, "PROXY_DIR_ERR", ("?,=,[,],),(,*,&,^,%,$,#,@,!,~,`,{,},>,<,\,',\"]",))
|
||||
# 检测发送域名格式
|
||||
if get.todomain:
|
||||
if not re.search(tod, get.todomain):
|
||||
return public.returnMsg(False, 'SENT_DOMAIN_FORMAT', (get.todomain,))
|
||||
if re.search("[\}\{\#\;\"\']+",get.todomain):
|
||||
return public.returnMsg(False, 'Sent Domain format error :'+get.todomain+'<br>The following special characters cannot exist [ } { # ; \" \' ] ')
|
||||
if public.get_webserver() != 'openlitespeed' and not get.todomain:
|
||||
get.todomain = "$host"
|
||||
|
||||
@@ -3648,7 +3716,11 @@ RewriteRule ^%s(.*)$ http://%s/$1 [P,E=Proxy-Host:%s]
|
||||
ng_conf = re.sub("location\s+\~\*\s+\\\.\(gif.*\n\{\s*proxy_pass\s+%s.*" % (php_pass_proxy),
|
||||
"location ~* \.(gif|png|jpg|css|js|woff|woff2)$\n{\n\tproxy_pass %s;" % php_pass_proxy,ng_conf)
|
||||
|
||||
ng_conf = re.sub("\sHost\s+%s" % '\\' + conf[i]["todomain"]," Host "+get.todomain,ng_conf)
|
||||
backslash = ""
|
||||
if "Host $host" in ng_conf:
|
||||
backslash = "\\"
|
||||
|
||||
ng_conf = re.sub("\sHost\s+%s" % backslash + conf[i]["todomain"], " Host " + get.todomain, ng_conf)
|
||||
cache_rep = r"proxy_cache_valid\s+200\s+304\s+301\s+302\s+\d+m;((\n|.)+expires\s+\d+m;)*"
|
||||
if int(get.cache) == 1:
|
||||
if re.search(cache_rep, ng_conf):
|
||||
|
||||
+550
-97
@@ -49,7 +49,6 @@ def HttpGet(url,timeout = 6,headers = {}):
|
||||
import http_requests
|
||||
res = http_requests.get(url,timeout=timeout,headers = headers)
|
||||
if res.status_code == 0:
|
||||
if old_url.find(home) != -1: return http_get_home(old_url,timeout,res.text)
|
||||
if headers: return False
|
||||
s_body = res.text
|
||||
return s_body
|
||||
@@ -113,43 +112,12 @@ def HttpPost(url,data,timeout = 6,headers = {}):
|
||||
import http_requests
|
||||
res = http_requests.post(url,data=data,timeout=timeout,headers = headers)
|
||||
if res.status_code == 0:
|
||||
if old_url.find(home) != -1: return http_post_home(old_url,data,timeout,res.text)
|
||||
if headers: return False
|
||||
s_body = res.text
|
||||
return s_body
|
||||
s_body = res.text
|
||||
return s_body
|
||||
|
||||
|
||||
def http_post_home(url,data,timeout,ex):
|
||||
"""
|
||||
@name POST方式使用优选节点访问官网
|
||||
@author hwliang<hwl@bt.cn>
|
||||
@param url(string) 当前官网URL地址
|
||||
@param data(dict) POST数据
|
||||
@param timeout(int) 用于测试超时时间
|
||||
@param ex(string) 上一次错误的响应内容
|
||||
@return string 响应内容
|
||||
|
||||
如果已经是优选节点,将直接返回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}
|
||||
for host in hosts:
|
||||
new_url = url.replace(home, host)
|
||||
res = HttpPost(new_url, data, timeout, headers)
|
||||
if res:
|
||||
writeFile("data/home_host.pl", host)
|
||||
# set_home_host(host)
|
||||
return res
|
||||
return ex
|
||||
except: return ex
|
||||
|
||||
def httpPost(url,data,timeout=6):
|
||||
"""
|
||||
@name 发送POST请求
|
||||
@@ -200,7 +168,6 @@ def FileMd5(filename):
|
||||
f.close()
|
||||
return my_hash.hexdigest()
|
||||
|
||||
|
||||
def GetRandomString(length):
|
||||
"""
|
||||
@name 取随机字符串
|
||||
@@ -336,6 +303,13 @@ def ReadFile(filename,mode = 'r'):
|
||||
return f_body
|
||||
|
||||
def readFile(filename,mode='r'):
|
||||
'''
|
||||
@name 读取指定文件数据
|
||||
@author hwliang<2021-06-09>
|
||||
@param filename<string> 文件名
|
||||
@param mode<string> 文件打开模式,默认r
|
||||
@return string or bytes or False 如果返回False则说明读取失败
|
||||
'''
|
||||
return ReadFile(filename,mode)
|
||||
|
||||
def WriteFile(filename,s_body,mode='w+'):
|
||||
@@ -360,6 +334,14 @@ def WriteFile(filename,s_body,mode='w+'):
|
||||
return False
|
||||
|
||||
def writeFile(filename,s_body,mode='w+'):
|
||||
'''
|
||||
@name 写入到指定文件
|
||||
@author hwliang<2021-06-09>
|
||||
@param filename<string> 文件名
|
||||
@param s_boey<string/bytes> 被写入的内容,字节或字符串
|
||||
@param mode<string> 文件打开模式,默认w+
|
||||
@return bool
|
||||
'''
|
||||
return WriteFile(filename,s_body,mode)
|
||||
|
||||
def WriteLog(type,logMsg,args=(),not_web = False):
|
||||
@@ -409,7 +391,9 @@ def GetConfigValue(key):
|
||||
取配置值
|
||||
'''
|
||||
config = GetConfig()
|
||||
if not key in config.keys(): return None
|
||||
if not key in config.keys():
|
||||
if key == 'download': return 'https://node.aapanel.com'
|
||||
return None
|
||||
return config[key]
|
||||
|
||||
def SetConfigValue(key,value):
|
||||
@@ -495,7 +479,7 @@ def serviceReload():
|
||||
return ServiceReload()
|
||||
|
||||
|
||||
def ExecShell(cmdstring, cwd=None, timeout=None, shell=True):
|
||||
def ExecShell(cmdstring, timeout=None, shell=True,cwd=None,env=None):
|
||||
a = ''
|
||||
e = ''
|
||||
import subprocess,tempfile
|
||||
@@ -504,8 +488,20 @@ def ExecShell(cmdstring, cwd=None, timeout=None, shell=True):
|
||||
rx = md5(cmdstring)
|
||||
succ_f = tempfile.SpooledTemporaryFile(max_size=4096,mode='wb+',suffix='_succ',prefix='btex_' + rx ,dir='/dev/shm')
|
||||
err_f = tempfile.SpooledTemporaryFile(max_size=4096,mode='wb+',suffix='_err',prefix='btex_' + rx ,dir='/dev/shm')
|
||||
sub = subprocess.Popen(cmdstring, close_fds=True, shell=shell,bufsize=128,stdout=succ_f,stderr=err_f)
|
||||
sub.wait()
|
||||
sub = subprocess.Popen(cmdstring, close_fds=True, shell=shell,bufsize=128,stdout=succ_f,stderr=err_f,cwd=cwd,env=env)
|
||||
if timeout:
|
||||
s = 0
|
||||
d = 0.01
|
||||
while sub.poll() is None:
|
||||
time.sleep(d)
|
||||
s += d
|
||||
if s >= timeout:
|
||||
if not err_f.closed: err_f.close()
|
||||
if not succ_f.closed: succ_f.close()
|
||||
return 'Timed out'
|
||||
else:
|
||||
sub.wait()
|
||||
|
||||
err_f.seek(0)
|
||||
succ_f.seek(0)
|
||||
a = succ_f.read()
|
||||
@@ -513,7 +509,7 @@ def ExecShell(cmdstring, cwd=None, timeout=None, shell=True):
|
||||
if not err_f.closed: err_f.close()
|
||||
if not succ_f.closed: succ_f.close()
|
||||
except:
|
||||
print(get_error_info())
|
||||
return '',get_error_info()
|
||||
try:
|
||||
#编码修正
|
||||
if type(a) == bytes: a = a.decode('utf-8')
|
||||
@@ -600,7 +596,9 @@ def phpReload(version):
|
||||
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')
|
||||
ExecShell("/etc/init.d/php-fpm-{} start".format(version))
|
||||
|
||||
|
||||
def get_timeout(url,timeout=3):
|
||||
try:
|
||||
@@ -610,6 +608,8 @@ def get_timeout(url,timeout=3):
|
||||
except: return 0,False
|
||||
|
||||
def get_url(timeout = 0.5):
|
||||
return 'https://node.aapanel.com'
|
||||
|
||||
import json
|
||||
try:
|
||||
pkey = 'node_url'
|
||||
@@ -824,6 +824,9 @@ def getSpeed():
|
||||
writeFile('/tmp/panelSpeed.pl', data)
|
||||
return json.loads(data)
|
||||
|
||||
def get_requests_headers():
|
||||
return {"Content-type":"application/x-www-form-urlencoded","User-Agent":"BT-Panel"}
|
||||
|
||||
def downloadFile(url,filename):
|
||||
try:
|
||||
if sys.version_info[0] == 2:
|
||||
@@ -834,16 +837,30 @@ def downloadFile(url,filename):
|
||||
f.write(r.content)
|
||||
else:
|
||||
import urllib.request
|
||||
import ssl
|
||||
ssl._create_default_https_context = ssl._create_unverified_context
|
||||
opener = urllib.request.build_opener()
|
||||
opener.addheaders = [('User-agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36')]
|
||||
urllib.request.install_opener(opener)
|
||||
urllib.request.urlretrieve(url, filename=filename, reporthook=downloadHook)
|
||||
urllib.request.urlretrieve(url, filename=filename)
|
||||
except:
|
||||
return get_error_info()
|
||||
ExecShell("wget -O --no-check-certificate {} {}".format(filename,url))
|
||||
|
||||
def exists_args(args,get):
|
||||
'''
|
||||
@name 检查参数是否存在
|
||||
@author hwliang<2021-06-08>
|
||||
@param args<list or str> 参数列表 允许是列表或字符串
|
||||
@param get<dict_obj> 参数对像
|
||||
@return bool 都存在返回True,否则抛出KeyError异常
|
||||
'''
|
||||
if type(args) == str:
|
||||
args = args.split(',')
|
||||
for arg in args:
|
||||
if not arg in get:
|
||||
raise KeyError('Required parameters are missing:{}'.format(arg))
|
||||
return True
|
||||
|
||||
def downloadHook(count, blockSize, totalSize):
|
||||
speed = {'total':totalSize,'block':blockSize,'count':count}
|
||||
#print('%02d%%'%(100.0 * count * blockSize / totalSize))
|
||||
|
||||
def get_error_info():
|
||||
import traceback
|
||||
@@ -851,6 +868,78 @@ def get_error_info():
|
||||
return errorMsg
|
||||
|
||||
|
||||
def get_plugin_replace_rules():
|
||||
'''
|
||||
@name 获取插件文件内容替换规则
|
||||
@author hwliang<2021-06-28>
|
||||
@return list
|
||||
'''
|
||||
return [
|
||||
{
|
||||
"find":"[PATH]",
|
||||
"replace": "[PATH]"
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def get_plugin_title(plugin_name):
|
||||
'''
|
||||
@name 获取插件标题
|
||||
@author hwliang<2021-06-24>
|
||||
@param plugin_name<string> 插件名称
|
||||
@return string
|
||||
'''
|
||||
|
||||
info_file = '/www/server/panel/plugin/{}/info.json'.format(plugin_name)
|
||||
try:
|
||||
return json.loads(readFile(info_file))['title']
|
||||
except:
|
||||
return plugin_name
|
||||
|
||||
def get_error_object(plugin_title = None,plugin_name = None):
|
||||
'''
|
||||
@name 获取格式化错误响应对像
|
||||
@author hwliang<2021-06-21>
|
||||
@return Resp
|
||||
'''
|
||||
if not plugin_title: plugin_title = get_plugin_title(plugin_name)
|
||||
try:
|
||||
from BTPanel import request,Resp
|
||||
is_cli = False
|
||||
except:
|
||||
is_cli = True
|
||||
|
||||
if is_cli:
|
||||
raise get_error_info()
|
||||
ss = '''404 Not Found: The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
|
||||
|
||||
During handling of the above exception, another exception occurred:'''
|
||||
error_info = get_error_info().strip().split(ss)[-1].strip()
|
||||
request_info = '''REQUEST_DATE: {request_date}
|
||||
PAN_VERSION: {panel_version}
|
||||
OS_VERSION: {os_version}
|
||||
REMOTE_ADDR: {remote_addr}
|
||||
REQUEST_URI: {method} {full_path}
|
||||
REQUEST_FORM: {request_form}
|
||||
USER_AGENT: {user_agent}'''.format(
|
||||
request_date = getDate(),
|
||||
remote_addr = GetClientIp(),
|
||||
method = request.method,
|
||||
full_path = request.full_path,
|
||||
request_form = request.form.to_dict(),
|
||||
user_agent = request.headers.get('User-Agent'),
|
||||
panel_version = get_panel_version(),
|
||||
os_version = get_os_version()
|
||||
)
|
||||
|
||||
result =readFile('/www/server/panel/BTPanel/templates/default/plugin_error.html').format(
|
||||
plugin_name=plugin_title,
|
||||
request_info=request_info,
|
||||
error_title=error_info.split("\n")[-1],
|
||||
error_msg=error_info
|
||||
)
|
||||
return Resp(result,500)
|
||||
|
||||
# 搜索数据中是否存在
|
||||
def inArray(arrays, searchStr):
|
||||
for key in arrays:
|
||||
@@ -1233,6 +1322,22 @@ def get_uuid():
|
||||
import uuid
|
||||
return uuid.UUID(int=uuid.getnode()).hex[-12:]
|
||||
|
||||
#取计算机名
|
||||
def get_hostname():
|
||||
import socket
|
||||
return socket.gethostname()
|
||||
|
||||
|
||||
#取mysql datadir
|
||||
def get_datadir():
|
||||
mycnf_file = '/etc/my.cnf'
|
||||
if not os.path.exists(mycnf_file): return ''
|
||||
mycnf = readFile(mycnf_file)
|
||||
import re
|
||||
tmp = re.findall(r"datadir\s*=\s*(.+)",mycnf)
|
||||
if not tmp: return ''
|
||||
return tmp[0]
|
||||
|
||||
|
||||
#进程是否存在
|
||||
def process_exists(pname,exe = None,cmdline = None):
|
||||
@@ -1253,8 +1358,13 @@ def process_exists(pname,exe = None,cmdline = None):
|
||||
except:
|
||||
pass
|
||||
return False
|
||||
except:
|
||||
except: return True
|
||||
|
||||
#pid是否存在
|
||||
def pid_exists(pid):
|
||||
if os.path.exists('/proc/{}/exe'.format(pid)):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
# 重启面板
|
||||
@@ -1359,18 +1469,79 @@ def get_panel_version():
|
||||
return version
|
||||
|
||||
|
||||
# 取文件或目录大小
|
||||
def get_path_size(path):
|
||||
def get_os_version():
|
||||
'''
|
||||
@name 取操作系统版本
|
||||
@author hwliang<2021-08-07>
|
||||
@return string
|
||||
'''
|
||||
version = readFile('/etc/redhat-release')
|
||||
if not version:
|
||||
version = 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 = "{} {}(Py{}.{}.{})".format(version,os.uname().machine,v_info.major,v_info.minor,v_info.micro)
|
||||
return version
|
||||
|
||||
#取文件或目录大小
|
||||
def get_path_size(path, exclude=[]):
|
||||
"""根据排除目录获取路径的总大小
|
||||
|
||||
:path 目标路径
|
||||
:exclude 排除路径单个字符串或者多个列表。匹配路径是基于path的相对路径,规则是
|
||||
tar命令的--exclude规则的子集。
|
||||
"""
|
||||
import fnmatch
|
||||
if not os.path.exists(path): return 0
|
||||
if not os.path.isdir(path): return os.path.getsize(path)
|
||||
size_total = 0
|
||||
for nf in os.walk(path):
|
||||
for f in nf[2]:
|
||||
filename = nf[0] + '/' + f
|
||||
if os.path.isfile(path): return os.path.getsize(path)
|
||||
if type(exclude) != type([]):
|
||||
exclude = [exclude]
|
||||
|
||||
path = path[0:-1] if path[-1] == "/" else path
|
||||
path = os.path.normcase(path)
|
||||
# print("path:"+ path)
|
||||
# print("exclude:"+ str(exclude))
|
||||
_exclude = exclude[0:]
|
||||
for i, e in enumerate(_exclude):
|
||||
if not e.startswith(path):
|
||||
basename = os.path.basename(path)
|
||||
if not e.startswith(basename):
|
||||
exclude.append(os.path.join(path, e))
|
||||
else:
|
||||
new_exc = e.replace(basename+"/", "")
|
||||
new_exc = os.path.join(path, new_exc)
|
||||
exclude.append(new_exc)
|
||||
|
||||
# print(exclude)
|
||||
total_size = 0
|
||||
count = 0
|
||||
for root, dirs, files in os.walk(path, topdown=True):
|
||||
# filter path
|
||||
for exc in exclude:
|
||||
for d in dirs:
|
||||
sub_dir = os.path.normcase(root+os.path.sep+d)
|
||||
if fnmatch.fnmatch(sub_dir, exc) or d==exc:
|
||||
# print("排除目录:"+sub_dir)
|
||||
dirs.remove(d)
|
||||
count += 1
|
||||
for f in files:
|
||||
to_exclude = False
|
||||
count += 1
|
||||
filename = os.path.normcase(root+os.path.sep+f)
|
||||
if not os.path.exists(filename): continue
|
||||
if os.path.islink(filename): continue
|
||||
size_total += os.path.getsize(filename)
|
||||
return size_total
|
||||
# filter file
|
||||
norm_filename = os.path.normcase(filename)
|
||||
for fexc in exclude:
|
||||
if fnmatch.fnmatch(norm_filename, fexc) or fexc==f:
|
||||
to_exclude = True
|
||||
# print("排除文件:"+norm_filename)
|
||||
break
|
||||
if to_exclude:
|
||||
continue
|
||||
total_size += os.path.getsize(filename)
|
||||
return total_size
|
||||
|
||||
#写关键请求日志
|
||||
def write_request_log(reques = None):
|
||||
@@ -1533,22 +1704,54 @@ def de_crypt(key,strings):
|
||||
return strings
|
||||
|
||||
|
||||
#获取IP限制列表
|
||||
def get_limit_ip():
|
||||
iplong_list = []
|
||||
ip_file = 'data/limitip.conf'
|
||||
if not os.path.exists(ip_file): return iplong_list
|
||||
|
||||
from BTPanel import cache
|
||||
ikey = 'limit_ip'
|
||||
iplong_list = cache.get(ikey)
|
||||
if iplong_list: return iplong_list
|
||||
|
||||
iplong_list = []
|
||||
iplist = ReadFile(ip_file)
|
||||
if not iplist:return iplong_list
|
||||
iplist = iplist.strip()
|
||||
for limit_ip in iplist.split(','):
|
||||
if not limit_ip: continue
|
||||
limit_ip = limit_ip.split('-')
|
||||
iplong = {}
|
||||
iplong['min'] = ip2long(limit_ip[0])
|
||||
if len(limit_ip) > 1:
|
||||
iplong['max'] = ip2long(limit_ip[1])
|
||||
else:
|
||||
iplong['max'] = iplong['min']
|
||||
iplong_list.append(iplong)
|
||||
|
||||
cache.set(ikey,iplong_list,3600)
|
||||
return iplong_list
|
||||
|
||||
|
||||
|
||||
|
||||
#检查IP白名单
|
||||
def check_ip_panel():
|
||||
ip_file = 'data/limitip.conf'
|
||||
if os.path.exists(ip_file):
|
||||
iplist = ReadFile(ip_file)
|
||||
if iplist:
|
||||
iplist = iplist.strip()
|
||||
client_ip = GetClientIp()
|
||||
if client_ip in ['127.0.0.1','localhost','::1']: return False
|
||||
if not client_ip in iplist.split(','):
|
||||
errorStr = ReadFile('./BTPanel/templates/' + GetConfigValue('template') + '/error2.html')
|
||||
try:
|
||||
errorStr = errorStr.format(getMsg('PAGE_ERR_TITLE'),getMsg('PAGE_ERR_IP_H1'),getMsg('PAGE_ERR_IP_P1',(GetClientIp(),)),getMsg('PAGE_ERR_IP_P2'),getMsg('PAGE_ERR_IP_P3'),getMsg('NAME'),getMsg('PAGE_ERR_HELP'))
|
||||
except IndexError:pass
|
||||
return errorStr
|
||||
return False
|
||||
iplong_list = get_limit_ip()
|
||||
if not iplong_list: return False
|
||||
client_ip = GetClientIp()
|
||||
if client_ip in ['127.0.0.1','localhost','::1']: return False
|
||||
client_ip_long = ip2long(client_ip)
|
||||
for limit_ip in iplong_list:
|
||||
if client_ip_long >= limit_ip['min'] and client_ip_long <= limit_ip['max']:
|
||||
return False
|
||||
|
||||
errorStr = ReadFile('./BTPanel/templates/' + GetConfigValue('template') + '/error2.html')
|
||||
try:
|
||||
errorStr = errorStr.format(getMsg('PAGE_ERR_TITLE'),getMsg('PAGE_ERR_IP_H1'),getMsg('PAGE_ERR_IP_P1',(GetClientIp(),)),getMsg('PAGE_ERR_IP_P2'),getMsg('PAGE_ERR_IP_P3'),getMsg('NAME'),getMsg('PAGE_ERR_HELP'))
|
||||
except IndexError:pass
|
||||
return errorStr
|
||||
|
||||
#检查面板域名
|
||||
def check_domain_panel():
|
||||
@@ -1625,7 +1828,7 @@ def sync_date():
|
||||
if os.path.exists(tip_file):
|
||||
if s_time - int(readFile(tip_file)) < 60: return False
|
||||
os.remove(tip_file)
|
||||
time_str = HttpGet('http://www.bt.cn/api/index/get_time')
|
||||
time_str = HttpGet(GetConfigValue('home') + '/api/index/get_time')
|
||||
new_time = int(time_str)
|
||||
time_arr = time.localtime(new_time)
|
||||
date_str = time.strftime("%Y-%m-%d %H:%M:%S", time_arr)
|
||||
@@ -1724,7 +1927,7 @@ def request_php(version,uri,document_root,method='GET',pdata=b''):
|
||||
return result
|
||||
|
||||
|
||||
def get_fpm_address(php_version):
|
||||
def get_fpm_address(php_version,bind=False):
|
||||
'''
|
||||
@name 获取FPM请求地址
|
||||
@author hwliang<2020-10-23>
|
||||
@@ -1740,7 +1943,10 @@ def get_fpm_address(php_version):
|
||||
if tmp[0].find('sock') != -1: return fpm_address
|
||||
if tmp[0].find(':') != -1:
|
||||
listen_tmp = tmp[0].split(':')
|
||||
fpm_address = ('127.0.0.1',int(listen_tmp[1]))
|
||||
if bind:
|
||||
fpm_address = (listen_tmp[0],int(listen_tmp[1]))
|
||||
else:
|
||||
fpm_address = ('127.0.0.1',int(listen_tmp[1]))
|
||||
else:
|
||||
fpm_address = ('127.0.0.1',int(tmp[0]))
|
||||
return fpm_address
|
||||
@@ -1777,7 +1983,7 @@ def get_php_version_conf(conf):
|
||||
'''
|
||||
if not conf: return '00'
|
||||
if conf.find('enable-php-') != -1:
|
||||
rep = r"enable-php-([0-9]{2,3})\.conf"
|
||||
rep = r"enable-php-(\w{2,5})\.conf"
|
||||
tmp = re.findall(rep,conf)
|
||||
if not tmp: return '00'
|
||||
elif conf.find('/usr/local/lsws/lsphp') != -1:
|
||||
@@ -1809,6 +2015,25 @@ def get_site_php_version(siteName):
|
||||
return get_php_version_conf(conf)
|
||||
|
||||
|
||||
def check_tcp(ip,port):
|
||||
'''
|
||||
@name 使用TCP的方式检测指定IP:端口是否能连接
|
||||
@author hwliang<2021-06-01>
|
||||
@param ip<string> IP地址
|
||||
@param port<int> 端口
|
||||
@return bool
|
||||
'''
|
||||
import socket
|
||||
try:
|
||||
s = socket.socket()
|
||||
s.settimeout(5)
|
||||
s.connect((ip.strip(),int(port)))
|
||||
s.close()
|
||||
except:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def sub_php_address(conf_file,rep,tsub,php_version):
|
||||
'''
|
||||
@name 替换新的PHP配置到配置文件
|
||||
@@ -2070,9 +2295,10 @@ def get_debug_log():
|
||||
|
||||
#获取sessionid
|
||||
def get_session_id():
|
||||
from BTPanel import request
|
||||
session_id = request.cookies.get('SESSIONID','')
|
||||
if not re.findall(r"^([\w\.-]{64,64})$",session_id): return GetRandomString(64)
|
||||
from BTPanel import request,app
|
||||
session_id = request.cookies.get(app.config['SESSION_COOKIE_NAME'],'')
|
||||
if not re.findall(r"^([\w\.-]{64,64})$",session_id):
|
||||
return GetRandomString(64)
|
||||
return session_id
|
||||
|
||||
#尝试自动恢复面板数据库
|
||||
@@ -2200,11 +2426,14 @@ def get_ssh_port():
|
||||
s_file = '/etc/ssh/sshd_config'
|
||||
conf = readFile(s_file)
|
||||
if not conf: conf = ''
|
||||
rep = r"#*Port\s+([0-9]+)\s*\n"
|
||||
tmp1 = re.search(rep, conf)
|
||||
port_all = re.findall(r".*Port\s+[0-9]+",conf)
|
||||
ssh_port = 22
|
||||
if tmp1:
|
||||
ssh_port = int(tmp1.groups(0)[0])
|
||||
for p in port_all:
|
||||
rep = r"^\s*Port\s+([0-9]+)\s*"
|
||||
tmp1 = re.findall(rep,p)
|
||||
if tmp1:
|
||||
ssh_port = int(tmp1[0])
|
||||
|
||||
return ssh_port
|
||||
|
||||
def set_error_num(key,empty = False,expire=3600):
|
||||
@@ -2386,6 +2615,8 @@ def cloud_check_domain(domain):
|
||||
check_domain_path = '/www/server/panel/data/check_domain/'
|
||||
if not os.path.exists(check_domain_path):
|
||||
os.makedirs(check_domain_path,384)
|
||||
pdata = get_user_info()
|
||||
pdata['domain'] = domain
|
||||
result = httpPost('https://www.aapanel.com/api/panel/checkDomain',{"domain":domain})
|
||||
cd_file = check_domain_path + domain +'.pl'
|
||||
writeFile(cd_file,result)
|
||||
@@ -2393,6 +2624,23 @@ def cloud_check_domain(domain):
|
||||
pass
|
||||
|
||||
|
||||
def get_user_info():
|
||||
user_file = '/www/server/panel/data/userInfo.json'
|
||||
if not os.path.exists(user_file): return {}
|
||||
userInfo = {}
|
||||
try:
|
||||
userTmp = json.loads(readFile(user_file))
|
||||
userInfo['uid'] = userTmp['id']
|
||||
userInfo['username'] = userTmp['username']
|
||||
userInfo['serverid'] = userTmp['serverid']
|
||||
userInfo['oem'] = get_oem_name()
|
||||
userInfo['o'] = userInfo['oem']
|
||||
except: pass
|
||||
return userInfo
|
||||
|
||||
|
||||
|
||||
|
||||
def send_file(data,fname='',mimetype = ''):
|
||||
'''
|
||||
@name 以文件流的形式返回
|
||||
@@ -2449,12 +2697,41 @@ def get_oem_name():
|
||||
@return string
|
||||
'''
|
||||
oem = ''
|
||||
oem_file = '/www/server/panel/data/o.pl'
|
||||
oem_file = '{}/data/o.pl'.format(get_panel_path())
|
||||
if os.path.exists(oem_file):
|
||||
oem = readFile(oem_file)
|
||||
if oem: oem = oem.strip()
|
||||
return oem
|
||||
|
||||
def get_pdata():
|
||||
'''
|
||||
@name 构造POST基础参数
|
||||
@author hwliang<2021-03-24>
|
||||
@return dict
|
||||
'''
|
||||
import panelAuth
|
||||
pdata = panelAuth.panelAuth().create_serverid(None)
|
||||
pdata['oem'] = get_oem_name()
|
||||
return pdata
|
||||
|
||||
|
||||
# 名称输入系列化
|
||||
def xssdecode(text):
|
||||
try:
|
||||
cs = {""":'"',"'":"'"}
|
||||
for c in cs.keys():
|
||||
text = text.replace(c,cs[c])
|
||||
|
||||
str_convert = text
|
||||
if sys.version_info[0] == 3:
|
||||
import html
|
||||
text2 = html.unescape(str_convert)
|
||||
else:
|
||||
text2 = cgi.unescape(str_convert)
|
||||
return text2
|
||||
except:
|
||||
return text
|
||||
|
||||
def fetch_disk_SN():
|
||||
r,e = ExecShell("fdisk -l |grep 'Disk identifier' |awk {'print $3'}")
|
||||
if r:
|
||||
@@ -2511,6 +2788,8 @@ class dict_obj:
|
||||
def __delitem__(self,key): delattr(self,key)
|
||||
def __delattr__(self, key): delattr(self,key)
|
||||
def get_items(self): return self
|
||||
def exists(self,keys):
|
||||
return exists_args(keys,self)
|
||||
def get(self,key,default='',format='',limit = []):
|
||||
'''
|
||||
@name 获取指定参数
|
||||
@@ -2659,7 +2938,7 @@ class get_modules:
|
||||
else:
|
||||
print(p.__dict__)
|
||||
'''
|
||||
os.chdir('/www/server/panel')
|
||||
os.chdir(get_panel_path())
|
||||
exp_files = ['__init__.py','__pycache__']
|
||||
if not path in sys.path:
|
||||
sys.path.insert(0,path)
|
||||
@@ -2685,7 +2964,7 @@ class get_modules:
|
||||
|
||||
#检查App和小程序的绑定
|
||||
def check_app(check='app'):
|
||||
path='/www/server/panel/'
|
||||
path=get_panel_path() + '/'
|
||||
if check=='app':
|
||||
try:
|
||||
if not os.path.exists(path+'data/user.json') and os.path.exists(path+'config/api.json') and not os.path.exists(path+'plugin/app/user.json'):return False
|
||||
@@ -2723,8 +3002,8 @@ def send_mail(title,body,is_logs=False,is_type="aapanel login reminder"):
|
||||
import send_mail
|
||||
send_mail22 = send_mail.send_mail()
|
||||
tongdao = send_mail22.get_settings()
|
||||
if tongdao['user_mail']['mail_list']==0:return false
|
||||
if not tongdao['user_mail']['info']: return false
|
||||
if tongdao['user_mail']['mail_list']==0:return False
|
||||
if not tongdao['user_mail']['info']: return False
|
||||
if len(tongdao['user_mail']['mail_list'])==1:
|
||||
send_mail=tongdao['user_mail']['mail_list'][0]
|
||||
send_mail22.qq_smtp_send(send_mail, title=title, body=body)
|
||||
@@ -2739,8 +3018,8 @@ def send_mail(title,body,is_logs=False,is_type="aapanel login reminder"):
|
||||
import send_mail
|
||||
send_mail22 = send_mail.send_mail()
|
||||
tongdao = send_mail22.get_settings()
|
||||
if tongdao['user_mail']['mail_list'] == 0: return false
|
||||
if not tongdao['user_mail']['info']: return false
|
||||
if tongdao['user_mail']['mail_list'] == 0: return False
|
||||
if not tongdao['user_mail']['info']: return False
|
||||
if len(tongdao['user_mail']['mail_list']) == 1:
|
||||
send_mail = tongdao['user_mail']['mail_list'][0]
|
||||
return send_mail22.qq_smtp_send(send_mail, title=title, body=body)
|
||||
@@ -2756,7 +3035,7 @@ def send_dingding(body,is_logs=False,is_type="aapanel login reminder"):
|
||||
import send_mail
|
||||
send_mail22 = send_mail.send_mail()
|
||||
tongdao = send_mail22.get_settings()
|
||||
if not tongdao['dingding']['info']: return false
|
||||
if not tongdao['dingding']['info']: return False
|
||||
tongdao = send_mail22.get_settings()
|
||||
if is_logs:
|
||||
WriteLog2(is_type,body)
|
||||
@@ -2768,15 +3047,16 @@ def send_dingding(body,is_logs=False,is_type="aapanel login reminder"):
|
||||
import send_mail
|
||||
send_mail22 = send_mail.send_mail()
|
||||
tongdao = send_mail22.get_settings()
|
||||
if not tongdao['dingding']['info']: return false
|
||||
if not tongdao['dingding']['info']: return False
|
||||
tongdao = send_mail22.get_settings()
|
||||
return send_mail22.dingding_send(body)
|
||||
except:return False
|
||||
|
||||
#获取服务器IP
|
||||
def get_ip():
|
||||
if os.path.exists('/www/server/panel/data/iplist.txt'):
|
||||
data=ReadFile('/www/server/panel/data/iplist.txt')
|
||||
iplist_file = '{}/data/iplist.txt'.format(get_panel_path())
|
||||
if os.path.exists(iplist_file):
|
||||
data=ReadFile(iplist_file)
|
||||
return data.strip()
|
||||
else:return '127.0.0.1'
|
||||
|
||||
@@ -2825,11 +3105,14 @@ def check_ip_white(path,ip):
|
||||
|
||||
#登陆告警
|
||||
def login_send_body(is_type,username,login_ip,port):
|
||||
if os.path.exists("/www/server/panel/data/login_send_mail.pl"):
|
||||
if check_ip_white('/www/server/panel/data/send_login_white.json',login_ip):return False
|
||||
login_send_mail = "{}/data/login_send_mail.pl".format(get_panel_path())
|
||||
send_login_white = '{}/data/send_login_white.json'.format(get_panel_path())
|
||||
login_send_dingding = "{}/data/login_send_dingding.pl".format(get_panel_path())
|
||||
if os.path.exists(login_send_mail):
|
||||
if check_ip_white(send_login_white,login_ip):return False
|
||||
send_mail("aapanel login reminder","aapanel login reminder:Your server "+get_ip()+" successfully logged in via "+is_type+", account number: "+username+", login IP: "+login_ip+":"+port+", login time: "+time.strftime('%Y -%m-%d %X',time.localtime()), True)
|
||||
if os.path.exists("/www/server/panel/data/login_send_dingding.pl"):
|
||||
if check_ip_white('/www/server/panel/data/send_login_white.json',login_ip):return False
|
||||
if os.path.exists(login_send_dingding):
|
||||
if check_ip_white(send_login_white,login_ip):return False
|
||||
send_dingding("aapanel login reminder:Your server "+get_ip()+" successfully logged in via "+is_type+", account number: "+username+", login IP: "+login_ip+":"+port+", login time: "+time.strftime('%Y -%m-%d %X',time.localtime()), True)
|
||||
|
||||
#普通模式下调用发送消息【设置登陆告警后的设置】
|
||||
@@ -2838,11 +3121,14 @@ def login_send_body(is_type,username,login_ip,port):
|
||||
#is_logs= 是否记录日志
|
||||
#is_type=发送告警的类型
|
||||
def send_to_body(title,body,is_logs=False,is_type="aaPanel email alert"):
|
||||
if os.path.exists("/www/server/panel/data/login_send_mail.pl"):
|
||||
login_send_mail = "{}/data/login_send_mail.pl".format(get_panel_path())
|
||||
login_send_dingding = "{}/data/login_send_dingding.pl".format(get_panel_path())
|
||||
if os.path.exists(login_send_mail):
|
||||
if is_logs:
|
||||
send_mail(title, body,True,is_type)
|
||||
send_mail(title,body)
|
||||
if os.path.exists("/www/server/panel/data/login_send_dingding.pl"):
|
||||
|
||||
if os.path.exists(login_send_dingding):
|
||||
if is_logs:
|
||||
send_dingding(body,True,is_type)
|
||||
send_dingding(body)
|
||||
@@ -2864,4 +3150,171 @@ def return_is_send_info():
|
||||
ret={}
|
||||
ret['mail']=tongdao['user_mail']['user_name']
|
||||
ret['dingding']=tongdao['dingding']['dingding']
|
||||
return ret
|
||||
return ret
|
||||
|
||||
|
||||
def get_sys_path():
|
||||
'''
|
||||
@name 关键目录
|
||||
@author hwliang<2021-06-11>
|
||||
@return tuple
|
||||
'''
|
||||
a = ['/www','/usr','/','/dev','/home','/media','/mnt','/opt','/tmp','/var']
|
||||
c = ['/www/Recycle_bin/','/www/backup/','/www/php_session/','/www/wwwlogs/','/www/server/','/etc/','/usr/','/var/','/boot/','/proc/','/sys/','/tmp/','/root/','/lib/','/bin/','/sbin/','/run/','/lib64/','/lib32/','/srv/']
|
||||
return a,c
|
||||
|
||||
|
||||
def check_site_path(site_path):
|
||||
'''
|
||||
@name 检查网站根目录是否为系统关键目录
|
||||
@author hwliang<2021-05-31>
|
||||
@param site_path<string> 网站根目录全路径
|
||||
@return bool
|
||||
'''
|
||||
whites = ['/www/server/tomcat','/www/server/stop','/www/server/phpmyadmin']
|
||||
for w in whites:
|
||||
if site_path.find(w) == 0: return True
|
||||
a,error_paths = get_sys_path()
|
||||
site_path = site_path.strip()
|
||||
if site_path[-1] == '/': site_path = site_path[:-1]
|
||||
if site_path in a:
|
||||
return False
|
||||
site_path += '/'
|
||||
for ep in error_paths:
|
||||
if site_path.find(ep) == 0: return False
|
||||
return True
|
||||
|
||||
def is_debug():
|
||||
debug_file = "{}/data/debug.pl".format(get_panel_path())
|
||||
return os.path.exists(debug_file)
|
||||
|
||||
|
||||
class PanelError(Exception):
|
||||
'''
|
||||
@name 宝塔通用异常对像
|
||||
@author hwliang<2021-06-25>
|
||||
'''
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def __str__(self):
|
||||
return ("面板运行时发生错误: {}".format(repr(self.value)))
|
||||
|
||||
def get_setup_path():
|
||||
'''
|
||||
@name 获取安装路径
|
||||
@author hwliang<2021-07-22>
|
||||
@return string
|
||||
'''
|
||||
return '/www/server'
|
||||
|
||||
def get_panel_path():
|
||||
'''
|
||||
@name 取面板根目录
|
||||
@author hwliang<2021-07-14>
|
||||
@return string
|
||||
'''
|
||||
return '{}/panel'.format(get_setup_path())
|
||||
|
||||
def check_hooks():
|
||||
'''
|
||||
@name 自动注册HOOK
|
||||
@author hwliang<2021-07-19>
|
||||
@return void
|
||||
'''
|
||||
hooks_path = '{}/hooks'.format(get_panel_path())
|
||||
if not os.path.exists(hooks_path):
|
||||
return
|
||||
for hook_name in os.listdir(hooks_path):
|
||||
if hook_name[-3:] != '.py': continue
|
||||
filename = os.path.join(hooks_path,hook_name)
|
||||
_obj = get_script_object(filename)
|
||||
_main = getattr(_obj,'main',None)
|
||||
if not _main: continue
|
||||
_main()
|
||||
|
||||
def register_hook(hook_index, hook_def):
|
||||
'''
|
||||
@name 注册HOOK
|
||||
@author hwliang<2021-07-15>
|
||||
@param hook_index<string> HOOK位置
|
||||
@param hook_def<def> HOOK函数对像
|
||||
@return void
|
||||
'''
|
||||
from BTPanel import hooks
|
||||
hook_keys = hooks.keys()
|
||||
if not hook_index in hook_keys:
|
||||
hooks[hook_index] = []
|
||||
if not hook_def in hooks[hook_index]:
|
||||
hooks[hook_index].append(hook_def)
|
||||
|
||||
def exec_hook(hook_index, data):
|
||||
'''
|
||||
@name 执行HOOk
|
||||
@author hwliang<2021-07-15>
|
||||
@param hook_index<string> HOOK索引位置,格式限制:^\w+$
|
||||
@param data<mixed> 运行数据
|
||||
@return mixed
|
||||
'''
|
||||
|
||||
from BTPanel import hooks
|
||||
hook_keys = hooks.keys()
|
||||
if not hook_index in hook_keys:
|
||||
return data
|
||||
|
||||
for hook_def in hooks[hook_index]:
|
||||
data = hook_def(data)
|
||||
return data
|
||||
|
||||
def get_hook_index(mod_name, def_name):
|
||||
'''
|
||||
@name 获取HOOK位置
|
||||
@author hwliang<2021-07-19>
|
||||
@param mod_name<string> 模块名称
|
||||
@param def_name<string> 方法名称
|
||||
@return tuple
|
||||
'''
|
||||
mod_name = mod_name.upper()
|
||||
def_name = def_name.upper()
|
||||
last_index = '{}_{}_LAST'.format(mod_name, def_name)
|
||||
end_index = '{}_{}_END'.format(mod_name, def_name)
|
||||
return last_index, end_index
|
||||
|
||||
def get_session_timeout():
|
||||
'''
|
||||
@name 获取session过期时间
|
||||
@author hwliang<2021-07-28>
|
||||
@return int
|
||||
'''
|
||||
from BTPanel import cache
|
||||
skey = 'session_timeout'
|
||||
session_timeout = cache.get(skey)
|
||||
if not session_timeout is None: return session_timeout
|
||||
|
||||
sess_out_path = '{}/data/session_timeout.pl'.format(get_panel_path())
|
||||
session_timeout = 86400
|
||||
if not os.path.exists(sess_out_path):
|
||||
return session_timeout
|
||||
session_timeout = int(readFile(sess_out_path))
|
||||
cache.set(skey,session_timeout,3600)
|
||||
return session_timeout
|
||||
|
||||
|
||||
def get_login_token_auth():
|
||||
'''
|
||||
@name 获取登录token
|
||||
@author hwliang<2021-07-28>
|
||||
@return string
|
||||
'''
|
||||
from BTPanel import cache
|
||||
skey = 'login_token'
|
||||
login_token = cache.get(skey)
|
||||
if not login_token is None: return login_token
|
||||
|
||||
login_token_file = '{}/data/login_token.pl'.format(get_panel_path())
|
||||
login_token = '1234567890'
|
||||
if not os.path.exists(login_token_file):
|
||||
return login_token
|
||||
login_token = readFile(login_token_file)
|
||||
cache.set(skey,login_token,3600)
|
||||
return login_token
|
||||
@@ -85,7 +85,7 @@ class setPanelLets:
|
||||
gcl = pssl.GetCertList(get)
|
||||
for i in gcl:
|
||||
for v in i.values():
|
||||
if get.domain in v:
|
||||
if get.domain == v:
|
||||
try:
|
||||
time_stamp = int(i['notAfter'])
|
||||
except:
|
||||
|
||||
+37
-25
@@ -123,9 +123,9 @@ class SiteDirAuth:
|
||||
try:
|
||||
conf = public.readFile(self.setup_path + '/panel/vhost/'+public.get_webserver()+'/'+siteName+'.conf');
|
||||
if public.get_webserver() == 'nginx':
|
||||
rep = "enable-php-([0-9]{2,3})\.conf"
|
||||
rep = "enable-php-(\w{2,5})\.conf"
|
||||
else:
|
||||
rep = "php-cgi-([0-9]{2,3})\.sock"
|
||||
rep = "php-cgi-(\w{2,5})\.sock"
|
||||
tmp = re.search(rep,conf).groups()
|
||||
if tmp:
|
||||
return tmp[0]
|
||||
@@ -145,8 +145,15 @@ class SiteDirAuth:
|
||||
conf = public.readFile(file_path)
|
||||
if not conf:
|
||||
return False
|
||||
rep = "include\s+enable-php-\d+\.conf;"
|
||||
conf = re.sub(rep,'include enable-php-{}.conf;'.format(phpv),conf)
|
||||
|
||||
if phpv == 'other':
|
||||
php_conf = "include /www/server/panel/vhost/other_php/{}/enable-php-other.conf;".format(site_name)
|
||||
else:
|
||||
php_conf = 'include enable-php-{}.conf;'.format(phpv)
|
||||
|
||||
rep = r"include\s+(enable-php-\w+|/www/server/panel/vhost/other_php/{}/enable-php-other)\.conf;".format(site_name)
|
||||
conf = re.sub(rep,php_conf,conf)
|
||||
|
||||
public.writeFile(file_path,conf)
|
||||
|
||||
# 设置独立认证文件
|
||||
@@ -154,7 +161,11 @@ class SiteDirAuth:
|
||||
php_ver = self.get_site_php_version(site_name)
|
||||
php_conf = ""
|
||||
if php_ver:
|
||||
php_conf = "include enable-php-{}.conf;".format(php_ver)
|
||||
if php_ver == 'other':
|
||||
php_conf = "include /www/server/panel/vhost/other_php/{}/enable-php-{}.conf;".format(site_name,php_ver)
|
||||
else:
|
||||
php_conf = "include enable-php-{}.conf;".format(php_ver)
|
||||
|
||||
for i in ["nginx","apache"]:
|
||||
file_path = "{setup_path}/panel/vhost/{webserver}/dir_auth/{site_name}"
|
||||
if i == "nginx":
|
||||
@@ -242,26 +253,27 @@ class SiteDirAuth:
|
||||
site_info = self.get_site_info(get.id)
|
||||
site_name = site_info["site_name"]
|
||||
conf = self._read_conf()
|
||||
if site_name in conf:
|
||||
for i in range(len(conf[site_name])):
|
||||
if name in conf[site_name][i].values():
|
||||
print(conf[site_name][i])
|
||||
del(conf[site_name][i])
|
||||
if not conf[site_name]:
|
||||
del(conf[site_name])
|
||||
break
|
||||
public.writeFile(self.conf_file,json.dumps(conf))
|
||||
for i in ["nginx", "apache"]:
|
||||
file_path = "{setup_path}/panel/vhost/{webserver}/dir_auth/{site_name}/{name}.conf".format(webserver=i,
|
||||
setup_path=self.setup_path,
|
||||
site_name=site_name,
|
||||
name=name)
|
||||
os.remove(file_path)
|
||||
if not conf:
|
||||
self.set_conf(site_name,"delete")
|
||||
if not hasattr(get,'multiple'):
|
||||
public.serviceReload()
|
||||
return public.returnMsg(True,"DEL_SUCCESS")
|
||||
if site_name not in conf:
|
||||
return public.returnMsg(False,"The website does not exist in the configuration:{}".format(site_name))
|
||||
for i in range(len(conf[site_name])):
|
||||
if name in conf[site_name][i].values():
|
||||
print(conf[site_name][i])
|
||||
del(conf[site_name][i])
|
||||
if not conf[site_name]:
|
||||
del(conf[site_name])
|
||||
break
|
||||
public.writeFile(self.conf_file,json.dumps(conf))
|
||||
for i in ["nginx", "apache"]:
|
||||
file_path = "{setup_path}/panel/vhost/{webserver}/dir_auth/{site_name}/{name}.conf".format(webserver=i,
|
||||
setup_path=self.setup_path,
|
||||
site_name=site_name,
|
||||
name=name)
|
||||
os.remove(file_path)
|
||||
if not conf:
|
||||
self.set_conf(site_name,"delete")
|
||||
if not hasattr(get,'multiple'):
|
||||
public.serviceReload()
|
||||
return public.returnMsg(True,"DEL_SUCCESS")
|
||||
|
||||
# 修改目录保护密码
|
||||
def modify_dir_auth_pass(self,get):
|
||||
|
||||
+60
-6
@@ -47,6 +47,7 @@ class ssh_terminal:
|
||||
_tp = None
|
||||
_old_conf = None
|
||||
_debug_file = 'logs/terminal.log'
|
||||
_s_code = None
|
||||
|
||||
def connect(self):
|
||||
'''
|
||||
@@ -123,8 +124,16 @@ class ssh_terminal:
|
||||
pkey = paramiko.DSSKey.from_private_key(p_file)
|
||||
self._tp.auth_publickey(username=self._user, key=pkey)
|
||||
else:
|
||||
self.debug(public.getMsg('AUTH_PASSWD'))
|
||||
self._tp.auth_password(username=self._user, password=self._pass)
|
||||
try:
|
||||
self._tp.auth_none(self._user)
|
||||
except Exception as e:
|
||||
e = str(e)
|
||||
if e.find('keyboard-interactive') >= 0:
|
||||
self._auth_interactive()
|
||||
else:
|
||||
self.debug('Authenticating password')
|
||||
self._tp.auth_password(username=self._user, password=self._pass)
|
||||
# self._tp.auth_password(username=self._user, password=self._pass)
|
||||
except Exception as e:
|
||||
if self._old_conf:
|
||||
s_file = '/www/server/panel/config/t_info.json'
|
||||
@@ -132,6 +141,11 @@ class ssh_terminal:
|
||||
self.set_sshd_config(True)
|
||||
self._tp.close()
|
||||
e = str(e)
|
||||
if e.find('websocket error!') != -1:
|
||||
return returnMsg(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))
|
||||
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)),))
|
||||
@@ -167,6 +181,40 @@ class ssh_terminal:
|
||||
self.debug('SSH_LOGIN_INFO2')
|
||||
return returnMsg(True,'CONNECTION_SUCCEEDED')
|
||||
|
||||
def _auth_interactive(self):
|
||||
self.debug('Verification Code')
|
||||
|
||||
self.brk = False
|
||||
|
||||
def handler(title, instructions, prompt_list):
|
||||
if not self._ws: raise public.PanelError('websocket error!')
|
||||
if instructions:
|
||||
self._ws.send(instructions)
|
||||
if title:
|
||||
self._ws.send(title)
|
||||
resp = []
|
||||
for pr in prompt_list:
|
||||
if str(pr[0]).strip() == "Password:":
|
||||
resp.append(self._pass)
|
||||
elif str(pr[0]).strip() == "Verification code:":
|
||||
# 获取前段传入的验证码
|
||||
self._ws.send("Verification code# ")
|
||||
self._s_code = True
|
||||
code = ""
|
||||
while True:
|
||||
data = self._ws.receive()
|
||||
if data.find('"resize":1') != -1:
|
||||
self.resize(data)
|
||||
continue
|
||||
self._ws.send(data)
|
||||
if data in ["\n", "\r"]: break
|
||||
code += data
|
||||
resp.append(code)
|
||||
self._ws.send("\n")
|
||||
self._s_code = None
|
||||
return tuple(resp)
|
||||
|
||||
self._tp.auth_interactive(self._user, handler)
|
||||
|
||||
def get_login_user(self):
|
||||
'''
|
||||
@@ -349,7 +397,6 @@ class ssh_terminal:
|
||||
@return bool
|
||||
'''
|
||||
self.is_running(rep)
|
||||
return False
|
||||
if rep and not self._rep_ssh_config:
|
||||
return False
|
||||
|
||||
@@ -490,6 +537,9 @@ class ssh_terminal:
|
||||
'''
|
||||
try:
|
||||
while not self._ws.closed:
|
||||
if self._s_code:
|
||||
time.sleep(0.1)
|
||||
continue
|
||||
client_data = self._ws.receive()
|
||||
if not client_data: continue
|
||||
if len(client_data) > 10:
|
||||
@@ -588,7 +638,8 @@ class ssh_terminal:
|
||||
try:
|
||||
if self._ssh:
|
||||
self._ssh.close()
|
||||
#self._ssh = None
|
||||
if self._tp: # 关闭宿主服务
|
||||
self._tp.close()
|
||||
if not self._ws.closed:
|
||||
self._ws.close()
|
||||
except:
|
||||
@@ -609,8 +660,11 @@ class ssh_terminal:
|
||||
self._pkey = ssh_info['pkey']
|
||||
if 'password' in ssh_info:
|
||||
self._pass = ssh_info['password']
|
||||
|
||||
result = self.connect()
|
||||
try:
|
||||
result = self.connect()
|
||||
except Exception as ex:
|
||||
if str(ex).find("NoneType") == -1:
|
||||
raise public.PanelError(ex)
|
||||
return result
|
||||
|
||||
|
||||
|
||||
+39
-67
@@ -127,46 +127,46 @@ class system:
|
||||
data['web'] = tmp
|
||||
|
||||
tmp = {}
|
||||
vfile = self.setupPath + '/phpmyadmin/version.pl';
|
||||
tmp['version'] = public.readFile(vfile);
|
||||
vfile = self.setupPath + '/phpmyadmin/version.pl'
|
||||
tmp['version'] = public.readFile(vfile)
|
||||
if tmp['version']: tmp['version'] = tmp['version'].strip()
|
||||
tmp['setup'] = os.path.exists(vfile);
|
||||
tmp['status'] = pstatus;
|
||||
tmp['phpversion'] = phpversion.strip();
|
||||
tmp['port'] = phpport;
|
||||
tmp['auth'] = pauth;
|
||||
data['phpmyadmin'] = tmp;
|
||||
tmp['setup'] = os.path.exists(vfile)
|
||||
tmp['status'] = pstatus
|
||||
tmp['phpversion'] = phpversion.strip()
|
||||
tmp['port'] = phpport
|
||||
tmp['auth'] = pauth
|
||||
data['phpmyadmin'] = tmp
|
||||
|
||||
tmp = {}
|
||||
tmp['setup'] = os.path.exists('/etc/init.d/tomcat');
|
||||
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');
|
||||
data['tomcat'] = tmp;
|
||||
tmp['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['setup'] = os.path.exists(self.setupPath +'/mysql/bin/mysql')
|
||||
tmp['version'] = public.readFile(self.setupPath + '/mysql/version.pl')
|
||||
tmp['status'] = os.path.exists('/tmp/mysql.sock')
|
||||
data['mysql'] = tmp
|
||||
|
||||
tmp = {}
|
||||
tmp['setup'] = os.path.exists(self.setupPath +'/redis/runtest');
|
||||
tmp['status'] = os.path.exists('/var/run/redis_6379.pid');
|
||||
data['redis'] = tmp;
|
||||
tmp['setup'] = os.path.exists(self.setupPath +'/redis/runtest')
|
||||
tmp['status'] = os.path.exists('/var/run/redis_6379.pid')
|
||||
data['redis'] = tmp
|
||||
|
||||
tmp = {}
|
||||
tmp['setup'] = os.path.exists('/usr/local/memcached/bin/memcached');
|
||||
tmp['status'] = os.path.exists('/var/run/memcached.pid');
|
||||
data['memcached'] = tmp;
|
||||
tmp['setup'] = os.path.exists('/usr/local/memcached/bin/memcached')
|
||||
tmp['status'] = os.path.exists('/var/run/memcached.pid')
|
||||
data['memcached'] = tmp
|
||||
|
||||
tmp = {}
|
||||
tmp['setup'] = os.path.exists(self.setupPath +'/pure-ftpd/bin/pure-pw');
|
||||
tmp['version'] = public.readFile(self.setupPath + '/pure-ftpd/version.pl');
|
||||
tmp['setup'] = os.path.exists(self.setupPath +'/pure-ftpd/bin/pure-pw')
|
||||
tmp['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()
|
||||
data['systemdate'] = public.ExecShell('date +"%Y-%m-%d %H:%M:%S %Z %z"')[0].strip();
|
||||
data['systemdate'] = public.format_date("%Y-%m-%d %H:%M:%S %Z %z") #public.ExecShell('date +"%Y-%m-%d %H:%M:%S %Z %z"')[0].strip()
|
||||
|
||||
return data
|
||||
|
||||
@@ -176,15 +176,15 @@ class system:
|
||||
try:
|
||||
port = public.GetHost(True)
|
||||
except:
|
||||
port = '8888';
|
||||
port = '8888'
|
||||
domain = ''
|
||||
if os.path.exists('data/domain.conf'):
|
||||
domain = public.readFile('data/domain.conf');
|
||||
domain = public.readFile('data/domain.conf')
|
||||
|
||||
autoUpdate = ''
|
||||
if os.path.exists('data/autoUpdate.pl'): autoUpdate = 'checked';
|
||||
if os.path.exists('data/autoUpdate.pl'): autoUpdate = 'checked'
|
||||
limitip = ''
|
||||
if os.path.exists('data/limitip.conf'): limitip = public.readFile('data/limitip.conf');
|
||||
if os.path.exists('data/limitip.conf'): limitip = public.readFile('data/limitip.conf')
|
||||
admin_path = '/'
|
||||
if os.path.exists('data/admin_path.pl'): admin_path = public.readFile('data/admin_path.pl').strip()
|
||||
|
||||
@@ -193,8 +193,8 @@ class system:
|
||||
# if os.path.isdir('templates/' + template): templates.append(template);
|
||||
template = public.GetConfigValue('template')
|
||||
|
||||
check502 = '';
|
||||
if os.path.exists('data/502Task.pl'): check502 = 'checked';
|
||||
check502 = ''
|
||||
if os.path.exists('data/502Task.pl'): check502 = 'checked'
|
||||
return {'port':port,'address':address,'domain':domain,'auto':autoUpdate,'502':check502,'limitip':limitip,'templates':templates,'template':template,'admin_path':admin_path}
|
||||
|
||||
def GetPHPConfig(self,version):
|
||||
@@ -373,9 +373,13 @@ class system:
|
||||
|
||||
def GetMemInfo(self,get=None):
|
||||
#取内存信息
|
||||
skey = 'memInfo'
|
||||
memInfo = cache.get(skey)
|
||||
if memInfo: return memInfo
|
||||
mem = psutil.virtual_memory()
|
||||
memInfo = {'memTotal':int(mem.total/1024/1024),'memFree':int(mem.free/1024/1024),'memBuffers':int(mem.buffers/1024/1024),'memCached':int(mem.cached/1024/1024)}
|
||||
memInfo['memRealUsed'] = memInfo['memTotal'] - memInfo['memFree'] - memInfo['memBuffers'] - memInfo['memCached']
|
||||
cache.set(skey,memInfo,60)
|
||||
return memInfo
|
||||
|
||||
def GetDiskInfo(self,get=None):
|
||||
@@ -428,7 +432,7 @@ class system:
|
||||
except Exception as ex:
|
||||
public.WriteLog('GET_INFO',str(ex))
|
||||
continue
|
||||
cache.set(key,diskInfo,360)
|
||||
cache.set(key,diskInfo,10)
|
||||
return diskInfo
|
||||
|
||||
|
||||
@@ -483,7 +487,6 @@ class system:
|
||||
|
||||
cache.set(iokey,{'info':diskio_2,'time':mtime})
|
||||
except:
|
||||
public.writeFile('/tmp/2',str(public.get_error_info()))
|
||||
return diskInfo
|
||||
return diskInfo
|
||||
|
||||
@@ -625,8 +628,11 @@ class system:
|
||||
|
||||
|
||||
def get_cpu_times(self):
|
||||
data = {}
|
||||
skey = 'cpu_times'
|
||||
data = cache.get(skey)
|
||||
if data:return data
|
||||
try:
|
||||
data = {}
|
||||
cpu_times_p = psutil.cpu_times_percent()
|
||||
data['user'] = cpu_times_p.user
|
||||
data['nice'] = cpu_times_p.nice
|
||||
@@ -649,7 +655,8 @@ class system:
|
||||
continue
|
||||
data['total_processes'] += 1
|
||||
|
||||
except: pass
|
||||
cache.set(skey,data,60)
|
||||
except: return None
|
||||
return data
|
||||
|
||||
|
||||
@@ -921,38 +928,10 @@ class system:
|
||||
|
||||
#重启面板
|
||||
def ReWeb(self,get):
|
||||
#s = time.time()
|
||||
#if not self.shell: self.connect_ssh()
|
||||
#self.shell.send("nohup /etc/init.d/bt restart && sleep 1 && /etc/init.d/bt start > /dev/null &\n")
|
||||
#public.ExecShell("nohup sleep 2 && /etc/init.d/bt restart 2>&1 >/dev/null &")
|
||||
|
||||
public.ExecShell("/etc/init.d/bt start")
|
||||
public.writeFile('data/restart.pl','True')
|
||||
return public.returnMsg(True,'PANEL_WAS_RESTART')
|
||||
|
||||
def connect_ssh(self):
|
||||
import paramiko
|
||||
self.ssh = paramiko.SSHClient()
|
||||
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
try:
|
||||
self.ssh.connect('127.0.0.1', public.GetSSHPort())
|
||||
except:
|
||||
if public.GetSSHStatus():
|
||||
try:
|
||||
self.ssh.connect('localhost', public.GetSSHPort())
|
||||
except:
|
||||
return False
|
||||
import firewalls
|
||||
fw = firewalls.firewalls()
|
||||
get = public.dict_obj()
|
||||
get.status = '0'
|
||||
fw.SetSshStatus(get)
|
||||
self.ssh.connect('127.0.0.1', public.GetSSHPort())
|
||||
get.status = '1'
|
||||
fw.SetSshStatus(get)
|
||||
self.shell = self.ssh.invoke_shell(term='xterm', width=100, height=29)
|
||||
self.shell.setblocking(0)
|
||||
return True
|
||||
|
||||
#修复面板
|
||||
def RepPanel(self,get):
|
||||
@@ -966,10 +945,3 @@ class system:
|
||||
public.ExecShell("wget -O update.sh " + public.get_url() + "/install/update6_en.sh && bash update.sh")
|
||||
self.ReWeb(None)
|
||||
return True
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+4
-6
@@ -106,8 +106,7 @@ class userlogin:
|
||||
self.limit_address('-')
|
||||
cache.delete('panelNum')
|
||||
cache.delete('dologin')
|
||||
sess_input_path = 'data/session_last.pl'
|
||||
public.writeFile(sess_input_path,str(int(time.time())))
|
||||
session['session_timeout'] = time.time() + public.get_session_timeout()
|
||||
del(data['tmp_token'])
|
||||
del(data['tmp_time'])
|
||||
public.writeFile(save_path,json.dumps(data))
|
||||
@@ -157,8 +156,7 @@ class userlogin:
|
||||
self.limit_address('-')
|
||||
cache.delete('panelNum')
|
||||
cache.delete('dologin')
|
||||
sess_input_path = 'data/session_last.pl'
|
||||
public.writeFile(sess_input_path,str(int(time.time())))
|
||||
session['session_timeout'] = time.time() + public.get_session_timeout()
|
||||
self.set_request_token()
|
||||
self.login_token()
|
||||
self.set_cdn_host(get)
|
||||
@@ -277,12 +275,12 @@ class userlogin:
|
||||
session['login'] = True
|
||||
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'))))
|
||||
self.limit_address('-')
|
||||
cache.delete('panelNum')
|
||||
cache.delete('dologin')
|
||||
sess_input_path = 'data/session_last.pl'
|
||||
public.writeFile(sess_input_path,str(int(time.time())))
|
||||
session['session_timeout'] = time.time() + public.get_session_timeout()
|
||||
self.set_request_token()
|
||||
self.login_token()
|
||||
login_type = 'data/app_login.pl'
|
||||
|
||||
+34
-35
@@ -58,28 +58,28 @@ class ScanLogin(object):
|
||||
if cache.get(session_id) == 'True':
|
||||
return self.check_app_login(get)
|
||||
|
||||
if os.path.exists(self.app_path+"login.pl"):
|
||||
data = public.readFile(self.app_path+'login.pl')
|
||||
public.ExecShell('rm ' + self.app_path+"login.pl")
|
||||
secret_key, init_time = data.split(':')
|
||||
if time.time() - float(init_time) < 60 and get['secret_key'] == secret_key:
|
||||
sql = db.Sql()
|
||||
userInfo = sql.table('users').where(
|
||||
"id=?", (1,)).field('id,username,password').find()
|
||||
session['login'] = True
|
||||
session['username'] = userInfo['username']
|
||||
cache.delete('panelNum')
|
||||
cache.delete('dologin')
|
||||
public.WriteLog('TYPE_LOGIN', 'LOGIN_SUCCESS',
|
||||
('WeChat scan code login', public.GetClientIp()+ ":" + str(request.environ.get('REMOTE_PORT'))))
|
||||
login_type = 'data/app_login.pl'
|
||||
self.set_request_token()
|
||||
import config
|
||||
config.config().reload_session()
|
||||
public.writeFile(login_type,'True')
|
||||
public.login_send_body("Wechat program",userInfo['username'],public.GetClientIp(),str(request.environ.get('REMOTE_PORT')))
|
||||
return public.returnMsg(True, 'login successful')
|
||||
return public.returnMsg(False, 'Login failed')
|
||||
# if os.path.exists(self.app_path+"login.pl"):
|
||||
# data = public.readFile(self.app_path+'login.pl')
|
||||
# public.ExecShell('rm ' + self.app_path+"login.pl")
|
||||
# secret_key, init_time = data.split(':')
|
||||
# if time.time() - float(init_time) < 60 and get['secret_key'] == secret_key:
|
||||
# sql = db.Sql()
|
||||
# userInfo = sql.table('users').where(
|
||||
# "id=?", (1,)).field('id,username,password').find()
|
||||
# session['login'] = True
|
||||
# session['username'] = userInfo['username']
|
||||
# cache.delete('panelNum')
|
||||
# cache.delete('dologin')
|
||||
# public.WriteLog('TYPE_LOGIN', 'LOGIN_SUCCESS',
|
||||
# ('微信扫码登录', public.GetClientIp()+ ":" + str(request.environ.get('REMOTE_PORT'))))
|
||||
# login_type = 'data/app_login.pl'
|
||||
# self.set_request_token()
|
||||
# import config
|
||||
# config.config().reload_session()
|
||||
# public.writeFile(login_type,'True')
|
||||
# public.login_send_body("微信小程序",userInfo['username'],public.GetClientIp(),str(request.environ.get('REMOTE_PORT')))
|
||||
# return public.returnMsg(True, '登录成功')
|
||||
return public.returnMsg(False, '登录失败')
|
||||
|
||||
|
||||
#验证APP是否登录成功
|
||||
@@ -107,8 +107,7 @@ class ScanLogin(object):
|
||||
public.WriteLog('TYPE_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')
|
||||
sess_input_path = 'data/session_last.pl'
|
||||
public.writeFile(sess_input_path,str(int(time.time())))
|
||||
session['session_timeout'] = time.time() + public.get_session_timeout()
|
||||
login_type = 'data/app_login.pl'
|
||||
self.set_request_token()
|
||||
import config
|
||||
@@ -208,17 +207,17 @@ class wxapp(SelfModule, ScanLogin):
|
||||
elif get['panel_token'] != password:
|
||||
return public.returnMsg(False, 'SK_NOT_INCORRECT')
|
||||
return True
|
||||
else:
|
||||
# 是否在白名单ip sgin 是否正确
|
||||
if hasattr(get, 'uid') and hasattr(get, 'sgin') and hasattr(get, 'fun') and get['uid'] in self.user_info.keys():
|
||||
encryption_str = self.user_info[get['uid']]['token']+get['fun']+get['uid']
|
||||
if sys.version_info[0] == 3:
|
||||
if type(encryption_str) == str:
|
||||
encryption_str = encryption_str.encode()
|
||||
if get['sgin'] == public.md5(binascii.hexlify(base64.b64encode(encryption_str))):
|
||||
if public.GetClientIp() in ['47.52.194.186']:
|
||||
return True
|
||||
return public.returnMsg(False, 'UNAUTHORIZED')
|
||||
# else:
|
||||
# # 是否在白名单ip sgin 是否正确
|
||||
# if hasattr(get, 'uid') and hasattr(get, 'sgin') and hasattr(get, 'fun') and get['uid'] in self.user_info.keys():
|
||||
# encryption_str = self.user_info[get['uid']]['token']+get['fun']+get['uid']
|
||||
# if sys.version_info[0] == 3:
|
||||
# if type(encryption_str) == str:
|
||||
# encryption_str = encryption_str.encode()
|
||||
# if get['sgin'] == public.md5(binascii.hexlify(base64.b64encode(encryption_str))):
|
||||
# if public.GetClientIp() in ['47.52.194.186']:
|
||||
# return public.returnMsg(False, '未授权')
|
||||
return public.returnMsg(False, 'UNAUTHORIZED')
|
||||
|
||||
# 用户绑定
|
||||
def blind(self, get):
|
||||
|
||||
+790
@@ -0,0 +1,790 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
LANG=en_US.UTF-8
|
||||
cd ~
|
||||
|
||||
setup_path="/www"
|
||||
SET_SSL=false
|
||||
python_bin=$setup_path/server/panel/pyenv/bin/python
|
||||
cpu_cpunt=$(cat /proc/cpuinfo|grep processor|wc -l)
|
||||
if [ "$1" ];then
|
||||
IDC_CODE=$1
|
||||
fi
|
||||
|
||||
GetSysInfo(){
|
||||
if [ -s "/etc/redhat-release" ];then
|
||||
SYS_VERSION=$(cat /etc/redhat-release)
|
||||
elif [ -s "/etc/issue" ]; then
|
||||
SYS_VERSION=$(cat /etc/issue)
|
||||
fi
|
||||
SYS_INFO=$(uname -r)
|
||||
SYS_BIT=$(getconf LONG_BIT)
|
||||
MEM_TOTAL=$(free -m|grep Mem|awk '{print $2}')
|
||||
CPU_INFO=$(getconf _NPROCESSORS_ONLN)
|
||||
|
||||
echo -e ${SYS_VERSION}
|
||||
echo -e Bit:${SYS_BIT} Mem:${MEM_TOTAL}M Core:${CPU_INFO}
|
||||
echo -e ${SYS_INFO}
|
||||
echo -e "Please screenshot the above error message and post to the forum forum.aapanel.com for help"
|
||||
}
|
||||
Red_Error(){
|
||||
echo '=================================================';
|
||||
printf '\033[1;31;40m%b\033[0m\n' "$1";
|
||||
GetSysInfo
|
||||
exit 1;
|
||||
}
|
||||
|
||||
is64bit=$(getconf LONG_BIT)
|
||||
if [ "${is64bit}" != '64' ];then
|
||||
Red_Error "Sorry, aaPanel Does not support 32-bit systems, Use 64-bit system Please!";
|
||||
|
||||
fi
|
||||
Lock_Clear(){
|
||||
if [ -f "/etc/bt_crack.pl" ];then
|
||||
chattr -R -ia /www
|
||||
chattr -ia /etc/init.d/bt
|
||||
\cp -rpa /www/backup/panel/vhost/* /www/server/panel/vhost/
|
||||
mv /www/server/panel/BTPanel/__init__.bak /www/server/panel/BTPanel/__init__.py
|
||||
rm -f /etc/bt_crack.pl
|
||||
fi
|
||||
}
|
||||
Install_Check(){
|
||||
while [ "$yes" != 'yes' ] && [ "$yes" != 'n' ]
|
||||
do
|
||||
echo -e "----------------------------------------------------"
|
||||
echo -e "Web service is alreday installed,installing aaPanel may affect existing sites."
|
||||
echo -e "----------------------------------------------------"
|
||||
read -p "Enter yes to force installation (yes/n): " yes;
|
||||
done
|
||||
if [ "$yes" == 'n' ];then
|
||||
exit;
|
||||
fi
|
||||
}
|
||||
System_Check(){
|
||||
for serviceS in nginx httpd mysqld
|
||||
do
|
||||
if [ -f "/etc/init.d/${serviceS}" ]; then
|
||||
if [ "${serviceS}" = "httpd" ]; then
|
||||
serviceCheck=$(cat /etc/init.d/${serviceS}|grep /www/server/apache)
|
||||
elif [ "${serviceS}" = "mysqld" ]; then
|
||||
serviceCheck=$(cat /etc/init.d/${serviceS}|grep /www/server/mysql)
|
||||
else
|
||||
serviceCheck=$(cat /etc/init.d/${serviceS}|grep /www/server/${serviceS})
|
||||
fi
|
||||
[ -z "${serviceCheck}" ] && Install_Check
|
||||
fi
|
||||
done
|
||||
}
|
||||
Set_Ssl(){
|
||||
echo -e ""
|
||||
echo -e "----------------------------------------------------------------------"
|
||||
echo -e "If you choose to enable SSL (self-signed certificate), you will use https access panel after installation."
|
||||
echo -e "After logging in, you can go to the panel settings and change to Let's Encrypt certificate."
|
||||
echo -e "----------------------------------------------------------------------"
|
||||
echo -e ""
|
||||
read -p "Do you need to enable the panel SSl ? (yes/n): " yes;
|
||||
if [ "$yes" == "yes" ];then
|
||||
SET_SSL=true
|
||||
fi
|
||||
if [ "$yes" != "yes" ] && [ $yes != "n" ];then
|
||||
Set_Ssl
|
||||
fi
|
||||
}
|
||||
Get_Pack_Manager(){
|
||||
if [ -f "/usr/bin/yum" ] && [ -d "/etc/yum.repos.d" ]; then
|
||||
PM="yum"
|
||||
elif [ -f "/usr/bin/apt-get" ] && [ -f "/usr/bin/dpkg" ]; then
|
||||
PM="apt-get"
|
||||
fi
|
||||
}
|
||||
|
||||
Auto_Swap()
|
||||
{
|
||||
swap=$(free |grep Swap|awk '{print $2}')
|
||||
if [ "${swap}" -gt 1 ];then
|
||||
echo "Swap total sizse: $swap";
|
||||
return;
|
||||
fi
|
||||
if [ ! -d /www ];then
|
||||
mkdir /www
|
||||
fi
|
||||
swapFile="/www/swap"
|
||||
dd if=/dev/zero of=$swapFile bs=1M count=1025
|
||||
mkswap -f $swapFile
|
||||
swapon $swapFile
|
||||
echo "$swapFile swap swap defaults 0 0" >> /etc/fstab
|
||||
swap=`free |grep Swap|awk '{print $2}'`
|
||||
if [ $swap -gt 1 ];then
|
||||
echo "Swap total sizse: $swap";
|
||||
return;
|
||||
fi
|
||||
|
||||
sed -i "/\/www\/swap/d" /etc/fstab
|
||||
rm -f $swapFile
|
||||
}
|
||||
Service_Add(){
|
||||
if [ "${PM}" == "yum" ] || [ "${PM}" == "dnf" ]; then
|
||||
chkconfig --add bt
|
||||
chkconfig --level 2345 bt on
|
||||
elif [ "${PM}" == "apt-get" ]; then
|
||||
update-rc.d bt defaults
|
||||
fi
|
||||
}
|
||||
|
||||
get_node_url(){
|
||||
if [ ! -f /bin/curl ];then
|
||||
if [ "${PM}" = "yum" ]; then
|
||||
yum install curl -y
|
||||
elif [ "${PM}" = "apt-get" ]; then
|
||||
apt-get install curl -y
|
||||
fi
|
||||
fi
|
||||
|
||||
echo '---------------------------------------------';
|
||||
echo "Selected download node...";
|
||||
nodes=(http://node.aapanel.com http://128.1.164.196 http://45.76.53.20 http://103.224.251.67 http://dg2.bt.cn http://dg1.bt.cn http://123.129.198.197 http://125.88.182.172:5880 http://119.188.210.21:5880 http://120.206.184.160 http://113.107.111.78);
|
||||
tmp_file1=/dev/shm/net_test1.pl
|
||||
tmp_file2=/dev/shm/net_test2.pl
|
||||
|
||||
[ -f "${tmp_file1}" ] && rm -f ${tmp_file1}
|
||||
|
||||
|
||||
[ -f "${tmp_file2}" ] && rm -f ${tmp_file2}
|
||||
|
||||
touch $tmp_file1
|
||||
touch $tmp_file2
|
||||
for node in ${nodes[@]};
|
||||
do
|
||||
NODE_CHECK=$(curl --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${node}/net_test|xargs)
|
||||
RES=$(echo ${NODE_CHECK}|awk '{print $1}')
|
||||
NODE_STATUS=$(echo ${NODE_CHECK}|awk '{print $2}')
|
||||
TIME_TOTAL=$(echo ${NODE_CHECK}|awk '{print $3 * 1000 - 500 }'|cut -d '.' -f 1)
|
||||
if [ "${NODE_STATUS}" == "200" ];then
|
||||
if [ $TIME_TOTAL -lt 100 ];then
|
||||
if [ $RES -ge 1500 ];then
|
||||
echo "$RES $node" >> $tmp_file1
|
||||
fi
|
||||
else
|
||||
if [ $RES -ge 1500 ];then
|
||||
echo "$TIME_TOTAL $node" >> $tmp_file2
|
||||
fi
|
||||
fi
|
||||
|
||||
i=$(($i+1))
|
||||
if [ $TIME_TOTAL -lt 100 ];then
|
||||
if [ $RES -ge 3000 ];then
|
||||
break;
|
||||
fi
|
||||
fi
|
||||
|
||||
fi
|
||||
done
|
||||
|
||||
NODE_URL=$(cat $tmp_file1|sort -r -g -t " " -k 1|head -n 1|awk '{print $2}')
|
||||
if [ -z "$NODE_URL" ];then
|
||||
NODE_URL=$(cat $tmp_file2|sort -g -t " " -k 1|head -n 1|awk '{print $2}')
|
||||
if [ -z "$NODE_URL" ];then
|
||||
NODE_URL='http://download.bt.cn';
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -f $tmp_file1
|
||||
rm -f $tmp_file2
|
||||
download_Url=$NODE_URL
|
||||
echo "Download node: $download_Url";
|
||||
echo '---------------------------------------------';
|
||||
}
|
||||
Remove_Package(){
|
||||
local PackageNmae=$1
|
||||
if [ "${PM}" == "yum" ];then
|
||||
isPackage=$(rpm -q ${PackageNmae}|grep "not installed")
|
||||
if [ -z "${isPackage}" ];then
|
||||
yum remove ${PackageNmae} -y
|
||||
fi
|
||||
elif [ "${PM}" == "apt-get" ];then
|
||||
isPackage=$(dpkg -l|grep ${PackageNmae})
|
||||
if [ "${PackageNmae}" ];then
|
||||
apt-get remove ${PackageNmae} -y
|
||||
fi
|
||||
fi
|
||||
}
|
||||
Install_RPM_Pack(){
|
||||
yumPath=/etc/yum.conf
|
||||
Centos8Check=$(cat /etc/redhat-release | grep ' 8.' | grep -iE 'centos|Red Hat')
|
||||
isExc=$(cat $yumPath|grep httpd)
|
||||
if [ "$isExc" = "" ];then
|
||||
echo "exclude=httpd nginx php mysql mairadb python-psutil python2-psutil" >> $yumPath
|
||||
fi
|
||||
|
||||
yumBaseUrl=$(cat /etc/yum.repos.d/CentOS-Base.repo|grep baseurl=http|cut -d '=' -f 2|cut -d '$' -f 1|head -n 1)
|
||||
[ "${yumBaseUrl}" ] && checkYumRepo=$(curl --connect-timeout 5 --head -s -o /dev/null -w %{http_code} ${yumBaseUrl})
|
||||
if [ "${checkYumRepo}" != "200" ];then
|
||||
curl -Ss --connect-timeout 3 -m 60 http://download.bt.cn/install/yumRepo_select.sh|bash
|
||||
fi
|
||||
|
||||
# 尝试同步时间(从bt.cn)
|
||||
echo 'Synchronizing system time...'
|
||||
getBtTime=$(curl -sS --connect-timeout 3 -m 60 http://www.bt.cn/api/index/get_time)
|
||||
if [ "${getBtTime}" ];then
|
||||
date -s "$(date -d @$getBtTime +"%Y-%m-%d %H:%M:%S")"
|
||||
fi
|
||||
|
||||
#if [ -z "${Centos8Check}" ]; then
|
||||
# yum install ntp -y
|
||||
# rm -rf /etc/localtime
|
||||
# ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
||||
|
||||
#尝试同步国际时间(从ntp服务器)
|
||||
# ntpdate 0.asia.pool.ntp.org
|
||||
# setenforce 0
|
||||
#fi
|
||||
|
||||
startTime=`date +%s`
|
||||
|
||||
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
|
||||
#yum remove -y python-requests python3-requests python-greenlet python3-greenlet
|
||||
yumPacks="libcurl-devel wget tar gcc make zip unzip openssl openssl-devel gcc libxml2 libxml2-devel libxslt* zlib zlib-devel libjpeg-devel libpng-devel libwebp libwebp-devel freetype freetype-devel lsof pcre pcre-devel vixie-cron crontabs icu libicu-devel c-ares libffi-devel bzip2-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel"
|
||||
yum install -y ${yumPacks}
|
||||
|
||||
for yumPack in ${yumPacks}
|
||||
do
|
||||
rpmPack=$(rpm -q ${yumPack})
|
||||
packCheck=$(echo ${rpmPack}|grep not)
|
||||
if [ "${packCheck}" ]; then
|
||||
yum install ${yumPack} -y
|
||||
fi
|
||||
done
|
||||
if [ -f "/usr/bin/dnf" ]; then
|
||||
dnf install -y redhat-rpm-config
|
||||
fi
|
||||
|
||||
yum install epel-release -y
|
||||
}
|
||||
Install_Deb_Pack(){
|
||||
ln -sf bash /bin/sh
|
||||
apt-get update -y
|
||||
apt-get install ruby -y
|
||||
apt-get install lsb-release -y
|
||||
#apt-get install ntp ntpdate -y
|
||||
#/etc/init.d/ntp stop
|
||||
#update-rc.d ntp remove
|
||||
#cat >>~/.profile<<EOF
|
||||
#TZ='Asia/Shanghai'; export TZ
|
||||
#EOF
|
||||
#rm -rf /etc/localtime
|
||||
#cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
||||
#echo 'Synchronizing system time...'
|
||||
#ntpdate 0.asia.pool.ntp.org
|
||||
#apt-get upgrade -y
|
||||
for pace in wget curl libcurl4-openssl-dev gcc make zip unzip openssl libssl-dev gcc libxml2 libxml2-dev libxslt zlib1g zlib1g-dev libjpeg-dev libpng-dev lsof libpcre3 libpcre3-dev cron net-tools swig build-essential libffi-dev libbz2-dev libncurses-dev libsqlite3-dev libreadline-dev tk-dev libgdbm-dev libdb-dev libdb++-dev libpcap-dev xz-utils git;
|
||||
do apt-get -y install $pace --force-yes; done
|
||||
if [ ! -d '/etc/letsencrypt' ];then
|
||||
mkdir -p /etc/letsencryp
|
||||
mkdir -p /var/spool/cron
|
||||
if [ ! -f '/var/spool/cron/crontabs/root' ];then
|
||||
echo '' > /var/spool/cron/crontabs/root
|
||||
chmod 600 /var/spool/cron/crontabs/root
|
||||
fi
|
||||
fi
|
||||
}
|
||||
Install_Bt(){
|
||||
panelPort="8888"
|
||||
if [ -f ${setup_path}/server/panel/data/port.pl ];then
|
||||
panelPort=$(cat ${setup_path}/server/panel/data/port.pl)
|
||||
fi
|
||||
mkdir -p ${setup_path}/server/panel/logs
|
||||
mkdir -p ${setup_path}/server/panel/vhost/apache
|
||||
mkdir -p ${setup_path}/server/panel/vhost/nginx
|
||||
mkdir -p ${setup_path}/server/panel/vhost/rewrite
|
||||
mkdir -p ${setup_path}/server/panel/install
|
||||
mkdir -p /www/server
|
||||
mkdir -p /www/wwwroot
|
||||
mkdir -p /www/wwwlogs
|
||||
mkdir -p /www/backup/database
|
||||
mkdir -p /www/backup/site
|
||||
|
||||
if [ ! -f "/usr/bin/unzip" ]; then
|
||||
if [ "${PM}" = "yum" ]; then
|
||||
yum install unzip -y
|
||||
elif [ "${PM}" = "apt-get" ]; then
|
||||
apt-get install unzip -y
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -f "/etc/init.d/bt" ]; then
|
||||
/etc/init.d/bt stop
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
wget -O panel.zip ${download_Url}/install/src/panel6_en.zip -T 10
|
||||
wget -O /etc/init.d/bt ${download_Url}/install/src/bt6_en.init -T 10
|
||||
wget -O /www/server/panel/install/public.sh ${download_Url}/install/public.sh -T 10
|
||||
|
||||
if [ -f "${setup_path}/server/panel/data/default.db" ];then
|
||||
if [ -d "/${setup_path}/server/panel/old_data" ];then
|
||||
rm -rf ${setup_path}/server/panel/old_data
|
||||
fi
|
||||
mkdir -p ${setup_path}/server/panel/old_data
|
||||
mv -f ${setup_path}/server/panel/data/default.db ${setup_path}/server/panel/old_data/default.db
|
||||
mv -f ${setup_path}/server/panel/data/system.db ${setup_path}/server/panel/old_data/system.db
|
||||
mv -f ${setup_path}/server/panel/data/port.pl ${setup_path}/server/panel/old_data/port.pl
|
||||
mv -f ${setup_path}/server/panel/data/admin_path.pl ${setup_path}/server/panel/old_data/admin_path.pl
|
||||
fi
|
||||
|
||||
unzip -o panel.zip -d ${setup_path}/server/ > /dev/null
|
||||
|
||||
if [ -d "${setup_path}/server/panel/old_data" ];then
|
||||
mv -f ${setup_path}/server/panel/old_data/default.db ${setup_path}/server/panel/data/default.db
|
||||
mv -f ${setup_path}/server/panel/old_data/system.db ${setup_path}/server/panel/data/system.db
|
||||
mv -f ${setup_path}/server/panel/old_data/port.pl ${setup_path}/server/panel/data/port.pl
|
||||
mv -f ${setup_path}/server/panel/old_data/admin_path.pl ${setup_path}/server/panel/data/admin_path.pl
|
||||
if [ -d "/${setup_path}/server/panel/old_data" ];then
|
||||
rm -rf ${setup_path}/server/panel/old_data
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -f panel.zip
|
||||
|
||||
if [ ! -f ${setup_path}/server/panel/tools.py ];then
|
||||
Red_Error "ERROR: Failed to download, please try install again!"
|
||||
fi
|
||||
|
||||
rm -f ${setup_path}/server/panel/class/*.pyc
|
||||
rm -f ${setup_path}/server/panel/*.pyc
|
||||
|
||||
chmod +x /etc/init.d/bt
|
||||
chmod -R 600 ${setup_path}/server/panel
|
||||
chmod -R +x ${setup_path}/server/panel/script
|
||||
ln -sf /etc/init.d/bt /usr/bin/bt
|
||||
echo "${panelPort}" > ${setup_path}/server/panel/data/port.pl
|
||||
wget -O /etc/init.d/bt ${download_Url}/install/src/bt6_en.init -T 10
|
||||
wget -O /www/server/panel/init.sh ${download_Url}/install/src/bt6_en.init -T 10
|
||||
}
|
||||
Install_Python_Lib(){
|
||||
#curl -Ss --connect-timeout 3 -m 60 $download_Url/install/pip_select.sh|bash
|
||||
pyenv_path="/www/server/panel"
|
||||
if [ -f $pyenv_path/pyenv/bin/python ];then
|
||||
chmod -R 700 $pyenv_path/pyenv/bin
|
||||
$pyenv_path/pyenv/bin/pip install cachelib
|
||||
is_package=$($python_bin -m psutil 2>&1|grep package)
|
||||
if [ "$is_package" = "" ];then
|
||||
wget -O $pyenv_path/pyenv/pip.txt $download_Url/install/pyenv/pip.txt -T 5
|
||||
$pyenv_path/pyenv/bin/pip install -U pip
|
||||
$pyenv_path/pyenv/bin/pip install -U setuptools
|
||||
$pyenv_path/pyenv/bin/pip install -r $pyenv_path/pyenv/pip.txt
|
||||
$pyenv_path/pyenv/bin/pip install cachelib
|
||||
fi
|
||||
source $pyenv_path/pyenv/bin/activate
|
||||
return
|
||||
fi
|
||||
py_version="3.7.8"
|
||||
mkdir -p $pyenv_path
|
||||
os_type='el'
|
||||
os_version='7'
|
||||
is_export_openssl=0
|
||||
Get_Versions
|
||||
Centos6_Openssl
|
||||
Other_Openssl
|
||||
echo "OS: $os_type - $os_version"
|
||||
is_aarch64=$(uname -a|grep aarch64)
|
||||
if [ "$is_aarch64" != "" ];then
|
||||
os_version="aarch64"
|
||||
fi
|
||||
if [ "${os_version}" != "" ];then
|
||||
pyenv_file="/www/pyenv.tar.gz"
|
||||
wget -O $pyenv_file $download_Url/install/pyenv/pyenv-${os_type}${os_version}-x${is64bit}.tar.gz -T 10
|
||||
tmp_size=$(du -b $pyenv_file|awk '{print $1}')
|
||||
if [ $tmp_size -lt 703460 ];then
|
||||
rm -f $pyenv_file
|
||||
echo "ERROR: Download python env fielded."
|
||||
else
|
||||
echo "Install python env..."
|
||||
tar zxvf $pyenv_file -C $pyenv_path/ &> /dev/null
|
||||
chmod -R 700 $pyenv_path/pyenv/bin
|
||||
if [ ! -f $pyenv_path/pyenv/bin/python ];then
|
||||
rm -f $pyenv_file
|
||||
Red_Error "ERROR: Install python env fielded."
|
||||
fi
|
||||
rm -f $pyenv_file
|
||||
ln -sf $pyenv_path/pyenv/bin/pip3.7 /usr/bin/btpip
|
||||
ln -sf $pyenv_path/pyenv/bin/python3.7 /usr/bin/btpython
|
||||
source $pyenv_path/pyenv/bin/activate
|
||||
return
|
||||
fi
|
||||
fi
|
||||
if [ -f /usr/local/openssl/lib/libssl.so ];then
|
||||
export LDFLAGS="-L/usr/local/openssl/lib"
|
||||
export CPPFLAGS="-I/usr/local/openssl/include"
|
||||
export PKG_CONFIG_PATH="/usr/local/openssl/lib/pkgconfig"
|
||||
echo "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/openssl/lib" >> /etc/profile
|
||||
source /etc/profile
|
||||
fi
|
||||
cd /www
|
||||
python_src='/www/python_src.tar.xz'
|
||||
python_src_path="/www/Python-${py_version}"
|
||||
wget -O $python_src $download_Url/src/Python-${py_version}.tar.xz -T 5
|
||||
tmp_size=$(du -b $python_src|awk '{print $1}')
|
||||
if [ $tmp_size -lt 10703460 ];then
|
||||
rm -f $python_src
|
||||
Red_Error "ERROR: Download python source code fielded."
|
||||
fi
|
||||
tar xvf $python_src
|
||||
rm -f $python_src
|
||||
cd $python_src_path
|
||||
./configure --prefix=$pyenv_path/pyenv
|
||||
make -j$cpu_cpunt
|
||||
make install
|
||||
if [ ! -f $pyenv_path/pyenv/bin/python3.7 ];then
|
||||
rm -rf $python_src_path
|
||||
Red_Error "ERROR: Make python env fielded."
|
||||
fi
|
||||
cd ~
|
||||
rm -rf $python_src_path
|
||||
wget -O $pyenv_path/pyenv/bin/activate $download_Url/install/pyenv/activate.panel -T 5
|
||||
wget -O $pyenv_path/pyenv/pip.txt $download_Url/install/pyenv/pip-3.7.8.txt -T 5
|
||||
ln -sf $pyenv_path/pyenv/bin/pip3.7 $pyenv_path/pyenv/bin/pip
|
||||
ln -sf $pyenv_path/pyenv/bin/python3.7 $pyenv_path/pyenv/bin/python
|
||||
ln -sf $pyenv_path/pyenv/bin/pip3.7 /usr/bin/btpip
|
||||
ln -sf $pyenv_path/pyenv/bin/python3.7 /usr/bin/btpython
|
||||
chmod -R 700 $pyenv_path/pyenv/bin
|
||||
$pyenv_path/pyenv/bin/pip install -U pip
|
||||
$pyenv_path/pyenv/bin/pip install -U setuptools
|
||||
$pyenv_path/pyenv/bin/pip install -U wheel==0.34.2
|
||||
$pyenv_path/pyenv/bin/pip install -r $pyenv_path/pyenv/pip.txt
|
||||
$pyenv_path/pyenv/bin/pip install -U cachelib
|
||||
source $pyenv_path/pyenv/bin/activate
|
||||
}
|
||||
|
||||
Other_Openssl(){
|
||||
openssl_version=$(openssl version|grep -Eo '[0-9]\.[0-9]\.[0-9]')
|
||||
if [ "$openssl_version" = '1.0.1' ] || [ "$openssl_version" = '1.0.0' ];then
|
||||
opensslVersion="1.0.2r"
|
||||
if [ ! -f "/usr/local/openssl/lib/libssl.so" ];then
|
||||
cd /www
|
||||
openssl_src_file=/www/openssl.tar.gz
|
||||
wget -O $openssl_src_file ${download_Url}/src/openssl-${opensslVersion}.tar.gz
|
||||
tmp_size=$(du -b $openssl_src_file|awk '{print $1}')
|
||||
if [ $tmp_size -lt 703460 ];then
|
||||
rm -f $openssl_src_file
|
||||
Red_Error "ERROR: Download openssl-1.0.2 source code fielded."
|
||||
fi
|
||||
tar -zxf $openssl_src_file
|
||||
rm -f $openssl_src_file
|
||||
cd openssl-${opensslVersion}
|
||||
#zlib-dynamic shared
|
||||
./config --openssldir=/usr/local/openssl zlib-dynamic shared
|
||||
make -j${cpuCore}
|
||||
make install
|
||||
echo "/usr/local/openssl/lib" > /etc/ld.so.conf.d/zopenssl.conf
|
||||
ldconfig
|
||||
cd ..
|
||||
rm -rf openssl-${opensslVersion}
|
||||
is_export_openssl=1
|
||||
cd ~
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
Insatll_Libressl(){
|
||||
openssl_version=$(openssl version|grep -Eo '[0-9]\.[0-9]\.[0-9]')
|
||||
if [ "$openssl_version" = '1.0.1' ] || [ "$openssl_version" = '1.0.0' ];then
|
||||
opensslVersion="3.0.2"
|
||||
cd /www
|
||||
openssl_src_file=/www/openssl.tar.gz
|
||||
wget -O $openssl_src_file ${download_Url}/install/pyenv/libressl-${opensslVersion}.tar.gz
|
||||
tmp_size=$(du -b $openssl_src_file|awk '{print $1}')
|
||||
if [ $tmp_size -lt 703460 ];then
|
||||
rm -f $openssl_src_file
|
||||
Red_Error "ERROR: Download libressl-$opensslVersion source code fielded."
|
||||
fi
|
||||
tar -zxf $openssl_src_file
|
||||
rm -f $openssl_src_file
|
||||
cd libressl-${opensslVersion}
|
||||
./config –prefix=/usr/local/lib
|
||||
make -j${cpuCore}
|
||||
make install
|
||||
ldconfig
|
||||
ldconfig -v
|
||||
cd ..
|
||||
rm -rf libressl-${opensslVersion}
|
||||
is_export_openssl=1
|
||||
cd ~
|
||||
fi
|
||||
}
|
||||
|
||||
Centos6_Openssl(){
|
||||
if [ "$os_type" != 'el' ];then
|
||||
return
|
||||
fi
|
||||
if [ "$os_version" != '6' ];then
|
||||
return
|
||||
fi
|
||||
echo 'Centos6 install openssl-1.0.2...'
|
||||
openssl_rpm_file="/www/openssl.rpm"
|
||||
wget -O $openssl_rpm_file $download_Url/rpm/centos6/${is64bit}/bt-openssl102.rpm -T 10
|
||||
tmp_size=$(du -b $openssl_rpm_file|awk '{print $1}')
|
||||
if [ $tmp_size -lt 102400 ];then
|
||||
rm -f $openssl_rpm_file
|
||||
Red_Error "ERROR: Download python env fielded."
|
||||
fi
|
||||
rpm -ivh $openssl_rpm_file
|
||||
rm -f $openssl_rpm_file
|
||||
is_export_openssl=1
|
||||
}
|
||||
|
||||
Get_Versions(){
|
||||
redhat_version_file="/etc/redhat-release"
|
||||
deb_version_file="/etc/issue"
|
||||
if [ -f $redhat_version_file ];then
|
||||
os_type='el'
|
||||
is_aliyunos=$(cat $redhat_version_file|grep Aliyun)
|
||||
if [ "$is_aliyunos" != "" ];then
|
||||
return
|
||||
fi
|
||||
os_version=$(cat $redhat_version_file|grep CentOS|grep -Eo '([0-9]+\.)+[0-9]+'|grep -Eo '^[0-9]')
|
||||
if [ "${os_version}" = "5" ];then
|
||||
os_version=""
|
||||
fi
|
||||
else
|
||||
os_type='ubuntu'
|
||||
os_version=$(cat $deb_version_file|grep Ubuntu|grep -Eo '([0-9]+\.)+[0-9]+'|grep -Eo '^[0-9]+')
|
||||
if [ "${os_version}" = "" ];then
|
||||
os_type='debian'
|
||||
os_version=$(cat $deb_version_file|grep Debian|grep -Eo '([0-9]+\.)+[0-9]+'|grep -Eo '[0-9]+')
|
||||
if [ "${os_version}" = "" ];then
|
||||
os_version=$(cat $deb_version_file|grep Debian|grep -Eo '[0-9]+')
|
||||
fi
|
||||
if [ "${os_version}" = "8" ];then
|
||||
os_version=""
|
||||
fi
|
||||
if [ "${is64bit}" = '32' ];then
|
||||
os_version=""
|
||||
fi
|
||||
else
|
||||
if [ "$os_version" = "14" ];then
|
||||
os_version=""
|
||||
fi
|
||||
if [ "$os_version" = "12" ];then
|
||||
os_version=""
|
||||
fi
|
||||
if [ "$os_version" = "19" ];then
|
||||
os_version=""
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
Set_Bt_Panel(){
|
||||
chmod -R 700 /www/server/panel/pyenv/bin
|
||||
/www/server/panel/pyenv/bin/pip install cachelib
|
||||
password=$(cat /dev/urandom | head -n 16 | md5sum | head -c 8)
|
||||
sleep 1
|
||||
admin_auth="/www/server/panel/data/admin_path.pl"
|
||||
if [ ! -f ${admin_auth} ];then
|
||||
auth_path=$(cat /dev/urandom | head -n 16 | md5sum | head -c 8)
|
||||
echo "/${auth_path}" > ${admin_auth}
|
||||
fi
|
||||
auth_path=$(cat ${admin_auth})
|
||||
cd ${setup_path}/server/panel/
|
||||
if [ "$SET_SSL" == true ];then
|
||||
pip install -I pyOpenSSl
|
||||
python /www/server/panel/tools.py ssl
|
||||
fi
|
||||
/etc/init.d/bt start
|
||||
$python_bin -m py_compile tools.py
|
||||
$python_bin tools.py username
|
||||
username=$($python_bin tools.py panel ${password})
|
||||
cd ~
|
||||
echo "${password}" > ${setup_path}/server/panel/default.pl
|
||||
chmod 600 ${setup_path}/server/panel/default.pl
|
||||
sleep 3
|
||||
/etc/init.d/bt restart
|
||||
sleep 3
|
||||
isStart=$(ps aux |grep 'BT-Panel'|grep -v grep|awk '{print $2}')
|
||||
LOCAL_CURL=$(curl 127.0.0.1:8888/login 2>&1 |grep -i html)
|
||||
if [ -z "${isStart}" ] && [ -z "${LOCAL_CURL}" ];then
|
||||
/etc/init.d/bt 22
|
||||
Red_Error "ERROR: The BT-Panel service startup failed."
|
||||
fi
|
||||
}
|
||||
Set_Firewall(){
|
||||
sshPort=$(cat /etc/ssh/sshd_config | grep 'Port '|awk '{print $2}')
|
||||
if [ "${PM}" = "apt-get" ]; then
|
||||
apt-get install -y ufw
|
||||
if [ -f "/usr/sbin/ufw" ];then
|
||||
ufw allow 888/tcp
|
||||
ufw allow 20/tcp
|
||||
ufw allow 21/tcp
|
||||
ufw allow 22/tcp
|
||||
ufw allow 80/tcp
|
||||
ufw allow ${panelPort}/tcp
|
||||
ufw allow ${sshPort}/tcp ufw allow 39000:40000/tcp
|
||||
|
||||
ufw_status=`ufw status`
|
||||
echo y|ufw enable
|
||||
ufw default deny
|
||||
ufw reload
|
||||
fi
|
||||
else
|
||||
if [ -f "/etc/init.d/iptables" ];then
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 20 -j ACCEPT
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 21 -j ACCEPT
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ${panelPort} -j ACCEPT
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ${sshPort} -j ACCEPT
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 39000:40000 -j ACCEPT
|
||||
#iptables -I INPUT -p tcp -m state --state NEW -m udp --dport 39000:40000 -j ACCEPT
|
||||
iptables -A INPUT -p icmp --icmp-type any -j ACCEPT
|
||||
iptables -A INPUT -s localhost -d localhost -j ACCEPT
|
||||
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
iptables -P INPUT DROP
|
||||
service iptables save
|
||||
sed -i "s#IPTABLES_MODULES=\"\"#IPTABLES_MODULES=\"ip_conntrack_netbios_ns ip_conntrack_ftp ip_nat_ftp\"#" /etc/sysconfig/iptables-config
|
||||
iptables_status=$(service iptables status | grep 'not running')
|
||||
if [ "${iptables_status}" == '' ];then
|
||||
service iptables restart
|
||||
fi
|
||||
else
|
||||
AliyunCheck=$(cat /etc/redhat-release|grep "Aliyun Linux")
|
||||
[ "${AliyunCheck}" ] && return
|
||||
yum install firewalld -y
|
||||
[ "${Centos8Check}" ] && yum reinstall python3-six -y
|
||||
systemctl enable firewalld
|
||||
systemctl start firewalld
|
||||
firewall-cmd --set-default-zone=public > /dev/null 2>&1
|
||||
firewall-cmd --permanent --zone=public --add-port=20/tcp > /dev/null 2>&1
|
||||
firewall-cmd --permanent --zone=public --add-port=21/tcp > /dev/null 2>&1
|
||||
firewall-cmd --permanent --zone=public --add-port=22/tcp > /dev/null 2>&1
|
||||
firewall-cmd --permanent --zone=public --add-port=80/tcp > /dev/null 2>&1
|
||||
firewall-cmd --permanent --zone=public --add-port=${panelPort}/tcp > /dev/null 2>&1
|
||||
firewall-cmd --permanent --zone=public --add-port=${sshPort}/tcp > /dev/null 2>&1
|
||||
firewall-cmd --permanent --zone=public --add-port=39000-40000/tcp > /dev/null 2>&1
|
||||
#firewall-cmd --permanent --zone=public --add-port=39000-40000/udp > /dev/null 2>&1
|
||||
firewall-cmd --reload
|
||||
fi
|
||||
fi
|
||||
}
|
||||
Get_Ip_Address(){
|
||||
getIpAddress=""
|
||||
# getIpAddress=$(curl -sS --connect-timeout 10 -m 60 https://brandnew.aapanel.com/api/common/getClientIP)
|
||||
getIpAddress=$(curl -sS --connect-timeout 10 -m 60 https://www.bt.cn/Api/getIpAddress)
|
||||
if [ -z "${getIpAddress}" ] || [ "${getIpAddress}" = "0.0.0.0" ]; then
|
||||
isHosts=$(cat /etc/hosts|grep 'www.bt.cn')
|
||||
if [ -z "${isHosts}" ];then
|
||||
echo "" >> /etc/hosts
|
||||
echo "103.224.251.67 www.bt.cn" >> /etc/hosts
|
||||
#getIpAddress=$(curl -sS --connect-timeout 10 -m 60 https://brandnew.aapanel.com/api/common/getClientIP)
|
||||
getIpAddress=$(curl -sS --connect-timeout 10 -m 60 https://www.bt.cn/Api/getIpAddress)
|
||||
if [ -z "${getIpAddress}" ];then
|
||||
sed -i "/bt.cn/d" /etc/hosts
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
ipv4Check=$($python_bin -c "import re; print(re.match('^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$','${getIpAddress}'))")
|
||||
if [ "${ipv4Check}" == "None" ];then
|
||||
ipv6Address=$(echo ${getIpAddress}|tr -d "[]")
|
||||
ipv6Check=$($python_bin -c "import re; print(re.match('^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$','${ipv6Address}'))")
|
||||
if [ "${ipv6Check}" == "None" ]; then
|
||||
getIpAddress="SERVER_IP"
|
||||
else
|
||||
echo "True" > ${setup_path}/server/panel/data/ipv6.pl
|
||||
sleep 1
|
||||
/etc/init.d/bt restart
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "${getIpAddress}" != "SERVER_IP" ];then
|
||||
echo "${getIpAddress}" > ${setup_path}/server/panel/data/iplist.txt
|
||||
fi
|
||||
}
|
||||
Setup_Count(){
|
||||
curl -sS --connect-timeout 10 -m 60 https://brandnew.aapanel.com/api/setupCount/setupPanel?type=Linux > /dev/null 2>&1
|
||||
#curl -sS --connect-timeout 10 -m 60 https://www.aapanel.com/Api/SetupCount?type=Linux > /dev/null 2>&1
|
||||
curl -sS --connect-timeout 10 -m 60 https://console.aapanel.com/Api/SetupCount?type=Linux > /dev/null 2>&1
|
||||
#if [ "$1" != "" ];then
|
||||
echo "66959f96" > /www/server/panel/data/o.pl
|
||||
cd /www/server/panel
|
||||
$python_bin tools.py o
|
||||
#fi
|
||||
echo /www > /var/bt_setupPath.conf
|
||||
}
|
||||
|
||||
Install_Main(){
|
||||
setenforce 0
|
||||
startTime=`date +%s`
|
||||
Lock_Clear
|
||||
System_Check
|
||||
#Set_Ssl
|
||||
Get_Pack_Manager
|
||||
get_node_url
|
||||
|
||||
MEM_TOTAL=$(free -g|grep Mem|awk '{print $2}')
|
||||
if [ "${MEM_TOTAL}" -le "1" ];then
|
||||
Auto_Swap
|
||||
fi
|
||||
|
||||
|
||||
if [ "${PM}" = "yum" ]; then
|
||||
Install_RPM_Pack
|
||||
elif [ "${PM}" = "apt-get" ]; then
|
||||
Install_Deb_Pack
|
||||
fi
|
||||
|
||||
Install_Python_Lib
|
||||
Install_Bt
|
||||
|
||||
Set_Bt_Panel
|
||||
Service_Add
|
||||
Set_Firewall
|
||||
|
||||
Get_Ip_Address
|
||||
Setup_Count ${IDC_CODE}
|
||||
}
|
||||
|
||||
echo "
|
||||
+----------------------------------------------------------------------
|
||||
| aaPanel 6.0 FOR CentOS/Ubuntu/Debian
|
||||
+----------------------------------------------------------------------
|
||||
| Copyright © 2015-2099 BT-SOFT(http://www.aapanel.com) All rights reserved.
|
||||
+----------------------------------------------------------------------
|
||||
| The WebPanel URL will be http://SERVER_IP:8888 when installed.
|
||||
+----------------------------------------------------------------------
|
||||
"
|
||||
|
||||
while [ "$go" != 'y' ] && [ "$go" != 'n' ]
|
||||
do
|
||||
read -p "Do you want to install aaPanel to the $setup_path directory now?(y/n): " go;
|
||||
done
|
||||
|
||||
if [ "$go" == 'n' ];then
|
||||
exit;
|
||||
fi
|
||||
|
||||
Install_Main
|
||||
intenal_ip=$(ip addr | grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -E -v "^127\.|^255\.|^0\." | head -n 1)
|
||||
echo -e "=================================================================="
|
||||
echo -e "\033[32mCongratulations! Installed successfully!\033[0m"
|
||||
echo -e "=================================================================="
|
||||
if [ "$SET_SSL" == true ];then
|
||||
echo "aaPanel Internet Address: https://${getIpAddress}:${panelPort}$auth_path"
|
||||
echo "aaPanel Internal Address: https://${intenal_ip}:${panelPort}$auth_path"
|
||||
else
|
||||
echo "aaPanel Internet Address: http://${getIpAddress}:${panelPort}$auth_path"
|
||||
echo "aaPanel Internal Address: http://${intenal_ip}:${panelPort}$auth_path"
|
||||
fi
|
||||
echo -e "username: $username"
|
||||
echo -e "password: $password"
|
||||
echo -e "\033[33mWarning:\033[0m"
|
||||
echo -e "\033[33mIf you cannot access the panel, \033[0m"
|
||||
echo -e "\033[33mrelease the following port (8888|888|80|443|20|21) in the security group\033[0m"
|
||||
echo -e "=================================================================="
|
||||
|
||||
endTime=`date +%s`
|
||||
((outTime=($endTime-$startTime)/60))
|
||||
echo -e "Time consumed:\033[32m $outTime \033[0mMinute!"
|
||||
rm -f new_install_en.sh
|
||||
|
||||
|
||||
@@ -94,14 +94,14 @@ def WriteLogs(logMsg):
|
||||
pass
|
||||
|
||||
|
||||
def ExecShell(cmdstring, cwd=None, timeout=None, shell=True):
|
||||
def ExecShell(cmdstring, cwd=None, timeout=None, shell=True, symbol = '&>'):
|
||||
try:
|
||||
global logPath
|
||||
import shlex
|
||||
import datetime
|
||||
import subprocess
|
||||
import time
|
||||
sub = subprocess.Popen(cmdstring+' &> '+logPath, cwd=cwd,
|
||||
sub = subprocess.Popen(cmdstring+ symbol +logPath, cwd=cwd,
|
||||
stdin=subprocess.PIPE, shell=shell, bufsize=4096)
|
||||
|
||||
while sub.poll() is None:
|
||||
@@ -135,6 +135,7 @@ def startTask():
|
||||
DownloadFile(argv[0], argv[1])
|
||||
elif value['type'] == 'execshell':
|
||||
ExecShell(value['execstr'])
|
||||
ExecShell("echo '|-Successify ---Script execution completed---'",symbol=">>")
|
||||
end = int(time.time())
|
||||
sql.table('tasks').where("id=?", (value['id'],)).save(
|
||||
'status,end', ('1', end))
|
||||
@@ -603,11 +604,11 @@ def check_files_panel():
|
||||
|
||||
|
||||
# 面板消息提醒
|
||||
def check_panel_msg():
|
||||
python_bin = get_python_bin()
|
||||
while True:
|
||||
os.system('{} {}/script/check_msg.py &'.format(python_bin,base_path))
|
||||
time.sleep(600)
|
||||
# def check_panel_msg():
|
||||
# python_bin = get_python_bin()
|
||||
# while True:
|
||||
# os.system('{} {}/script/check_msg.py &'.format(python_bin,base_path))
|
||||
# time.sleep(600)
|
||||
|
||||
|
||||
def main():
|
||||
@@ -658,9 +659,9 @@ def main():
|
||||
p.setDaemon(True)
|
||||
p.start()
|
||||
|
||||
p = threading.Thread(target=check_files_panel)
|
||||
p.setDaemon(True)
|
||||
p.start()
|
||||
# p = threading.Thread(target=check_files_panel)
|
||||
# p.setDaemon(True)
|
||||
# p.start()
|
||||
import panelTask
|
||||
task_obj = panelTask.bt_task()
|
||||
task_obj.not_web = True
|
||||
@@ -668,9 +669,9 @@ def main():
|
||||
p.setDaemon(True)
|
||||
p.start()
|
||||
|
||||
p = threading.Thread(target=check_panel_msg)
|
||||
p.setDaemon(True)
|
||||
p.start()
|
||||
# p = threading.Thread(target=check_panel_msg)
|
||||
# p.setDaemon(True)
|
||||
# p.start()
|
||||
|
||||
startTask()
|
||||
|
||||
|
||||
@@ -275,7 +275,7 @@ def ClearMail():
|
||||
total += size;
|
||||
count += num;
|
||||
print('=======================================================================')
|
||||
print("CLEAR_RUBBISH2",(str(count),ToSize(total)))
|
||||
print(public.GetMsg('CLEAR_RUBBISH2',(str(count),ToSize(total))))
|
||||
return total,count
|
||||
|
||||
#清理php_session文件
|
||||
|
||||
Reference in New Issue
Block a user