pull/628/head
Mr Chen 7 months ago
parent 95ff8c66f6
commit d026385370
  1. 4
      class/core/files_api.py
  2. 120
      class/core/site_api.py
  3. 7
      web/admin/__init__.py
  4. 17
      web/admin/files/__init__.py
  5. 38
      web/core/mw.py
  6. 77
      web/static/app/files.js
  7. 242
      web/utils/file.py
  8. 2
      web/version.py

@ -1074,9 +1074,9 @@ class files_api:
order_arr = order.split(' ')
if len(order_arr) < 2:
plist = mw.sortFileList(path, order_arr[0],'')
plist = mw.sortFileList(path, order_arr[0], '')
else:
plist = mw.sortFileList(path, order_arr[0],order_arr[1])
plist = mw.sortFileList(path, order_arr[0], order_arr[1])
for filename in plist:
if search:

@ -727,43 +727,43 @@ class site_api:
conf = mw.readFile(file)
if conf:
rep = "\n\s*#HTTP_TO_HTTPS_START(.|\n){1,300}#HTTP_TO_HTTPS_END"
rep = "\n\\s*#HTTP_TO_HTTPS_START(.|\n){1,300}#HTTP_TO_HTTPS_END"
conf = re.sub(rep, '', conf)
rep = "\s+ssl_certificate\s+.+;\s+ssl_certificate_key\s+.+;"
rep = "\\s+ssl_certificate\\s+.+;\\s+ssl_certificate_key\\s+.+;"
conf = re.sub(rep, '', conf)
rep = "\s+ssl_protocols\s+.+;\n"
rep = "\\s+ssl_protocols\\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\s+ssl_ciphers\s+.+;\n"
rep = "\\s+ssl_ciphers\\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\s+ssl_prefer_server_ciphers\s+.+;\n"
rep = "\\s+ssl_prefer_server_ciphers\\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\s+ssl_session_cache\s+.+;\n"
rep = "\\s+ssl_session_cache\\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\s+ssl_session_timeout\s+.+;\n"
rep = r"\s+ssl_session_timeout\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\s+ssl_ecdh_curve\s+.+;\n"
rep = r"\s+ssl_ecdh_curve\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\s+ssl_session_tickets\s+.+;\n"
rep = r"\s+ssl_session_tickets\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\s+ssl_stapling\s+.+;\n"
rep = r"\s+ssl_stapling\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\s+ssl_stapling_verify\s+.+;\n"
rep = r"\s+ssl_stapling_verify\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\s+add_header\s+.+;\n"
rep = r"\s+add_header\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\s+add_header\s+.+;\n"
rep = r"\s+add_header\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\s+ssl\s+on;"
rep = r"\s+ssl\s+on;"
conf = re.sub(rep, '', conf)
rep = "\s+error_page\s497.+;"
rep = r"\s+error_page\s497.+;"
conf = re.sub(rep, '', conf)
rep = "\s+if.+server_port.+\n.+\n\s+\s*}"
rep = r"\s+if.+server_port.+\n.+\n\s+\s*}"
conf = re.sub(rep, '', conf)
rep = "\s+listen\s+443.*;"
rep = r"\s+listen\s+443.*;"
conf = re.sub(rep, '', conf)
rep = "\s+listen\s+\[\:\:\]\:443.*;"
rep = r"\s+listen\s+\[\:\:\]\:443.*;"
conf = re.sub(rep, '', conf)
rep = "\s+http2\s+on;"
rep = r"\s+http2\s+on;"
conf = re.sub(rep, '', conf)
mw.writeFile(file, conf)
@ -888,7 +888,7 @@ class site_api:
# fix binddir domain ssl apply question
mw.backFile(host_conf_file)
auth_to = self.getSitePath(siteName)
rep = "\s*root\s*(.+);"
rep = r"\s*root\s*(.+);"
replace_root = "\n\troot " + auth_to + ";"
siteConf = re.sub(rep, replace_root, siteConf)
mw.writeFile(host_conf_file, siteConf)
@ -1043,7 +1043,7 @@ class site_api:
src_path = mw.getAcmeDomainDir(domains[0])
src_cert = src_path + '/fullchain.cer'
src_key = src_path + '/' + domains[0] + '.key'
src_cert.replace("\*", "*")
src_cert.replace("\\*", "*")
msg = '签发失败,您尝试申请证书的失败次数已达上限!<p>1、检查域名是否绑定到对应站点</p>\
<p>2检查域名是否正确解析到本服务器,或解析还未完全生效</p>\
@ -1115,9 +1115,9 @@ class site_api:
file = self.getHostConf(site_name)
conf = mw.readFile(file)
if conf:
rep = "\n\s*#HTTP_TO_HTTPS_START(.|\n){1,300}#HTTP_TO_HTTPS_END"
rep = r"\n\s*#HTTP_TO_HTTPS_START(.|\n){1,300}#HTTP_TO_HTTPS_END"
conf = re.sub(rep, '', conf)
rep = "\s+if.+server_port.+\n.+\n\s+\s*}"
rep = r"\s+if.+server_port.+\n.+\n\s+\s*}"
conf = re.sub(rep, '', conf)
mw.writeFile(file, conf)
@ -1282,7 +1282,7 @@ class site_api:
domain_name = self.toPunycode(domain[0])
domain_port = '80'
reg = "^([\w\-\*]{1,100}\.){1,4}([\w\-]{1,24}|[\w\-]{1,24}\.[\w\-]{1,24})$"
reg = r"^([\w\-\*]{1,100}\.){1,4}([\w\-]{1,24}|[\w\-]{1,24}\.[\w\-]{1,24})$"
if not re.match(reg, domain_name):
return mw.returnJson(False, '域名格式不正确!')
@ -1339,7 +1339,7 @@ class site_api:
if dirName == '':
mw.returnJson(False, '目录不能为空!')
reg = "^([\w\-\*]{1,100}\.){1,4}(\w{1,10}|\w{1,10}\.\w{1,10})$"
reg = r"^([\w\-\*]{1,100}\.){1,4}(\w{1,10}|\w{1,10}\.\w{1,10})$"
if not re.match(reg, domain):
return mw.returnJson(False, '主域名格式不正确!')
@ -1355,7 +1355,7 @@ class site_api:
filename = self.getHostConf(siteInfo['name'])
conf = mw.readFile(filename)
if conf:
rep = "enable-php-([0-9]{2,3})\.conf"
rep = r"enable-php-([0-9]{2,3})\.conf"
tmp = re.search(rep, conf).groups()
version = tmp[0]
@ -1507,7 +1507,7 @@ class site_api:
filename = self.getHostConf(siteName)
if os.path.exists(filename):
conf = mw.readFile(filename)
rep = '\s*root\s*(.+);'
rep = r'\s*root\s*(.+);'
path = re.search(rep, conf).groups()[0]
conf = conf.replace(path, newPath)
mw.writeFile(filename, conf)
@ -1578,7 +1578,7 @@ class site_api:
if os.path.exists(configFile):
conf = mw.readFile(configFile)
rep = "\n\s*#AUTH_START(.|\n){1,200}#AUTH_END"
rep = r"\n\s*#AUTH_START(.|\n){1,200}#AUTH_END"
conf = re.sub(rep, '', conf)
mw.writeFile(configFile, conf)
@ -1604,19 +1604,19 @@ class site_api:
conf = mw.readFile(file)
if conf:
# 删除域名
rep = "server_name\s+(.+);"
rep = r"server_name\s+(.+);"
tmp = re.search(rep, conf).group()
newServerName = tmp.replace(' ' + domain + ';', ';')
newServerName = newServerName.replace(' ' + domain + ' ', ' ')
conf = conf.replace(tmp, newServerName)
# 删除端口
rep = "listen\s+([0-9]+);"
rep = r"listen\s+([0-9]+);"
tmp = re.findall(rep, conf)
port_count = mw.M('domain').where(
'pid=? AND port=?', (pid, port)).count()
if mw.inArray(tmp, port) == True and port_count < 2:
rep = "\n*\s+listen\s+" + port + ";"
rep = r"\n*\s+listen\s+" + port + ";"
conf = re.sub(rep, '', conf)
# 保存配置
mw.writeFile(file, conf)
@ -1778,7 +1778,7 @@ class site_api:
if item["r_from"] == _from:
return mw.returnJson(False, "重复的规则!")
rep = "http(s)?\:\/\/([a-zA-Z0-9][-a-zA-Z0-9]{0,62}\.)+([a-zA-Z0-9][a-zA-Z0-9]{0,62})+.?"
rep = r"http(s)?\:\/\/([a-zA-Z0-9][-a-zA-Z0-9]{0,62}\.)+([a-zA-Z0-9][a-zA-Z0-9]{0,62})+.?"
if not re.match(rep, _to):
return mw.returnJson(False, "错误的目标地址")
@ -1942,7 +1942,7 @@ class site_api:
if _name == "" or _siteName == "" or _from == "" or _to == "" or _host == "":
return mw.returnJson(False, "必填项不能为空")
rep = "http(s)?\:\/\/([a-zA-Z0-9][-a-zA-Z0-9]{0,62}\.)+([a-zA-Z0-9][a-zA-Z0-9]{0,62})+.?"
rep = r"http(s)?\:\/\/([a-zA-Z0-9][-a-zA-Z0-9]{0,62}\.)+([a-zA-Z0-9][a-zA-Z0-9]{0,62})+.?"
if not re.match(rep, _to):
return mw.returnJson(False, "错误的目标地址!")
@ -1990,7 +1990,7 @@ location ^~ {from} {\n\
}\n\
# PROXY-END"
tpl_proxy_cache = "\n\
tpl_proxy_cache = r"\n\
if ( $uri ~* \"\.(gif|png|jpg|css|js|woff|woff2)$\" )\n\
{\n\
expires {cache_time}m;\n\
@ -2001,7 +2001,7 @@ location ^~ {from} {\n\
proxy_cache_valid 200 304 301 302 {cache_time}m;\n\
"
tpl_proxy_nocache = "\n\
tpl_proxy_nocache = r"\n\
set $static_files_app 0; \n\
if ( $uri ~* \"\.(gif|png|jpg|css|js|woff|woff2)$\" )\n\
{\n\
@ -2219,7 +2219,7 @@ location ^~ {from} {\n\
file = self.getHostConf(siteName)
if os.path.exists(file):
conf = mw.readFile(file)
rep = '\s*root\s*(.+);'
rep = r'\s*root\s*(.+);'
find_cnf = re.search(rep, conf)
if not find_cnf:
return ''
@ -2236,7 +2236,7 @@ location ^~ {from} {\n\
filename = self.getHostConf(siteName)
if os.path.exists(filename):
conf = mw.readFile(filename)
rep = '\s*root\s*(.+);'
rep = r'\s*root\s*(.+);'
path = re.search(rep, conf).groups()[0]
data = {}
@ -2321,7 +2321,7 @@ location ^~ {from} {\n\
def getSitePhpVersion(self, siteName):
conf = mw.readFile(self.getHostConf(siteName))
rep = "enable-php-(.*)\.conf"
rep = r"enable-php-(.*)\.conf"
find_php_cnf = re.search(rep, conf)
def_pver = '00'
@ -2337,7 +2337,7 @@ location ^~ {from} {\n\
siteName = mw.M('sites').where("id=?", (sid,)).getField('name')
file = self.getHostConf(siteName)
conf = mw.readFile(file)
rep = "\s+index\s+(.+);"
rep = r"\s+index\s+(.+);"
tmp = re.search(rep, conf).groups()
return tmp[0].replace(' ', ',')
@ -2356,7 +2356,7 @@ location ^~ {from} {\n\
file = self.getHostConf(siteName)
conf = mw.readFile(file)
if conf:
rep = "\s+index\s+.+;"
rep = r"\s+index\s+.+;"
conf = re.sub(rep, "\n\tindex " + index_l + ";", conf)
mw.writeFile(file, conf)
@ -2370,17 +2370,17 @@ location ^~ {from} {\n\
data = {}
conf = mw.readFile(filename)
try:
rep = "\s+limit_conn\s+perserver\s+([0-9]+);"
rep = r"\s+limit_conn\s+perserver\s+([0-9]+);"
tmp = re.search(rep, conf).groups()
data['perserver'] = int(tmp[0])
# IP并发限制
rep = "\s+limit_conn\s+perip\s+([0-9]+);"
rep = r"\s+limit_conn\s+perip\s+([0-9]+);"
tmp = re.search(rep, conf).groups()
data['perip'] = int(tmp[0])
# 请求并发限制
rep = "\s+limit_rate\s+([0-9]+)\w+;"
rep = r"\s+limit_rate\s+([0-9]+)\w+;"
tmp = re.search(rep, conf).groups()
data['limit_rate'] = int(tmp[0])
except:
@ -2410,15 +2410,15 @@ location ^~ {from} {\n\
conf = mw.readFile(filename)
if(conf.find('limit_conn perserver') != -1):
# 替换总并发
rep = "limit_conn\s+perserver\s+([0-9]+);"
rep = r"limit_conn\s+perserver\s+([0-9]+);"
conf = re.sub(rep, str_perserver, conf)
# 替换IP并发限制
rep = "limit_conn\s+perip\s+([0-9]+);"
rep = r"limit_conn\s+perip\s+([0-9]+);"
conf = re.sub(rep, str_perip, conf)
# 替换请求流量限制
rep = "limit_rate\s+([0-9]+)\w+;"
rep = r"limit_rate\s+([0-9]+)\w+;"
conf = re.sub(rep, str_limit_rate, conf)
else:
conf = conf.replace('#error_page 404/404.html;', "#error_page 404/404.html;\n " +
@ -2434,15 +2434,15 @@ location ^~ {from} {\n\
filename = self.getHostConf(siteName)
conf = mw.readFile(filename)
# 清理总并发
rep = "\s+limit_conn\s+perserver\s+([0-9]+);"
rep = r"\s+limit_conn\s+perserver\s+([0-9]+);"
conf = re.sub(rep, '', conf)
# 清理IP并发限制
rep = "\s+limit_conn\s+perip\s+([0-9]+);"
rep = r"\s+limit_conn\s+perip\s+([0-9]+);"
conf = re.sub(rep, '', conf)
# 清理请求流量限制
rep = "\s+limit_rate\s+([0-9]+)\w+;"
rep = r"\s+limit_rate\s+([0-9]+)\w+;"
conf = re.sub(rep, '', conf)
mw.writeFile(filename, conf)
mw.restartWeb()
@ -2458,15 +2458,15 @@ location ^~ {from} {\n\
rep = "#SECURITY-START(\n|.){1,500}#SECURITY-END"
tmp = re.search(rep, conf).group()
data['fix'] = re.search(
"\(.+\)\$", tmp).group().replace('(', '').replace(')$', '').replace('|', ',')
r"\(.+\)\$", tmp).group().replace('(', '').replace(')$', '').replace('|', ',')
data['status'] = False
data['none'] = False
valid_referers = re.search(
"valid_referers\s+(.+);\n", tmp)
r"valid_referers\s+(.+);\n", tmp)
valid_referers_none = re.search(
"valid_referers\s+none\s+blocked\s+(.+);\n", tmp)
r"valid_referers\s+none\s+blocked\s+(.+);\n", tmp)
if valid_referers or valid_referers_none:
data['status'] = True
@ -2500,11 +2500,11 @@ location ^~ {from} {\n\
if os.path.exists(file):
conf = mw.readFile(file)
if status == 'false':
rep = "\s{0,4}#SECURITY-START(\n|.){1,500}#SECURITY-END\n?"
rep = r"\s{0,4}#SECURITY-START(\n|.){1,500}#SECURITY-END\n?"
conf = re.sub(rep, '', conf)
mw.writeLog('网站管理', '站点[' + name + ']已关闭防盗链设置!')
else:
rep = "\s{0,4}#SECURITY-START(\n|.){1,500}#SECURITY-END\n?"
rep = r"\s{0,4}#SECURITY-START(\n|.){1,500}#SECURITY-END\n?"
conf = re.sub(rep, '', conf)
valid_referers = domains.strip().replace(',', ' ')
@ -2512,8 +2512,8 @@ location ^~ {from} {\n\
valid_referers = 'none blocked ' + valid_referers
pre_path = self.setupPath + "/php/conf"
re_path = "include\s+" + pre_path + "/enable-php-"
rconf = '''#SECURITY-START 防盗链配置
re_path = r"include\s+" + pre_path + "/enable-php-"
rconf = r'''#SECURITY-START 防盗链配置
location ~ .*\.(%s)$
{
expires 30d;
@ -2555,7 +2555,7 @@ location ^~ {from} {\n\
conf_dir = mw.getServerDir() + "/web_conf/php/conf"
conf_list = os.listdir(conf_dir)
l = len(conf_list)
rep = "enable-php-(.*?)\.conf"
rep = r"enable-php-(.*?)\.conf"
for name in conf_list:
tmp = {}
try:
@ -2611,7 +2611,7 @@ location ^~ {from} {\n\
return
# 添加域名
rep = "server_name\s*(.*);"
rep = r"server_name\s*(.*);"
tmp = re.search(rep, conf).group()
domains = tmp.split(' ')
if not mw.inArray(domains, domain):
@ -2619,7 +2619,7 @@ location ^~ {from} {\n\
conf = conf.replace(tmp, newServerName)
# 添加端口
rep = "listen\s+([0-9]+)\s*[default_server]*\s*;"
rep = r"listen\s+([0-9]+)\s*[default_server]*\s*;"
tmp = re.findall(rep, conf)
if not mw.inArray(tmp, port):
listen = re.search(rep, conf).group()
@ -2820,7 +2820,7 @@ location ^~ {from} {\n\
conf = conf.replace('#error_page 404/404.html;', sslStr)
rep = "listen\s+([0-9]+)\s*[default_server|reuseport]*;"
rep = r"listen\s+([0-9]+)\s*[default_server|reuseport]*;"
tmp = re.findall(rep, conf)
if not mw.inArray(tmp, '443'):
listen = re.search(rep, conf).group()

@ -10,6 +10,7 @@
import os
import sys
import time
import uuid
import logging
from datetime import timedelta
@ -109,8 +110,12 @@ def page_unauthorized(error):
# 设置模板全局变量
@app.context_processor
def inject_global_variables():
ver = setting.APP_VERSION;
if mw.isDebugMode():
ver = ver + str(time.time())
config = {
'version': setting.APP_VERSION,
'version': ver,
'title' : '面板',
'ip' : '127.0.0.1'
}

@ -14,6 +14,7 @@ from flask import Blueprint, render_template
from flask import request
import core.mw as mw
import utils.file as file
blueprint = Blueprint('files', __name__, url_prefix='/files', template_folder='../../templates/default')
@blueprint.route('/index', endpoint='index')
@ -99,22 +100,20 @@ def get_file_last_body():
def get_dir():
path = request.form.get('path', '')
if not os.path.exists(path):
path = mw.getRootDir() + "/wwwroot"
path = mw.getFatherDir() + '/wwwroot'
search = request.args.get('search', '').strip().lower()
search_all = request.args.get('all', '').strip().lower()
page = request.args.get('p', '1').strip().lower()
row = request.args.get('row', '10')
order = request.form.get('order', '')
print(path,search,search_all,page,row,order)
if not os.path.exists(path):
return mw.returnData(False, '文件不存在', (path,))
if search_all == 'yes' and search != '':
dir_list = file.getAllDirList(path, int(page), int(row),order, search)
else:
dir_list = file.getDirList(path, int(page), int(row),order, search)
try:
data = mw.getLastLine(path, int(line))
return mw.returnData(True, 'OK', data)
except Exception as ex:
return mw.returnData(False, '无法正确读取文件!' + str(ex))
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

@ -115,6 +115,19 @@ def getUniqueId():
unique_id = "{0}".format(str_time)
return unique_id
def toSize(size, middle='') -> str:
"""
字节单位转换
"""
units = ('b', 'KB', 'MB', 'GB', 'TB')
s = d[0]
for u in units:
if size < 1024:
return str(round(size, 2)) + middle + u
size = float(size) / 1024.0
s = u
return str(round(size, 2)) + middle + u
def returnData(status, msg, data=None):
if data == None:
return {'status': status, 'msg': msg}
@ -469,7 +482,6 @@ def writeLog(stype, msg, args=()):
def writeDbLog(stype, msg, args=(), uid=1):
try:
import admin.model.logs as logs
format_msg = getInfo(msg, args)
logs.add(stype, format_msg, uid)
# mdate = time.strftime('%Y-%m-%d %X', time.localtime())
@ -479,3 +491,27 @@ def writeDbLog(stype, msg, args=(), uid=1):
return False
# ---------------------------------------------------------------------------------
# 打印相关 START
# ---------------------------------------------------------------------------------
def echoStart(tag):
print("=" * 89)
print("★开始{}[{}]".format(tag, formatDate()))
print("=" * 89)
def echoEnd(tag):
print("=" * 89)
print("{}完成[{}]".format(tag, formatDate()))
print("=" * 89)
print("\n")
def echoInfo(msg):
print("|-{}".format(msg))
# ---------------------------------------------------------------------------------
# 打印相关 END
# ---------------------------------------------------------------------------------

@ -415,18 +415,19 @@ function getFiles(Path) {
var loadT = layer.load();
$.post('/files/get_dir?' + query_str, post, function(rdata) {
console.log(rdata);
layer.close(loadT);
//构建分页
makeFilePage(file_row,rdata.PAGE);
makeFilePage(file_row,rdata.page);
if(rdata.DIR == null) {
rdata.DIR = [];
if(rdata.dir == null) {
rdata.dir = [];
}
for (var i = 0; i < rdata.DIR.length; i++) {
var fmp = rdata.DIR[i].split(";");
for (var i = 0; i < rdata.dir.length; i++) {
console.log(rdata.dir[i]);
var fmp = rdata.dir[i].split(";");
var cnametext =fmp[0] + fmp[5];
fmp[0] = fmp[0].replace(/'/, "\\'");
@ -445,41 +446,42 @@ function getFiles(Path) {
//列表展示
$("#set_list").addClass("active");
$("#set_icon").removeClass("active");
body += "<tr class='folderBoxTr' data-path='" + rdata.PATH + "/" + fmp[0] + "' filetype='dir'>\
body += "<tr class='folderBoxTr' data-path='" + rdata.path + "/" + fmp[0] + "' filetype='dir'>\
<td><input type='checkbox' name='id' value='"+fmp[0]+"'></td>\
<td class='column-name'><span class='cursor' onclick=\"getFiles('" + rdata.PATH + "/" + fmp[0] + "')\">\
<td class='column-name'><span class='cursor' onclick=\"getFiles('" + rdata.path + "/" + fmp[0] + "')\">\
<span class='ico ico-folder'></span><a class='text' title='" + fmp[0] + fmp[5] + "'>" + cnametext + "</a></span></td>\
<td>"+toSize(fmp[1])+"</td>\
<td>"+getLocalTime(fmp[2])+"</td>\
<td>"+fmp[3]+"</td>\
<td>"+fmp[4]+"</td>\
<td class='editmenu'><span>\
<a class='btlink' href='javascript:;' onclick=\"copyFile('" + rdata.PATH +"/"+ fmp[0] + "')\">复制</a> | \
<a class='btlink' href='javascript:;' onclick=\"cutFile('" + rdata.PATH +"/"+ fmp[0]+ "')\">剪切</a> | \
<a class='btlink' href='javascript:;' onclick=\"copyFile('" + rdata.path +"/"+ fmp[0] + "')\">复制</a> | \
<a class='btlink' href='javascript:;' onclick=\"cutFile('" + rdata.path +"/"+ fmp[0]+ "')\">剪切</a> | \
<a class='btlink' href='javascript:;' onclick=\"reName(0,'" + fmp[0] + "');\">重命名</a> | \
<a class='btlink' href='javascript:;' onclick=\"setChmod(0,'" + rdata.PATH + "/"+fmp[0] + "');\">权限</a> | \
<a class='btlink' href='javascript:;' onclick=\"zip('" + rdata.PATH +"/" +fmp[0] + "');\">压缩</a> | \
<a class='btlink' href='javascript:;' onclick=\"deleteDir('" + rdata.PATH +"/"+ fmp[0] + "')\">删除</a></span>\
<a class='btlink' href='javascript:;' onclick=\"setChmod(0,'" + rdata.path + "/"+fmp[0] + "');\">权限</a> | \
<a class='btlink' href='javascript:;' onclick=\"zip('" + rdata.path +"/" +fmp[0] + "');\">压缩</a> | \
<a class='btlink' href='javascript:;' onclick=\"deleteDir('" + rdata.path +"/"+ fmp[0] + "')\">删除</a></span>\
</td>\
</tr>";
} else {
//图标展示
$("#set_icon").addClass("active");
$("#set_list").removeClass("active");
body += "<div class='file folderBox menufolder' data-path='" + rdata.PATH + "/" + fmp[0] + "' filetype='dir' title='"+lan.files.file_name+":" + fmp[0]+"&#13;"+lan.files.file_size+":"
body += "<div class='file folderBox menufolder' data-path='" + rdata.path + "/" + fmp[0] + "' filetype='dir' title='"+lan.files.file_name+":" + fmp[0]+"&#13;"+lan.files.file_size+":"
+ toSize(fmp[1])+"&#13;"+lan.files.file_etime+":"+getLocalTime(fmp[2])+"&#13;"+lan.files.file_auth+":"+fmp[3]+"&#13;"+lan.files.file_own+":"+fmp[4]+"'>\
<input type='checkbox' name='id' value='"+fmp[0]+"'>\
<div class='ico ico-folder' ondblclick=\"getFiles('" + rdata.PATH + "/" + fmp[0] + "')\"></div>\
<div class='titleBox' onclick=\"getFiles('" + rdata.PATH + "/" + fmp[0] + "')\">\
<div class='ico ico-folder' ondblclick=\"getFiles('" + rdata.path + "/" + fmp[0] + "')\"></div>\
<div class='titleBox' onclick=\"getFiles('" + rdata.path + "/" + fmp[0] + "')\">\
<span class='tname'>" + fmp[0] + "</span>\
</div>\
</div>";
}
}
for (var i = 0; i < rdata.FILES.length; i++) {
if(rdata.FILES[i] == null) continue;
var fmp = rdata.FILES[i].split(";");
for (var i = 0; i < rdata.files.length; i++) {
console.log(rdata.files[i]);
// if(rdata.files[i] == null) continue;
var fmp = rdata.files[i].split(";");
var bodyZip = '';
var download = '';
var cnametext =fmp[0] + fmp[5];
@ -497,22 +499,22 @@ function getFiles(Path) {
var displayCompress = 1;
if(isCompressFile(fmp[0])){
bodyZip = "<a class='btlink' href='javascript:;' onclick=\"unCompressFile('" + rdata.PATH +"/" +fmp[0] + "')\">解压</a> | ";
bodyZip = "<a class='btlink' href='javascript:;' onclick=\"unCompressFile('" + rdata.path +"/" +fmp[0] + "')\">解压</a> | ";
}
if(isText(fmp[0])){
bodyZip = "<a class='btlink' href='javascript:;' onclick=\"onlineEditFile(0,'" + rdata.PATH +"/"+ fmp[0] + "')\">编辑</a> | ";
bodyZip = "<a class='btlink' href='javascript:;' onclick=\"onlineEditFile(0,'" + rdata.path +"/"+ fmp[0] + "')\">编辑</a> | ";
}
if(isImage(fmp[0])){
download = "<a class='btlink' href='javascript:;' onclick=\"getImage('" + rdata.PATH +"/"+ fmp[0] + "')\">预览</a> | ";
download = "<a class='btlink' href='javascript:;' onclick=\"getImage('" + rdata.path +"/"+ fmp[0] + "')\">预览</a> | ";
} else {
download = "<a class='btlink' href='javascript:;' onclick=\"getFileBytes('" + rdata.PATH +"/"+ fmp[0] + "',"+fmp[1]+")\">下载</a> | ";
download = "<a class='btlink' href='javascript:;' onclick=\"getFileBytes('" + rdata.path +"/"+ fmp[0] + "',"+fmp[1]+")\">下载</a> | ";
}
totalSize += parseInt(fmp[1]);
if(getCookie("rank")=="a"){
body += "<tr style='cursor:pointer;' class='folderBoxTr' data-path='" + rdata.PATH +"/"+ fmp[0] + "' filetype='" + fmp[0] + "' ondblclick='openFilename(this)'>\
body += "<tr style='cursor:pointer;' class='folderBoxTr' data-path='" + rdata.path +"/"+ fmp[0] + "' filetype='" + fmp[0] + "' ondblclick='openFilename(this)'>\
<td><input type='checkbox' name='id' value='"+fmp[0]+"'></td>\
<td class='column-name'><span class='ico ico-"+(getExtName(fmp[0]))+"'></span><a class='text' title='" + fmp[0] + fmp[5] + "'>" + cnametext + "</a></td>\
<td>" + (toSize(fmp[1])) + "</td>\
@ -520,29 +522,29 @@ function getFiles(Path) {
<td>"+fmp[3]+"</td>\
<td>"+fmp[4]+"</td>\
<td class='editmenu'>\
<span><a class='btlink' href='javascript:;' onclick=\"copyFile('" + rdata.PATH +"/"+ fmp[0] + "')\">复制</a> | \
<a class='btlink' href='javascript:;' onclick=\"cutFile('" + rdata.PATH +"/"+ fmp[0] + "')\">剪切</a> | \
<span><a class='btlink' href='javascript:;' onclick=\"copyFile('" + rdata.path +"/"+ fmp[0] + "')\">复制</a> | \
<a class='btlink' href='javascript:;' onclick=\"cutFile('" + rdata.path +"/"+ fmp[0] + "')\">剪切</a> | \
<a class='btlink' href='javascript:;' onclick=\"reName(0,'" + fmp[0] + "')\">重命名</a> | \
<a class='btlink' href=\"javascript:setChmod(0,'" + rdata.PATH +"/"+ fmp[0] + "');\">权限</a> | \
<a class='btlink' href=\"javascript:zip('" + rdata.PATH +"/" +fmp[0] + "');\">压缩</a> | "
<a class='btlink' href=\"javascript:setChmod(0,'" + rdata.path +"/"+ fmp[0] + "');\">权限</a> | \
<a class='btlink' href=\"javascript:zip('" + rdata.path +"/" +fmp[0] + "');\">压缩</a> | "
+ bodyZip
+ download
+ "<a class='btlink' href='javascript:;' onclick=\"deleteFile('" + rdata.PATH +"/"+ fmp[0] + "')\">删除</a>\
+ "<a class='btlink' href='javascript:;' onclick=\"deleteFile('" + rdata.path +"/"+ fmp[0] + "')\">删除</a>\
</span></td>\
</tr>";
}
else{
body += "<div class='file folderBox menufile' data-path='" + rdata.PATH +"/"+ fmp[0] + "' filetype='"+fmp[0]+"' title='文件名:" + fmp[0]+"&#13;大小:"
body += "<div class='file folderBox menufile' data-path='" + rdata.path +"/"+ fmp[0] + "' filetype='"+fmp[0]+"' title='文件名:" + fmp[0]+"&#13;大小:"
+ toSize(fmp[1])+"&#13;修改时间:"+getLocalTime(fmp[2])+"&#13;权限:"+fmp[3]+"&#13;所有者:"+fmp[4]+"' >\
<input type='checkbox' name='id' value='"+fmp[0]+"' />\
<div data-path='" + rdata.PATH +"/"+ fmp[0] + "' filetype='"+fmp[0]+"' class='ico ico-"+(getExtName(fmp[0]))+"' ondblclick='javascript;openFilename(this);'></div>\
<div data-path='" + rdata.path +"/"+ fmp[0] + "' filetype='"+fmp[0]+"' class='ico ico-"+(getExtName(fmp[0]))+"' ondblclick='javascript;openFilename(this);'></div>\
<div class='titleBox'>\
<span class='tname'>" + fmp[0] + "</span>\
</div>\
</div>";
}
}
var dirInfo = '(共{1}个目录与{2}个文件,大小:'.replace('{1}',rdata.DIR.length+'').replace('{2}',rdata.FILES.length+'')+'<font id="pathSize">'
var dirInfo = '(共{1}个目录与{2}个文件,大小:'.replace('{1}',rdata.dir.length+'').replace('{2}',rdata.files.length+'')+'<font id="pathSize">'
+ (toSize(totalSize))+'<a class="btlink ml5" onClick="getPathSize()">获取</a></font>)';
$("#dir_info").html(dirInfo);
if( getCookie('rank') == 'a' ){
@ -595,7 +597,7 @@ function getFiles(Path) {
$("#fileCon").addClass("fileList").html(body);
$("#tipTools").width($("#fileCon").width());
}
$("#DirPathPlace input").val(rdata.PATH);
$("#DirPathPlace input").val(rdata.path);
var BarTools = '<div class="btn-group">\
<button class="btn btn-default btn-sm dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">\
新建<span class="caret"></span>\
@ -605,11 +607,11 @@ function getFiles(Path) {
<li><a href="javascript:createDir(0,\'' + Path + '\');">新建目录</a></li>\
</ul>\
</div>';
if (rdata.PATH != '/') {
if (rdata.path != '/') {
BarTools += ' <button onclick="javascript:backDir();" class="btn btn-default btn-sm glyphicon glyphicon-arrow-left" title="返回上一级"></button>';
}
setCookie('open_dir_path',rdata.PATH);
BarTools += ' <button onclick="javascript:getFiles(\'' + rdata.PATH + '\');" class="btn btn-default btn-sm glyphicon glyphicon-refresh" title="刷新"></button>\
setCookie('open_dir_path',rdata.path);
BarTools += ' <button onclick="javascript:getFiles(\'' + rdata.path + '\');" class="btn btn-default btn-sm glyphicon glyphicon-refresh" title="刷新"></button>\
<button onclick="webShell()" title="终端" type="button" class="btn btn-default btn-sm"><em class="ico-cmd"></em></button>';
var copyName = getCookie('copyFileName');
var cutName = getCookie('cutFileName');
@ -701,7 +703,7 @@ function getFiles(Path) {
setCookie('file_row',$(this).val());
getFiles(p);
});
pathPlaceBtn(rdata.PATH);
pathPlaceBtn(rdata.path);
},'json');
// setTimeout(function(){getCookie('open_dir_path');},200);
}
@ -944,6 +946,7 @@ function ShowEditMenu(){
//取磁盘
function getDisk() {
var LBody = '';
$.get('/system/disk_info', function(rdata) {
for (var i = 0; i < rdata.length; i++) {
LBody += "<span onclick=\"getFiles('" + rdata[i].path + "')\">\

@ -0,0 +1,242 @@
# coding:utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
import os
import pwd
import core.mw as mw
# 获取文件权限描述
def getFileStatsDesc(
filename: str | None = None,
path: str | None = None,
):
if path is None or filename is None:
return ';;;;;'
filename = filename.replace('//', '/')
try:
stat = os.stat(filename)
accept = str(oct(stat.st_mode)[-3:])
mtime = str(int(stat.st_mtime))
user = ''
try:
user = str(pwd.getpwuid(stat.st_uid).pw_name)
except:
user = str(stat.st_uid)
size = str(stat.st_size)
link = ''
if os.path.islink(filename):
link = ' -> ' + os.readlink(filename)
if path:
path_t = (path + '/').replace('//', '/')
filename = filename.replace(path_t, '', 1)
return filename + ';' + size + ';' + mtime + ';' + accept + ';' + user + ';' + link
except Exception as e:
print(str(e))
return ';;;;;'
def sortFileList(path, ftype = 'mtime', sort = 'desc'):
flist = os.listdir(path)
if ftype == 'mtime':
if sort == 'desc':
flist = sorted(flist, key=lambda f: os.path.getmtime(os.path.join(path,f)), reverse=True)
if sort == 'asc':
flist = sorted(flist, key=lambda f: os.path.getmtime(os.path.join(path,f)), reverse=False)
if ftype == 'size':
if sort == 'desc':
flist = sorted(flist, key=lambda f: os.path.getsize(os.path.join(path,f)), reverse=True)
if sort == 'asc':
flist = sorted(flist, key=lambda f: os.path.getsize(os.path.join(path,f)), reverse=False)
if ftype == 'fname':
if sort == 'desc':
flist = sorted(flist, key=lambda f: os.path.join(path,f), reverse=True)
if sort == 'asc':
flist = sorted(flist, key=lambda f: os.path.join(path,f), reverse=False)
return flist
def sortAllFileList(path, ftype = 'mtime', sort = 'desc', search = '',limit = 3000):
count = 0
flist = []
for d_list in os.walk(path):
if count >= limit:
break
for d in d_list[1]:
if count >= limit:
break
if d.lower().find(search) != -1:
filename = d_list[0] + '/' + d
if not os.path.exists(filename):
continue
count += 1
flist.append(filename)
for f in d_list[2]:
if count >= limit:
break
if f.lower().find(search) != -1:
filename = d_list[0] + '/' + f
if not os.path.exists(filename):
continue
count += 1
flist.append(filename)
if ftype == 'mtime':
if sort == 'desc':
flist = sorted(flist, key=lambda f: os.path.getmtime(f), reverse=True)
if sort == 'asc':
flist = sorted(flist, key=lambda f: os.path.getmtime(f), reverse=False)
if ftype == 'size':
if sort == 'desc':
flist = sorted(flist, key=lambda f: os.path.getsize(f), reverse=True)
if sort == 'asc':
flist = sorted(flist, key=lambda f: os.path.getsize(f), reverse=False)
return flist
def getAllDirList(path, page=1, size=10, order = '', search=None):
if page < 1:
page == 1
data = {}
dirnames = []
filenames = []
max_limit = 3000
order_split = order.split(' ')
if len(order_split) < 2:
flist = sortAllFileList(path, order_split[0],'',search, max_limit)
else:
flist = sortAllFileList(path, order_split[0], order_split[1], search, max_limit)
count = len(flist)
start = (page - 1) * size
end = start + size
if end > count:
end = count
plist = flist[start:end]
for dst_file in plist:
if not os.path.exists(dst_file):
continue
stat = getFileStatsDesc(dst_file, path)
if os.path.isdir(dst_file):
dirnames.append(stat)
else:
filenames.append(stat)
data['count'] = count
data['dir'] = dirnames
data['files'] = filenames
data['path'] = path.replace('//', '/')
return data
def getDirList(path, page=1, size=10, order = '', search=None):
if page < 1:
page == 1
data = {}
dirnames = []
filenames = []
count = getCount(path, search)
order_split = order.strip().split(' ')
if len(order_split) < 2:
flist = sortFileList(path, order_split[0], '')
else:
flist = sortFileList(path, order_split[0], order_split[1])
start = (page - 1) * size
end = start + size
if end > count:
end = count
if search or search != '':
nlist = []
for f in flist:
if f.lower().find(search) == -1:
continue
nlist.append(f)
plist = nlist[start:end]
else:
plist = flist[start:end]
for filename in plist:
abs_file = path + '/' + filename
if not os.path.exists(abs_file):
continue
stats = getFileStatsDesc(abs_file, path)
if os.path.isdir(abs_file):
dirnames.append(stats)
else:
filenames.append(stats)
data['count'] = count
data['dir'] = dirnames
data['files'] = filenames
data['path'] = path.replace('//', '/')
return data
# 检测文件名
def checkFileName(filename):
nots = ['\\', '&', '*', '|', ';']
if filename.find('/') != -1:
filename = filename.split('/')[-1]
for n in nots:
if n in filename:
return False
return True
# 获取目录大小
def getDirSize(filePath, size=0):
for root, dirs, files in os.walk(filePath):
for f in files:
size += os.path.getsize(os.path.join(root, f))
# print(f)
return size
# 获取目录大小(bash)
def getDirSizeByBash(path):
tmp = mw.execShell('du -sh ' + path)
return tmp[0].split()[0]
# 计算文件数量
def getCount(path, search = None):
i = 0
for name in os.listdir(path):
if name == '.' or name == '..':
continue
if search:
if name.lower().find(search) == -1:
continue
i += 1
return i
# 获取文件权限
def getAccess(fname):
data = {}
try:
stat = os.stat(fname)
data['chmod'] = str(oct(stat.st_mode)[-3:])
data['chown'] = pwd.getpwuid(stat.st_uid).pw_name
except Exception as e:
# print(e)
data['chmod'] = 755
data['chown'] = 'www'
return data

@ -13,7 +13,7 @@
# 应用程序版本号组件
APP_RELEASE = 0
APP_REVISION = 18
APP_SMALL_VERSION = 0.3
APP_SMALL_VERSION = 0
# 应用程序版本后缀,例如“beta1”、“dev”。通常为空字符串GA发布。
APP_SUFFIX = ''

Loading…
Cancel
Save