update to 6.8.37

This commit is contained in:
zhw
2024-04-29 15:35:04 +08:00
parent fa9a865beb
commit ed34994f45
474 changed files with 125711 additions and 34665 deletions
+104
View File
@@ -0,0 +1,104 @@
#coding: utf-8
import public,os
class filesBase:
__upload_objs = ['bos','alioss','obs','upyun','txcos'] #支持下载的云存储
__down_objs = ['bos','alioss','txcos','obs'] #支持上传的云存储
def __init__(self):
pass
#************************ start 对象存储 ************************
def get_base_objects(self,objs):
"""
@name 获取可上传的对象存储
"""
import panelPlugin
plu_obj = panelPlugin.panelPlugin()
res = []
for name in objs:
is_conf = 0
info = plu_obj.get_soft_find(name)
if not info: continue
if info['setup']:
is_conf = self._check_objects_conf(info['name'])
res.append({'name':info['name'],'title':info['title'],'setup':info['setup'],'is_conf':is_conf})
return res
def get_all_objects(self,get):
"""
@name 获取可上传的对象存储
"""
result = {}
result['upload'] = []
result['down'] = self.get_base_objects(self.__down_objs)
for info in result['down']:
if info['name'] in self.__upload_objs:
result['upload'].append(info)
return result
def get_upload_objects(self,get):
"""
@name 获取可上传的对象存储
"""
return self.get_base_objects(self.__upload_objs)
def get_down_objects(self,get):
"""
@name 获取可下载的对象存储
"""
return self.get_base_objects(self.__down_objs)
def _check_objects_conf(self,plu_name):
"""
@name 获取插件是否配置
"""
plugin_obj = self.get_plugin_main_object(plu_name)
args = public.dict_obj()
args.path = '/bt_upload/'
res = plugin_obj.get_config(args)
if 'status' in res and not res['status']:
return 0
for key in res:
if not res[key].strip(): return 0
return 1
def get_plugin_main_object(self,plugin_name):
"""
@name 获取插件主对象
@param plugin_name 插件名称
"""
sys_path = '{}/plugin/{}'.format(public.get_panel_path(),plugin_name)
if not os.path.exists(sys_path): return False
public.sys_path_append(sys_path)
os_file = '{}/{}_main.py'.format(sys_path,plugin_name)
plugin_obj = __import__(plugin_name + '_main')
plugin_obj = getattr(plugin_obj, plugin_name + '_main')()
return plugin_obj
def get_soft_find(self,name):
"""
@获取插件详细
"""
import panelPlugin
plu_obj = panelPlugin.panelPlugin()
return plu_obj.get_soft_find(name)
#************************ end 对象存储 ************************
+46
View File
@@ -0,0 +1,46 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: cjxin <cjxin@bt.cn>
#-------------------------------------------------------------------
# 上传文件至oss
#------------------------------
from filesModel.base import filesBase
import public
class main(filesBase):
def __init__(self):
pass
def get_oss_objects(self,get):
"""
@name 获取可上传的对象存储
"""
return self.get_all_objects(get)
def download_file(self,get):
"""
@name 下载文件
@param get
file:文件路径
"""
info = self.get_soft_find(get.name)
if not info['setup']:
return public.returnMsg(False,'未安装[{}]插件'.format(info['title']))
import panelTask
task_obj = panelTask.bt_task()
task_obj.create_task('下载文件', 1, get.url, get.path + '/' + get.filename)
public.set_module_logs('files_down_to_file', 'download_file', 1)
public.WriteLog('TYPE_FILE', '从 [{}] 下载文件 [{}] 到 {}'.format(info['title'],get.filename,get.path))
return public.returnMsg(True, 'FILE_DOANLOAD')
+342
View File
@@ -0,0 +1,342 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: cjxin <cjxin@bt.cn>
#-------------------------------------------------------------------
#
#------------------------------
import os,sys,re
from filesModel.base import filesBase
import public,json
import tarfile,shutil,gzip
class main(filesBase):
def __init__(self):
pass
def __check_zipfile(self,sfile,is_close = False):
'''
@name 检查文件是否为zip文件
@param sfile 文件路径
@return bool
'''
pass
def get_zip_files(self,args):
'''
@name 获取压缩包内文件列表
@param args['path'] 压缩包路径
@return list
'''
sfile = args.sfile
if not os.path.exists(sfile):
return public.returnMsg(False,'FILE_NOT_EXISTS')
if not tarfile.is_tarfile(sfile):
return public.returnMsg(False,'Not a valid tar.gz archive file')
zip_file = tarfile.open(sfile)
data = {}
for item in zip_file.getmembers():
sub_data = data
f_name = self.__get_zip_filename(item)
f_dirs = f_name.split('/')
for d in f_dirs:
if not d: continue
if not d in sub_data:
if d == f_name[-len(d):]:
sub_data[d] = {
'file_size': item.size,
'filename':d,
'fullpath':f_name,
'date_time': public.format_date(times=item.mtime),
'is_dir': 0
}
if item.isdir():
sub_data[d]['is_dir'] = 1
else:
sub_data[d] = {}
sub_data = sub_data[d]
return data
def get_fileinfo_by(self,args):
'''
@name 获取压缩包内文件信息
@param args['path'] 压缩包路径
@param args['filename'] 文件名
@return dict
'''
sfile = args.sfile
filename = args.filename
if not os.path.exists(sfile):
return public.returnMsg(False,'FILE_NOT_EXISTS')
tmp_path = '{}/tmp/{}'.format(public.get_panel_path(),public.md5(sfile + filename))
result = {}
result['status'] = True
result['data'] = ''
with tarfile.open(sfile,'r') as zip_file:
try:
zip_file.extract(filename,tmp_path)
result['data'] = public.readFile('{}/{}'.format(tmp_path,filename))
except:pass
try:
public.rmdir(tmp_path)
except:pass
return result
def delete_zip_file(self,args):
'''
@name 删除压缩包内文件
@param args['path'] 压缩包路径
@param args['filenames'] 文件名列表,数组格式
@return dict
'''
sfile = args.sfile
filenames = args.filenames
if not tarfile.is_tarfile(sfile):
return public.returnMsg(False,'Not a valid tar.gz archive file')
tmp_path = self.__unzip_tmp_path(sfile)
if not tmp_path: return public.returnMsg(False,'Failed edit!')
#组装原有的文件
s_list = []
src_list = {}
public.get_file_list(tmp_path,s_list)
for f in s_list:
if not os.path.isfile(f): continue
src_file = f.replace(tmp_path,'').strip('/')
if src_file in filenames:
continue
src_list[src_file] = f
with tarfile.open(sfile,'w') as new_zfile:
try:
for src_file in src_list:
new_zfile.add(src_list[src_file],src_file)
except:
shutil.rmtree(tmp_path, True)
return public.returnMsg(False,'Failed delete file,error:' + public.get_error_info())
shutil.rmtree(tmp_path, True)
return public.returnMsg(True,'Compressed package file modified successfully')
def write_zip_file(self,args):
'''
@name 写入压缩包内文件
@param args['path'] 压缩包路径
@param args['filename'] 文件名
@param args['data'] 写入数据
@return dict
'''
sfile = args.sfile
filename = args.filename
data = args.data
if not os.path.exists(sfile):
return public.returnMsg(False,'FILE_NOT_EXISTS')
tmp_path = self.__unzip_tmp_path(sfile)
if not tmp_path: return public.returnMsg(False,'Failed edit!')
public.writeFile('{}/{}'.format(tmp_path,filename),data)
#组装原有的文件
s_list = []
src_list = {}
public.get_file_list(tmp_path,s_list)
for f in s_list:
if os.path.isdir(f):
continue
src_file = f.replace(tmp_path,'').strip('/')
if src_file in src_list:
continue
src_list[src_file] = f
with tarfile.open(sfile,'w') as new_zfile:
try:
for src_file in src_list:
new_zfile.add(src_list[src_file],src_file)
except:
shutil.rmtree(tmp_path, True)
return public.returnMsg(False,'Failed modify file,error:' + public.get_error_info())
shutil.rmtree(tmp_path, True)
return public.returnMsg(True,'Compressed package file modified successfully')
def extract_byfiles(self,args):
"""
@name 解压部分文件
@param args['path'] 压缩包路径
@param args['extract_path'] 解压路径
@param args['filenames'] 文件名列表,数组格式
"""
sfile = args.sfile
filenames = args.filenames
extract_path = args.extract_path
if not os.path.exists(sfile):
return public.returnMsg(False,'FILE_NOT_EXISTS')
if not os.path.exists(extract_path):
os.makedirs(extract_path,384)
tmp_path = '{}/tmp/{}'.format(public.get_panel_path(),public.md5(public.GetRandomString(32)))
if not os.path.exists(tmp_path):
os.makedirs(tmp_path,384)
with tarfile.open(sfile) as zip_file:
try:
m_list = {}
f_infos = zip_file.getmembers()
for item in f_infos:
filename = self.__get_zip_filename(item)
if filename in filenames:
spath = os.path.join(tmp_path,filename).strip('/')
if item.isdir():
m_list[spath] = []
else:
if not 'other' in m_list:
m_list['other'] = []
dir_key = os.path.dirname(spath)
info = {'src':spath,'dst':'{}/{}'.format(extract_path, filename.strip('/'))}
if dir_key in m_list:
info['dst'] = '{}/{}'.format(extract_path,'/'.join(filename.split('/')[1:]))
s_path = os.path.dirname(info['dst'])
if not os.path.exists(s_path): os.makedirs(s_path,384)
m_list[dir_key].append(info)
else:
m_list['other'].append(info)
s_path = os.path.dirname(info['dst'])
if not os.path.exists(s_path): os.makedirs(s_path, 384)
zip_file.extract(filename.strip('/'),tmp_path)
for key in m_list:
try:
for info in m_list[key]:
if os.getenv('BT_PANEL'):
shutil.copyfile(info['src'],info['dst'])
else:
shutil.copyfile('/' + info['src'],'/' + info['dst'])
except:
pass
shutil.rmtree(tmp_path, True)
except:
return public.returnMsg(False,'Decompression failed,error:' + public.get_error_info())
return public.returnMsg(True,'File was decompressed successfully')
def __unzip_tmp_path(self,sfile):
'''
@name 获取临时解压路径
@param sfile 压缩包路径
@return str
'''
tmp_path = '{}/tmp/{}'.format(public.get_soft_path(),public.md5(public.GetRandomString(32)))
with tarfile.open(sfile) as zip_file:
try:
zip_file.extractall(tmp_path)
except: return False
return tmp_path
def add_zip_file(self,args):
'''
@name 添加文件到压缩包
@param args['r_path'] 跟路径
@param args['filename'] 文件名
@param args['f_list'] 写入数据
@return dict
'''
sfile = args.sfile
r_path = args.r_path
f_list = args.f_list
if not os.path.exists(sfile):
return public.returnMsg(False,'FILE_NOT_EXISTS')
tmp_path = self.__unzip_tmp_path(sfile)
if not tmp_path: return public.returnMsg(False,'Failed edit!')
#组装新添加的文件
src_list = {}
for fname in f_list:
if os.path.isdir(fname):
s_list = []
public.get_file_list(fname,s_list)
for f in s_list:
if os.path.isdir(f):
continue
src_file = '{}/{}{}'.format(r_path,os.path.basename(fname),f.replace(fname,'')).replace('//','/')
src_list[src_file] = f
else:
src_file = '{}/{}'.format(r_path, os.path.basename(fname)).replace('//','/')
src_list[src_file] = fname
#组装原有的文件
s_list = []
public.get_file_list(tmp_path,s_list)
for f in s_list:
if os.path.isdir(f):
continue
src_file = f.replace(tmp_path,'').strip('/')
if src_file in src_list:
continue
src_list[src_file] = f
with tarfile.open(sfile,'w') as new_zfile:
try:
for src_file in src_list:
new_zfile.add(src_list[src_file],src_file)
except:
shutil.rmtree(tmp_path, True)
return public.returnMsg(False,'Failed add file,error:' + public.get_error_info())
shutil.rmtree(tmp_path, True)
return public.returnMsg(True,'Compressed package file modified successfully')
def __get_zip_filename(self,item):
'''
@name 获取压缩包文件名
@param item 压缩包文件对象
@return string
'''
filename = item.name
try:
filename = item.name.encode('cp437').decode('gbk')
except:pass
if item.isdir():
filename += '/'
return filename
+289
View File
@@ -0,0 +1,289 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: cjxin <cjxin@bt.cn>
#-------------------------------------------------------------------
#
#------------------------------
import os,sys,re
from filesModel.base import filesBase
import public,files,json,time
from BTPanel import cache
class main(filesBase):
__objs = ['bos']
def __init__(self):
pass
def get_logs_info(self,get):
"""
@查看日志
@param get
limit:每页显示条数
file:日志文件
"""
p = 1
limit = 200
search = None
file = get.file
if 'limit' in get: limit = int(get.limit)
if 'p' in get: limit = int(get.p)
if 'search' in get: search = get.search
if not os.path.exists(file):
return public.returnMsg(False,'Please specify file!')
res = {}
res['status'] = True
res['data'] = self.GetNumLines(file,limit,p,search)
res['md5'] = public.md5(res['data'])
res['limit'] = limit
if not cache.get(file+'_logs_info'):
public.set_module_logs('files_get_logs_info','get_logs_info')
cache.set(file+'_logs_info','1',86400)
return res
def set_log_split(self,get):
"""
@name 文件切割
@param filename 文件路径
@param stype 切割类型 day:按天切割 size:按大小切割
@param size 切割大小(stype=size必传)
"""
filename = get.filename
stype = get.stype
limit = int(get.limit)
if not stype in ['day','size']:
return public.returnMsg(False,'Cut type passing error.')
if not os.path.exists(filename):
return public.returnMsg(False,'FILE_NOT_EXISTS')
if limit < 3:
return public.returnMsg(False,'The number of reserved copies cannot be less than 3.')
data = {'type':stype,'limit':limit,'addtime':int(time.time())}
if stype == 'size':
size = int(get.size)
if size < 1024:
return public.returnMsg(False,'Cut size cannot be empty.')
data['size'] = size
public.set_split_logs(filename,1,data)
return public.returnMsg(True,'successfully set.')
def get_log_split(self,get):
"""
@name 获取文件切割信息
@param filename 文件路径
"""
data = {}
sfile = '{}/data/cutting_log.json'.format(public.get_panel_path())
if os.path.exists(sfile):
try:
data = json.loads(public.readFile(sfile))
except:pass
return data
def get_file_ext(self,filename):
"""
@name 获取文件扩展名
@param filename
"""
ss_exts = ['.tar.gz','.tar.bz2','.tar.bz']
for s in ss_exts:
e_len = len(s)
f_len = len(filename)
if f_len < e_len: continue
if filename[-e_len:] == s:
return filename[:-e_len] ,s
if filename.find('.') == -1: return filename,''
return os.path.splitext(filename)
def copy_file_to(self, get):
"""
@name 创建文件副本
@param get
@return
"""
sfile = get.sfile
if not os.path.exists(sfile):
return public.returnMsg(False, 'FILE_NOT_EXISTS')
spath,ext = sfile,''
if os.path.isfile(get.sfile):
spath,ext = self.get_file_ext(sfile)
# public.print_log(spath)
for x in range(1,1000):
dfile = '{} - copy ({}){}'.format(spath,x,ext)
if not os.path.exists(dfile):
break
get.dfile = dfile
f_obj = files.files()
if os.path.isdir(get.sfile):
public.WriteLog("File manager","Create copy of the directory [{}]".format(sfile))
return f_obj.CopyDir(get)
import shutil
try:
shutil.copyfile(get.sfile, get.dfile)
public.WriteLog('TYPE_FILE', 'FILE_COPY_SUCCESS',
(get.sfile, get.dfile))
try:
stat = os.stat(get.sfile)
os.chmod(get.dfile,stat.st_mode)
os.chown(get.dfile, stat.st_uid, stat.st_gid)
except:pass
public.WriteLog("File manager","Create copy of the file[{}]".format(sfile))
return public.returnMsg(True, 'FILE_COPY_SUCCESS')
except:
return public.returnMsg(False, 'FILE_COPY_ERR')
def set_topping_status(self,get):
"""
@name 设置文件或目录置顶
@param get
file:文件路径
type:置顶类型
"""
sfile = get.sfile
status = int(get.status)
if not os.path.exists(sfile):
import html
sfile = html.unescape(sfile)
if not os.path.exists(sfile):
return public.returnMsg(False, 'File or directory does not exist.')
data = {}
conf_file = '{}/data/toping.json'.format(public.get_panel_path())
try :
if os.path.exists(conf_file):
data = json.loads(public.readFile(conf_file))
except:pass
if sfile in data: del data[sfile]
if status:
data[sfile] = status
public.writeFile(conf_file, json.dumps(data))
public.set_module_logs('files_set_topping_status','set_topping_status')
public.WriteLog("File manager","Modify [{}] top status".format(sfile))
return public.returnMsg(True, 'Successful set.')
def GetNumLines(self,path, num, p=1,search = None):
"""
@name 取文件指定尾行数
@param path 文件路径
@param num 取尾行数
@param p 当前页
@param search 搜索关键字
@return list
"""
pyVersion = sys.version_info[0]
max_len = 1024 * 128
try:
from html import escape
if not os.path.exists(path): return ""
start_line = (p - 1) * num
count = start_line + num
fp = open(path, 'rb')
buf = ""
fp.seek(-1, 2)
if fp.read(1) == "\n": fp.seek(-1, 2)
data = []
total_len = 0
b = True
n = 0
for i in range(count):
while True:
newline_pos = str.rfind(str(buf), "\n")
pos = fp.tell()
if newline_pos != -1:
if n >= start_line:
line = buf[newline_pos + 1:]
is_res = True
if search:
is_res = False
if line.find(search) >= 0 or re.search(search,line):
is_res = True
if is_res:
line_len = len(line)
total_len += line_len
sp_len = total_len - max_len
if sp_len > 0:
line = line[sp_len:]
try:
data.insert(0, escape(line))
except:
pass
buf = buf[:newline_pos]
n += 1
break
else:
if pos == 0:
b = False
break
to_read = min(4096, pos)
fp.seek(-to_read, 1)
t_buf = fp.read(to_read)
if pyVersion == 3:
try:
if type(t_buf) == bytes: t_buf = t_buf.decode('utf-8',errors='ignore')
except:
try:
if type(t_buf) == bytes: t_buf = t_buf.decode('gbk',errors='ignore')
except:
t_buf = str(t_buf)
buf = t_buf + buf
fp.seek(-to_read, 1)
if pos - to_read == 0:
buf = "\n" + buf
if total_len >= max_len: break
if not b: break
fp.close()
result = "\n".join(data)
if not result: raise Exception('null')
except:
result = ''
if len(result) > max_len:
result = result[-max_len:]
try:
try:
result = json.dumps(result)
return json.loads(result).strip()
except:
if pyVersion == 2:
result = result.decode('utf8', errors='ignore')
else:
result = result.encode('utf-8', errors='ignore').decode("utf-8", errors="ignore")
return result.strip()
except:
return ""
+243
View File
@@ -0,0 +1,243 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: cjxin <cjxin@bt.cn>
#-------------------------------------------------------------------
#
#------------------------------
import os,sys,re
from filesModel.base import filesBase
import public,json
import zipfile,shutil
try:
from unrar import rarfile
except:
os.system('btpip install unrar')
from unrar import rarfile
class main(filesBase):
def __init__(self):
pass
def __check_zipfile(self,sfile,is_close = False):
'''
@name 检查文件是否为zip文件
@param sfile 文件路径
@return bool
'''
zip_file = None
try:
zip_file = rarfile.RarFile(sfile)
except:pass
if is_close and zip_file:
zip_file.close()
return zip_file
def get_zip_files(self,args):
'''
@name 获取压缩包内文件列表
@param args['path'] 压缩包路径
@return list
'''
sfile = args.sfile
if not os.path.exists(sfile):
return public.returnMsg(False,'FILE_NOT_EXISTS')
zip_file = self.__check_zipfile(sfile)
if not zip_file:
return public.returnMsg(False,'NOT_ZIP_FILE')
data = {}
for item in zip_file.infolist():
sub_data = data
f_name = self.__get_zip_filename(item)
f_dirs = f_name.split('/')
for d in f_dirs:
if not d: continue
if not d in sub_data:
if d == f_name[-len(d):]:
tmps = item.date_time
sub_data[d] = {
'file_size': item.file_size,
'compress_size': item.compress_size,
'filename':d,
'fullpath':f_name,
'date_time': public.to_date(times = '{}-{}-{} {}:{}:{}'.format(tmps[0],tmps[1],tmps[2],tmps[3],tmps[4],tmps[5])),
'is_dir': 0
}
if item.flag_bits == 32:
sub_data[d]['is_dir'] = 1
else:
sub_data[d] = {}
sub_data = sub_data[d]
return data
def get_fileinfo_by(self,args):
'''
@name 获取压缩包内文件信息
@param args['path'] 压缩包路径
@param args['filename'] 文件名
@return dict
'''
sfile = args.sfile
filename = args.filename
if not os.path.exists(sfile):
return public.returnMsg(False,'FILE_NOT_EXISTS')
result = {}
result['status'] = True
result['data'] = ''
with rarfile.RarFile(sfile,'r') as zip_file:
for item in zip_file.infolist():
z_filename = self.__get_zip_filename(item)
if z_filename == filename:
buff = zip_file.read(item.filename)
encoding,srcBody = public.decode_data(buff)
result['encoding'] = encoding
result['data'] = srcBody
break
return result
def delete_zip_file(self,args):
'''
@name 删除压缩包内文件
@param args['path'] 压缩包路径
@param args['filenames'] 文件名列表,数组格式
@return dict
'''
sfile = args.sfile
filenames = args.filenames
return public.returnMsg(False,'RAR archive files do not support file deletion')
def write_zip_file(self,args):
'''
@name 写入压缩包内文件
@param args['path'] 压缩包路径
@param args['filename'] 文件名
@param args['data'] 写入数据
@return dict
'''
sfile = args.sfile
filename = args.filename
data = args.data
return public.returnMsg(False,'RAR archive does not support this function!')
def extract_byfiles(self,args):
"""
@name 解压部分文件
@param args['path'] 压缩包路径
@param args['extract_path'] 解压路径
@param args['filenames'] 文件名列表,数组格式
"""
sfile = args.sfile
filenames = args.filenames
extract_path = args.extract_path
if not os.path.exists(sfile):
return public.returnMsg(False,'FILE_NOT_EXISTS')
if not os.path.exists(extract_path):
os.makedirs(extract_path,384)
tmp_path = '{}/tmp/{}'.format(public.get_soft_path(),public.md5(public.GetRandomString(32)))
if not os.path.exists(tmp_path):
os.makedirs(tmp_path,384)
with rarfile.RarFile(sfile) as zip_file:
try:
m_list = {}
f_infos = zip_file.infolist()
f_infos = sorted(f_infos,key=lambda x:x.filename)
for item in f_infos:
filename = self.__get_zip_filename(item)
if filename in filenames:
spath = os.path.join(tmp_path,filename).strip('/')
if item.flag_bits == 32:
m_list[spath] = []
else:
if not 'other' in m_list:
m_list['other'] = []
dir_key = os.path.dirname(spath)
info = {'src':spath,'dst':'{}/{}'.format(extract_path,os.path.basename(spath))}
if dir_key in m_list:
info['dst'] = '{}/{}'.format(extract_path,'/'.join(filename.split('/')[1:]))
s_path = os.path.dirname(info['dst'])
if not os.path.exists(s_path): os.makedirs(s_path,384)
m_list[dir_key].append(info)
else:
m_list['other'].append(info)
zip_file.extract(filename.strip('/').replace('/','\\'),tmp_path)
for key in m_list:
try:
# if key != 'other':
# dir_name = '{}/{}'.format(extract_path,os.path.basename(key))
# if not os.path.exists(dir_name): os.makedirs(dir_name,384)
for info in m_list[key]:
shutil.copyfile(info['src'],info['dst'])
except:pass
shutil.rmtree(tmp_path, True)
except:
return public.returnMsg(False,'Decompression failed,error:' + public.get_error_info())
return public.returnMsg(True,'The file was decompressed successfully')
def add_zip_file(self,args):
'''
@name 添加文件到压缩包
@param args['r_path'] 跟路径
@param args['filename'] 文件名
@param args['f_list'] 写入数据
@return dict
'''
sfile = args.sfile
r_path = args.r_path
f_list = args.f_list
return public.returnMsg(False,'RAR archive does not support this function!')
def __get_zip_filename(self,item):
'''
@name 获取压缩包文件名
@param item 压缩包文件对象
@return string
'''
filename = item.filename
try:
filename = item.filename.encode('cp437').decode('gbk')
except:pass
if item.flag_bits == 32:
filename += '/'
return filename.replace('\\','/')
+307
View File
@@ -0,0 +1,307 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: cjxin <cjxin@bt.cn>
#-------------------------------------------------------------------
#
#------------------------------
import os, re
from filesModel.base import filesBase
import public, json
from html import escape
class main(filesBase):
__s_class = []
def __init__(self):
for i in range(1, 100):
self.__s_class.append('f-s-%s' % i)
def get_search_status(self, get):
"""
@name 验证是否可用
"""
return public.returnMsg(True, '1')
def get_search_result(self, get):
"""
@name 搜索文件
@param get
path:搜索路径
search:搜索关键字
limit:每页显示条数
p:页码
"""
result = {}
is_dir = 0
search = []
if not 'ext' in get: get.ext = '*'
if 'search' in get: search = get.search
if 'is_dir' in get: is_dir = get.is_dir
public.set_module_logs('searchModel', 'get_search_result')
if not is_dir:
if len(search) == 0:
return public.returnMsg(False, 'Please enter search keywords!')
if not os.path.exists(get.path):
return public.returnMsg(False, 'Search directory does not exist!')
slist = self.get_search_files(get)
if is_dir: return slist
num = 0
total_num = len(slist)
if slist: public.writeSpeed('files_search', num, total_num)
for sfile in slist:
data = self.__check_file_contents(sfile, search)
if data:
result[sfile] = data
num += 1
public.writeSpeed('files_search', num, total_num)
progress = int(public.getSpeed()['progress'])
if '_ws' in get:
get._ws.send(
public.getJson({
"end": False if progress < 100 else True,
"ws_callback": get.ws_callback,
"file": sfile,
"progress": progress,
"total": total_num,
"num": num,
"type": "get_search_result"
}))
if not slist and '_ws' in get:
get._ws.send(
public.getJson({
"end": True,
"ws_callback": get.ws_callback,
"file": '',
"progress": 100,
"total": 0,
"num": 0,
"type": "get_search_result"
}))
return result
def get_search_files(self, get):
"""
@name 搜索文件
@param get
path:搜索路径
search:搜索关键字
"""
data = {}
data['is_sub'] = 0
if 'is_sub' in get:
data['is_sub'] = int(get.is_sub)
data['ext'] = []
for ext in get.ext.split(','):
if ext: data['ext'].append(ext)
data['s_time'] = 0
data['e_time'] = 4070880000
if 's_time' in get:
data['s_time'] = int(get.s_time)
if 'e_time' in get:
data['e_time'] = int(get.e_time)
data['min_size'] = 0
data['max_size'] = 1024 * 1024 * 10
if 'min_size' in get:
data['min_size'] = int(get.min_size)
if 'max_size' in get:
data['max_size'] = int(get.max_size)
data['names'] = []
if 'names' in get:
data['names'] = get.names
flist = []
self.__get_file_list(get.path, data, flist)
return flist
def __check_file_contents(self, sfile, contents):
"""
@name 验证文件内容
@param sfile:文件路径
@param contents:文件内容
"""
n = 1
result = {}
try:
for line in open(sfile, 'rb'):
try:
if type(line) == bytes: line = line.decode('utf-8')
except:
line = str(line)
rep_list = {}
_line = escape(line)
p = 0
for txt in contents:
if not txt: continue
p += 1
txt = escape(txt)
if line.find(txt) >= 0:
_line = self.__replace_contents(
_line, txt, p, rep_list)
else:
tmp = re.search('(' + txt + ')', _line, flags=re.I)
if tmp:
_line = self.__replace_contents(
_line,
tmp.groups()[0], p, rep_list)
for key in rep_list:
# public.print_log(json.dumps(rep_list))
result[n] = _line.replace(key, rep_list[key])
n += 1
except:
pass
return result
# line = line.replace("BT_SEARCH".format(p), )
def __replace_contents(self, line, txt, p, rep_list):
"""
@name 替换文件内容
@param line:文件内容
@param txt:替换内容
@param p:替换位置
"""
n_data = 'BT_SEARCH{}'.format(p)
line = line.replace(txt, n_data)
rep_list[n_data] = "<span class='{}'>{}</span>".format(
self.__s_class[p - 1], txt)
return line
def __get_file_list(self, path, data, flist):
"""
@name 获取文件列表
@param path:文件路径
@param ext:文件类型
@param s_time:开始时间
@param e_time:结束时间
@param min_size:最小文件大小
@param max_size:最大文件大小
@param flist:返回文件列表
"""
exts, s_time, e_time, min_size, max_size, names = data['ext'], data[
's_time'], data['e_time'], data['min_size'], data[
'max_size'], data['names']
for name in os.listdir(path):
sfile = os.path.join(path, name)
if os.path.isdir(sfile):
if not data['is_sub']: continue
self.__get_file_list(sfile, data, flist)
else:
#第一步:验证文件名
if not self.__check_filename(sfile=sfile, names=names):
continue
#第二步:验证后缀
if not self.__check_ext(sfile=sfile, exts=exts):
continue
#第三步:验证时间
if not self.__check_time(
sfile=sfile, s_time=s_time, e_time=e_time):
continue
#第四步:验证大小
if not self.__check_size(
sfile=sfile, min_size=min_size, max_size=max_size):
continue
flist.append(sfile)
def __check_filename(self, sfile, names):
"""
@name 验证文件名
@param sfile:文件路径
@param names:文件名
"""
try:
if len(names) == 0: return True
filename = os.path.basename(sfile)
for name in names:
if filename.find(name) >= 0:
return True
try:
if re.search(name, filename):
return True
except:
pass
except:
pass
return False
def __check_ext(self, sfile, exts):
"""
@name 验证文件后缀
@param sfile:文件路径
@param exts:文件类型
"""
try:
if "*" in exts:
return True
spath, ext = os.path.splitext(sfile)
if ext:
if ext[1:] in exts:
return True
else:
if 'no_ext' in exts:
return True
except:
pass
return False
def __check_time(self, sfile, s_time, e_time):
"""
@name 验证文件时间
@param sfile:文件路径
@param s_time:开始时间
@param e_time:结束时间
"""
try:
st_time = int(os.stat(sfile).st_mtime)
if st_time >= s_time and st_time <= e_time:
return True
except:
pass
return False
def __check_size(self, sfile, min_size, max_size):
"""
@name 验证文件大小
@param sfile:文件路径
@param min_size:最小文件大小
@param max_size:最大文件大小
"""
try:
f_size = os.path.getsize(sfile)
if f_size >= min_size and f_size <= max_size:
return True
except:
pass
return False
+287
View File
@@ -0,0 +1,287 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: cjxin <cjxin@bt.cn>
#-------------------------------------------------------------------
import copy
import random
# 获取目录大小
#------------------------------
import sys, os
import json, os, time, re
import public
from filesModel.base import filesBase
panelPath = '/www/server/panel'
os.chdir(panelPath)
class main(filesBase):
_exe_cmd = 'ncdu'
# 扫描历史
log_path = '{}/data/scan/'.format(public.get_panel_path())
# 缓存
cache_file = '{}/config/scan_disk_cache.json'.format(public.get_panel_path())
def __init__(self):
self.is_use = False
if os.path.isdir("{}/plugin/disk_analysis".format(public.get_panel_path())):
self.is_use = True
if not os.path.exists(self.log_path):
os.makedirs(self.log_path)
if not os.path.exists(self.cache_file):
public.writeFile(self.cache_file,"{}")
if os.getenv('BT_PANEL'):
self._exe_cmd = '{}/plugin/disk_analysis/ncdu'.format(panelPath)
def get_path_size(self, get):
"""
@name 根据排除目录获取路径的总大小
@param path 目标路径
"""
if self.is_use is False:
return {"code": 404, "status": False, "msg": 'Please install [Disk analysis] first !'}
path = get.path
is_refresh = get.is_refresh == "true"
real_path_dict = {} # 软连接处理
temp_path_list = []
for path in str(path).split(","):
r_path = os.path.realpath(path)
if r_path != path:
real_path_dict[r_path] = path
path = r_path
if path != "/": path = str(path).rstrip("/")
temp_path_list.append(path)
try:
cache_data = json.loads(public.readFile(self.cache_file))
except:
cache_data = {}
result = {}
path_list = []
if is_refresh is True:
path_list = temp_path_list
else:
for path in temp_path_list:
if cache_data.get(path) is not None:
result[path] = cache_data.get(path)
else:
path_list.append(path)
if path_list:
scan_path = path_list[0]
if os.path.isfile(scan_path):
scan_path = os.path.split(scan_path)[0]
for path in path_list[1:]:
while True:
if path.startswith(scan_path):
break
scan_path = os.path.split(scan_path)[0]
import string
code = "".join(random.sample(string.ascii_letters + string.digits, 8))
result_file = '{}{}'.format(self.log_path, f"temp_scan_size_{code}")
scan_time = int(time.time())
exec_shell = "{} '{}' -o '{}' ".format(self._exe_cmd, scan_path, result_file).replace('\\', '/').replace('//','/')
public.ExecShell(exec_shell)
scan_result = self.__get_log_size(result_file, path_list, scan_time, cache_data)
os.remove(result_file)
result.update(scan_result)
public.writeFile(self.cache_file, json.dumps(cache_data))
for r_path, path in real_path_dict.items():
result[path] = result[r_path]
del result[r_path]
return result
@classmethod
def __get_log_size(cls, log_file, path_list, scan_time, cache_data):
"""
@name 获取文件或目录大小
@param log_file 日志文件
"""
result = {}
for path in path_list:
result[path] = None
data = public.readFile(log_file)
data = json.loads(data)
data = data[-1]
root_path = data[0]["name"]
if root_path in path_list:
result[root_path] = data
else:
cls.__get_sub_size(data[1:], root_path, path_list, result)
for path,info in result.items():
if info is None:
continue
if isinstance(info, dict):
info["type"] = 0
info["asize"] = info.get("asize", 0)
info["dsize"] = info.get("dsize", 0)
info["dir_num"] = 0
info["file_num"] = 0
info["total_asize"] = info.get("asize", 0)
info["total_dsize"] = info.get("dsize", 0)
info["stime"] = scan_time
cls.__get_stat(path, info)
cache_data[path] = info
else:
cls.__get_dirs_size(info)
cls.__get_stat(path, info[0])
result[path] = info[0]
result[path]["stime"] = scan_time
cache_data[path] = result[path]
return result
@classmethod
def __get_sub_size(cls, data, root_path, path_list, result):
"""
@name 获取子目录数据
@param id int 记录id
@param path string 目录
"""
if len(path_list) == 0: return
for val in data:
if isinstance(val, list):
sfile = f"{root_path}/{val[0]['name']}".replace('\\', '/').replace('//', '/')
if sfile in path_list:
result[sfile] = val
path_list.remove(sfile)
if len(val) > 1:
cls.__get_sub_size(val[1:], sfile, path_list, result)
elif isinstance(val, dict):
sfile = f"{root_path}/{val['name']}".replace('\\', '/').replace('//', '/')
if sfile in path_list:
result[sfile] = val
path_list.remove(sfile)
@classmethod
def __get_dirs_size(cls, dirs_list):
"""
@param info 目录信息
@param result 结果
"""
dir_info = dirs_list[0]
dir_info["type"] = 1
dir_info["asize"] = dir_info.get("asize", 0)
dir_info["dsize"] = dir_info.get("dsize", 0)
dir_info["dirs"] = 0
dir_info["files"] = 0
dir_info["dir_num"] = 0
dir_info["file_num"] = 0
dir_info["total_asize"] = dir_info.get("asize", 0)
dir_info["total_dsize"] = dir_info.get("dsize", 0)
for info in dirs_list[1:]:
if isinstance(info, list): # 目录
dir_info["dirs"] += 1
dir_info["dir_num"] += 1
cls.__get_dirs_size(info)
temp_info = info[0]
dir_info["dir_num"] += temp_info["dir_num"]
dir_info["file_num"] += temp_info["file_num"]
dir_info["total_asize"] += temp_info["total_asize"]
dir_info["total_dsize"] += temp_info["total_dsize"]
else:
if info.get("excluded") == "pattern":
continue
dir_info["files"] += 1
dir_info["file_num"] += 1
if info.get("asize") is None: info["asize"] = 0
if info.get("dsize") is None: info["dsize"] = 0
info["type"] = 0
dir_info["total_asize"] += info["asize"]
dir_info["total_dsize"] += info["dsize"]
@classmethod
def __get_stat(cls, path, info):
if not os.path.exists(path):
info["accept"] = None
info["user"] = None
info["mtime"] = "--"
info["ps"] = None
return
stat_file = os.stat(path)
info["accept"] = oct(stat_file.st_mode)[-3:]
import pwd
try:
info["user"] = pwd.getpwuid(stat_file.st_uid).pw_name
except:
info["user"] = str(stat_file.st_uid)
info["atime"] = int(stat_file.st_atime)
info["ctime"] = int(stat_file.st_ctime)
info["mtime"] = int(stat_file.st_mtime)
info["ps"] = cls.get_file_ps(path)
@classmethod
def get_file_ps(cls,filename):
'''
@name 获取文件或目录备注
@author hwliang<2020-10-22>
@param filename<string> 文件或目录全路径
@return string
'''
ps_path = public.get_panel_path() + '/data/files_ps'
f_key1 = '/'.join((ps_path,public.md5(filename)))
if os.path.exists(f_key1):
return public.readFile(f_key1)
f_key2 = '/'.join((ps_path,public.md5(os.path.basename(filename))))
if os.path.exists(f_key2):
return public.readFile(f_key2)
pss = {
'/www/server/data': 'This is the default data directory of the MySQL database, please do not delete it!',
'/www/server/mysql': 'MySQL program directory',
'/www/server/redis': 'Redis program directory',
'/www/server/mongodb': 'MongoDB program directory',
'/www/server/nvm': 'PM2/NVM/NPM program directory',
'/www/server/pass': 'Website BasicAuth authentication password storage directory',
'/www/server/speed': 'Website acceleration data directory',
'/www/server/docker': 'Docker plugin and data directory',
'/www/server/total': 'Website monitoring report data directory',
'/www/server/btwaf': 'WAF firewall data directory',
'/www/server/pure-ftpd': 'ftp program directory',
'/www/server/phpmyadmin': 'phpMyAdmin program directory',
'/www/server/rar': 'rar expansion library directory, will lose support for RAR compressed files after deletion',
'/www/server/stop': 'The website deactivates the page directory, please do not delete it!',
'/www/server/nginx': 'Nginx program directory',
'/www/server/apache': 'Apache program directory',
'/www/server/cron': 'Scheduled task script and log directory',
'/www/server/php': 'PHP directory, all PHP version interpreters are in this directory',
'/www/server/tomcat': 'Tomcat program directory',
'/www/php_session': 'PHP-SESSION isolation directory',
'/www/server/panel': 'aaPanel program directory',
'/proc': 'system process directory',
'/dev': 'system device directory',
'/sys': 'system call directory',
'/tmp': 'system temporary file directory',
'/var/log': 'System log directory',
'/var/run': 'System running log directory',
'/var/spool': 'system queue directory',
'/var/lock': 'system lock directory',
'/var/mail': 'system mail directory',
'/mnt': 'System mount directory',
'/media': 'System multimedia directory',
'/dev/shm': 'system shared memory directory',
'/lib': 'system dynamic library directory',
'/lib64': 'system dynamic library directory',
'/lib32': 'system dynamic library directory',
'/usr/lib': 'system dynamic library directory',
'/usr/lib64': 'system dynamic library directory',
'/usr/local/lib': 'system dynamic library directory',
'/usr/local/lib64': 'system dynamic library directory',
'/usr/local/libexec': 'system dynamic library directory',
'/usr/local/sbin': 'System script directory',
'/usr/local/bin': 'System script directory'
}
if filename in pss: return "PS" + pss[filename]
return None
+170
View File
@@ -0,0 +1,170 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: cjxin <cjxin@bt.cn>
#-------------------------------------------------------------------
# 上传文件至oss
#------------------------------
import os
from filesModel.base import filesBase
import public,smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.utils import formataddr
class main(filesBase):
def __init__(self):
pass
def get_oss_objects(self,get):
"""
@name 获取可上传的对象存储
"""
return self.get_all_objects(get)
def get_file_list(self,get):
"""
@name 获取可上传的对象存储
"""
return self.get_base_objects(get)
def check_email_config(self,get):
"""
@name 检测邮箱是否配置
"""
import config
c_obj = config.config()
mail_config = c_obj.get_msg_configs(get)['mail']
return mail_config
def send_to_email(self,get):
"""
@name 发送文件到邮件
@flist list 文件列表
@msg string 邮件正文
@to string 邮件接收人,多个逗号隔开
"""
import config
c_obj = config.config()
try:
mail_config = c_obj.get_msg_configs(get)['mail']['data']
if not mail_config :
return public.returnMsg(False,'未正确配置邮箱信息。')
if not mail_config['send']['qq_mail']:
return public.returnMsg(False,'未正确配置邮箱信息。')
except:
return public.returnMsg(False,'未正确配置邮箱信息。')
msg = get.msg
receive_list = get.to_email.split(',')
if len(receive_list) <= 0:
return public.returnMsg(False,'发送失败,接收者不能为空.')
#附件文件
flist = []
if 'flist' in get: flist = get.flist
result = {}
result['status'] = True
result['list'] = {}
for email in receive_list:
slist = {}
try:
data = MIMEMultipart()
data['From'] = formataddr([mail_config['send']['qq_mail'], mail_config['send']['qq_mail']])
data['To'] = formataddr([mail_config['send']['qq_mail'], email.strip()])
data['Subject'] = '宝塔面板消息通知'
if int(mail_config['send']['port']) == 465:
server = smtplib.SMTP_SSL(str(mail_config['send']['hosts']), str(mail_config['send']['port']))
else:
server = smtplib.SMTP(str(mail_config['send']['hosts']), str(mail_config['send']['port']))
data.attach(MIMEText(msg, 'html', 'utf-8'))
slist['error'] = {}
#添加附件
for filename in flist:
if not os.path.exists(filename):
slist['error'][filename] = '文件不存在'
continue
#超过50M无法发送
if os.path.getsize(filename) > 50 * 1024 *1024:
slist['error'][filename] = '文件大于50M'
continue
#中文无法发送
if public.check_chinese(filename):
slist['error'][filename] = '文件名包含中文,发送失败.'
continue
att1 = MIMEText(open(filename, 'rb').read(), 'base64', 'utf-8')
att1["Content-Type"] = 'application/octet-stream'
att1["Content-Disposition"] = 'attachment; filename="' + os.path.basename(filename) + '"'
data.attach(att1)
server.login(mail_config['send']['qq_mail'], mail_config['send']['qq_stmp_pwd'])
server.sendmail(mail_config['send']['qq_mail'], [email.strip(), ], data.as_string())
server.quit()
slist['status'] = True
except :
slist = '发送失败,' + public.get_error_info()
result['list'][email] = slist
public.set_module_logs('files_send_to_email', 'send_to_email', 1)
return result
def upload_file(self,args):
"""
@name 上传文件到指定的对象存储
"""
name = args.name
filename = args.filename
bucket = args.object_name.rstrip('/')
if not os.path.exists(filename):
return public.returnMsg(False,'FILE_NOT_EXIST')
info = self.get_soft_find(name)
if not info['setup']:
return public.returnMsg(False,'未安装[{}]插件'.format(info['title']))
sfile = '{path}/plugin/{name}/{name}_main.py'.format(path=public.get_panel_path(),name=name)
if public.readFile(sfile).find('upload_to') == -1:
return public.returnMsg(False,'暂不支持该操作,请将[{}]插件升级到最新版'.format(info['title']))
#创建任务
import panelTask
task_obj = panelTask.bt_task()
msg = '上传文件{}{}'.format(filename,info['title'])
exec_shell = 'btpython -u {spath} upload_to {file} {bucket}/{filename}'.format(spath=sfile,file=filename,bucket=bucket,filename=os.path.basename(filename))
task_obj.create_task(msg, 0, exec_shell)
public.set_module_logs('files_upload_to_file', 'upload_file', 1)
public.WriteLog('TYPE_FILE', msg)
return public.returnMsg(True, '已添加到上传队列.')
+327
View File
@@ -0,0 +1,327 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: cjxin <cjxin@bt.cn>
#-------------------------------------------------------------------
#
#------------------------------
import os,sys,re
from filesModel.base import filesBase
import public,json
import zipfile,shutil
from pathlib import Path
class main(filesBase):
def __init__(self):
pass
def __check_zipfile(self,sfile,is_close = False):
'''
@name 检查文件是否为zip文件
@param sfile 文件路径
@return bool
'''
zip_file = None
try:
zip_file = zipfile.ZipFile(sfile)
except:pass
if is_close and zip_file:
zip_file.close()
return zip_file
def get_zip_files(self,args):
'''
@name 获取压缩包内文件列表
@param args['path'] 压缩包路径
@return list
'''
sfile = args.sfile
if not os.path.exists(sfile):
return public.returnMsg(False,'FILE_NOT_EXISTS')
zip_file = self.__check_zipfile(sfile)
if not zip_file:
return public.returnMsg(False,'NOT_ZIP_FILE')
data = {}
for item in zip_file.infolist():
sub_data = data
f_name = self.__get_zip_filename(item)
f_dirs = f_name.split('/')
d_idx = 0
for d in f_dirs:
if not d: continue
if not d in sub_data:
if d == f_name[-len(d):] and d_idx == len(f_dirs) - 1:
tmps = item.date_time
sub_data[d] = {
'file_size': item.file_size,
'compress_size': item.compress_size,
'compress_type': item.compress_type,
'filename':d,
'fullpath':f_name,
'date_time': public.to_date(times = '{}-{}-{} {}:{}:{}'.format(tmps[0],tmps[1],tmps[2],tmps[3],tmps[4],tmps[5])),
'is_dir': 0
}
if item.is_dir():
sub_data[d]['is_dir'] = 1
else:
sub_data[d] = {}
d_idx += 1
sub_data = sub_data[d]
zip_file.close()
return data
def get_fileinfo_by(self,args):
'''
@name 获取压缩包内文件信息
@param args['path'] 压缩包路径
@param args['filename'] 文件名
@return dict
'''
sfile = args.sfile
filename = args.filename
if not os.path.exists(sfile):
return public.returnMsg(False,'FILE_NOT_EXISTS')
result = {}
result['status'] = True
result['data'] = ''
with zipfile.ZipFile(sfile,'r') as zip_file:
for item in zip_file.infolist():
z_filename = self.__get_zip_filename(item)
if z_filename == filename:
buff = zip_file.read(item.filename)
encoding,srcBody = public.decode_data(buff)
result['encoding'] = encoding
result['data'] = srcBody
break
return result
def delete_zip_file(self,args):
'''
@name 删除压缩包内文件
@param args['path'] 压缩包路径
@param args['filenames'] 文件名列表,数组格式
@return dict
'''
sfile = args.sfile
filenames = args.filenames
if not os.path.exists(sfile):
return public.returnMsg(False,'FILE_NOT_EXISTS')
with zipfile.ZipFile(sfile,'r') as zip_file:
with zipfile.ZipFile(sfile + '.tmp','w',zipfile.ZIP_DEFLATED) as new_zfile:
for item in zip_file.infolist():
filename = self.__get_zip_filename(item)
if filename in filenames:
continue
src_name = item.filename
item.filename = filename
new_zfile.writestr(item,zip_file.read(src_name))
shutil.move(sfile + '.tmp',sfile)
return public.returnMsg(True,'File deleted successfully')
def write_zip_file(self,args):
'''
@name 写入压缩包内文件
@param args['path'] 压缩包路径
@param args['filename'] 文件名
@param args['data'] 写入数据
@return dict
'''
sfile = args.sfile
filename = args.filename
data = args.data
if not os.path.exists(sfile):
return public.returnMsg(False,'FILE_NOT_EXISTS')
with zipfile.ZipFile(sfile,'r') as zip_file:
with zipfile.ZipFile(sfile + '.tmp','w',zipfile.ZIP_DEFLATED) as new_zfile:
for item in zip_file.infolist():
z_filename = self.__get_zip_filename(item)
if z_filename == filename:
continue
new_zfile.writestr(item,zip_file.read(item.filename))
new_zfile.writestr(filename, data=data, compress_type=zipfile.ZIP_DEFLATED)
shutil.move(sfile + '.tmp',sfile)
return public.returnMsg(True,'File written successfully')
def extract_byfiles(self,args):
"""
@name 解压部分文件
@param args['path'] 压缩包路径
@param args['extract_path'] 解压路径
@param args['filenames'] 文件名列表,数组格式
"""
zip_path = ''
if 'zip_path' in args: zip_path = args.zip_path
sfile = args.sfile
filenames = args.filenames
extract_path = args.extract_path
if not os.path.exists(sfile):
return public.returnMsg(False,'FILE_NOT_EXISTS')
if not os.path.exists(extract_path):
os.makedirs(extract_path,384)
tmp_path = '{}/tmp/{}'.format(public.get_soft_path(),public.md5(public.GetRandomString(32)))
if not os.path.exists(tmp_path):
os.makedirs(tmp_path,384)
with zipfile.ZipFile(sfile) as zip_file:
try:
m_list = {}
for item in zip_file.infolist():
filename = self.__get_zip_filename(item)
if filename in filenames:
spath = os.path.join(tmp_path,filename).strip('/')
if item.is_dir():
m_list[spath] = []
else:
if not 'other' in m_list:
m_list['other'] = []
dir_key = os.path.dirname(spath)
info = {'src':spath,'dst':'{}/{}'.format(extract_path,filename.strip('/'))}
if zip_path:
info['dst'] = '{}/{}'.format(extract_path,filename.replace(zip_path,'').strip('/'))
s_path = os.path.dirname(info['dst'])
if not os.path.exists(s_path): os.makedirs(s_path,384)
if dir_key in m_list:
m_list[dir_key].append(info)
else:
m_list['other'].append(info)
item.filename = filename
zip_file.extract(item,tmp_path)
for key in m_list:
try:
for info in m_list[key]:
if os.getenv('BT_PANEL'):
shutil.copyfile(info['src'],info['dst'])
else:
shutil.copyfile('/' + info['src'],'/' + info['dst'])
except:
pass
shutil.rmtree(tmp_path, True)
except:
return public.returnMsg(False,'Decompression failed,error:' + public.get_error_info())
return public.returnMsg(True,'The file was decompressed successfully')
def add_zip_file(self,args):
'''
@name 添加文件到压缩包
@param args['r_path'] 跟路径
@param args['filename'] 文件名
@param args['f_list'] 写入数据
@return dict
'''
sfile = args.sfile
r_path = args.r_path
f_list = args.f_list
if not os.path.exists(sfile):
return public.returnMsg(False,'FILE_NOT_EXISTS')
#追加原路径
src_list = {}
for fname in f_list:
if os.path.isdir(fname):
s_list = []
public.get_file_list(fname,s_list)
for f in s_list:
if os.path.isdir(f):
continue
src_file = '{}/{}{}'.format(r_path,os.path.basename(fname),f.replace(fname,''))
src_list[src_file] = f
else:
src_file = r_path + '/' + os.path.basename(fname)
src_list[src_file] = fname
tmp_path = sfile + '.tmp'
if os.path.exists(tmp_path):
os.remove(tmp_path)
with zipfile.ZipFile(sfile,'r') as zip_file:
with zipfile.ZipFile(tmp_path,'w',zipfile.ZIP_DEFLATED) as new_zfile:
try:
#过滤旧文件
for item in zip_file.namelist():
if item in src_list:
continue
new_zfile.writestr(item,zip_file.read(item))
#追加新文件
for src_file in src_list:
new_zfile.write(src_list[src_file],src_file)
except:
return public.returnMsg(False,'Failed add file,error:' + public.get_error_info())
shutil.move(tmp_path,sfile)
return public.returnMsg(True,'Compressed package file modified successfully')
# def __get_zip_filename(self,item):
# '''
# @name 获取压缩包文件名
# @param item 压缩包文件对象
# @return string
# '''
# path = item.filename
# try:
# path_name = path.decode('utf-8')
# except:
# path_name = path.encode('cp437').decode('gbk')
# path_name = path_name.encode('utf-8').decode('utf-8')
# return path_name
def __get_zip_filename(self,item):
'''
@name 获取压缩包文件名
@param item 压缩包文件对象
@return string
'''
filename = item.filename
try:
filename = item.filename.encode('cp437').decode('gbk')
except:pass
return filename