From 57cbf9315c8c155bdc2b38e122e142310daa8c35 Mon Sep 17 00:00:00 2001 From: flucout Date: Sat, 10 Aug 2024 22:55:52 +0800 Subject: [PATCH] wiki --- wiki/files/linux/PluginLoader.py | 373 +++++++++++++------ wiki/files/win/bt.js | 761 ++++++++++++++++++++------------------- wiki/updatewin.md | 2 + 3 files changed, 660 insertions(+), 476 deletions(-) diff --git a/wiki/files/linux/PluginLoader.py b/wiki/files/linux/PluginLoader.py index 41e1975..33cc028 100644 --- a/wiki/files/linux/PluginLoader.py +++ b/wiki/files/linux/PluginLoader.py @@ -1,132 +1,239 @@ #coding: utf-8 -import public,os,sys,json +# +------------------------------------------------------------------- +# | 宝塔Linux面板 +# +------------------------------------------------------------------- +# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved. +# +------------------------------------------------------------------- +# | Author: hwliang +# +------------------------------------------------------------------- -#获取插件列表(0/1) -def get_plugin_list(force = 0): - api_root_url = 'https://api.bt.cn' - api_url = api_root_url+ '/panel/get_plugin_list' - cache_file = 'data/plugin_list.json' - - if force==0 and os.path.exists(cache_file): - jsonData = public.readFile(cache_file) - softList = json.loads(jsonData) - else: - try: - jsonData = public.HttpGet(api_url) - except Exception as ex: - raise public.error_conn_cloud(str(ex)) - softList = json.loads(jsonData) - if type(softList)!=dict or 'list' not in softList: - if type(softList)==str: - raise Exception(softList) - else: - raise Exception('云端插件列表获取失败') - public.writeFile(cache_file, jsonData) - return softList +#+-------------------------------------------------------------------- +#| 插件和模块加载器 +#+-------------------------------------------------------------------- -#获取授权状态() 返回:0.免费版 1.专业版 2.企业版 -1.获取失败 -def get_auth_state(): - try: - softList = get_plugin_list() - if softList['ltd'] > -1: - return 2 - elif softList['pro'] > -1: - return 1 - else: - return 0 - except: - return -1 +import public,os,sys,json -#执行插件方法(插件名,方法名,参数) -def plugin_run(plugin_name, def_name, args): +def plugin_run(plugin_name,def_name,args): + ''' + @name 执行插件方法 + @param plugin_name 插件名称 + @param def_name 方法名称 + @param args 参数对像 + @return mixed + ''' if not plugin_name or not def_name: return public.returnMsg(False,'插件名称和插件方法名称不能为空!') - if not path_check(plugin_name) or not path_check(def_name): return public.returnMsg(False,'插件名或方法名不能包含特殊符号!') - p_path = public.get_plugin_path(plugin_name) - if not os.path.exists(p_path + '/index.php') and not os.path.exists(p_path + '/%s_main.py' % plugin_name): return public.returnMsg(False,'插件不存在!') - is_php = os.path.exists(p_path + '/index.php') - if not is_php: - public.package_path_append(p_path) - plugin_main = __import__(plugin_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.' + plugin_name + '_main()') - if not hasattr(plu, def_name): - return public.returnMsg(False,'在[%s]插件中找不到[%s]方法' % (plugin_name,def_name)) + # 获取插件目录 + plugin_path = public.get_plugin_path(plugin_name) + is_php = os.path.exists(os.path.join(plugin_path,'index.php')) - if 'plugin_get_object' in args and args.plugin_get_object == 1: - if not is_php: - return getattr(plu, def_name) - else: - return None + # 检查插件目录是否合法 + if is_php: + plugin_file = os.path.join(plugin_path,'index.php') else: + plugin_file = os.path.join(plugin_path, plugin_name + '_main.py') + if not public.path_safe_check(plugin_file): return public.returnMsg(False,'插件路径不合法') + + # 检查插件入口文件是否存在 + if not os.path.exists(plugin_file): return public.returnMsg(False,'指定插件入口文件不存在') + + # 添加插件目录到系统路径 + public.sys_path_append(plugin_path) + + try: if not is_php: - data = eval('plu.' + def_name + '(args)') + # 引用插件入口文件 + _name = "{}_main".format(plugin_name) + plugin_main = __import__(_name) + + # 检查类名是否符合规范 + if not hasattr(plugin_main,_name): + return public.returnMsg(False,'指定插件入口文件不符合规范') + + try: + if sys.version_info[0] == 2: + reload(plugin_main) + else: + from imp import reload + reload(plugin_main) + except: + pass + + # 实例化插件类 + plugin_obj = getattr(plugin_main,_name)() + + # 检查方法是否存在 + if not hasattr(plugin_obj,def_name): + return public.returnMsg(False,'在[%s]插件中找不到[%s]方法' % (plugin_name,def_name)) + + if 'plugin_get_object' in args and args.plugin_get_object == 1: + return getattr(plugin_obj, def_name) + + # 执行方法 + return getattr(plugin_obj,def_name)(args) else: + if 'plugin_get_object' in args and args.plugin_get_object == 1: + return None import panelPHP args.s = def_name args.name = plugin_name - data = panelPHP.panelPHP(plugin_name).exec_php_script(args) - return data + return panelPHP.panelPHP(plugin_name).exec_php_script(args) -#执行模块方法(模块名,方法名,参数) -def module_run(mod_name, def_name, args): - if not mod_name or not def_name: return public.returnMsg(False,'模块名称和模块方法名称不能为空!') - if not path_check(mod_name) or not path_check(def_name): return public.returnMsg(False,'模块名或方法名不能包含特殊符号!') + except SyntaxError as ex: + return public.returnMsg(False,'指定插件不兼容当前操作系统') + except Exception as ex: + public.print_error() + return public.returnMsg(False,'指定插件不存在') + - if 'model_index' in args: - if args.model_index: - mod_file = "{}/{}Model/{}Model.py".format(public.get_class_path(),args.model_index,mod_name) +def get_module_list(): + ''' + @name 获取模块列表 + @return list + ''' + module_list = [] + class_path = public.get_class_path() + for name in os.listdir(class_path): + path = os.path.join(class_path,name) + # 过滤无效文件 + if not name or name.endswith('.py') or name[0] == '.' or not name.endswith('Model') or os.path.isfile(path):continue + module_list.append(name) + return module_list + +def module_run(module_name,def_name,args): + ''' + @name 执行模块方法 + @param module_name 模块名称 + @param def_name 方法名称 + @param args 参数对像 + @return mixed + ''' + if not module_name or not def_name: return public.returnMsg(False,'模块名称和模块方法名称不能为空!') + model_index = args.get('model_index',None) + class_path = public.get_class_path() + panel_path = public.get_panel_path() + + module_file = None + if model_index: + # 新模块目录 + if model_index in ['mod']: + _name = "{}Mod".format(module_name) + module_file = os.path.join(panel_path,'mod','project',module_name + 'Mod.py') + elif model_index: + # 旧模块目录 + _name = "{}Model".format(module_name) + module_file = os.path.join(class_path,model_index+"Model",module_name + 'Model.py') else: - mod_file = "{}/projectModel/{}Model.py".format(public.get_class_path(),mod_name) + _name = "{}Model".format(module_name) + module_file = os.path.join(class_path,"projectModel",module_name + 'Model.py') else: + # 如果没指定模块名称,则遍历所有模块目录 module_list = get_module_list() - for module_dir in module_list: - mod_file = "{}/{}/{}Model.py".format(public.get_class_path(),module_dir,mod_name) - if os.path.exists(mod_file): break + for name in module_list: + module_file = os.path.join(class_path,name,module_name + 'Model.py') + if os.path.exists(module_file): + _name = "{}Model".format(module_name) + break + + # 判断模块入口文件是否存在 + if not os.path.exists(module_file): + return public.returnMsg(False,'模块[%s]不存在' % module_name) + + # 判断模块路径是否合法 + if not public.path_safe_check(module_file): + return public.returnMsg(False,'模块路径不合法') + + public.sys_path_append(os.path.dirname(module_file)) + try: + # 引用模块入口文件 + module_main = __import__(_name) - if not os.path.exists(mod_file): - return public.returnMsg(False,'模块[%s]不存在' % mod_name) + # 检查模块是否符合规范 + if not hasattr(module_main,'main'): + return public.returnMsg(False,'指定模块入口文件不符合规范') - def_object = public.get_script_object(mod_file) - if not def_object: return public.returnMsg(False,'模块[%s]不存在!' % mod_name) - try: - run_object = getattr(def_object.main(),def_name,None) - except: - return public.returnMsg(False,'模块入口实例化失败' % mod_name) - if not run_object: return public.returnMsg(False,'在[%s]模块中找不到[%s]方法' % (mod_name,def_name)) - if 'module_get_object' in args and args.module_get_object == 1: - return run_object - result = run_object(args) - return result + # 实例化模块类 + module_obj = getattr(module_main,'main')() + + # 检查方法是否存在 + if not hasattr(module_obj,def_name): + return public.returnMsg(False,'在[%s]模块中找不到[%s]方法' % (module_name,def_name)) + + if 'module_get_object' in args and args.module_get_object == 1: + return getattr(module_obj,def_name) + + # 执行方法 + return getattr(module_obj,def_name)(args) + except SyntaxError as ex: + return public.returnMsg(False,'指定模块不兼容当前操作系统') + except Exception as ex: + public.print_error() + return public.returnMsg(False,'指定模块不存在') + + +def get_plugin_list(upgrade_force = False): + ''' + @name 获取插件列表 + @param upgrade_force 是否强制重新获取列表 + @return dict + ''' + + api_root_url = 'https://api.bt.cn' + api_url = api_root_url+ '/panel/get_plugin_list' + panel_path = public.get_panel_path() + data_path = os.path.join(panel_path,'data') + + if not os.path.exists(data_path): + os.makedirs(data_path,384) + + plugin_list = {} + plugin_list_file = os.path.join(data_path,'plugin_list.json') + if os.path.exists(plugin_list_file) and not upgrade_force: + plugin_list_body = public.readFile(plugin_list_file) + try: + plugin_list = json.loads(plugin_list_body) + except: + plugin_list = {} + + if not os.path.exists(plugin_list_file) or upgrade_force or not plugin_list: + try: + res = public.HttpGet(api_url) + except Exception as ex: + raise public.error_conn_cloud(str(ex)) + if not res: raise Exception(False,'云端插件列表获取失败') + + plugin_list = json.loads(res) + if type(plugin_list)!=dict or 'list' not in plugin_list: + if type(plugin_list)==str: + raise Exception(plugin_list) + else: + raise Exception('云端插件列表获取失败') + public.writeFile(plugin_list_file,json.dumps(plugin_list)) + + return plugin_list + + +def start_total(): + ''' + @name 启动统计服务 + @return dict + ''' + pass + +def get_soft_list(args): + ''' + @name 获取软件列表 + @param args 参数对像 + @return dict + ''' + pass -#获取模块文件夹列表 -def get_module_list(): - list = [] - class_path = public.get_class_path() - f_list = os.listdir(class_path) - for fname in f_list: - f_path = class_path+'/'+fname - if os.path.isdir(f_path) and len(fname) > 6 and fname.find('.') == -1 and fname.find('Model') != -1: - list.append(fname) - return list - -#检查路径是否合法 -def path_check(path): - list = ["./","..",",",";",":","?","'","\"","<",">","|","\\","\n","\r","\t","\b","\a","\f","\v","*","%","&","$","#","@","!","~","`","^","(",")","+","=","{","}","[","]"] - for i in path: - if i in list: - return False - return True - -#数据加密 def db_encrypt(data): + ''' + @name 数据库加密 + @param args 参数对像 + @return dict + ''' try: key = __get_db_sgin() iv = __get_db_iv() @@ -143,8 +250,12 @@ def db_encrypt(data): } return result -#数据解密 def db_decrypt(data): + ''' + @name 数据库解密 + @param args 参数对像 + @return dict + ''' try: key = __get_db_sgin() iv = __get_db_iv() @@ -215,3 +326,49 @@ def __aes_encrypt(data, key, iv): encryptedbytes = aes.encrypt(data) en_text = base64.b64encode(encryptedbytes) return en_text.decode('utf-8') + +def plugin_end(): + ''' + @name 插件到期处理 + @return dict + ''' + pass + +def daemon_task(): + ''' + @name 后台任务守护 + @return dict + ''' + pass + +def daemon_panel(): + ''' + @name 面板守护 + @return dict + ''' + pass + +def flush_auth_key(): + ''' + @name 刷新授权密钥 + @return dict + ''' + pass + +def get_auth_state(): + ''' + @name 获取授权状态 + @return 返回:0.免费版 1.专业版 2.企业版 -1.获取失败 + ''' + try: + softList = get_plugin_list() + if softList['ltd'] > -1: + return 2 + elif softList['pro'] > -1: + return 1 + else: + return 0 + except: + return -1 + + \ No newline at end of file diff --git a/wiki/files/win/bt.js b/wiki/files/win/bt.js index 6ba0d4b..2859de0 100644 --- a/wiki/files/win/bt.js +++ b/wiki/files/win/bt.js @@ -1,369 +1,394 @@ -/* - *宝塔面板去除各种计算题与延时等待 -*/ -if("undefined" != typeof bt && bt.hasOwnProperty("show_confirm")){ - bt.show_confirm = function(title, msg, fun, error) { - if (error == undefined) { - error = "" - } - var mess = layer.open({ - type: 1, - title: title, - area: "350px", - closeBtn: 2, - shadeClose: true, - content: "

