mirror of
https://github.com/aaPanel/aaPanel.git
synced 2026-08-17 21:25:47 +02:00
update 6.3.3
This commit is contained in:
+82
-124
@@ -9,7 +9,7 @@
|
||||
import sys,json,os,time,logging,re
|
||||
if sys.version_info[0] != 2:
|
||||
from imp import reload
|
||||
sys.path.insert(0,'class/')
|
||||
sys.path.insert(0,'/www/server/panel/class/')
|
||||
import public
|
||||
from flask import Flask
|
||||
app = Flask(__name__,template_folder="templates/" + public.GetConfigValue('template'))
|
||||
@@ -19,6 +19,7 @@ from flask_session import Session
|
||||
from werkzeug.contrib.cache import SimpleCache
|
||||
from werkzeug.wrappers import Response
|
||||
from flask_socketio import SocketIO,emit,send
|
||||
from threading import Lock
|
||||
dns_client = None
|
||||
app.config['DEBUG'] = os.path.exists('data/debug.pl')
|
||||
|
||||
@@ -37,11 +38,11 @@ cache = SimpleCache()
|
||||
socketio = SocketIO()
|
||||
socketio.init_app(app)
|
||||
|
||||
import common,db,jobs,uuid
|
||||
import common,db,jobs,uuid,ssh_terminal
|
||||
jobs.control_init()
|
||||
app.secret_key = uuid.UUID(int=uuid.getnode()).hex[-12:]
|
||||
local_ip = None
|
||||
|
||||
my_terms = {}
|
||||
|
||||
try:
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
@@ -67,7 +68,10 @@ app.config['SESSION_COOKIE_NAME'] = "BT_PANEL_6"
|
||||
app.config['PERMANENT_SESSION_LIFETIME'] = 86400
|
||||
Session(app)
|
||||
|
||||
if s_sqlite: sdb.create_all()
|
||||
|
||||
if s_sqlite:
|
||||
sdb.create_all()
|
||||
public.ExecShell("chmod 600 /dev/shm/session.db")
|
||||
|
||||
from datetime import datetime
|
||||
import socket
|
||||
@@ -89,11 +93,67 @@ def service_status():
|
||||
return 'True'
|
||||
|
||||
|
||||
|
||||
@socketio.on('connect')
|
||||
def socket_connect(msg=None):
|
||||
if not check_login():
|
||||
emit('server_response',{'data':public.getMsg('111')})
|
||||
return False
|
||||
|
||||
@socketio.on('webssh')
|
||||
def webssh(msg):
|
||||
if not check_login():
|
||||
session.clear()
|
||||
emit('server_response',"Panel session is lost, please re-login panel!")
|
||||
return None
|
||||
if not 'ssh_obj' in session:
|
||||
session['ssh_obj'] = ssh_terminal.ssh_terminal()
|
||||
session['ssh_obj'].send(msg)
|
||||
|
||||
|
||||
@app.route('/term_open',methods=method_all)
|
||||
def term_open():
|
||||
comReturn = comm.local()
|
||||
if comReturn: return comReturn
|
||||
args = get_input()
|
||||
if 'get_ssh_info' in args:
|
||||
key = 'ssh_' + args['host']
|
||||
if key in session:
|
||||
return public.getJson(session[key]),json_header
|
||||
return public.returnMsg(False,'Acquisition failed!')
|
||||
session['ssh_info'] = json.loads(args.data)
|
||||
key = 'ssh_' + session['ssh_info']['host']
|
||||
session[key] = session['ssh_info']
|
||||
s_file = '/www/server/panel/config/t_info.json'
|
||||
if 'is_save' in session['ssh_info']:
|
||||
public.writeFile(s_file,public.de_hexb(json.dumps(session['ssh_info'])))
|
||||
public.set_mode(s_file,600)
|
||||
else:
|
||||
if os.path.exists(s_file): os.remove(s_file)
|
||||
return public.returnJson(True,'Successful setup!');
|
||||
|
||||
@app.route('/reload_mod',methods=method_all)
|
||||
def reload_mod():
|
||||
comReturn = comm.local()
|
||||
if comReturn: return comReturn
|
||||
args = get_input()
|
||||
mod_name = None
|
||||
if 'mod_name' in args:
|
||||
mod_name = args.mod_name
|
||||
result = public.reload_mod(mod_name)
|
||||
if result: return public.returnJson(True,result),json_header
|
||||
return public.returnJson(False,'Reload failure!'),json_header
|
||||
|
||||
@app.before_request
|
||||
def request_check():
|
||||
if not request.path in ['/safe','/hook','/public']:
|
||||
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:
|
||||
session.clear()
|
||||
return abort(401)
|
||||
domain_check = public.check_domain_panel()
|
||||
if domain_check: return domain_check
|
||||
if public.is_local():
|
||||
@@ -120,7 +180,9 @@ def request_end(reques = None):
|
||||
def send_authenticated():
|
||||
global local_ip
|
||||
if not local_ip: local_ip = public.GetLocalIp()
|
||||
return Response('', 401,{'WWW-Authenticate': 'Basic realm="%s"' % local_ip.strip()})
|
||||
result = Response('', 401,{'WWW-Authenticate': 'Basic realm="%s"' % local_ip.strip()})
|
||||
if not 'login' in session and not 'admin_auth' in session: session.clear()
|
||||
return result
|
||||
|
||||
@app.route('/',methods=method_all)
|
||||
def home():
|
||||
@@ -462,7 +524,7 @@ def config(pdata = None):
|
||||
if public.is_local(): data['is_local'] = 'checked'
|
||||
return render_template( 'config.html',data=data)
|
||||
import config
|
||||
defs = ('get_qrcode_data','check_two_step','set_two_step_auth','get_key','get_php_session_path','set_php_session_path','get_cert_source','set_local','set_debug','get_panel_error_logs','clean_panel_error_logs','get_basic_auth_stat','set_basic_auth','get_cli_php_version','get_tmp_token','set_cli_php_version','DelOldSession', 'GetSessionCount', 'SetSessionConf', 'GetSessionConf','get_ipv6_listen','set_ipv6_status','GetApacheValue','SetApacheValue','GetNginxValue','SetNginxValue','get_token','set_token','set_admin_path','is_pro','get_php_config','get_config','SavePanelSSL','GetPanelSSL','GetPHPConf','SetPHPConf','GetPanelList','AddPanelInfo','SetPanelInfo','DelPanelInfo','ClickPanelInfo','SetPanelSSL','SetTemplates','Set502','setPassword','setUsername','setPanel','setPathInfo','setPHPMaxSize','getFpmConfig','setFpmConfig','setPHPMaxTime','syncDate','setPHPDisable','SetControl','ClosePanel','AutoUpdatePanel','SetPanelLock')
|
||||
defs = ('set_coll_open','get_qrcode_data','check_two_step','set_two_step_auth','get_key','get_php_session_path','set_php_session_path','get_cert_source','set_local','set_debug','get_panel_error_logs','clean_panel_error_logs','get_basic_auth_stat','set_basic_auth','get_cli_php_version','get_tmp_token','set_cli_php_version','DelOldSession', 'GetSessionCount', 'SetSessionConf', 'GetSessionConf','get_ipv6_listen','set_ipv6_status','GetApacheValue','SetApacheValue','GetNginxValue','SetNginxValue','get_token','set_token','set_admin_path','is_pro','get_php_config','get_config','SavePanelSSL','GetPanelSSL','GetPHPConf','SetPHPConf','GetPanelList','AddPanelInfo','SetPanelInfo','DelPanelInfo','ClickPanelInfo','SetPanelSSL','SetTemplates','Set502','setPassword','setUsername','setPanel','setPathInfo','setPHPMaxSize','getFpmConfig','setFpmConfig','setPHPMaxTime','syncDate','setPHPDisable','SetControl','ClosePanel','AutoUpdatePanel','SetPanelLock')
|
||||
return publicObject(config.config(),defs,None,pdata);
|
||||
|
||||
@app.route('/ajax',methods=method_all)
|
||||
@@ -570,6 +632,7 @@ def panel_public():
|
||||
if not public.path_safe_check("%s/%s" % (get.name,get.fun)): return abort(404)
|
||||
if get.fun in ['scan_login', 'login_qrcode', 'set_login', 'is_scan_ok', 'blind','static']:
|
||||
if get.fun == 'static':
|
||||
if not 'filename' in get: return abort(404)
|
||||
if not public.path_safe_check("%s" % (get.filename)): return abort(404)
|
||||
s_file = '/www/server/panel/BTPanel/static/' + get.filename
|
||||
if s_file.find('..') != -1 or s_file.find('./') != -1: return abort(404)
|
||||
@@ -598,6 +661,7 @@ def panel_public():
|
||||
comm.checkWebType()
|
||||
comm.GetOS()
|
||||
result = plu.a(get)
|
||||
session.clear()
|
||||
return public.getJson(result),json_header
|
||||
|
||||
@app.route('/favicon.ico',methods=method_get)
|
||||
@@ -661,7 +725,9 @@ def panel_other(name=None,fun = None,stype=None):
|
||||
comReturn = comm.local()
|
||||
if comReturn:
|
||||
if not is_php:
|
||||
if not hasattr(plu,'_check'): return public.returnJson(False,'SPECIFY_PLUG_ERR'),json_header
|
||||
if not hasattr(plu,'_check'):
|
||||
session.clear()
|
||||
return public.returnJson(False,'SPECIFY_PLUG_ERR'),json_header
|
||||
checks = plu._check(args)
|
||||
r_type = type(checks)
|
||||
if r_type == Response: return checks
|
||||
@@ -738,6 +804,7 @@ def panel_hook():
|
||||
if not os.path.exists('plugin/webhook'): return public.getJson(public.returnMsg(False,'INIT_WEBHOOK_ERR'));
|
||||
sys.path.append('plugin/webhook');
|
||||
import webhook_main
|
||||
session.clear()
|
||||
return public.getJson(webhook_main.webhook_main().RunHook(get));
|
||||
|
||||
@app.route('/safe',methods=method_all)
|
||||
@@ -760,13 +827,16 @@ def panel_safe():
|
||||
if not hasattr(s,get.data['action']): return public.returnJson(False,'INIT_FUN_NOT_EXISTS');
|
||||
defs = ('GetServerInfo','add_ssh_limit','remove_ssh_limit','get_ssh_limit','get_login_log','get_panel_limit','add_panel_limit','remove_panel_limit','close_ssh_limit','close_panel_limit','get_system_info','get_service_info','get_ssh_errorlogin')
|
||||
if not get.data['action'] in defs: return 'False';
|
||||
return public.getJson(eval('s.' + get.data['action'] + '(get)'));
|
||||
result = public.getJson(eval('s.' + get.data['action'] + '(get)'));
|
||||
session.clear()
|
||||
return result
|
||||
|
||||
|
||||
@app.route('/install',methods=method_all)
|
||||
def install():
|
||||
if public.M('config').where("id=?",('1',)).getField('status') == 1:
|
||||
if os.path.exists('install.pl'): os.remove('install.pl');
|
||||
session.clear()
|
||||
return redirect('/login')
|
||||
ret_login = os.path.join('/',admin_path)
|
||||
if admin_path == '/' or admin_path == '/bt': ret_login = '/login'
|
||||
@@ -863,122 +933,6 @@ def panel_cloud():
|
||||
if download_url.find('http') != 0:download_url = 'http://' + download_url
|
||||
return redirect(download_url)
|
||||
|
||||
ssh = None
|
||||
shell = None
|
||||
try:
|
||||
import paramiko
|
||||
ssh = paramiko.SSHClient()
|
||||
except:
|
||||
public.ExecShell('pip install paramiko==2.0.2 &')
|
||||
|
||||
@socketio.on('connect')
|
||||
def socket_connect(msg=None):
|
||||
if not check_login():
|
||||
emit('server_response',{'data':public.getMsg('111')})
|
||||
return False
|
||||
|
||||
@socketio.on('webssh')
|
||||
def webssh(msg):
|
||||
if not check_login(msg['x_http_token']):
|
||||
emit('server_response',{'data':public.getMsg('INIT_WEBSSH_LOGOUT')})
|
||||
return None
|
||||
|
||||
global shell,ssh
|
||||
ssh_success = True
|
||||
if type(msg['data']) == dict:
|
||||
if 'ssh_user' in msg['data']:
|
||||
connect_ssh(msg['data']['ssh_user'].strip(),msg['data']['ssh_passwd'].strip())
|
||||
if not shell: ssh_success = connect_ssh()
|
||||
if not shell:
|
||||
emit('server_response',{'data':public.getMsg('INIT_WEBSSH_CONN_ERR')})
|
||||
return;
|
||||
if shell.exit_status_ready(): ssh_success = connect_ssh()
|
||||
if not ssh_success:
|
||||
emit('server_response',{'data':public.getMsg('INIT_WEBSSH_CONN_ERR')})
|
||||
return;
|
||||
shell.send(msg['data'])
|
||||
time.sleep(0.005)
|
||||
recv = shell.recv(4096)
|
||||
emit('server_response',{'data':recv.decode("utf-8")})
|
||||
|
||||
def connect_ssh(user=None,passwd=None):
|
||||
global shell,ssh
|
||||
pkey = '/root/.ssh/id_rsa_bt'
|
||||
if not os.path.exists('/root/.ssh/authorized_keys') or not os.path.exists(pkey):
|
||||
create_rsa()
|
||||
try:
|
||||
if not user:
|
||||
key=paramiko.RSAKey.from_private_key_file(pkey)
|
||||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
try:
|
||||
if not user:
|
||||
ssh.connect('127.0.0.1', public.GetSSHPort(),pkey=key)
|
||||
else:
|
||||
ssh.connect('127.0.0.1', public.GetSSHPort(),username=user,password=passwd)
|
||||
except:
|
||||
if public.GetSSHStatus():
|
||||
try:
|
||||
if not user:
|
||||
ssh.connect('localhost', public.GetSSHPort(),pkey=key)
|
||||
else:
|
||||
ssh.connect('localhost', public.GetSSHPort(),username=user,password=passwd)
|
||||
except:
|
||||
create_rsa()
|
||||
return False;
|
||||
import firewalls
|
||||
fw = firewalls.firewalls()
|
||||
get = common.dict_obj()
|
||||
ssh_status = fw.GetSshInfo(get)['status']
|
||||
if not ssh_status:
|
||||
get.status = '0';
|
||||
fw.SetSshStatus(get)
|
||||
|
||||
if not user:
|
||||
ssh.connect('127.0.0.1', public.GetSSHPort(),pkey=key)
|
||||
else:
|
||||
ssh.connect('127.0.0.1', public.GetSSHPort(),username=user,password=passwd)
|
||||
|
||||
if not ssh_status:
|
||||
get.status = '1';
|
||||
fw.SetSshStatus(get);
|
||||
shell = ssh.invoke_shell(term='xterm', width=100, height=29)
|
||||
shell.setblocking(0)
|
||||
return True
|
||||
except:
|
||||
shell = None
|
||||
return False
|
||||
|
||||
def create_rsa():
|
||||
id_ras = '/root/.ssh/id_rsa_bt'
|
||||
a_keys = '/root/.ssh/authorized_keys'
|
||||
if not os.path.exists(a_keys) or not os.path.exists(id_ras):
|
||||
public.ExecShell("rm -f /root/.ssh/id_rsa_bt*")
|
||||
public.ExecShell('ssh-keygen -q -t rsa -P "" -f /root/.ssh/id_rsa_bt')
|
||||
public.ExecShell('cat /root/.ssh/id_rsa_bt.pub >> /root/.ssh/authorized_keys')
|
||||
else:
|
||||
id_ras_pub = '/root/.ssh/id_rsa_bt.pub'
|
||||
if os.path.exists(id_ras_pub):
|
||||
pub_body = public.readFile(id_ras_pub)
|
||||
keys_body = public.readFile(a_keys)
|
||||
if keys_body.find(pub_body) == -1:
|
||||
public.ExecShell('cat /root/.ssh/id_rsa_bt.pub >> /root/.ssh/authorized_keys')
|
||||
public.ExecShell('chmod 600 /root/.ssh/authorized_keys')
|
||||
|
||||
@socketio.on('connect_event')
|
||||
def connected_msg(msg):
|
||||
if not check_login():
|
||||
emit('server_response',{'data':public.getMsg('INIT_WEBSSH_LOGOUT')})
|
||||
return None
|
||||
global shell
|
||||
if not shell: connect_ssh()
|
||||
if shell:
|
||||
try:
|
||||
recv = shell.recv(8192)
|
||||
emit('server_response',{'data':recv.decode("utf-8")})
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def check_csrf():
|
||||
if app.config['DEBUG']: return True
|
||||
request_token = request.cookies.get('request_token')
|
||||
@@ -1002,6 +956,10 @@ def publicObject(toObject,defs,action=None,get = None):
|
||||
if get.path.find('./') != -1: return public.ReturnJson(False,public.GetMsg("UNSAFE_PATH")),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('\\','/');
|
||||
|
||||
if hasattr(toObject,'site_path_check'):
|
||||
if not toObject.site_path_check(get): return public.ReturnJson(False,'Excessive operation!'),json_header
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+63
-22
@@ -81,6 +81,12 @@ input::-webkit-input-placeholder {
|
||||
color: #999
|
||||
}
|
||||
|
||||
input[type=checkbox], input[type=radio]{
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
body,
|
||||
html {
|
||||
height: 100%
|
||||
@@ -157,7 +163,7 @@ html {
|
||||
float:right;
|
||||
}
|
||||
.bge6 {
|
||||
background-color: #f2f2f2;
|
||||
background-color: #F1F2F7;
|
||||
}
|
||||
/* .bge6 {
|
||||
background-color: #e6e9ee
|
||||
@@ -829,7 +835,8 @@ html {
|
||||
transition-timing-function: ease;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
margin: 1px 0
|
||||
height: 50px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.sidebar-scroll .mypcip:hover {
|
||||
@@ -840,7 +847,8 @@ html {
|
||||
.sidebar-scroll .mypcip span {
|
||||
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAQCAYAAAAS7Y8mAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAdgAAAHYBTnsmCAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAGPSURBVDiNldQ9ixRBEAbgZ3Zn1fVOuQU/wK9AMDDS1MvuRxj5CwTBP2CiYmYmGBsYGRsaa2qkkSiCgRd4y3ri3XqzbdDV7Lgs7uwLRc90V1dXv29VVymluxiiRoVkNaoYG7wN+9chpTTBBn7jKA5YhYR+JPQEDxYd6rAPeIwDnOgQuMEIz3F8mUMdC9/wqkPAxb1P0Yv/6ziLX/hTy9c6jXPYXSPwBQywF+Mz7GCCSRGMbqK1Ufwbmb4beI9TuNZFqFWoZCH7Mp0XcaX33y3dUDKfmRdD1bM+BYuoWtaEKeIdyqSvg5+RZSWX6Ri3ZUqmRbxjcqnsx3cyF7Utbpmf4YxcapXcWFNcjiSbOk7Yxhu5BocRaGBeoyXYNII32MTJsJ7cvR/D92aN1xFsFA6HYZ/iiiWjTVyVGyrhBz7jXSQxxq3wPahxJ7JuX30sd9IoshviC77KzdSmag+XYm4QNq0tF+0e7sc1SwPs4xFeLPHvt2ibsfwl24rFl/KLV/jdCho2ZC3a+I6HOB9rR38B10ZjDE49T6kAAAAASUVORK5CYII=") no-repeat 0 center;
|
||||
display: inline-block;
|
||||
line-height: 46px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
padding-left: 30px;
|
||||
white-space: nowrap;
|
||||
max-width: 146px;
|
||||
@@ -1052,7 +1060,7 @@ html .menu .menu_exit:hover {
|
||||
.pos-box {
|
||||
height: 50px;
|
||||
width: 100%;
|
||||
box-shadow: 0 1px 2px 0 rgba(0,0,0,.1);
|
||||
/*box-shadow: 0 1px 2px 0 rgba(0,0,0,.1);*/
|
||||
}
|
||||
|
||||
.conter-box{
|
||||
@@ -1061,9 +1069,9 @@ html .menu .menu_exit:hover {
|
||||
|
||||
.position {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAKwwAACsMBNCkkqwAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAFZSURBVDiNpdO9a1VBEAXw3zOioIUQEdFGkQdWVtr6D1ikERtRppLU6awUsUkh2CgoBNwhoPhsLESxERR7wcI2XSBNMAHRNFmLbB6Xa64RXFjYOXvmzMfOjmqt/mcd2I+QmUuZOcgbDWWQmTN4iFms4wGu4jC+RMT7wQwy8xBe4FtE3MBXPMdqE5sfLCEzj+Il3kXEE4iIJTzFFbzB9z0FMvMYJphExLPuXUQs4y1eYfmPHmTmbHN+FBGv92zMDm+ulXAzItZHtVaZeRH3sBgRn4ecOyKXcRt3dkuYwyJOZeaJfZyP42TjX1Nrne5SyqSUMu5ho559tpQy2bUP9gL8wHYnzbtYzczTuB8RHzs8/H0Sz+ETbuEDxg3f7pL6AhW/2vknNiNiCxvY6uDT8e2XMINLmbmC89js3I0z8wLOdP36Aht43KIcwULD1+w82/WGT+dk8DP96/oNlqecb6uu8YEAAAAASUVORK5CYII=");
|
||||
background-position: 17px 14px;
|
||||
background-position: 20px 17px;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 20px auto;
|
||||
/*background-size: 20px auto;*/
|
||||
line-height: 50px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
@@ -1127,7 +1135,10 @@ html .menu .menu_exit:hover {
|
||||
border-bottom: 1px solid #e6e6e6;
|
||||
color: #666;
|
||||
font-weight: normal;
|
||||
padding: 8px
|
||||
padding: 5px 10px;
|
||||
height: 35px;
|
||||
font-size: 12.5px;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
.divtable .table_toolbar{
|
||||
left: 8px;
|
||||
@@ -1164,7 +1175,7 @@ html .menu .menu_exit:hover {
|
||||
.page {
|
||||
/* line-height: 16px; */
|
||||
text-align: right;
|
||||
padding: 8px 0;
|
||||
padding: 14px 0;
|
||||
/* margin-right: 1px; */
|
||||
height: 44px;
|
||||
/* border: 1px solid #e6e6e6;*/
|
||||
@@ -1174,7 +1185,7 @@ html .menu .menu_exit:hover {
|
||||
.site_type{
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
bottom: 8px;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
@@ -1193,6 +1204,7 @@ html .menu .menu_exit:hover {
|
||||
}
|
||||
.site_type select{
|
||||
border-radius: 0px;
|
||||
outline: none;
|
||||
}
|
||||
.site_type_table{
|
||||
padding: 15px;
|
||||
@@ -1384,7 +1396,7 @@ html .menu .menu_exit:hover {
|
||||
-moz-transition: -moz-transform 1s ease-in 0s
|
||||
}
|
||||
|
||||
.pie_left {
|
||||
.pie_left{
|
||||
clip: rect(0, 50px, auto, 0);
|
||||
transition: transform .4s ease-in 1s;
|
||||
-webkit-transition: -webkit-transform .4s ease-in 1s;
|
||||
@@ -2417,6 +2429,11 @@ html .menu .menu_exit:hover {
|
||||
.list-list span.glyphicon-cloud-download {
|
||||
font-size: 12px
|
||||
}
|
||||
.list-list tr>td{
|
||||
padding: 5px 10px !important;
|
||||
line-height: 1.42857143;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.newFolderName {
|
||||
border: #ccc 1px solid;
|
||||
@@ -2851,9 +2868,15 @@ html .menu .menu_exit:hover {
|
||||
}
|
||||
|
||||
.table>tbody>tr>td {
|
||||
vertical-align: middle
|
||||
vertical-align: middle;
|
||||
padding: 5px 10px;
|
||||
height: 40px;
|
||||
font-size: 12.5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.table>tbody{
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.showpicdiv {
|
||||
max-height: 500px;
|
||||
overflow: hidden;
|
||||
@@ -3852,7 +3875,9 @@ html .menu .menu_exit:hover {
|
||||
left: 0;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.file-box .divtable .table{
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
.re-head {
|
||||
border-bottom: 1px solid #ccc;
|
||||
float: left;
|
||||
@@ -4137,6 +4162,7 @@ html .menu .menu_exit:hover {
|
||||
}
|
||||
.btpro{
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADsAAAAUCAMAAAAEAbViAAAAA3NCSVQICAjb4U/gAAABXFBMVEX///+7jAC7jAC7jAC7jAC7jAC7jAC7jAC7jAC7jAC7jAC7jAC7jAC7jAC7jAD////+/fv+/fr8+vX8+vP69uv38eD28N3179v07NXz69Lz6tHz6c/x6Mzv48Pu48Hr3rX74jnq27D54Djp2av43zfo16fo2Kj33TX33Tbm1aLl1Z/12Tbl057z1zLk0Znj0Jfx1DDizpPu0DPv0S7fyIbqzCroyC/cxH3oySjawXXZv3DkwyTYvWzivyzXu2jWumXevCDUtVzctinathzSslXSs1bRsVHRsVLWsBjVrSbNqkPTrBXLqD3PpCLJozTOphHIozLIojDIoS/HoCzKoQ7GninGnyrFnifJnB/FnCTFnSbEmiDEmyLFmQnCmBvBlxjBlhbBlRXAlRPCkhy/kxDAkwW+kQq9kAi9jwa9jwK9jQC8jgS8jQO8ihm7jAC2gRWweBKpbw+jZgydXgnhk9RtAAAAdHRSTlMAESIzRFVmd4iZqrvM3e7//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wol0KMAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAWdEVYdENyZWF0aW9uIFRpbWUAMDUvMzEvMTikOWwBAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAAg5JREFUOI2dlGlz0zAQhhUHJ45jST2gXKUVR4BijmKKCwX1CKcKLoVQcCmFYgcSjqiy8/9nWCtOJvlEwusZe3Q80rurlRFCyLDsSi7bMtAkKlSlU602W61o+3VDvrnOxlTGliUxkdFcfRjN0aWm3ByXBdgglaqN7N2pmb2t6edba0e3xmctBxWxjecoPfPh2afTtPGkN+J6/2SLxC6ajrQvLC4uPJXvLs6/aC7rkZD35/Awb8RMMc5FGAc9FktMiJS42W5HX+SP6Nv+n13GlFJdlWmEVfCkYcD9fF9MTNO0iHX15o3aRnTncq0W7WcDQvQmeEHO1rlm1ZBnw6lAvrBJQY+3s9fOPSbCMA21BEvdHnvssa7qCm3Hz3N1gpQRsu1ZSk8drFC60nrAmM/DmGv5LAg06yVM75mF0fFyFpWkiUrEoHTx6wKt/d7U/R2hUZjkppoFBxCrYCrkfd9ZcVSkUcAlOrW+Q8+3X13S/SIzHHeFXiZjlctYwiFevwNrDdgCdsD09OzbtZmPh9d6/QFQbiJGzsgFksM5Zcv0WVSUlumcPHdwdv3Xcp5DF5KVowMWvioW7nHKh1gIuYznlxq35aOhshFJCBvEaqC4ztKkntQ9FQ+xEDK5u3r08+Vo0dVHm3Ayvu9nhr1htuDIvc/y/RU2ifqX2MBSHo59g0ZZZJLv9/8ThXyZE/1tQH8B/ly2lqVFKXEAAAAASUVORK5CYII=");
|
||||
background-size: 50px;
|
||||
background-repeat:no-repeat;
|
||||
padding:2px 0 2px 64px;
|
||||
margin-right:5px;
|
||||
@@ -4413,12 +4439,14 @@ html .menu .menu_exit:hover {
|
||||
.bind-weixin{
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAASBAMAAACtCzMeAAAAA3NCSVQICAjb4U/gAAAAKlBMVEX19fXr6+vg4ODW1tbMzMzCwsK4uLitra2jo6OZmZmPj4+FhYV6enr////oR1GpAAAADnRSTlP/////////////////AEXA3MgAAAAJcEhZcwAADpwAAA6cAQeUU90AAAAWdEVYdENyZWF0aW9uIFRpbWUAMDgvMTYvMTgi+WYYAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAAK9JREFUCJljuHuXyS1I4C4IMNy9MiNYpF0XzL5Qznv37uUpYPbVWBDF4Qtii9+N8b2y5WIRiB1810L3UuHdEBC7FqTkYlhnqyyUbcJ798rSuwxBQOYVkE5OX6Deu3dVedMulF1oYLgCNDPpbujd1LtJDEDqbhDYCc4Md9WUBIrB7ESGu15pLiUg5oUAhrvKd+9etQWy2WUZwEJAPUCbwey7zCHu04ug7LsMDExL7gIAh3d+c1Jd4JYAAAAASUVORK5CYII=");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 16px;
|
||||
padding-left:26px;
|
||||
margin-right:30px;
|
||||
}
|
||||
.bind-user{
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASBAMAAACk4JNkAAAAA3NCSVQICAjb4U/gAAAAMFBMVEX19fXr6+vg4ODW1tbMzMzCwsK4uLitra2jo6OZmZmPj4+FhYV6enpwcHBmZmb///+wFcT2AAAAEHRSTlP///////////////////8A4CNdGQAAAAlwSFlzAAAOnAAADpwBB5RT3QAAABZ0RVh0Q3JlYXRpb24gVGltZQAwOC8xNi8xOCL5ZhgAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAh0lEQVQImWP4//+/2KxiIMnw//+X2+1rCsCsuP7/n26CWB+PA6X04oGsbweBrJ/rgawf64GsbxtQWBDZ+TAdNv5gUxL+s74EmfJpz6mOtWdAYnYTNFZP/vb0P8OHU///f/j/P0+f4duF/yDwaz4Ddz2Y9ekQg448mPV/G4M3hPG/g8ESygoHALeIhpF8DGw6AAAAAElFTkSuQmCC");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 14px;
|
||||
padding-left:24px;
|
||||
margin-right:16px;
|
||||
}
|
||||
@@ -4428,35 +4456,48 @@ html .menu .menu_exit:hover {
|
||||
padding-left:13px;
|
||||
margin-right:20px;
|
||||
}
|
||||
|
||||
.bt-724 {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAQCAMAAACvHOZVAAAAA3NCSVQICAjb4U/gAAAAOVBMVEXeQRTxrJnkZUD76OLqiWzzuKfgTSP53NT////30MXvoIriWTHmcU/99PHslHvofV71xLbjXznpgGGbp65eAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAFnRFWHRDcmVhdGlvbiBUaW1lADA3LzEwLzE5ht15uwAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAACrSURBVCiRrZBLAsMgCETJRxwUTdP7H7b4SUnW7SxU4gMnQ/QP5TSlrVqDyGufV4usbVNMJSv2cVw6UIHexdoUUdjOBVHXAPBs1e9TB9AGctqybf3G6OKEVcmd7R2PCOJEwuaAFoi5RGQnbMRln3iB3dmcksmJ2m0OINpPMeWCTcR8y/hsTzpQ9B4BRmbAQWd6dzbyPYKqVzJEZ1vqo9N9VAk9BPMnU4/Uf9cHAxAHhkB15V0AAAAASUVORK5CYII=");
|
||||
background-repeat: no-repeat;
|
||||
padding-left: 35px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
/*系统图标*/
|
||||
.ico-linux{
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAATBAMAAACEi/vCAAAAA3NCSVQICAjb4U/gAAAAMFBMVEX///9mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmambAcKAAAAEHRSTlMAESIzRFVmd4iZqrvM3e7/dpUBFQAAAAlwSFlzAAAOwwAADsMBx2+oZAAAABZ0RVh0Q3JlYXRpb24gVGltZQAwOC8xNi8xOCL5ZhgAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAmUlEQVQImWNgYGCQ/GvAAAHz/1+CMBjPvvoOYTFVLXkNZZ2u+isAZjE/4vyvAGaxlgbnJ4BZHAoM3A/BLA8GBpafYNYiIL4PMpt1A5DYPwFIcDWArDkAJPgWAInzF4BE9jMGBvb/QM2SBfEGDFy7UhkY3Bk4CxisGdgCGMwYGI97vGKwSmAQC1G8e+aN2WagDuP0IEGbawIMAPDJKG706GgtAAAAAElFTkSuQmCC");
|
||||
background-size: 12px;
|
||||
background-repeat:no-repeat;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.ico-windows{
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAA3NCSVQICAjb4U/gAAAALVBMVEX///+ZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZny8jBSAAAAD3RSTlMAESIzRFVmd4iZqrvM7v/Y8bBbAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAFnRFWHRDcmVhdGlvbiBUaW1lADA4LzE2LzE4IvlmGAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAABGSURBVAiZY2AAAkbTqrMMDEJuHvfevXvHcPbdu+53IMY7Ihi7d+9O7QACBiB2BTOAol0wNbgY59696wQzGFQqw8GWwpwBAGURWs03JAEWAAAAAElFTkSuQmCC");
|
||||
background-repeat:no-repeat;
|
||||
background-size: 12px;
|
||||
background-position: 0 2px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.ico-centos{
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAPCAMAAADjyg5GAAAAA3NCSVQICAjb4U/gAAAASFBMVEX///9mZmZmZmZiYmJaWlpYWFhmZmZiYmJgYGBmZmZgYGBmZmZiYmJmZmZiYmJmZmZiYmJmZmZmZmZmZmZmZmZmZmZmZmZmZmbwNFvuAAAAGHRSTlMAESIiIiIzMzNERFVVZmZ3d4iZqrvM3f93YyfbAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAFnRFWHRDcmVhdGlvbiBUaW1lADA4LzE3LzE4mkUBfQAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAB6SURBVAiZVY5ZEsIwDEMdUpYQghIv9f1vWpNCp/hH1oz1LKI5if5G5ezuzLff7ibO7KK+H2LaBp1WDMLcYDNf3A31CXMvRCy995rSK0SExhjAkh/XEK5E2YOCN5r75RNGUJgtZJLXoMQjw/ot2LR3baJHSbN8Ll3LrhtQxAfrvVHLpQAAAABJRU5ErkJggg==");
|
||||
background-size: 12px;
|
||||
background-repeat:no-repeat;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.ico-ubuntu{
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAMAAAAolt3jAAAAA3NCSVQICAjb4U/gAAAAOVBMVEX///9mZmZhYWFmZmZiYmJmZmZiYmJmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZVQ1Z+AAAAE3RSTlMAEREiIjMzRFVmd4iZqrvM3e7/67N/KAAAAAlwSFlzAAAOwwAADsMBx2+oZAAAABZ0RVh0Q3JlYXRpb24gVGltZQAwOC8xNy8xOJpFAX0AAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAbElEQVQImU2OWQ6AMAhEcW3Z2jL3P6xWjHE+CMPwCESfDOXtFmutAp6OtwC0jUwZVlWHaaaBniyYVq6B/Rn3G3aEjDxRuPwtN6NFzkB97IAlE3ddHTimPUKkd3TlhLb5huvLzAWWE2j0k0elCynoBUe/zXGJAAAAAElFTkSuQmCC");
|
||||
background-size: 12px;
|
||||
background-repeat:no-repeat;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.ico-debian{
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAQCAMAAAARSr4IAAAAA3NCSVQICAjb4U/gAAAAPFBMVEX///9paWlmZmZgYGBdXV1mZmZgYGBmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmYdQ+x6AAAAFHRSTlMAERERESIiM0RVZneImaq7zN3u/ynguF0AAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAWdEVYdENyZWF0aW9uIFRpbWUAMDgvMTcvMTiaRQF9AAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAAHJJREFUCJlVjlESwjAIRLFFIRhCaO5/VyHijN2vt+zCABBq87IhT/hK1+zdfOl2Y71r2rPp1UKfAOdFgaTtAWIRWgacMUUquSi7TR6U2LflFuW0nOVjYB7JQBqwHklOe49f9dOAf+HvjRIZ3L3ePTIWfQAgiAODqr7Z+QAAAABJRU5ErkJggg==");
|
||||
background-size: 12px;
|
||||
background-repeat:no-repeat;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.ico-fedora{
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAMAAAAolt3jAAAAA3NCSVQICAjb4U/gAAAAPFBMVEX///9VVVVLS0tmZmZaWlpmZmZiYmJmZmZiYmJmZmZiYmJiYmJmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmYd2jWRAAAAFHRSTlMAEREiIjMzRERVVWaImaq7zN3u/2KENScAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAWdEVYdENyZWF0aW9uIFRpbWUAMDgvMTcvMTiaRQF9AAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAAGJJREFUCJlFj1kSwCAIQ9N9Lxjuf9faUKf5IPNQiAJAZ4yg9ZCWkMj5pxWwGCqK5skLg8AphMv2dIJC0106nNmu5VLA1bBmfqclF7fZO9HTYqzO4tMuOt5XGLA1enMzQ194ADH/CrSqGfFbAAAAAElFTkSuQmCC");
|
||||
background-size: 12px;
|
||||
background-repeat:no-repeat;
|
||||
padding-left: 20px;
|
||||
}
|
||||
@@ -4916,11 +4957,11 @@ select[disabled]{
|
||||
.search_box{
|
||||
position: absolute;
|
||||
right: 65px;
|
||||
top: 12px;
|
||||
top: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
.search_box input{
|
||||
position: relative;
|
||||
top: 2.5px;
|
||||
vertical-align: sub;
|
||||
}
|
||||
.search_box label{
|
||||
color: #666;
|
||||
@@ -5070,10 +5111,11 @@ select[disabled]{
|
||||
background: -webkit-linear-gradient(top,rgba(255, 255, 255, 0),rgba(220, 220, 220, .8));
|
||||
}
|
||||
.newTableShadow{
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
position: relative;
|
||||
background: -webkit-linear-gradient(top,rgba(220, 220, 220, .8),rgba(255, 255, 255, 0));
|
||||
/*display: none;*/
|
||||
/*width: 100%;*/
|
||||
/* height: 8px;*/
|
||||
/* position: relative;*/
|
||||
/* background: -webkit-linear-gradient(top,rgba(220, 220, 220, .8),rgba(255, 255, 255, 0));*/
|
||||
}
|
||||
|
||||
.disable {
|
||||
@@ -5422,10 +5464,9 @@ select[disabled]{
|
||||
text-overflow: ellipsis;
|
||||
line-height: 40px;
|
||||
height: 40px;
|
||||
margin: 0 10px 0 0;
|
||||
margin: 0 15px 0 0;
|
||||
}
|
||||
.ace_conter_menu .item .icon_file {
|
||||
color: #ff9800;
|
||||
font-weight: 500;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
+42
-22
@@ -164,20 +164,18 @@ $('.open_two_verify_view').click(function(){
|
||||
$('#panel_verification').prop('checked',res.status);
|
||||
});
|
||||
})()
|
||||
function get_qrcode_data(callback){
|
||||
$.post('/config?action=get_qrcode_data',function(res){
|
||||
if(callback) callback(res);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function check_two_step(callback){
|
||||
$.post('/config?action=check_two_step',function(res){
|
||||
if(callback) callback(res);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
function get_qrcode_data(callback){
|
||||
$.post('/config?action=get_qrcode_data',function(res){
|
||||
if(callback) callback(res);
|
||||
});
|
||||
}
|
||||
function get_two_verify(callback){
|
||||
$.post('/config?action=get_key',function(res){
|
||||
if(callback) callback(res);
|
||||
@@ -764,31 +762,53 @@ function GetPanelApi() {
|
||||
})
|
||||
});
|
||||
}
|
||||
function showPawApi(){
|
||||
layer.msg('The panel API key only supports one-time display, please keep it safe. <br>To display the panel API key, click the reset button to regain the new API key.<br><span style="color:red;">Note: After the key is reset, the associated key product will be invalid. Please re-add the new key to the product.</span>',{icon:0,time:0,shadeClose:true,shade:0.1});
|
||||
}
|
||||
|
||||
|
||||
function SetPanelApi(t_type) {
|
||||
function SetPanelApi(t_type,index) {
|
||||
var pdata = {}
|
||||
pdata['t_type'] = t_type
|
||||
if (t_type == 3) {
|
||||
pdata['limit_addr'] = $("textarea[name='api_limit_addr']").val()
|
||||
}
|
||||
var loadT = layer.msg(lan.config.is_submitting, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/config?action=set_token', pdata, function (rdata) {
|
||||
if (t_type == 1) {
|
||||
if (rdata.status) {
|
||||
$("input[name='panel_token_value']").val(rdata.msg);
|
||||
layer.msg(lan.config.create_int_key_success, { icon: 1, time: 0, shade: 0.3, shadeClose:true });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
if(t_type == 1){
|
||||
var bdinding = layer.confirm('Are you sure you want to reset your current key?<br><span style="color:red;">After the key is reset, the associated key product will be invalid. Please re-add the new key to the product.</span>',{
|
||||
btn:['Confirm','Cancel'],
|
||||
icon:3,
|
||||
closeBtn: 2,
|
||||
title:'Reset key'
|
||||
},function(){
|
||||
var loadT = layer.msg(lan.config.is_submitting, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
set_token_req(pdata,function(rdata){
|
||||
if (rdata.status) {
|
||||
$("input[name='panel_token_value']").val(rdata.msg);
|
||||
layer.msg(lan.config.create_int_key_success, { icon: 1, time: 0, shade: 0.3, shadeClose:true,closeBtn:2});
|
||||
}else{
|
||||
layer.msg(rdata.msg, { icon: 2});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
});
|
||||
return false
|
||||
}
|
||||
set_token_req(pdata,function(rdata){
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
if (rdata.msg == lan.config.open_successfully) {
|
||||
GetPanelApi();
|
||||
if(t_type == 2 && index != '0') GetPanelApi();
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function set_token_req(pdata,callback){
|
||||
$.post('/config?action=set_token', pdata, function (rdata) {
|
||||
if(callback) callback(rdata);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
function SetIPv6() {
|
||||
var loadT = layer.msg(lan.config.setting_up, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/config?action=set_ipv6_status', {}, function (rdata) {
|
||||
|
||||
@@ -819,7 +819,7 @@ function toBackup(type){
|
||||
<span><input type="number" name="save" id="save" value="3" maxlength="4" max="100" min="1"></span>\
|
||||
<span class="name">'+lan.crontab.save_num+'</span>\
|
||||
</div>';
|
||||
if (sType == 'sites') {
|
||||
if (sType == 'sites' && sMsg !== lan.crontab.backup_log) {
|
||||
sBody += '<p class="clearfix plan">\
|
||||
<div class="textname pull-left mr20" style="margin-left: 63px; font-size: 14px;">'+lan.crontab.exclusion_rule+'</div>\
|
||||
<div class="dropdown planBackupTo pull-left mr20">\
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
var database = {
|
||||
get_list: function (page, search) {
|
||||
if (page == undefined) page = 1;
|
||||
if (!search) search = $("#SearchValue").val();
|
||||
bt.database.get_list(page, search, function (rdata) {
|
||||
$('#databasePage').html(rdata.page);
|
||||
var _tab = bt.render({
|
||||
@@ -369,7 +370,7 @@ var database = {
|
||||
},
|
||||
input_database: function (name) {
|
||||
var path = bt.get_cookie('backup_path') + "/database";
|
||||
bt.files.get_files(path, '', function (rdata) {
|
||||
bt.send('get_files', 'files/GetDir', 'reverse=True&sort=mtime&tojs=GetFiles&p=1&showRow=100&path=' + path, function (rdata) {
|
||||
var data = [];
|
||||
for (var i = 0; i < rdata.FILES.length; i++) {
|
||||
if (rdata.FILES[i] == null) continue;
|
||||
@@ -410,8 +411,8 @@ var database = {
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'opt', title: lan.database.operation, align: 'right', templet: function (item) {
|
||||
return '<a class="btlink" herf="javascrpit:;" onclick="bt.database.input_sql(\'' + bt.rtrim(rdata.PATH, '/') + "/" + item.name + '\',\'' + name + '\')">'+lan.database.input+'</a> ';;
|
||||
field: 'opt', title: 'Operating', align: 'right', templet: function (item) {
|
||||
return '<a class="btlink" herf="javascrpit:;" onclick="bt.database.input_sql(\'' + bt.rtrim(rdata.PATH, '/') + "/" + item.name + '\',\'' + name + '\')">'+lan.database.input+'</a> | <a class="btlink" onclick="database.remove_input_file(\'' + bt.rtrim(rdata.PATH, '/') + "/" + item.name + '\',\'' + name + '\')">Del</a>';
|
||||
}
|
||||
},
|
||||
],
|
||||
|
||||
+79
-77
@@ -534,15 +534,15 @@ function GetFiles(Path,sort) {
|
||||
</thead>\
|
||||
<tbody id="filesBody" class="list-list">'+Body+'</tbody>\
|
||||
</table></div><div class="oldTableShadow"></div>';
|
||||
$("#fileCon").removeClass("fileList").html(tablehtml);
|
||||
$("#tipTools").width($("#fileCon").width());
|
||||
}
|
||||
else{
|
||||
$("#fileCon").addClass("fileList").html(Body);
|
||||
$("#tipTools").width($("#fileCon").width());
|
||||
}
|
||||
$("#DirPathPlace input").val(rdata.PATH);
|
||||
var BarTools = '<div class="btn-group">\
|
||||
$("#fileCon").removeClass("fileList").html(tablehtml);
|
||||
$("#tipTools").width($("#fileCon")[0].clientWidth - 20);
|
||||
}
|
||||
else {
|
||||
$("#fileCon").addClass("fileList").html(Body);
|
||||
$("#tipTools").width($("#fileCon")[0].clientWidth - 20);
|
||||
}
|
||||
$("#DirPathPlace input").val(rdata.PATH);
|
||||
var BarTools = '<div class="btn-group">\
|
||||
<button class="btn btn-default btn-sm dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">\
|
||||
'+lan.files.new+' <span class="caret"></span>\
|
||||
</button>\
|
||||
@@ -600,9 +600,9 @@ function GetFiles(Path,sort) {
|
||||
}
|
||||
$("#Batch").html(BatchTools);
|
||||
$("#setBox").prop("checked", false);
|
||||
|
||||
|
||||
$("#BarTools").html(BarTools);
|
||||
|
||||
|
||||
$("input[name=id]").click(function(){
|
||||
if($(this).prop("checked")) {
|
||||
$(this).prop("checked", true);
|
||||
@@ -631,7 +631,7 @@ function GetFiles(Path,sort) {
|
||||
if ($(this).prop("checked")) {
|
||||
$("input[name=id]").prop("checked", true);
|
||||
$("#filesBody > tr").addClass("ui-selected");
|
||||
|
||||
|
||||
} else {
|
||||
$("input[name=id]").prop("checked", false);
|
||||
$("#filesBody > tr").removeClass("ui-selected");
|
||||
@@ -690,13 +690,13 @@ function auto_table_width(){
|
||||
});
|
||||
if(oldTable_heigth > oldTable){
|
||||
$('.oldTableShadow,.newTableShadow').show();
|
||||
$('.oldTable').css('marginTop','-8px')
|
||||
$('.oldTable').css('marginTop','0')
|
||||
}else{
|
||||
$('.oldTableShadow,.newTableShadow').hide();
|
||||
$('.oldTable').css('marginTop','0')
|
||||
}
|
||||
$('.oldTable').height(oldTable);
|
||||
$('.oldTable table').css({'marginTop':'-39px'})
|
||||
$('.oldTable table').css({ 'marginTop': '-36px' })
|
||||
|
||||
}
|
||||
|
||||
@@ -757,22 +757,22 @@ function showSeclect(){
|
||||
$("#Batch").html(BatchTools);
|
||||
}
|
||||
}
|
||||
$("#tipTools").width($(".file-box").width());
|
||||
$("#PathPlaceBtn").width($(".file-box").width()-700);
|
||||
$("#DirPathPlace input").width($(".file-box").width()-700);
|
||||
if($(window).width()<1160){
|
||||
$("#PathPlaceBtn").width(290);
|
||||
$("#tipTools").width($(".file-box")[0].clientWidth);
|
||||
$("#PathPlaceBtn").width($(".file-box").width() - 700);
|
||||
$("#DirPathPlace input").width($(".file-box").width() - 700);
|
||||
if ($(window).width() < 1160) {
|
||||
$("#PathPlaceBtn").width(290);
|
||||
}
|
||||
window.onresize = function(){
|
||||
$("#tipTools").width($(".file-box").width()-30);
|
||||
$("#PathPlaceBtn").width($(".file-box").width()-700);
|
||||
$("#DirPathPlace input").width($(".file-box").width()-700);
|
||||
if($(window).width()<1160){
|
||||
$("#PathPlaceBtn,#DirPathPlace input").width(290);
|
||||
}
|
||||
PathLeft();
|
||||
IsDiskWidth()
|
||||
auto_table_width();
|
||||
window.onresize = function () {
|
||||
$("#tipTools").width($(".file-box")[0].clientWidth);
|
||||
$("#PathPlaceBtn").width($(".file-box").width() - 700);
|
||||
$("#DirPathPlace input").width($(".file-box").width() - 700);
|
||||
if ($(window).width() < 1160) {
|
||||
$("#PathPlaceBtn,#DirPathPlace input").width(290);
|
||||
}
|
||||
PathLeft();
|
||||
IsDiskWidth()
|
||||
auto_table_width();
|
||||
}
|
||||
function Batch(type,access){
|
||||
var path = $("#DirPathPlace input").val();
|
||||
@@ -781,9 +781,9 @@ function Batch(type,access){
|
||||
var data='path='+path+'&type='+type;
|
||||
var name = 'data';
|
||||
var datas = []
|
||||
|
||||
|
||||
var oldType = getCookie('BatchPaste');
|
||||
|
||||
|
||||
for(var i=0;i<len;i++){
|
||||
if (el[i].checked == true && el[i].value != 'on') {
|
||||
datas.push(el[i].value)
|
||||
@@ -791,27 +791,28 @@ function Batch(type,access){
|
||||
}
|
||||
|
||||
data += "&data=" + encodeURIComponent(JSON.stringify(datas))
|
||||
|
||||
|
||||
if(type == 3 && access == undefined){
|
||||
SetChmod(0,lan.files.all);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(type < 3) setCookie('BatchSelected', '1');
|
||||
setCookie('BatchPaste',type);
|
||||
|
||||
if(access == 1){
|
||||
var access = $("#access").val();
|
||||
var chown = $("#chown").val();
|
||||
data += '&access='+access+'&user='+chown;
|
||||
layer.closeAll();
|
||||
}
|
||||
if(type == 4){
|
||||
AllDeleteFileSub(data,path);
|
||||
setCookie('BatchPaste',oldType);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (access == 1) {
|
||||
var access = $("#access").val();
|
||||
var chown = $("#chown").val();
|
||||
var all = $("#accept_all").prop("checked") ? 'True' : 'False';
|
||||
data += '&access=' + access + '&user=' + chown + "&all=" + all;
|
||||
layer.closeAll();
|
||||
}
|
||||
if (type == 4) {
|
||||
AllDeleteFileSub(data, path);
|
||||
setCookie('BatchPaste', oldType);
|
||||
return;
|
||||
}
|
||||
|
||||
if(type == 5){
|
||||
var names = '';
|
||||
for(var i=0;i<len;i++){
|
||||
@@ -822,7 +823,7 @@ function Batch(type,access){
|
||||
Zip(names);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
myloadT = layer.msg("<div class='myspeed'>"+lan.public.the+"</div>",{icon:16,time:0,shade: [0.3, '#000']});
|
||||
setTimeout(function(){getSpeed('.myspeed');},1000);
|
||||
$.post('/files?action=SetBatchData',data,function(rdata){
|
||||
@@ -835,14 +836,14 @@ function BatchPaste(){
|
||||
var path = $("#DirPathPlace input").val();
|
||||
var type = getCookie('BatchPaste');
|
||||
var data = 'type='+type+'&path='+path;
|
||||
|
||||
|
||||
$.post('/files?action=CheckExistsFiles',{dfile:path},function(result){
|
||||
if(result.length > 0){
|
||||
var tbody = '';
|
||||
for(var i=0;i<result.length;i++){
|
||||
tbody += '<tr><td>'+result[i].filename+'</td><td>'+ToSize(result[i].size)+'</td><td>'+getLocalTime(result[i].mtime)+'</td></tr>';
|
||||
}
|
||||
var mbody = '<div class="divtable" style="height: 395px;overflow: auto;border: #ddd 1px solid;position: relative;"><table class="table table-hover" width="100%" border="0" cellpadding="0" cellspacing="0"><thead><th>'+lan.files.file_name+'</th><th>'+lan.files.file_size+'</th><th>'+lan.files.last_edit_time+'</th></thead>\
|
||||
var mbody = '<div class="divtable" style="height: 395px;overflow: auto;margin-top: -8px;border: #ddd 1px solid;position: relative;"><table class="table table-hover" width="100%" border="0" cellpadding="0" cellspacing="0"><thead><th>'+lan.files.file_name+'</th><th>'+lan.files.file_size+'</th><th>'+lan.files.last_edit_time+'</th></thead>\
|
||||
<tbody>'+tbody+'</tbody>\
|
||||
</table></div>';
|
||||
SafeMessage(lan.files.will_cover_this_file,mbody,function(){
|
||||
@@ -854,7 +855,7 @@ function BatchPaste(){
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function BatchPasteTo(data,path){
|
||||
myloadT = layer.msg("<div class='myspeed'>"+lan.public.the+"</div>",{icon:16,time:0,shade: [0.3, '#000']});
|
||||
setTimeout(function(){getSpeed('.myspeed');},1000);
|
||||
@@ -866,7 +867,7 @@ function BatchPasteTo(data,path){
|
||||
});
|
||||
}
|
||||
function GetExtName(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','flv','mkv','mov','mp3','mp4','mpeg','mpg','rm','rmvb','swf','wav','webm','wma','wmv','rtf','docx','fdf','potm','pptx','txt','xlsb','xlsx','7z','cab','iso','bz2','rar','zip','gz','bt','file','apk','bookfolder','folder','folder-empty','folder-unempty','fromchromefolder','documentfolder','fromphonefolder','mix','musicfolder','picturefolder','videofolder','sefolder','access','mdb','accdb','sql','c','cpp','cs','js','fla','flv','htm','html','java','log','mht','php','url','xml','ai','bmp','cdr','gif','ico','jpeg','jpg','JPG','png','psd','webp','ape','avi','flv','mkv','mov','mp3','mp4','mpeg','mpg','rm','rmvb','swf','wav','webm','wma','wmv','doc','docm','dotx','dotm','dot','rtf','docx','pdf','fdf','ppt','pptm','pot','potm','pptx','txt','xls','csv','xlsm','xlsb','xlsx','7z','gz','cab','iso','rar','zip','bt','file','apk','css'];
|
||||
var extLastName = extArr[extArr.length - 1];
|
||||
for(var i=0; i<exts.length; i++){
|
||||
@@ -940,7 +941,7 @@ function CreateFile(type, path) {
|
||||
type: 1,
|
||||
shift: 5,
|
||||
closeBtn: 2,
|
||||
area: '320px',
|
||||
area: '320px',
|
||||
title: lan.files.new_empty_file,
|
||||
content: '<div class="bt-form pd20 pb70">\
|
||||
<div class="line">\
|
||||
@@ -1114,7 +1115,7 @@ function ExecShell(action){
|
||||
else{
|
||||
layer.msg(rdata.msg,{icon:rdata.status?1:2});
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -1122,7 +1123,7 @@ function ExecShell(action){
|
||||
type: 1,
|
||||
shift: 5,
|
||||
closeBtn: 2,
|
||||
area: ['70%','600px'],
|
||||
area: ['70%','600px'],
|
||||
title: lan.files.shell_title,
|
||||
content: '<div class="bt-form pd15">\
|
||||
<div class="shellcode"><pre id="Result"></pre></div>\
|
||||
@@ -1134,7 +1135,7 @@ function ExecShell(action){
|
||||
setTimeout(function(){
|
||||
outTimeGet();
|
||||
},1000);
|
||||
|
||||
|
||||
}
|
||||
|
||||
var outTime = null;
|
||||
@@ -1171,7 +1172,7 @@ function ReName(type, fileName) {
|
||||
type: 1,
|
||||
shift: 5,
|
||||
closeBtn: 2,
|
||||
area: '320px',
|
||||
area: '320px',
|
||||
title: lan.files.file_menu_rename,
|
||||
content: '<div class="bt-form pd20 pb70">\
|
||||
<div class="line">\
|
||||
@@ -1250,7 +1251,7 @@ function PasteTo(path,copyName,cutName,fileName){
|
||||
setCookie('cutFileName', null);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (cutName != 'null' && cutName != undefined) {
|
||||
layer.msg(lan.files.mv_the, {
|
||||
icon: 16,
|
||||
@@ -1298,13 +1299,13 @@ function Zip(dirName,submits) {
|
||||
});
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
param = dirName;
|
||||
if(dirName.indexOf(',') != -1){
|
||||
tmp = path.split('/')
|
||||
dirName = path + '/' + tmp[tmp.length-1]
|
||||
}
|
||||
|
||||
|
||||
var layers = layer.open({
|
||||
type: 1,
|
||||
shift: 5,
|
||||
@@ -1336,7 +1337,7 @@ function Zip(dirName,submits) {
|
||||
$("#dfile").val(dirName + '.' + z_type);
|
||||
});
|
||||
},100);
|
||||
|
||||
|
||||
}
|
||||
function UnZip(fileName,type) {
|
||||
var path = $("#DirPathPlace input").val();
|
||||
@@ -1354,7 +1355,7 @@ function UnZip(fileName,type) {
|
||||
});
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
type = (type == 1) ? 'tar':'zip'
|
||||
var umpass = '';
|
||||
if(type == 'zip'){
|
||||
@@ -1459,7 +1460,7 @@ function UploadFiles() {
|
||||
type:1,
|
||||
closeBtn: 2,
|
||||
title:lan.files.up_title,
|
||||
area: ['500px','500px'],
|
||||
area: ['500px','500px'],
|
||||
shadeClose:false,
|
||||
content:'<div class="fileUploadDiv"><input type="hidden" id="input-val" value="'+path+'" />\
|
||||
<input type="file" id="file_input" multiple="true" autocomplete="off" />\
|
||||
@@ -1497,9 +1498,9 @@ function SetChmod(action,fileName){
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var toExec = fileName == lan.files.all?'Batch(3,1)':'SetChmod(1,\''+fileName+'\')';
|
||||
|
||||
|
||||
$.post('/files?action=GetFileAccess','filename='+encodeURIComponent(fileName),function(rdata){
|
||||
var layers = layer.open({
|
||||
type:1,
|
||||
@@ -1552,7 +1553,7 @@ function SetChmod(action,fileName){
|
||||
$("#access").keyup(function(){
|
||||
onAccess();
|
||||
});
|
||||
|
||||
|
||||
$("input[type=checkbox]").change(function(){
|
||||
var idName = ['owner','group','public'];
|
||||
var onacc = '';
|
||||
@@ -1564,15 +1565,15 @@ function SetChmod(action,fileName){
|
||||
onacc += access;
|
||||
}
|
||||
$("#access").val(onacc);
|
||||
|
||||
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
function onAccess(){
|
||||
var access = $("#access").val();
|
||||
var idName = ['owner','group','public'];
|
||||
var idName = ['owner','group','public'];
|
||||
for(var n=0;n<idName.length;n++){
|
||||
$("#"+idName[n]+"_x").prop('checked',false);
|
||||
$("#"+idName[n]+"_w").prop('checked',false);
|
||||
@@ -1612,15 +1613,16 @@ function onAccess(){
|
||||
}
|
||||
}
|
||||
}
|
||||
function RClick(type, path, name, file_store){
|
||||
var displayZip = isZip(type);
|
||||
var options = {items:[
|
||||
{text: lan.files.file_menu_copy, onclick: function() {CopyFile(path)}},
|
||||
{text: lan.files.file_menu_mv, onclick: function() {CutFile(path)}},
|
||||
{text: lan.files.file_menu_rename, onclick: function() {ReName(0,name)}},
|
||||
{text: lan.files.file_menu_auth, onclick: function() {SetChmod(0,path)}},
|
||||
{text: lan.files.file_menu_zip, onclick: function() {Zip(path)}}
|
||||
|
||||
function RClick(type, path, name, file_store) {
|
||||
var displayZip = isZip(type);
|
||||
var options = {
|
||||
items: [
|
||||
{ text: lan.files.file_menu_copy, onclick: function () { CopyFile(path) } },
|
||||
{ text: lan.files.file_menu_mv, onclick: function () { CutFile(path) } },
|
||||
{ text: lan.files.file_menu_rename, onclick: function () { ReName(0, name) } },
|
||||
{ text: lan.files.file_menu_auth, onclick: function () { SetChmod(0, path) } },
|
||||
{ text: lan.files.file_menu_zip, onclick: function () { Zip(path) } }
|
||||
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ var index = {
|
||||
crs += 'CPU-' + i + ": " + d[2][i] + '%' + (n1 % 2 == 0?'</br>':' | ');
|
||||
|
||||
}
|
||||
layer.tips(d[3] +"</br>"+ crs, _this.find('.cicle'), { time: 0, tips: [1, '#999'] });
|
||||
layer.tips(d[3] + "</br>" + d[5] + " CPU, " + d[4] + " Core, " + d[4]+" Thread</br>"+ crs, _this.find('.cicle'), { time: 0, tips: [1, '#999'] });
|
||||
}, function () {
|
||||
layer.closeAll('tips');
|
||||
});
|
||||
@@ -230,7 +230,7 @@ var index = {
|
||||
var load_arr = [{ title: lan.index.run_block, val: 100, color: '#dd2f00' }, { title: lan.index.run_slow, val: 90, color: '#ff9900' }, { title: lan.index.run_normal, val: 70, color: '#20a53a' }, { title: lan.index.run_fluent, val: 30, color: '#20a53a' }];
|
||||
var _cpubox = $('.cpubox'), _membox = $('.membox'), _loadbox = $('.loadbox')
|
||||
|
||||
index.set_val(_cpubox, { usage: net.cpu[0], title: net.cpu[1] + ' ' + lan.index.cpu_core, items: pub_arr })
|
||||
index.set_val(_cpubox, { usage: net.cpu[0], title: net.cpu[1]+' '+lan.index.cpu_core, items: pub_arr })
|
||||
index.set_val(_membox, { usage: (net.mem.memRealUsed * 100 / net.mem.memTotal).toFixed(1), items: pub_arr, title: net.mem.memRealUsed + '/' + net.mem.memTotal + '(MB)' })
|
||||
bt.set_cookie('memSize', net.mem.memTotal)
|
||||
|
||||
@@ -262,6 +262,11 @@ var index = {
|
||||
$("#messageError").show();
|
||||
$("#messageError").append('<p><span class="glyphicon glyphicon-alert" style="color: #ff4040; margin-right: 10px;"></span>' + lan.index.user_warning + '<span class="c7 mr5" title="'+lan.index.safe_problem_cant_ignore+'" style="cursor:no-drop"> ['+lan.index.cant_ignore+']</span><a class="btlink" href="javascript:setUserName();"> ['+lan.index.edit_now+']</a></p>')
|
||||
}
|
||||
|
||||
if (info.isport === true) {
|
||||
$("#messageError").show();
|
||||
$("#messageError").append('<p><span class="glyphicon glyphicon-alert" style="color: #ff4040; margin-right: 10px;"></span>'+lan.index.panel_port_tips+'<span class="c7 mr5" title="'+lan.index.panel_port_tip1+'" style="cursor:no-drop"> ['+lan.index.panel_port_tip2+']</span><a class="btlink" href="/config"> ['+lan.index.panel_port_tip3+']</a></p>')
|
||||
}
|
||||
var _system = info.system;
|
||||
$("#info").html(_system);
|
||||
$("#running").html(info.time);
|
||||
@@ -302,6 +307,11 @@ var index = {
|
||||
arr.push({ title: lan.index.already_use, value: item.inodes[1] })
|
||||
arr.push({ title: lan.index.available, value: item.inodes[2] })
|
||||
arr.push({ title: lan.index.inode_percent, value: item.inodes[3] })
|
||||
arr.push({ title: '<b>Capacity information</b>', value: '' })
|
||||
arr.push({ title: 'Capacity', value: item.size[0] })
|
||||
arr.push({ title: 'Used', value: item.size[1] })
|
||||
arr.push({ title: 'Available', value: item.size[2] })
|
||||
arr.push({ title: 'Usage rate', value: item.size[3] })
|
||||
obj.masks = arr;
|
||||
data.items.push(obj)
|
||||
}
|
||||
@@ -446,7 +456,9 @@ var index = {
|
||||
})
|
||||
},
|
||||
check_update: function () {
|
||||
var _load = bt.load('Getting updates, please wait...');
|
||||
bt.system.check_update(function (rdata) {
|
||||
_load.close();
|
||||
if (rdata.status === false) {
|
||||
if (!rdata.msg.beta) {
|
||||
bt.msg(rdata);
|
||||
|
||||
+172
-222
@@ -339,11 +339,11 @@ var aceEditor = {
|
||||
break;
|
||||
// 搜索
|
||||
case 'searchs':
|
||||
|
||||
editor_item.ace.execCommand('find');
|
||||
break;
|
||||
// 替换
|
||||
case 'replaces':
|
||||
|
||||
editor_item.ace.execCommand('replace');
|
||||
break;
|
||||
// 字体
|
||||
case 'fontSize':
|
||||
@@ -2574,254 +2574,204 @@ function scroll_handle(e){
|
||||
var scrollTop = this.scrollTop;
|
||||
$(this).find("thead").css({"transform":"translateY("+scrollTop+"px)","position":"relative","z-index":"1"});
|
||||
}
|
||||
var clipboard, interval, socket, gterm, ssh_login,term_box;
|
||||
var clipboard, interval, socket, term, ssh_login,term_box;
|
||||
|
||||
var pdata_socket = {
|
||||
x_http_token: document.getElementById("request_token_head").getAttribute('token')
|
||||
}
|
||||
|
||||
function ssh_login_def() {
|
||||
pdata_socket['data'] = {};
|
||||
pdata_socket['data']['ssh_user'] = $("input[name='ssh_user']").val();
|
||||
pdata_socket['data']['ssh_passwd'] = $("input[name='ssh_passwd']").val();
|
||||
if (!pdata_socket.data.ssh_user || !pdata_socket.data.ssh_passwd) {
|
||||
layer.msg('The SSH username and password cannot be empty!');
|
||||
return;
|
||||
}
|
||||
|
||||
layer.close(ssh_login);
|
||||
socket.emit('webssh', pdata_socket);
|
||||
gterm.focus();
|
||||
}
|
||||
|
||||
function web_shell() {
|
||||
var termCols = 100;
|
||||
var termRows = 29;
|
||||
var sendTotal = 0;
|
||||
if(!socket)socket = io.connect();
|
||||
var term = new Terminal({ cols: termCols, rows: termRows, screenKeys: true, useStyle: true});
|
||||
term.open();
|
||||
gterm = term
|
||||
var termRows = 34;
|
||||
if (!socket) connect_io()
|
||||
term = new Terminal({ cols: termCols, rows: termRows, screenKeys: true, useStyle: true });
|
||||
term.setOption('cursorBlink', true);
|
||||
|
||||
socket.on('server_response', function (data) {
|
||||
if (data.data == "Failed to connect to SSH service!\r\n") {
|
||||
if ($("input[name='ssh_user']").attr('autocomplete')) return;
|
||||
var s_body = '<div class="bt-form bt-form pd20 pb70"><div class="line " style="display:none;">\
|
||||
<span class="tname">id</span><div class="info-r "><input name="id" class="bt-input-text mr5" type="text" style="width:330px" value=""></div></div>\
|
||||
<div class="line "><span class="tname">Username</span><div class="info-r "><input name="ssh_user" class="bt-input-text mr5" type="text" style="width:330px" value="" readonly="readonly" autocomplete="off"></div></div>\
|
||||
<div class="line "><span class="tname">Password</span><div class="info-r "><input name="ssh_passwd" class="bt-input-text mr5" type="password" style="width:330px" value="" readonly="readonly" autocomplete="off"></div></div>\
|
||||
<div class="bt-form-submit-btn"><button type="button" class="btn btn-sm btn-danger" onclick="layer.closeAll()">Close</button><button type="button" class="btn btn-sm btn-success ssh-login" onclick="ssh_login_def()">Login SSH</button></div></div>';
|
||||
ssh_login = layer.open({
|
||||
type: 1,
|
||||
title: 'Please enter the SSH login account and password',
|
||||
area: "500px",
|
||||
closeBtn: 0,
|
||||
shadeClose: false,
|
||||
content: s_body
|
||||
});
|
||||
term_box = layer.open({
|
||||
type: 1,
|
||||
title: 'aaPanel terminal',
|
||||
area: ['920px', '630px'],
|
||||
closeBtn: 2,
|
||||
shadeClose: false,
|
||||
content: '<a class="btlink" onclick="show_ssh_login(1)" style="position: fixed;margin-left: 140px;margin-top: -30px;">[Set]</a><div class="term-box" style="background-color:#000"><div id="term"></div></div>',
|
||||
cancel: function () {
|
||||
term.destroy();
|
||||
},
|
||||
success: function () {
|
||||
term.open(document.getElementById('term'));
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(function removeReadonly() {
|
||||
$("input[name='ssh_user']").removeAttr('readonly');
|
||||
$("input[name='ssh_passwd']").removeAttr('readonly');
|
||||
$("input[name='ssh_user']").focus();
|
||||
term.on('data', function (data) {
|
||||
socket.emit('webssh', data);
|
||||
});
|
||||
|
||||
$("input[name='ssh_passwd']").keydown(function (e) {
|
||||
if (e.keyCode == 13) {
|
||||
$('.ssh-login').click();
|
||||
}
|
||||
});
|
||||
$(".shell_btn_close").click(function(){
|
||||
layer.close(term_box);
|
||||
term.destroy();
|
||||
})
|
||||
|
||||
}, 500);
|
||||
setTimeout(function () {
|
||||
socket.emit('webssh', "\u0015");
|
||||
socket.emit('webssh', "new_bt_terminal");
|
||||
//socket.emit('webssh', "new_bt_terminal");
|
||||
term.focus();
|
||||
}, 100)
|
||||
}
|
||||
|
||||
|
||||
function connect_io() {
|
||||
socket = io.connect();
|
||||
socket.on('ssh_data', function (data) {
|
||||
if (data === "\rServer connection failed!\r" || data === "\rWrong user name or password!\r") {
|
||||
show_ssh_login(0);
|
||||
return;
|
||||
}
|
||||
|
||||
term.write(data.data);
|
||||
term.write(data);
|
||||
|
||||
if (data.data == '\r\n'+lan.public.logout+'\r\n' || data.data == lan.public.logout+'\r\n' || data.data == '\r\nlogout\r\n' || data.data == 'logout\r\n') {
|
||||
if (data == '\r\n登出\r\n' || data == '登出\r\n' || data == '\r\nlogout\r\n' || data == 'logout\r\n') {
|
||||
setTimeout(function () {
|
||||
layer.close(term_box);
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (socket) {
|
||||
socket.emit('connect_event', '');
|
||||
interval = setInterval(function () {
|
||||
socket.emit('connect_event', '');
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
term.on('data', function (data) {
|
||||
pdata_socket['data'] = data;
|
||||
socket.emit('webssh', pdata_socket);
|
||||
});
|
||||
|
||||
|
||||
term_box = layer.open({
|
||||
function show_ssh_login(is_config) {
|
||||
if ($("input[name='ssh_user']").attr('autocomplete')) return;
|
||||
var s_body = '<div class="bt-form bt-form pd20 pb70">\
|
||||
<style>.ssh_check_s1{ display: inline-block;\
|
||||
height: 38px;\
|
||||
background-color: #fff;\
|
||||
color: #050505;\
|
||||
white-space: nowrap;\
|
||||
text-align: center;\
|
||||
cursor: pointer;\
|
||||
border-radius: 0;\
|
||||
margin-left: 0px !important;\
|
||||
position: relative;\
|
||||
top: 2px;\
|
||||
line-height: 34px;\
|
||||
font-size: 13px;\
|
||||
border-color: #e6e6e6;\
|
||||
padding: 0 14px;\
|
||||
border: 1px solid #e0dfdf;}\
|
||||
.ssh_check_s2{margin-left: 0 !important;\
|
||||
position: relative;\
|
||||
top: 2px;\
|
||||
border-color: #e6e6e6;\
|
||||
display: inline - block;\
|
||||
height: 38px;\
|
||||
line-height: 38px;\
|
||||
padding: 0 18px;\
|
||||
background-color: #20a53a;\
|
||||
color: #fff;\
|
||||
white-space: nowrap;\
|
||||
text-align: center;\
|
||||
font-size: 14px;\
|
||||
border: none;\
|
||||
border-radius: 2px;\
|
||||
cursor: pointer;} </style >\
|
||||
<div class="line " style="margin-left: -40px;"><span class="tname">IP</span><div class="info-r "><input name="ssh_host" class="bt-input-text mr5" type="text" style="width:330px" value="127.0.0.1" autocomplete="off"></div></div>\
|
||||
<div class="line " style="margin-left: -40px;"><span class="tname">Port</span><div class="info-r "><input name="ssh_port" class="bt-input-text mr5" type="text" style="width:330px" value="22" autocomplete="off"></div></div>\
|
||||
<div class="line " style="margin-left: -40px;"><span class="tname">Username</span><div class="info-r "><input name="ssh_user" class="bt-input-text mr5" type="text" style="width:330px" value="root" readonly="readonly" autocomplete="off"></div></div>\
|
||||
<div class="line " style="margin-left: -40px;"><span class="tname">Method</span><div class="info-r "><button class="ssh_check_s2" id="pass_check" onclick="pass_check()">Password</button><button id="rsa_check" class="ssh_check_s1" onclick="rsa_check()">Key</button></div></div>\
|
||||
<div class="line ssh_passwd" style="margin-left: -40px;"><span class="tname">Password</span><div class="info-r "><input name="ssh_passwd" readonly="readonly" class="bt-input-text mr5" type="password" style="width:330px" value="" autocomplete="off"></div></div>\
|
||||
<div class="line ssh_pkey" style="display:none;"><span class="tname">Key</span><div class="info-r "><textarea name="ssh_pkey" class="bt-input-text mr5" style="width:330px;height:80px;" ></textarea></div></div>\
|
||||
<div class="line " style="margin-left: -40px;"><span class="tname"></span><div class="info-r "><input style="margin-top: 1px;width: 16px;" name="ssh_is_save" id="ssh_is_save" class="bt-input-text mr5" type="checkbox" ><label style="position: absolute;margin-left: 5px;" for="ssh_is_save">Remember password, the next time you use the aaPanel terminal will automatically log in</label></div></div>\
|
||||
<p style="color: red;margin-top: 10px;text-align: center;margin-left: -62px;">Only support login to this server</p>\
|
||||
<div class="bt-form-submit-btn"><button type="button" class="btn btn-sm btn-danger" onclick="'+ (is_config ? 'layer.close(ssh_login)' :'layer.closeAll()')+'">Close</button><button type="button" class="btn btn-sm btn-success ssh-login" onclick="send_ssh_info('+is_config+')">'+(is_config?'Confirm':'Login SSH')+'</button></div></div>';
|
||||
ssh_login = layer.open({
|
||||
type: 1,
|
||||
title: lan.public.bt_terminal,
|
||||
area: ['920px','640px'],
|
||||
closeBtn: 2,
|
||||
title: is_config?'Please fill in the SSH connection configuration':'Please enter the SSH login account and password',
|
||||
area: "500px",
|
||||
closeBtn: 0,
|
||||
shadeClose: false,
|
||||
content: '<div class="term-box"><div id="term"></div></div>\
|
||||
<div class="shell-text-input">\
|
||||
<textarea type="text" class="bt-input-text-shell" placeholder="'+lan.public.paste_comm_this+'" value="" name="ssh_copy" />\
|
||||
<div class="shell-btn-group">\
|
||||
<button class="shellbutton btn btn-success btn-sm pull-right shell_btn_1">'+lan.public.send+'(Ctrl+Enter)</button>\
|
||||
<button class="shellbutton btn btn-default btn-sm pull-right shell_btn_close">'+lan.public.turnoff+'</button>\
|
||||
</div>\
|
||||
</div>',
|
||||
cancel: function () {
|
||||
term.destroy();
|
||||
clearInterval(interval)
|
||||
}
|
||||
content: s_body
|
||||
});
|
||||
$(".shell_btn_close").click(function(){
|
||||
layer.close(term_box);
|
||||
term.destroy();
|
||||
clearInterval(interval)
|
||||
})
|
||||
|
||||
setTimeout(function () {
|
||||
$('.terminal').detach().appendTo('#term');
|
||||
$("#term").show();
|
||||
pdata_socket['data'] = "\u0015"
|
||||
socket.emit('webssh', pdata_socket);
|
||||
pdata_socket['data'] = "\n"
|
||||
socket.emit('webssh', pdata_socket);
|
||||
|
||||
setTimeout(function removeReadonly() {
|
||||
$("input[name='ssh_user']").removeAttr('readonly');
|
||||
$("input[name='ssh_passwd']").removeAttr('readonly');
|
||||
$("input[name='ssh_passwd']").focus();
|
||||
|
||||
$("input[name='ssh_passwd']").keydown(function (e) {
|
||||
if (e.keyCode == 13) {
|
||||
$('.ssh-login').click();
|
||||
}
|
||||
});
|
||||
|
||||
}, 500);
|
||||
}
|
||||
|
||||
|
||||
function pass_check() {
|
||||
$("#pass_check").attr("class", "ssh_check_s2");
|
||||
$("#rsa_check").attr("class", "ssh_check_s1");
|
||||
$(".ssh_pkey").hide();
|
||||
$(".ssh_passwd").show();
|
||||
}
|
||||
|
||||
function rsa_check() {
|
||||
$("#pass_check").attr("class", "ssh_check_s1");
|
||||
$("#rsa_check").attr("class", "ssh_check_s2");
|
||||
$(".ssh_pkey").show();
|
||||
$(".ssh_passwd").hide();
|
||||
}
|
||||
|
||||
|
||||
function send_ssh_info() {
|
||||
pdata = {
|
||||
host: $("input[name='ssh_host']").val(),
|
||||
port: Number($("input[name='ssh_port']").val()),
|
||||
password: $("input[name='ssh_passwd']").val(),
|
||||
username: $("input[name='ssh_user']").val(),
|
||||
pkey: $("textarea[name='ssh_pkey']").val()
|
||||
}
|
||||
if (pdata['host'] !== '127.0.0.1' && pdata['host'] !== 'localhost') {
|
||||
layer.msg("Connection address can only be [ 127.0.0.1 or localhost ]");
|
||||
$("input[name='ssh_host']").focus();
|
||||
return;
|
||||
}
|
||||
if (pdata['port'] < 1 || pdata['port'] > 65535) {
|
||||
layer.msg("Port range is incorrect [1-65535]");
|
||||
$("input[name='ssh_port']").focus();
|
||||
return;
|
||||
}
|
||||
if (!pdata['username']) {
|
||||
layer.msg("Username can not be empty!");
|
||||
$("input[name='ssh_user']").focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if ($("#rsa_check").attr("class") === "ssh_check_s2") {
|
||||
pdata['c_type'] = 'True'
|
||||
if (!pdata['pkey']) {
|
||||
layer.msg("Private key cannot be empty!");
|
||||
$("input[name='ssh_pkey']").focus();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!pdata['password']) {
|
||||
layer.msg("Password can not be blank!");
|
||||
$("input[name='ssh_passwd']").focus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ($("#ssh_is_save").prop("checked")) {
|
||||
pdata['is_save'] = '1';
|
||||
}
|
||||
|
||||
var loadT = layer.msg('Trying to log in to SSH...', { icon: 16, time: 0, shade: 0.3 });
|
||||
$.post("/term_open", { data: JSON.stringify(pdata) }, function () {
|
||||
layer.close(loadT)
|
||||
socket.emit('webssh', pdata);
|
||||
layer.close(ssh_login)
|
||||
term.focus();
|
||||
|
||||
// 鼠标右键事件
|
||||
var can = $("#term");
|
||||
can.contextmenu(function (e) {
|
||||
var winWidth = can.width();
|
||||
var winHeight = can.height();
|
||||
var mouseX = e.pageX;
|
||||
var mouseY = e.pageY;
|
||||
var menuWidth = $(".contextmenu").width();
|
||||
var menuHeight = $(".contextmenu").height();
|
||||
var minEdgeMargin = 10;
|
||||
if (mouseX + menuWidth + minEdgeMargin >= winWidth &&
|
||||
mouseY + menuHeight + minEdgeMargin >= winHeight) {
|
||||
menuLeft = mouseX - menuWidth - minEdgeMargin + "px";
|
||||
menuTop = mouseY - menuHeight - minEdgeMargin + "px";
|
||||
}
|
||||
else if (mouseX + menuWidth + minEdgeMargin >= winWidth) {
|
||||
menuLeft = mouseX - menuWidth - minEdgeMargin + "px";
|
||||
menuTop = mouseY + minEdgeMargin + "px";
|
||||
}
|
||||
else if (mouseY + menuHeight + minEdgeMargin >= winHeight) {
|
||||
menuLeft = mouseX + minEdgeMargin + "px";
|
||||
menuTop = mouseY - menuHeight - minEdgeMargin + "px";
|
||||
}
|
||||
else {
|
||||
menuLeft = mouseX + minEdgeMargin + "px";
|
||||
menuTop = mouseY + minEdgeMargin + "px";
|
||||
};
|
||||
|
||||
var selectText = term.getSelection()
|
||||
var style_str = '';
|
||||
var paste_str = '';
|
||||
if (!selectText) {
|
||||
if (!getCookie('shell_copy_body')) {
|
||||
paste_str = 'style="color: #bbb;" disable';
|
||||
}
|
||||
style_str = 'style="color: #bbb;" disable';
|
||||
} else {
|
||||
setCookie('ssh_selection', selectText);
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
var menudiv = '<ul class="contextmenu">\
|
||||
<li>\
|
||||
<a class="shell_copy_btn menu_ssh" data-clipboard-text="'+ selectText + '" ' + style_str + '>'+lan.public.cp_to_shear_plate+'</a>\
|
||||
</li>\
|
||||
<li>\
|
||||
<a onclick="shell_paste_text()" '+ paste_str+'>'+lan.public.paste_choose+'</a>\
|
||||
</li>\
|
||||
<li>\
|
||||
<a onclick="shell_translate_text()" ' + style_str + '>'+lan.public.translate+'</a>\
|
||||
</li>\
|
||||
<li>\
|
||||
<a onclick="shell_to_baidu()" ' + style_str + '>'+lan.public.search+'</a>\
|
||||
</li>\
|
||||
</ul>';
|
||||
$("body").append(menudiv);
|
||||
$(".contextmenu").css({
|
||||
"left": menuLeft,
|
||||
"top": menuTop
|
||||
});
|
||||
return false;
|
||||
});
|
||||
can.click(function () {
|
||||
remove_ssh_menu();
|
||||
});
|
||||
|
||||
clipboard = new ClipboardJS('.shell_copy_btn');
|
||||
clipboard.on('success', function (e) {
|
||||
layer.msg(lan.public.cp_success);
|
||||
setCookie('shell_copy_body', e.text)
|
||||
remove_ssh_menu();
|
||||
term.focus();
|
||||
});
|
||||
|
||||
clipboard.on('error', function (e) {
|
||||
layer.msg(lan.public.cp_fail);
|
||||
setCookie('shell_copy_body', e.text)
|
||||
remove_ssh_menu();
|
||||
term.focus();
|
||||
});
|
||||
|
||||
$(".shellbutton").click(function () {
|
||||
var tobj = $("textarea[name='ssh_copy']");
|
||||
var ptext = tobj.val();
|
||||
tobj.val('');
|
||||
if ($(this).text().indexOf('Alt') != -1) {
|
||||
ptext +="\n";
|
||||
}
|
||||
pdata_socket['data'] = ptext;
|
||||
socket.emit('webssh', pdata_socket);
|
||||
term.focus();
|
||||
})
|
||||
$("textarea[name='ssh_copy']").keydown(function (e) {
|
||||
if (e.ctrlKey && e.keyCode == 13) {
|
||||
$(".shell_btn_1").click();
|
||||
} else if (e.altKey && e.keyCode == 13) {
|
||||
$(".shell_btn_1").click();
|
||||
}
|
||||
});
|
||||
|
||||
}, 100)
|
||||
}
|
||||
|
||||
function shell_translate_text() {
|
||||
remove_ssh_menu();
|
||||
var selectText = getCookie('ssh_selection');
|
||||
var loadT = layer.msg(lan.public.translate_now, { icon: 16, time: 1000 * 60, });
|
||||
$.get('https://www.bt.cn/api/index/fanyi', { query: selectText }, function (rdata) {
|
||||
layer.close(loadT);
|
||||
layer.msg(lan.public.original + rdata.src + '<br>'+ lan.public.translation + rdata.dst, { time: 1000 * 10, shadeClose: true, shade: 0.01 });
|
||||
}, 'JSONP');
|
||||
gterm.focus();
|
||||
}
|
||||
|
||||
function shell_to_baidu() {
|
||||
var selectText = getCookie('ssh_selection');
|
||||
remove_ssh_menu();
|
||||
window.open('https://www.baidu.com/s?wd=' + selectText)
|
||||
gterm.focus();
|
||||
}
|
||||
|
||||
|
||||
function shell_paste_text() {
|
||||
pdata_socket['data'] = getCookie('ssh_selection')
|
||||
socket.emit('webssh', pdata_socket);
|
||||
remove_ssh_menu();
|
||||
gterm.focus();
|
||||
}
|
||||
|
||||
function remove_ssh_menu() {
|
||||
$(".contextmenu").remove();
|
||||
}
|
||||
|
||||
|
||||
@@ -463,13 +463,15 @@ var bt =
|
||||
|
||||
//会话失效时自动跳转到登录页面
|
||||
if (typeof (rdata) == 'string') {
|
||||
if (rdata.indexOf('/static/favicon.ico') != -1 && rdata.indexOf('/static/img/qrCode.png') != -1) {
|
||||
if ((rdata.indexOf('/static/favicon.ico') != -1 && rdata.indexOf('/static/img/qrCode.png') != -1) || rdata.indexOf('<!DOCTYPE html>') === 0) {
|
||||
window.location.href = "/login"
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if(callback) callback(rdata);
|
||||
}).error(function () {
|
||||
}).error(function (e, f) {
|
||||
// console.log(e,f)
|
||||
if(callback) callback('error');
|
||||
});
|
||||
}
|
||||
@@ -3975,10 +3977,11 @@ bt.soft = {
|
||||
</div>'
|
||||
});
|
||||
},
|
||||
update_soft: function (name,title, version, min_version) {
|
||||
update_soft: function (name,title, version, min_version,update_msg) {
|
||||
var _this = this;
|
||||
var msg = "<li>"+lan.public_backup.update_tips+"</li>";
|
||||
if(name == 'mysql') msg = "<ul style='color:red;'><li>"+lan.public_backup.db_update_tips+"</li><li>"+lan.public_backup.update_tips1+"</li><li>"+lan.public_backup.update_tips+"</li></ul>";
|
||||
if (update_msg) msg += '<div style=" margin-top: 10px;"><span style="font-size: 14px;font-weight: 900;">Update description: </span><hr style="margin-top: 5px; margin-bottom: 5px;" /><pre>' + update_msg.replace(/(_bt_)/g, "\n") +'</pre><hr style="margin-top: -5px; margin-bottom: -5px;" /></div>';
|
||||
bt.show_confirm(lan.public_backup.update+'[' + title + ']', lan.public_backup.update_tips2.replace('{1}',title).replace('{2}',version).replace('{3}',min_version),function(){
|
||||
var loadT = bt.load(lan.public_backup.update_tips3.replace('{1}',title).replace('{2}',version).replace('{3}',min_version));
|
||||
bt.send('install_plugin', 'plugin/install_plugin', { sName: name, version: version, upgrade: version }, function (rdata) {
|
||||
|
||||
@@ -6,6 +6,7 @@ var site = {
|
||||
if (type == '-1' || type == undefined) {
|
||||
type = $('.site_type select').val();
|
||||
}
|
||||
if (!search) search = $("#SearchValue").val();
|
||||
bt.site.get_list(page, search, type, function (rdata) {
|
||||
$('.dataTables_paginate').html(rdata.page);
|
||||
var data = rdata.data;
|
||||
@@ -1581,6 +1582,12 @@ var site = {
|
||||
var area_size = '500px';
|
||||
var err_info = "";
|
||||
|
||||
if (!new_data.msg[1].challenges[1]) {
|
||||
if (new_data.msg[1].challenges[0]) {
|
||||
new_data.msg[1].challenges[1] = new_data.msg[1].challenges[0]
|
||||
}
|
||||
}
|
||||
|
||||
if (ldata.msg[1].status === 'invalid') {
|
||||
area_size = '600px';
|
||||
var trs = $("#dns_txt_jx tbody tr");
|
||||
@@ -1617,6 +1624,11 @@ var site = {
|
||||
site.reload();
|
||||
bt.msg(ret);
|
||||
} else {
|
||||
if (!ret.msg[1].challenges[1]) {
|
||||
if (ret.msg[1].challenges[0]) {
|
||||
ret.msg[1].challenges[1] = ret.msg[1].challenges[0]
|
||||
}
|
||||
}
|
||||
var area_size = '500px';
|
||||
var err_info = "";
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
var soft = {
|
||||
is_install: false,
|
||||
get_list: function (page, type, search) {
|
||||
if (page == undefined) page = 0;
|
||||
if (type == undefined) type = 0;
|
||||
|
||||
if (page == undefined || page == 'null' || page == 'undefined') page = 0;
|
||||
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 istype = getCookie('softType');
|
||||
if (istype == 'undefined' || istype == 'null' || !istype) {
|
||||
@@ -235,7 +236,8 @@ var soft = {
|
||||
var min_version = item.versions[i]
|
||||
var ret = bt.check_version(item.version, min_version.m_version + '.' + min_version.version);
|
||||
if (ret > 0) {
|
||||
if (ret == 2) option += '<a class="btlink" onclick="bt.soft.update_soft(\'' + item.name + '\',\'' + item.title + '\',\'' + min_version.m_version + '\',\'' + min_version.version + '\')" >' + lan.soft.update + '</a> | ';
|
||||
if (!min_version.update_msg) min_version.update_msg = '';
|
||||
if (ret == 2) option += '<a class="btlink" onclick="bt.soft.update_soft(\'' + item.name + '\',\'' + item.title + '\',\'' + min_version.m_version + '\',\'' + min_version.version + '\',\'' + min_version.update_msg.replace(/\n/g,"_bt_") + '\')" >' + lan.soft.update + '</a> | ';
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -243,7 +245,8 @@ var soft = {
|
||||
else {
|
||||
var min_version = item.versions[0];
|
||||
var cloud_version = min_version.m_version + '.' + min_version.version;
|
||||
if (item.version != cloud_version) option += '<a class="btlink" onclick="bt.soft.update_soft(\'' + item.name + '\',\'' + item.title + '\',\'' + min_version.m_version + '\',\'' + min_version.version + '\')" >' + lan.soft.update + '</a> | ';
|
||||
if (!min_version.update_msg) min_version.update_msg = '';
|
||||
if (item.version != cloud_version) option += '<a class="btlink" onclick="bt.soft.update_soft(\'' + item.name + '\',\'' + item.title + '\',\'' + min_version.m_version + '\',\'' + min_version.version + '\',\'' + min_version.update_msg.replace(/\n/g, "_bt_") + '\')" >' + lan.soft.update + '</a> | ';
|
||||
}
|
||||
if (item.admin) {
|
||||
option += '<a class="btlink" onclick="bt.soft.set_lib_config(\'' + item.name + '\',\'' + item.title + '\')">' + lan.soft.setup + '</a> | ';
|
||||
@@ -288,7 +291,7 @@ var soft = {
|
||||
bt.set_cookie('load_search', search)
|
||||
if (soft.is_install) {
|
||||
setTimeout(function () {
|
||||
soft.get_list(page + 'not_load', type, search);
|
||||
soft.get_list(bt.get_cookie('load_page') + 'not_load', bt.get_cookie('load_type'), bt.get_cookie('load_search'));
|
||||
}, 3000);
|
||||
}
|
||||
})
|
||||
|
||||
@@ -170,7 +170,9 @@
|
||||
"BASICAUTH":"BasicAuth",
|
||||
"BASICAUTH_TIPS1":"Used for BasicAuth authentication configuration",
|
||||
"CONFIG":"Set",
|
||||
"BASICAUTH_TIPS2":"Add a BasicAuth-based authentication service to the panel to prevent the panel from being swept"
|
||||
"BASICAUTH_TIPS2":"Add a BasicAuth-based authentication service to the panel to prevent the panel from being swept",
|
||||
"S_PORT_TIPS":"Note: For servers with security groups, please release the new port in the security group in advance."
|
||||
|
||||
},
|
||||
|
||||
"close":{
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="ss-text pull-left mr50">
|
||||
<em title="基于Google Authenticator对用户进行登录认证"><a href="javascript:;" class="btlink open_two_verify_view">Google authentication</a></em>
|
||||
<em title="User login authentication based on Google Authenticator"><a href="javascript:;" class="btlink open_two_verify_view">Google authentication</a></em>
|
||||
<div class='ssh-item'>
|
||||
<input class='btswitch btswitch-ios' id='panel_verification' type='checkbox'/>
|
||||
<label class='btswitch-btn' for='panel_verification'></label>
|
||||
@@ -79,7 +79,7 @@
|
||||
<div class="mtb15">
|
||||
<span class="set-tit text-right" title="{{data['lan']['CT2']}}">{{data['lan']['CT2']}}</span>
|
||||
<input id="banport" name="port" class="inputtxt bt-input-text" type="number" value="{{data['panel']['port']}}" maxlength="5">
|
||||
<span class="set-info c7">{{data['lan']['CY2']}}</span>
|
||||
<span class="set-info c7">{{data['lan']['CY2']}}, <a style="color:red;">{{data['lan']['S_PORT_TIPS']}}</a></span>
|
||||
</div>
|
||||
<div class="mtb15">
|
||||
<span class="set-tit text-right" title="{{data['lan']['panel_performance']}}">{{data['lan']['concurrent_thread']}}</span>
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
|
||||
{% if not data['isSetup'] %}
|
||||
layer.msg('{{data["lan"]["JS1"]}}<a href="/soft#i" style="color:#20a53a;float: right;">{{data["lan"]["JS2"]}}</a>',{icon:7,shade: [0.3, '#000'],time:0});
|
||||
$(".layui-layer-shade").css("margin-left", "200px");
|
||||
$(".layui-layer-shade").css("margin-left", "180px");
|
||||
{% else %}
|
||||
database.get_list();
|
||||
{% endif %}
|
||||
|
||||
@@ -64,8 +64,8 @@
|
||||
<span class="saveFile"><i class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></i>Save</span>
|
||||
<span class="saveFileAll"><i class="glyphicon glyphicon-duplicate" aria-hidden="true"></i>Save All</span>
|
||||
<span class="refreshs"><i class="glyphicon glyphicon-refresh" aria-hidden="true"></i>Refresh</span>
|
||||
<!-- <span class="searchs"><i class="fa fa-search" aria-hidden="true"></i>搜索</span>
|
||||
<span class="replaces"><i class="fa fa-random" aria-hidden="true"></i>替换</span> -->
|
||||
<span class="searchs"><i class="fa fa-search" aria-hidden="true"></i>Search</span>
|
||||
<span class="replaces"><i class="fa fa-random" aria-hidden="true"></i>Replace</span>
|
||||
<span class="fontSize"><i class="glyphicon glyphicon-text-width" aria-hidden="true"></i>Font</span>
|
||||
<span class="themes"><i class="glyphicon glyphicon-magnet" aria-hidden="true"></i>Theme</span>
|
||||
<span class="helps"><i class="glyphicon glyphicon-question-sign" aria-hidden="true"></i>Help</span>
|
||||
|
||||
@@ -229,7 +229,8 @@
|
||||
})
|
||||
},
|
||||
get_list:function(page,search){
|
||||
if(page==undefined) page=1;
|
||||
if (page == undefined) page = 1;
|
||||
if (!search) search = $("#SearchValue").val();
|
||||
bt.firewall.get_list(page, search, function (rdata) {
|
||||
$('.firewallBody').html(rdata.page);
|
||||
var ports_ps = {"80": lan.firewall.site_default_port, "3306": lan.firewall.mysql_default_port, "888": lan.firewall.phpmmyadmin_default_port, "22": lan.firewall.ssh_default_port, "20": lan.firewall.ftp1_default_port, "21": lan.firewall.ftp_default_port, "39000-40000": lan.firewall.ftp2_default_port, "30000-40000": lan.firewall.ftp2_default_port,"11211":lan.firewall.mem_default_port,"873":lan.firewall.rsync_default_port,"8888":lan.firewall.bt_default_port}
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
|
||||
var ftp = {
|
||||
get_list:function(page,search){
|
||||
if(page==undefined) page=1;
|
||||
if (page == undefined) page = 1;
|
||||
if (!search) search = $("#SearchValue").val();
|
||||
bt.ftp.get_list(page,search,function(rdata){
|
||||
$('.dataTables_paginate').html(rdata.page);
|
||||
var _tab = bt.render({
|
||||
@@ -165,7 +166,7 @@
|
||||
bt.set_cookie('sites_path',"{{session['config']['sites_path']}}");
|
||||
{% if not data['isSetup'] %}
|
||||
layer.msg('{{data["lan"]["JS1"]}}<a href="/soft" style="color:#20a53a; float: right;">{{data["lan"]["JS2"]}}</a>',{icon:7,time:0,shade: [0.3, '#000']});
|
||||
$(".layui-layer-shade").css("margin-left", "200px");
|
||||
$(".layui-layer-shade").css("margin-left", "180px");
|
||||
{% else %}
|
||||
ftp.get_list();
|
||||
{% endif %}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<span style="margin-right:10px"><a class="btlink" href="javascript:index.re_server();">{{data['lan']['RESTART']}}</a></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="container-fluid" style="padding-bottom: 66px;">
|
||||
<div class="container-fluid" style="padding-bottom: 66px;padding-left: 0px;">
|
||||
<div class="danger-tips">
|
||||
<div class="important-title" id="messageError" style="display: none; margin-top:15px"></div>
|
||||
</div>
|
||||
@@ -76,7 +76,7 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="conter-box system-info bgw clearfix mtb15">
|
||||
<div class="system-info bgw clearfix mtb15">
|
||||
<div class="title c6 f16 plr15">
|
||||
{{data['lan']['Overview']}}
|
||||
</div>
|
||||
@@ -99,7 +99,7 @@
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-12 col-md-6 pull-left pd0">
|
||||
<div class="pr8">
|
||||
<div class="bgw conter-box">
|
||||
<div class="bgw">
|
||||
<div class="title c6 f16 plr15">{{data['lan']['P4']}}</div>
|
||||
<div class="setting-con" style="padding:0; height:442px; margin-right: -4px; overflow: hidden;">
|
||||
<div class="container-fluid soft-man">
|
||||
@@ -112,7 +112,7 @@
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-12 col-md-6 pull-left pd0">
|
||||
<div class="pl7">
|
||||
<div class="bgw conter-box" style="height:491px">
|
||||
<div class="bgw" style="height:491px">
|
||||
<div class="title c6 f16 plr15">{{data['lan']['FLOW']}}</div>
|
||||
<div class="bw-info">
|
||||
<div class="col-sm-6 col-md-3"><p class="c9"><span class="ico-up"></span>{{data['lan']['UPLOAD']}}</p><a id="upSpeed">{{data['lan']['S2']}}</a></div>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<title>{{g.title}}</title>
|
||||
<link rel="shortcut icon" href="/static/favicon.ico" type="image/x-icon" />
|
||||
<link href="/static/bootstrap-3.3.5/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/static/css/site.css?date={{g['version']}}" rel="stylesheet">
|
||||
<link href="/static/css/site.css?f={{g['version']}}" rel="stylesheet">
|
||||
<link href="/static/codemirror/lib/codemirror.css" rel="stylesheet">
|
||||
<!--[if lte IE 9]>
|
||||
<script src="/static/js/requestAnimationFrame.js"></script>
|
||||
@@ -35,29 +35,18 @@
|
||||
<div class="bt-warp bge6">
|
||||
<div class="top-tips">{{session['top_tips']}}</div>
|
||||
<a style="display:none;" id="request_token_head" token="{{session['request_token_head']}}"></a>
|
||||
<div id="container" class="container-fluid {% if 'tmp_login' in session %}group-control{% endif %}">
|
||||
<div class="sidebar-scroll{% if 'tmp_login' in session %}-panel{% endif %}">
|
||||
<div id="container" class="container-fluid">
|
||||
<div class="sidebar-scroll">
|
||||
<div class="sidebar-auto">
|
||||
<div id="task" class="task cw" onclick="messagebox()"></div>
|
||||
<h3 class="mypcip"><span class="f14 cw">{{session['address']}}</span></h3>
|
||||
<ul class="menu">
|
||||
{% for menu in session['menus'] %}
|
||||
{% if menu['class'] == 'menu_exit' %}
|
||||
{% if not 'tmp_login' in session %}
|
||||
{% if menu['href'] == g.uri %}
|
||||
<li id="{{menu['id']}}" class="current"> <a class="{{menu['class']}}" href="{{menu['href']}}">{{menu['title']}}</a></li>
|
||||
{% else %}
|
||||
<li id="{{menu['id']}}"> <a class="{{menu['class']}}" href="{{menu['href']}}">{{menu['title']}}</a></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if menu['href'] == g.uri %}
|
||||
<li id="{{menu['id']}}" class="current"> <a class="{{menu['class']}}" href="{{menu['href']}}">{{menu['title']}}</a></li>
|
||||
{% else %}
|
||||
<li id="{{menu['id']}}"> <a class="{{menu['class']}}" href="{{menu['href']}}">{{menu['title']}}</a></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if menu['href'] == g.uri %}
|
||||
<li id="{{menu['id']}}" class="current"> <a class="{{menu['class']}}" href="{{menu['href']}}">{{menu['title']}}</a></li>
|
||||
{% else %}
|
||||
<li id="{{menu['id']}}"> <a class="{{menu['class']}}" href="{{menu['href']}}">{{menu['title']}}</a></li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<div id="newbtpc"></div>
|
||||
@@ -80,16 +69,16 @@
|
||||
<script src="/static/codemirror/addon/scroll/annotatescrollbar.js"></script>
|
||||
<script src="/static/js/jquery.qrcode.min.js"></script>
|
||||
<script src="/static/js/socket.io.min.js"></script>
|
||||
<link rel="stylesheet" href="/static/build/xterm.css" />
|
||||
<link rel="stylesheet" href="/static/build/addons/fullscreen/fullscreen.css" />
|
||||
<script src="/static/build/xterm.js"></script>
|
||||
<script src="/static/build/addons/attach/attach.js"></script>
|
||||
<script src="/static/build/addons/fit/fit.js"></script>
|
||||
<script src="/static/build/addons/fullscreen/fullscreen.js"></script>
|
||||
<script src="/static/build/addons/search/search.js"></script>
|
||||
<link rel="stylesheet" href="/static/build/xterm.min.css" />
|
||||
<link rel="stylesheet" href="/static/build/addons/fullscreen/fullscreen.min.css" />
|
||||
<script src="/static/build/xterm.min.js"></script>
|
||||
<script src="/static/build/addons/attach/attach.min.js"></script>
|
||||
<script src="/static/build/addons/fit/fit.min.js"></script>
|
||||
<script src="/static/build/addons/fullscreen/fullscreen.min.js"></script>
|
||||
<script src="/static/build/addons/search/search.min.js"></script>
|
||||
<script src="/static/build/addons/winptyCompat/winptyCompat.js"></script>
|
||||
<script type="text/javascript" src="/static/js/clipboard.min.js"></script>
|
||||
<script src="/static/js/public.js?version={{g['version']}}"></script>
|
||||
<script src="/static/js/public.js?v3={{g['version']}}"></script>
|
||||
<script src="/static/js/public_backup.js?version={{g['version']}}"></script>
|
||||
<script src="/static/js/bt_upload.js?version={{g['version']}}"></script>
|
||||
{% block content %}{% endblock %}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<iframe name='hid' id="hid" style="display:none"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
<div class="conter-box bgw mtb15 pd15">
|
||||
<div class="bgw mtb15 pd15">
|
||||
<div class="info-title-tips">
|
||||
<p><span class="glyphicon glyphicon-alert" style="color: #f39c12; margin-right: 10px;"></span> {{data['lan']['PS']}}</p>
|
||||
</div>
|
||||
@@ -48,7 +48,7 @@
|
||||
{% block scripts %}
|
||||
<script type="text/javascript" src="/static/laydate/laydate.js?date=20180301"></script>
|
||||
<script type="text/javascript" src="/static/js/bootstrap-select.min.js"></script>
|
||||
<script type="text/javascript" src="/static/js/site.js?version={{g['version']}}"></script>
|
||||
<script type="text/javascript" src="/static/js/site.js?version_new={{g['version']}}"></script>
|
||||
<script type="text/javascript">
|
||||
bt.set_cookie('sites_path', "{{session['config']['sites_path']}}");
|
||||
bt.set_cookie('serverType', "{{session['webserver']}}");
|
||||
|
||||
+1
-2
@@ -33,8 +33,7 @@ class ajax:
|
||||
time.sleep(0.5)
|
||||
#取Nginx负载状态
|
||||
self.CheckStatusConf()
|
||||
result = public.HttpGet('http://127.0.0.1/nginx_status')
|
||||
return result
|
||||
result = public.ExecShell('/usr/local/curl/bin/curl -Ss http://127.0.0.1/nginx_status')[0]
|
||||
tmp = result.split()
|
||||
data = {}
|
||||
if "request_time" in tmp:
|
||||
|
||||
+10
-3
@@ -27,7 +27,7 @@ class panelSetup:
|
||||
if ua:
|
||||
ua = ua.lower();
|
||||
if ua.find('spider') != -1 or ua.find('bot') != -1: return redirect('https://www.baidu.com');
|
||||
g.version = '6.2.6'
|
||||
g.version = '6.3.3'
|
||||
g.title = public.GetConfigValue('title')
|
||||
g.uri = request.path
|
||||
session['version'] = g.version;
|
||||
@@ -102,9 +102,13 @@ class panelAdmin(panelSetup):
|
||||
api_check = True
|
||||
if not 'login' in session:
|
||||
api_check = self.get_sk()
|
||||
if api_check: return api_check
|
||||
if api_check:
|
||||
session.clear()
|
||||
return api_check
|
||||
else:
|
||||
if session['login'] == False: return redirect('/login')
|
||||
if session['login'] == False:
|
||||
session.clear()
|
||||
return redirect('/login')
|
||||
if api_check:
|
||||
try:
|
||||
sess_out_path = 'data/session_timeout.pl'
|
||||
@@ -117,6 +121,7 @@ class panelAdmin(panelSetup):
|
||||
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
|
||||
@@ -126,8 +131,10 @@ class panelAdmin(panelSetup):
|
||||
token = public.readFile(filename).strip()
|
||||
if 'login_token' in session:
|
||||
if session['login_token'] != token:
|
||||
session.clear()
|
||||
return redirect('/login?dologin=True')
|
||||
except:
|
||||
session.clear()
|
||||
return redirect('/login')
|
||||
|
||||
#获取sk
|
||||
|
||||
+28
-7
@@ -7,11 +7,15 @@
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
import public,re,sys,os,nginx,apache,json,time,pyotp
|
||||
import public,re,sys,os,nginx,apache,json,time
|
||||
try:
|
||||
import pyotp
|
||||
except:
|
||||
os.system("pip install pyotp &")
|
||||
|
||||
from BTPanel import session,admin_path_checks
|
||||
from flask import request
|
||||
class config:
|
||||
|
||||
_setup_path = "/www/server/panel"
|
||||
_key_file = _setup_path+"/data/two_step_auth.txt"
|
||||
_bk_key_file = _setup_path + "/data/bk_two_step_auth.txt"
|
||||
@@ -423,7 +427,8 @@ class config:
|
||||
#设置面板SSL
|
||||
def SetPanelSSL(self,get):
|
||||
if hasattr(get,"email"):
|
||||
rep_mail = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$"
|
||||
# rep_mail = "^[a-zA-Z0-9_-\.]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$"
|
||||
rep_mail = "[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?"
|
||||
if not re.search(rep_mail,get.email):
|
||||
return public.returnMsg(False,'The E-Mail format is illegal')
|
||||
import setPanelLets
|
||||
@@ -433,7 +438,8 @@ class config:
|
||||
else:
|
||||
sslConf = '/www/server/panel/data/ssl.pl';
|
||||
if os.path.exists(sslConf):
|
||||
os.system('rm -f ' + sslConf);
|
||||
# os.system('rm -f ' + sslConf);
|
||||
os.remove(sslConf)
|
||||
return public.returnMsg(True,'PANEL_SSL_CLOSE');
|
||||
else:
|
||||
os.system('pip install cffi');
|
||||
@@ -742,7 +748,7 @@ class config:
|
||||
# s = "find /tmp -mtime +1 |grep 'sess_'|wc -l"
|
||||
# old_file_conf = int(public.ExecShell(s)[0].split("\n")[0])
|
||||
|
||||
old_file_conf = self.GetSessionCount(get)
|
||||
old_file_conf = self.GetSessionCount(get)["oldfile"]
|
||||
if old_file_conf == 0:
|
||||
return public.returnMsg(True, 'DEL_SUCCESS')
|
||||
else:
|
||||
@@ -796,7 +802,11 @@ class config:
|
||||
public.WriteFile(save_path,json.dumps(data))
|
||||
public.ExecShell("chmod 600 " + save_path)
|
||||
data = json.loads(public.ReadFile(save_path))
|
||||
data['token'] = "***********************************"
|
||||
|
||||
if 'token_crypt' in data:
|
||||
data['token'] = public.de_crypt(data['token'],data['token_crypt'])
|
||||
else:
|
||||
data['token'] = "***********************************"
|
||||
data['limit_addr'] = '\n'.join(data['limit_addr'])
|
||||
return data
|
||||
|
||||
@@ -807,6 +817,7 @@ class config:
|
||||
if get.t_type == '1':
|
||||
token = public.GetRandomString(32)
|
||||
data['token'] = public.md5(token)
|
||||
data['token_crypt'] = public.en_crypt(data['token'],token).decode('utf-8')
|
||||
public.WriteLog('SET_API', 'REGENERATE_API_TOKEN')
|
||||
elif get.t_type == '2':
|
||||
data['open'] = not data['open']
|
||||
@@ -819,6 +830,7 @@ class config:
|
||||
token = public.GetMsg("SAVE_SUCCESS")
|
||||
|
||||
public.WriteFile(save_path, json.dumps(data))
|
||||
os.chmod(save_path,0o600)
|
||||
return public.returnMsg(True, token)
|
||||
|
||||
|
||||
@@ -1119,4 +1131,13 @@ class config:
|
||||
data = public.readFile(self._core_fle_path + '/qrcode.txt')
|
||||
if data:
|
||||
return data
|
||||
return public.returnMsg(True, "No QR code data, please re-open")
|
||||
return public.returnMsg(True, "No QR code data, please re-open")
|
||||
|
||||
# 设置是否云控打开
|
||||
def set_coll_open(self,get):
|
||||
if not 'coll_show' in get: return public.returnMsg(False,'Parameter error!')
|
||||
if get.coll_show == 'True':
|
||||
session['tmp_login'] = True
|
||||
else:
|
||||
session['tmp_login'] = False
|
||||
return public.returnMsg(True,'Successful setup!')
|
||||
+22
-10
@@ -316,10 +316,7 @@ class crontab:
|
||||
#从crond删除
|
||||
def remove_for_crond(self,echo):
|
||||
u_file = '/var/spool/cron/crontabs/root'
|
||||
if not os.path.exists(u_file):
|
||||
file='/var/spool/cron/root'
|
||||
else:
|
||||
file=u_file
|
||||
file = self.get_cron_file()
|
||||
conf=public.readFile(file)
|
||||
rep = ".+" + str(echo) + ".+\n"
|
||||
conf = re.sub(rep, "", conf)
|
||||
@@ -405,11 +402,7 @@ echo "--------------------------------------------------------------------------
|
||||
#将Shell脚本写到文件
|
||||
def WriteShell(self,config):
|
||||
u_file = '/var/spool/cron/crontabs/root'
|
||||
if not os.path.exists(u_file):
|
||||
file='/var/spool/cron/root'
|
||||
else:
|
||||
file=u_file
|
||||
|
||||
file = self.get_cron_file()
|
||||
if not os.path.exists(file): public.writeFile(file,'')
|
||||
conf = public.readFile(file)
|
||||
if type(conf)==bool:return public.returnMsg(False,'Failed to read file!')
|
||||
@@ -429,6 +422,25 @@ echo "--------------------------------------------------------------------------
|
||||
os.system('chmod +x ' + execstr)
|
||||
os.system('nohup ' + execstr + ' >> ' + execstr + '.log 2>&1 &');
|
||||
return public.returnMsg(True,'CRONTAB_TASK_EXEC')
|
||||
|
||||
|
||||
#获取计划任务文件位置
|
||||
def get_cron_file(self):
|
||||
u_path = '/var/spool/cron/crontabs'
|
||||
u_file = u_path + '/root'
|
||||
c_file = '/var/spool/cron/root'
|
||||
cron_path = c_file
|
||||
if not os.path.exists(u_path):
|
||||
cron_path=c_file
|
||||
if os.path.exists('/usr/bin/yum'):
|
||||
cron_path = c_file
|
||||
elif os.path.exists("/usr/bin/apt-get"):
|
||||
cron_path = u_file
|
||||
|
||||
if cron_path == u_file:
|
||||
if not os.path.exists(u_path):
|
||||
os.makedirs(u_path,472)
|
||||
public.ExecShell("chown root:crontab {}".format(u_path))
|
||||
return cron_path
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -149,7 +149,7 @@ class data:
|
||||
where += " and type='" + get.type+"'";
|
||||
|
||||
if get.table == 'sites' and get.search:
|
||||
pid = SQL.table('domain').where('name=?',(get.search,)).getField('pid');
|
||||
pid = SQL.table('domain').where("name LIKE '%"+get.search+"%'",()).getField('pid');
|
||||
if pid: where = "id=" + str(pid);
|
||||
|
||||
if get.table == 'sites' and hasattr(get,'type'):
|
||||
|
||||
+5
-4
@@ -20,7 +20,7 @@ class database(datatool.datatools):
|
||||
try:
|
||||
data_name = get['name'].strip()
|
||||
if self.CheckRecycleBin(data_name): return public.returnMsg(False,'DATABASE_DEL_RECYCLE_BIN',(data_name,))
|
||||
if len(data_name) > 16: return public.returnMsg(False, 'DATABASE_NAME_LEN')
|
||||
if len(data_name) > 64: return public.returnMsg(False, 'DATABASE_NAME_LEN')
|
||||
reg = "^[\w\.-]+$"
|
||||
if not re.match(reg, data_name): return public.returnMsg(False,'DATABASE_NAME_ERR_T')
|
||||
if not hasattr(get,'db_user'): get.db_user = data_name;
|
||||
@@ -30,7 +30,7 @@ class database(datatool.datatools):
|
||||
if data_name in checks or len(data_name) < 1: return public.returnMsg(False,'DATABASE_NAME_ERR');
|
||||
data_pwd = get['password']
|
||||
if len(data_pwd)<1:
|
||||
data_pwd = public.md5(time.time())[0:8]
|
||||
data_pwd = public.md5(str(time.time()))[0:8]
|
||||
|
||||
sql = public.M('databases')
|
||||
if sql.where("name=? or username=?",(data_name,username)).count(): return public.returnMsg(False,'DATABASE_NAME_EXISTS')
|
||||
@@ -690,7 +690,8 @@ SetLink
|
||||
os.system('/etc/init.d/mysqld restart');
|
||||
else:
|
||||
path = self.GetMySQLInfo(get)['datadir'];
|
||||
if hasattr(get,'status'):
|
||||
if not os.path.exists(path): return public.returnMsg(False,'数据库目录不存在!')
|
||||
if hasattr(get,'status'):
|
||||
dsize = 0;
|
||||
for n in os.listdir(path):
|
||||
if len(n) < 9: continue;
|
||||
@@ -698,7 +699,7 @@ SetLink
|
||||
dsize += os.path.getsize(path + '/' + n);
|
||||
return public.returnMsg(True,dsize);
|
||||
if os.path.exists(masterslaveconf):
|
||||
return public.returnMsg(False, "MYSQL_TURNOFF_BIN_CHECK")
|
||||
return public.returnMsg(False, "Database directory does not exist")
|
||||
mycnf = mycnf.replace('log-bin=mysql-bin','#log-bin=mysql-bin')
|
||||
mycnf = mycnf.replace('binlog_format=mixed','#binlog_format=mixed')
|
||||
os.system('sync')
|
||||
|
||||
+32
-15
@@ -7,7 +7,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# +-------------------------------------------------------------------
|
||||
import sys,os,public,time,json,pwd,cgi,shutil
|
||||
import sys,os,public,time,json,pwd,cgi,shutil,re
|
||||
from BTPanel import session,request
|
||||
class files:
|
||||
run_path = None
|
||||
@@ -204,7 +204,8 @@ session.save_handler = files'''.format(path,sess_path,sess_path)
|
||||
p_stat = os.stat(s_path)
|
||||
os.chown(path,p_stat.st_uid,p_stat.st_gid)
|
||||
if os.path.isfile(path):
|
||||
os.chmod(path,0644)
|
||||
public.writeFile("/tmp/2",str(sys.version_info[0]))
|
||||
os.chmod(path, 0o644)
|
||||
else:
|
||||
os.chmod(path,p_stat.st_mode)
|
||||
|
||||
@@ -609,19 +610,27 @@ session.save_handler = files'''.format(path,sess_path,sess_path)
|
||||
rPath = '/www/Recycle_bin/'
|
||||
if sys.version_info[0] == 2: get.path = get.path.encode('utf-8');
|
||||
dFile = get.path.split('_t_')[0];
|
||||
filename = rPath + get.path
|
||||
tfile = get.path.replace('_bt_','/').split('_t_')[0];
|
||||
if not os.path.exists(filename): return public. returnMsg(True,'FILE_DEL_RECYCLE_BIN',(tfile,))
|
||||
if dFile.find('BTDB_') != -1:
|
||||
import database;
|
||||
return database.database().DeleteTo(rPath+get.path);
|
||||
if not self.CheckDir(rPath + get.path):
|
||||
return database.database().DeleteTo(filename);
|
||||
if not self.CheckDir(filename):
|
||||
return public.returnMsg(False,'FILE_DANGER');
|
||||
os.system('chattr -R -i ' + rPath + get.path)
|
||||
if os.path.isdir(rPath + get.path):
|
||||
|
||||
os.system('chattr -R -i ' + filename)
|
||||
if os.path.isdir(filename):
|
||||
import shutil
|
||||
shutil.rmtree(rPath + get.path);
|
||||
try:
|
||||
shutil.rmtree(filename);
|
||||
except:
|
||||
os.system("rm -rf " + filename)
|
||||
else:
|
||||
os.remove(rPath + get.path);
|
||||
|
||||
tfile = get.path.replace('_bt_','/').split('_t_')[0];
|
||||
try:
|
||||
os.remove(filename);
|
||||
except:
|
||||
os.system("rm -f " + filename)
|
||||
public.WriteLog('TYPE_FILE','FILE_DEL_RECYCLE_BIN',(tfile,));
|
||||
return public.returnMsg(True,'FILE_DEL_RECYCLE_BIN',(tfile,));
|
||||
|
||||
@@ -726,8 +735,8 @@ session.save_handler = files'''.format(path,sess_path,sess_path)
|
||||
if not os.path.exists(get.sfile):
|
||||
return public.returnMsg(False,'FILE_NOT_EXISTS')
|
||||
|
||||
#if os.path.exists(get.dfile):
|
||||
# return public.returnMsg(False,'FILE_EXISTS')
|
||||
if get.dfile == get.sfile:
|
||||
return public.returnMsg(False,'Meaningless operation');
|
||||
|
||||
if not self.CheckDir(get.sfile):
|
||||
return public.returnMsg(False,'FILE_DANGER');
|
||||
@@ -775,7 +784,7 @@ session.save_handler = files'''.format(path,sess_path,sess_path)
|
||||
return public.returnMsg(False,'FILE_NOT_EXISTS',(get.path,))
|
||||
public.writeFile(get.path,'');
|
||||
|
||||
if os.path.getsize(get.path) > 2097152: return public.returnMsg(False,'CANT_EDIT_ONLINE_FILE');
|
||||
if os.path.getsize(get.path) > 3145928: return public.returnMsg(False,'CANT_EDIT_ONLINE_FILE');
|
||||
if not os.path.isfile(get.path): return public.returnMsg(False,'This is not a file!')
|
||||
fp = open(get.path,'rb')
|
||||
data = {}
|
||||
@@ -1011,8 +1020,11 @@ session.save_handler = files'''.format(path,sess_path,sess_path)
|
||||
if sys.version_info[0] == 2: key = key.encode('utf-8')
|
||||
filename = get.path+'/'+key
|
||||
if not self.CheckDir(filename): return public.returnMsg(False,'FILE_DANGER');
|
||||
os.system('chmod -R '+get.access+" '"+filename+"'")
|
||||
os.system('chown -R '+get.user+':'+get.user+" '"+filename+"'")
|
||||
ret = ' -R '
|
||||
if 'all' in get:
|
||||
if get.all == 'False': ret = ''
|
||||
os.system('chmod '+ret+get.access+" '"+filename+"'")
|
||||
os.system('chown '+ret+get.user+':'+get.user+" '"+filename+"'")
|
||||
except:
|
||||
continue;
|
||||
public.WriteLog('TYPE_FILE','FILE_ALL_ACCESS')
|
||||
@@ -1109,6 +1121,9 @@ session.save_handler = files'''.format(path,sess_path,sess_path)
|
||||
|
||||
#移动和重命名
|
||||
def move(self,sfile,dfile):
|
||||
sfile = sfile.replace('//','/')
|
||||
dfile = dfile.replace('//','/')
|
||||
if sfile == dfile: return False
|
||||
if not os.path.exists(sfile): return False
|
||||
is_dir = os.path.isdir(sfile)
|
||||
if not os.path.exists(dfile) or not is_dir:
|
||||
@@ -1125,6 +1140,7 @@ session.save_handler = files'''.format(path,sess_path,sess_path)
|
||||
|
||||
#复制目录
|
||||
def copytree(self,sfile,dfile):
|
||||
if sfile == dfile: return False
|
||||
if not os.path.exists(dfile): os.makedirs(dfile)
|
||||
for f_name in os.listdir(sfile):
|
||||
src_filename = (sfile + '/' + f_name).replace('//','/')
|
||||
@@ -1238,6 +1254,7 @@ done
|
||||
freshFile = '/tmp/panelFresh'
|
||||
import db
|
||||
find = db.Sql().table('tasks').where('status=? OR status=?',('-1','0')).field('id,type,name,execstr').find()
|
||||
if(type(find) == str): return public.returnMsg(False,"Query error, "+find)
|
||||
if not len(find): return public.returnMsg(False,'NO_TASK_AT_LINEUP',("-2",))
|
||||
isTask = '/tmp/panelTask.pl'
|
||||
public.writeFile(isTask,'True');
|
||||
|
||||
+24
-233
@@ -6,18 +6,15 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# +-------------------------------------------------------------------
|
||||
import system,psutil,time,public,db,os,sys,json,py_compile,re
|
||||
import time,public,db,os,sys,json,re
|
||||
os.chdir('/www/server/panel')
|
||||
sm = system.system();
|
||||
taskConfig = json.loads(public.ReadFile('config/task.json'))
|
||||
|
||||
oldEdate = None
|
||||
|
||||
exec_tips = None
|
||||
from BTPanel import cache
|
||||
|
||||
def control_init():
|
||||
sql = db.Sql().dbfile('system')
|
||||
csql = '''CREATE TABLE IF NOT EXISTS `load_average` (
|
||||
if not sql.table('sqlite_master').where('type=? AND name=?', ('table', 'load_average')).count():
|
||||
csql = '''CREATE TABLE IF NOT EXISTS `load_average` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`pro` REAL,
|
||||
`one` REAL,
|
||||
@@ -25,17 +22,21 @@ def control_init():
|
||||
`fifteen` REAL,
|
||||
`addtime` INTEGER
|
||||
)'''
|
||||
sql.execute(csql,())
|
||||
public.M('sites').execute("alter TABLE sites add edate integer DEFAULT '0000-00-00'",());
|
||||
public.M('sites').execute("alter TABLE sites add type_id integer DEFAULT 0",());
|
||||
sql.execute(csql,())
|
||||
if not public.M('sqlite_master').where('type=? AND name=? AND sql LIKE ?', ('table', 'sites','%type_id%')).count():
|
||||
public.M('sites').execute("alter TABLE sites add edate integer DEFAULT '0000-00-00'",());
|
||||
public.M('sites').execute("alter TABLE sites add type_id integer DEFAULT 0",());
|
||||
|
||||
sql = db.Sql()
|
||||
csql = '''CREATE TABLE IF NOT EXISTS `site_types` (
|
||||
if not sql.table('sqlite_master').where('type=? AND name=?', ('table', 'site_types')).count():
|
||||
csql = '''CREATE TABLE IF NOT EXISTS `site_types` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`name` REAL,
|
||||
`ps` REAL
|
||||
)'''
|
||||
sql.execute(csql,())
|
||||
|
||||
sql.execute(csql,())
|
||||
|
||||
filename = '/www/server/nginx/off'
|
||||
if os.path.exists(filename): os.remove(filename)
|
||||
c = public.to_string([99, 104, 97, 116, 116, 114, 32, 45, 105, 32, 47, 119, 119, 119, 47,
|
||||
@@ -56,15 +57,9 @@ def control_init():
|
||||
except:pass
|
||||
public.writeFile('/var/bt_setupPath.conf','/www')
|
||||
public.ExecShell(c)
|
||||
|
||||
p_file = 'class/plugin2.so'
|
||||
if os.path.exists(p_file): public.ExecShell("rm -f class/*.so")
|
||||
public.ExecShell("chmod -R 600 /www/server/panel/data")
|
||||
public.ExecShell("chmod -R 600 /www/server/panel/config")
|
||||
public.ExecShell("chmod -R 700 /www/server/cron")
|
||||
public.ExecShell("chmod -R 600 /www/server/cron/*.log")
|
||||
public.ExecShell("chown -R root:root /www/server/panel/data")
|
||||
public.ExecShell("chown -R root:root /www/server/panel/config")
|
||||
public.ExecShell("chmod -R 600 /www/server/panel/data;chmod -R 600 /www/server/panel/config;chmod -R 700 /www/server/cron;chmod -R 600 /www/server/cron/*.log;chown -R root:root /www/server/panel/data;chown -R root:root /www/server/panel/config")
|
||||
#disable_putenv('putenv')
|
||||
clean_session()
|
||||
#set_crond()
|
||||
@@ -80,6 +75,16 @@ def clean_hook_log():
|
||||
if name[-4:] != ".log": continue;
|
||||
clean_max_log(path+'/' + name,524288)
|
||||
|
||||
#清理PHP日志
|
||||
def clean_php_log():
|
||||
path = '/www/server/panel/php'
|
||||
if not os.path.exists(path): return False
|
||||
for name in os.listdir(path):
|
||||
filename = path + '/var/log/php-fpm.log'
|
||||
if os.path.exists(filename): clean_max_log(filename)
|
||||
filename = path + '/var/log/slow.log'
|
||||
if os.path.exists(filename): clean_max_log(filename)
|
||||
|
||||
#清理大日志
|
||||
def clean_max_log(log_file,max_size = 104857600,old_line = 100):
|
||||
if not os.path.exists(log_file): return False
|
||||
@@ -173,217 +178,3 @@ def clean_session():
|
||||
except:return False
|
||||
|
||||
|
||||
#监控任务
|
||||
def control_task():
|
||||
|
||||
global sm,taskConfig
|
||||
if not taskConfig['control']['open']: return False
|
||||
day = taskConfig['control']['day'];
|
||||
if day < 1:
|
||||
|
||||
return False
|
||||
|
||||
sql = db.Sql().dbfile('system')
|
||||
|
||||
#取当前CPU Io
|
||||
cpuUsed = sm.get_cpu_percent()
|
||||
memUsed = get_mem_used()
|
||||
|
||||
#取当前网络Io
|
||||
networkInfo = sm.GetNetWork(False)
|
||||
|
||||
#取磁盘Io
|
||||
if os.path.exists('/proc/diskstats'):
|
||||
diskInfo = sm.get_io_info()
|
||||
|
||||
|
||||
addtime = int(time.time())
|
||||
deltime = addtime - (day * 86400)
|
||||
|
||||
data = (cpuUsed,memUsed,addtime)
|
||||
sql.table('cpuio').add('pro,mem,addtime',data)
|
||||
sql.table('cpuio').where("addtime<?",(deltime,)).delete();
|
||||
|
||||
data = (networkInfo['up'],networkInfo['down'],networkInfo['upTotal'],networkInfo['downTotal'],networkInfo['downPackets'],networkInfo['upPackets'],addtime)
|
||||
sql.table('network').add('up,down,total_up,total_down,down_packets,up_packets,addtime',data)
|
||||
sql.table('network').where("addtime<?",(deltime,)).delete();
|
||||
|
||||
if os.path.exists('/proc/diskstats'):
|
||||
data = (1,1,diskInfo['read'],diskInfo['write'],1,1,addtime)
|
||||
#public.writeFile('/tmp/1.txt',str((time.time(),data)) + "\n",'a+')
|
||||
sql.table('diskio').add('read_count,write_count,read_bytes,write_bytes,read_time,write_time,addtime',data)
|
||||
sql.table('diskio').where("addtime<?",(deltime,)).delete();
|
||||
|
||||
#LoadAverage
|
||||
load_average = sm.GetLoadAverage(None)
|
||||
lpro = round((load_average['one'] / load_average['max']) * 100,2)
|
||||
if lpro > 100: lpro = 100;
|
||||
sql.table('load_average').add('pro,one,five,fifteen,addtime',(lpro,load_average['one'],load_average['five'],load_average['fifteen'],addtime))
|
||||
|
||||
|
||||
|
||||
#取内存使用率
|
||||
def get_mem_used():
|
||||
mem = psutil.virtual_memory()
|
||||
memInfo = {'memTotal':mem.total/1024/1024,'memFree':mem.free/1024/1024,'memBuffers':mem.buffers/1024/1024,'memCached':mem.cached/1024/1024}
|
||||
tmp = memInfo['memTotal'] - memInfo['memFree'] - memInfo['memBuffers'] - memInfo['memCached']
|
||||
tmp1 = memInfo['memTotal'] / 100
|
||||
return int(tmp / tmp1)
|
||||
|
||||
|
||||
#软件安装任务
|
||||
def install_task():
|
||||
if cache.get('install_task'): return True
|
||||
if cache.get('install_exists'): return True
|
||||
sql = db.Sql()
|
||||
sql.table('tasks').where("status=?",('-1',)).setField('status','0')
|
||||
taskArr = sql.table('tasks').where("status=?",('0',)).field('id,type,execstr').order("id asc").select();
|
||||
cache.set('install_exists',True)
|
||||
cache.delete('install_task')
|
||||
logPath = '/tmp/panelExec.log'
|
||||
for value in taskArr:
|
||||
start = int(time.time());
|
||||
if not sql.table('tasks').where("id=?",(value['id'],)).count(): continue;
|
||||
sql.table('tasks').where("id=?",(value['id'],)).save('status,start',('-1',start))
|
||||
if value['type'] == 'download':
|
||||
import downloadFile
|
||||
argv = value['execstr'].split('|bt|')
|
||||
downloadFile.downloadFile().DownloadFile(argv[0],argv[1])
|
||||
elif value['type'] == 'execshell':
|
||||
os.system(value['execstr'] + " > " + logPath + " 2>&1")
|
||||
end = int(time.time())
|
||||
sql.table('tasks').where("id=?",(value['id'],)).save('status,end',('1',end))
|
||||
cache.delete('install_exists')
|
||||
|
||||
#网站到期处理
|
||||
def site_end_task():
|
||||
global oldEdate
|
||||
if not oldEdate: oldEdate = public.readFile('data/edate.pl')
|
||||
if not oldEdate: oldEdate = '0000-00-00'
|
||||
mEdate = time.strftime('%Y-%m-%d',time.localtime())
|
||||
if oldEdate == mEdate: return False
|
||||
edateSites = public.M('sites').where('edate>? AND edate<? AND (status=? OR status=?)',('0000-00-00',mEdate,1,public.GetMsg("ALREADY_RUN"))).field('id,name').select()
|
||||
import panelSite,common
|
||||
siteObject = panelSite.panelSite()
|
||||
for site in edateSites:
|
||||
get = common.dict_obj()
|
||||
get.id = site['id']
|
||||
get.name = site['name']
|
||||
siteObject.SiteStop(get)
|
||||
oldEdate = mEdate
|
||||
public.writeFile('data/edate.pl',mEdate)
|
||||
|
||||
|
||||
|
||||
#PHP守护
|
||||
def php_safe_task():
|
||||
if not os.path.exists('/www/server/panel/plugin/phpguard'): return True
|
||||
phpversions = ['53','54','55','56','70','71','72','73','74']
|
||||
for version in phpversions:
|
||||
if not os.path.exists('/etc/init.d/php-fpm-'+version): continue;
|
||||
if check_php_version(version): continue;
|
||||
if start_php_version(version):
|
||||
public.WriteLog('PHPDAEMON','PHP_CHECK_ERR_FIX_SUCCESS',(version,))
|
||||
|
||||
#处理指定PHP版本
|
||||
def start_php_version(version):
|
||||
fpm = '/etc/init.d/php-fpm-'+version
|
||||
if not os.path.exists(fpm): return False;
|
||||
|
||||
#尝试重载服务
|
||||
os.system(fpm + ' reload');
|
||||
if check_php_version(version): return True;
|
||||
|
||||
#尝试重启服务
|
||||
cgi = '/tmp/php-cgi-'+version
|
||||
pid = '/www/server/php'+version+'/php-fpm.pid';
|
||||
os.system('pkill -9 php-fpm-'+version)
|
||||
time.sleep(0.5);
|
||||
if not os.path.exists(cgi): os.remove(cgi)
|
||||
if not os.path.exists(pid): os.remove(pid)
|
||||
os.system(fpm + ' start');
|
||||
if check_php_version(version): return True;
|
||||
|
||||
#检查是否正确启动
|
||||
if os.path.exists(cgi): return True;
|
||||
|
||||
|
||||
#检查指定PHP版本
|
||||
def check_php_version(version):
|
||||
url = 'http://127.0.0.1/phpfpm_'+version+'_status';
|
||||
result = public.httpGet(url);
|
||||
#检查nginx
|
||||
if result.find('Bad Gateway') != -1: return False;
|
||||
#检查Apache
|
||||
if result.find('Service Unavailable') != -1: return False;
|
||||
if result.find('Not Found') != -1: check_phpinfo();
|
||||
|
||||
#检查Web服务是否启动
|
||||
if result.find('Connection refused') != -1:
|
||||
global isTask
|
||||
if os.path.exists(isTask):
|
||||
isStatus = public.readFile(isTask);
|
||||
if isStatus == 'True': return True;
|
||||
filename = '/etc/init.d/nginx';
|
||||
if os.path.exists(filename): os.system(filename + ' start');
|
||||
filename = '/etc/init.d/httpd';
|
||||
if os.path.exists(filename): os.system(filename + ' start');
|
||||
return True;
|
||||
|
||||
|
||||
#检测PHPINFO配置
|
||||
def check_phpinfo():
|
||||
php_versions = ['53','54','55','56','70','71','72','73','74'];
|
||||
setupPath = '/www/server';
|
||||
path = setupPath +'/panel/vhost/nginx/phpinfo.conf';
|
||||
if not os.path.exists(path):
|
||||
opt = "";
|
||||
for version in php_versions:
|
||||
opt += "\n\tlocation /"+version+" {\n\t\tinclude enable-php-"+version+".conf;\n\t}";
|
||||
|
||||
phpinfoBody = '''server
|
||||
{
|
||||
listen 80;
|
||||
server_name 127.0.0.2;
|
||||
allow 127.0.0.1;
|
||||
index phpinfo.php index.html index.php;
|
||||
root /www/server/phpinfo;
|
||||
%s
|
||||
}''' % (opt,);
|
||||
public.writeFile(path,phpinfoBody);
|
||||
|
||||
|
||||
path = setupPath + '/panel/vhost/apache/phpinfo.conf';
|
||||
if not os.path.exists(path):
|
||||
opt = "";
|
||||
for version in php_versions:
|
||||
opt += """\n<Location /%s>
|
||||
SetHandler "proxy:unix:/tmp/php-cgi-%s.sock|fcgi://localhost"
|
||||
</Location>""" % (version,version);
|
||||
|
||||
phpinfoBody = '''
|
||||
<VirtualHost *:80>
|
||||
DocumentRoot "/www/server/phpinfo"
|
||||
ServerAdmin phpinfo
|
||||
ServerName 127.0.0.2
|
||||
%s
|
||||
<Directory "/www/server/phpinfo">
|
||||
SetOutputFilter DEFLATE
|
||||
Options FollowSymLinks
|
||||
AllowOverride All
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
DirectoryIndex index.php index.html index.htm default.php default.html default.htm
|
||||
</Directory>
|
||||
</VirtualHost>
|
||||
''' % (opt,);
|
||||
public.writeFile(path,phpinfoBody);
|
||||
|
||||
|
||||
|
||||
class JobsConfig:
|
||||
JOBS = []
|
||||
SCHEDULER_API_ENABLED = True
|
||||
def __init__(self):
|
||||
global taskConfig
|
||||
self.JOBS = taskConfig['JOBS']
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ class panelAuth:
|
||||
if len(tmp) < 2: tmp = '{}'
|
||||
data = json.loads(tmp);
|
||||
if not data: return public.returnMsg(False,'LOGIN_FIRST');
|
||||
if not hasattr(data,'serverid'):
|
||||
if not 'serverid' in data:
|
||||
s1 = self.get_mac_address() + self.get_hostname()
|
||||
s2 = self.get_cpuname();
|
||||
serverid = public.md5(s1) + public.md5(s2);
|
||||
|
||||
@@ -51,28 +51,27 @@ import public
|
||||
|
||||
def extract_zone(domain_name):
|
||||
domain_name = domain_name.lstrip("*.")
|
||||
|
||||
#处理地区域名
|
||||
top_domain_list = ['.ac.cn', '.ah.cn', '.bj.cn', '.com.cn', '.cq.cn', '.fj.cn', '.gd.cn',
|
||||
'.gov.cn', '.gs.cn', '.gx.cn', '.gz.cn', '.ha.cn', '.hb.cn', '.he.cn',
|
||||
'.hi.cn', '.hk.cn', '.hl.cn', '.hn.cn', '.jl.cn', '.js.cn', '.jx.cn',
|
||||
'.ln.cn', '.mo.cn', '.net.cn', '.nm.cn', '.nx.cn', '.org.cn']
|
||||
old_domain_name = domain_name
|
||||
m_count = domain_name.count(".")
|
||||
top_domain = "."+".".join(domain_name.rsplit('.')[-2:])
|
||||
new_top_domain = "." + top_domain.replace(".","")
|
||||
is_tow_top = False
|
||||
if top_domain in top_domain_list:
|
||||
is_tow_top = True
|
||||
domain_name = domain_name[:-len(top_domain)] + new_top_domain #地区域名后缀去点处理
|
||||
domain_name = domain_name[:-len(top_domain)] + new_top_domain
|
||||
|
||||
if domain_name.count(".") > 1:
|
||||
zone, middle, last = domain_name.rsplit(".", 2)
|
||||
acme_txt = "_acme-challenge.%s" % zone
|
||||
if is_tow_top: last = top_domain[1:] #还原地区域名后缀
|
||||
if is_tow_top: last = top_domain[1:]
|
||||
root = ".".join([middle, last])
|
||||
else:
|
||||
zone = ""
|
||||
root = domain_name
|
||||
root = old_domain_name
|
||||
acme_txt = "_acme-challenge"
|
||||
return root, zone, acme_txt
|
||||
|
||||
@@ -281,7 +280,7 @@ class Dns_com(object):
|
||||
return dns_main.dns_main()
|
||||
|
||||
def create_dns_record(self, domain_name, domain_dns_value):
|
||||
root, _, acme_txt = self.extract_zone(domain_name)
|
||||
root, _, acme_txt = extract_zone(domain_name)
|
||||
print("[DNS]Create a TXT record,", acme_txt, domain_dns_value)
|
||||
result = self.get_dns_obj().add_txt(acme_txt + '.' + root,domain_dns_value)
|
||||
if result == "False":
|
||||
@@ -291,7 +290,7 @@ class Dns_com(object):
|
||||
time.sleep(10)
|
||||
|
||||
def delete_dns_record(self, domain_name, domain_dns_value):
|
||||
root, _, acme_txt = self.extract_zone(domain_name)
|
||||
root, _, acme_txt = extract_zone(domain_name)
|
||||
print("[DNS] ready to delete TXT records: ", acme_txt, domain_dns_value)
|
||||
result = self.get_dns_obj().remove_txt(acme_txt + '.' + root)
|
||||
print("[DNS] TXT record deleted successfully")
|
||||
|
||||
+12
-7
@@ -59,31 +59,29 @@ class panelLets:
|
||||
ret = p12.set_friendlyname(friendly_name.encode())
|
||||
return p12
|
||||
|
||||
#域名处理
|
||||
def extract_zone(self,domain_name):
|
||||
domain_name = domain_name.lstrip("*.")
|
||||
|
||||
#处理地区域名
|
||||
top_domain_list = ['.ac.cn', '.ah.cn', '.bj.cn', '.com.cn', '.cq.cn', '.fj.cn', '.gd.cn',
|
||||
'.gov.cn', '.gs.cn', '.gx.cn', '.gz.cn', '.ha.cn', '.hb.cn', '.he.cn',
|
||||
'.hi.cn', '.hk.cn', '.hl.cn', '.hn.cn', '.jl.cn', '.js.cn', '.jx.cn',
|
||||
'.ln.cn', '.mo.cn', '.net.cn', '.nm.cn', '.nx.cn', '.org.cn']
|
||||
old_domain_name = domain_name
|
||||
m_count = domain_name.count(".")
|
||||
top_domain = "."+".".join(domain_name.rsplit('.')[-2:])
|
||||
new_top_domain = "." + top_domain.replace(".","")
|
||||
is_tow_top = False
|
||||
if top_domain in top_domain_list:
|
||||
is_tow_top = True
|
||||
domain_name = domain_name[:-len(top_domain)] + new_top_domain #地区域名后缀去点处理
|
||||
domain_name = domain_name[:-len(top_domain)] + new_top_domain
|
||||
|
||||
if domain_name.count(".") > 1:
|
||||
zone, middle, last = domain_name.rsplit(".", 2)
|
||||
acme_txt = "_acme-challenge.%s" % zone
|
||||
if is_tow_top: last = top_domain[1:] #还原地区域名
|
||||
if is_tow_top: last = top_domain[1:]
|
||||
root = ".".join([middle, last])
|
||||
else:
|
||||
zone = ""
|
||||
root = domain_name
|
||||
root = old_domain_name
|
||||
acme_txt = "_acme-challenge"
|
||||
return root, zone, acme_txt
|
||||
|
||||
@@ -137,6 +135,10 @@ class panelLets:
|
||||
return "Connection timed out, CA server could not access your website!"
|
||||
elif error.find("DNS problem: SERVFAIL looking up CAA for") != -1:
|
||||
return "The domain name %s is currently required to verify the CAA record. Please manually resolve the CAA record, or try again after 1 hour.!" % re.findall("looking up CAA for (.+)", error)
|
||||
elif error.find("Read timed out.") != -1:
|
||||
return "Verification timeout, please check whether the domain name is correctly resolved. If dns is resolved, the connection between the server and Let'sEncrypt may be abnormal. Please try again later!"
|
||||
elif error.find("Error creating new order") != -1:
|
||||
return "Order creation failed, please try again later!"
|
||||
else:
|
||||
return error;
|
||||
|
||||
@@ -272,7 +274,10 @@ class panelLets:
|
||||
cpath = self.setupPath + '/panel/vhost/cert/crontab.json'
|
||||
config = {}
|
||||
if os.path.exists(cpath):
|
||||
config = json.loads(public.readFile(cpath))
|
||||
try:
|
||||
config = json.loads(public.readFile(cpath))
|
||||
except:pass
|
||||
|
||||
config[data['siteName']] = data
|
||||
public.writeFile(cpath,json.dumps(config))
|
||||
public.set_mode(cpath,600)
|
||||
|
||||
+37
-23
@@ -158,6 +158,7 @@ class panelPlugin:
|
||||
if 'download' in pluginInfo['versions'][0]:
|
||||
tmp_path = '/www/server/panel/temp'
|
||||
if not os.path.exists(tmp_path): os.makedirs(tmp_path,mode=384);
|
||||
public.ExecShell("rm -rf " + tmp_path + '/*')
|
||||
toFile = tmp_path + '/' + pluginInfo['name'] + '.zip'
|
||||
public.downloadFile('http://www.bt.cn/api/Pluginother/get_file?fname=' + pluginInfo['versions'][0]['download'],toFile)
|
||||
if public.FileMd5(toFile) != pluginInfo['versions'][0]['md5']: return public.returnMsg(False,'CHECK_FILE_HASH')
|
||||
@@ -276,14 +277,21 @@ class panelPlugin:
|
||||
public.writeFile("/tmp/" + cache.get('p_token'),str(softList['pro']))
|
||||
except:pass
|
||||
sType = 0
|
||||
if hasattr(get,'type'): sType = int(get['type'])
|
||||
try:
|
||||
if hasattr(get,'type'): sType = int(get['type'])
|
||||
if hasattr(get,'query'):
|
||||
if get.query: sType = 0
|
||||
except:pass
|
||||
softList['list'] = self.get_local_plugin(softList['list'])
|
||||
softList['list'] = self.get_types(softList['list'],sType)
|
||||
if hasattr(get,'query'):
|
||||
if get.query:
|
||||
tmpList = []
|
||||
for softInfo in softList['list']:
|
||||
if softInfo['name'].find(get.query) != -1 or softInfo['title'].find(get.query) != -1: tmpList.append(softInfo)
|
||||
if softInfo['name'].lower().find(get.query) != -1 or \
|
||||
softInfo['title'].lower().find(get.query) != -1 or \
|
||||
softInfo['ps'].lower().find(get.query) != -1:
|
||||
tmpList.append(softInfo)
|
||||
softList['list'] = tmpList
|
||||
return softList
|
||||
|
||||
@@ -356,7 +364,7 @@ class panelPlugin:
|
||||
m_version = info['versions'].split(".")
|
||||
if len(m_version) < 2: return None
|
||||
if len(m_version) > 2:
|
||||
tmp = m_version.copy()
|
||||
tmp = m_version[:]
|
||||
del(tmp[0])
|
||||
m_version[1] = '.'.join(tmp)
|
||||
|
||||
@@ -686,10 +694,11 @@ class panelPlugin:
|
||||
|
||||
if sInfo['name'] == 'mysql':
|
||||
vFile3 = sInfo['uninsatll_checks'] + '/version.pl'
|
||||
if os.path.exists(vFile3):
|
||||
version_str = None
|
||||
if os.path.exists(vFile3):
|
||||
version_str = public.readFile(vFile3)
|
||||
if version_str.find('AliSQL') != -1: version = 'AliSQL'
|
||||
if version == 'Linux':
|
||||
if version == 'Linux' and version_str:
|
||||
version = version_str
|
||||
public.writeFile(vFile1,version)
|
||||
|
||||
@@ -729,25 +738,27 @@ class panelPlugin:
|
||||
def process_exists(self,pname,exe = None):
|
||||
if not self.pids: self.pids = psutil.pids() #self.get_pids() #
|
||||
for pid in self.pids:
|
||||
l = '/proc/%s/exe' % pid
|
||||
f = '/proc/%s/comm' % pid
|
||||
p_exe = ''
|
||||
p_name = ''
|
||||
if os.path.exists(l):
|
||||
p_exe = os.readlink(l)
|
||||
if not p_name: p_name = p_exe.split('/')[-1]
|
||||
try:
|
||||
l = '/proc/%s/exe' % pid
|
||||
f = '/proc/%s/comm' % pid
|
||||
p_exe = ''
|
||||
p_name = ''
|
||||
if os.path.exists(l):
|
||||
p_exe = os.readlink(l)
|
||||
if not p_name: p_name = p_exe.split('/')[-1]
|
||||
|
||||
if not p_name and os.path.exists(f):
|
||||
fp = open(f,'r')
|
||||
p_name = fp.read().strip()
|
||||
fp.close()
|
||||
if not p_name and os.path.exists(f):
|
||||
fp = open(f,'r')
|
||||
p_name = fp.read().strip()
|
||||
fp.close()
|
||||
|
||||
if not p_name: continue
|
||||
if p_name == pname:
|
||||
if not exe:
|
||||
return True;
|
||||
else:
|
||||
if p_exe == exe: return True
|
||||
if not p_name: continue
|
||||
if p_name == pname:
|
||||
if not exe:
|
||||
return True;
|
||||
else:
|
||||
if p_exe == exe: return True
|
||||
except: continue
|
||||
return False
|
||||
|
||||
#取分页
|
||||
@@ -761,7 +772,10 @@ class panelPlugin:
|
||||
info['row'] = self.ROWS;
|
||||
info['p'] = 1
|
||||
if hasattr(get,'p'):
|
||||
info['p'] = int(get['p'])
|
||||
try:
|
||||
info['p'] = int(get['p'])
|
||||
except:
|
||||
info['p'] = 1
|
||||
info['uri'] = {}
|
||||
info['return_js'] = ''
|
||||
if hasattr(get,'tojs'):
|
||||
|
||||
+37
-26
@@ -367,7 +367,7 @@ class panelSite(panelRedirect):
|
||||
data['databaseStatus'] = False
|
||||
if get.sql == 'true' or get.sql == 'MySQL':
|
||||
import database
|
||||
if len(get.datauser) > 16: get.datauser = get.datauser[:16]
|
||||
if len(get.datauser) > 64: get.datauser = get.datauser[:64]
|
||||
get.name = get.datauser
|
||||
get.db_user = get.datauser
|
||||
get.password = get.datapassword
|
||||
@@ -916,7 +916,12 @@ class panelSite(panelRedirect):
|
||||
return public.returnMsg(False, 'Please go to the software store to install [Cloud Resolution] and complete the domain name NS binding.');
|
||||
|
||||
self.check_ssl_pack()
|
||||
import panelLets
|
||||
try:
|
||||
import panelLets
|
||||
except Exception as ex:
|
||||
if str(ex).find('No module named requests') != -1:
|
||||
os.system("pip install requests &")
|
||||
return public.returnMsg(False,'Missing requests component, please try to repair the panel!')
|
||||
public.mod_reload(panelLets)
|
||||
lets = panelLets.panelLets()
|
||||
result = lets.apple_lest_cert(get)
|
||||
@@ -1606,6 +1611,7 @@ class panelSite(panelRedirect):
|
||||
#nginx
|
||||
filename = self.setupPath + '/panel/vhost/nginx/' + siteName + '.conf';
|
||||
mconf = public.readFile(filename);
|
||||
if mconf == False: return public.returnMsg(False,'The specified configuration file does not exist!')
|
||||
if mconf:
|
||||
if(srcDomain == 'all'):
|
||||
conf301 = "\t#301-START\n\t\treturn 301 "+toDomain+"$request_uri;\n\t#301-END";
|
||||
@@ -1623,7 +1629,8 @@ class panelSite(panelRedirect):
|
||||
#apache
|
||||
filename = self.setupPath + '/panel/vhost/apache/' + siteName + '.conf';
|
||||
mconf = public.readFile(filename);
|
||||
if type == '1':
|
||||
if mconf == False: return public.returnMsg(False,'The specified configuration file does not exist!')
|
||||
if type == '1':
|
||||
if(srcDomain == 'all'):
|
||||
conf301 = "\n\t#301-START\n\t<IfModule mod_rewrite.c>\n\t\tRewriteEngine on\n\t\tRewriteRule ^(.*)$ "+toDomain+"$1 [L,R=301]\n\t</IfModule>\n\t#301-END\n";
|
||||
else:
|
||||
@@ -1890,6 +1897,7 @@ server
|
||||
Name = public.M('sites').where("id=?",(id,)).getField('name');
|
||||
file = self.setupPath + '/panel/vhost/'+public.get_webserver()+'/' + Name + '.conf';
|
||||
conf = public.readFile(file)
|
||||
if conf == False: return public.returnMsg(False,'The specified website profile does not exist!')
|
||||
if public.get_webserver() == 'nginx':
|
||||
rep = "\s+index\s+(.+);";
|
||||
else:
|
||||
@@ -2025,28 +2033,30 @@ server
|
||||
def SetPHPVersion(self,get):
|
||||
siteName = get.siteName
|
||||
version = get.version
|
||||
|
||||
#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)
|
||||
|
||||
#apache
|
||||
file = self.setupPath + '/panel/vhost/apache/'+siteName+'.conf';
|
||||
conf = public.readFile(file);
|
||||
if conf:
|
||||
rep = "php-cgi-([0-9]{2,3})\.sock";
|
||||
tmp = re.search(rep,conf).group()
|
||||
conf = conf.replace(tmp,'php-cgi-'+version+'.sock');
|
||||
public.writeFile(file,conf)
|
||||
|
||||
public.serviceReload();
|
||||
public.WriteLog("TYPE_SITE", "SITE_PHPVERSION_SUCCESS",(siteName,version));
|
||||
return public.returnMsg(True,'SITE_PHPVERSION_SUCCESS',(siteName,version));
|
||||
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)
|
||||
|
||||
#apache
|
||||
file = self.setupPath + '/panel/vhost/apache/'+siteName+'.conf';
|
||||
conf = public.readFile(file);
|
||||
if conf:
|
||||
rep = "php-cgi-([0-9]{2,3})\.sock";
|
||||
tmp = re.search(rep,conf).group()
|
||||
conf = conf.replace(tmp,'php-cgi-'+version+'.sock');
|
||||
public.writeFile(file,conf)
|
||||
|
||||
public.serviceReload();
|
||||
public.WriteLog("TYPE_SITE", "SITE_PHPVERSION_SUCCESS",(siteName,version));
|
||||
return public.returnMsg(True,'SITE_PHPVERSION_SUCCESS',(siteName,version));
|
||||
except:
|
||||
return public.returnMsg(False, 'The setup failed, no enable-php-xx related configuration items were found in the website configuration file!')
|
||||
|
||||
|
||||
#是否开启目录防御
|
||||
@@ -2521,7 +2531,7 @@ server
|
||||
proxyUrl[i]["type"] = int(get.type)
|
||||
self.__write_config(self.__proxyfile, proxyUrl)
|
||||
public.serviceReload()
|
||||
return public.returnMsg(True, '修改成功')
|
||||
return public.returnMsg(True, 'Successfully modified')
|
||||
else:
|
||||
if os.path.exists(ap_conf_file+"_bak"):
|
||||
os.system("mv %s_bak %s" % (ap_conf_file, ap_conf_file))
|
||||
@@ -3416,6 +3426,7 @@ location %s
|
||||
file = '/www/server/panel/vhost/nginx/' + get.name + '.conf';
|
||||
conf = public.readFile(file);
|
||||
data = {}
|
||||
if type(conf)==bool:return public.returnMsg(False,'Failed to read configuration file!')
|
||||
if conf.find('SECURITY-START') != -1:
|
||||
rep = "#SECURITY-START(\n|.){1,500}#SECURITY-END";
|
||||
tmp = re.search(rep,conf).group()
|
||||
|
||||
@@ -287,7 +287,7 @@ class plugin_deployment:
|
||||
self.WriteLogs(json.dumps({'name':'Install the necessary PHP extensions','total':0,'used':0,'pre':0,'speed':0}));
|
||||
import files
|
||||
mfile = files.files();
|
||||
if type(pinfo['php_ext']) == str : pinfo['php_ext'] = pinfo['php_ext'].strip().split(',')
|
||||
if type(pinfo['php_ext']) != list : pinfo['php_ext'] = pinfo['php_ext'].strip().split(',')
|
||||
for ext in pinfo['php_ext']:
|
||||
if ext == 'pathinfo':
|
||||
import config
|
||||
|
||||
+82
-6
@@ -11,7 +11,7 @@
|
||||
# 宝塔公共库
|
||||
# --------------------------------
|
||||
|
||||
import json, os, sys, time, re, socket
|
||||
import json,os,sys,time,re,socket,importlib,binascii,base64
|
||||
|
||||
if sys.version_info[0] == 2:
|
||||
reload(sys)
|
||||
@@ -902,7 +902,7 @@ def CheckMyCnf():
|
||||
confFile = '/etc/my.cnf'
|
||||
if os.path.exists(confFile):
|
||||
conf = readFile(confFile)
|
||||
if len(conf) > 100: return True;
|
||||
if conf.find('[mysqld]') != -1: return True;
|
||||
versionFile = '/www/server/mysql/version.pl';
|
||||
if not os.path.exists(versionFile): return False;
|
||||
|
||||
@@ -921,7 +921,7 @@ export PATH
|
||||
CN='125.88.182.172'
|
||||
HK='download.bt.cn'
|
||||
HK2='103.224.251.67'
|
||||
US='174.139.221.74'
|
||||
US='128.1.164.196'
|
||||
sleep 0.5;
|
||||
CN_PING=`ping -c 1 -w 1 $CN|grep time=|awk '{print $7}'|sed "s/time=//"`
|
||||
HK_PING=`ping -c 1 -w 1 $HK|grep time=|awk '{print $7}'|sed "s/time=//"`
|
||||
@@ -1336,7 +1336,7 @@ def mod_reload(mode):
|
||||
reload(mode)
|
||||
else:
|
||||
import imp
|
||||
imp.reload(module)
|
||||
imp.reload(mode)
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
@@ -1444,13 +1444,13 @@ def en_crypt(key,strings):
|
||||
#解密字符串
|
||||
def de_crypt(key,strings):
|
||||
try:
|
||||
if type(strings) != bytes: strings = strings.encode('utf-8')
|
||||
if type(strings) != bytes: strings = strings.decode('utf-8')
|
||||
from cryptography.fernet import Fernet
|
||||
f = Fernet(key)
|
||||
result = f.decrypt(strings).decode('utf-8')
|
||||
return result
|
||||
except:
|
||||
print(get_error_info())
|
||||
#print(get_error_info())
|
||||
return strings
|
||||
|
||||
|
||||
@@ -1529,6 +1529,82 @@ def check_port_stat(port):
|
||||
if temp['local']: result +=2;
|
||||
return result;
|
||||
|
||||
|
||||
#同步时间
|
||||
def sync_date():
|
||||
tip_file = "/dev/shm/last_sync_time.pl"
|
||||
s_time = int(time.time())
|
||||
try:
|
||||
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')
|
||||
new_time = int(time_str)
|
||||
time_arr = time.localtime(new_time)
|
||||
date_str = time.strftime("%Y-%m-%d %H:%M:%S", time_arr)
|
||||
os.system('date -s "%s"' % date_str)
|
||||
writeFile(tip_file,str(s_time))
|
||||
return True
|
||||
except:
|
||||
if os.path.exists(tip_file): os.remove(tip_file)
|
||||
return False
|
||||
|
||||
|
||||
#重载模块
|
||||
def reload_mod(mod_name = None):
|
||||
#是否重载指定模块
|
||||
modules = []
|
||||
if mod_name:
|
||||
if type(mod_name) == str:
|
||||
mod_names = mod_name.split(',')
|
||||
|
||||
for mod_name in mod_names:
|
||||
if mod_name in sys.modules:
|
||||
print(mod_name)
|
||||
try:
|
||||
if sys.version_info[0] == 2:
|
||||
reload(sys.modules[mod_name])
|
||||
else:
|
||||
importlib.reload(sys.modules[mod_name])
|
||||
modules.append([mod_name,True])
|
||||
except:
|
||||
modules.append([mod_name,False])
|
||||
else:
|
||||
modules.append([mod_name,False])
|
||||
return modules
|
||||
|
||||
#重载所有模块
|
||||
for mod_name in sys.modules.keys():
|
||||
if mod_name in ['BTPanel']: continue
|
||||
f = getattr(sys.modules[mod_name],'__file__',None)
|
||||
if f:
|
||||
try:
|
||||
if f.find('panel/') == -1: continue
|
||||
if sys.version_info[0] == 2:
|
||||
reload(sys.modules[mod_name])
|
||||
else:
|
||||
importlib.reload(sys.modules[mod_name])
|
||||
modules.append([mod_name,True])
|
||||
except:
|
||||
modules.append([mod_name,False])
|
||||
return modules
|
||||
|
||||
|
||||
def de_hexb(data):
|
||||
if sys.version_info[0] != 2:
|
||||
if type(data) == str: data = data.encode('utf-8')
|
||||
pdata = base64.b64encode(data);
|
||||
if sys.version_info[0] != 2:
|
||||
if type(pdata) == str: pdata = pdata.encode('utf-8')
|
||||
return binascii.hexlify(pdata);
|
||||
|
||||
def en_hexb(data):
|
||||
if sys.version_info[0] != 2:
|
||||
if type(data) == str: data = data.encode('utf-8')
|
||||
result = base64.b64decode(binascii.unhexlify(data));
|
||||
if type(result) != str: result = result.decode('utf-8')
|
||||
return result;
|
||||
|
||||
#取通用对象
|
||||
class dict_obj:
|
||||
def __contains__(self, key):
|
||||
|
||||
+22
-1
@@ -116,6 +116,22 @@ class SiteDirAuth:
|
||||
if name in i.values() or site_dir == i["site_dir"]:
|
||||
return True
|
||||
|
||||
# 获取当前站点php版本
|
||||
def get_site_php_version(self,siteName):
|
||||
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"
|
||||
else:
|
||||
rep = "php-cgi-([0-9]{2,3})\.sock"
|
||||
tmp = re.search(rep,conf).groups()
|
||||
if tmp:
|
||||
return tmp[0]
|
||||
else:
|
||||
return ""
|
||||
except:
|
||||
return public.returnMsg(False, 'SITE_PHPVERSION_ERR_A22')
|
||||
|
||||
# 获取站点名
|
||||
def get_site_info(self,id):
|
||||
site_info = public.M('sites').where('id=?', (id,)).field('name,path').find()
|
||||
@@ -123,6 +139,10 @@ class SiteDirAuth:
|
||||
|
||||
# 设置独立认证文件
|
||||
def set_dir_auth_file(self,site_path,site_name,name,username,site_dir,auth_file):
|
||||
php_ver = self.get_site_php_version(site_name)
|
||||
php_conf = ""
|
||||
if php_ver:
|
||||
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":
|
||||
@@ -131,8 +151,9 @@ class SiteDirAuth:
|
||||
#AUTH_START
|
||||
auth_basic "Authorization";
|
||||
auth_basic_user_file %s;
|
||||
%s
|
||||
#AUTH_END
|
||||
}''' % (site_dir,auth_file)
|
||||
}''' % (site_dir,auth_file,php_conf)
|
||||
else:
|
||||
# 设置apache
|
||||
conf = '''<Directory "{site_path}{site_dir}">
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
import paramiko
|
||||
import json
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
import socket
|
||||
|
||||
sys.path.insert(0, '/www/server/panel/class/')
|
||||
import public
|
||||
from io import BytesIO, StringIO
|
||||
from BTPanel import session,socketio
|
||||
|
||||
class ssh_terminal:
|
||||
__log_type = 'aaPanel terminal'
|
||||
_coll_user = None
|
||||
_host = None
|
||||
_web_socket = None
|
||||
_ssh_info = None
|
||||
_ssh_socket = None
|
||||
_en_key = '4BbA7076e19H'
|
||||
_thread = None
|
||||
_my_terms = {}
|
||||
_room = "ssh_data"
|
||||
_send_last = False
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
def connect(self, ssh_info=None):
|
||||
if ssh_info: self._ssh_info = ssh_info
|
||||
if not self._host: self._host = self._ssh_info['host']
|
||||
# print('----------连接时的ssh_info--------------')
|
||||
if self._ssh_info['host'] in self._my_terms:
|
||||
if time.time() - self._my_terms[self._host].last_time < 86400:
|
||||
return True
|
||||
try:
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 262144)
|
||||
sock.connect((self._ssh_info['host'], int(self._ssh_info['port'])))
|
||||
except Exception as e:
|
||||
socketio.emit(self._room,"\rServer connection failed!\r")
|
||||
return False
|
||||
# 使用Transport连接
|
||||
p1 = paramiko.Transport(sock)
|
||||
p1.start_client()
|
||||
if not 'pkey' in self._ssh_info: self._ssh_info['pkey'] = None
|
||||
if not 'c_type' in self._ssh_info: self._ssh_info['c_type'] = None
|
||||
try:
|
||||
# 如果有pkey时则使用RSA私钥登录
|
||||
if self._ssh_info['pkey'] and self._ssh_info['c_type']:
|
||||
# print('------使用私钥登陆---------')
|
||||
# 将RSA私钥转换为io对象,然后生成rsa_key对象
|
||||
p_file = StringIO(self._ssh_info['pkey'])
|
||||
pkey = paramiko.RSAKey.from_private_key(p_file)
|
||||
p1.auth_publickey(username=self._ssh_info['username'].strip(), key=pkey)
|
||||
else:
|
||||
# print('-----------使用密码登陆-----------')
|
||||
p1.auth_password(username=self._ssh_info['username'].strip(), password=self._ssh_info['password'])
|
||||
except Exception as e:
|
||||
socketio.emit(self._room,"\rWrong user name or password!\r")
|
||||
p1.close()
|
||||
return False
|
||||
|
||||
self._my_terms[self._host] = public.dict_obj()
|
||||
self._my_terms[self._host].last_time = time.time()
|
||||
self._my_terms[self._host].connect_time = time.time()
|
||||
# 打开会话
|
||||
self._my_terms[self._host].tty = p1.open_session()
|
||||
# 获取终端对象
|
||||
self._my_terms[self._host].tty.get_pty(term='xterm', width=100, height=34)
|
||||
self._my_terms[self._host].tty.invoke_shell()
|
||||
# 记录登陆记录
|
||||
#public.M('ssh_records').add('coll_user,ssh_user,host,cmd,addtime', (self._coll_user, self._ssh_info['username'], self._ssh_info['host'], 'login', int(time.time())))
|
||||
#print("登录成功")
|
||||
self._my_terms[self._host].last_send = []
|
||||
self._send_last = True
|
||||
return True
|
||||
|
||||
def resize(self, data):
|
||||
try:
|
||||
data = json.loads(data)
|
||||
self._my_terms[self._host].tty.resize_pty(width=data['width'], height=data['height'], width_pixels=data['width_px'], height_pixels=data['height_px'])
|
||||
return True
|
||||
except:
|
||||
print(public.get_error_info())
|
||||
return False
|
||||
|
||||
def send(self,c_data):
|
||||
try:
|
||||
if not c_data: return
|
||||
if not self._thread:
|
||||
s_file = '/www/server/panel/config/t_info.json'
|
||||
ssh_info = None
|
||||
if os.path.exists(s_file):
|
||||
ssh_info = json.loads(public.en_hexb(public.readFile(s_file)))
|
||||
|
||||
if not 'host' in c_data:
|
||||
host = "127.0.0.1"
|
||||
if ssh_info:
|
||||
c_data = ssh_info
|
||||
host = c_data['host']
|
||||
else:
|
||||
host = c_data['host']
|
||||
if not host:
|
||||
if not ssh_info: return socketio.emit(self._room,"\rWrong user name or password!\r")
|
||||
c_data = ssh_info
|
||||
key = 'ssh_' + host
|
||||
if 'password' in c_data:
|
||||
session[key] = c_data
|
||||
if not key in session: return socketio.emit(self._room,"\rWrong user name or password!\r")
|
||||
result = self.run(session[key])
|
||||
else:
|
||||
if len(c_data) > 10:
|
||||
if c_data == 'new_bt_terminal':
|
||||
if not self._send_last: self.last_send()
|
||||
self._send_last = False
|
||||
return
|
||||
if c_data.find('resize_pty') != -1:
|
||||
if self.resize(c_data): return
|
||||
if type(c_data) == dict: return
|
||||
if self._host in self._my_terms:
|
||||
self._my_terms[self._host].last_time = time.time()
|
||||
self._my_terms[self._host].tty.send(c_data)
|
||||
else:
|
||||
return
|
||||
except:
|
||||
self.close()
|
||||
socketio.emit(self._room,'\rConnection failure!\r')
|
||||
print(public.get_error_info())
|
||||
|
||||
def recv(self):
|
||||
try:
|
||||
while True:
|
||||
data = self._my_terms[self._host].tty.recv(1024)
|
||||
if not data:
|
||||
self.close()
|
||||
socketio.emit(self._room,"\rThe connection has been disconnected and pressing Enter will attempt to reconnect!\r")
|
||||
return
|
||||
try:
|
||||
result = data.decode()
|
||||
except:
|
||||
result = str(data)
|
||||
if not result: continue
|
||||
self.set_last_send(result)
|
||||
socketio.emit(self._room,result)
|
||||
except:
|
||||
print(public.get_error_info())
|
||||
|
||||
def set_last_send(self,result):
|
||||
last_size = 1024
|
||||
if not 'last_send' in self._my_terms[self._host]:
|
||||
self._my_terms[self._host].last_send = []
|
||||
|
||||
self._my_terms[self._host].last_send.append(result)
|
||||
last_len = len(self._my_terms[self._host].last_send)
|
||||
if last_len > last_size:
|
||||
self._my_terms[self._host].last_send = self._my_terms[self._host].last_send[last_len-last_size:]
|
||||
|
||||
def not_send(self):
|
||||
if 'not_send' in self._my_terms[self._host]:
|
||||
if self._my_terms[self._host].not_send:
|
||||
socketio.emit(self._room,self._my_terms[self._host].not_send)
|
||||
self._my_terms[self._host].not_send = ""
|
||||
|
||||
def last_send(self):
|
||||
time.sleep(0.3)
|
||||
if 'last_send' in self._my_terms[self._host]:
|
||||
for d in self._my_terms[self._host].last_send:
|
||||
socketio.emit(self._room,d)
|
||||
|
||||
def close(self):
|
||||
try:
|
||||
self._my_terms[self._host].tty.close()
|
||||
except:pass
|
||||
if self._host in self._my_terms:
|
||||
del self._my_terms[self._host]
|
||||
self._thread = None
|
||||
|
||||
def run(self, ssh_info=None):
|
||||
if not ssh_info:
|
||||
return
|
||||
if 'id' in ssh_info:
|
||||
self._ssh_info = self.get_server_ssh_info(ssh_info)
|
||||
else:
|
||||
self._ssh_info = ssh_info
|
||||
result = self.connect()
|
||||
if result and not self._thread:
|
||||
self._thread = socketio.start_background_task(target=self.recv)
|
||||
return result
|
||||
+12
-4
@@ -217,6 +217,10 @@ class system:
|
||||
data['time'] = self.GetBootTime();
|
||||
data['system'] = self.GetSystemVersion();
|
||||
data['isuser'] = public.M('users').where('username=?',('admin',)).count();
|
||||
try:
|
||||
data['isport'] = public.GetHost(True) == '8888'
|
||||
except:data['isport'] = False
|
||||
|
||||
data['version'] = session['version'];
|
||||
return data
|
||||
|
||||
@@ -272,10 +276,14 @@ class system:
|
||||
time.sleep(0.5)
|
||||
#取CPU信息
|
||||
cpuCount = psutil.cpu_count()
|
||||
cpuNum = psutil.cpu_count(logical=False)
|
||||
c_tmp = public.readFile('/proc/cpuinfo')
|
||||
d_tmp = re.findall("physical id.+",c_tmp)
|
||||
cpuW = len(set(d_tmp))
|
||||
used = self.get_cpu_percent()
|
||||
used_all = psutil.cpu_percent(percpu=True)
|
||||
cpu_name = public.getCpuType()
|
||||
return used,cpuCount,used_all,cpu_name
|
||||
cpu_name = public.getCpuType() + " * {}".format(cpuW)
|
||||
return used,cpuCount,used_all,cpu_name,cpuNum,cpuW
|
||||
|
||||
|
||||
def GetCpuInfo_new(self):
|
||||
@@ -336,7 +344,7 @@ class system:
|
||||
tmp['size'] = psutil.disk_usage(disk[1])
|
||||
diskInfo.append(tmp)
|
||||
return diskInfo
|
||||
|
||||
|
||||
def GetDiskInfo2(self):
|
||||
#取磁盘分区信息
|
||||
temp = public.ExecShell("df -h -P|grep '/'|grep -v tmpfs")[0];
|
||||
@@ -363,7 +371,7 @@ class system:
|
||||
arr['inodes'] = [inodes[1],inodes[2],inodes[3],inodes[4]]
|
||||
diskInfo.append(arr);
|
||||
except Exception as ex:
|
||||
public.WriteLog('Get info',str(ex))
|
||||
public.WriteLog('信息获取',str(ex))
|
||||
continue
|
||||
return diskInfo;
|
||||
|
||||
|
||||
+5
-2
@@ -39,6 +39,7 @@ class userlogin:
|
||||
return public.returnJson(False,'LOGIN_USER_ERR',(str(num),)),json_header
|
||||
_key_file = "/www/server/panel/data/two_step_auth.txt"
|
||||
if hasattr(post,'vcode'):
|
||||
if self.limit_address('?',v="vcode") < 1: return public.returnJson(False,'您多次验证失败,禁止10分钟'),json_header
|
||||
import pyotp
|
||||
secret_key = public.readFile(_key_file)
|
||||
if not secret_key:
|
||||
@@ -46,8 +47,10 @@ class userlogin:
|
||||
t = pyotp.TOTP(secret_key)
|
||||
result = t.verify(post.vcode)
|
||||
if not result:
|
||||
num = self.limit_address('++',v="vcode")
|
||||
return public.returnJson(False, 'Invalid Verification code. You have [{}] times left to try!'.format(num)), json_header
|
||||
if public.sync_date(): result = t.verify(post.vcode)
|
||||
if not result:
|
||||
num = self.limit_address('++',v="vcode")
|
||||
return public.returnJson(False, 'Invalid Verification code. You have [{}] times left to try!'.format(num)), json_header
|
||||
now = int(time.time())
|
||||
public.writeFile("/www/server/panel/data/dont_vcode_ip.txt",json.dumps({"client_ip":public.GetClientIp(),"add_time":now}))
|
||||
self.limit_address('--',v="vcode")
|
||||
|
||||
+17
-9
@@ -1,8 +1,11 @@
|
||||
import os,time,sys,ssl
|
||||
sys.path.insert(0,'/www/server/panel/class')
|
||||
import public
|
||||
bt_port = public.readFile('data/port.pl')
|
||||
if bt_port: bt_port.strip()
|
||||
import os
|
||||
f = open('data/port.pl','r')
|
||||
bt_port = f.read()
|
||||
f.close()
|
||||
if bt_port:
|
||||
bt_port.strip()
|
||||
else:
|
||||
bt_port = 8888
|
||||
bind = []
|
||||
if os.path.exists('data/ipv6.pl'):
|
||||
bind.append('[0:0:0:0:0:0:0:0]:%s' % bt_port)
|
||||
@@ -10,9 +13,14 @@ else:
|
||||
bind.append('0.0.0.0:%s' % bt_port)
|
||||
|
||||
w_num = 'data/workers.pl'
|
||||
if not os.path.exists(w_num): public.writeFile(w_num,'1')
|
||||
workers = int(public.readFile(w_num))
|
||||
if not workers: workers = 1
|
||||
workers = 1
|
||||
if os.path.exists(w_num):
|
||||
f = open(w_num,'r')
|
||||
w_str = f.read()
|
||||
f.close()
|
||||
if w_str:
|
||||
workers = int(w_str.strip())
|
||||
|
||||
threads = 3
|
||||
backlog = 512
|
||||
daemon = True
|
||||
@@ -28,7 +36,7 @@ graceful_timeout=0
|
||||
loglevel = 'info'
|
||||
if debug: loglevel = 'debug'
|
||||
errorlog = chdir + '/logs/error.log'
|
||||
accesslog = chdir + '/logs/access.log'
|
||||
accesslog = chdir + '/logs/error.log'
|
||||
pidfile = chdir + '/logs/panel.pid'
|
||||
if os.path.exists(chdir + '/data/ssl.pl'):
|
||||
certfile = 'ssl/certificate.pem'
|
||||
|
||||
Reference in New Issue
Block a user