diff --git a/panel_task.py b/panel_task.py index 363276993..2c9131fcb 100755 --- a/panel_task.py +++ b/panel_task.py @@ -51,7 +51,7 @@ timeoutCount = 0 isCheck = 0 oldEdate = None -g_log_file = mw.getMWLogs() + '/panelExec.log' +g_log_file = mw.getMWLogs() + '/panel_task.log' isTask = mw.getMWLogs() + '/panelTask.pl' if not os.path.exists(os.getcwd() + "/tmp"): @@ -183,7 +183,7 @@ def writeLogs(data): def runTask(): - mw.writeLog("后台任务", "运行") + # mw.writeLog("后台任务", "运行") print(model.getTaskCount()) # global isTask diff --git a/web/admin/files/__init__.py b/web/admin/files/__init__.py index 74e7c4fc6..a5c5e88ff 100644 --- a/web/admin/files/__init__.py +++ b/web/admin/files/__init__.py @@ -13,6 +13,9 @@ import os from flask import Blueprint, render_template from flask import request + +from admin import model + import core.mw as mw import utils.file as file @@ -25,35 +28,7 @@ def index(): @blueprint.route('/get_body', endpoint='get_file_body', methods=['POST']) def get_file_body(): path = request.form.get('path', '') - - if not os.path.exists(path): - return mw.returnData(False, '文件不存在', (path,)) - - if os.path.getsize(path) > 2097152: - return mw.returnData(False, '不能在线编辑大于2MB的文件!') - - if os.path.isdir(path): - return mw.returnData(False, '这不是一个文件!') - - fp = open(path, 'rb') - data = {} - data['status'] = True - if fp: - srcBody = fp.read() - fp.close() - - encoding_list = ['utf-8', 'GBK', 'BIG5'] - for el in encoding_list: - try: - data['encoding'] = el - data['data'] = srcBody.decode(data['encoding']) - break - except Exception as ex: - if el == 'BIG5': - return mw.returnData(False, '文件编码不被兼容,无法正确读取文件!' + str(ex)) - else: - return mw.returnData(False, '文件未正常打开!') - return mw.returnData(True, 'OK', data) + return file.getFileBody(path) # 获取文件内容 @blueprint.route('/save_body', endpoint='save_body', methods=['POST']) @@ -74,7 +49,7 @@ def save_body(): if path.find("web_conf") > 0: mw.restartWeb() - # mw.writeLog('文件管理', '文件[{1}]保存成功', (path,)) + mw.writeLog('文件管理', '文件[{1}]保存成功', (path,)) return mw.returnData(True, '文件保存成功') except Exception as ex: return mw.returnData(False, '文件保存错误:' + str(ex)) @@ -115,7 +90,6 @@ def get_dir(): dir_list['page'] = mw.getPage({'p':page, 'row': row, 'tojs':'getFiles', 'count': dir_list['count']}, '1,2,3,4,5,6,7,8') return dir_list - # 获取站点日志目录 @blueprint.route('/get_dir_size', endpoint='get_dir_size', methods=['POST']) def get_dir_size(): @@ -124,6 +98,33 @@ def get_dir_size(): return mw.returnData(True, mw.toSize(size)) +# 删除文件 +@blueprint.route('/delete', endpoint='delete', methods=['POST']) +def delete(): + path = request.form.get('path', '') + return file.fileDelete(path) + + +# 回收站文件 +@blueprint.route('/get_recycle_bin', endpoint='get_recycle_bin', methods=['POST']) +def get_recycle_bin(): + return file.getRecycleBin() + +# 回收站文件恢复 +@blueprint.route('/re_recycle_bin', endpoint='re_recycle_bin', methods=['POST']) +def re_recycle_bin(): + path = request.form.get('path', '') + return file.reRecycleBin(path) + +# 回收站文件 +@blueprint.route('/recycle_bin', endpoint='recycle_bin', methods=['POST']) +def recycle_bin(): + return file.toggleRecycleBin() + + + + + diff --git a/web/admin/setting/__init__.py b/web/admin/setting/__init__.py index 19074a4ff..43f58e8d4 100644 --- a/web/admin/setting/__init__.py +++ b/web/admin/setting/__init__.py @@ -51,12 +51,14 @@ def set_ip(): @blueprint.route('/set_admin_path', endpoint='set_admin_path', methods=['POST']) def set_admin_path(): admin_path = request.form.get('admin_path', '') - admin_path_sensitive = ['/', '/close', '/login', - '/do_login', '/site', '/sites', - '/download_file', '/control', '/crontab', - '/firewall', '/files', '/config', '/setting','/monitor' - '/soft', '/system', '/code', - '/ssl', '/plugins', '/hook'] + admin_path_sensitive = [ + '/', '/close', '/login', + '/do_login', '/site', '/sites', + '/download_file', '/control', '/crontab', + '/firewall', '/files', '/config', '/setting','/monitor' + '/soft', '/system', '/code', + '/ssl', '/plugins', '/hook' + ] if admin_path == '': admin_path = '/' diff --git a/web/core/mw.py b/web/core/mw.py index 77f1eab85..ca199b3aa 100644 --- a/web/core/mw.py +++ b/web/core/mw.py @@ -94,6 +94,12 @@ def getServerDir(): def getLogsDir(): return getFatherDir() + '/wwwlogs' +def getRecycleBinDir(): + rb_dir = getFatherDir() + '/recycle_bin' + if not os.path.exists(rb_dir): + os.system('mkdir -p ' + rb_dir) + return rb_dir + def getRandomString(length): # 取随机字符串 rnd_str = '' diff --git a/web/static/app/public.js b/web/static/app/public.js index 56fb17891..c67358887 100755 --- a/web/static/app/public.js +++ b/web/static/app/public.js @@ -610,7 +610,7 @@ function showMsg(msg, callback ,icon, time){ function openPath(a) { setCookie("open_dir_path", a); - window.location.href = "/files/"; + window.location.href = "/files/index"; } function onlineEditFile(k, f, callback) { diff --git a/web/utils/file.py b/web/utils/file.py index 7b927df02..fbae943fa 100644 --- a/web/utils/file.py +++ b/web/utils/file.py @@ -10,9 +10,42 @@ import os import pwd +import time + +from admin import model import core.mw as mw +def getFileBody(path): + if not os.path.exists(path): + return mw.returnData(False, '文件不存在', (path,)) + + if os.path.getsize(path) > 2097152: + return mw.returnData(False, '不能在线编辑大于2MB的文件!') + + if os.path.isdir(path): + return mw.returnData(False, '这不是一个文件!') + + fp = open(path, 'rb') + data = {} + data['status'] = True + if fp: + srcBody = fp.read() + fp.close() + + encoding_list = ['utf-8', 'GBK', 'BIG5'] + for el in encoding_list: + try: + data['encoding'] = el + data['data'] = srcBody.decode(data['encoding']) + break + except Exception as ex: + if el == 'BIG5': + return mw.returnData(False, '文件编码不被兼容,无法正确读取文件!' + str(ex)) + else: + return mw.returnData(False, '文件未正常打开!') + return mw.returnData(True, 'OK', data) + # 获取文件权限描述 def getFileStatsDesc( filename: str | None = None, @@ -239,4 +272,111 @@ def getAccess(fname): # print(e) data['chmod'] = 755 data['chown'] = 'www' - return data \ No newline at end of file + return data + +def fileDelete(path): + if not os.path.exists(path): + return mw.returnData(False, '指定文件不存在!') + + # 检查是否为.user.ini + if path.find('.user.ini') >= 0: + cmd = "which chattr && chattr -i {0}".format(path) + mw.execShell(cmd) + + try: + recycle_bin = model.getOption('recycle_bin') + if recycle_bin == 'open': + if file.mvRecycleBin(path): + return mw.returnData(True, '已将文件移动到回收站!') + return mw.returnData(False, '移动到回收站失败!') + os.remove(path) + mw.writeLog('文件管理', mw.getInfo('删除文件[{1}]成功!', (path,))) + return mw.returnData(True, '删除文件成功!') + except Exception as e: + return mw.returnData(False, '删除文件失败!') + +# 关闭 +def toggleRecycleBin(): + recycle_bin = model.getOption('recycle_bin') + if recycle_bin == 'open': + model.setOption('recycle_bin','close') + mw.writeLog('文件管理', '已关闭回收站功能!') + return mw.returnData(True, '已关闭回收站功能!') + else: + model.setOption('recycle_bin','open') + mw.writeLog('文件管理', '已开启回收站功能!') + return mw.returnData(True, '已开启回收站功能!') + +def getRecycleBin(): + rb_dir = mw.getRecycleBinDir() + recycle_bin = model.getOption('recycle_bin') + + data = {} + data['dirs'] = [] + data['files'] = [] + data['status'] = False + if recycle_bin == 'open': + data['status'] = True + + for file in os.listdir(rb_dir): + try: + tmp = {} + fname = rb_dir+'/'+ file + tmp1 = file.split('_mw_') + tmp2 = tmp1[len(tmp1) - 1].split('_t_') + tmp['rname'] = file + tmp['dname'] = file.replace('_mw_', '/').split('_t_')[0] + tmp['name'] = tmp2[0] + tmp['time'] = int(float(tmp2[1])) + if os.path.islink(fname): + filePath = os.readlink(fname) + link = ' -> ' + filePath + if os.path.exists(filePath): + tmp['size'] = os.path.getsize(filePath) + else: + tmp['size'] = 0 + else: + tmp['size'] = os.path.getsize(fname) + if os.path.isdir(fname): + data['dirs'].append(tmp) + else: + data['files'].append(tmp) + except Exception as e: + continue + + return mw.returnJson(True, 'OK', data) + +# 移动到回收站 +def mvRecycleBin(path): + rb_dir = mw.getRecycleBinDir() + rb_file = rb_dir + '/' + path.replace('/', '_mw_') + '_t_' + str(time.time()) + try: + import shutil + shutil.move(path, rb_dir) + mw.writeLog('文件管理', mw.getInfo('移动[{1}]到回收站成功!', (path,))) + return True + except Exception as e: + mw.writeLog('文件管理', mw.getInfo('移动[{1}]到回收站失败!', (path,))) + return False + +# 回收站文件恢复 +def reRecycleBin(path): + rb_dir = mw.getRecycleBinDir() + dst_file = path.replace('_mw_', '/').split('_t_')[0] + try: + import shutil + shutil.move(rb_dir + '/' + path, dst_file) + msg = mw.getInfo('移动文件[{1}]到回收站成功!', (dst_file,)) + mw.writeLog('文件管理', msg) + return mw.returnData(True, '恢复成功!') + except Exception as e: + msg = mw.getInfo('从回收站恢复[{1}]失败!', (dst_file,)) + mw.writeLog('文件管理', msg) + return mw.returnData(False, '恢复失败!') + +# 设置文件和目录权限 +def setMode(path): + s_path = os.path.dirname(path) + p_stat = os.stat(s_path) + os.chown(path, p_stat.st_uid, p_stat.st_gid) + os.chmod(path, p_stat.st_mode) \ No newline at end of file