" + msg + "

" + error + "
" - }); - $(".bt-cancel").click(function () { - layer.close(mess); - }); - $("#toSubmit").click(function () { - layer.close(mess); - fun(); - }) - } -} -if("undefined" != typeof bt && bt.hasOwnProperty("prompt_confirm")){ - bt.prompt_confirm = function (title, msg, callback) { - layer.open({ - type: 1, - title: title, - area: "350px", - closeBtn: 2, - btn: ['确认', '取消'], - content: "
\ -

" + msg + "

\ -
", - yes: function (layers, index) { - layer.close(layers) - if (callback) callback() - } - }); - } -} -if("undefined" != typeof bt && bt.hasOwnProperty("compute_confirm")){ - bt.compute_confirm = function (config, callback) { - layer.open({ - type: 1, - title: config.title, - area: '430px', - closeBtn: 2, - shadeClose: true, - btn: [lan['public'].ok, lan['public'].cancel], - content: - '
\ -
\ - \ -
' + - config.msg + - '
\ -
\ -
', - yes: function (layers, index) { - layer.close(layers) - if (callback) callback() - } - }); - } -} -if("undefined" != typeof database && database.hasOwnProperty("del_database")){ - database.del_database = function (wid, dbname,obj, callback) { - var title = '', - tips = '是否确认【删除数据库】,删除后可能会影响业务使用!'; - if(obj && obj.db_type > 0) tips = '远程数据库不支持数据库回收站,删除后将无法恢复,请谨慎操作'; - title = typeof dbname === "function" ?'批量删除数据库':'删除数据库 [ '+ dbname +' ]'; - layer.open({ - type:1, - title:title, - icon:0, - skin:'delete_site_layer', - area: "530px", - closeBtn: 2, - shadeClose: true, - content:"
" + - "" + - "
"+tips+"
" + - "
注意:数据无价,请谨慎操作!!!"+(!recycle_bin_db_open?'
风险操作:当前数据库回收站未开启,删除数据库将永久消失!':'')+"
" + - "
", - btn:[lan.public.ok,lan.public.cancel], - yes:function(indexs){ - var data = {id: wid,name: dbname}; - if(typeof dbname === "function"){ - delete data.id; - delete data.name; - } - layer.close(indexs) - var arrs = wid instanceof Array ? wid : [wid] - var ids = JSON.stringify(arrs), countDown = 9; - if (arrs.length == 1) countDown = 4 - title = typeof dbname === "function" ?'二次验证信息,批量删除数据库':'二次验证信息,删除数据库 [ ' + dbname + ' ]'; - var loadT = bt.load('正在检测数据库数据信息,请稍后...') - - bt_tools.send({url:'database/'+bt.data.db_tab_name+'/check_del_data',data:{data:JSON.stringify({ids: ids})}},function(res){ - loadT.close() - layer.open({ - type:1, - title:title, - closeBtn: 2, - skin: 'verify_site_layer_info', - area: '740px', - content: '
' + - '' + - '
堡塔温馨提示您,请冷静几秒钟,确认是否要删除以下数据。
' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
风险事项:当前未开启数据库回收站功能,删除数据库后,数据库将永久消失!
' + - '
注意:请仔细阅读以上要删除信息,防止数据库被误删
' + - '
', - btn: ['确认删除', '取消删除'], - success: function (layers) { - var html = '', rdata = res.data; - var filterData = rdata.filter(function(el){ - return ids.indexOf(el.id) != -1 - }) - for (var i = 0; i < filterData.length; i++) { - var item = filterData[i], newTime = parseInt(new Date().getTime() / 1000), - t_icon = ''; - - database_html = (function(item){ - var is_time_rule = (newTime - item.st_time) > (86400 * 30) && (item.total > 1024 * 10), - is_database_rule = res.db_size <= item.total, - database_time = bt.format_data(item.st_time, 'yyyy-MM-dd'), - database_size = bt.format_size(item.total); - - var f_size = ' ' + database_size + ' ' + (is_database_rule ? t_icon : ''); - var t_size = '注意:此数据库较大,可能为重要数据,请谨慎操作.\n数据库:' + database_size; - - return '
' + - '数据库:' + item.name + '' + - '大小:' + f_size +'' + - '创建时间:' + database_time + '' + - '
' - }(item)) - if(database_html !== '') html += '
' + database_html +'
'; - } - if(html === '') html = '
无数据
' - $('.check_layer_content').html(html) - }, - yes:function(indes,layers){ - if(typeof dbname === "function"){ - dbname(data) - }else{ - bt.database.del_database(data, function (rdata) { - layer.closeAll() - if (rdata.status) database_table.$refresh_table_list(true); - if (callback) callback(rdata); - bt.msg(rdata); - }) - } - } - }) - }) - } - }) - } -} -if("undefined" != typeof site && site.hasOwnProperty("del_site")){ - site.del_site = function(wid, wname, callback) { - var title = typeof wname === "function" ? '批量删除站点' : '删除站点 [ ' + wname + ' ]'; - recycle_bin_open = bt.get_cookie("is_recycle") || bt.get_cookie("is_recycle") == null ? true : false - layer.open({ - type: 1, - title: title, - icon: 0, - skin: 'delete_site_layer', - area: "440px", - closeBtn: 2, - shadeClose: true, - content: "
" + - '' + - "
是否要删除关联的FTP、数据库、站点目录!
" + - "
" + - "" + - "" + - "" + - "
" + - "
", - btn: [lan.public.ok, lan.public.cancel], - success: function (layers, indexs) { - $(layers).find('.check_type_group label').hover(function () { - var name = $(this).find('input').attr('name'); - if (name === 'data' && !recycle_bin_db_open) { - layer.tips('风险操作:当前数据库回收站未开启,删除数据库将永久消失!', this, { tips: [1, 'red'], time: 0 }) - } else if (name === 'path' && !recycle_bin_open) { - layer.tips('风险操作:当前文件回收站未开启,删除站点目录将永久消失!', this, { tips: [1, 'red'], time: 0 }) - } - }, function () { - layer.closeAll('tips'); - }) - }, - yes: function (indexs) { - var data = { id: wid, webname: wname }; - $('#site_delete_form input[type=checkbox]').each(function (index, item) { - if ($(item).is(':checked')) data[$(item).attr('name')] = 1 - }) - var is_database = data.hasOwnProperty('database'), is_path = data.hasOwnProperty('path'), is_ftp = data.hasOwnProperty('ftp'); - if ((!is_database && !is_path) && (!is_ftp || is_ftp)) { - if (typeof wname === "function") { - wname(data) - return false; - } - bt.site.del_site(data, function (rdata) { - layer.close(indexs); - if (callback) callback(rdata); - bt.msg(rdata); - }) - return false - } - if (typeof wname === "function") { - delete data.id; - delete data.webname; - } - layer.close(indexs) - var arrs = wid instanceof Array ? wid : [wid] - var ids = JSON.stringify(arrs), countDown = 9; - if (arrs.length == 1) countDown = 4 - title = typeof wname === "function" ? '二次验证信息,批量删除站点' : '二次验证信息,删除站点 [ ' + wname + ' ]'; - var loadT = bt.load('正在检测站点数据信息,请稍后...') - bt.send('check_del_data', 'site/check_del_data', { ids: ids }, function (res) { - loadT.close() - layer.open({ - type: 1, - title: title, - closeBtn: 2, - skin: 'verify_site_layer_info', - area: '740px', - content: '
' + - '' + - '
堡塔温馨提示您,请冷静几秒钟,确认以下要删除的数据。
' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
风险事项:当前未开启数据库回收站功能,删除数据库后,数据库将永久消失!
' + - '
风险事项:当前未开启文件回收站功能,删除站点目录后,站点目录将永久消失!
' + - '
注意:请仔细阅读以上要删除信息,防止网站数据被误删
' + - '
', - // recycle_bin_db_open && - // recycle_bin_open && - btn: ['确认删除', '取消删除'], - success: function (layers) { - var html = '', rdata = res.data; - for (var i = 0; i < rdata.length; i++) { - var item = rdata[i], newTime = parseInt(new Date().getTime() / 1000), - t_icon = ''; - - site_html = (function (item) { - if (!is_path) return '' - var is_time_rule = (newTime - item.st_time) > (86400 * 30) && (item.total > 1024 * 10), - is_path_rule = res.file_size <= item.total, - dir_time = bt.format_data(item.st_time, 'yyyy-MM-dd'), - dir_size = bt.format_size(item.total); - - var f_html = ' ' + dir_size + ' ' + (is_path_rule ? t_icon : ''); - var f_title = (is_path_rule ? '注意:此目录较大,可能为重要数据,请谨慎操作.\n' : '') + '目录:' + item.path + '(' + (item.limit ? '大于' : '') + dir_size + ')'; - - return '
' + - '站点名:' + item.name + '' + - '目录:' + item.path + ' (' + f_html + ')' + - '创建时间:' + dir_time + '' + - '
' - }(item)), - database_html = (function (item) { - if (!is_database || !item.database) return ''; - var is_time_rule = (newTime - item.st_time) > (86400 * 30) && (item.total > 1024 * 10), - is_database_rule = res.db_size <= item.database.total, - database_time = bt.format_data(item.database.st_time, 'yyyy-MM-dd'), - database_size = bt.format_size(item.database.total); - - var f_size = ' ' + database_size + ' ' + (is_database_rule ? t_icon : ''); - var t_size = '注意:此数据库较大,可能为重要数据,请谨慎操作.\n数据库:' + database_size; - - return '
' + - '数据库:' + item.database.name + '' + - '大小:' + f_size + '' + - '创建时间:' + database_time + '' + - '
' - }(item)) - if ((site_html + database_html) !== '') html += '
' + site_html + database_html + '
'; - } - if (html === '') html = '
无数据
' - $('.check_layer_content').html(html) - }, - yes: function (indes, layers) { - if (typeof wname === "function") { - wname(data) - } else { - bt.site.del_site(data, function (rdata) { - layer.closeAll() - if (rdata.status) site.get_list(); - if (callback) callback(rdata); - bt.msg(rdata); - }) - } - } - }) - }) - } - }) - if(bt.get_cookie("is_recycle") || bt.get_cookie("is_recycle")==null){ - $('[name="path"]').attr('checked',true) - }else{ - $('[name="path"]').removeProp('checked'); - } - } -} -if("undefined" != typeof bt && bt.hasOwnProperty("firewall") && bt.firewall.hasOwnProperty("add_accept_port")){ - bt.firewall.add_accept_port = function(type, port, ps, callback) { - var action = "AddDropAddress"; - if (type == 'port') { - ports = port.split(':'); - if (port.indexOf('-') != -1) ports = port.split('-'); - for (var i = 0; i < ports.length; i++) { - if (!bt.check_port(ports[i])) { - layer.msg(lan.firewall.port_err, { icon: 5 }); - return; - } - } - action = "AddAcceptPort"; - } - - loading = bt.load(); - bt.send(action, 'firewall/' + action, { port: port, type: type, ps: ps }, function(rdata) { - loading.close(); - if (callback) callback(rdata); - }) - } -} -function SafeMessage(j, h, g, f) { - if(f == undefined) { - f = "" - } - var mess = layer.open({ - type: 1, - title: j, - area: "350px", - closeBtn: 2, - shadeClose: true, - content: "

