mirror of
https://github.com/aaPanel/aaPanel.git
synced 2026-08-17 21:25:47 +02:00
update 6.2.0
This commit is contained in:
+92
-55
@@ -64,7 +64,7 @@ app.config['SESSION_PERMANENT'] = True
|
||||
app.config['SESSION_USE_SIGNER'] = True
|
||||
app.config['SESSION_KEY_PREFIX'] = 'BT_:'
|
||||
app.config['SESSION_COOKIE_NAME'] = "BT_PANEL_6"
|
||||
app.config['PERMANENT_SESSION_LIFETIME'] = 86400 * 7
|
||||
app.config['PERMANENT_SESSION_LIFETIME'] = 86400
|
||||
Session(app)
|
||||
|
||||
if s_sqlite: sdb.create_all()
|
||||
@@ -81,7 +81,7 @@ cache.set('p_token','bmac_' + public.Md5(public.get_mac_address()))
|
||||
admin_path_file = 'data/admin_path.pl'
|
||||
admin_path = '/'
|
||||
if os.path.exists(admin_path_file): admin_path = public.readFile(admin_path_file).strip()
|
||||
admin_path_checks = ['/','/san','/monitor','/abnormal','/close','/task','/login','/config','/site','/sites','ftp','/public','/database','/data','/download_file','/control','/crontab','/firewall','/files','config','/soft','/ajax','/system','/panel_data','/code','/ssl','/plugin','/wxapp','/hook','/safe','/yield','/downloadApi','/pluginApi','/auth','/download','/cloud','/webssh','/connect_event','/panel']
|
||||
admin_path_checks = ['/','/san','/bak','/monitor','/abnormal','/close','/task','/login','/config','/site','/sites','ftp','/public','/database','/data','/download_file','/control','/crontab','/firewall','/files','config','/soft','/ajax','/system','/panel_data','/code','/ssl','/plugin','/wxapp','/hook','/safe','/yield','/downloadApi','/pluginApi','/auth','/download','/cloud','/webssh','/connect_event','/panel']
|
||||
if admin_path in admin_path_checks: admin_path = '/bt'
|
||||
|
||||
@app.route('/service_status',methods = method_get)
|
||||
@@ -90,7 +90,17 @@ def service_status():
|
||||
|
||||
|
||||
@app.before_request
|
||||
def basic_auth_check():
|
||||
def request_check():
|
||||
if not request.path in ['/safe','/hook','/public']:
|
||||
ip_check = public.check_ip_panel()
|
||||
if ip_check: return ip_check
|
||||
domain_check = public.check_domain_panel()
|
||||
if domain_check: return domain_check
|
||||
if public.is_local():
|
||||
not_networks = ['uninstall_plugin','install_plugin','UpdatePanel']
|
||||
if request.args.get('action') in not_networks:
|
||||
return public.returnJson(False,'This feature is not available in offline mode!'),json_header
|
||||
|
||||
if app.config['BASIC_AUTH_OPEN']:
|
||||
if request.path in ['/public','/download']: return;
|
||||
auth = request.authorization
|
||||
@@ -101,10 +111,16 @@ def basic_auth_check():
|
||||
return send_authenticated()
|
||||
|
||||
|
||||
@app.teardown_request
|
||||
def request_end(reques = None):
|
||||
not_acts = ['GetTaskSpeed','GetNetWork','check_pay_status','get_re_order_status','get_order_stat']
|
||||
key = request.args.get('action')
|
||||
if not key in not_acts and request.full_path.find('/static/') == -1: public.write_request_log()
|
||||
|
||||
def send_authenticated():
|
||||
global local_ip
|
||||
if not local_ip: local_ip = public.GetLocalIp()
|
||||
return Response('', 401,{'WWW-Authenticate': 'Basic realm="%s"' % local_ip})
|
||||
return Response('', 401,{'WWW-Authenticate': 'Basic realm="%s"' % local_ip.strip()})
|
||||
|
||||
@app.route('/',methods=method_all)
|
||||
def home():
|
||||
@@ -117,6 +133,7 @@ def home():
|
||||
data['databaseCount'] = public.M('databases').count()
|
||||
data['lan'] = public.GetLan('index')
|
||||
data['724'] = public.format_date("%m%d") == '0724'
|
||||
public.auto_backup_panel()
|
||||
return render_template( 'index.html',data = data)
|
||||
|
||||
@app.route('/close',methods=method_get)
|
||||
@@ -303,14 +320,14 @@ def firewall(pdata = None):
|
||||
defs = ('GetList','AddDropAddress','DelDropAddress','FirewallReload','SetFirewallStatus','AddAcceptPort','DelAcceptPort','SetSshStatus','SetPing','SetSshPort','GetSshInfo')
|
||||
return publicObject(firewallObject,defs,None,pdata);
|
||||
|
||||
#@app.route('/firewall_new',methods=method_all)
|
||||
@app.route('/firewall_new',methods=method_all)
|
||||
def firewall_new(pdata = None):
|
||||
comReturn = comm.local()
|
||||
if comReturn: return comReturn
|
||||
if request.method == method_get[0] and not pdata:
|
||||
data = {}
|
||||
data['lan'] = public.GetLan('firewall')
|
||||
return render_template( 'firewall.html',data=data)
|
||||
return render_template( 'firewall_new.html',data=data)
|
||||
import firewall_new
|
||||
firewallObject = firewall_new.firewalls()
|
||||
defs = ('GetList','AddDropAddress','DelDropAddress','FirewallReload','SetFirewallStatus','AddAcceptPort','DelAcceptPort','SetSshStatus','SetPing','SetSshPort','GetSshInfo','AddSpecifiesIp','DelSpecifiesIp')
|
||||
@@ -337,6 +354,18 @@ def san_baseline(pdata=None):
|
||||
return publicObject(dataObject, defs, None, pdata)
|
||||
|
||||
|
||||
@app.route('/bak', methods=method_all)
|
||||
def backup_bak(pdata=None):
|
||||
comReturn = comm.local()
|
||||
if comReturn: return comReturn
|
||||
import backup_bak
|
||||
dataObject = backup_bak.backup_bak()
|
||||
defs = ('get_sites', 'get_databases', 'backup_database', 'backup_site', 'backup_path', 'get_database_progress',
|
||||
'get_site_progress', 'down','get_down_progress','download_path','backup_site_all','get_all_site_progress','backup_date_all','get_all_date_progress')
|
||||
return publicObject(dataObject, defs, None, pdata)
|
||||
|
||||
|
||||
|
||||
@app.route('/abnormal', methods=method_all)
|
||||
def abnormal(pdata=None):
|
||||
comReturn = comm.local()
|
||||
@@ -357,7 +386,7 @@ def files(pdata = None):
|
||||
import files
|
||||
filesObject = files.files()
|
||||
defs = ('CheckExistsFiles','GetExecLog','GetSearch','ExecShell','GetExecShellMsg','UploadFile','GetDir','CreateFile','CreateDir','DeleteDir','DeleteFile',
|
||||
'CopyFile','CopyDir','MvFile','GetFileBody','SaveFileBody','Zip','UnZip','SearchFiles','upload',
|
||||
'CopyFile','CopyDir','MvFile','GetFileBody','SaveFileBody','Zip','UnZip','SearchFiles','upload','read_history',
|
||||
'GetFileAccess','SetFileAccess','GetDirSize','SetBatchData','BatchPaste','install_rar','get_path_size',
|
||||
'DownloadFile','GetTaskSpeed','CloseLogs','InstallSoft','UninstallSoft','SaveTmpFile','GetTmpFile',
|
||||
'RemoveTask','ActionTask','Re_Recycle_bin','Get_Recycle_bin','Del_Recycle_bin','Close_Recycle_bin','Recycle_bin')
|
||||
@@ -416,9 +445,11 @@ def config(pdata = None):
|
||||
if data['basic_auth']['open']: data['basic_auth']['value'] = public.GetMsg("OPEN")
|
||||
data['debug'] = ''
|
||||
if app.config['DEBUG']: data['debug'] = 'checked'
|
||||
data['is_local'] = ''
|
||||
if public.is_local(): data['is_local'] = 'checked'
|
||||
return render_template( 'config.html',data=data)
|
||||
import config
|
||||
defs = ('get_cert_source','set_debug','get_panel_error_logs','clean_panel_error_logs','get_basic_auth_stat','set_basic_auth','get_cli_php_version','get_tmp_token','set_cli_php_version','DelOldSession', 'GetSessionCount', 'SetSessionConf', 'GetSessionConf','get_ipv6_listen','set_ipv6_status','GetApacheValue','SetApacheValue','GetNginxValue','SetNginxValue','get_token','set_token','set_admin_path','is_pro','get_php_config','get_config','SavePanelSSL','GetPanelSSL','GetPHPConf','SetPHPConf','GetPanelList','AddPanelInfo','SetPanelInfo','DelPanelInfo','ClickPanelInfo','SetPanelSSL','SetTemplates','Set502','setPassword','setUsername','setPanel','setPathInfo','setPHPMaxSize','getFpmConfig','setFpmConfig','setPHPMaxTime','syncDate','setPHPDisable','SetControl','ClosePanel','AutoUpdatePanel','SetPanelLock')
|
||||
defs = ('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)
|
||||
@@ -517,8 +548,16 @@ def plugin(pdata = None):
|
||||
def panel_public():
|
||||
get = get_input();
|
||||
get.client_ip = public.GetClientIp();
|
||||
if not hasattr(get,'name'): get.name = ''
|
||||
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']:
|
||||
if get.fun in ['scan_login', 'login_qrcode', 'set_login', 'is_scan_ok', 'blind','static']:
|
||||
if get.fun == 'static':
|
||||
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)
|
||||
if not os.path.exists(s_file): return abort(404)
|
||||
return send_file(s_file, conditional=True, add_etags=True)
|
||||
|
||||
#检查是否验证过安全入口
|
||||
if get.fun in ['login_qrcode','is_scan_ok']:
|
||||
global admin_check_auth,admin_path,route_path,admin_path_file
|
||||
@@ -555,28 +594,9 @@ def send_favicon():
|
||||
@app.route('/<name>/<fun>',methods=method_all)
|
||||
@app.route('/<name>/<fun>/<path:stype>',methods=method_all)
|
||||
def panel_other(name=None,fun = None,stype=None):
|
||||
#插件公共动态路由 <name: 插件名称, fun: 被访问的插件方法名, stype:fun=static时则为文件相对于插件static目录下的路径> 访问方式:http://面板地址:端口/插件名称/插件方法.响应类型(html|json)
|
||||
'''
|
||||
插件静态文件存储目录: static (允许多级目录,请不要将重要文件放在静态目录),访问方式:http://面板地址:端口/插件名称/static/相对于static的文件路径 如:http://demo.cn:8888/demo/static/js/test.js
|
||||
插件模板文件存储目录: templates (请不要在里面创建二级目录) 使用模板方法: http://demo.cn:8888/demo/get_logs.html
|
||||
插件模板文件格式:方法名.html (支持jinja2语法,但无法使用extends语句),请在被访问的方法中返回一个dict,它将被当作data参数传入到模板变量
|
||||
响应JSON数据: 示例: http://demo.cn:8888/demo/get_logs.json 注意:此处会将插件方法中返回的数据自动转换成JSON字符串响应
|
||||
直接响应: 示例:http://demo.cn:8888/demo/get_logs ,此时直接响应插件方法返回的数据,注意: 支持 int、float、string、list、redirect对象
|
||||
'''
|
||||
|
||||
#前置准备
|
||||
|
||||
if not name: name = 'coll'
|
||||
if not public.path_safe_check("%s/%s/%s" % (name,fun,stype)): return abort(404)
|
||||
|
||||
#是否响应面板默认静态文件
|
||||
if name == 'static':
|
||||
s_file = '/www/server/panel/BTPanel/static/' + fun + '/' + stype
|
||||
if s_file.find('..') != -1 or s_file.find('./') != -1: return abort(404)
|
||||
if not os.path.exists(s_file): return abort(404)
|
||||
return send_file(s_file,conditional=True,add_etags=True)
|
||||
|
||||
if name.find('./') != -1 or not re.match("^[\w-]+$",name): return public.returnJson(False,public.GetMsg("REQUEST_ERR")),json_header
|
||||
if name.find('./') != -1 or not re.match("^[\w-]+$",name): return abort(404)
|
||||
if not name: return public.returnJson(False,public.GetMsg("PLUGIN_INPUT_A")),json_header
|
||||
p_path = '/www/server/panel/plugin/' + name
|
||||
if not os.path.exists(p_path): return abort(404)
|
||||
@@ -584,10 +604,12 @@ def panel_other(name=None,fun = None,stype=None):
|
||||
|
||||
#是否响插件应静态文件
|
||||
if fun == 'static':
|
||||
if stype.find('./') != -1 or not os.path.exists(p_path + '/static'): return public.returnJson(False,public.GetMsg("REQUEST_ERR")),json_header
|
||||
if stype.find('./') != -1 or not os.path.exists(p_path + '/static'): return abort(404)
|
||||
s_file = p_path + '/static/' + stype
|
||||
if s_file.find('..') != -1: return abort(404)
|
||||
if not os.path.exists(s_file): return public.returnJson(False,'The specified file does not exist ['+stype+']'),json_header
|
||||
if not re.match("^[\w\./-]+$",s_file): return abort(404)
|
||||
if not public.path_safe_check(s_file): return abort(404)
|
||||
if not os.path.exists(s_file): return abort(404)
|
||||
return send_file(s_file,conditional=True,add_etags=True)
|
||||
|
||||
#准备参数
|
||||
@@ -603,26 +625,29 @@ def panel_other(name=None,fun = None,stype=None):
|
||||
|
||||
#初始化插件对象
|
||||
try:
|
||||
sys.path.append(p_path);
|
||||
plugin_main = __import__(name+'_main')
|
||||
try:
|
||||
if sys.version_info[0] == 2:
|
||||
reload(plugin_main)
|
||||
else:
|
||||
from imp import reload
|
||||
reload(plugin_main)
|
||||
except:pass
|
||||
plu = eval('plugin_main.' + name + '_main()')
|
||||
if not hasattr(plu, fun): return public.returnJson(False, public.GetMsg("SPECIFY_METHOD")), json_header
|
||||
is_php = os.path.exists(p_path + '/index.php')
|
||||
if not is_php:
|
||||
sys.path.append(p_path);
|
||||
plugin_main = __import__(name+'_main')
|
||||
try:
|
||||
if sys.version_info[0] == 2:
|
||||
reload(plugin_main)
|
||||
else:
|
||||
from imp import reload
|
||||
reload(plugin_main)
|
||||
except:pass
|
||||
plu = eval('plugin_main.' + name + '_main()')
|
||||
if not hasattr(plu,fun): return public.returnJson(False,'SPECIFY_METHOD'),json_header
|
||||
|
||||
#检查访问权限
|
||||
comReturn = comm.local()
|
||||
if comReturn:
|
||||
if not hasattr(plu, '_check'): return public.returnJson(False, public.GetMsg("SPECIFY_PLUG_ERR")), json_header
|
||||
checks = plu._check(args)
|
||||
r_type = type(checks)
|
||||
if r_type == Response: return checks
|
||||
if r_type != bool or not checks: return public.getJson(checks),json_header
|
||||
if not is_php:
|
||||
if not hasattr(plu,'_check'): return public.returnJson(False,'SPECIFY_PLUG_ERR'),json_header
|
||||
checks = plu._check(args)
|
||||
r_type = type(checks)
|
||||
if r_type == Response: return checks
|
||||
if r_type != bool or not checks: return public.getJson(checks),json_header
|
||||
|
||||
#初始化面板数据
|
||||
comm.setSession()
|
||||
@@ -637,7 +662,14 @@ def panel_other(name=None,fun = None,stype=None):
|
||||
return public.returnMsg(False,public.to_string([24744, 26410, 36141, 20080, 91, 37, 115, 93, 25110, 25480, 26435, 24050, 21040, 26399, 33]) % (plugins.get_title_byname(args),))
|
||||
|
||||
#执行插件方法
|
||||
data = eval('plu.'+fun+'(args)')
|
||||
if not is_php:
|
||||
data = eval('plu.'+fun+'(args)')
|
||||
else:
|
||||
import panelPHP
|
||||
args.s = fun
|
||||
args.name = name
|
||||
data = panelPHP.panelPHP(name).exec_php_script(args)
|
||||
|
||||
r_type = type(data)
|
||||
if r_type == Response: return data
|
||||
|
||||
@@ -785,6 +817,7 @@ def download():
|
||||
filename = request.args.get('filename')
|
||||
if not filename: return public.ReturnJson(False,"INIT_ARGS_ERR"),json_header
|
||||
if filename in ['alioss','qiniu','upyun','txcos','ftp']: return panel_cloud()
|
||||
if filename in ['gdrive','gcloud_storage']: return "Google storage products do not currently support downloads"
|
||||
if not os.path.exists(filename): return public.ReturnJson(False,"FILE_NOT_EXISTS"),json_header
|
||||
mimetype = "application/octet-stream"
|
||||
extName = filename.split('.')[-1]
|
||||
@@ -943,11 +976,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();
|
||||
not_acts = ['GetTaskSpeed','GetNetWork','check_pay_status','get_re_order_status','get_order_stat']
|
||||
|
||||
for key in defs:
|
||||
if key == get.action:
|
||||
fun = 'toObject.'+key+'(get)'
|
||||
if not key in not_acts: public.write_request_log()
|
||||
if hasattr(get,'html') or hasattr(get,'s_module'):
|
||||
return eval(fun)
|
||||
else:
|
||||
@@ -967,10 +999,11 @@ def check_login(http_token=None):
|
||||
|
||||
def get_pd():
|
||||
tmp = -1
|
||||
#tmp1 = cache.get(public.to_string([112, 108, 117, 103, 105, 110, 95, 115, 111, 102, 116, 95, 108, 105, 115, 116]))
|
||||
#if not tmp1:
|
||||
import panelPlugin
|
||||
tmp1 = panelPlugin.panelPlugin().get_cloud_list()
|
||||
try:
|
||||
import panelPlugin
|
||||
tmp1 = panelPlugin.panelPlugin().get_cloud_list()
|
||||
except:
|
||||
tmp1 = None
|
||||
if tmp1:
|
||||
tmp = tmp1[public.to_string([112,114,111])]
|
||||
else:
|
||||
@@ -1018,9 +1051,13 @@ def notfound(e):
|
||||
|
||||
@app.errorhandler(500)
|
||||
def internalerror(e):
|
||||
#if str(e).find('Permanent Redirect') != -1: return e
|
||||
errorStr = public.ReadFile('./BTPanel/templates/' + public.GetConfigValue('template') + '/error.html')
|
||||
try:
|
||||
errorStr = errorStr.format(public.getMsg('PAGE_ERR_500_TITLE'),public.getMsg('PAGE_ERR_500_H1'),public.getMsg('PAGE_ERR_500_P1'),public.getMsg('NAME'),public.getMsg('PAGE_ERR_HELP'))
|
||||
if not app.config['DEBUG']:
|
||||
errorStr = errorStr.format(public.getMsg('PAGE_ERR_500_TITLE'),public.getMsg('PAGE_ERR_500_H1'),public.getMsg('PAGE_ERR_500_P1'),public.getMsg('NAME'),public.getMsg('PAGE_ERR_HELP'))
|
||||
else:
|
||||
errorStr = errorStr.format(public.getMsg('PAGE_ERR_500_TITLE'),str(e),'<pre>'+public.get_error_info() + '</pre>','The above debugging information is only displayed in developer mode','Version: ' + public.version())
|
||||
except IndexError:pass
|
||||
return errorStr,500
|
||||
|
||||
|
||||
+381
-14
@@ -1368,27 +1368,25 @@ html .menu .menu_exit:hover {
|
||||
left: 0
|
||||
}
|
||||
|
||||
.left,
|
||||
.right {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: #ccc;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0
|
||||
}
|
||||
/*.left,*/
|
||||
/*.right {*/
|
||||
/* width: 100px;*/
|
||||
/* height: 100px;*/
|
||||
/* background: #ccc;*/
|
||||
/* border-radius: 50%;*/
|
||||
/* position: absolute;*/
|
||||
/* top: 0;*/
|
||||
/* left: 0*/
|
||||
/*}*/
|
||||
|
||||
.pie_right,
|
||||
.right {
|
||||
.pie_right {
|
||||
clip: rect(0, auto, auto, 50px);
|
||||
transition: transform 1s ease-in 0s;
|
||||
-webkit-transition: -webkit-transform 1s ease-in 0s;
|
||||
-moz-transition: -moz-transform 1s ease-in 0s
|
||||
}
|
||||
|
||||
.pie_left,
|
||||
.left {
|
||||
.pie_left {
|
||||
clip: rect(0, 50px, auto, 0);
|
||||
transition: transform .4s ease-in 1s;
|
||||
-webkit-transition: -webkit-transform .4s ease-in 1s;
|
||||
@@ -2308,6 +2306,11 @@ html .menu .menu_exit:hover {
|
||||
.setting-con .btn_tips{
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
z-index: 10
|
||||
}
|
||||
|
||||
.setting-con p .set-info {
|
||||
margin-left: 20px
|
||||
}
|
||||
|
||||
.set-submit {
|
||||
@@ -5223,3 +5226,367 @@ select[disabled]{
|
||||
.ssl_cert_from>.line .line .info-r{
|
||||
margin-bottom:0;
|
||||
}
|
||||
|
||||
#ace_conter{
|
||||
background: #444;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
/*background: url('/static/img/resize_corner.png') no-repeat;*/
|
||||
}
|
||||
.ace_overall {
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
.ace_catalogue {
|
||||
display: none;
|
||||
float: left;
|
||||
width: 250px;
|
||||
position: absolute;
|
||||
z-index: 99;
|
||||
height: 45px;
|
||||
background: #333;
|
||||
}
|
||||
.ace_catalogue_sidebar {
|
||||
display: none;
|
||||
height: 100%;
|
||||
width: 10px;
|
||||
background: #444;
|
||||
cursor: col-resize;
|
||||
position: absolute;
|
||||
left: 240px;
|
||||
top: 90px;
|
||||
}
|
||||
.ace_catalogue_sidebar img {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 10px;
|
||||
margin-top: -20px;
|
||||
}
|
||||
.ace_catalogue_title {
|
||||
height: 45px;
|
||||
line-height: 45px;
|
||||
padding-left: 20px;
|
||||
color: #fff;
|
||||
}
|
||||
.ace_conter_menu {
|
||||
height: 40px;
|
||||
position: relative;
|
||||
background: #292929;
|
||||
overflow: auto;
|
||||
}
|
||||
.ace_editor {
|
||||
font-size: 15px;
|
||||
}
|
||||
.ace_editors {
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
right: 0;
|
||||
bottom: 35px;
|
||||
left: 0px;
|
||||
font-size: 13px;
|
||||
display: none;
|
||||
}
|
||||
.ace_editors.active {
|
||||
display: block;
|
||||
}
|
||||
.ace_header {
|
||||
position: relative;
|
||||
height: 35px;
|
||||
background: #565656;
|
||||
/* transition: all 500ms; */
|
||||
}
|
||||
.ace_header span {
|
||||
float: left;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
padding: 0 15px;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
border-right: 1px solid #4c4c4c;
|
||||
cursor: pointer;
|
||||
}
|
||||
.ace_header span .glyphicon {
|
||||
margin-right: 5px;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
.ace_header span:hover {
|
||||
background: #2f2f2f;
|
||||
}
|
||||
.ace_header .pull-down{
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
right: 0;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
padding: 0 14px;
|
||||
font-size: 15px;
|
||||
color: #fff;
|
||||
background: #292929;
|
||||
cursor: pointer;
|
||||
}
|
||||
.ace_editor_main {
|
||||
position: relative;
|
||||
background: #444;
|
||||
}
|
||||
|
||||
.ace_editor_main_storey {
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
background: linear-gradient(rgba(0, 0, 0, 0.3), rgba(255, 255, 255, 0));
|
||||
}
|
||||
.ace_conter_menu .item {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
font-size: 15px;
|
||||
max-width: 350px;
|
||||
padding: 0 35px 0 10px;
|
||||
height: 40px;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
color: #ececec;
|
||||
cursor: pointer;
|
||||
border-right: 1px solid #191919;
|
||||
}
|
||||
.ace_conter_menu .item:hover {
|
||||
background: #313131;
|
||||
}
|
||||
.ace_conter_menu .item:hover .icon-tool {
|
||||
display: block;
|
||||
}
|
||||
.ace_conter_menu .item.active {
|
||||
color: #fff;
|
||||
background: #404040;
|
||||
border-bottom: 2px solid #20a53a;
|
||||
}
|
||||
.ace_conter_menu .item.active .icon-tool {
|
||||
display: block;
|
||||
}
|
||||
.ace_conter_menu .item span {
|
||||
display: inline-block;
|
||||
line-height: 40px;
|
||||
height: 40px;
|
||||
margin: 0 10px 0 0;
|
||||
}
|
||||
.ace_conter_menu .item .icon_file {
|
||||
color: #ff9800;
|
||||
font-weight: 500;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.ace_conter_menu .item .icon-tool.fa-circle {
|
||||
display: block;
|
||||
}
|
||||
.ace_conter_menu .item .icon-tool {
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
top: 13px;
|
||||
transition: all 1000ms;
|
||||
font-size: 14px;
|
||||
}
|
||||
.ace_editor_add {
|
||||
float: left;
|
||||
height: 40px;
|
||||
padding: 9px 15px;
|
||||
font-size: 17px;
|
||||
color: #ddd;
|
||||
cursor: pointer;
|
||||
transition: all 500ms;
|
||||
}
|
||||
.ace_editor_add:hover {
|
||||
background-color: #505050
|
||||
}
|
||||
/* 关闭视图-开始 */
|
||||
.ace-clear-form {
|
||||
padding-top: 25px;
|
||||
}
|
||||
.ace-clear-form .line {
|
||||
margin-left: 20px;
|
||||
}
|
||||
.clear-title {
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
}
|
||||
.clear-tips {
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
}
|
||||
.clear-tips,
|
||||
.clear-title {
|
||||
padding-left: 80px;
|
||||
}
|
||||
.clear-icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background-image: url(/static/layer/skin/default/icon.png);
|
||||
background-position: 0 0;
|
||||
position: absolute;
|
||||
left: 30px;
|
||||
top: 28px;
|
||||
}
|
||||
/* 取消按钮组 */
|
||||
.ace-clear-btn {
|
||||
padding: 8px 20px 15px;
|
||||
text-align: right;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.ace-clear-btn .btn-default:hover {
|
||||
color: #fff;
|
||||
background-color: #d9534f;
|
||||
border-color: #d43f3a;
|
||||
}
|
||||
/* 关闭视图-结束 */
|
||||
.ace_conter_toolbar {
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
bottom: 0;
|
||||
text-align: right;
|
||||
margin-right: 15px;
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
background: #444;
|
||||
font-size: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ace_conter_toolbar .pull-left,
|
||||
.ace_conter_toolbar .pull-right{
|
||||
height: 35px;
|
||||
}
|
||||
.ace_conter_toolbar .pull-left span ,
|
||||
.ace_conter_toolbar .pull-right span {
|
||||
color: #fff;
|
||||
display: inline-block;
|
||||
border-right: 1px solid #505050;
|
||||
padding: 0 15px;
|
||||
cursor: pointer;
|
||||
transition: all 500ms;
|
||||
font-size: 13px;
|
||||
}
|
||||
.ace_conter_toolbar .pull-left span{
|
||||
border-right:0;
|
||||
cursor: default;
|
||||
}
|
||||
.ace_conter_toolbar .pull-left span i,
|
||||
.ace_conter_toolbar .pull-right span i {
|
||||
font-style: normal;
|
||||
}
|
||||
.ace_conter_toolbar .pull-right span:hover {
|
||||
background: #717171;
|
||||
}
|
||||
.ace_toolbar_menu {
|
||||
position: absolute;
|
||||
z-index: 9999;
|
||||
top: 40px;
|
||||
left: 50%;
|
||||
margin-left: -200px;
|
||||
background: #444444;
|
||||
width: 400px;
|
||||
padding: 15px 0;
|
||||
box-shadow: 0px 0px 2px 0px #000;
|
||||
}
|
||||
.ace_toolbar_menu .menu-conter {
|
||||
margin: 0 15px 15px;
|
||||
position: relative;
|
||||
}
|
||||
.ace_toolbar_menu .menu-conter .fa {
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 7px;
|
||||
font-size: 18px;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
.ace_toolbar_menu input {
|
||||
width: 100%;
|
||||
height: 35px;
|
||||
background: #444;
|
||||
border: 1px solid #7d7d7d;
|
||||
color: #fff;
|
||||
padding: 0px 10px;
|
||||
outline: none;
|
||||
}
|
||||
.ace_toolbar_menu input:focus{
|
||||
border: 1px solid #fff;
|
||||
}
|
||||
|
||||
.ace_toolbar_menu .menu-item ul {
|
||||
overflow: auto;
|
||||
max-height: 300px;
|
||||
}
|
||||
.ace_toolbar_menu .menu-item li {
|
||||
padding: 0 20px;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
transition: all 500ms;
|
||||
position: relative;
|
||||
}
|
||||
.ace_toolbar_menu .menu-item li.active,
|
||||
.ace_toolbar_menu .menu-item li.active:hover {
|
||||
background: #666;
|
||||
}
|
||||
.ace_toolbar_menu .menu-item li:hover {
|
||||
background: #505050;
|
||||
}
|
||||
.ace_toolbar_menu .icon-link {
|
||||
margin-left: 15px;
|
||||
color: #20a53a;
|
||||
}
|
||||
.ace_toolbar_menu .menu-item .icon {
|
||||
position: absolute;
|
||||
right: 25px;
|
||||
}
|
||||
.ace_toolbar_menu .menu-title {
|
||||
padding: 0 0 5px 20px;
|
||||
border-bottom: 1px solid #666666;
|
||||
color: #9e9e9e;
|
||||
}
|
||||
|
||||
.make_transist {
|
||||
-webkit-transition: all .2s ease-in-out;
|
||||
-moz-transition: all .2s ease-in-out;
|
||||
-o-transition: all .2s ease-in-out;
|
||||
-ms-transition: all .2s ease-in-out;
|
||||
transition: all .2s ease-in-out
|
||||
}
|
||||
.ace_conter_search{
|
||||
display: none;
|
||||
}
|
||||
.helps_conter{
|
||||
padding: 25px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.helps_conter .helps_item{
|
||||
margin-bottom: 10px;
|
||||
display: inline-block;
|
||||
border-left: 3px solid #20a53a;
|
||||
padding-left: 5px;
|
||||
font-size: 15px;
|
||||
}
|
||||
.helps_conter .helps_box{
|
||||
margin-bottom: 20px;
|
||||
font-size: 14px;
|
||||
padding-left: 10px;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.helps_left{
|
||||
width: 50%;
|
||||
float: left;
|
||||
padding:15px;
|
||||
}
|
||||
|
||||
.cursor-row,.cursor-line{
|
||||
margin:5px;
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 364 B |
@@ -347,11 +347,30 @@ function SetDebug() {
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
});
|
||||
},function () {
|
||||
console.log('index.html');
|
||||
$("#panelDebug").prop('checked',debug_stat);
|
||||
});
|
||||
}
|
||||
|
||||
function set_local() {
|
||||
var status_s = { false: 'Open', true: 'Close' }
|
||||
var debug_stat = $("#panelLocal").prop('checked');
|
||||
bt.confirm({
|
||||
title: status_s[debug_stat] + "Offline mode",
|
||||
msg: "Do you really want "+ status_s[debug_stat] + "offline mode?",
|
||||
cancel: function () {
|
||||
$("#panelLocal").prop('checked',debug_stat);
|
||||
}}, function () {
|
||||
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/config?action=set_local', {}, function (rdata) {
|
||||
layer.close(loadT);
|
||||
if (rdata.status) layer.closeAll();
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
});
|
||||
},function () {
|
||||
$("#panelLocal").prop('checked',debug_stat);
|
||||
});
|
||||
}
|
||||
|
||||
if(window.location.protocol.indexOf('https') != -1){
|
||||
$("#panelSSL").prop('checked',true);
|
||||
}
|
||||
|
||||
@@ -446,7 +446,7 @@ function GetFiles(Path,sort) {
|
||||
bodyZip = "<a class='btlink' href='javascript:;' onclick=\"UnZip('" + rdata.PATH +"/" +fmp[0] + "'," + displayZip + ")\">"+lan.files.file_menu_unzip+"</a> | ";
|
||||
}
|
||||
if(isText(fmp[0])){
|
||||
bodyZip = "<a class='btlink' href='javascript:;' onclick=\"OnlineEditFile(0,'" + rdata.PATH +"/"+ fmp[0] + "')\">"+lan.files.file_menu_edit+"</a> | ";
|
||||
bodyZip = "<a class='btlink' href='javascript:;' onclick=\"openEditorView(0,'" + rdata.PATH +"/"+ fmp[0] + "')\">"+lan.files.file_menu_edit+"</a> | ";
|
||||
}
|
||||
if(isImage(fmp[0])){
|
||||
download = "<a class='btlink' href='javascript:;' onclick=\"GetImage('" + rdata.PATH +"/"+ fmp[0] + "')\">"+lan.files.file_menu_img+"</a> | ";
|
||||
@@ -895,7 +895,7 @@ function CreateFile(type, path) {
|
||||
});
|
||||
if(rdata.status){
|
||||
GetFiles($("#DirPathPlace input").val());
|
||||
OnlineEditFile(0,path + '/' + fileName);
|
||||
openEditorView(0,path + '/' + fileName);
|
||||
}
|
||||
});
|
||||
return;
|
||||
@@ -1571,7 +1571,7 @@ function RClick(type,path,name){
|
||||
// options.items.push({ text: '播放', onclick: function () { GetPlay(path) } }, { text: lan.files.file_menu_down, onclick: function () { GetFileBytes(path) } }, { text: lan.files.file_menu_del, onclick: function () { DeleteFile(path) } });
|
||||
//}
|
||||
else if(isText(type)){
|
||||
options.items.push({text: lan.files.file_menu_edit, onclick: function() {OnlineEditFile(0,path)}},{text: lan.files.file_menu_down, onclick: function() {GetFileBytes(path)}},{text: lan.files.file_menu_del, onclick: function() {DeleteFile(path)}});
|
||||
options.items.push({text: lan.files.file_menu_edit, onclick: function() {openEditorView(0,path)}},{text: lan.files.file_menu_down, onclick: function() {GetFileBytes(path)}},{text: lan.files.file_menu_del, onclick: function() {DeleteFile(path)}});
|
||||
}
|
||||
else if(displayZip != -1){
|
||||
options.items.push({text: lan.files.file_menu_unzip, onclick: function() {UnZip(path,displayZip)}},{text: lan.files.file_menu_down, onclick: function() {GetFileBytes(path)}},{text: lan.files.file_menu_del, onclick: function() {DeleteFile(path)}});
|
||||
|
||||
@@ -135,6 +135,21 @@ var index = {
|
||||
layer.closeAll('tips');
|
||||
})
|
||||
|
||||
$('.cpubox').hover(function () {
|
||||
var _this = $(this);
|
||||
var d = _this.parents('ul').data('data').cpu;
|
||||
var crs = '';
|
||||
var n1 = 0;
|
||||
for (var i = 0; i < d[2].length; i++) {
|
||||
n1++;
|
||||
crs += 'CPU-' + i + ": " + d[2][i] + '%' + (n1 % 2 == 0?'</br>':' | ');
|
||||
|
||||
}
|
||||
layer.tips(d[3] +"</br>"+ crs, _this.find('.cicle'), { time: 0, tips: [1, '#999'] });
|
||||
}, function () {
|
||||
layer.closeAll('tips');
|
||||
});
|
||||
|
||||
$(".mem-release").hover(function () {
|
||||
$(this).addClass("shine_green");
|
||||
if (!($(this).hasClass("mem-action"))) {
|
||||
@@ -446,7 +461,7 @@ var index = {
|
||||
closeBtn: 2,
|
||||
content: '<div class="setchmod bt-form">\
|
||||
<div class="update_title"><i class="layui-layer-ico layui-layer-ico1"></i><span>'+lan.index.last_version_now+'</span></div>\
|
||||
<div class="update_version">'+lan.index.this_version+'<a href="http://www.bt.cn/bbs/forum.php?mod=viewthread&tid=19376" target="_blank" class="btlink" title="'+lan.index.check_this_version_log+'">'+lan.index.bt_linux+ (rdata.msg.is_beta == 1 ? lan.index.test_version+' ' + rdata.msg.beta.version : lan.index.final_version+' ' + rdata.msg.version) + '</a> &n'+ lan.index.release_time + (rdata.msg.is_beta == 1 ? rdata.msg.beta.uptime : rdata.msg.uptime) + '</div>\
|
||||
<div class="update_version">'+lan.index.this_version+'<a href="https://forum.aapanel.com/d/9-aapanel-linux-panel-6-1-5-installation-tutorial/36" target="_blank" class="btlink" title="'+lan.index.check_this_version_log+'">'+lan.index.bt_linux+ (rdata.msg.is_beta == 1 ? lan.index.test_version+' ' + rdata.msg.beta.version : lan.index.final_version+' ' + rdata.msg.version) + '</a> &n'+ lan.index.release_time + (rdata.msg.is_beta == 1 ? rdata.msg.beta.uptime : rdata.msg.uptime) + '</div>\
|
||||
<div class="bt-form-submit-btn">\
|
||||
<button type="button" class="btn btn-danger btn-sm btn-title" onclick="layer.closeAll()">'+ lan.public.cancel + '</button>\
|
||||
<button type="button" class="btn btn-success btn-sm btn-title btn_update_panel" onclick="layer.closeAll()">'+ lan.public.know + '</button>\
|
||||
@@ -484,7 +499,7 @@ var index = {
|
||||
content: '<div class="setchmod bt-form" style="padding-bottom:50px;">\
|
||||
<div class="update_title"><i class="layui-layer-ico layui-layer-ico0"></i><span>'+lan.index.have_new_version+'</span></div>\
|
||||
<div class="update_conter">\
|
||||
<div class="update_version">'+lan.index.last_version+'<a href="https://www.bt.cn/bbs/forum.php?mod=forumdisplay&fid=36" target="_blank" class="btlink" title="'+lan.index.check_version_log+'">'+lan.index.bt_linux+ (is_beta === 1 ? lan.index.test_version : lan.index.final_version) + rdata.version + '</a> '+lan.index.update_date + (result.msg.is_beta == 1 ? result.msg.beta.uptime : result.msg.uptime) + '</div>\
|
||||
<div class="update_version">'+lan.index.last_version+'<a href="https://forum.aapanel.com/d/9-aapanel-linux-panel-6-1-5-installation-tutorial/36" target="_blank" class="btlink" title="'+lan.index.check_version_log+'">'+lan.index.bt_linux+ (is_beta === 1 ? lan.index.test_version : lan.index.final_version) + rdata.version + '</a> '+lan.index.update_date + (result.msg.is_beta == 1 ? result.msg.beta.uptime : result.msg.uptime) + '</div>\
|
||||
<div class="update_logs">'+ rdata.updateMsg + '</div>\
|
||||
</div>\
|
||||
<!--div class="update_conter">\
|
||||
|
||||
+842
-2
@@ -4,6 +4,846 @@ $(document).ready(function() {
|
||||
});
|
||||
});
|
||||
|
||||
function openEditorView(type,path){
|
||||
var paths = path.split('/'),_fileName = paths[paths.length -1], _aceTmplate = document.getElementById("aceTmplate").innerHTML;
|
||||
_aceTmplate = _aceTmplate.replace(/\<\\\/script\>/g,'</script>');
|
||||
if(aceEditor.editor !== null){
|
||||
if(aceEditor.isAceView == false){
|
||||
aceEditor.isAceView = true;
|
||||
$('.aceEditors .layui-layer-max').click()
|
||||
}
|
||||
for(var i=0;i<aceEditor.pathAarry.length;i++){
|
||||
if(path === aceEditor.pathAarry[i]){
|
||||
layer.msg('File is open',{icon:0});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
aceEditor.openEditorView(path);
|
||||
return false;
|
||||
}
|
||||
var r = layer.open({
|
||||
type: 1,
|
||||
maxmin: true,
|
||||
shade:false,
|
||||
area: ['80%','80%'],
|
||||
title: "Online text editor",
|
||||
skin:'aceEditors',
|
||||
zIndex:19999,
|
||||
content: _aceTmplate,
|
||||
success:function(layero,index){
|
||||
aceEditor.layer_view = index;
|
||||
aceEditor.ace_active = '';
|
||||
aceEditor.eventEditor();
|
||||
ace.require("/ace/ext/language_tools");
|
||||
ace.config.set("modePath", "/static/ace");
|
||||
ace.config.set("workerPath", "/static/ace");
|
||||
ace.config.set("themePath", "/static/ace");
|
||||
aceEditor.openEditorView(path);
|
||||
$('.aceEditors .layui-layer-min').click(function (e){
|
||||
aceEditor.isAceView = false;
|
||||
setTimeout(function(){
|
||||
var _id = $('.ace_conter_menu .active').attr('data-id');
|
||||
aceEditor.editor['ace_editor_'+_id].ace.resize();
|
||||
},105);
|
||||
});
|
||||
$('.aceEditors .layui-layer-max').click(function (e){
|
||||
setTimeout(function(){
|
||||
aceEditor.setEditorView();
|
||||
var _id = $('.ace_conter_menu .active').attr('data-id');
|
||||
aceEditor.editor['ace_editor_'+_id].ace.resize();
|
||||
},105);
|
||||
});
|
||||
},
|
||||
cancel:function(){
|
||||
for(var item in aceEditor.editor){
|
||||
if(aceEditor.editor[item].fileType == 1){
|
||||
layer.open({
|
||||
type: 1,
|
||||
area: ['400px', '180px'],
|
||||
title: 'Save Tips',
|
||||
content: '<div class="ace-clear-form">\
|
||||
<div class="clear-icon"></div>\
|
||||
<div class="clear-title">Detected that the file was not saved, did you save the file change?</div>\
|
||||
<div class="clear-tips">If you don\'t save, the changes will be lost!</div>\
|
||||
<div class="ace-clear-btn" style="">\
|
||||
<button type="button" class="btn btn-sm btn-default" style="float:left" data-type="2">Dont save</button>\
|
||||
<button type="button" class="btn btn-sm btn-default" style="margin-right:10px;" data-type="1">Cancel</button>\
|
||||
<button type="button" class="btn btn-sm btn-success" data-type="0">Save</button>\
|
||||
</div>\
|
||||
</div>',
|
||||
success: function (layers, indexs) {
|
||||
$('.ace-clear-btn button').click(function(){
|
||||
var _type = $(this).attr('data-type');
|
||||
switch(_type){
|
||||
case '2':
|
||||
aceEditor.editor = null;
|
||||
layer.closeAll();
|
||||
break;
|
||||
case '1':
|
||||
layer.close(indexs);
|
||||
break;
|
||||
case '0':
|
||||
var _arry = [],editor = aceEditor['editor'];
|
||||
for(var item in editor){
|
||||
_arry.push({
|
||||
path: editor[item]['path'],
|
||||
data: editor[item]['ace'].getValue(),
|
||||
encoding: editor[item]['encoding'],
|
||||
})
|
||||
}
|
||||
aceEditor.saveAllFileBody(_arry,function(){
|
||||
$('.ace_conter_menu>.item').each(function (el,indexx) {
|
||||
var _id = $(this).attr('data-id');
|
||||
$(this).find('i').removeClass('glyphicon-exclamation-sign').addClass('glyphicon-remove').attr('data-file-state','0')
|
||||
aceEditor.editor['ace_editor_'+_id].fileType = 0;
|
||||
});
|
||||
aceEditor.editor = null;
|
||||
aceEditor.pathAarry = [];
|
||||
layer.closeAll();
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
aceEditor.editor = null;
|
||||
aceEditor.pathAarry = [];
|
||||
aceEditor.editorLength = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var aceEditor = {
|
||||
layer_view:'',
|
||||
editor: null,
|
||||
supportedModes: {
|
||||
Apache_Conf: ["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"],
|
||||
BatchFile: ["bat|cmd"],
|
||||
C_Cpp: ["cpp|c|cc|cxx|h|hh|hpp|ino"],
|
||||
CSharp: ["cs"],
|
||||
CSS: ["css"],
|
||||
Dockerfile: ["^Dockerfile"],
|
||||
golang: ["go"],
|
||||
HTML: ["html|htm|xhtml|vue|we|wpy"],
|
||||
Java: ["java"],
|
||||
JavaScript: ["js|jsm|jsx"],
|
||||
'JSON': ["json"],
|
||||
JSP: ["jsp"],
|
||||
LESS: ["less"],
|
||||
Lua: ["lua"],
|
||||
Makefile: ["^Makefile|^GNUmakefile|^makefile|^OCamlMakefile|make"],
|
||||
Markdown: ["md|markdown"],
|
||||
MySQL: ["mysql"],
|
||||
Nginx: ["nginx|conf"],
|
||||
INI: ["ini|conf|cfg|prefs"],
|
||||
ObjectiveC: ["m|mm"],
|
||||
Perl: ["pl|pm"],
|
||||
Perl6: ["p6|pl6|pm6"],
|
||||
pgSQL: ["pgsql"],
|
||||
PHP_Laravel_blade: ["blade.php"],
|
||||
PHP: ["php|inc|phtml|shtml|php3|php4|php5|phps|phpt|aw|ctp|module"],
|
||||
Powershell: ["ps1"],
|
||||
Python: ["py"],
|
||||
R: ["r"],
|
||||
Ruby: ["rb|ru|gemspec|rake|^Guardfile|^Rakefile|^Gemfile"],
|
||||
Rust: ["rs"],
|
||||
SASS: ["sass"],
|
||||
SCSS: ["scss"],
|
||||
SH: ["sh|bash|^.bashrc"],
|
||||
SQL: ["sql"],
|
||||
SQLServer: ["sqlserver"],
|
||||
Swift: ["swift"],
|
||||
Text: ["txt"],
|
||||
Typescript: ["ts|typescript|str"],
|
||||
VBScript: ["vbs|vb"],
|
||||
Verilog: ["v|vh|sv|svh"],
|
||||
XML: ["xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl|xaml"],
|
||||
YAML: ["yaml|yml"]
|
||||
},
|
||||
nameOverrides: {
|
||||
ObjectiveC: "Objective-C",
|
||||
CSharp: "C#",
|
||||
golang: "Go",
|
||||
C_Cpp: "C and C++",
|
||||
PHP_Laravel_blade: "PHP (Blade Template)",
|
||||
Perl6: "Perl 6",
|
||||
},
|
||||
pathAarry:[],
|
||||
encodingList: ['UTF-8', 'GBK', 'GB2312', 'BIG5'],
|
||||
themeList: [
|
||||
'chrome',
|
||||
'clouds',
|
||||
'crimson_editor',
|
||||
'ambiance',
|
||||
'chaos',
|
||||
'monokai'
|
||||
],
|
||||
editorTheme: 'monokai', // 编辑器主题
|
||||
editorLength: 0,
|
||||
isAceView:true,
|
||||
ace_active:'',
|
||||
// aceEditor:'',
|
||||
// 事件编辑器-方法,事件绑定
|
||||
eventEditor: function () {
|
||||
var _this = this;
|
||||
$(window).resize(function(){
|
||||
var _id = $('.ace_conter_menu .active').attr('data-id');
|
||||
aceEditor.editor['ace_editor_'+_id].ace.resize();
|
||||
_this.setEditorView()
|
||||
})
|
||||
// 显示工具条
|
||||
$('.ace_header .pull-down').click(function(){
|
||||
if($(this).find('i').hasClass('glyphicon-menu-down')){
|
||||
$('.ace_header').css({'marginTop':'-35px','height':'0'});
|
||||
$(this).css({'top':'35px','height':'40px','line-height':'40px'});
|
||||
$(this).find('i').addClass('glyphicon-menu-up').removeClass('glyphicon-menu-down');
|
||||
}else{
|
||||
$('.ace_header').removeAttr('style');
|
||||
$(this).removeAttr('style');
|
||||
$(this).find('i').addClass('glyphicon-menu-down').removeClass('glyphicon-menu-up');
|
||||
}
|
||||
_this.setEditorView();
|
||||
});
|
||||
|
||||
// 切换TAB视图
|
||||
$('.ace_conter_menu').on('click', '.item', function (e) {
|
||||
var _id = $(this).attr('data-id');
|
||||
$('.item_tab_'+ _id).addClass('active').siblings().removeClass('active');
|
||||
$('#ace_editor_'+ _id).addClass('active').siblings().removeClass('active');
|
||||
_this.ace_active = _id;
|
||||
_this.currentStatusBar(_id);
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
// 移上TAB按钮变化,仅文件被修改后
|
||||
$('.ace_conter_menu').on('mouseover', '.item .icon-tool', function () {
|
||||
var type = $(this).attr('data-file-state');
|
||||
if (type != '0') {
|
||||
$(this).removeClass('glyphicon-exclamation-sign').addClass('glyphicon-remove');
|
||||
}
|
||||
});
|
||||
|
||||
// 移出tab按钮变化,仅文件被修改后
|
||||
$('.ace_conter_menu').on('mouseout', '.item .icon-tool', function () {
|
||||
var type = $(this).attr('data-file-state');
|
||||
if (type != '0') {
|
||||
$(this).removeClass('glyphicon-remove').addClass('glyphicon-exclamation-sign');
|
||||
}
|
||||
});
|
||||
|
||||
// 关闭编辑视图
|
||||
$('.ace_conter_menu').on('click', '.item .icon-tool', function (e) {
|
||||
var file_type = $(this).attr('data-file-state');
|
||||
var file_title = $(this).attr('data-title');
|
||||
var _path = $(this).parent().attr('title');
|
||||
var _id = $(this).parent().attr('data-id');
|
||||
switch (file_type) {
|
||||
// 直接关闭
|
||||
case '0':
|
||||
_this.removeEditor(_id);
|
||||
break;
|
||||
// 未保存
|
||||
case '1':
|
||||
var loadT = layer.open({
|
||||
type: 1,
|
||||
area: ['400px', '180px'],
|
||||
title: 'Tips',
|
||||
content: '<div class="ace-clear-form">\
|
||||
<div class="clear-icon"></div>\
|
||||
<div class="clear-title">Do you want to save changes to  ' + file_title + ' ?</div>\
|
||||
<div class="clear-tips">If you don\'t save, the changes will be lost!</div>\
|
||||
<div class="ace-clear-btn" style="">\
|
||||
<button type="button" class="btn btn-sm btn-default" style="float:left" data-type="2">Dont save</button>\
|
||||
<button type="button" class="btn btn-sm btn-default" style="margin-right:10px;" data-type="1">Cancel</button>\
|
||||
<button type="button" class="btn btn-sm btn-success" data-type="0">Save</button>\
|
||||
</div>\
|
||||
</div>',
|
||||
success: function (layers, index) {
|
||||
$('.ace-clear-btn .btn').click(function () {
|
||||
var _type = $(this).attr('data-type');
|
||||
switch (_type) {
|
||||
case '0': //保存文件
|
||||
console.log()
|
||||
_this.saveFileBody({
|
||||
path:_path,
|
||||
data:editor_item.ace.getValue(),
|
||||
encoding:editor_item.ace.getValue()
|
||||
},function(){
|
||||
layer.msg(res.msg, {icon: 1});
|
||||
editor_item.fileType = 0;
|
||||
$('.item_tab_' + editor_item.id + ' .icon-tool').attr('data-file-state', '0').removeClass('glyphicon-exclamation-sign').addClass('glyphicon-remove');
|
||||
});
|
||||
break;
|
||||
case '1': //关闭视图
|
||||
layer.close(index);
|
||||
break;
|
||||
case '2': //取消保存
|
||||
_this.removeEditor(_id);
|
||||
layer.close(index);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
// 新建编辑器视图
|
||||
$('.ace_editor_add').click(function () {
|
||||
_this.addEditor();
|
||||
});
|
||||
|
||||
// 底部状态栏功能按钮
|
||||
$('.ace_conter_toolbar .pull-right span').click(function (e) {
|
||||
var _type = $(this).attr('data-type'),_id = $(this).attr('data-id'),_item = _this.editor['ace_editor_'+_id],_icon = '<span class="icon"><i class="glyphicon glyphicon-ok" aria-hidden="true"></i></span>';
|
||||
$('.ace_toolbar_menu').show();
|
||||
switch (_type) {
|
||||
case 'cursor':
|
||||
$('.ace_toolbar_menu').hide();
|
||||
break;
|
||||
case 'tab':
|
||||
$('.ace_toolbar_menu .menu-tabs').show().siblings().hide();
|
||||
$('.tabsType').find(_item.softTabs?'[data-value="nbsp"]':'[data-value="tabs"]').addClass('active').append(_icon);
|
||||
$('.tabsSize [data-value="'+ _item.tabSize +'"]').addClass('active').append(_icon);
|
||||
$('.menu-tabs li').click(function(e){
|
||||
var _val = $(this).attr('data-value');
|
||||
if($(this).parent().hasClass('tabsType')){
|
||||
_item.ace.getSession().setUseSoftTabs(_val == 'nbsp');
|
||||
_item.softTabs = _val == 'nbsp';
|
||||
}else{
|
||||
_item.ace.getSession().setTabSize(_val);
|
||||
_item.tabSize = _val;
|
||||
}
|
||||
$(this).siblings().removeClass('active').find('.icon').remove();
|
||||
$(this).addClass('active').append(_icon);
|
||||
_this.currentStatusBar(_id);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
break;
|
||||
case 'encoding':
|
||||
$('.ace_toolbar_menu .menu-encoding').show().siblings().hide();
|
||||
_this.setEncodingType();
|
||||
$('.menu-encoding ul li').click(function (e) {
|
||||
layer.msg('Set file encoding: ' + $(this).attr('data-value'));
|
||||
$('.ace_conter_toolbar [data-type="encoding"]').html('coding: <i>'+ $(this).attr('data-value') +'</i>');
|
||||
$(this).addClass('active').append(_icon).siblings().removeClass('active').find('span').remove();
|
||||
_item.encoding = $(this).attr('data-value');
|
||||
});
|
||||
break;
|
||||
case 'lang':
|
||||
$('.ace_toolbar_menu').hide();
|
||||
layer.msg('Switching language mode is not supported at this time, so stay tuned!',{icon:6});
|
||||
// $('.ace_toolbar_menu .menu-files').show().siblings().hide();
|
||||
// _this.getRelevanceList(_item.fileName);
|
||||
break;
|
||||
}
|
||||
$('.ace_toolbar_menu').click(function(e){
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
$(document).click(function(e){
|
||||
$('.ace_toolbar_menu').hide();
|
||||
$('.ace_toolbar_menu .menu-tabs,.ace_toolbar_menu .menu-encoding,.ace_toolbar_menu .menu-files').hide();
|
||||
})
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
// 搜索内容键盘事件
|
||||
$('.menu-files .menu-input').keyup(function () {
|
||||
_this.searchRelevance($(this).val());
|
||||
if($(this).val != ''){
|
||||
$(this).next().show();
|
||||
}else{
|
||||
$(this).next().hide();
|
||||
}
|
||||
});
|
||||
|
||||
// 清除搜索内容事件
|
||||
$('.menu-files .menu-conter .fa').click(function(){
|
||||
$('.menu-files .menu-input').val('').next().hide();
|
||||
_this.searchRelevance()
|
||||
});
|
||||
|
||||
// 状态
|
||||
$('.ace_header span').click(function () {
|
||||
var type = $(this).attr('class'),editor_item = _this.editor['ace_editor_'+ _this.ace_active ];
|
||||
switch(type){
|
||||
case 'saveFile': //保存当时文件
|
||||
_this.saveFileBody({
|
||||
path: editor_item.path,
|
||||
data: editor_item.ace.getValue(),
|
||||
encoding: editor_item.encoding
|
||||
}, function (res) {
|
||||
layer.msg(res.msg, {icon: 1});
|
||||
editor_item.fileType = 0;
|
||||
$('.item_tab_' + editor_item.id + ' .icon-tool').attr('data-file-state', '0').removeClass('glyphicon-exclamation-sign').addClass('glyphicon-remove');
|
||||
});
|
||||
break;
|
||||
case 'saveFileAll': //保存全部
|
||||
var loadT = layer.open({
|
||||
type: 1,
|
||||
area: ['350px', '180px'],
|
||||
title: 'Tips',
|
||||
content: '<div class="ace-clear-form">\
|
||||
<div class="clear-icon"></div>\
|
||||
<div class="clear-title">Do you want to save changes to all files?</div>\
|
||||
<div class="clear-tips">If you don\'t save, the changes will be lost!</div>\
|
||||
<div class="ace-clear-btn" style="">\
|
||||
<button type="button" class="btn btn-sm btn-default clear-btn" style="margin-right:10px;" >Cancel</button>\
|
||||
<button type="button" class="btn btn-sm btn-success save-all-btn">Save</button>\
|
||||
</div>\
|
||||
</div>',
|
||||
success: function (layers, index) {
|
||||
$('.clear-btn').click(function(){
|
||||
layer.close(index);
|
||||
});
|
||||
$('.save-all-btn').click(function(){
|
||||
var _arry = [],editor = aceEditor['editor'];
|
||||
for(var item in editor){
|
||||
_arry.push({
|
||||
path: editor[item]['path'],
|
||||
data: editor[item]['ace'].getValue(),
|
||||
encoding: editor[item]['encoding'],
|
||||
})
|
||||
}
|
||||
_this.saveAllFileBody(_arry,function(){
|
||||
$('.ace_conter_menu>.item').each(function (el,index) {
|
||||
var _id = $(this).attr('data-id');
|
||||
$(this).find('i').attr('data-file-state','0').removeClass('glyphicon-exclamation-sign').addClass('glyphicon-remove')
|
||||
aceEditor.editor['ace_editor_'+_id].fileType = 0;
|
||||
});
|
||||
layer.close(index);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'refreshs': //刷新文件
|
||||
if(editor_item.fileType === 0 ){
|
||||
aceEditor.getFileBody({path:editor_item.path},function(res){
|
||||
editor_item.ace.setValue(res.data);
|
||||
editor_item.fileType = 0;
|
||||
$('.item_tab_' + editor_item.id + ' .icon-tool').attr('data-file-state', '0').removeClass('glyphicon-exclamation-sign').addClass('glyphicon-remove');
|
||||
layer.msg('Refresh successfully',{icon:1});
|
||||
});
|
||||
return false;
|
||||
}
|
||||
var loadT = layer.open({
|
||||
type: 1,
|
||||
area: ['350px', '180px'],
|
||||
title: 'Tips',
|
||||
content: '<div class="ace-clear-form">\
|
||||
<div class="clear-icon"></div>\
|
||||
<div class="clear-title">Whether to refresh the current file</div>\
|
||||
<div class="clear-tips">Refreshing the current file will overwrite the current modification and continue!</div>\
|
||||
<div class="ace-clear-btn" style="">\
|
||||
<button type="button" class="btn btn-sm btn-default clear-btn" style="margin-right:10px;" >Cancel</button>\
|
||||
<button type="button" class="btn btn-sm btn-success save-all-btn">Save</button>\
|
||||
</div>\
|
||||
</div>',
|
||||
success: function (layers, index) {
|
||||
$('.clear-btn').click(function(){
|
||||
layer.close(index);
|
||||
});
|
||||
$('.save-all-btn').click(function(){
|
||||
aceEditor.getFileBody({path:editor_item.path},function(res){
|
||||
layer.close(index);
|
||||
editor_item.ace.setValue(res.data);
|
||||
editor_item.fileType == 0;
|
||||
$('.item_tab_' + editor_item.id + ' .icon-tool').attr('data-file-state', '0').removeClass('glyphicon-exclamation-sign').addClass('glyphicon-remove');
|
||||
layer.msg('Refresh successfully',{icon:1});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
break;
|
||||
// 搜索
|
||||
case 'searchs':
|
||||
|
||||
break;
|
||||
// 替换
|
||||
case 'replaces':
|
||||
|
||||
break;
|
||||
// 字体
|
||||
case 'fontSize':
|
||||
layer.open({
|
||||
type:1,
|
||||
area:['400px','300px'],
|
||||
title:'Tips',
|
||||
btn:['Save','Cancel'],
|
||||
content:'<div class="ace-fontSize">\
|
||||
<div class="line"><div class="">Font style</div><div class=""></div></div>\
|
||||
<div class="line"><div class="">font size</div><div class=""><input type="text" />px</div></div>\
|
||||
</div>',
|
||||
yes:function(layers,index){
|
||||
|
||||
},
|
||||
btn1:function(layers,index){
|
||||
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'themes':
|
||||
layer.msg('The theme feature is under development, so stay tuned!',{icon:6});
|
||||
break;
|
||||
case 'helps':
|
||||
layer.open({
|
||||
type:1,
|
||||
area:'1300px',
|
||||
title:'Help',
|
||||
content:'<div class="helps_conter">\
|
||||
<div class="helps_left">\
|
||||
<div class="helps_item">Common shortcuts:</div>\
|
||||
<div class="helps_box">\
|
||||
ctrl+s Save</br>\
|
||||
ctrl+a Select all ctrl+x Cut</br>\
|
||||
ctrl+c Copy ctrl+v Paste</br>\
|
||||
ctrl+z Cancel ctrl+y Anti-cancel</br>\
|
||||
ctrl+f Find ctrl+alt+f Replace</br>\
|
||||
win+alt+0 Collapse all</br>\
|
||||
win+alt+shift+0 Expand all</br>\
|
||||
esc [Exit the search and cancel the automatic prompt...]</br>\
|
||||
ctrl-shift-s Preview</br>\
|
||||
ctrl-shift-e Show & close function\
|
||||
</div>\
|
||||
<div class="helps_item">Select:</div>\
|
||||
<div class="helps_box">\
|
||||
Mouse frame selection -- drag</br>\
|
||||
shift+home/end/up/left/down/right</br>\
|
||||
shift+pageUp/PageDown Scroll up and down</br>\
|
||||
ctrl+shift+ home/end Current cursor to the end of the head</br>\
|
||||
alt+ Mouse drag Block selection</br>\
|
||||
ctrl+alt+g Batch select current and enter multi-tab editing</br>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class="helps_left">\
|
||||
<div class="helps_item">Cursor movement:</div>\
|
||||
<div class="helps_box">\
|
||||
home/end/up/left/down/right</br>\
|
||||
ctrl+home/end Cursor moves to the beginning/end of the document</br>\
|
||||
ctrl+p Jump to the matching tag</br>\
|
||||
pageUp/PageDown Cursor up and down</br>\
|
||||
alt+left/right Cursor moves to the top of the line</br>\
|
||||
shift+left/right Cursor moves to the beginning & end of the line</br>\
|
||||
ctrl+l Jump to the specified line</br>\
|
||||
ctrl+alt+up/down Add cursor to the top (bottom)</br>\
|
||||
</div>\
|
||||
<div class="helps_item">Edit:</div>\
|
||||
<div class="helps_box">\
|
||||
ctrl+/ Comment & Uncomment ctrl+alt+a Align left and right</br>\
|
||||
table Tab alignment shift+table Overall advancement table</br>\
|
||||
delete Delete ctrl+d Delete entire line</br>\
|
||||
ctrl+delete Delete the word on the right side of the line</br>\
|
||||
ctrl/shift+backspace Delete the word on the left</br>\
|
||||
alt+shift+up/down Copy the line and add it to the top (below)</br>\
|
||||
alt+delete Delete the right side of the cursor</br>\
|
||||
alt+up/down The current line is swapped with the previous line (the next line)</br>\
|
||||
ctrl+shift+d Copy the line and add it below</br>\
|
||||
ctrl+delete Delete the word on the right</br>\
|
||||
ctrl+shift+u Convert to lowercase</br>\
|
||||
ctrl+u Convert selected content to uppercase</br>\
|
||||
</div>\
|
||||
</div>\
|
||||
</div>'
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// 选择语言
|
||||
|
||||
this.setEditorView();
|
||||
},
|
||||
// 设置搜索视图
|
||||
setSearchView:function(){
|
||||
|
||||
},
|
||||
// 设置替换视图
|
||||
setReplaceView:function(){
|
||||
|
||||
},
|
||||
// 设置编辑器视图
|
||||
setEditorView:function () {
|
||||
var page_height = $('.aceEditors').height();
|
||||
var ace_header = $('.ace_header').height();
|
||||
var ace_conter_menu = $('.ace_conter_menu').height();
|
||||
var ace_conter_toolbar = $('.ace_conter_toolbar').height();
|
||||
var _height = page_height - ace_header - ace_conter_menu - ace_conter_toolbar - 42;
|
||||
$('.ace_conter_editor').height(_height);
|
||||
},
|
||||
// 获取文件编码列表
|
||||
getEncodingList: function (type) {
|
||||
var _option = '';
|
||||
for (var i = 0; i < this.encodingList.length; i++) {
|
||||
var item = this.encodingList[i] == type.toUpperCase();
|
||||
_option += '<li data- data-value="' + this.encodingList[i] + '" ' + (item ? 'class="active"' : '') + '>' + this.encodingList[i] + (item ?'<span class="icon"><i class="glyphicon glyphicon-ok" aria-hidden="true"></i></span>' : '') + '</li>';
|
||||
}
|
||||
$('.menu-encoding ul').html(_option);
|
||||
},
|
||||
// 获取文件关联列表
|
||||
getRelevanceList: function (fileName) {
|
||||
var _option = '', _top = 0, fileType = this.getFileType(fileName), _set_tops = 0;
|
||||
for (var name in this.supportedModes) {
|
||||
var data = this.supportedModes[name],item = (name == fileType.name);
|
||||
_option += '<li data-height="' + _top + '" data-rule="' + this.supportedModes[name] + '" data-value="' + name + '" ' + (item ? 'class="active"' : '') + '>' + (this.nameOverrides[name] || name) + (item ?'<span class="icon"><i class="glyphicon glyphicon-ok" aria-hidden="true"></i></span>' : '') + '</li>'
|
||||
if (item) _set_tops = _top
|
||||
_top += 35;
|
||||
}
|
||||
$('.menu-files ul').html(_option);
|
||||
$('.menu-files ul').scrollTop(_set_tops);
|
||||
},
|
||||
// 搜索文件关联
|
||||
searchRelevance: function (search) {
|
||||
if(search == undefined) search = '';
|
||||
$('.menu-files ul li').each(function (index, el) {
|
||||
var val = $(this).attr('data-value').toLowerCase(),
|
||||
rule = $(this).attr('data-rule'),
|
||||
suffixs = rule.split('|'),
|
||||
_suffixs = false;
|
||||
search = search.toLowerCase();
|
||||
for (var i = 0; i < suffixs.length; i++) {
|
||||
if (suffixs[i].indexOf(search) > -1) _suffixs = true
|
||||
}
|
||||
if (search == '') {
|
||||
$(this).removeAttr('style');
|
||||
} else {
|
||||
if (val.indexOf(search) == -1) {
|
||||
$(this).attr('style', 'display:none');
|
||||
} else {
|
||||
$(this).removeAttr('style');
|
||||
}
|
||||
if (_suffixs) $(this).removeAttr('style')
|
||||
}
|
||||
});
|
||||
},
|
||||
// 设置编码类型
|
||||
setEncodingType: function (encode) {
|
||||
this.getEncodingList('UTF-8');
|
||||
$('.menu-encoding ul li').click(function (e) {
|
||||
layer.msg('Set file encoding:' + $(this).attr('data-value'));
|
||||
$(this).addClass('active').append('<span class="icon"><i class="glyphicon glyphicon-ok" aria-hidden="true"></i></span>').siblings().removeClass('active').find('span').remove();
|
||||
});
|
||||
},
|
||||
// 更新状态栏
|
||||
currentStatusBar: function(id){
|
||||
var _editor = this.editor['ace_editor_'+id];
|
||||
$('.ace_conter_toolbar [data-type="path"]').html('Dir:<i>'+ _editor.path +'</i>');
|
||||
$('.ace_conter_toolbar [data-type="tab"]').html(_editor.softTabs?'Space:<i>'+ _editor.tabSize +'</i>':'Tab length:<i>'+ _editor.tabSize +'</i>');
|
||||
$('.ace_conter_toolbar [data-type="encoding"]').html('coding:<i>'+ _editor.encoding.toUpperCase() +'</i>');
|
||||
$('.ace_conter_toolbar [data-type="lang"]').html('Language:<i>'+ _editor.type +'</i>');
|
||||
$('.ace_conter_toolbar span').attr('data-id',id);
|
||||
_editor.ace.resize();
|
||||
},
|
||||
// 创建ACE编辑器-对象
|
||||
creationEditor: function (obj, callabck) {
|
||||
var _this = this;
|
||||
$('#ace_editor_' + obj.id).text(obj.data || '');
|
||||
if(this.editor == null) this.editor = {}
|
||||
this.editor['ace_editor_' + obj.id] = {
|
||||
ace: ace.edit("ace_editor_" + obj.id, {
|
||||
theme: "ace/theme/monokai", //主题
|
||||
mode: "ace/mode/" + (obj.fileName != undefined ? obj.mode : 'text'), // 语言类型
|
||||
wrap: true,
|
||||
showInvisibles:false,
|
||||
showPrintMargin: false,
|
||||
enableBasicAutocompletion: true,
|
||||
enableSnippets: true,
|
||||
enableLiveAutocompletion: true,
|
||||
useSoftTabs:false,
|
||||
tabSize:4,
|
||||
keyboardHandler:'sublime'
|
||||
}), //ACE编辑器对象
|
||||
id: obj.id,
|
||||
wrap: true, //是否换行
|
||||
path:obj.path,
|
||||
tabSize:4,
|
||||
softTabs:false,
|
||||
fileName:obj.fileName,
|
||||
enableSnippets: true, //是否代码提示
|
||||
encoding: (obj.encoding != undefined ? obj.encoding : 'utf-8'), //编码类型
|
||||
mode: (obj.fileName != undefined ? obj.mode : 'text'), //语言类型
|
||||
type:obj.type,
|
||||
fileType: 0, //文件状态
|
||||
historys: obj.historys
|
||||
};
|
||||
var ACE = this.editor['ace_editor_' + obj.id];
|
||||
ACE.ace.moveCursorTo(0, 0); //设置鼠标焦点
|
||||
ACE.ace.resize(); //设置自适应
|
||||
ACE.ace.commands.addCommand({
|
||||
name: 'Save document',
|
||||
bindKey: {
|
||||
win: 'Ctrl-S',
|
||||
mac: 'Command-S'
|
||||
},
|
||||
exec: function (editor) {
|
||||
// 保存文件
|
||||
_this.saveFileBody({
|
||||
path: ACE.path,
|
||||
data: editor.getValue(),
|
||||
encoding: ACE.encoding
|
||||
}, function (res) {
|
||||
layer.msg(res.msg, {icon: 1});
|
||||
ACE.fileType = 0;
|
||||
$('.item_tab_' + ACE.id + ' .icon-tool').attr('data-file-state', '0').removeClass('glyphicon-exclamation-sign').addClass('glyphicon-remove');
|
||||
});
|
||||
},
|
||||
readOnly: false // 如果不需要使用只读模式,这里设置false
|
||||
});
|
||||
|
||||
|
||||
// 获取光标位置
|
||||
ACE.ace.getSession().selection.on('changeCursor', function(e) {
|
||||
var _cursor = ACE.ace.selection.getCursor();
|
||||
$('[data-type="cursor"]').html('Row<i class="cursor-row">'+ (_cursor.row + 1) +'</i>,Column<i class="cursor-line">'+ _cursor.column +'</i>');
|
||||
});
|
||||
|
||||
// 触发修改内容
|
||||
ACE.ace.getSession().on('change', function (editor) {
|
||||
$('.item_tab_' + ACE.id + ' .icon-tool').addClass('glyphicon-exclamation-sign').removeClass('glyphicon-remove').attr('data-file-state', '1');
|
||||
ACE.fileType = 1;
|
||||
});
|
||||
this.currentStatusBar(ACE.id);
|
||||
},
|
||||
// 获取文件模型
|
||||
getFileType: function (fileName) {
|
||||
var filenames = fileName.split('.')[1],modesByName = {};
|
||||
for (var name in this.supportedModes) {
|
||||
var data = this.supportedModes[name];
|
||||
var suffixs = data[0].split('|');
|
||||
var filename = name.toLowerCase()
|
||||
for (var i = 0; i < suffixs.length; i++) {
|
||||
if (filenames == suffixs[i]){
|
||||
return { name: name,mode: filename }
|
||||
}
|
||||
}
|
||||
}
|
||||
return {name:'Text',mode:'text'}
|
||||
},
|
||||
// 新建编辑器视图-方法
|
||||
addEditor: function () {
|
||||
var _index = this.editorLength,_id = bt.get_random(8);
|
||||
$('.ace_conter_menu .item').removeClass('active');
|
||||
$('.ace_conter_editor .ace_editors').removeClass('active');
|
||||
$('.ace_conter_menu .ace_editor_add').before('<div class="item active item_tab_'+_id+'" data-type="text" data-id="'+_id+'" data-index="'+ _index +'">\
|
||||
<span class="icon_file"><i class="fa fa-code" aria-hidden="true"></i></span>\
|
||||
<span>Untitled-'+_index+'</span>\
|
||||
<i class="fa fa-circle icon-tool" aria-hidden="true" data-file-state="1" data-title="Untitled-'+ _index +'"></i>\
|
||||
</div>');
|
||||
$('.ace_conter_editor').append('<div id="ace_editor_'+_id+'" class="ace_editors active"></div>');
|
||||
$('#ace_editor_' + _id).siblings().removeClass('active');
|
||||
this.creationEditor({ id: _id });
|
||||
this.editorLength = this.editorLength + 1;
|
||||
},
|
||||
// 删除编辑器视图-方法
|
||||
removeEditor: function (id) {
|
||||
if ($('.item_tab_' + id).next('.item').length == 0) {
|
||||
$('.item_tab_' + id).prev('.item').addClass('active');
|
||||
$('#ace_editor_' + id).prev('.ace_editor').addClass('active');
|
||||
this.ace_active = $('.item_tab_' + id).prev('.item').attr('data-id');
|
||||
} else {
|
||||
$('.item_tab_' + id).next('.item').addClass('active');
|
||||
$('#ace_editor_' + id).next('.ace_editor').addClass('active');
|
||||
this.ace_active = $('.item_tab_' + id).next('.item').attr('data-id');
|
||||
}
|
||||
$('.item_tab_' + id).remove();
|
||||
$('#ace_editor_' + id).remove();
|
||||
for(var i=0;i<aceEditor.pathAarry.length;i++){
|
||||
if(aceEditor.pathAarry[i] == this.editor['ace_editor_' + id].path){
|
||||
aceEditor.pathAarry.splice(i,1);
|
||||
}
|
||||
}
|
||||
delete this.editor['ace_editor_' + id];
|
||||
this.editorLength --;
|
||||
if(this.editorLength === 0){
|
||||
this.ace_active = '';
|
||||
this.pathAarry = [];
|
||||
$('.layui-layer-close').click();
|
||||
}else{
|
||||
this.currentStatusBar(this.ace_active);
|
||||
}
|
||||
},
|
||||
// 打开编辑器文件-方法
|
||||
openEditorView: function (path) {
|
||||
if(path == undefined) return false;
|
||||
// 文件类型(type,列如:JavaScript) 、文件模型(mode,列如:text)、文件标识(id,列如:x8AmsnYn)、文件编号(index,列如:0)、文件路径 (path,列如:/www/root/)
|
||||
var _this = this,paths = path.split('/'),_fileName = paths[paths.length - 1],_fileType = this.getFileType(_fileName),_type = _fileType.name,_mode = _fileType.mode,_id = bt.get_random(8),_index = this.editorLength;
|
||||
this.getFileBody({path: path}, function (res) {
|
||||
_this.pathAarry.push(path);
|
||||
$('.ace_conter_menu .item').removeClass('active');
|
||||
$('.ace_conter_editor .ace_editors').removeClass('active');
|
||||
$('.ace_conter_menu .ace_editor_add').before('<div class="item active item_tab_' + _id +'" title="'+ path +'" data-type="'+ _type +'" data-mode="'+ _mode +'" data-id="'+ _id +'" data-index="'+ _index +'" data-fileName="'+ _fileName +'">\
|
||||
<span class="icon_file"><img src="/static/img/iconfont_code.png" style="width:16px;" /></span><span>' + _fileName + '</span>\
|
||||
<i class="glyphicon glyphicon-remove icon-tool" aria-hidden="true" data-file-state="0" data-title="' + _fileName + '"></i>\
|
||||
</div>');
|
||||
$('.ace_conter_editor').append('<div id="ace_editor_'+_id +'" class="ace_editors active"></div>');
|
||||
_this.ace_active = _id;
|
||||
_this.editorLength = _this.editorLength + 1;
|
||||
_this.creationEditor({id: _id,fileName: _fileName,path: path,mode:_mode,encoding: res.encoding,data: res.data,type:_type,historys:res.historys});
|
||||
});
|
||||
},
|
||||
// 获取收藏夹列表-方法
|
||||
getFavoriteList: function () {},
|
||||
// 获取文件列表-请求
|
||||
getFileList: function () {},
|
||||
// 获取文件内容-请求
|
||||
getFileBody: function (obj, callback) {
|
||||
var loadT = layer.msg('Getting file content, please wait...',{time: 0,icon: 16,shade: [0.3, '#000']}),_this = this;
|
||||
$.post("/files?action=GetFileBody", "path=" + encodeURIComponent(obj.path), function(res) {
|
||||
layer.close(loadT);
|
||||
if (!res.status) {
|
||||
if(_this.editorLength == 0) layer.closeAll();
|
||||
layer.msg(res.msg, {icon: 2});
|
||||
|
||||
return false;
|
||||
}else{
|
||||
if(!aceEditor.isAceView){
|
||||
var _path = obj.path.split('/');
|
||||
layer.msg('Opened file ['+ (_path[_path.length-1]) +']');
|
||||
}
|
||||
}
|
||||
if (callback) callback(res);
|
||||
});
|
||||
},
|
||||
// 保存文件内容-请求
|
||||
saveFileBody: function (obj, callback) {
|
||||
var loadT = layer.msg('Saving file content, please wait...', {time: 0,icon: 16,shade: [0.3, '#000']});
|
||||
$.post("/files?action=SaveFileBody","data=" + encodeURIComponent(obj.data) + "&path=" + encodeURIComponent(obj.path) + "&encoding=" + obj.encoding, function(res) {
|
||||
layer.close(loadT);
|
||||
if (callback) callback(res)
|
||||
});
|
||||
},
|
||||
// 递归保存文件
|
||||
saveAllFileBody:function(arry,num,callabck) {
|
||||
var _this = this;
|
||||
if(typeof num == "function"){
|
||||
callabck = num; num = 0;
|
||||
}else if(typeof num == "undefined"){
|
||||
num = 0;
|
||||
}
|
||||
if(num == arry.length){
|
||||
if(callabck) callabck();
|
||||
layer.msg('All saved successfully',{icon:1});
|
||||
return false;
|
||||
}
|
||||
aceEditor.saveFileBody({
|
||||
path: arry[num].path,
|
||||
data: arry[num].data,
|
||||
encoding: arry[num].encoding
|
||||
},function(){
|
||||
num = num + 1;
|
||||
aceEditor.saveAllFileBody(arry,num,callabck);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var my_headers = {};
|
||||
var request_token_ele = document.getElementById("request_token_head");
|
||||
if (request_token_ele) {
|
||||
@@ -699,11 +1539,11 @@ function SafeMessage(j, h, g, f) {
|
||||
$("#toSubmit").click(function() {
|
||||
var a = $("#vcodeResult").val().replace(/ /g, "");
|
||||
if(a == undefined || a == "") {
|
||||
layer.msg(lan.index.input_calc_result);
|
||||
layer.msg(lan.public.input_calc_result);
|
||||
return
|
||||
}
|
||||
if(a != getCookie("vcodesum")) {
|
||||
layer.msg(lan.index.input_calc_result);
|
||||
layer.msg(lan.public.input_calc_result);
|
||||
return
|
||||
}
|
||||
layer.close(mess);
|
||||
|
||||
@@ -173,7 +173,7 @@ var site = {
|
||||
},
|
||||
{ field: 'addtime', title: lan.site.backup_time },
|
||||
{
|
||||
field: 'opt', title: lan.site.operation, align: 'right', templet: function (item) {
|
||||
field: 'opt', title: lan.site.operate, align: 'right', templet: function (item) {
|
||||
var _opt = '<a class="btlink" href="/download?filename=' + item.filename + '&name=' + item.name + '" target="_blank">'+lan.site.download+'</a> | ';
|
||||
_opt += '<a class="btlink" herf="javascrpit:;" onclick="bt.site.del_backup(\'' + item.id + '\',\'' + id + '\',\'' + siteName + '\')">'+lan.site.del+'</a>'
|
||||
return _opt;
|
||||
|
||||
@@ -495,7 +495,7 @@ var soft = {
|
||||
return;
|
||||
}
|
||||
var f = fs[0]
|
||||
if (f.type !== 'application/x-zip-compressed' && f.type !== 'application/zip') {
|
||||
if (f.type.indexOf('zip') == -1) {
|
||||
layer.msg('Only supports files in zip format!');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,13 @@
|
||||
<label class='btswitch-btn' for='panelDebug' onclick="SetDebug()"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ss-text pull-left mr50">
|
||||
<em title="after Open, The panel will stop connecting to the cloud, and the software installation, uninstallation, panel update and other functions will not be available.">Offline mode</em>
|
||||
<div class='ssh-item'>
|
||||
<input class='btswitch btswitch-ios' id='panelLocal' type='checkbox' {{data['is_local']}}>
|
||||
<label class='btswitch-btn' for='panelLocal' onclick="set_local()"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setbox bgw mtb15">
|
||||
|
||||
@@ -57,10 +57,120 @@
|
||||
<li onclick="javascript:Batch(3);"><a style="cursor: pointer;">{{data['lan']['L4']}}</a></li>
|
||||
<li onclick="javascript:Batch(4);"><a style="cursor: pointer;">{{data['lan']['L5']}}</a></li>
|
||||
</ul>
|
||||
<!--<link rel="stylesheet" href="./static/ace/font-awesome/css/font-awesome.min.css">-->
|
||||
<script type="text/tmplate" id="aceTmplate">
|
||||
<div id="ace_conter">
|
||||
<div class="ace_header">
|
||||
<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="fontSize"><i class="fa fa-text-height" aria-hidden="true"></i>字体</span> -->
|
||||
<!-- <span class="themes"><i class="fa fa-tachometer" aria-hidden="true"></i>主题</span> -->
|
||||
<span class="helps"><i class="glyphicon glyphicon-question-sign" aria-hidden="true"></i>Help</span>
|
||||
<div class="pull-down" title="Hide toolbar"><i class="glyphicon glyphicon-menu-down" aria-hidden="true"></i></div>
|
||||
</div>
|
||||
<div class="ace_overall">
|
||||
<!-- 编辑器目录 -->
|
||||
<div class="ace_catalogue">
|
||||
<div class="ace_catalogue_title">Favorites</div>
|
||||
<div class="ace_catalogue_list">
|
||||
<ul class="cd-accordion-menu animated">
|
||||
<li class="has-children">
|
||||
<input type="checkbox" name ="group-1" id="group-1" checked>
|
||||
<label for="group-1">Group 1</label>
|
||||
<ul>
|
||||
<li class="has-children">
|
||||
<input type="checkbox" name ="sub-group-1" id="sub-group-1">
|
||||
<label for="sub-group-1">Sub Group 1</label>
|
||||
<ul>
|
||||
<li><a href="#0">Image</a></li>
|
||||
<li><a href="#0">Image</a></li>
|
||||
<li><a href="#0">Image</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="has-children">
|
||||
<input type="checkbox" name ="sub-group-2" id="sub-group-2">
|
||||
<label for="sub-group-2">Sub Group 2</label>
|
||||
<ul>
|
||||
<li class="has-children">
|
||||
<input type="checkbox" name ="sub-group-level-3" id="sub-group-level-3">
|
||||
<label for="sub-group-level-3">Sub Group Level 3</label>
|
||||
<ul>
|
||||
<li><a href="#0">Image</a></li>
|
||||
<li><a href="#0">Image</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#0">Image</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#0">Image</a></li>
|
||||
<li><a href="#0">Image</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 编辑内容 -->
|
||||
<!-- <div class="ace_catalogue_sidebar"><img src="/static/img/col-resize.png" /></div> -->
|
||||
<div class="ace_editor_main">
|
||||
<div class="ace_conter_menu">
|
||||
<div class="ace_editor_add" style="display:none;"><i class="fa fa-plus-square" aria-hidden="true"></i></div>
|
||||
</div>
|
||||
<div class="ace_editor_main_storey"></div>
|
||||
<div class="ace_conter_editor"></div>
|
||||
<div class="ace_conter_toolbar">
|
||||
<div class="pull-left">
|
||||
<span data-type="path"></span>
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
<span data-type="cursor"></span>
|
||||
<span data-type="tab"></span>
|
||||
<span data-type="encoding"></span>
|
||||
<span data-type="lang"></span>
|
||||
<!--<span data-type="history"></span>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ace_toolbar_menu" style="display: none;">
|
||||
<div class="menu-item menu-tabs" style="display: none;">
|
||||
<div class="menu-title">Set tabs</div>
|
||||
<ul class="tabsType">
|
||||
<li data-value="nbsp">Indent using spaces</li>
|
||||
<li data-value="tabs">Indent using "Tab"</li>
|
||||
</ul>
|
||||
<div class="menu-title" style="margin-top:15px">Set the tab length</div>
|
||||
<ul class="tabsSize">
|
||||
<li data-value="1">1</li>
|
||||
<li data-value="2">2</li>
|
||||
<li data-value="3">3</li>
|
||||
<li data-value="4">4</li>
|
||||
<li data-value="5">5</li>
|
||||
<li data-value="6">6</li>
|
||||
<li data-value="7">7</li>
|
||||
<li data-value="8">8</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="menu-item menu-encoding" style="display: none;">
|
||||
<div class="menu-title">Set file save encoding format</div>
|
||||
<ul></ul>
|
||||
</div>
|
||||
<div class="menu-item menu-files" style="display: none;">
|
||||
<div class="menu-conter"><input type="text" class="menu-input" placeholder="Input language mode"><i class="fa fa-close" aria-hidden="true"></i></div>
|
||||
<div class="menu-title">Set file language association</div>
|
||||
<ul></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<script src="/static/js/jquery-ui.min.js"></script>
|
||||
<script src="/static/js/jquery.contextify.min.js"></script>
|
||||
<script src="/static/js/files.js?date={{g.version}}"></script>
|
||||
<script src="/static/js/upload.js?date={{g.version}}"></script>
|
||||
<script type="text/javascript" src="./static/ace/ace.js"></script>
|
||||
<script type="text/javascript" src="./static/ace/ext-language_tools.js"></script>
|
||||
<script type="text/javascript">
|
||||
setTimeout(function(){
|
||||
GetDisk();
|
||||
|
||||
@@ -0,0 +1,351 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block content %}
|
||||
<style>
|
||||
.weblog {
|
||||
font-size: 14px;
|
||||
display: inline-block;
|
||||
line-height: 30px;
|
||||
}
|
||||
.weblog em {
|
||||
font-style: normal;
|
||||
color: #666;
|
||||
margin: 0 15px;
|
||||
font-size:12px;
|
||||
}
|
||||
.weblog span {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.weblog a {
|
||||
color: #20a53a;
|
||||
}
|
||||
.firewall-port-box{
|
||||
margin-bottom:15px;
|
||||
}
|
||||
</style>
|
||||
<div class="main-content">
|
||||
<div class="container-fluid" style="padding-bottom: 50px;">
|
||||
<div class="pos-box bgw mtb15">
|
||||
<div class="position f14 c9 pull-left">
|
||||
<a class="plr10 c4" href="/">{{data['lan']['H1']}}</a>/<span class="plr10 c4">{{data['lan']['H2']}}</span>
|
||||
</div>
|
||||
<div class="search pull-right">
|
||||
<form target="hid" onsubmit='firewall.get_log_list(1,$("#SearchValue").prop("value"))'>
|
||||
<input type="text" id="SearchValue" class="ser-text pull-left" placeholder="{{data['lan']['SEARCH']}}" />
|
||||
<button type="button" class="ser-sub pull-left" onclick='firewall.get_log_list(1,$("#SearchValue").prop("value"))'></button>
|
||||
</form>
|
||||
<iframe name='hid' id="hid" style="display:none"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
<div class="safe container-fluid bgw mtb15 pd15">
|
||||
<div class="mr50 pull-left">
|
||||
<form>
|
||||
<div class="ss-text pull-left">
|
||||
<em>{{data['lan']['BTN1']}}</em>
|
||||
<div class='ssh-item' id="in_safe">
|
||||
<input class='btswitch btswitch-ios' id='sshswitch' type='checkbox' checked><label class='btswitch-btn sshswitch' for='sshswitch' ></label>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="mr50 pull-left">
|
||||
<div class="ss-text pull-left mr5">
|
||||
<em>{{data['lan']['BTN2']}}</em>
|
||||
<input type="text" class="bt-input-text" id="mstscPort" value="" />
|
||||
</div>
|
||||
<div class="ss-text pull-left">
|
||||
<button id="mstscSubmit" onclick='bt.firewall.set_mstsc($("#mstscPort").prop("value"))' class="btn btn-default btn-sm" type="button">{{data['lan']['BTN3']}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mr50 pull-left" style="border-right: 1px solid #ccc; padding-right: 40px;">
|
||||
<div class="ss-text pull-left">
|
||||
<em>{{data['lan']['BTN4']}}</em>
|
||||
<div class='ssh-item' id="isPing">
|
||||
<input class='btswitch btswitch-ios' id='noping' type='checkbox' checked><label class='btswitch-btn noping' for='noping' ></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="weblog">
|
||||
<span class="f12 c5">{{data['lan']['S1']}}</span><a href="javascript:openPath('{{session['logsPath']}}');">{{session['logsPath']}}</a><em id="logSize">0KB</em>
|
||||
<button class="btn btn-default btn-sm" onclick="firewall.clear_logs_files();">{{data['lan']['BTN5']}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="white-black-ip bgw mtb15">
|
||||
<div class="black-ip">
|
||||
<div class="def-log">
|
||||
<div class="title c6 plr15">
|
||||
<h3 class="f16">{{data['lan']['H3']}}</h3>
|
||||
</div>
|
||||
<div class="divtable pd15">
|
||||
<div class="firewall-port-box">
|
||||
<select id="firewalldType" class="bt-input-text c5 mr5" name="type" style="width:120px;">
|
||||
<option value="port">{{data['lan']['F1']}}</option>
|
||||
<option value="address">{{data['lan']['F2']}}</option>
|
||||
<option value="ip_port">Specify IP release port</option>
|
||||
</select>
|
||||
<select id="type_pool" class="bt-input-text c5 mr5" name="type" style="width:80px;">
|
||||
<option value="tcp">TCP</option>
|
||||
<option value="udp">UDP</option>
|
||||
</select>
|
||||
<input type="text" class="bt-input-text mr5" style="width: 117px;" id="AcceptPort" placeholder="{{data['lan']['F3']}}">
|
||||
<input type="text" class="bt-input-text mr5" style="width: 150px;display:none;" id="AcceptAddress" placeholder="被放行的IP地址">
|
||||
<input type="text" class="bt-input-text mr5" id="Ps" placeholder="{{data['lan']['F4']}}">
|
||||
<button id="toAccept" onclick="firewall.add_accept_port()" class="btn btn-default btn-sm va0" type="button">{{data['lan']['F5']}}</button>
|
||||
<span id="f-ps" class="c9" style="margin-left: 10px;">{{data['lan']['F6']}}</span>
|
||||
</div>
|
||||
<div class="tablescroll">
|
||||
<table id="firewallBody" class="table table-hover" style="min-width: 640px;border: 0 none;">
|
||||
</table>
|
||||
</div>
|
||||
<div class="dataTables_paginate paging_bootstrap page firewallBody" style="margin-bottom:0">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="white-black-ip bgw mtb15">
|
||||
<div class="black-ip">
|
||||
<div class="def-log">
|
||||
<div class="title c6 plr15">
|
||||
<h3 class="f16">{{data['lan']['H4']}}</h3>
|
||||
<a class="btn btn-default btn-sm va0" onclick="bt.firewall.clear_logs(function(){firewall.get_log_list()});">{{data['lan']['BTN5']}}</a>
|
||||
<span class="btn btn-default btn-sm" style="position: absolute;right: 30px;margin-top: 10px;" onclick="firewall.get_panel_error_logs()">面板运行日志</span>
|
||||
</div>
|
||||
<div class="divtable pd15">
|
||||
<div class="tablescroll">
|
||||
<table id="logsBody" class="table table-hover" style="min-width: 640px;border: 0 none;">
|
||||
|
||||
</table>
|
||||
</div>
|
||||
<div class="dataTables_paginate paging_bootstrap page logsBody" style="margin-bottom:0">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script type="text/javascript">
|
||||
|
||||
var firewall = {
|
||||
get_init:function(){
|
||||
firewall.flush_init();
|
||||
firewall.get_list();
|
||||
firewall.get_log_list();
|
||||
firewall.get_logs_size();
|
||||
$('.sshswitch').click(function(){
|
||||
var status = $("#sshswitch").prop("checked")==true?1:0;
|
||||
bt.firewall.set_mstsc_status(status,function(rdata){
|
||||
if(rdata===-1){
|
||||
if(status){
|
||||
$("#sshswitch").prop("checked","checked")
|
||||
}else{
|
||||
$("#sshswitch").removeAttr('checked');
|
||||
}
|
||||
}else{
|
||||
bt.msg(rdata);
|
||||
firewall.flush_init();
|
||||
}
|
||||
})
|
||||
})
|
||||
$('.noping').click(function(){
|
||||
var status = $("#noping").prop("checked")==true?1:0;
|
||||
bt.firewall.ping(status,function(rdata){
|
||||
if(rdata===-1){
|
||||
if(status){
|
||||
$("#noping").prop("checked","checked")
|
||||
}else{
|
||||
$("#noping").removeAttr('checked');
|
||||
}
|
||||
}else{
|
||||
bt.msg(rdata);
|
||||
firewall.flush_init();
|
||||
}
|
||||
})
|
||||
})
|
||||
$("#firewalldType").change(function(){
|
||||
var type = $(this).val();
|
||||
var w = '120px';
|
||||
var p = lan.firewall.port;
|
||||
var t = lan.firewall.accept;
|
||||
var m = lan.firewall.port_ps;
|
||||
$("#AcceptAddress").hide();
|
||||
if (type == 'address') {
|
||||
w = '150px';
|
||||
p = lan.firewall.ip;
|
||||
t = lan.firewall.drop;
|
||||
m = lan.firewall.ip_ps;
|
||||
} else if (type === 'ip_port') {
|
||||
$("#AcceptAddress").show();
|
||||
m = 'NOTE: Only specified IP addresses are allowed to access a port. For example: Only 192.168.0.1 is allowed to access port 8080.';
|
||||
}
|
||||
$("#AcceptPort").css("width",w);
|
||||
$("#AcceptPort").attr('placeholder',p);
|
||||
$("#toAccept").html(t);
|
||||
$("#f-ps").html(m);
|
||||
});
|
||||
},
|
||||
flush_init:function(){
|
||||
bt.firewall.get_ssh_info(function(rdata){
|
||||
if(!rdata.status){
|
||||
$("#mstscSubmit").attr('disabled','disabled')
|
||||
$("#mstscPort").attr('disabled','disabled')
|
||||
$('#sshswitch').removeAttr('checked');
|
||||
}
|
||||
else{
|
||||
$("#mstscSubmit").removeAttr('disabled')
|
||||
$("#mstscPort").removeAttr('disabled')
|
||||
$('#sshswitch').attr('checked','checked');
|
||||
}
|
||||
if(rdata.ping){
|
||||
$('#noping').removeAttr('checked');
|
||||
}else{
|
||||
$('#noping').attr('checked','checked');
|
||||
}
|
||||
$("#mstscPort").val(rdata.port);
|
||||
})
|
||||
},
|
||||
get_logs_size:function(){
|
||||
bt.firewall.get_logs_size(function(rdata){
|
||||
$("#logSize").text(rdata);
|
||||
})
|
||||
},
|
||||
clear_logs_files:function(){
|
||||
bt.firewall.clear_logs_files(function(rdata){
|
||||
$("#logSize").text(rdata);
|
||||
bt.msg({msg:lan.firewall.empty,icon:1});
|
||||
})
|
||||
},
|
||||
add_accept_port:function(){
|
||||
var type = $("#firewalldType").val();
|
||||
var port = $("#AcceptPort").val();
|
||||
var ps = $("#Ps").val();
|
||||
bt.firewall.add_accept_port(type,port,ps,function(rdata){
|
||||
if(rdata.status){
|
||||
firewall.get_list();
|
||||
$("#AcceptPort").val('');
|
||||
$("#Ps").val('');
|
||||
}
|
||||
bt.msg(rdata);
|
||||
})
|
||||
},
|
||||
remove_accept_port: function (id,port) {
|
||||
bt.firewall.del_accept_port(id, port, function (rdata) {
|
||||
if (rdata.status) {
|
||||
firewall.get_list();
|
||||
}
|
||||
bt.msg(rdata);
|
||||
})
|
||||
},
|
||||
get_list:function(page,search){
|
||||
if(page==undefined) page=1;
|
||||
$.post('/firewall_new?action=GetList', { p: page, search: search,collback:'firewall.get_list' }, function (rdata) {
|
||||
|
||||
$('.firewallBody').html(rdata.page);
|
||||
var ports_ps = { "3306": "MySQL service default port", "888": "phpMyAdmin default port", "22": "SSH remote service", "20": "FTP active mode data port", "21": "FTP protocol default port", "39000-40000": "FTP passive mode port range", "30000-40000": "FTP passive mode port range","11211":"Memcached service port","873":"Rsync data synchronization service","8888":"aaPanel Linux panel default port"}
|
||||
var _tab = bt.render({
|
||||
table:'#firewallBody',
|
||||
columns:[
|
||||
{ field: 'id', title: "{{data['lan']['TH1']}}"},
|
||||
{ field: 'port', title: "{{data['lan']['TH2']}}",templet:function(item){
|
||||
var _ps = lan.firewall.accept_port;
|
||||
if(bt.contains(item.port,'.')){
|
||||
_ps = lan.firewall.drop_ip;
|
||||
}
|
||||
_ps += ':['+item.port+']'
|
||||
return _ps;
|
||||
}},
|
||||
{ field: 'status', title: "{{data['lan']['TH3']}}",templet:function(item){
|
||||
var status = '';
|
||||
switch(item.status){
|
||||
case 0:
|
||||
status = lan.firewall.status_not;
|
||||
break;
|
||||
case 1:
|
||||
status = lan.firewall.status_net;
|
||||
break;
|
||||
default:
|
||||
status = lan.firewall.status_ok;
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
},help:'https://www.bt.cn/bbs/thread-4708-1-1.html'},
|
||||
{ field: 'addtime', title: "{{data['lan']['TH4']}}"},
|
||||
{ field: 'ps', title: "{{data['lan']['TH5']}}", templet: function (item) {
|
||||
if (item.port in ports_ps) return ports_ps[item.port];
|
||||
return item.ps;
|
||||
}},
|
||||
{ field: 'opt',align:'right',width:50, title: "{{data['lan']['TH6']}}",templet:function(item){
|
||||
return '<a href="javascript:;" class="btlink" onclick="firewall.remove_accept_port('+item.id+',\''+item.port+'\')">Delete</a>';
|
||||
}}
|
||||
],
|
||||
data:rdata.data
|
||||
})
|
||||
})
|
||||
},
|
||||
get_log_list:function(page,search){
|
||||
if (page == undefined) page = 1;
|
||||
if (search == undefined) search = $("#SearchValue").val();
|
||||
bt.firewall.get_log_list(page,search,function(rdata){
|
||||
$('.logsBody').html(rdata.page);
|
||||
var _tab = bt.render({
|
||||
table:'#logsBody',
|
||||
columns:[
|
||||
{ field: 'id', title: "{{data['lan']['LTH1']}}"},
|
||||
{ field: 'type', title: "{{data['lan']['LTH2']}}"},
|
||||
{ field: 'log', title: "{{data['lan']['LTH3']}}"},
|
||||
{ field: 'addtime', title: "{{data['lan']['LTH4']}}"}
|
||||
],
|
||||
data:rdata.data
|
||||
})
|
||||
})
|
||||
},
|
||||
//查看面板运行日志
|
||||
get_panel_error_logs: function () {
|
||||
layer.msg(lan.public.the_get, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/config?action=get_panel_error_logs', {}, function (rdata) {
|
||||
layer.closeAll();
|
||||
if (!rdata.status) {
|
||||
layer.msg(rdata.msg, { icon: 2 });
|
||||
return;
|
||||
};
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: 'Panel run log',
|
||||
area: ['700px', '490px'],
|
||||
shadeClose: false,
|
||||
closeBtn: 2,
|
||||
content: '<div class="setchmod bt-form pb70">'
|
||||
+ '<pre class="crontab-log" style="overflow: auto; border: 0px none; line-height:23px;padding: 15px; margin: 0px; white-space: pre-wrap; height: 405px; background-color: rgb(51,51,51);color:#f1f1f1;border-radius:0px;font-family: \"微软雅黑\"">' + (rdata.msg == '' ? 'Current log is empty' : rdata.msg) + '</pre>'
|
||||
+ '<div class="bt-form-submit-btn" style="margin-top: 0px;">'
|
||||
+ '<button type="button" class="btn btn-danger btn-sm btn-title" style="margin-right:15px;" onclick="firewall.clean_panel_error_logs()">' + lan.public.empty + '</button>'
|
||||
+ '<button type="button" class="btn btn-success btn-sm btn-title" onclick="layer.closeAll()">' + lan.public.close + '</button>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
});
|
||||
setTimeout(function () {
|
||||
$("#crontab-log").text(rdata.msg);
|
||||
var div = document.getElementsByClassName('crontab-log')[0]
|
||||
div.scrollTop = div.scrollHeight;
|
||||
}, 200)
|
||||
}).error(function () {
|
||||
layer.closeAll();
|
||||
layer.msg('Unable to get log!', { icon: 2 });
|
||||
});
|
||||
},
|
||||
//清空面板错误日志
|
||||
clean_panel_error_logs:function() {
|
||||
layer.msg(lan.public.the_get, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/config?action=clean_panel_error_logs', {}, function (rdata) {
|
||||
layer.closeAll();
|
||||
layer.msg(rdata.msg, { icon: 1 });
|
||||
});
|
||||
}
|
||||
}
|
||||
firewall.get_init();
|
||||
</script>
|
||||
{% endblock %}
|
||||
+7
-46
@@ -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.1.5'
|
||||
g.version = '6.2.0'
|
||||
g.title = public.GetConfigValue('title')
|
||||
g.uri = request.path
|
||||
session['version'] = g.version;
|
||||
@@ -42,36 +42,18 @@ class panelAdmin(panelSetup):
|
||||
def local(self):
|
||||
result = panelSetup().init()
|
||||
if result: return result
|
||||
result = self.checkLimitIp()
|
||||
if result: return result
|
||||
result = self.setSession();
|
||||
if result: return result
|
||||
result = self.checkClose();
|
||||
if result: return result
|
||||
result = self.checkWebType();
|
||||
if result: return result
|
||||
result = self.checkDomain();
|
||||
result = self.check_login();
|
||||
if result: return result
|
||||
result = self.checkConfig();
|
||||
#self.checkSafe();
|
||||
self.GetOS();
|
||||
|
||||
|
||||
#检查IP白名单
|
||||
def checkAddressWhite(self):
|
||||
token = self.GetToken();
|
||||
if not token: return redirect('/login');
|
||||
if not request.remote_addr in token['address']: return redirect('/login');
|
||||
|
||||
|
||||
#检查IP限制
|
||||
def checkLimitIp(self):
|
||||
if os.path.exists('data/limitip.conf'):
|
||||
iplist = public.ReadFile('data/limitip.conf')
|
||||
if iplist:
|
||||
iplist = iplist.strip();
|
||||
if not request.remote_addr in iplist.split(','): return redirect('/login')
|
||||
|
||||
|
||||
|
||||
#设置基础Session
|
||||
def setSession(self):
|
||||
session['menus'] = sorted(json.loads(public.ReadFile('config/menu.json')),key=lambda x:x['sort'])
|
||||
@@ -114,8 +96,8 @@ class panelAdmin(panelSetup):
|
||||
if os.path.exists('data/close.pl'):
|
||||
return redirect('/close');
|
||||
|
||||
#检查域名绑定
|
||||
def checkDomain(self):
|
||||
#检查登录
|
||||
def check_login(self):
|
||||
try:
|
||||
api_check = True
|
||||
if not 'login' in session:
|
||||
@@ -123,10 +105,6 @@ class panelAdmin(panelSetup):
|
||||
if api_check: return api_check
|
||||
else:
|
||||
if session['login'] == False: return redirect('/login')
|
||||
tmp = public.GetHost()
|
||||
domain = public.ReadFile('data/domain.conf')
|
||||
if domain:
|
||||
if(tmp.strip().lower() != domain.strip().lower()): return redirect('/login')
|
||||
if api_check:
|
||||
try:
|
||||
sess_out_path = 'data/session_timeout.pl'
|
||||
@@ -176,24 +154,7 @@ class panelAdmin(panelSetup):
|
||||
session['config']['email'] = public.M('users').where("id=?",('1',)).getField('email');
|
||||
if not 'address' in session:
|
||||
session['address'] = public.GetLocalIp()
|
||||
|
||||
def checkSafe(self):
|
||||
mods = ['/','/site','/ftp','/database','/plugin','/soft','/public'];
|
||||
if not os.path.exists('/www/server/panel/data/userInfo.json'):
|
||||
if 'vip' in session: del(session.vip);
|
||||
if not request.path in mods: return True
|
||||
if 'vip' in session: return True
|
||||
|
||||
import panelAuth
|
||||
data = panelAuth.panelAuth().get_order_status(None);
|
||||
try:
|
||||
if data['status'] == True:
|
||||
session.vip = data
|
||||
return True
|
||||
return redirect('/vpro');
|
||||
except:pass
|
||||
return False
|
||||
|
||||
|
||||
#获取操作系统类型
|
||||
def GetOS(self):
|
||||
if not 'server_os' in session:
|
||||
|
||||
+14
-1
@@ -939,6 +939,19 @@ class config:
|
||||
else:
|
||||
t_str = 'Open'
|
||||
public.writeFile(debug_path,'True')
|
||||
public.WriteLog('TYPE_PANEL','%sDeveloper mode(debug)' % t_str)
|
||||
public.WriteLog('TYPE_PANEL','%s Developer mode(debug)' % t_str)
|
||||
public.restart_panel()
|
||||
return public.returnMsg(True,'Successful setup!')
|
||||
|
||||
|
||||
#设置离线模式
|
||||
def set_local(self,get):
|
||||
d_path = 'data/not_network.pl'
|
||||
if os.path.exists(d_path):
|
||||
t_str = 'Close'
|
||||
os.remove(d_path)
|
||||
else:
|
||||
t_str = 'Open'
|
||||
public.writeFile(d_path,'True')
|
||||
public.WriteLog('TYPE_PANEL','%s Offline mode' % t_str)
|
||||
return public.returnMsg(True,'Successful setup!')
|
||||
+1
-1
@@ -363,7 +363,7 @@ class crontab:
|
||||
shell=wheres[type]
|
||||
except:
|
||||
if type == 'toUrl':
|
||||
shell = head + "curl -sS --connect-timeout 10 -m 60 '" + param['urladdress']+"'";
|
||||
shell = head + "curl -sS --connect-timeout 10 -m 3600 '" + param['urladdress']+"'";
|
||||
else:
|
||||
shell=head+param['sBody'].replace("\r\n","\n")
|
||||
|
||||
|
||||
+4
-4
@@ -102,7 +102,7 @@ class database(datatool.datatools):
|
||||
if "libmysqlclient" in mysqlMsg:
|
||||
result = self.rep_lnk()
|
||||
os.system("pip uninstall mysql-python -y")
|
||||
os.system("pip install mysql-python")
|
||||
os.system("pip install pymysql")
|
||||
public.writeFile('data/restart.pl','True')
|
||||
return public.returnMsg(False,"MYSQL_FIX_WITH_AUTO_ERR")
|
||||
return None
|
||||
@@ -299,7 +299,7 @@ SetLink
|
||||
def SetupPassword(self,get):
|
||||
password = get['password'].strip()
|
||||
try:
|
||||
rep = "^[\w@\.]+$"
|
||||
rep = "^[\w@\.\?\-\_\>\<\~\!\#\$\%\^\&\*\(\)]+$"
|
||||
if not re.match(rep, password): return public.returnMsg(False, 'DATABASE_NAME_ERR_T')
|
||||
mysql_root = public.M('config').where("id=?",(1,)).getField('mysql_root')
|
||||
#修改MYSQL
|
||||
@@ -343,7 +343,7 @@ SetLink
|
||||
id = get['id']
|
||||
name = public.M('databases').where('id=?',(id,)).getField('name');
|
||||
|
||||
rep = "^[\w@\.]+$"
|
||||
rep = "^[\w@\.\?\-\_\>\<\~\!\#\$\%\^\&\*\(\)]+$"
|
||||
if len(re.search(rep, newpassword).groups()) > 0: return public.returnMsg(False, 'DATABASE_NAME_ERR_T')
|
||||
|
||||
#修改MYSQL
|
||||
@@ -447,7 +447,7 @@ SetLink
|
||||
tmpFile = tmpFile.replace('.' + ext, '.sql')
|
||||
tmpFile = tmpFile.replace('tar.', '')
|
||||
backupPath = session['config']['backup_path'] + '/database'
|
||||
|
||||
|
||||
if ext == 'zip':
|
||||
public.ExecShell("cd " + backupPath + " && unzip " + file)
|
||||
else:
|
||||
|
||||
+42
-6
@@ -707,7 +707,8 @@ class files:
|
||||
else:
|
||||
data['data'] = srcBody.decode('utf-8')
|
||||
data['encoding'] = u'utf-8';
|
||||
|
||||
if hasattr(get,'filename'): get.path = get.filename
|
||||
data['historys'] = self.get_history(get.path)
|
||||
return data;
|
||||
except Exception as ex:
|
||||
return public.returnMsg(False,'INCOMPATIBLE_FILECODE',(str(ex)),)
|
||||
@@ -744,12 +745,14 @@ class files:
|
||||
pass
|
||||
|
||||
if get.encoding == 'ascii':get.encoding = 'utf-8';
|
||||
self.save_history(get.path)
|
||||
if sys.version_info[0] == 2:
|
||||
data = data.encode(get.encoding,errors='ignore');
|
||||
fp = open(get.path,'w+')
|
||||
else:
|
||||
data = data.encode(get.encoding,errors='ignore').decode(get.encoding);
|
||||
fp = open(get.path,'w+',encoding=get.encoding)
|
||||
|
||||
fp.write(data)
|
||||
fp.close()
|
||||
|
||||
@@ -767,7 +770,39 @@ class files:
|
||||
except Exception as ex:
|
||||
return public.returnMsg(False,'FILE_SAVE_ERR' + str(ex));
|
||||
|
||||
|
||||
#保存历史副本
|
||||
def save_history(self,filename):
|
||||
try:
|
||||
save_path = ('/www/backup/file_history/' + filename).replace('//','/')
|
||||
if not os.path.exists(save_path): os.makedirs(save_path,384)
|
||||
public.writeFile(save_path + '/' + str(int(time.time())),public.readFile(filename,'rb'),'wb')
|
||||
his_list = sorted(os.listdir(save_path))
|
||||
num = public.readFile('data/history_num.pl')
|
||||
if not num:
|
||||
num = 10
|
||||
else:
|
||||
num = int(num)
|
||||
d_num = len(his_list)
|
||||
for i in range(d_num):
|
||||
if d_num <= num: break;
|
||||
rm_file = save_path + '/' + his_list[i]
|
||||
if os.path.exists(rm_file): os.remove(rm_file)
|
||||
except:pass
|
||||
|
||||
#取历史副本
|
||||
def get_history(self,filename):
|
||||
try:
|
||||
save_path = ('/www/backup/file_history/' + filename).replace('//','/')
|
||||
if not os.path.exists(save_path): return []
|
||||
return sorted(os.listdir(save_path))
|
||||
except: return []
|
||||
|
||||
#读取指定历史副本
|
||||
def read_history(self,args):
|
||||
save_path = ('/www/backup/file_history/' + args.filename).replace('//','/')
|
||||
args.path = save_path + '/' + args.history
|
||||
return self.GetFileBody(args)
|
||||
|
||||
#文件压缩
|
||||
def Zip(self,get) :
|
||||
if not 'z_type' in get: get.z_type = 'rar'
|
||||
@@ -821,10 +856,11 @@ class files:
|
||||
|
||||
def SetFileAccept(self,filename):
|
||||
os.system('chown -R www:www ' + filename)
|
||||
os.system('chmod -R 644 ' + filename)
|
||||
|
||||
|
||||
|
||||
if os.path.isfile(filename):
|
||||
os.system('chmod -R 644 ' + filename)
|
||||
else:
|
||||
os.system('chmod -R 755 ' + filename)
|
||||
|
||||
#取目录大小
|
||||
def GetDirSize(self,get):
|
||||
if sys.version_info[0] == 2: get.path = get.path.encode('utf-8');
|
||||
|
||||
@@ -89,6 +89,17 @@ class firewalls:
|
||||
data['accept'][i]['address'],addtime))
|
||||
except:
|
||||
return public.get_error_info()
|
||||
count = public.M('firewall').count();
|
||||
data = {}
|
||||
data['page'] = public.get_page(count,int(get.p),12,get.collback)
|
||||
data['data'] = public.M('firewall').limit(data['page']['shift'] + ',' + data['page']['row']).order('id desc').select()
|
||||
for i in range(len(data['data'])):
|
||||
if data['data'][i]['port'].find(':') != -1 or data['data'][i]['port'].find('.') != -1 or data['data'][i]['port'].find('-') != -1:
|
||||
data['data'][i]['status'] = -1;
|
||||
else:
|
||||
data['data'][i]['status'] = public.check_port_stat(int(data['data'][i]['port']));
|
||||
|
||||
data['page'] = data['page']['page']
|
||||
return data
|
||||
except Exception as ex:
|
||||
return public.get_error_info()
|
||||
|
||||
+2
-1
@@ -110,13 +110,14 @@ class firewalls:
|
||||
#添加放行端口
|
||||
def AddAcceptPort(self,get):
|
||||
import re
|
||||
src_port = get.port
|
||||
get.port = get.port.replace('-',':')
|
||||
rep = "^\d{1,5}(:\d{1,5})?$"
|
||||
if not re.search(rep,get.port): return public.returnMsg(False,'PORT_CHECK_RANGE');
|
||||
import time
|
||||
port = get.port
|
||||
ps = get.ps
|
||||
if public.M('firewall').where("port=?",(port,)).count() > 0: return public.returnMsg(False,'FIREWALL_PORT_EXISTS')
|
||||
if public.M('firewall').where("port=? or port=?",(port,src_port)).count() > 0: return public.returnMsg(False,'FIREWALL_PORT_EXISTS')
|
||||
notudps = ['80','443','8888','888','39000:40000','21','22']
|
||||
if self.__isUfw:
|
||||
public.ExecShell('ufw allow ' + port + '/tcp');
|
||||
|
||||
+36
-1
@@ -49,6 +49,9 @@ def control_init():
|
||||
if md51 != md52:
|
||||
import shutil
|
||||
shutil.copyfile(src_file,init_file)
|
||||
if os.path.getsize(init_file) < 10:
|
||||
os.system("chattr -i " + init_file)
|
||||
os.system("\cp -arf %s %s" % (src_file,init_file))
|
||||
except:pass
|
||||
public.writeFile('/var/bt_setupPath.conf','/www')
|
||||
public.ExecShell(c)
|
||||
@@ -63,7 +66,39 @@ def control_init():
|
||||
public.ExecShell("chown -R root:root /www/server/panel/config")
|
||||
#disable_putenv('putenv')
|
||||
clean_session()
|
||||
set_crond()
|
||||
#set_crond()
|
||||
clean_max_log('/www/server/panel/plugin/rsync/lsyncd.log')
|
||||
remove_tty1()
|
||||
clean_hook_log()
|
||||
|
||||
#清理webhook日志
|
||||
def clean_hook_log():
|
||||
path = '/www/server/panel/plugin/webhook/script'
|
||||
if not os.path.exists(path): return False
|
||||
for name in os.listdir(path):
|
||||
if name[-4:] != ".log": continue;
|
||||
clean_max_log(path+'/' + name,524288)
|
||||
|
||||
#清理大日志
|
||||
def clean_max_log(log_file,max_size = 104857600,old_line = 100):
|
||||
if not os.path.exists(log_file): return False
|
||||
if os.path.getsize(log_file) > max_size:
|
||||
try:
|
||||
old_body = public.GetNumLines(log_file,old_line)
|
||||
public.writeFile(log_file,old_body)
|
||||
except:
|
||||
print(public.get_error_info())
|
||||
|
||||
#删除tty1
|
||||
def remove_tty1():
|
||||
file_path = '/etc/systemd/system/getty@tty1.service'
|
||||
if not os.path.exists(file_path): return False
|
||||
if not os.path.islink(file_path): return False
|
||||
if os.readlink(file_path) != '/dev/null': return False
|
||||
try:
|
||||
os.remove(file_path)
|
||||
except:pass
|
||||
|
||||
|
||||
#默认禁用指定PHP函数
|
||||
def disable_putenv(fun_name):
|
||||
|
||||
+15
-13
@@ -20,19 +20,21 @@ class panelAuth:
|
||||
__product_id = '100000011';
|
||||
|
||||
def create_serverid(self,get):
|
||||
userPath = 'data/userInfo.json';
|
||||
if not os.path.exists(userPath): return public.returnMsg(False,'LOGIN_FIRST');
|
||||
tmp = public.readFile(userPath);
|
||||
if len(tmp) < 2: tmp = '{}'
|
||||
data = json.loads(tmp);
|
||||
if not data: return public.returnMsg(False,'LOGIN_FIRST');
|
||||
if not hasattr(data,'serverid'):
|
||||
s1 = self.get_mac_address() + self.get_hostname()
|
||||
s2 = self.get_cpuname();
|
||||
serverid = public.md5(s1) + public.md5(s2);
|
||||
data['serverid'] = serverid;
|
||||
public.writeFile(userPath,json.dumps(data));
|
||||
return data;
|
||||
try:
|
||||
userPath = 'data/userInfo.json';
|
||||
if not os.path.exists(userPath): return public.returnMsg(False,'LOGIN_FIRST');
|
||||
tmp = public.readFile(userPath);
|
||||
if len(tmp) < 2: tmp = '{}'
|
||||
data = json.loads(tmp);
|
||||
if not data: return public.returnMsg(False,'LOGIN_FIRST');
|
||||
if not hasattr(data,'serverid'):
|
||||
s1 = self.get_mac_address() + self.get_hostname()
|
||||
s2 = self.get_cpuname();
|
||||
serverid = public.md5(s1) + public.md5(s2);
|
||||
data['serverid'] = serverid;
|
||||
public.writeFile(userPath,json.dumps(data));
|
||||
return data;
|
||||
except: return public.returnMsg(False,'LOGIN_FIRST');
|
||||
|
||||
|
||||
def create_plugin_other_order(self,get):
|
||||
|
||||
+3
-3
@@ -83,15 +83,15 @@ class panelLets:
|
||||
def get_error(self,error):
|
||||
|
||||
if error.find("Max checks allowed") >= 0 :
|
||||
return "CA server verification timed out, please wait 5-10 minutes and try again."
|
||||
return "CA can't verify your domain name, please check if the domain name resolution is correct, or wait 5-10 minutes and try again."
|
||||
elif error.find("Max retries exceeded with") >= 0:
|
||||
return "The CA server connection timed out, please make sure the server network is unobstructed."
|
||||
return "The CA server connection timed out, please try again later."
|
||||
elif error.find("The domain name belongs") >= 0:
|
||||
return "The domain name does not belong to this DNS service provider. Please ensure that the domain name is filled in correctly."
|
||||
elif error.find('login token ID is invalid') >=0:
|
||||
return 'The DNS server connection failed. Please check if the key is correct.'
|
||||
elif "too many certificates already issued for exact set of domains" in error or "Error creating new account :: too many registrations for this IP" in error:
|
||||
return '<h2>The signing failed, and the number of attempts to apply for a certificate today has reached the limit!</h2>'
|
||||
return '<h2>You have failed more than 5 verifications in 1 hour. Please wait 1 hour and try again.</h2>'
|
||||
elif "DNS problem: NXDOMAIN looking up A for" in error or "No valid IP addresses found for" in error or "Invalid response from" in error:
|
||||
return '<h2>The signing failed, the domain name resolution error, or the resolution is not valid, or the domain name is not filed!</h2>'
|
||||
elif error.find('TLS Web Server Authentication') != -1:
|
||||
|
||||
@@ -260,7 +260,7 @@ class panelPlugin:
|
||||
import panelAuth
|
||||
pdata = panelAuth.panelAuth().create_serverid(None)
|
||||
listTmp = public.httpPost(cloudUrl,pdata,10)
|
||||
if len(listTmp) < 200:
|
||||
if not listTmp or len(listTmp) < 200:
|
||||
listTmp = public.readFile(lcoalTmp)
|
||||
try:
|
||||
softList = json.loads(listTmp)
|
||||
@@ -1554,7 +1554,11 @@ class panelPlugin:
|
||||
try:
|
||||
if not public.path_safe_check("%s/%s" % (get.name,get.s)): return public.returnMsg(False,'PLUGIN_INPUT_C');
|
||||
path = self.__install_path + '/' + get.name
|
||||
if not os.path.exists(path + '/'+get.name+'_main.py'): return public.returnMsg(False,'PLUGIN_INPUT_B');
|
||||
if not os.path.exists(path + '/'+get.name+'_main.py'):
|
||||
if os.path.exists(path+'/index.php'):
|
||||
import panelPHP
|
||||
return panelPHP.panelPHP(get.name).exec_php_script(get)
|
||||
return public.returnMsg(False,'PLUGIN_INPUT_B');
|
||||
if not self.check_accept(get):return public.returnMsg(False,public.to_string([24744, 26410, 36141, 20080, 91, 37, 115, 93, 25110, 25480, 26435, 24050, 21040, 26399, 33]) % (self.get_title_byname(get),))
|
||||
sys.path.append(path);
|
||||
plugin_main = __import__(get.name+'_main');
|
||||
|
||||
+8
-4
@@ -31,10 +31,14 @@ class panelSSL:
|
||||
self.__userInfo = {}
|
||||
else:
|
||||
self.__userInfo = {}
|
||||
|
||||
if self.__userInfo:
|
||||
pdata['access_key'] = self.__userInfo['access_key'];
|
||||
data['secret_key'] = self.__userInfo['secret_key'];
|
||||
try:
|
||||
if self.__userInfo:
|
||||
pdata['access_key'] = self.__userInfo['access_key'];
|
||||
data['secret_key'] = self.__userInfo['secret_key'];
|
||||
except:
|
||||
self.__userInfo = {}
|
||||
pdata['access_key'] = 'test';
|
||||
data['secret_key'] = '123456';
|
||||
else:
|
||||
pdata['access_key'] = 'test';
|
||||
data['secret_key'] = '123456';
|
||||
|
||||
+27
-11
@@ -759,7 +759,7 @@ class panelSite(panelRedirect):
|
||||
|
||||
sql.table('domain').where("id=?",(find['id'],)).delete();
|
||||
public.WriteLog('TYPE_SITE', 'DOMAIN_DEL_SUCCESS',(get.webname,get.domain));
|
||||
public.serviceReload();
|
||||
public.serviceReload()
|
||||
return public.returnMsg(True,'DEL_SUCCESS');
|
||||
|
||||
#检查域名是否解析
|
||||
@@ -856,7 +856,7 @@ class panelSite(panelRedirect):
|
||||
|
||||
for domain in domains:
|
||||
if public.checkIp(domain): continue;
|
||||
if domain.find('*.') >=0 and not file_auth:
|
||||
if domain.find('*.') >= 0 and file_auth:
|
||||
return public.returnMsg(False, 'A generic domain name cannot be used to apply for a certificate using [File Validation]!');
|
||||
|
||||
if file_auth:
|
||||
@@ -901,7 +901,7 @@ class panelSite(panelRedirect):
|
||||
return result
|
||||
|
||||
def get_site_info(self,siteName):
|
||||
data = public.M("sites").where('name=?',siteName).field('path,name').find()
|
||||
data = public.M("sites").where('name=?',siteName).field('id,path,name').find()
|
||||
return data
|
||||
|
||||
|
||||
@@ -2439,6 +2439,11 @@ server
|
||||
return f.SaveFileBody(get)
|
||||
# return public.returnMsg(True, '保存成功')
|
||||
|
||||
# 检查是否存在#Set Nginx Cache
|
||||
def check_annotate(self,data):
|
||||
rep = "\n\s*#Set\s*Nginx\s*Cache"
|
||||
if re.search(rep,data):
|
||||
return True
|
||||
|
||||
# 修改反向代理
|
||||
def ModifyProxy(self, get):
|
||||
@@ -2477,17 +2482,26 @@ server
|
||||
proxy_cache cache_one;
|
||||
proxy_cache_key $host$uri$is_args$args;
|
||||
proxy_cache_valid 200 304 301 302 %sm;""" % (get.cachetime)
|
||||
cache_rep = '#proxy_set_header\s+Connection\s+"upgrade";'
|
||||
ng_conf = re.sub(cache_rep,'#proxy_set_header Connection "upgrade";\n'+ng_cache,ng_conf)
|
||||
if self.check_annotate(ng_conf):
|
||||
cache_rep = '\n\s*#Set\s*Nginx\s*Cache(.|\n)*no-cache;'
|
||||
ng_conf = re.sub(cache_rep,'\n\t#Set Nginx Cache\n'+ng_cache,ng_conf)
|
||||
else:
|
||||
cache_rep = '#proxy_set_header\s+Connection\s+"upgrade";'
|
||||
ng_conf = re.sub(cache_rep, '\n\t#proxy_set_header Connection "upgrade";\n\t#Set Nginx Cache' + ng_cache,
|
||||
ng_conf)
|
||||
else:
|
||||
rep = '\s+proxy_cache\s+cache_one.*[\n\s\w\_\";\$]+m;'
|
||||
ng_conf = re.sub(rep, "", ng_conf)
|
||||
if self.check_annotate(ng_conf):
|
||||
rep = '\n\s*#Set\s*Nginx\s*Cache(.|\n)*1m;'
|
||||
ng_conf = re.sub(rep, "\n\t#Set Nginx Cache\n\tadd_header Cache-Control no-cache;", ng_conf)
|
||||
else:
|
||||
rep = '\s+proxy_cache\s+cache_one.*[\n\s\w\_\";\$]+m;'
|
||||
ng_conf = re.sub(rep, '\n\t#Set Nginx Cache\n\tadd_header Cache-Control no-cache;', ng_conf)
|
||||
|
||||
sub_rep = "sub_filter"
|
||||
subfilter = json.loads(get.subfilter)
|
||||
if str(proxyUrl[i]["subfilter"]) != str(subfilter):
|
||||
if re.search(sub_rep, ng_conf):
|
||||
sub_rep = "\s+proxy_set_header\s+Accept-Encoding.*[\n\s\w\_\";]+off;"
|
||||
sub_rep = "\s+proxy_set_header\s+Accept-Encoding(.|\n)+off;"
|
||||
ng_conf = re.sub(sub_rep,"",ng_conf)
|
||||
|
||||
# 构造替换字符串
|
||||
@@ -2582,8 +2596,9 @@ location %s
|
||||
#proxy_http_version 1.1;
|
||||
#proxy_set_header Upgrade $http_upgrade;
|
||||
#proxy_set_header Connection "upgrade";
|
||||
|
||||
add_header X-Cache $upstream_cache_status;
|
||||
|
||||
#Set Nginx Cache
|
||||
%s
|
||||
%s
|
||||
}
|
||||
@@ -2617,14 +2632,14 @@ location %s
|
||||
get.proxydir, get.proxydir,get.proxysite, get.todomain, public.GetMsg("NGINX_PERSISTENCE") ,ng_sub_filter, ng_cache ,get.proxydir)
|
||||
if type == 1 and cache == 0:
|
||||
ng_proxy_cache += ng_proxy % (
|
||||
get.proxydir, get.proxydir, get.proxysite, get.todomain, public.GetMsg("NGINX_PERSISTENCE") ,ng_sub_filter,'' ,get.proxydir)
|
||||
get.proxydir, get.proxydir, get.proxysite, get.todomain, public.GetMsg("NGINX_PERSISTENCE") ,ng_sub_filter,'\tadd_header Cache-Control no-cache;' ,get.proxydir)
|
||||
else:
|
||||
if type == 1 and cache == 1:
|
||||
ng_proxy_cache += ng_proxy % (
|
||||
get.proxydir, get.proxydir, get.proxysite, get.todomain, public.GetMsg("NGINX_PERSISTENCE") ,ng_sub_filter, ng_cache, get.proxydir)
|
||||
if type == 1 and cache == 0:
|
||||
ng_proxy_cache += ng_proxy % (
|
||||
get.proxydir, get.proxydir, get.proxysite, get.todomain, public.GetMsg("NGINX_PERSISTENCE") ,ng_sub_filter, '', get.proxydir)
|
||||
get.proxydir, get.proxydir, get.proxysite, get.todomain, public.GetMsg("NGINX_PERSISTENCE") ,ng_sub_filter, '\tadd_header Cache-Control no-cache;', get.proxydir)
|
||||
public.writeFile(ng_proxyfile, ng_proxy_cache)
|
||||
|
||||
|
||||
@@ -3348,6 +3363,7 @@ location %s
|
||||
#设置防盗链
|
||||
def SetSecurity(self,get):
|
||||
if len(get.fix) < 2: return public.returnMsg(False,'URL_SUFFIX_NOT_EMPTY!');
|
||||
if len(get.domains) < 3: return public.returnMsg(False,'Anti-theft chain domain name cannot be empty!');
|
||||
file = '/www/server/panel/vhost/nginx/' + get.name + '.conf';
|
||||
if os.path.exists(file):
|
||||
conf = public.readFile(file);
|
||||
|
||||
+7
-1
@@ -133,6 +133,7 @@ class bt_task:
|
||||
down_file = downloadFile.downloadFile()
|
||||
down_file.logPath = log_file
|
||||
print(down_file.DownloadFile(task_shell,other))
|
||||
os.system("chown www.www {}".format(other))
|
||||
elif task_type == 2: #解压文件
|
||||
zip_info = json.loads(other)
|
||||
self._unzip(task_shell,zip_info['dfile'],zip_info['password'],log_file)
|
||||
@@ -379,7 +380,12 @@ class bt_task:
|
||||
#设置权限
|
||||
def set_file_accept(self,filename):
|
||||
os.system('chown -R www:www ' + filename)
|
||||
os.system('chmod -R 755 ' + filename)
|
||||
# os.system('chmod -R 755 ' + filename)
|
||||
a = 'find {filename} -type d |xargs chmod 0755'.format(filename=filename)
|
||||
public.writeFile("/tmp/2",str(a))
|
||||
os.system(a)
|
||||
os.system('find {filename} -type f |xargs chmod 0644'.format(filename=filename))
|
||||
|
||||
|
||||
#检查敏感目录
|
||||
def check_dir(self,path):
|
||||
|
||||
+93
-24
@@ -29,6 +29,8 @@ def HttpGet(url,timeout = 6,headers = {}):
|
||||
@timeout 超时时间默认60秒
|
||||
return string
|
||||
"""
|
||||
|
||||
if is_local(): return False
|
||||
home = 'www.bt.cn'
|
||||
host_home = 'data/home_host.pl'
|
||||
old_url = url
|
||||
@@ -104,6 +106,7 @@ def HttpPost(url,data,timeout = 6,headers = {}):
|
||||
@timeout 超时时间默认60秒
|
||||
return string
|
||||
"""
|
||||
if is_local(): return False
|
||||
home = 'www.bt.cn'
|
||||
host_home = 'data/home_host.pl'
|
||||
old_url = url
|
||||
@@ -1289,25 +1292,22 @@ def get_path_size(path):
|
||||
size_total += os.path.getsize(filename)
|
||||
return size_total
|
||||
|
||||
|
||||
# 写关键请求日志
|
||||
def write_request_log():
|
||||
#写关键请求日志
|
||||
def write_request_log(reques = None):
|
||||
try:
|
||||
log_path = '/www/server/panel/logs/request'
|
||||
log_file = getDate(format='%Y-%m-%d') + '.json'
|
||||
if not os.path.exists(log_path): os.makedirs(log_path)
|
||||
|
||||
from flask import request
|
||||
log_data = {}
|
||||
log_data['date'] = getDate()
|
||||
log_data['ip'] = GetClientIp()
|
||||
log_data['method'] = request.method
|
||||
log_data['uri'] = request.full_path
|
||||
log_data['user-agent'] = request.headers.get('User-Agent')
|
||||
WriteFile(log_path + '/' + log_file, json.dumps(log_data) + "\n", 'a+')
|
||||
except:
|
||||
pass
|
||||
|
||||
log_data = []
|
||||
log_data.append(getDate())
|
||||
log_data.append(GetClientIp())
|
||||
log_data.append(request.method)
|
||||
log_data.append(request.full_path)
|
||||
log_data.append(request.headers.get('User-Agent'))
|
||||
WriteFile(log_path + '/' + log_file,json.dumps(log_data) + "\n",'a+')
|
||||
except: pass
|
||||
|
||||
# 重载模块
|
||||
def mod_reload(mode):
|
||||
@@ -1337,9 +1337,11 @@ def set_own(filename, user, group=None):
|
||||
from pwd import getpwnam
|
||||
try:
|
||||
user_info = getpwnam(user)
|
||||
# user_info = getpwnam('www')
|
||||
user = user_info.pw_uid
|
||||
if group:
|
||||
user_info = getpwnam(group)
|
||||
# user_info = getpwnam('www')
|
||||
group = user_info.pw_gid
|
||||
except:
|
||||
# 如果指定用户或组不存在,则使用www
|
||||
@@ -1433,18 +1435,85 @@ def de_crypt(key,strings):
|
||||
return strings
|
||||
|
||||
|
||||
# 取通用对象
|
||||
#检查IP白名单
|
||||
def check_ip_panel():
|
||||
ip_file = 'data/limitip.conf'
|
||||
if os.path.exists(ip_file):
|
||||
iplist = ReadFile(ip_file)
|
||||
if iplist:
|
||||
iplist = iplist.strip();
|
||||
if not GetClientIp() in iplist.split(','):
|
||||
errorStr = ReadFile('./BTPanel/templates/' + GetConfigValue('template') + '/error2.html')
|
||||
try:
|
||||
errorStr = errorStr.format(getMsg('PAGE_ERR_TITLE'),getMsg('PAGE_ERR_IP_H1'),getMsg('PAGE_ERR_IP_P1',(GetClientIp(),)),getMsg('PAGE_ERR_IP_P2'),getMsg('PAGE_ERR_IP_P3'),getMsg('NAME'),getMsg('PAGE_ERR_HELP'))
|
||||
except IndexError:pass
|
||||
return errorStr
|
||||
return False
|
||||
|
||||
#检查面板域名
|
||||
def check_domain_panel():
|
||||
tmp = GetHost()
|
||||
domain = ReadFile('data/domain.conf')
|
||||
if domain:
|
||||
if tmp.strip().lower() != domain.strip().lower():
|
||||
errorStr = ReadFile('./BTPanel/templates/' + GetConfigValue('template') + '/error2.html')
|
||||
try:
|
||||
errorStr = errorStr.format(getMsg('PAGE_ERR_TITLE'),getMsg('PAGE_ERR_DOMAIN_H1'),getMsg('PAGE_ERR_DOMAIN_P1'),getMsg('PAGE_ERR_DOMAIN_P2'),getMsg('PAGE_ERR_DOMAIN_P3'),getMsg('NAME'),getMsg('PAGE_ERR_HELP'))
|
||||
except IndexError:pass
|
||||
return errorStr
|
||||
return False
|
||||
|
||||
#是否离线模式
|
||||
def is_local():
|
||||
s_file = '/www/server/panel/data/not_network.pl'
|
||||
return os.path.exists(s_file)
|
||||
|
||||
|
||||
#自动备份面板数据
|
||||
def auto_backup_panel():
|
||||
b_path = '/www/backup/panel'
|
||||
backup_path = b_path + '/' + format_date('%Y-%m-%d')
|
||||
panel_paeh = '/www/server/panel'
|
||||
if os.path.exists(backup_path): return True
|
||||
os.makedirs(backup_path,384)
|
||||
import shutil
|
||||
shutil.copytree(panel_paeh + '/data',backup_path + '/data')
|
||||
shutil.copytree(panel_paeh + '/config',backup_path + '/config')
|
||||
time_now = time.time() - (86400 * 15)
|
||||
for f in os.listdir(b_path):
|
||||
try:
|
||||
if time.mktime(time.strptime(f, "%Y-%m-%d")) < time_now:
|
||||
path = b_path + '/' + f
|
||||
if os.path.exists(path): shutil.rmtree(path)
|
||||
except: continue
|
||||
|
||||
|
||||
#检查端口状态
|
||||
def check_port_stat(port):
|
||||
import socket
|
||||
localIP = '127.0.0.1';
|
||||
temp = {}
|
||||
temp['port'] = port;
|
||||
temp['local'] = True;
|
||||
try:
|
||||
s = socket.socket()
|
||||
s.settimeout(0.15)
|
||||
s.connect((localIP,port))
|
||||
s.close()
|
||||
except:
|
||||
temp['local'] = False;
|
||||
|
||||
result = 0;
|
||||
if temp['local']: result +=2;
|
||||
return result;
|
||||
|
||||
#取通用对象
|
||||
class dict_obj:
|
||||
def __contains__(self, key):
|
||||
return getattr(self, key, None)
|
||||
|
||||
def __setitem__(self, key, value): setattr(self, key, value)
|
||||
|
||||
def __getitem__(self, key): return getattr(self, key, None)
|
||||
|
||||
def __delitem__(self, key): delattr(self, key)
|
||||
|
||||
def __delattr__(self, key): delattr(self, key)
|
||||
|
||||
return getattr(self,key,None)
|
||||
def __setitem__(self, key, value): setattr(self,key,value)
|
||||
def __getitem__(self, key): return getattr(self,key,None)
|
||||
def __delitem__(self,key): delattr(self,key)
|
||||
def __delattr__(self, key): delattr(self,key)
|
||||
def get_items(self): return self
|
||||
|
||||
|
||||
+4
-1
@@ -273,7 +273,10 @@ class system:
|
||||
#取CPU信息
|
||||
cpuCount = psutil.cpu_count()
|
||||
used = self.get_cpu_percent()
|
||||
return used,cpuCount
|
||||
used_all = psutil.cpu_percent(percpu=True)
|
||||
cpu_name = public.getCpuType()
|
||||
return used,cpuCount,used_all,cpu_name
|
||||
|
||||
|
||||
def GetCpuInfo_new(self):
|
||||
cpuCount = psutil.cpu_count()
|
||||
|
||||
+6
-5
@@ -12,9 +12,9 @@ os.chdir("/www/server/panel")
|
||||
sys.path.append('class/')
|
||||
import public
|
||||
print ('==================================================================')
|
||||
print( '★['+time.strftime("%Y/%m/%d %H:%M:%S")+'],切割日志')
|
||||
print( '★['+time.strftime("%Y/%m/%d %H:%M:%S")+'],Cutting log')
|
||||
print ('==================================================================')
|
||||
print ('|--当前保留最新的['+sys.argv[2]+']份')
|
||||
print ('|--Currently retaining the latest ['+sys.argv[2]+'] copies')
|
||||
logsPath = '/www/wwwlogs/'
|
||||
is_nginx = False
|
||||
if os.path.exists('/www/server/nginx/logs/nginx.pid'): is_nginx = True
|
||||
@@ -24,7 +24,7 @@ if not is_nginx: px = '-access_log'
|
||||
def split_logs(oldFileName,num):
|
||||
global logsPath
|
||||
if not os.path.exists(oldFileName):
|
||||
print('|---'+oldFileName+'文件不存在!')
|
||||
print('|---'+oldFileName+'file does not exist!')
|
||||
return
|
||||
|
||||
logs=sorted(glob.glob(oldFileName+"_*"))
|
||||
@@ -34,11 +34,12 @@ def split_logs(oldFileName,num):
|
||||
for i in range(count):
|
||||
if i>num: break;
|
||||
os.remove(logs[i])
|
||||
print('|---多余日志['+logs[i]+']已删除!')
|
||||
print('|---Extra log ['+logs[i]+'] has been deleted!')
|
||||
|
||||
newFileName=oldFileName+'_'+time.strftime("%Y-%m-%d_%H%M%S")+'.log'
|
||||
shutil.move(oldFileName,newFileName)
|
||||
print('|---已切割日志到:'+newFileName)
|
||||
os.system("gzip %s" % newFileName)
|
||||
print('|---The log has been cut to: '+newFileName+'.gz')
|
||||
|
||||
def split_all(save):
|
||||
sites = public.M('sites').field('name').select()
|
||||
|
||||
@@ -12,9 +12,9 @@ os.chdir("/www/server/panel")
|
||||
sys.path.append('class/')
|
||||
import public
|
||||
print ('==================================================================')
|
||||
print( '★['+time.strftime("%Y/%m/%d %H:%M:%S")+'],切割日志')
|
||||
print( '★['+time.strftime("%Y/%m/%d %H:%M:%S")+'],Cutting log')
|
||||
print ('==================================================================')
|
||||
print ('|--当前保留最新的['+sys.argv[2]+']份')
|
||||
print ('|--Currently retaining the latest ['+sys.argv[2]+'] copies')
|
||||
logsPath = '/www/wwwlogs/'
|
||||
is_nginx = False
|
||||
if os.path.exists('/www/server/nginx/logs/nginx.pid'): is_nginx = True
|
||||
@@ -24,7 +24,7 @@ if not is_nginx: px = '-access_log'
|
||||
def split_logs(oldFileName,num):
|
||||
global logsPath
|
||||
if not os.path.exists(oldFileName):
|
||||
print('|---'+oldFileName+'文件不存在!')
|
||||
print('|---'+oldFileName+'file does not exist!')
|
||||
return
|
||||
|
||||
logs=sorted(glob.glob(oldFileName+"_*"))
|
||||
@@ -34,11 +34,12 @@ def split_logs(oldFileName,num):
|
||||
for i in range(count):
|
||||
if i>num: break;
|
||||
os.remove(logs[i])
|
||||
print('|---多余日志['+logs[i]+']已删除!')
|
||||
print('|---The extra log ['+logs[i]+'] has been deleted!')
|
||||
|
||||
newFileName=oldFileName+'_'+time.strftime("%Y-%m-%d_%H%M%S")+'.log'
|
||||
shutil.move(oldFileName,newFileName)
|
||||
print('|---已切割日志到:'+newFileName)
|
||||
os.system("gzip %s" % newFileName)
|
||||
print('|---The log has been cut to:'+newFileName+'.gz')
|
||||
|
||||
def split_all(save):
|
||||
sites = public.M('sites').field('name').select()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#!/bin/python
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
@@ -438,6 +439,8 @@ def panel_status():
|
||||
panel_url = pool + '127.0.0.1:' + port + '/service_status'
|
||||
panel_pid = get_panel_pid()
|
||||
n = 0
|
||||
s = 0
|
||||
v = 0
|
||||
while True:
|
||||
time.sleep(1)
|
||||
if not panel_pid: panel_pid = get_panel_pid()
|
||||
@@ -455,6 +458,25 @@ def panel_status():
|
||||
continue
|
||||
|
||||
n += 1
|
||||
v += 1
|
||||
|
||||
if v > 10:
|
||||
v = 0
|
||||
log_path = panel_path + '/logs/error.log'
|
||||
if os.path.exists(log_path):
|
||||
e_body = public.GetNumLines(log_path,10)
|
||||
if e_body:
|
||||
if e_body.find('PyWSGIServer.do_close') != -1 or e_body.find('Expected GET method:')!=-1 or e_body.find('Invalid HTTP method:') != -1 or e_body.find('table session') != -1:
|
||||
result = public.httpGet(panel_url)
|
||||
if result != 'True':
|
||||
if e_body.find('table session') != -1:
|
||||
sess_file = '/dev/shm/session.db'
|
||||
if os.path.exists(sess_file): os.remove(sess_file)
|
||||
os.system("/etc/init.d/bt reload &")
|
||||
time.sleep(10)
|
||||
result = public.httpGet(panel_url)
|
||||
if result == 'True':
|
||||
public.WriteLog('TYPE_SOFE','Checked to panel service exception, has been automatically restored!')
|
||||
|
||||
if n > 18000:
|
||||
n = 0
|
||||
@@ -465,7 +487,7 @@ def panel_status():
|
||||
os.system("/etc/init.d/bt reload &")
|
||||
result = public.httpGet(panel_url)
|
||||
if result == 'True':
|
||||
public.WriteLog('守护程序','检查到面板服务异常,已自动恢复!')
|
||||
public.WriteLog('TYPE_SOFE','Checked to panel service exception, has been automatically restored!')
|
||||
time.sleep(10)
|
||||
continue
|
||||
|
||||
|
||||
Reference in New Issue
Block a user