" + h + "

" + f + "
" - }); - $(".bt-cancel").click(function(){ - layer.close(mess); - }); - $("#toSubmit").click(function() { - layer.close(mess); - g(); - }) -} -$(document).ready(function () { - if($('#updata_pro_info').length>0){ - $('#updata_pro_info').html(''); - bt.set_cookie('productPurchase', 1); - } +/* + *宝塔面板去除各种计算题与延时等待 +*/ +if("undefined" != typeof bt && bt.hasOwnProperty("show_confirm")){ + bt.show_confirm = function(title, msg, fun, error) { + if (error == undefined) { + error = "" + } + var mess = layer.open({ + type: 1, + title: title, + area: "350px", + closeBtn: 2, + shadeClose: true, + content: "

" + msg + "

" + error + "
" + }); + $(".bt-cancel").click(function () { + layer.close(mess); + }); + $("#toSubmit").click(function () { + layer.close(mess); + fun(); + }) + } +} +if("undefined" != typeof bt && bt.hasOwnProperty("prompt_confirm")){ + bt.prompt_confirm = function (title, msg, callback) { + layer.open({ + type: 1, + title: title, + area: "350px", + closeBtn: 2, + btn: ['确认', '取消'], + content: "
\ +

" + msg + "

\ +
", + yes: function (layers, index) { + layer.close(layers) + if (callback) callback() + } + }); + } +} +if("undefined" != typeof bt && bt.hasOwnProperty("compute_confirm")){ + bt.compute_confirm = function (config, callback) { + layer.open({ + type: 1, + title: config.title, + area: '430px', + closeBtn: 2, + shadeClose: true, + btn: [lan['public'].ok, lan['public'].cancel], + content: + '
\ +
\ + \ +
' + + config.msg + + '
\ +
\ +
', + yes: function (layers, index) { + layer.close(layers) + if (callback) callback() + } + }); + } +} +if("undefined" != typeof bt && bt.hasOwnProperty("input_confirm")){ + bt.input_confirm = function (config, callback) { + layer.open({ + type: 1, + title: config.title, + area: '430px', + closeBtn: 2, + shadeClose: true, + btn: [lan['public'].ok, lan['public'].cancel], + content: + '
\ +
\ + \ +
' + + config.msg + + '
\ +
\ +
', + yes: function (layers, index) { + layer.close(layers); + if (callback) callback(); + }, + }); + } +} +if("undefined" != typeof database && database.hasOwnProperty("del_database")){ + database.del_database = function (wid, dbname,obj, callback) { + var title = '', + tips = '是否确认【删除数据库】,删除后可能会影响业务使用!'; + if(obj && obj.db_type > 0) tips = '远程数据库不支持数据库回收站,删除后将无法恢复,请谨慎操作'; + title = typeof dbname === "function" ?'批量删除数据库':'删除数据库 [ '+ dbname +' ]'; + layer.open({ + type:1, + title:title, + icon:0, + skin:'delete_site_layer', + area: "530px", + closeBtn: 2, + shadeClose: true, + content:"
" + + "" + + "
"+tips+"
" + + "
注意:数据无价,请谨慎操作!!!"+(!recycle_bin_db_open?'
风险操作:当前数据库回收站未开启,删除数据库将永久消失!':'')+"
" + + "
", + btn:[lan.public.ok,lan.public.cancel], + yes:function(indexs){ + var data = {id: wid,name: dbname}; + if(typeof dbname === "function"){ + delete data.id; + delete data.name; + } + layer.close(indexs) + var arrs = wid instanceof Array ? wid : [wid] + var ids = JSON.stringify(arrs), countDown = 9; + if (arrs.length == 1) countDown = 4 + title = typeof dbname === "function" ?'二次验证信息,批量删除数据库':'二次验证信息,删除数据库 [ ' + dbname + ' ]'; + var loadT = bt.load('正在检测数据库数据信息,请稍后...') + + bt_tools.send({url:'database/'+bt.data.db_tab_name+'/check_del_data',data:{data:JSON.stringify({ids: ids})}},function(res){ + loadT.close() + layer.open({ + type:1, + title:title, + closeBtn: 2, + skin: 'verify_site_layer_info', + area: '740px', + content: '
' + + '' + + '
堡塔温馨提示您,请冷静几秒钟,确认是否要删除以下数据。
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
风险事项:当前未开启数据库回收站功能,删除数据库后,数据库将永久消失!
' + + '
注意:请仔细阅读以上要删除信息,防止数据库被误删
' + + '
', + btn: ['确认删除', '取消删除'], + success: function (layers) { + var html = '', rdata = res.data; + var filterData = rdata.filter(function(el){ + return ids.indexOf(el.id) != -1 + }) + for (var i = 0; i < filterData.length; i++) { + var item = filterData[i], newTime = parseInt(new Date().getTime() / 1000), + t_icon = ''; + + database_html = (function(item){ + var is_time_rule = (newTime - item.st_time) > (86400 * 30) && (item.total > 1024 * 10), + is_database_rule = res.db_size <= item.total, + database_time = bt.format_data(item.st_time, 'yyyy-MM-dd'), + database_size = bt.format_size(item.total); + + var f_size = ' ' + database_size + ' ' + (is_database_rule ? t_icon : ''); + var t_size = '注意:此数据库较大,可能为重要数据,请谨慎操作.\n数据库:' + database_size; + + return '
' + + '数据库:' + item.name + '' + + '大小:' + f_size +'' + + '创建时间:' + database_time + '' + + '
' + }(item)) + if(database_html !== '') html += '
' + database_html +'
'; + } + if(html === '') html = '
无数据
' + $('.check_layer_content').html(html) + }, + yes:function(indes,layers){ + if(typeof dbname === "function"){ + dbname(data) + }else{ + bt.database.del_database(data, function (rdata) { + layer.closeAll() + if (rdata.status) database_table.$refresh_table_list(true); + if (callback) callback(rdata); + bt.msg(rdata); + }) + } + } + }) + }) + } + }) + } +} +if("undefined" != typeof site && site.hasOwnProperty("del_site")){ + site.del_site = function(wid, wname, callback) { + var title = typeof wname === "function" ? '批量删除站点' : '删除站点 [ ' + wname + ' ]'; + recycle_bin_open = bt.get_cookie("is_recycle") || bt.get_cookie("is_recycle") == null ? true : false + layer.open({ + type: 1, + title: title, + icon: 0, + skin: 'delete_site_layer', + area: "440px", + closeBtn: 2, + shadeClose: true, + content: "
" + + '' + + "
是否要删除关联的FTP、数据库、站点目录!
" + + "
" + + "" + + "" + + "" + + "
" + + "
", + btn: [lan.public.ok, lan.public.cancel], + success: function (layers, indexs) { + $(layers).find('.check_type_group label').hover(function () { + var name = $(this).find('input').attr('name'); + if (name === 'data' && !recycle_bin_db_open) { + layer.tips('风险操作:当前数据库回收站未开启,删除数据库将永久消失!', this, { tips: [1, 'red'], time: 0 }) + } else if (name === 'path' && !recycle_bin_open) { + layer.tips('风险操作:当前文件回收站未开启,删除站点目录将永久消失!', this, { tips: [1, 'red'], time: 0 }) + } + }, function () { + layer.closeAll('tips'); + }) + }, + yes: function (indexs) { + var data = { id: wid, webname: wname }; + $('#site_delete_form input[type=checkbox]').each(function (index, item) { + if ($(item).is(':checked')) data[$(item).attr('name')] = 1 + }) + var is_database = data.hasOwnProperty('database'), is_path = data.hasOwnProperty('path'), is_ftp = data.hasOwnProperty('ftp'); + if ((!is_database && !is_path) && (!is_ftp || is_ftp)) { + if (typeof wname === "function") { + wname(data) + return false; + } + bt.site.del_site(data, function (rdata) { + layer.close(indexs); + if (callback) callback(rdata); + bt.msg(rdata); + }) + return false + } + if (typeof wname === "function") { + delete data.id; + delete data.webname; + } + layer.close(indexs) + var arrs = wid instanceof Array ? wid : [wid] + var ids = JSON.stringify(arrs), countDown = 9; + if (arrs.length == 1) countDown = 4 + title = typeof wname === "function" ? '二次验证信息,批量删除站点' : '二次验证信息,删除站点 [ ' + wname + ' ]'; + var loadT = bt.load('正在检测站点数据信息,请稍后...') + bt.send('check_del_data', 'site/check_del_data', { ids: ids }, function (res) { + loadT.close() + layer.open({ + type: 1, + title: title, + closeBtn: 2, + skin: 'verify_site_layer_info', + area: '740px', + content: '
' + + '' + + '
堡塔温馨提示您,请冷静几秒钟,确认以下要删除的数据。
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
风险事项:当前未开启数据库回收站功能,删除数据库后,数据库将永久消失!
' + + '
风险事项:当前未开启文件回收站功能,删除站点目录后,站点目录将永久消失!
' + + '
注意:请仔细阅读以上要删除信息,防止网站数据被误删
' + + '
', + // recycle_bin_db_open && + // recycle_bin_open && + btn: ['确认删除', '取消删除'], + success: function (layers) { + var html = '', rdata = res.data; + for (var i = 0; i < rdata.length; i++) { + var item = rdata[i], newTime = parseInt(new Date().getTime() / 1000), + t_icon = ''; + + site_html = (function (item) { + if (!is_path) return '' + var is_time_rule = (newTime - item.st_time) > (86400 * 30) && (item.total > 1024 * 10), + is_path_rule = res.file_size <= item.total, + dir_time = bt.format_data(item.st_time, 'yyyy-MM-dd'), + dir_size = bt.format_size(item.total); + + var f_html = ' ' + dir_size + ' ' + (is_path_rule ? t_icon : ''); + var f_title = (is_path_rule ? '注意:此目录较大,可能为重要数据,请谨慎操作.\n' : '') + '目录:' + item.path + '(' + (item.limit ? '大于' : '') + dir_size + ')'; + + return '
' + + '站点名:' + item.name + '' + + '目录:' + item.path + ' (' + f_html + ')' + + '创建时间:' + dir_time + '' + + '
' + }(item)), + database_html = (function (item) { + if (!is_database || !item.database) return ''; + var is_time_rule = (newTime - item.st_time) > (86400 * 30) && (item.total > 1024 * 10), + is_database_rule = res.db_size <= item.database.total, + database_time = bt.format_data(item.database.st_time, 'yyyy-MM-dd'), + database_size = bt.format_size(item.database.total); + + var f_size = ' ' + database_size + ' ' + (is_database_rule ? t_icon : ''); + var t_size = '注意:此数据库较大,可能为重要数据,请谨慎操作.\n数据库:' + database_size; + + return '
' + + '数据库:' + item.database.name + '' + + '大小:' + f_size + '' + + '创建时间:' + database_time + '' + + '
' + }(item)) + if ((site_html + database_html) !== '') html += '
' + site_html + database_html + '
'; + } + if (html === '') html = '
无数据
' + $('.check_layer_content').html(html) + }, + yes: function (indes, layers) { + if (typeof wname === "function") { + wname(data) + } else { + bt.site.del_site(data, function (rdata) { + layer.closeAll() + if (rdata.status) site.get_list(); + if (callback) callback(rdata); + bt.msg(rdata); + }) + } + } + }) + }) + } + }) + if(bt.get_cookie("is_recycle") || bt.get_cookie("is_recycle")==null){ + $('[name="path"]').attr('checked',true) + }else{ + $('[name="path"]').removeProp('checked'); + } + } +} +if("undefined" != typeof bt && bt.hasOwnProperty("firewall") && bt.firewall.hasOwnProperty("add_accept_port")){ + bt.firewall.add_accept_port = function(type, port, ps, callback) { + var action = "AddDropAddress"; + if (type == 'port') { + ports = port.split(':'); + if (port.indexOf('-') != -1) ports = port.split('-'); + for (var i = 0; i < ports.length; i++) { + if (!bt.check_port(ports[i])) { + layer.msg(lan.firewall.port_err, { icon: 5 }); + return; + } + } + action = "AddAcceptPort"; + } + + loading = bt.load(); + bt.send(action, 'firewall/' + action, { port: port, type: type, ps: ps }, function(rdata) { + loading.close(); + if (callback) callback(rdata); + }) + } +} +function SafeMessage(j, h, g, f) { + if(f == undefined) { + f = "" + } + var mess = layer.open({ + type: 1, + title: j, + area: "350px", + closeBtn: 2, + shadeClose: true, + content: "

" + h + "

" + f + "
" + }); + $(".bt-cancel").click(function(){ + layer.close(mess); + }); + $("#toSubmit").click(function() { + layer.close(mess); + g(); + }) +} +$(document).ready(function () { + if($('#updata_pro_info').length>0){ + $('#updata_pro_info').html(''); + bt.set_cookie('productPurchase', 1); + } }) \ No newline at end of file diff --git a/wiki/updatewin.md b/wiki/updatewin.md index 1458777..3ad0680 100644 --- a/wiki/updatewin.md +++ b/wiki/updatewin.md @@ -16,6 +16,8 @@ Windows版宝塔由于加密文件太多,无法全部解密,因此无法做 - 全局搜索替换 https://www.bt.cn/api/ => http://www.example.com/api/(需排除ipsModel.py) +- 全局搜索替换 http://www.bt.cn/api/ => http://www.example.com/api/ + - 全局搜索替换 https://download.bt.cn/win/panel/data/setup.py => http://www.example.com/win/panel/data/setup.py - class/panel_update.py 文件 public.get_url() => 'http://www.example.com'