mirror of
https://github.com/aaPanel/aaPanel.git
synced 2026-08-17 21:25:47 +02:00
File manager add drag and drop upload folder
Add website list to show SSL certificate expiration time Optimization of other functions
This commit is contained in:
+15
-2
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
import sys
|
||||
import json
|
||||
@@ -1159,8 +1159,11 @@ def down(token=None,fname=None):
|
||||
"token":find['token'],
|
||||
"expire":public.format_date(times=find['expire'])
|
||||
}
|
||||
session['down'] = True
|
||||
return render_template('down.html',data = pdata)
|
||||
|
||||
if not find['password']:
|
||||
session['down'] = True
|
||||
session[token] = 1
|
||||
|
||||
if session[token] != 1:
|
||||
@@ -1277,7 +1280,17 @@ def get_pd():
|
||||
if tmp: tmp = int(tmp)
|
||||
|
||||
if ltd < 1:
|
||||
if tmp == -1:
|
||||
if ltd == -2:
|
||||
tmp3 = public.to_string([60, 115, 112, 97, 110, 32, 99, 108, 97, 115, 115, 61, 34, 98, 116, 108, 116, 100,
|
||||
45, 103, 114, 97, 121, 34, 62, 60, 115, 112, 97, 110, 32, 115, 116, 121, 108, 101,
|
||||
61, 34, 99, 111, 108, 111, 114, 58, 32, 35, 102, 99, 54, 100, 50, 54, 59, 102, 111,
|
||||
110, 116, 45, 119, 101, 105, 103, 104, 116, 58, 32, 98, 111, 108, 100, 59, 109, 97,
|
||||
114, 103, 105, 110, 45, 114, 105, 103, 104, 116, 58, 53, 112, 120, 34, 62, 24050, 36807,
|
||||
26399, 60, 47, 115, 112, 97, 110, 62, 60, 97, 32, 99, 108, 97, 115, 115, 61, 34, 98, 116,
|
||||
108, 105, 110, 107, 34, 32, 111, 110, 99, 108, 105, 99, 107, 61, 34, 98, 116, 46, 115, 111,
|
||||
102, 116, 46, 117, 112, 100, 97, 116, 97, 95, 108, 116, 100, 40, 41, 34, 62, 32493,
|
||||
36153, 60, 47, 97, 62, 60, 47, 115, 112, 97, 110, 62])
|
||||
elif tmp == -1:
|
||||
tmp3 = public.to_string([60, 115, 112, 97, 110, 32, 99, 108, 97, 115, 115, 61, 34, 98,
|
||||
116, 112, 114, 111, 45, 102, 114, 101, 101, 34, 32, 111, 110, 99, 108, 105, 99, 107,
|
||||
61, 34, 98, 116, 46, 115, 111, 102, 116, 46, 117, 112, 100, 97, 116, 97, 95, 99,
|
||||
|
||||
+252
-3
@@ -5787,10 +5787,8 @@ select[disabled]{
|
||||
}
|
||||
/* 取消按钮组 */
|
||||
.ace-clear-btn {
|
||||
padding: 8px 20px 15px;
|
||||
padding: 15px 20px;
|
||||
text-align: right;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.ace-clear-btn .btn-default:hover {
|
||||
@@ -6732,4 +6730,255 @@ select[disabled]{
|
||||
}
|
||||
.minText{
|
||||
white-space: nowrap;
|
||||
}
|
||||
.upload_tips_mask{
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 445px;
|
||||
border: 2px dashed #e0e0e0;
|
||||
text-align: center;
|
||||
}
|
||||
.upload_file_body{
|
||||
position: relative;
|
||||
}
|
||||
.upload_file_body.active{
|
||||
height: 445px;
|
||||
border: 2px dashed #e0e0e0;
|
||||
text-align: center;
|
||||
}
|
||||
.upload_tips_mask span,
|
||||
.upload_file_body.active span{
|
||||
font-size: 35px;
|
||||
color: #999;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
margin-top: -40px;
|
||||
}
|
||||
.dropUpLoadFile{
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
height: 410px;
|
||||
padding-top:0;
|
||||
}
|
||||
.dropUpLoadFile::-webkit-scrollbar {
|
||||
/*滚动条整体样式*/
|
||||
width : 15px; /*高宽分别对应横竖滚动条的尺寸*/
|
||||
height: 1px;
|
||||
}
|
||||
.dropUpLoadFile::-webkit-scrollbar-thumb {
|
||||
/*滚动条里面小方块*/
|
||||
border-radius: 0;
|
||||
box-shadow : inset 0 0 5px rgba(0, 0, 0, 0.2);
|
||||
background : #bbb;
|
||||
}
|
||||
.dropUpLoadFile::-webkit-scrollbar-track {
|
||||
/*滚动条里面轨道*/
|
||||
box-shadow : inset 0 0 5px rgba(0, 0, 0, 0.2);
|
||||
border-radius: 0;
|
||||
background : #ededed;
|
||||
}
|
||||
.dropUpLoadFile li{
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
border-bottom: 1px solid #ececec;
|
||||
position: relative;
|
||||
}
|
||||
.dropUpLoadFileHead{
|
||||
border-bottom: 1px solid #dedede;
|
||||
}
|
||||
.dropUpLoadFileHead li.fileTitle{
|
||||
border-color: #ccc;
|
||||
}
|
||||
.upload_btn_groud .file_upload_info{
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
padding-left: 5px;
|
||||
font-weight: 400;
|
||||
color: #3c763d;
|
||||
background-color: #dff0d8;
|
||||
border: 1px solid #d6e9c6;
|
||||
border-radius: 2px;
|
||||
position: relative;
|
||||
}
|
||||
.upload_btn_groud .file_upload_info .ico-tips-close{
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
background: #90bb81;
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 50%;
|
||||
margin-top: -11px;
|
||||
cursor: pointer;
|
||||
transition: all 500ms;
|
||||
}
|
||||
.upload_btn_groud .file_upload_info .ico-tips-close:hover{
|
||||
background: #658859;
|
||||
}
|
||||
|
||||
|
||||
.upload_btn_groud .file_upload_info .ico-tips-close:after{
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
.upload_btn_groud .file_upload_info .ico-tips-close:before{
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
.upload_btn_groud .file_upload_info .ico-tips-close:after,
|
||||
.upload_btn_groud .file_upload_info .ico-tips-close:before{
|
||||
content:'';
|
||||
display: inline-block;
|
||||
height: 12px;
|
||||
width: 2px;
|
||||
background:#ececec;
|
||||
border-radius: 5px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
margin-top: -6px;
|
||||
margin-left: -1px;
|
||||
}
|
||||
.upload_btn_groud .file_upload_info i{
|
||||
font-style: initial;
|
||||
}
|
||||
.upload_btn_groud .file_upload_info span{
|
||||
margin-right: 10px;
|
||||
font-size: 13px;
|
||||
display: inline-block;
|
||||
height: 38px;
|
||||
line-height: 38px;
|
||||
margin-right: 0;
|
||||
padding-left: 10px;
|
||||
}
|
||||
.dropUpLoadFile li .fileItem{
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
}
|
||||
.dropUpLoadFile li .fileLoading{
|
||||
content: '';
|
||||
width: 0%;
|
||||
height: 40px;
|
||||
background: #6fb9d621;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
transition: width 100ms;
|
||||
z-index: 998;
|
||||
}
|
||||
.dropUpLoadFile li:hover{
|
||||
cursor: pointer;
|
||||
}
|
||||
.upload_btn_groud .dropdown-menu{
|
||||
width: 100%;
|
||||
min-width: 120%;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.upload_btn_groud .btn-group:hover .dropdown-menu{
|
||||
display: block;
|
||||
}
|
||||
.dropdown-menu:before{
|
||||
content: '';
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
height: 5px;
|
||||
}
|
||||
.upload_btn_groud{
|
||||
margin-bottom: 5px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
}
|
||||
.upload_btn_groud .dropdown-toggle{
|
||||
border-left-color: #3f51b5;
|
||||
}
|
||||
.upload_btn_groud .btn-primary{
|
||||
background-color: #4592f0;
|
||||
border-color: #367fa9;
|
||||
}
|
||||
.dropUpLoadFileHead li.fileTitle span{
|
||||
color: #666;
|
||||
font-size: 13px;
|
||||
display: inline-block;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
margin-right: 0;
|
||||
padding-left: 10px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.dropUpLoadFileHead li.fileTitle span:nth-child(1){
|
||||
width: 50%;
|
||||
padding-left: 15px;
|
||||
}
|
||||
.dropUpLoadFileHead li.fileTitle span:nth-child(2){
|
||||
width: 25%;
|
||||
}
|
||||
.dropUpLoadFileHead li.fileTitle span:nth-child(3){
|
||||
width: 25%;
|
||||
}
|
||||
.dropUpLoadFile .fileItem > span{
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
vertical-align: top;
|
||||
padding-left: 10px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
display: inline-block;
|
||||
}
|
||||
.dropUpLoadFile li .filename{
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
width: 50%;
|
||||
padding-left: 15px;
|
||||
}
|
||||
.dropUpLoadFile li .filename .ico {
|
||||
height: 27px;
|
||||
line-height: 27px;
|
||||
background-size: 27px;
|
||||
width: 25px;
|
||||
vertical-align: middle;
|
||||
margin-right: 10px;
|
||||
float: initial;
|
||||
}
|
||||
.dropUpLoadFile li .filesize{
|
||||
color: #999;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
width: 25%;
|
||||
}
|
||||
.dropUpLoadFile li .fileStatus{
|
||||
width: 25%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.dropUpLoadFile li em{
|
||||
font-style: normal;
|
||||
color: #06F;
|
||||
float: right;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.upload_success{
|
||||
color:#20a53a !important;
|
||||
}
|
||||
.upload_error{
|
||||
color:#F56C6C !important;
|
||||
}
|
||||
.upload_primary{
|
||||
color:#409EFF !important;
|
||||
}
|
||||
.upload_warning{
|
||||
color:#409EFF !important;
|
||||
}
|
||||
@@ -303,7 +303,7 @@ $.get('/ajax?action=GetCpuIo&start='+b+'&end='+e,function(rdata){
|
||||
for(var i = 0; i < rdata.length; i++){
|
||||
xData.push(rdata[i].addtime);
|
||||
//yData.push(rdata[i].pro);
|
||||
zData.push(rdata[i].mem);
|
||||
zData.push(rdata[i].mem.toFixed(2));
|
||||
}
|
||||
option = {
|
||||
tooltip: {
|
||||
|
||||
+458
-2
@@ -1,3 +1,460 @@
|
||||
var fileDrop = {
|
||||
startTime: 0,
|
||||
endTime:0,
|
||||
uploadLength:0, //上传数量
|
||||
splitSize: 1024 * 1024 * 2, //文件上传分片大小
|
||||
filesList:[], // 文件列表数组
|
||||
errorLength:0, //上传失败文件数量
|
||||
isUpload:true, //上传状态,是否可以上传
|
||||
uploadSuspend:[], //上传暂停参数
|
||||
isUploadNumber:800,//限制单次上传数量
|
||||
uploadAllSize:0, // 上传文件总大小
|
||||
uploadedSize:0, // 已上传文件大小
|
||||
topUploadedSize:0, // 上一次文件上传大小
|
||||
uploadExpectTime:0, // 预计上传时间
|
||||
initTimer:0, // 初始化计时
|
||||
speedInterval:null, //平局速度定时器
|
||||
timerSpeed:0, //速度
|
||||
isLayuiDrop:false, //是否是小窗口拖拽
|
||||
uploading:false,
|
||||
init:function(){
|
||||
if($('#mask_layer').length == 0) {
|
||||
window.UploadFiles = function(){ fileDrop.dialog_view()};
|
||||
$("body").append($('<div class="mask_layer" id="mask_layer" style="position:fixed;top:0;left:0;right:0;bottom:0; background:rgba(255,255,255,0.6);border:3px #ccc dashed;z-index:99999999;display:none;color:#999;font-size:40px;text-align:center;overflow:hidden;"><span style="position: absolute;top: 50%;left: 50%;margin-left: -200px;margin-top: -40px;">Upload files to the current directory</span></div>'));
|
||||
this.event_relation(document.querySelector('#container'),document,document.querySelector('#mask_layer'));
|
||||
}
|
||||
},
|
||||
// 事件关联 (进入,离开,放下)
|
||||
event_relation:function(enter,leave,drop){
|
||||
var that = this,obj = Object.keys(arguments);
|
||||
for(var item in arguments){
|
||||
if(typeof arguments[item] == "object" && typeof arguments[item].nodeType != 'undefined'){
|
||||
arguments[item] = {
|
||||
el:arguments[item],
|
||||
callback:null
|
||||
}
|
||||
}
|
||||
}
|
||||
leave.el.addEventListener("dragleave",(leave.callback != null)?leave.callback:function(e){
|
||||
e.preventDefault();
|
||||
if(e.x == 0 && e.y == 0) $('#mask_layer').hide();
|
||||
},false);
|
||||
enter.el.addEventListener("dragenter", (enter.callback != null)?enter.callback:function(e){
|
||||
if(e.dataTransfer.items[0].kind == 'string') return false
|
||||
$('#mask_layer').show();
|
||||
that.isLayuiDrop = false;
|
||||
e.preventDefault();
|
||||
},false);
|
||||
drop.el.addEventListener("dragover",function(e){ e.preventDefault() }, false);
|
||||
drop.el.addEventListener("drop",(enter.callback != null)?drop.callback:that.ev_drop, false);
|
||||
},
|
||||
// 事件触发
|
||||
ev_drop:function(e){
|
||||
e.preventDefault();
|
||||
if(fileDrop.uploading){
|
||||
layer.msg('Uploading, please wait...');
|
||||
return false;
|
||||
}
|
||||
var items = e.dataTransfer.items,time,num = 0;
|
||||
loadT = layer.msg('Getting upload file information, please wait...',{icon:16,time:0,shade:.3});
|
||||
fileDrop.isUpload = true;
|
||||
if(items && items.length && items[0].webkitGetAsEntry != null) {
|
||||
if(items[0].kind != 'file') return false;
|
||||
}
|
||||
if(fileDrop.filesList == null) fileDrop.filesList = []
|
||||
for(var i = fileDrop.filesList.length -1; i >= 0 ; i--){
|
||||
if(fileDrop.filesList[i].is_upload) fileDrop.filesList.splice(-i,1)
|
||||
}
|
||||
$('#mask_layer').hide();
|
||||
function update_sync(s){
|
||||
s.getFilesAndDirectories().then(function(subFilesAndDirs) {
|
||||
return iterateFilesAndDirs(subFilesAndDirs, s.path);
|
||||
});
|
||||
}
|
||||
var iterateFilesAndDirs = function(filesAndDirs, path) {
|
||||
if(!fileDrop.isUpload) return false
|
||||
for (var i = 0; i < filesAndDirs.length; i++) {
|
||||
if (typeof(filesAndDirs[i].getFilesAndDirectories) == 'function') {
|
||||
update_sync(filesAndDirs[i])
|
||||
// var path = filesAndDirs[i].path;
|
||||
// filesAndDirs[i].getFilesAndDirectories().then(function(subFilesAndDirs) {
|
||||
// iterateFilesAndDirs(subFilesAndDirs, path);
|
||||
// });
|
||||
} else {
|
||||
if(num > fileDrop.isUploadNumber){
|
||||
fileDrop.isUpload = false;
|
||||
layer.msg(' '+ fileDrop.isUploadNumber +'file. Unable to upload, please upload after compression!',{icon:2,area:'405px'});
|
||||
clearTimeout(time);
|
||||
return false;
|
||||
}
|
||||
if(/^\.\w*/.test(filesAndDirs[i].name) ||/\/\.\w*/g.test(path)) continue; //排查隐藏文件目录和文件
|
||||
fileDrop.filesList.push({
|
||||
file:filesAndDirs[i],
|
||||
path:bt.get_file_path(path +'/'+ filesAndDirs[i].name).replace('//','/'),
|
||||
name:filesAndDirs[i].name.replace('//','/'),
|
||||
icon:GetExtName(filesAndDirs[i].name),
|
||||
size:fileDrop.to_size(filesAndDirs[i].size),
|
||||
upload:0, //上传状态,未上传:0、上传中:1,已上传:2,上传失败:-1
|
||||
is_upload:false
|
||||
});
|
||||
fileDrop.uploadAllSize += filesAndDirs[i].size
|
||||
clearTimeout(time);
|
||||
time = setTimeout(function(){
|
||||
layer.close(loadT);
|
||||
fileDrop.dialog_view();
|
||||
},100);
|
||||
num ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if('getFilesAndDirectories' in e.dataTransfer){
|
||||
e.dataTransfer.getFilesAndDirectories().then(function(filesAndDirs) {
|
||||
return iterateFilesAndDirs(filesAndDirs, '/');
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
// 获取上传速度
|
||||
get_timer_speed:function(speed){
|
||||
var that = this,num = 0;
|
||||
if(speed == undefined) speed = 1000
|
||||
that.speedInterval = setInterval(function(){
|
||||
if(that.uploadedSize - that.topUploadedSize === 0){
|
||||
that.timerSpeed = that.timerSpeed == 0 ? 0:(parseInt(that.timerSpeed / num));
|
||||
num += 1;
|
||||
}else{
|
||||
that.timerSpeed = that.uploadedSize - that.topUploadedSize;
|
||||
num = 0;
|
||||
}
|
||||
that.topUploadedSize = that.uploadedSize;
|
||||
$('.file_upload_info .uploadSpeed').text(that.to_size(isNaN(that.timerSpeed)?0:that.timerSpeed)+'/s');
|
||||
var estimateTime = that.time(parseInt(((that.uploadAllSize - that.uploadedSize) / that.timerSpeed) * 1000))
|
||||
if(!isNaN(that.timerSpeed)) $('.file_upload_info .uploadEstimate').text(estimateTime.indexOf('NaN') == -1?estimateTime:'0sec');
|
||||
},speed);
|
||||
},
|
||||
// 上传视图
|
||||
dialog_view:function(config){
|
||||
var that = this,html = '';
|
||||
if(!$('.file_dir_uploads').length > 0){
|
||||
if(that.filesList == null) that.filesList = []
|
||||
for(var i =0; i<that.filesList.length; i++){
|
||||
var item = that.filesList[i];
|
||||
html +='<li><div class="fileItem"><span class="filename" title="File path:'+ (item.path + '/' + item.name).replace('//','/') +' File type:'+ item.file.type +' File size:'+ item.size +'"><i class="ico ico-'+ item.icon + '"></i>'+ (item.path + '/' + item.name).replace('//','/') +'</span><span class="filesize">'+ item.size +'</span><span class="fileStatus">'+ that.is_upload_status(item.upload) +'</span></div><div class="fileLoading"></div></li>';
|
||||
}
|
||||
var is_show = that.filesList.length > 11;
|
||||
layer.open({
|
||||
type: 1,
|
||||
closeBtn: 1,
|
||||
maxmin:true,
|
||||
area: ['640px','609px'],
|
||||
btn:['Start upload','Cancel upload'],
|
||||
title: 'Upload files to【'+ bt.get_cookie('Path') +'】--- Support breakpoint renewal',
|
||||
skin:'file_dir_uploads',
|
||||
content:'<div style="padding:15px 15px 10px 15px;"><div class="upload_btn_groud"><div class="btn-group"><button type="button" class="btn btn-primary btn-sm upload_file_btn">Upload file</button><button type="button" class="btn btn-primary btn-sm dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button><ul class="dropdown-menu"><li><a href="#" data-type="file">Upload file</a></li><li><a href="#" data-type="dir">Upload directory</a></li></ul></div><div class="file_upload_info" style="display:none;"><span>Total process <i class="uploadProgress"></i>, Uploading <i class="uploadNumber"></i>,</span><span style="display:none">Upload failed <i class="uploadError"></i></span><span>Upload speed <i class="uploadSpeed">Getting</i>,</span><span>Expect time <i class="uploadEstimate">Getting</i></span><i></i></div></div><div class="upload_file_body '+ (html==''?'active':'') +'">'+ (html!=''?('<ul class="dropUpLoadFileHead" style="padding-right:'+ (is_show?'15':'0') +'px"><li class="fileTitle"><span class="filename">File name</span><span class="filesize">File size</span><span class="fileStatus">File status</span></li></ul><ul class="dropUpLoadFile list-list">'+ html +'</ul>'):'<span>Please drag the file here</span>') +'</div></div>',
|
||||
success:function(){
|
||||
$('#mask_layer').hide();
|
||||
$('.file_dir_uploads .layui-layer-max').hide();
|
||||
$('.upload_btn_groud .upload_file_btn').click(function(){$('.upload_btn_groud .dropdown-menu [data-type=file]').click()});
|
||||
$('.upload_btn_groud .dropdown-menu a').click(function(){
|
||||
var type = $(this).attr('data-type');
|
||||
$('<input type="file" multiple="true" autocomplete="off" '+ (type == 'dir'?'webkitdirectory=""':'') +' />').change(function(e){
|
||||
var files = e.target.files,arry = [];
|
||||
for(var i=0;i<files.length;i++){
|
||||
if(/^\.\w*/.test(files[i].name) || /\/\.\w*/g.test(files[i].webkitRelativePath)) continue;
|
||||
var config = {
|
||||
file:files[i],
|
||||
path: bt.get_file_path('/' + files[i].webkitRelativePath).replace('//','/') ,
|
||||
icon:GetExtName(files[i].name),
|
||||
name:files[i].name.replace('//','/'),
|
||||
size:that.to_size(files[i].size),
|
||||
upload:0, //上传状态,未上传:0、上传中:1,已上传:2,上传失败:-1
|
||||
is_upload:true
|
||||
}
|
||||
that.filesList.push(config);
|
||||
fileDrop.uploadAllSize += files[i].size
|
||||
}
|
||||
that.dialog_view(that.filesList);
|
||||
}).click();
|
||||
});
|
||||
var el = '';
|
||||
that.event_relation({
|
||||
el:$('.upload_file_body')[0],
|
||||
callback:function(e){
|
||||
if($(this).hasClass('active')){
|
||||
$(this).css('borderColor','#4592f0').find('span').css('color','#4592f0');
|
||||
}
|
||||
}
|
||||
},{
|
||||
el:$('.upload_file_body')[0],
|
||||
callback:function(e){
|
||||
if($(this).hasClass('active')){
|
||||
$(this).removeAttr('style').find('span').removeAttr('style');
|
||||
}
|
||||
}
|
||||
},{
|
||||
el:$('.upload_file_body')[0],
|
||||
callback:function (e) {
|
||||
var active = $('.upload_file_body');
|
||||
if(active.hasClass('active')){
|
||||
active.removeAttr('style').find('span').removeAttr('style');
|
||||
}
|
||||
that.ev_drop(e);
|
||||
that.isLayuiDrop = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
yes:function(index, layero){
|
||||
if(!that.uploading){
|
||||
if(that.filesList.length == 0){
|
||||
layer.msg('Please select upload file',{icon:0});
|
||||
return false;
|
||||
}
|
||||
$('.layui-layer-btn0').css({'cursor':'no-drop','background':'#5c9e69'}).attr('data-upload','true').text('Uploading');
|
||||
that.upload_file();
|
||||
that.initTimer = new Date();
|
||||
that.uploading = true;
|
||||
that.get_timer_speed();
|
||||
}
|
||||
},
|
||||
btn2:function (index, layero){
|
||||
if(that.uploading){
|
||||
layer.confirm('Do you want to cancel the upload of files? It need to delete the uploaded files manually. Continue?',{title:'Cancel file upload',icon:0},function(indexs){
|
||||
layer.close(index);
|
||||
layer.close(indexs);
|
||||
});
|
||||
return false;
|
||||
}else{
|
||||
layer.close(index);
|
||||
}
|
||||
},
|
||||
cancel:function(index, layero){
|
||||
if(that.uploading){
|
||||
layer.confirm('Do you want to cancel the upload of files? It need to delete the uploaded files manually. Continue?',{title:'Cancel file upload',icon:0},function(indexs){
|
||||
layer.close(index);
|
||||
layer.close(indexs);
|
||||
});
|
||||
return false;
|
||||
}else{
|
||||
layer.close(index);
|
||||
}
|
||||
},
|
||||
end:function (){
|
||||
GetFiles(bt.get_cookie('Path'));
|
||||
that.clear_drop_stauts(true);
|
||||
},
|
||||
min:function(){
|
||||
$('.file_dir_uploads .layui-layer-max').show();
|
||||
$('#layui-layer-shade'+$('.file_dir_uploads').attr('times')).fadeOut();
|
||||
},
|
||||
restore:function(){
|
||||
$('.file_dir_uploads .layui-layer-max').hide();
|
||||
$('#layui-layer-shade'+$('.file_dir_uploads').attr('times')).fadeIn();
|
||||
}
|
||||
});
|
||||
}else{
|
||||
if(config == undefined && !that.isLayuiDrop) return false;
|
||||
if(that.isLayuiDrop) config = that.filesList;
|
||||
$('.upload_file_body').html('<ul class="dropUpLoadFileHead" style="padding-right:'+ (config.length>11?'15':'0') +'px"><li class="fileTitle"><span class="filename">File name</span><span class="filesize">File size</span><span class="fileStatus">Upload status</span></li></ul><ul class="dropUpLoadFile list-list"></ul>').removeClass('active');
|
||||
if(Array.isArray(config)){
|
||||
for(var i =0; i<config.length; i++){
|
||||
var item = config[i];
|
||||
html +='<li><div class="fileItem"><span class="filename" title="File path:'+ item.path + '/' + item.name +' File type:'+ item.file.type +' File size:'+ item.size +'"><i class="ico ico-'+ item.icon + '"></i>'+ (item.path + '/' + item.name).replace('//','/') +'</span><span class="filesize">'+ item.size +'</span><span class="fileStatus">'+ that.is_upload_status(item.upload) +'</span></div><div class="fileLoading"></div></li>';
|
||||
}
|
||||
$('.dropUpLoadFile').append(html);
|
||||
}else{
|
||||
$('.dropUpLoadFile').append('<li><div class="fileItem"><span class="filename" title="File path:'+ config.path + '/' + config.name +' File type:'+ config.type +' File size:'+ config.size +'"><i class="ico ico-'+ config.icon + '"></i>'+ config.name +'</span><span class="filesize">'+ config.size +'</span><span class="fileStatus">'+ that.is_upload_status(config.upload) +'</span></div><div class="fileLoading"></div></li>');
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
// 上传单文件状态
|
||||
is_upload_status:function(status,val){
|
||||
if(val === undefined) val = ''
|
||||
switch(status){
|
||||
case -1:
|
||||
return '<span class="upload_info upload_error" title="Upload failed'+ (val != ''?','+val:'') +'">Upload failed'+ (val != ''?','+val:'') +'</span>';
|
||||
break;
|
||||
case 0:
|
||||
return '<span class="upload_info upload_primary">Waiting to upload</span>';
|
||||
break;
|
||||
case 1:
|
||||
return '<span class="upload_info upload_success">Uploaded</span>';
|
||||
break;
|
||||
case 2:
|
||||
return '<span class="upload_info upload_warning">Uploading'+ val+'</span>';
|
||||
break;
|
||||
case 3:
|
||||
return '<span class="upload_info upload_success">Paused</span>';
|
||||
break;
|
||||
}
|
||||
},
|
||||
// 设置上传实时反馈视图
|
||||
set_upload_view:function(index,config){
|
||||
var item = $('.dropUpLoadFile li:eq('+ index +')'),that = this;
|
||||
var file_info = $('.file_upload_info');
|
||||
if($('.file_upload_info .uploadProgress').length == 0){
|
||||
$('.file_upload_info').html('<span>Total progress <i class="Upload Progress"></i>, Uploading <i class="uploadNumber"></i>,</span><span style="display:none">Upload failed <i class="uploadError"></i></span><span>Upload speed <i class="uploadSpeed">Getting</i>,</span><span>Expect time <i class="uploadEstimate">Getting</i></span><i></i>');
|
||||
}
|
||||
file_info.show().prev().hide().parent().css('paddingRight',0);
|
||||
if(that.errorLength > 0) file_info.find('.uploadError').text('('+ that.errorLength +'file)').parent().show();
|
||||
file_info.find('.uploadNumber').html('('+ that.uploadLength +'/'+ that.filesList.length +')');
|
||||
file_info.find('.uploadProgress').html( ((that.uploadedSize / that.uploadAllSize) * 100).toFixed(2) +'%');
|
||||
if(config.upload === 1 || config.upload === -1){
|
||||
that.filesList[index].is_upload = true;
|
||||
that.uploadLength += 1;
|
||||
item.find('.fileLoading').css({'width':'100%','opacity':'.5','background': config.upload == -1?'#ffadad':'#20a53a21'});
|
||||
item.find('.filesize').text(config.size);
|
||||
item.find('.fileStatus').html(that.is_upload_status(config.upload,(config.upload === 1?('(耗时:'+ that.diff_time(that.startTime,that.endTime) +')'):config.errorMsg)));
|
||||
item.find('.fileLoading').fadeOut(500,function(){
|
||||
$(this).remove();
|
||||
var uploadHeight = $('.dropUpLoadFile');
|
||||
if(uploadHeight.length == 0) return false;
|
||||
if(uploadHeight[0].scrollHeight > uploadHeight.height()){
|
||||
uploadHeight.scrollTop(uploadHeight.scrollTop()+40);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
item.find('.fileLoading').css('width',config.percent);
|
||||
item.find('.filesize').text(config.upload_size +'/'+ config.size);
|
||||
item.find('.fileStatus').html(that.is_upload_status(config.upload,'('+ config.percent +')'));
|
||||
}
|
||||
},
|
||||
// 清除上传状态
|
||||
clear_drop_stauts:function(status){
|
||||
var time = new Date(),that = this;
|
||||
if(!status){
|
||||
try {
|
||||
var s_peed = fileDrop.to_size(fileDrop.uploadedSize / ((time.getTime() - fileDrop.initTimer.getTime()) / 1000))
|
||||
$('.file_upload_info').html('<span>Uploaded : '+ this.uploadLength +' files, '+ (this.errorLength>0?('Upload failed '+ this.errorLength +' files, '):'') +'Time consuming : '+ this.diff_time(this.initTimer,time) + ', average speed : '+ s_peed +'/s</span>').append($('<i class="ico-tips-close"></i>').click(function(){
|
||||
$('.file_upload_info').hide().prev().show();
|
||||
}));
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
$('.layui-layer-btn0').removeAttr('style data-upload').text('Start upload');
|
||||
$.extend(fileDrop,{
|
||||
startTime: 0,
|
||||
endTime:0,
|
||||
uploadLength:0, //上传数量
|
||||
splitSize: 1024 * 1024 * 2, //文件上传分片大小
|
||||
filesList:[], // 文件列表数组
|
||||
errorLength:0, //上传失败文件数量
|
||||
isUpload:false, //上传状态,是否可以上传
|
||||
isUploadNumber:800,//限制单次上传数量
|
||||
uploadAllSize:0, // 上传文件总大小
|
||||
uploadedSize:0, // 已上传文件大小
|
||||
topUploadedSize:0, // 上一次文件上传大小
|
||||
uploadExpectTime:0, // 预计上传时间
|
||||
initTimer:0, // 初始化计时
|
||||
speedInterval:null, //平局速度定时器
|
||||
timerSpeed:0, //速度
|
||||
uploading:false
|
||||
});
|
||||
clearInterval(that.speedInterval);
|
||||
},
|
||||
// 上传文件,文件开始字段,文件编号
|
||||
upload_file:function(fileStart,index){
|
||||
if(fileStart == undefined && this.uploadSuspend.length == 0) fileStart = 0,index = 0;
|
||||
if(this.filesList.length === index){
|
||||
clearInterval(this.speedInterval);
|
||||
this.clear_drop_stauts();
|
||||
GetFiles(bt.get_cookie('Path'));
|
||||
return false;
|
||||
}
|
||||
var that = this;
|
||||
var item = this.filesList[index],fileEnd = '';
|
||||
if(item == undefined) return false;
|
||||
fileEnd = Math.min(item.file.size, fileStart + this.splitSize),
|
||||
form = new FormData();
|
||||
if(fileStart == 0){
|
||||
that.startTime = new Date();
|
||||
item = $.extend(item,{percent:'0%',upload:2,upload_size:'0B'});
|
||||
}
|
||||
form.append("f_path", bt.get_cookie('Path') + item.path);
|
||||
form.append("f_name", item.name);
|
||||
form.append("f_size", item.file.size);
|
||||
form.append("f_start", fileStart);
|
||||
form.append("blob", item.file.slice(fileStart, fileEnd));
|
||||
that.set_upload_view(index,item);
|
||||
$.ajax({
|
||||
url:'/files?action=upload',
|
||||
type: "POST",
|
||||
data: form,
|
||||
async: true,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success:function(data){
|
||||
if(typeof(data) === "number"){
|
||||
that.set_upload_view(index,$.extend(item,{percent:(((data / item.file.size)* 100).toFixed(2) +'%'),upload:2,upload_size:that.to_size(data)}));
|
||||
if(fileEnd != data){
|
||||
that.uploadedSize += data;
|
||||
}else{
|
||||
that.uploadedSize += parseInt(fileEnd - fileStart);
|
||||
}
|
||||
that.upload_file(data,index);
|
||||
}else{
|
||||
if(data.status){
|
||||
that.endTime = new Date();
|
||||
that.uploadedSize += parseInt(fileEnd - fileStart);
|
||||
that.set_upload_view(index,$.extend(item,{upload:1,upload_size:item.size}));
|
||||
that.upload_file(0,index += 1);
|
||||
}else{
|
||||
that.set_upload_view(index,$.extend(item,{upload:-1,errorMsg:data.msg}));
|
||||
that.errorLength ++;
|
||||
}
|
||||
}
|
||||
},
|
||||
error:function(e){
|
||||
if(that.filesList[index].req_error === undefined) that.filesList[index].req_error = 1
|
||||
if(that.filesList[index].req_error > 2){
|
||||
that.set_upload_view(index,$.extend(that.filesList[index],{upload:-1,errorMsg:e.statusText == 'error'?'Network interruption':e.statusText }));
|
||||
that.errorLength ++;
|
||||
that.upload_file(fileStart,index += 1)
|
||||
return false;
|
||||
}
|
||||
that.filesList[index].req_error += 1;
|
||||
that.upload_file(fileStart,index)
|
||||
}
|
||||
});
|
||||
},
|
||||
time:function(date){
|
||||
var hours = Math.floor(date / (60 * 60 * 1000));
|
||||
var minutes = Math.floor(date / (60 * 1000));
|
||||
var seconds = parseInt((date % (60 * 1000)) / 1000);
|
||||
var result = seconds + ' sec';
|
||||
if(minutes > 0) {
|
||||
result = minutes + " min" + seconds + ' sec';
|
||||
}
|
||||
if(hours > 0){
|
||||
result = hours + ' hour' + Math.floor((date - (hours * (60 * 60 * 1000))) / (60 * 1000)) + " min";
|
||||
}
|
||||
return result
|
||||
},
|
||||
diff_time: function (start_date, end_date) {
|
||||
var diff = end_date.getTime() - start_date.getTime();
|
||||
var minutes = Math.floor(diff / (60 * 1000));
|
||||
var leave3 = diff % (60 * 1000);
|
||||
var seconds = leave3 / 1000
|
||||
var result = seconds.toFixed(minutes > 0?0:2) + ' sec';
|
||||
if (minutes > 0) {
|
||||
result = minutes + "min" + seconds.toFixed(0) + ' sec'
|
||||
}
|
||||
return result
|
||||
},
|
||||
|
||||
to_size: function (a) {
|
||||
var d = [" B", " KB", " MB", " GB", " TB", " PB"];
|
||||
var e = 1024;
|
||||
for (var b = 0; b < d.length; b += 1) {
|
||||
if (a < e) {
|
||||
var num = (b === 0 ? a : a.toFixed(2)) + d[b];
|
||||
return (!isNaN((b === 0 ? a : a.toFixed(2))) && typeof num != 'undefined')?num:'0B';
|
||||
}
|
||||
a /= e
|
||||
}
|
||||
}
|
||||
}
|
||||
function IsDiskWidth() {
|
||||
var comlistWidth = $("#comlist").width();
|
||||
var bodyWidth = $(".file-box").width();
|
||||
@@ -354,8 +811,6 @@ function get_path_size(path) {
|
||||
}, function (rdata) {
|
||||
layer.close(loadT);
|
||||
var myclass = '.' + rdata.path.replace(/[^\w]/g, '-');
|
||||
console.log(myclass)
|
||||
console.log($(myclass).text())
|
||||
$(myclass).text(ToSize(rdata.size));
|
||||
});
|
||||
}
|
||||
@@ -620,6 +1075,7 @@ function GetFiles(Path, sort) {
|
||||
$("#tipTools").width($("#fileCon")[0].clientWidth - 30);
|
||||
}
|
||||
$("#DirPathPlace input").val(rdata.PATH);
|
||||
fileDrop.init();
|
||||
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">\
|
||||
' + lan.files.new + ' <span class="caret"></span>\
|
||||
|
||||
@@ -145,7 +145,7 @@ var index = {
|
||||
crs += 'CPU-' + i + ": " + d[2][i] + '%' + (n1 % 2 == 0?'</br>':' | ');
|
||||
|
||||
}
|
||||
layer.tips(d[3] + "</br>" + d[5] + " CPU, " + d[4] + " Core, " + d[4]+" Thread</br>"+ crs, _this.find('.cicle'), { time: 0, tips: [1, '#999'] });
|
||||
layer.tips(d[3] + "</br>" + d[5] + " CPU, " + d[4] + " Core, " + d[4]+" Thread</br>"+ crs, _this, { time: 0, tips: [1, '#999'] });
|
||||
}, function () {
|
||||
layer.closeAll('tips');
|
||||
});
|
||||
@@ -164,7 +164,8 @@ var index = {
|
||||
$(this).find(".mem-re-min").show();
|
||||
}
|
||||
else {
|
||||
$(this).find(".mem-re-min").hide();
|
||||
return false;
|
||||
//$(this).find(".mem-re-min").hide();
|
||||
}
|
||||
$(this).removeClass("shine_green");
|
||||
$(this).find(".occupy").css({ "color": "#20a53a" });
|
||||
@@ -172,6 +173,7 @@ var index = {
|
||||
$(this).next().show();
|
||||
//$(this).next().html(bt.get_cookie("mem-before"));
|
||||
}).click(function () {
|
||||
if (($(this).hasClass("mem-action"))) return false;
|
||||
var _this = $(this);
|
||||
bt.show_confirm(lan.index.mem_release_sure, '<font style="color:red;">'+lan.index.mem_release_warn+'</font>', function () {
|
||||
if (!(_this.hasClass("mem-action"))) {
|
||||
@@ -223,17 +225,20 @@ var index = {
|
||||
}, 1500)
|
||||
},
|
||||
get_data_info: function (callback) {
|
||||
|
||||
var _this = $(this);
|
||||
bt.system.get_net(function (net) {
|
||||
|
||||
var pub_arr = [{ val: 100, color: '#dd2f00' }, { val: 90, color: '#ff9900' }, { val: 70, color: '#20a53a' }, { val: 30, color: '#20a53a' }];
|
||||
var load_arr = [{ title: lan.index.run_block, val: 100, color: '#dd2f00' }, { title: lan.index.run_slow, val: 90, color: '#ff9900' }, { title: lan.index.run_normal, val: 70, color: '#20a53a' }, { title: lan.index.run_fluent, val: 30, color: '#20a53a' }];
|
||||
var _cpubox = $('.cpubox'), _membox = $('.membox'), _loadbox = $('.loadbox')
|
||||
var _cpubox = $('.cpubox'), _membox = $('.membox'), _loadbox = $('.loadbox'), _diskbox = $('.diskbox')
|
||||
|
||||
index.set_val(_cpubox, { usage: net.cpu[0], title: net.cpu[1]+' '+lan.index.cpu_core, items: pub_arr })
|
||||
index.set_val(_membox, { usage: (net.mem.memRealUsed * 100 / net.mem.memTotal).toFixed(1), items: pub_arr, title: net.mem.memRealUsed + '/' + net.mem.memTotal + '(MB)' })
|
||||
bt.set_cookie('memSize', net.mem.memTotal)
|
||||
|
||||
for (var i = 0; i < _diskbox.length; i++) {
|
||||
index.set_val(_diskbox.eq(i), { usage: net.disk[i].size[3].split('%')[0], title: net.disk[i].size[1]+'/'+net.disk[0].size[0], items: pub_arr })
|
||||
}
|
||||
|
||||
var _lval = Math.round((net.load.one / net.load.max) * 100);
|
||||
if (_lval > 100) _lval = 100;
|
||||
index.set_val(_loadbox, { usage: _lval, items: load_arr })
|
||||
@@ -335,14 +340,13 @@ var index = {
|
||||
html += '<h4 class="c9 f15">' + item.title + '</h4>';
|
||||
html += '</li>';
|
||||
var _li = $(html);
|
||||
|
||||
if (item.masks) {
|
||||
var mask = '';
|
||||
for (var j = 0; j < item.masks.length; j++) mask += item.masks[j].title + ': ' + item.masks[j].value + "<br>";
|
||||
_li.data('mask', mask);
|
||||
_li.hover(function () {
|
||||
_li.find('.cicle').hover(function () {
|
||||
var _this = $(this);
|
||||
layer.tips(_this.data('mask'), _this.find('.cicle'), { time: 0, tips: [1, '#999'] });
|
||||
layer.tips(_this.parent().data('mask'), _this, { time: 0, tips: [1, '#999'] });
|
||||
}, function () {
|
||||
layer.closeAll('tips');
|
||||
})
|
||||
|
||||
@@ -0,0 +1,324 @@
|
||||
/**********************************
|
||||
Directory Upload Proposal Polyfill
|
||||
Author: Ali Alabbas (Microsoft)
|
||||
**********************************/
|
||||
(function() {
|
||||
// Do not proceed with the polyfill if Directory interface is already natively available,
|
||||
// or if webkitdirectory is not supported (i.e. not Chrome, since the polyfill only works in Chrome)
|
||||
if (window.Directory || !('webkitdirectory' in document.createElement('input') && 'webkitGetAsEntry' in DataTransferItem.prototype)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var allowdirsAttr = 'allowdirs',
|
||||
getFilesMethod = 'getFilesAndDirectories',
|
||||
isSupportedProp = 'isFilesAndDirectoriesSupported',
|
||||
chooseDirMethod = 'chooseDirectory';
|
||||
|
||||
var separator = '/';
|
||||
|
||||
var Directory = function() {
|
||||
this.name = '';
|
||||
this.path = separator;
|
||||
this._children = {};
|
||||
this._items = false;
|
||||
};
|
||||
|
||||
Directory.prototype[getFilesMethod] = function() {
|
||||
var that = this;
|
||||
|
||||
// from drag and drop and file input drag and drop (webkitEntries)
|
||||
if (this._items) {
|
||||
var getItem = function(entry) {
|
||||
if (entry.isDirectory) {
|
||||
var dir = new Directory();
|
||||
dir.name = entry.name;
|
||||
dir.path = entry.fullPath;
|
||||
dir._items = entry;
|
||||
|
||||
return dir;
|
||||
} else {
|
||||
return new Promise(function(resolve, reject) {
|
||||
entry.file(function(file) {
|
||||
resolve(file);
|
||||
}, reject);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (this.path === separator) {
|
||||
var promises = [];
|
||||
|
||||
for (var i = 0; i < this._items.length; i++) {
|
||||
var entry;
|
||||
|
||||
// from file input drag and drop (webkitEntries)
|
||||
if (this._items[i].isDirectory || this._items[i].isFile) {
|
||||
entry = this._items[i];
|
||||
} else {
|
||||
entry = this._items[i].webkitGetAsEntry();
|
||||
}
|
||||
|
||||
promises.push(getItem(entry));
|
||||
}
|
||||
|
||||
return Promise.all(promises);
|
||||
} else {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var dirReader = that._items.createReader();
|
||||
var promises = [];
|
||||
|
||||
var readEntries = function() {
|
||||
dirReader.readEntries(function(entries) {
|
||||
if (!entries.length) {
|
||||
resolve(Promise.all(promises));
|
||||
} else {
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
promises.push(getItem(entries[i]));
|
||||
}
|
||||
|
||||
readEntries();
|
||||
}
|
||||
}, reject);
|
||||
};
|
||||
|
||||
readEntries();
|
||||
});
|
||||
}
|
||||
// from file input manual selection
|
||||
} else {
|
||||
var arr = [];
|
||||
|
||||
for (var child in this._children) {
|
||||
arr.push(this._children[child]);
|
||||
}
|
||||
|
||||
return Promise.resolve(arr);
|
||||
}
|
||||
};
|
||||
|
||||
// set blank as default for all inputs
|
||||
HTMLInputElement.prototype[getFilesMethod] = function() {
|
||||
return Promise.resolve([]);
|
||||
};
|
||||
|
||||
// if OS is Mac, the combined directory and file picker is supported
|
||||
HTMLInputElement.prototype[isSupportedProp] = navigator.appVersion.indexOf("Mac") !== -1;
|
||||
|
||||
HTMLInputElement.prototype[allowdirsAttr] = undefined;
|
||||
HTMLInputElement.prototype[chooseDirMethod] = undefined;
|
||||
|
||||
// expose Directory interface to window
|
||||
window.Directory = Directory;
|
||||
|
||||
/********************
|
||||
**** File Input ****
|
||||
********************/
|
||||
var convertInputs = function(nodes) {
|
||||
var recurse = function(dir, path, fullPath, file) {
|
||||
var pathPieces = path.split(separator);
|
||||
var dirName = pathPieces.shift();
|
||||
|
||||
if (pathPieces.length > 0) {
|
||||
var subDir = new Directory();
|
||||
subDir.name = dirName;
|
||||
subDir.path = separator + fullPath;
|
||||
|
||||
if (!dir._children[subDir.name]) {
|
||||
dir._children[subDir.name] = subDir;
|
||||
}
|
||||
|
||||
recurse(dir._children[subDir.name], pathPieces.join(separator), fullPath, file);
|
||||
} else {
|
||||
dir._children[file.name] = file;
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
var node = nodes[i];
|
||||
|
||||
if (node.tagName === 'INPUT' && node.type === 'file') {
|
||||
var getFiles = function() {
|
||||
var files = node.files;
|
||||
|
||||
if (draggedAndDropped) {
|
||||
files = node.webkitEntries;
|
||||
draggedAndDropped = false;
|
||||
} else {
|
||||
if (files.length === 0) {
|
||||
files = node.shadowRoot.querySelector('#input1').files;
|
||||
|
||||
if (files.length === 0) {
|
||||
files = node.shadowRoot.querySelector('#input2').files;
|
||||
|
||||
if (files.length === 0) {
|
||||
files = node.webkitEntries;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
};
|
||||
|
||||
var draggedAndDropped = false;
|
||||
|
||||
node.addEventListener('drop', function(e) {
|
||||
draggedAndDropped = true;
|
||||
}, false);
|
||||
|
||||
if (node.hasAttribute(allowdirsAttr)) {
|
||||
// force multiple selection for default behavior
|
||||
if (!node.hasAttribute('multiple')) {
|
||||
node.setAttribute('multiple', '');
|
||||
}
|
||||
|
||||
var shadow = node.createShadowRoot();
|
||||
|
||||
node[chooseDirMethod] = function() {
|
||||
// can't do this without an actual click
|
||||
console.log('This is unsupported. For security reasons the dialog cannot be triggered unless it is a response to some user triggered event such as a click on some other element.');
|
||||
};
|
||||
|
||||
shadow.innerHTML = '<div style="border: 1px solid #999; padding: 3px; width: 235px; box-sizing: content-box; font-size: 14px; height: 21px;">'
|
||||
+ '<div id="fileButtons" style="box-sizing: content-box;">'
|
||||
+ '<button id="button1" style="width: 100px; box-sizing: content-box;">Choose file(s)...</button>'
|
||||
+ '<button id="button2" style="width: 100px; box-sizing: content-box; margin-left: 3px;">Choose folder...</button>'
|
||||
+ '</div>'
|
||||
+ '<div id="filesChosen" style="padding: 3px; display: none; box-sizing: content-box;"><span id="filesChosenText">files selected...</span>'
|
||||
+ '<a id="clear" title="Clear selection" href="javascript:;" style="text-decoration: none; float: right; margin: -3px -1px 0 0; padding: 3px; font-weight: bold; font-size: 16px; color:#999; box-sizing: content-box;">×</a>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '<input id="input1" type="file" multiple style="display: none;">'
|
||||
+ '<input id="input2" type="file" webkitdirectory style="display: none;">'
|
||||
+ '</div>';
|
||||
|
||||
shadow.querySelector('#button1').onclick = function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
shadow.querySelector('#input1').click();
|
||||
};
|
||||
|
||||
shadow.querySelector('#button2').onclick = function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
shadow.querySelector('#input2').click();
|
||||
};
|
||||
|
||||
var toggleView = function(defaultView, filesLength) {
|
||||
shadow.querySelector('#fileButtons').style.display = defaultView ? 'block' : 'none';
|
||||
shadow.querySelector('#filesChosen').style.display = defaultView ? 'none' : 'block';
|
||||
|
||||
if (!defaultView) {
|
||||
shadow.querySelector('#filesChosenText').innerText = filesLength + ' file' + (filesLength > 1 ? 's' : '') + ' selected...';
|
||||
}
|
||||
};
|
||||
|
||||
var changeHandler = function(e) {
|
||||
node.dispatchEvent(new Event('change'));
|
||||
|
||||
toggleView(false, getFiles().length);
|
||||
};
|
||||
|
||||
shadow.querySelector('#input1').onchange = shadow.querySelector('#input2').onchange = changeHandler;
|
||||
|
||||
var clear = function (e) {
|
||||
toggleView(true);
|
||||
|
||||
var form = document.createElement('form');
|
||||
node.parentNode.insertBefore(form, node);
|
||||
node.parentNode.removeChild(node);
|
||||
form.appendChild(node);
|
||||
form.reset();
|
||||
|
||||
form.parentNode.insertBefore(node, form);
|
||||
form.parentNode.removeChild(form);
|
||||
|
||||
// reset does not instantly occur, need to give it some time
|
||||
setTimeout(function() {
|
||||
node.dispatchEvent(new Event('change'));
|
||||
}, 1);
|
||||
};
|
||||
|
||||
shadow.querySelector('#clear').onclick = clear;
|
||||
}
|
||||
|
||||
node.addEventListener('change', function() {
|
||||
var dir = new Directory();
|
||||
|
||||
var files = getFiles();
|
||||
|
||||
if (files.length > 0) {
|
||||
if (node.hasAttribute(allowdirsAttr)) {
|
||||
toggleView(false, files.length);
|
||||
}
|
||||
|
||||
// from file input drag and drop (webkitEntries)
|
||||
if (files[0].isFile || files[0].isDirectory) {
|
||||
dir._items = files;
|
||||
} else {
|
||||
for (var j = 0; j < files.length; j++) {
|
||||
var file = files[j];
|
||||
var path = file.webkitRelativePath;
|
||||
var fullPath = path.substring(0, path.lastIndexOf(separator));
|
||||
|
||||
recurse(dir, path, fullPath, file);
|
||||
}
|
||||
}
|
||||
} else if (node.hasAttribute(allowdirsAttr)) {
|
||||
toggleView(true, files.length);
|
||||
}
|
||||
|
||||
this[getFilesMethod] = function() {
|
||||
return dir[getFilesMethod]();
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// polyfill file inputs when the DOM loads
|
||||
document.addEventListener('DOMContentLoaded', function(event) {
|
||||
convertInputs(document.getElementsByTagName('input'));
|
||||
});
|
||||
|
||||
// polyfill file inputs that are created dynamically and inserted into the body
|
||||
var observer = new MutationObserver(function(mutations, observer) {
|
||||
for (var i = 0; i < mutations.length; i++) {
|
||||
if (mutations[i].addedNodes.length > 0) {
|
||||
convertInputs(mutations[i].addedNodes);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(document.body, {childList: true, subtree: true});
|
||||
|
||||
/***********************
|
||||
**** Drag and drop ****
|
||||
***********************/
|
||||
// keep a reference to the original method
|
||||
var _addEventListener = EventTarget.prototype.addEventListener;
|
||||
|
||||
DataTransfer.prototype[getFilesMethod] = function() {
|
||||
return Promise.resolve([]);
|
||||
};
|
||||
|
||||
EventTarget.prototype.addEventListener = function(type, listener, useCapture) {
|
||||
if (type === 'drop') {
|
||||
var _listener = listener;
|
||||
|
||||
listener = function(e) {
|
||||
var dir = new Directory();
|
||||
dir._items = e.dataTransfer.items;
|
||||
|
||||
e.dataTransfer[getFilesMethod] = function() {
|
||||
return dir[getFilesMethod]();
|
||||
};
|
||||
|
||||
_listener(e);
|
||||
};
|
||||
}
|
||||
|
||||
// call the original method
|
||||
return _addEventListener.apply(this, arguments);
|
||||
};
|
||||
}());
|
||||
+194
-98
@@ -138,8 +138,8 @@ var aceEditor = {
|
||||
$('.ace_conter_menu').on('click', '.item .icon-tool', function(e) {
|
||||
var file_type = $(this).attr('data-file-state');
|
||||
var file_title = $(this).attr('data-title');
|
||||
var _path = $(this).parent().attr('title');
|
||||
var _id = $(this).parent().attr('data-id');
|
||||
var _path = $(this).parent().parent().attr('title');
|
||||
var _id = $(this).parent().parent().attr('data-id');
|
||||
switch (file_type) {
|
||||
// 直接关闭
|
||||
case '0':
|
||||
@@ -206,6 +206,7 @@ var aceEditor = {
|
||||
switch (_type) {
|
||||
case 'cursor':
|
||||
$('.ace_toolbar_menu').hide();
|
||||
$('.ace_header .jumpLine').click();
|
||||
break;
|
||||
case 'history':
|
||||
$('.ace_toolbar_menu').hide();
|
||||
@@ -379,7 +380,7 @@ var aceEditor = {
|
||||
}
|
||||
var loadT = layer.open({
|
||||
type: 1,
|
||||
area: ['350px', '180px'],
|
||||
//area: ['350px', '180px'],
|
||||
title: 'Tips',
|
||||
content: '<div class="ace-clear-form">\
|
||||
<div class="clear-icon"></div>\
|
||||
@@ -476,10 +477,9 @@ var aceEditor = {
|
||||
//主题
|
||||
case 'themes':
|
||||
$('.ace_toolbar_menu').show().find('.menu-themes').show().siblings().hide();
|
||||
var _html = '',
|
||||
_arry = ['White', 'Black'];
|
||||
var _html = '',_arry = ['White', 'Black'];
|
||||
for (var i = 0; i < _this.themeList.length; i++) {
|
||||
if (_this.aceConfig.themeList[i] != _this.aceConfig.aceEditor.editorTheme) {
|
||||
if (_this.themeList[i] != _this.aceConfig.aceEditor.editorTheme) {
|
||||
_html += '<li data-value="' + _this.themeList[i] + '">' + _this.themeList[i] + '【' + _arry[i] + '】</li>';
|
||||
} else {
|
||||
_html += '<li data-value="' + _this.themeList[i] + '" class="active">' + _this.themeList[i] + '【' + _arry[i] + '】' + _icon + '</li>';
|
||||
@@ -489,7 +489,7 @@ var aceEditor = {
|
||||
$('.menu-themes ul li').click(function(){
|
||||
var _theme = $(this).attr('data-value');
|
||||
$(this).addClass('active').append(_icon).siblings().removeClass('active').find('.icon').remove();
|
||||
_this.aceConfig.aceEditor.editorTheme = _theme;
|
||||
_this.aceConfig.aceEditor.editorTheme = _theme;
|
||||
_this.saveAceConfig(_this.aceConfig,function(res){
|
||||
for(var item in _this.editor){
|
||||
_this.editor[item].ace.setTheme("ace/theme/"+_theme);
|
||||
@@ -850,7 +850,6 @@ var aceEditor = {
|
||||
} else if ($(this).prev().attr('data-type') === 0) {
|
||||
return false;
|
||||
}
|
||||
console.log(_type)
|
||||
switch (_type) {
|
||||
case 0: //新建文件夹
|
||||
_this.event_create_dir({ path: _path + '/' + _file_or_dir });
|
||||
@@ -1175,7 +1174,7 @@ var aceEditor = {
|
||||
_this = this;
|
||||
var loadT = layer.open({
|
||||
type: 1,
|
||||
area: ['400px', '200px'],
|
||||
//area: ['400px', '180px'],
|
||||
title: lan.public.restore_history_files,
|
||||
content: '<div class="ace-clear-form">\
|
||||
<div class="clear-icon"></div>\
|
||||
@@ -1483,6 +1482,28 @@ var aceEditor = {
|
||||
}
|
||||
_editor.ace.resize();
|
||||
},
|
||||
// currentStatusBar: function(id) {
|
||||
// var _item = this.editor['ace_editor_' + id];
|
||||
// if(_item == undefined){
|
||||
// this.removerStatusBar();
|
||||
// return false;
|
||||
// }
|
||||
// $('.ace_conter_toolbar [data-type="cursor"]').html(lan.public.row + '<i class="cursor-row">1</i>,'+ lan.public.column +'<i class="cursor-line">0</i>');
|
||||
// $('.ace_conter_toolbar [data-type="history"]').html(lan.public.history_v + ': <i>' + (_item.historys.length === 0 ? lan.public.empty : _item.historys.length) + '</i>');
|
||||
// $('.ace_conter_toolbar [data-type="path"]').html(lan.public.dir + ': <i title="' + _item.path + '">' + _item.path + '</i>');
|
||||
// $('.ace_conter_toolbar [data-type="tab"]').html(_item.softTabs ? lan.public.space + ': <i>' + _item.tabSize + '</i>' : lan.public.tab_length + ': <i>' + _item.tabSize + '</i>');
|
||||
// $('.ace_conter_toolbar [data-type="encoding"]').html(lan.public.encoding + ': <i>' + _item.encoding.toUpperCase() + '</i>');
|
||||
// $('.ace_conter_toolbar [data-type="lang"]').html(lan.public.lan + ': <i>' + _item.type + '</i>');
|
||||
// $('.ace_conter_toolbar span').attr('data-id', id);
|
||||
// $('.file_fold').removeClass('bg');
|
||||
// $('[data-menu-path="' + (_item.path) + '"]').find('.file_fold').addClass('bg');
|
||||
// if (_item.historys_file) {
|
||||
// $('.ace_conter_toolbar [data-type="history"]').hide();
|
||||
// } else {
|
||||
// $('.ace_conter_toolbar [data-type="history"]').show();
|
||||
// }
|
||||
// _item.ace.resize();
|
||||
// },
|
||||
// 清除状态栏
|
||||
removerStatusBar: function() {
|
||||
$('.ace_conter_toolbar [data-type="history"]').html('');
|
||||
@@ -1588,53 +1609,74 @@ var aceEditor = {
|
||||
return { name: 'Text', mode: 'text' };
|
||||
},
|
||||
// 新建编辑器视图-方法
|
||||
addEditorView: function() {
|
||||
var _index = this.editorLength,
|
||||
_id = bt.get_random(8);
|
||||
$('.ace_conter_menu .item').removeClass('active');
|
||||
$('.ace_conter_editor .ace_editors').removeClass('active');
|
||||
$('.ace_conter_menu .ace_editor_add').before('<div class="item active item_tab_' + _id + '" data-type="text" data-id="' + _id + '" data-index="' + _index + '">\
|
||||
<span class="icon_file"><i class="fa fa-code" aria-hidden="true"></i></span>\
|
||||
<span>Untitled-' + _index + '</span>\
|
||||
<i class="fa fa-circle icon-tool" aria-hidden="true" data-file-state="1" data-title="Untitled-' + _index + '"></i>\
|
||||
</div>');
|
||||
$('.ace_conter_editor').append('<div id="ace_editor_' + _id + '" class="ace_editors active"></div>');
|
||||
$('#ace_editor_' + _id).siblings().removeClass('active');
|
||||
this.creationEditor({ id: _id });
|
||||
this.editorLength = this.editorLength + 1;
|
||||
},
|
||||
// addEditorView: function() {
|
||||
// var _index = this.editorLength,
|
||||
// _id = bt.get_random(8);
|
||||
// $('.ace_conter_menu .item').removeClass('active');
|
||||
// $('.ace_conter_editor .ace_editors').removeClass('active');
|
||||
// $('.ace_conter_menu .ace_editor_add').before('<div class="item active item_tab_' + _id + '" data-type="text" data-id="' + _id + '" data-index="' + _index + '">\
|
||||
// <span class="icon_file"><i class="fa fa-code" aria-hidden="true"></i></span>\
|
||||
// <span>Untitled-' + _index + '</span>\
|
||||
// <i class="fa fa-circle icon-tool" aria-hidden="true" data-file-state="1" data-title="Untitled-' + _index + '"></i>\
|
||||
// </div>');
|
||||
// $('.ace_conter_editor').append('<div id="ace_editor_' + _id + '" class="ace_editors active"></div>');
|
||||
// $('#ace_editor_' + _id).siblings().removeClass('active');
|
||||
// this.creationEditor({ id: _id });
|
||||
// this.editorLength = this.editorLength + 1;
|
||||
// },
|
||||
addEditorView: function (type,conifg) {
|
||||
if(type == undefined) type = 0
|
||||
var _index = this.editorLength,_id = bt.get_random(8);
|
||||
$('.ace_conter_menu .item').removeClass('active');
|
||||
$('.ace_conter_editor .ace_editors').removeClass('active');
|
||||
$('.ace_conter_menu').append('<li class="item active item_tab_'+_id+'" data-type="shortcutKeys" data-id="'+ _id +'" >\
|
||||
<div class="ace_item_box">\
|
||||
<span class="icon_file"><i class="text-icon"></i></span>\
|
||||
<span>'+ (type?conifg.title:('Untitled-'+ _index)) +'</span>\
|
||||
<i class="glyphicon icon-tool glyphicon-remove" aria-hidden="true" data-file-state="0" data-title="'+ (type?conifg.title:('Untitled-'+ _index)) +'"></i>\
|
||||
</div>\
|
||||
</li>');
|
||||
$('#ace_editor_' + _id).siblings().removeClass('active');
|
||||
$('.ace_conter_editor').append('<div id="ace_editor_'+_id+'" class="ace_editors active">'+ (type?aceShortcutKeys.innerHTML:'') +'</div>');
|
||||
switch(type){
|
||||
case 0:
|
||||
this.creationEditor({ id: _id });
|
||||
this.editorLength = this.editorLength + 1;
|
||||
break;
|
||||
case 1:
|
||||
this.removerStatusBar();
|
||||
this.editorLength = this.editorLength + 1;
|
||||
break;
|
||||
}
|
||||
},
|
||||
// 删除编辑器视图-方法
|
||||
removeEditor: function(id) {
|
||||
if ($('.item_tab_' + id).next('.item').length == 0) {
|
||||
$('.item_tab_' + id).prev('.item').addClass('active');
|
||||
$('#ace_editor_' + id).prev('.ace_editor').addClass('active');
|
||||
this.ace_active = $('.item_tab_' + id).prev('.item').attr('data-id');
|
||||
} else {
|
||||
$('.item_tab_' + id).next('.item').addClass('active');
|
||||
$('#ace_editor_' + id).next('.ace_editor').addClass('active');
|
||||
this.ace_active = $('.item_tab_' + id).next('.item').attr('data-id');
|
||||
removeEditor: function (id) {
|
||||
if(id == undefined) id = this.ace_active;
|
||||
if ($('.item_tab_' + id).next('.item').length != 0 && this.editorLength != 1) {
|
||||
$('.item_tab_' + id).next('.item').click();
|
||||
} else if($('.item_tab_' + id).prev('.item').length != 0 && this.editorLength != 1){
|
||||
$('.item_tab_' + id).prev('.item').click();
|
||||
}
|
||||
$('.item_tab_' + id).remove();
|
||||
$('#ace_editor_' + id).remove();
|
||||
for (var i = 0; i < this.pathAarry.length; i++) {
|
||||
if (this.pathAarry[i] == this.editor['ace_editor_' + id].path) {
|
||||
this.pathAarry.splice(i, 1);
|
||||
}
|
||||
$('.item_tab_' + id).remove();
|
||||
$('#ace_editor_' + id).remove();
|
||||
this.editorLength --;
|
||||
if(this.editor['ace_editor_'+id] == undefined) return false;
|
||||
for(var i=0;i<this.pathAarry.length;i++){
|
||||
if(this.pathAarry[i] == this.editor['ace_editor_'+id].path){
|
||||
this.pathAarry.splice(i,1);
|
||||
}
|
||||
}
|
||||
if(!this.editor['ace_editor_'+id].historys_file) $('[data-menu-path="'+ (this.editor['ace_editor_'+id].path) +'"]').find('.file_fold').removeClass('active bg');
|
||||
delete this.editor['ace_editor_'+id];
|
||||
if(this.editorLength === 0){
|
||||
this.ace_active = '';
|
||||
this.pathAarry = [];
|
||||
this.removerStatusBar();
|
||||
}else{
|
||||
this.currentStatusBar(this.ace_active);
|
||||
}
|
||||
if (!aceEditor.editor['ace_editor_' + id].historys_file) $('[data-menu-path="' + (aceEditor.editor['ace_editor_' + id].path) + '"]').find('.file_fold').removeClass('active bg');
|
||||
delete this.editor['ace_editor_' + id];
|
||||
this.editorLength--;
|
||||
if (this.editorLength === 0) {
|
||||
this.ace_active = '';
|
||||
this.pathAarry = [];
|
||||
this.removerStatusBar();
|
||||
} else {
|
||||
this.currentStatusBar(this.ace_active);
|
||||
}
|
||||
if (this.ace_active != '') {
|
||||
this.is_file_history(this.editor['ace_editor_' + this.ace_active]);
|
||||
}
|
||||
},
|
||||
if(this.ace_active != '') this.is_file_history(this.editor['ace_editor_'+this.ace_active]);
|
||||
},
|
||||
// 打开历史文件文件-方法
|
||||
openHistoryEditorView: function (obj,callback) {
|
||||
// 文件类型(type,列如:JavaScript) 、文件模型(mode,列如:text)、文件标识(id,列如:x8AmsnYn)、文件编号(index,列如:0)、文件路径 (path,列如:/www/root/)
|
||||
@@ -1658,40 +1700,69 @@ var aceEditor = {
|
||||
});
|
||||
},
|
||||
// 打开编辑器文件-方法
|
||||
openEditorView: function(path, callback) {
|
||||
if (path == undefined) return false;
|
||||
// 文件类型(type,列如:JavaScript) 、文件模型(mode,列如:text)、文件标识(id,列如:x8AmsnYn)、文件编号(index,列如:0)、文件路径 (path,列如:/www/root/)
|
||||
var _this = this,
|
||||
paths = path.split('/'),
|
||||
_fileName = paths[paths.length - 1],
|
||||
_fileType = this.getFileType(_fileName),
|
||||
_type = _fileType.name,
|
||||
_mode = _fileType.mode,
|
||||
_id = bt.get_random(8),
|
||||
_index = this.editorLength;
|
||||
_this.is_file_open(path, function(is_state) {
|
||||
if (is_state) {
|
||||
$('.ace_conter_menu').find('[title="' + path + '"]').click();
|
||||
} else {
|
||||
_this.getFileBody({ path: path }, function(res) {
|
||||
_this.pathAarry.push(path);
|
||||
$('.ace_conter_menu .item').removeClass('active');
|
||||
$('.ace_conter_editor .ace_editors').removeClass('active');
|
||||
$('.ace_conter_menu .ace_editor_add').before('<div class="item active item_tab_' + _id + '" title="' + path + '" data-type="' + _type + '" data-mode="' + _mode + '" data-id="' + _id + '" data-index="' + _index + '" data-fileName="' + _fileName + '">\
|
||||
<span class="icon_file"><i class="' + _mode + '-icon"></i></span><span title="' + path + '">' + _fileName + '</span>\
|
||||
<i class="glyphicon glyphicon-remove icon-tool" aria-hidden="true" data-file-state="0" data-title="' + _fileName + '"></i>\
|
||||
</div>');
|
||||
$('.ace_conter_editor').append('<div id="ace_editor_' + _id + '" class="ace_editors active"></div>');
|
||||
$('[data-menu-path="' + path + '"]').find('.file_fold').addClass('active bg');
|
||||
_this.ace_active = _id;
|
||||
_this.editorLength = _this.editorLength + 1;
|
||||
_this.creationEditor({ id: _id, fileName: _fileName, path: path, mode: _mode, encoding: res.encoding, data: res.data, type: _type, historys: res.historys });
|
||||
if (callback) callback(res);
|
||||
});
|
||||
}
|
||||
});
|
||||
$('.ace_toolbar_menu').hide();
|
||||
},
|
||||
// openEditorView: function(path, callback) {
|
||||
// if (path == undefined) return false;
|
||||
// // 文件类型(type,列如:JavaScript) 、文件模型(mode,列如:text)、文件标识(id,列如:x8AmsnYn)、文件编号(index,列如:0)、文件路径 (path,列如:/www/root/)
|
||||
// var _this = this,
|
||||
// paths = path.split('/'),
|
||||
// _fileName = paths[paths.length - 1],
|
||||
// _fileType = this.getFileType(_fileName),
|
||||
// _type = _fileType.name,
|
||||
// _mode = _fileType.mode,
|
||||
// _id = bt.get_random(8),
|
||||
// _index = this.editorLength;
|
||||
// _this.is_file_open(path, function(is_state) {
|
||||
// if (is_state) {
|
||||
// $('.ace_conter_menu').find('[title="' + path + '"]').click();
|
||||
// } else {
|
||||
// _this.getFileBody({ path: path }, function(res) {
|
||||
// _this.pathAarry.push(path);
|
||||
// $('.ace_conter_menu .item').removeClass('active');
|
||||
// $('.ace_conter_editor .ace_editors').removeClass('active');
|
||||
// $('.ace_conter_menu .ace_editor_add').before('<div class="item active item_tab_' + _id + '" title="' + path + '" data-type="' + _type + '" data-mode="' + _mode + '" data-id="' + _id + '" data-index="' + _index + '" data-fileName="' + _fileName + '">\
|
||||
// <span class="icon_file"><i class="' + _mode + '-icon"></i></span><span title="' + path + '">' + _fileName + '</span>\
|
||||
// <i class="glyphicon glyphicon-remove icon-tool" aria-hidden="true" data-file-state="0" data-title="' + _fileName + '"></i>\
|
||||
// </div>');
|
||||
// $('.ace_conter_editor').append('<div id="ace_editor_' + _id + '" class="ace_editors active"></div>');
|
||||
// $('[data-menu-path="' + path + '"]').find('.file_fold').addClass('active bg');
|
||||
// _this.ace_active = _id;
|
||||
// _this.editorLength = _this.editorLength + 1;
|
||||
// _this.creationEditor({ id: _id, fileName: _fileName, path: path, mode: _mode, encoding: res.encoding, data: res.data, type: _type, historys: res.historys });
|
||||
// if (callback) callback(res);
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// $('.ace_toolbar_menu').hide();
|
||||
// },
|
||||
openEditorView: function (path,callback) {
|
||||
if(path == undefined) return false;
|
||||
// 文件类型(type,列如:JavaScript) 、文件模型(mode,列如:text)、文件标识(id,列如:x8AmsnYn)、文件编号(index,列如:0)、文件路径 (path,列如:/www/root/)
|
||||
var _this = this,paths = path.split('/'),_fileName = paths[paths.length - 1],_fileType = this.getFileType(_fileName),_type = _fileType.name,_mode = _fileType.mode,_id = bt.get_random(8),_index = this.editorLength;
|
||||
_this.is_file_open(path,function(is_state){
|
||||
if(is_state){
|
||||
$('.ace_conter_menu').find('[title="'+ path +'"]').click();
|
||||
}else{
|
||||
_this.getFileBody({path: path}, function (res) {
|
||||
_this.pathAarry.push(path);
|
||||
$('.ace_conter_menu .item').removeClass('active');
|
||||
$('.ace_conter_editor .ace_editors').removeClass('active');
|
||||
$('.ace_conter_menu').append('<li class="item active item_tab_' + _id +'" title="'+ path +'" data-type="'+ _type +'" data-mode="'+ _mode +'" data-id="'+ _id +'" data-fileName="'+ _fileName +'">'+
|
||||
'<div class="ace_item_box">'+
|
||||
'<span class="icon_file"><i class="'+ _mode +'-icon"></i></span><span title="'+ path +'">' + _fileName + '</span>'+
|
||||
'<i class="glyphicon glyphicon-remove icon-tool" aria-hidden="true" data-file-state="0" data-title="' + _fileName + '"></i>'+
|
||||
'</div>'+
|
||||
'</li>');
|
||||
$('.ace_conter_editor').append('<div id="ace_editor_'+_id +'" class="ace_editors active" style="font-size:'+ aceEditor.aceConfig.aceEditor.fontSize +'px"></div>');
|
||||
$('[data-menu-path="'+ path +'"]').find('.file_fold').addClass('active bg');
|
||||
_this.ace_active = _id;
|
||||
_this.editorLength = _this.editorLength + 1;
|
||||
_this.creationEditor({id: _id,fileName: _fileName,path: path,mode:_mode,encoding: res.encoding,data: res.data,type:_type,historys:res.historys});
|
||||
if(callback) callback(res);
|
||||
});
|
||||
}
|
||||
});
|
||||
$('.ace_toolbar_menu').hide();
|
||||
},
|
||||
// 获取收藏夹列表-方法
|
||||
getFavoriteList: function() {},
|
||||
// 获取文件列表-请求
|
||||
@@ -1717,17 +1788,42 @@ var aceEditor = {
|
||||
});
|
||||
},
|
||||
// 保存文件内容-请求
|
||||
saveFileBody: function(obj, callback) {
|
||||
var loadT = layer.msg(lan.public.save_file_content, { time: 0, icon: 16, shade: [0.3, '#000'] });
|
||||
$.post("/files?action=SaveFileBody", {
|
||||
data:obj.data,
|
||||
encoding:obj.encoding.toLowerCase(),
|
||||
path:obj.path
|
||||
}, function(res) {
|
||||
layer.close(loadT);
|
||||
if (callback) callback(res)
|
||||
});
|
||||
},
|
||||
// saveFileBody: function(obj, callback) {
|
||||
// var loadT = layer.msg(lan.public.save_file_content, { time: 0, icon: 16, shade: [0.3, '#000'] });
|
||||
// $.post("/files?action=SaveFileBody", {
|
||||
// data:obj.data,
|
||||
// encoding:obj.encoding.toLowerCase(),
|
||||
// path:obj.path
|
||||
// }, function(res) {
|
||||
// layer.close(loadT);
|
||||
// if (callback) callback(res)
|
||||
// });
|
||||
// },
|
||||
saveFileBody: function (obj,success,error) {
|
||||
$.ajax({
|
||||
type:'post',
|
||||
url:'/files?action=SaveFileBody',
|
||||
timeout: 7000, //设置保存超时时间
|
||||
data:{
|
||||
data:obj.data,
|
||||
encoding:obj.encoding.toLowerCase(),
|
||||
path:obj.path
|
||||
},
|
||||
complete:function(res,status){
|
||||
if(res.status != 200){
|
||||
if(error) error(res.responseJSON)
|
||||
}else if(res.status == 200){
|
||||
var rdata = res.responseJSON;
|
||||
if(rdata.status){
|
||||
if(success) success(rdata)
|
||||
}else{
|
||||
if(error) error(rdata)
|
||||
}
|
||||
if(!obj.tips) layer.msg(rdata.msg,{icon:rdata.status?1:2});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
saveAceConfig: function(data,callback){
|
||||
var loadT = layer.msg(lan.public.save_ace_config,{time: 0,icon: 16,shade: [0.3, '#000']}),_this = this;
|
||||
this.saveFileBody({
|
||||
|
||||
@@ -77,7 +77,26 @@ var site = {
|
||||
return "<span class='c9 input-edit' onclick=\"bt.pub.set_data_by_key('sites','ps',this)\">" + item.ps + "</span>";
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
field: 'ssl', title: 'SSL certificate', width: 110, templet: function (item) {
|
||||
var _ssl = '';
|
||||
if (item.ssl == -1)
|
||||
{
|
||||
_ssl = '<a class="ssl_tips btlink" style="color:orange;">Not deployed</a>';
|
||||
}else{
|
||||
var ssl_info = "Certificate: "+item.ssl.issuer+"<br>Due date: " + item.ssl.notAfter+"<br>Application date: " + item.ssl.notBefore +"<br>Domain name: " + item.ssl.dns.join("/");
|
||||
if(item.ssl.endtime < 0){
|
||||
_ssl = '<a class="ssl_tips btlink" style="color:red;" data-tips="'+ssl_info+'">Expired</a>';
|
||||
|
||||
}else if(item.ssl.endtime < 20){
|
||||
_ssl = '<a class="ssl_tips btlink" style="color:red;" data-tips="'+ssl_info+'">Expire: '+(item.ssl.endtime+' days')+'</a>';
|
||||
}else{
|
||||
_ssl = '<a class="ssl_tips btlink" style="color:green;" data-tips="'+ssl_info+'">Expire: '+item.ssl.endtime+' days</a>';
|
||||
}
|
||||
}
|
||||
return _ssl;
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'opt',
|
||||
width: 260,
|
||||
@@ -96,7 +115,30 @@ var site = {
|
||||
],
|
||||
data: data
|
||||
})
|
||||
|
||||
var outTime = '';
|
||||
$('.ssl_tips').hover(function(){
|
||||
var that = this,tips = $(that).attr('data-tips');
|
||||
if(!tips) return false;
|
||||
outTime = setTimeout(function(){
|
||||
layer.tips(tips, $(that), {
|
||||
tips: [2, '#20a53a'], //还可配置颜色
|
||||
time:0
|
||||
});
|
||||
},500);
|
||||
},function(){
|
||||
outTime != ''?clearTimeout(outTime):'';
|
||||
layer.closeAll('tips');
|
||||
})
|
||||
$('.ssl_tips').click(function(){
|
||||
site.web_edit(this);
|
||||
var timeVal = setInterval(function(){
|
||||
var content = $('#webedit-con').html();
|
||||
if(content != ''){
|
||||
$('.site-menu p:eq(9)').click();
|
||||
clearInterval(timeVal);
|
||||
}
|
||||
},100);
|
||||
});
|
||||
//设置到期时间
|
||||
$('a.setTimes').each(function() {
|
||||
var _this = $(this);
|
||||
|
||||
@@ -254,6 +254,7 @@ var soft = {
|
||||
var is_php = item.name.indexOf('php-') >= 0,
|
||||
is_php5 = item.name.indexOf('php-5') >= 0,
|
||||
webcache = bt.get_cookie('serverType') == 'openlitespeed' ? true : false,
|
||||
distribution = bt.get_cookie('distribution'),
|
||||
redhat = rdata.Redhat;
|
||||
if (rdata.apache22 && is_php && $.inArray(item.name, phps) == -1) {
|
||||
if (item.setup) {
|
||||
@@ -317,6 +318,9 @@ var soft = {
|
||||
option = '<span title="\' + lan.soft.ap2_2_not_support + \'">' + lan.soft.not_comp + '</span>';
|
||||
}
|
||||
}
|
||||
if (distribution=='centos8' && item.name == 'php-7.0') {
|
||||
option = '<span title="\' + lan.soft.ap2_2_not_support + \'">' + lan.soft.not_comp + '</span>';
|
||||
}
|
||||
return option;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1145,7 +1145,6 @@ td {
|
||||
window.location.href = text.attr('href');
|
||||
}
|
||||
});
|
||||
|
||||
function submit_pass(){
|
||||
var file_password = document.getElementById("file_password").value,
|
||||
url = $(this).parent().attr('data-url');
|
||||
@@ -1153,7 +1152,6 @@ td {
|
||||
alert("Incorrect password length!");
|
||||
return false;
|
||||
}
|
||||
$('.file_password').val('test');
|
||||
$.post(url, {file_password:file_password},function (res) {
|
||||
if (res.status==false){
|
||||
alert(res.msg);
|
||||
|
||||
@@ -212,14 +212,15 @@
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
<!--<link rel="stylesheet" type="text/css" href="https://at.alicdn.com/t/font_1628000_cso2y4bz1wk.css">-->
|
||||
<script src="/static/js/jquery-ui.min.js"></script>
|
||||
<script src="/static/js/jquery.contextify.min.js"></script>
|
||||
<script src="/static/js/files.js?date20191219={{g.version}}"></script>
|
||||
<script type="text/javascript" src="/static/js/bt_upload.js?version={{g['version']}}"></script>
|
||||
<script type="text/javascript" src="/static/js/jquery-ui.min.js"></script>
|
||||
<script type="text/javascript" src="/static/js/jquery.contextify.min.js"></script>
|
||||
<script type="text/javascript" src="/static/js/files.js?date20191219={{g.version}}"></script>
|
||||
<!-- <script type="text/javascript" src="/static/js/bt_upload.js?version={{g['version']}}"></script> -->
|
||||
<script type="text/javascript" src="/static/ace/ace.js?date={{g.version}}"></script>
|
||||
<script type="text/javascript" src="/static/ace/ext-language_tools.js?date={{g.version}}"></script>
|
||||
<script type="text/javascript" src="/static/js/clipboard.min.js"></script>
|
||||
<script type="text/javascript" src="{{g.cdn_url}}/js/jquery.dragsort-0.5.2.min.js"></script>
|
||||
<script type="text/javascript" src="/static/js/jquery.dragsort-0.5.2.min.js"></script>
|
||||
<script type="text/javascript" src="/static/js/polyfill.js"></script>
|
||||
<script type="text/javascript">
|
||||
setTimeout(function(){
|
||||
GetDisk();
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
<div class="footer bgw">{{session['brand']}}{{session['product']}} ©2014-{{session['yaer']}} {{session['brand']}} (bt.cn)
|
||||
<!--<a style="margin-left:20px;color:#20a53a;" href="http://www.bt.cn/bbs" target="_blank">求助|建议请上宝塔论坛</a>-->
|
||||
<a style="margin-left:20px;color:#20a53a;" href="http://forum.aapanel.com" target="_blank">{{session['bt_help']}}</a>
|
||||
<!--<a style="margin-left:20px;color:#20a53a;" href="http://docs.bt.cn/424204" target="_blank">{{session['manual']}}</a>-->
|
||||
<a style="margin-left:20px;color:#20a53a;" href="https://doc.aapanel.com/web/#/3?page_id=117" target="_blank">User manual</a>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/js/jquery-1.10.2.min.js"></script>
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
<script type="text/javascript">
|
||||
bt.set_cookie('sites_path', "{{session['config']['sites_path']}}");
|
||||
bt.set_cookie('serverType', "{{session['webserver']}}");
|
||||
bt.set_cookie('distribution', "{{session['config']['distribution']}}");
|
||||
$(document).ready(function () {
|
||||
soft.get_list();
|
||||
setTimeout(function () {
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: 黄文良 <287962566@qq.com>
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
+16
-3
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2016 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
from BTPanel import session,request
|
||||
import public,os,json,time,apache,psutil
|
||||
@@ -430,7 +430,18 @@ class ajax:
|
||||
return data
|
||||
except:
|
||||
return public.returnMsg(False,'AJAX_CONN_ERR')
|
||||
|
||||
|
||||
def get_other_info(self):
|
||||
other = {}
|
||||
other['ds'] = []
|
||||
ds = public.M('domain').field('name').select()
|
||||
# public.writeFile('/tmp/1.txt',str(ds))
|
||||
for d in ds:
|
||||
other['ds'].append(d['name'])
|
||||
|
||||
return ','.join(other['ds'])
|
||||
|
||||
|
||||
def UpdatePanel(self,get):
|
||||
try:
|
||||
if not public.IsRestart(): return public.returnMsg(False,'EXEC_ERR_TASK')
|
||||
@@ -445,7 +456,7 @@ class ajax:
|
||||
if 'updateInfo' in session and hasattr(get,'check') == False:
|
||||
updateInfo = session['updateInfo']
|
||||
else:
|
||||
logs = ''
|
||||
logs = '' #public.GetClientIp() +':'+ str(request.environ.get('REMOTE_PORT')) + '|' + str(int(time.time()))
|
||||
import psutil,system,sys
|
||||
mem = psutil.virtual_memory()
|
||||
import panelPlugin
|
||||
@@ -454,6 +465,7 @@ class ajax:
|
||||
mplugin.ROWS = 10000
|
||||
panelsys = system.system()
|
||||
data = {}
|
||||
data['ds'] = ''#self.get_other_info()
|
||||
data['sites'] = str(public.M('sites').count())
|
||||
data['ftps'] = str(public.M('ftps').count())
|
||||
data['databases'] = str(public.M('databases').count())
|
||||
@@ -514,6 +526,7 @@ class ajax:
|
||||
public.ExecShell('rm -rf /www/server/phpinfo/*')
|
||||
return public.returnMsg(True,updateInfo)
|
||||
except Exception as ex:
|
||||
return public.get_error_info()
|
||||
return public.returnMsg(False,"CONNECT_ERR")
|
||||
|
||||
#检查是否安装任何
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2018 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: 黄文良 <287962566@qq.com>
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
|
||||
+5
-5
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
from flask import request, redirect, g
|
||||
from BTPanel import session, cache
|
||||
@@ -34,7 +34,7 @@ class panelSetup:
|
||||
ua = ua.lower()
|
||||
if ua.find('spider') != -1 or ua.find('bot') != -1:
|
||||
return redirect('https://www.google.com')
|
||||
g.version = '6.7.0'
|
||||
g.version = '6.7.2'
|
||||
g.title = public.GetConfigValue('title')
|
||||
g.uri = request.path
|
||||
if not os.path.exists('data/debug.pl'):
|
||||
@@ -104,12 +104,12 @@ class panelAdmin(panelSetup):
|
||||
# 检查Web服务器类型
|
||||
|
||||
def checkWebType(self):
|
||||
if os.path.exists(self.setupPath + '/nginx'):
|
||||
session['webserver'] = 'nginx'
|
||||
if os.path.exists('/usr/local/lsws/bin/lswsctrl'):
|
||||
session['webserver'] = 'openlitespeed'
|
||||
elif os.path.exists(self.setupPath + '/apache'):
|
||||
session['webserver'] = 'apache'
|
||||
else:
|
||||
session['webserver'] = 'openlitespeed'
|
||||
session['webserver'] = 'nginx'
|
||||
if os.path.exists(self.setupPath+'/'+session['webserver']+'/version.pl'):
|
||||
session['webversion'] = public.ReadFile(self.setupPath+'/'+session['webserver']+'/version.pl').strip()
|
||||
filename = self.setupPath+'/data/phpmyadminDirName.pl'
|
||||
|
||||
+5
-2
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2017 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
import public,re,sys,os,nginx,apache,json,time,ols
|
||||
try:
|
||||
@@ -1039,8 +1039,11 @@ class config:
|
||||
|
||||
#获取配置
|
||||
def get_config(self,get):
|
||||
if 'config' in session: return session['config']
|
||||
if 'config' in session:
|
||||
session['config']['distribution'] = public.get_linux_distribution()
|
||||
return session['config']
|
||||
data = public.M('config').where("id=?",('1',)).field('webserver,sites_path,backup_path,status,mysql_root').find()
|
||||
data['distribution'] = public.get_linux_distribution()
|
||||
return data
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
import public,db,os,time,re
|
||||
from BTPanel import session,cache
|
||||
|
||||
+39
-4
@@ -4,11 +4,11 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2016 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
import sys
|
||||
import sys,os,re,time
|
||||
sys.path.append("class/")
|
||||
import db,public,re
|
||||
import db,public
|
||||
import json
|
||||
|
||||
class data:
|
||||
@@ -43,7 +43,41 @@ class data:
|
||||
result = 0
|
||||
if temp['local']: result +=2
|
||||
return result
|
||||
|
||||
|
||||
def get_site_ssl_info(self,siteName):
|
||||
s_file = 'vhost/nginx/{}.conf'.format(siteName)
|
||||
is_apache = False
|
||||
if not os.path.exists(s_file):
|
||||
s_file = 'vhost/apache/{}.conf'.format(siteName)
|
||||
is_apache = True
|
||||
|
||||
if not os.path.exists(s_file):
|
||||
return -1
|
||||
|
||||
s_conf = public.readFile(s_file)
|
||||
if not s_conf: return -1
|
||||
ssl_file = None
|
||||
if is_apache:
|
||||
if s_conf.find('SSLCertificateFile') == -1:
|
||||
return -1
|
||||
s_tmp = re.findall(r"SSLCertificateFile\s+(.+\.pem)",s_conf)
|
||||
if not s_tmp: return -1
|
||||
ssl_file = s_tmp[0]
|
||||
else:
|
||||
if s_conf.find('ssl_certificate') == -1:
|
||||
return -1
|
||||
s_tmp = re.findall(r"ssl_certificate\s+(.+\.pem);",s_conf)
|
||||
if not s_tmp: return -1
|
||||
ssl_file = s_tmp[0]
|
||||
ssl_info = public.get_cert_data(ssl_file)
|
||||
if not ssl_info: return -1
|
||||
ssl_info['endtime'] = int(int(time.mktime(time.strptime(ssl_info['notAfter'], "%Y-%m-%d")) - time.time()) / 86400)
|
||||
return ssl_info
|
||||
#return "{}:{}".format(ssl_info['issuer'],ssl_info['notAfter'])
|
||||
|
||||
|
||||
|
||||
|
||||
'''
|
||||
* 取数据列表
|
||||
* @param String _GET['tab'] 数据库表名
|
||||
@@ -71,6 +105,7 @@ class data:
|
||||
if table == 'sites':
|
||||
for i in range(len(data['data'])):
|
||||
data['data'][i]['domain'] = SQL.table('domain').where("pid=?",(data['data'][i]['id'],)).count()
|
||||
data['data'][i]['ssl'] = self.get_site_ssl_info(data['data'][i]['name'])
|
||||
elif table == 'firewall':
|
||||
for i in range(len(data['data'])):
|
||||
if data['data'][i]['port'].find(':') != -1 or data['data'][i]['port'].find('.') != -1 or data['data'][i]['port'].find('-') != -1:
|
||||
|
||||
+14
-6
@@ -4,7 +4,7 @@
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2017 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: 黄文良 <287962566@qq.com>
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
@@ -687,7 +687,7 @@ SetLink
|
||||
if mysqlInfo['datadir'] == get.datadir: return public.returnMsg(False,'DATABASE_MOVE_RE')
|
||||
|
||||
public.ExecShell('/etc/init.d/mysqld stop')
|
||||
public.ExecShell('\cp -a -r ' + mysqlInfo['datadir'] + '/* ' + get.datadir + '/')
|
||||
public.ExecShell('\cp -arf ' + mysqlInfo['datadir'] + '/* ' + get.datadir + '/')
|
||||
public.ExecShell('chown -R mysql.mysql ' + get.datadir)
|
||||
public.ExecShell('chmod -R 755 ' + get.datadir)
|
||||
public.ExecShell('rm -f ' + get.datadir + '/*.pid')
|
||||
@@ -714,7 +714,7 @@ SetLink
|
||||
def SetMySQLPort(self,get):
|
||||
myfile = '/etc/my.cnf'
|
||||
mycnf = public.readFile(myfile)
|
||||
rep = "port\s*=\s*([0-9]+)\s*\n"
|
||||
rep = r"port\s*=\s*([0-9]+)\s*\n"
|
||||
mycnf = re.sub(rep,'port = ' + get.port + '\n',mycnf)
|
||||
public.writeFile(myfile,mycnf)
|
||||
public.ExecShell('/etc/init.d/mysqld restart')
|
||||
@@ -793,11 +793,19 @@ SetLink
|
||||
m_version = public.readFile('/www/server/mysql/version.pl')
|
||||
if not m_version: m_version = ''
|
||||
for g in gets:
|
||||
if m_version.find('8.') == 0 and g in ['query_cache_type','query_cache_size']: continue
|
||||
if m_version.find('8.') == 0 and g in ['query_cache_type','query_cache_size']:
|
||||
n += 1
|
||||
continue
|
||||
s = 'M'
|
||||
if n > 5: s = 'K'
|
||||
if n > 5 and not g in ['key_buffer_size','query_cache_size','tmp_table_size','max_heap_table_size','innodb_buffer_pool_size','innodb_log_buffer_size']: s = 'K'
|
||||
if g in emptys: s = ''
|
||||
rep = '\s*'+g+'\s*=\s*\d+(M|K|k|m|G)?\n'
|
||||
if g in ['innodb_log_buffer_size']:
|
||||
s = 'M'
|
||||
if int(get[g]) < 8:
|
||||
return public.returnMsg(False,'innodb_log_buffer_size cannot be less than 8MB')
|
||||
|
||||
rep = r'\s*'+g+r'\s*=\s*\d+(M|K|k|m|G)?\n'
|
||||
|
||||
c = g+' = ' + get[g] + s +'\n'
|
||||
if mycnf.find(g) != -1:
|
||||
mycnf = re.sub(rep,'\n'+c,mycnf,1)
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
import sqlite3
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <2879625666@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
import os,sys,public,json,time
|
||||
class downloadFile:
|
||||
|
||||
+7
-2
@@ -5,7 +5,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2016 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
import sys
|
||||
import os
|
||||
@@ -196,6 +196,9 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
args.f_name = args.f_name.encode('utf-8')
|
||||
args.f_path = args.f_path.encode('utf-8')
|
||||
|
||||
if args.f_path == '/':
|
||||
return public.returnMsg(False,'Cannot upload files to the system root directory!')
|
||||
|
||||
if args.f_name.find('./') != -1 or args.f_path.find('./') != -1:
|
||||
return public.returnMsg(False, 'Wrong parameter')
|
||||
if not os.path.exists(args.f_path):
|
||||
@@ -333,6 +336,8 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
try:
|
||||
if sys.version_info[0] == 2:
|
||||
filename = filename.encode('utf-8')
|
||||
else:
|
||||
filename.encode('utf-8')
|
||||
filePath = get.path+'/'+filename
|
||||
link = ''
|
||||
if os.path.islink(filePath):
|
||||
@@ -1350,7 +1355,7 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
shutil.move(sfile, dfile)
|
||||
else:
|
||||
self.copytree(sfile, dfile)
|
||||
if os.path.exists(sfile):
|
||||
if os.path.exists(sfile) and os.path.exists(dfile):
|
||||
if is_dir:
|
||||
shutil.rmtree(sfile)
|
||||
else:
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2016 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
import sys,os,public,re,firewalld,time
|
||||
class firewalls:
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# + -------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2016 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# + -------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# + -------------------------------------------------------------------
|
||||
import public,db,re,os,firewalls
|
||||
from BTPanel import session
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
+6
-2
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
import time,public,db,os,sys,json,re
|
||||
os.chdir('/www/server/panel')
|
||||
@@ -75,6 +75,9 @@ def control_init():
|
||||
public.M('crontab').execute("ALTER TABLE 'crontab' ADD 'urladdress' TEXT",())
|
||||
|
||||
|
||||
public.M('users').where('email=? or email=?',('287962566@qq.com','amw_287962566@qq.com')).setField('email','test@message.com')
|
||||
|
||||
|
||||
filename = '/www/server/nginx/off'
|
||||
if os.path.exists(filename): os.remove(filename)
|
||||
c = public.to_string([99, 104, 97, 116, 116, 114, 32, 45, 105, 32, 47, 119, 119, 119, 47,
|
||||
@@ -102,6 +105,7 @@ def control_init():
|
||||
clean_session()
|
||||
#set_crond()
|
||||
clean_max_log('/www/server/panel/plugin/rsync/lsyncd.log')
|
||||
clean_max_log('/root/.pm2/pm2.log',1024*1024*20)
|
||||
remove_tty1()
|
||||
clean_hook_log()
|
||||
run_new()
|
||||
@@ -109,7 +113,7 @@ def control_init():
|
||||
#check_firewall()
|
||||
check_dnsapi()
|
||||
clean_php_log()
|
||||
update_py37()
|
||||
#update_py37()
|
||||
|
||||
|
||||
#尝试升级到独立环境
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 王张杰 <750755014@qq.com>
|
||||
# | Author: wzjie <wzj@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
import os
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: 黄文良 <287962566@qq.com>
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: 邹浩文 <627622230@qq.com>
|
||||
# Author: zhwwen <zhw@bt.cn>
|
||||
# -------------------------------------------------------------------
|
||||
#
|
||||
# ------------------------------
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2016 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
import math,string,public
|
||||
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2017 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 阿良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
import public,os,json,time
|
||||
class panelApi:
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2019 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: 黄文良 <287962566@qq.com>
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: 黄文良 <287962566@qq.com>
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
@@ -76,8 +76,8 @@ class backup:
|
||||
|
||||
def GetDiskInfo2(self):
|
||||
#取磁盘分区信息
|
||||
temp = public.ExecShell("df -T -P|grep '/'|grep -v tmpfs")[0]
|
||||
tempInodes = public.ExecShell("df -i -P|grep '/'|grep -v tmpfs|grep -v '/boot'")[0]
|
||||
temp = public.ExecShell("df -T -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev")[0]
|
||||
tempInodes = public.ExecShell("df -i -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev")[0]
|
||||
temp1 = temp.split('\n')
|
||||
tempInodes1 = tempInodes.split('\n')
|
||||
diskInfo = []
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 曹觉心 <314866873@qq.com>
|
||||
# | Author: 沐落 <cjx@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
import public,os,sys,json,time,random
|
||||
import requests
|
||||
|
||||
+4
-3
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 曹觉心 <314866873@qq.com>
|
||||
# | Author: 沐落 <cjx@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
import os,sys,json,time,re
|
||||
setup_path = '/www/server/panel'
|
||||
@@ -631,7 +631,6 @@ class panelLets:
|
||||
|
||||
headers = {"User-Agent": client.User_Agent}
|
||||
get_identifier_authorization_response = requests.get(url, timeout = client.ACME_REQUEST_TIMEOUT, headers=headers,verify=False)
|
||||
|
||||
if get_identifier_authorization_response.status_code not in [200, 201]:
|
||||
raise ValueError("Error getting identifier authorization: status_code={status_code}".format(status_code=get_identifier_authorization_response.status_code ) )
|
||||
res = get_identifier_authorization_response.json()
|
||||
@@ -763,5 +762,7 @@ if __name__ == "__main__":
|
||||
if len(sys.argv) > 1:
|
||||
type = sys.argv[1]
|
||||
if type == 'renew_lets_ssl':
|
||||
panelLets().renew_lets_ssl()
|
||||
try:
|
||||
panelLets().renew_lets_ssl()
|
||||
except: pass
|
||||
os.system(public.get_python_bin() + " /www/server/panel/class/acme_v2.py --renew=1")
|
||||
|
||||
+13
-9
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <2020-05-18>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
# +-------------------------------------------------------------------
|
||||
@@ -21,7 +21,7 @@ class panelMessage:
|
||||
def get_messages(self,args = None):
|
||||
'''
|
||||
@name 获取消息列表
|
||||
@author 黄文良 <2020-05-18>
|
||||
@author hwliang <2020-05-18>
|
||||
@return list
|
||||
'''
|
||||
data = public.M('messages').where('state=? and expire>?',(1,int(time.time()))).order("id desc").select()
|
||||
@@ -30,7 +30,7 @@ class panelMessage:
|
||||
def get_messages_all(self,args = None):
|
||||
'''
|
||||
@name 获取所有消息列表
|
||||
@author 黄文良 <2020-05-18>
|
||||
@author hwliang <2020-05-18>
|
||||
@return list
|
||||
'''
|
||||
data = public.M('messages').order("id desc").select()
|
||||
@@ -39,7 +39,7 @@ class panelMessage:
|
||||
def get_message_find(self,args = None,id = None):
|
||||
'''
|
||||
@name 获取指定消息
|
||||
@author 黄文良 <2020-05-18>
|
||||
@author hwliang <2020-05-18>
|
||||
@param args dict_obj{
|
||||
id: 消息标识
|
||||
}
|
||||
@@ -54,7 +54,7 @@ class panelMessage:
|
||||
def create_message(self,args = None,level=None,msg=None,expire=None):
|
||||
'''
|
||||
@name 创建新的消息
|
||||
@author 黄文良 <2020-05-18>
|
||||
@author hwliang <2020-05-18>
|
||||
@param args dict_obj{
|
||||
level: 消息级别(info/warning/danger/error),
|
||||
msg: 消息内容
|
||||
@@ -80,7 +80,7 @@ class panelMessage:
|
||||
def status_message(self,args = None,id = None,state = None):
|
||||
'''
|
||||
@name 设置消息状态
|
||||
@author 黄文良 <2020-05-18>
|
||||
@author hwliang <2020-05-18>
|
||||
@param args dict_obj{
|
||||
id: 消息标识,
|
||||
state: 消息状态(0.已忽略, 1.正常)
|
||||
@@ -97,7 +97,7 @@ class panelMessage:
|
||||
def remove_message(self,args = None,id = None):
|
||||
'''
|
||||
@name 删除指定消息
|
||||
@author 黄文良 <2020-05-18>
|
||||
@author hwliang <2020-05-18>
|
||||
@param args dict_obj{
|
||||
id: 消息标识
|
||||
}
|
||||
@@ -111,17 +111,21 @@ class panelMessage:
|
||||
def remove_message_level(self,level):
|
||||
'''
|
||||
@name 删除指定消息
|
||||
@author 黄文良 <2020-05-18>
|
||||
@author hwliang <2020-05-18>
|
||||
@param level string(指定级别或标识)
|
||||
@return bool
|
||||
'''
|
||||
public.M('messages').where('(level=? or level=? or level=? or level=?) and state=?',(level,level+'15',level+'7',level+'3',1)).delete()
|
||||
return True
|
||||
|
||||
def remove_message_all(self):
|
||||
public.M('messages').where('state=?',(1,)).delete()
|
||||
return True
|
||||
|
||||
def is_level(self,level):
|
||||
'''
|
||||
@name 指定消息是否忽略
|
||||
@author 黄文良 <2020-05-18>
|
||||
@author hwliang <2020-05-18>
|
||||
@param level string(指定级别或标识)
|
||||
@return bool
|
||||
'''
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
import re,os,sys,public
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
+46
-23
@@ -4,7 +4,7 @@
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2019 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: 黄文良 <287962566@qq.com>
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
import public,os,sys,json,time,psutil,py_compile,re
|
||||
from BTPanel import session,cache
|
||||
@@ -68,7 +68,9 @@ class panelPlugin:
|
||||
for name in mutexs:
|
||||
pluginInfo = self.get_soft_find(name)
|
||||
if not pluginInfo: continue
|
||||
if pluginInfo['setup'] == True: return False
|
||||
if pluginInfo['setup'] == True:
|
||||
self.mutex_title = pluginInfo['title']
|
||||
return False
|
||||
return True
|
||||
|
||||
#检查依赖
|
||||
@@ -322,7 +324,7 @@ class panelPlugin:
|
||||
cloudUrl = 'http://www.bt.cn/api/panel/get_soft_list_en?v=6.6.6'
|
||||
import panelAuth
|
||||
pdata = panelAuth.panelAuth().create_serverid(None)
|
||||
listTmp = public.httpPost(cloudUrl,pdata,10)
|
||||
listTmp = public.httpPost(cloudUrl,pdata,5)
|
||||
if not listTmp or len(listTmp) < 200:
|
||||
listTmp = public.readFile(lcoalTmp)
|
||||
try:
|
||||
@@ -331,7 +333,8 @@ class panelPlugin:
|
||||
if softList: public.writeFile(lcoalTmp,json.dumps(softList))
|
||||
public.ExecShell('rm -f /tmp/bmac_*')
|
||||
self.getCloudPHPExt(get)
|
||||
self.expire_msg(softList)
|
||||
# 专业版和企业版到期提醒,aaPanel目前没有先注释
|
||||
# self.expire_msg(softList)
|
||||
try:
|
||||
public.writeFile("/tmp/" + cache.get('p_token'),str(softList['pro']))
|
||||
except:pass
|
||||
@@ -403,10 +406,15 @@ class panelPlugin:
|
||||
'''
|
||||
s_time = time.time()
|
||||
is_plugin = True
|
||||
import panelMessage #引用消息提醒模块
|
||||
pm = panelMessage.panelMessage()
|
||||
pm.remove_message_all()
|
||||
|
||||
#企业版到期提醒
|
||||
if not data['ltd'] in [-1]:
|
||||
level,expire_day = self.get_level_msg('ltd',s_time,data['ltd'])
|
||||
self.add_expire_msg('企业版',level,'ltd',expire_day,100000032,data['ltd'])
|
||||
pm.remove_message_level('pro')
|
||||
return True
|
||||
|
||||
#专业版到期提醒
|
||||
@@ -416,14 +424,14 @@ class panelPlugin:
|
||||
is_plugin = False
|
||||
|
||||
#单独购买的插件到期提醒
|
||||
for p in data['list']:
|
||||
#跳过非企业版或专业版插件
|
||||
if not p['type'] in [8,12]: continue
|
||||
#已经是专业版的情况下跳过专业版插件
|
||||
if not is_plugin and p['type'] == 8: continue
|
||||
if not p['endtime'] in [-1,0]:
|
||||
level,expire_day = self.get_level_msg(p['name'],s_time,p['endtime'])
|
||||
self.add_expire_msg(p['title'],level,p['name'],expire_day,p['pid'],p['endtime'])
|
||||
# for p in data['list']:
|
||||
# #跳过非企业版或专业版插件
|
||||
# if not p['type'] in [8,12]: continue
|
||||
# #已经是专业版的情况下跳过专业版插件
|
||||
# if not is_plugin and p['type'] == 8: continue
|
||||
# if not p['endtime'] in [-1,0]:
|
||||
# level,expire_day = self.get_level_msg(p['name'],s_time,p['endtime'])
|
||||
# self.add_expire_msg(p['title'],level,p['name'],expire_day,p['pid'],p['endtime'])
|
||||
return True
|
||||
|
||||
|
||||
@@ -472,14 +480,28 @@ class panelPlugin:
|
||||
try:
|
||||
log_path = 'logs/request'
|
||||
if not os.path.exists(log_path): return False
|
||||
limit_num = 7
|
||||
limit_num = 180
|
||||
p_logs = sorted(os.listdir(log_path))
|
||||
num = len(p_logs) - limit_num
|
||||
if num <= 0: return False
|
||||
for i in range(num):
|
||||
filename = log_path + '/' + p_logs[i]
|
||||
if not os.path.exists(filename): continue
|
||||
os.remove(filename)
|
||||
if num > 0:
|
||||
for i in range(num):
|
||||
filename = log_path + '/' + p_logs[i]
|
||||
if not os.path.exists(filename): continue
|
||||
os.remove(filename)
|
||||
|
||||
today = public.getDate(format='%Y-%m-%d')
|
||||
for fname in os.listdir(log_path):
|
||||
fsplit = fname.split('.')
|
||||
if fsplit[-1] != 'json':
|
||||
continue
|
||||
if fsplit[0] == today:
|
||||
continue
|
||||
public.ExecShell("cd {} && gzip {}".format(log_path,fname))
|
||||
|
||||
#清理错误日志
|
||||
public.clean_max_log('/www/server/panel/logs/error.log',10,20)
|
||||
public.clean_max_log('/www/server/panel/logs/socks5.log',10,20)
|
||||
public.clean_max_log('/www/server/panel/logs/oos.log',10,20)
|
||||
return True
|
||||
except:return False
|
||||
|
||||
@@ -587,9 +609,13 @@ class panelPlugin:
|
||||
#处理分类
|
||||
def get_types(self,sList,sType):
|
||||
if sType <= 0: return sList
|
||||
if sType != 12:
|
||||
sType = [sType]
|
||||
else:
|
||||
sType = [sType,8]
|
||||
newList = []
|
||||
for sInfo in sList:
|
||||
if sInfo['type'] == sType: newList.append(sInfo)
|
||||
if sInfo['type'] in sType: newList.append(sInfo)
|
||||
return newList
|
||||
|
||||
#检查权限
|
||||
@@ -613,11 +639,11 @@ class panelPlugin:
|
||||
args.type = '12'
|
||||
p_list = self.get_cloud_list(args)
|
||||
for p in p_list['list']:
|
||||
if not p['type'] in [12,'12']: continue
|
||||
if p['name'] == get.name:
|
||||
if not 'endtime' in p: continue
|
||||
if p_list['ltd'] < 1 and p['endtime'] < 1: return False
|
||||
break
|
||||
|
||||
return True
|
||||
|
||||
#取软件列表
|
||||
@@ -647,9 +673,6 @@ class panelPlugin:
|
||||
if public.readFile(check_version_path).find('2.2') == 0:
|
||||
softList['apache22'] = True
|
||||
softList['apache24'] = False
|
||||
softList['Redhat'] = False
|
||||
if os.path.exists('/etc/redhat-release'):
|
||||
softList['Redhat'] = True
|
||||
|
||||
return softList
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2018 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: 黄文良 <287962566@qq.com>
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2016 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: 黄文良 <287962566@qq.com>
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2017 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: 黄文良 <287962566@qq.com>
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2019-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: 黄文良 <287962566@qq.com>
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# ------------------------------
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <2020-05-18>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/python
|
||||
#coding: utf-8
|
||||
# Author: <梁凯强>1249648969@qq.com
|
||||
# Author: <lkqiang>lkq@bt.cn
|
||||
# panelWaf.py
|
||||
# code: 面板基础安全类
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 梁凯强 <1249648969@qq.com>
|
||||
# | Author: lkqiang <lkq@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
# +--------------------------------------------------------------------
|
||||
# | 密码管理
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2019 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
#
|
||||
# ┏┓ ┏┓
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
#+--------------------------------------------------------------------
|
||||
|
||||
+41
-2
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
# --------------------------------
|
||||
@@ -1172,6 +1172,13 @@ def to_string(lites):
|
||||
m_str += chr(mu)
|
||||
return m_str
|
||||
|
||||
#解码
|
||||
def to_ord(string):
|
||||
o = []
|
||||
for s in string:
|
||||
o.append(ord(s))
|
||||
return o
|
||||
|
||||
#xss 防御
|
||||
def xssencode(text):
|
||||
import cgi
|
||||
@@ -1260,7 +1267,7 @@ def write_request_log(reques = None):
|
||||
from flask import request
|
||||
log_data = []
|
||||
log_data.append(getDate())
|
||||
log_data.append(GetClientIp())
|
||||
log_data.append(GetClientIp() + ':' + str(request.environ.get('REMOTE_PORT')))
|
||||
log_data.append(request.method)
|
||||
log_data.append(request.full_path)
|
||||
log_data.append(request.headers.get('User-Agent'))
|
||||
@@ -1684,6 +1691,38 @@ def aes_decrypt(data,key):
|
||||
aes_obj = panelAes.aescrypt_py3(key)
|
||||
return aes_obj.aesdecrypt(data)
|
||||
|
||||
#清理大日志文件
|
||||
def clean_max_log(log_file,max_size = 100,old_line = 100):
|
||||
if not os.path.exists(log_file): return False
|
||||
max_size = 1024 * 1024 * max_size
|
||||
if os.path.getsize(log_file) > max_size:
|
||||
try:
|
||||
old_body = GetNumLines(log_file,old_line)
|
||||
writeFile(log_file,old_body)
|
||||
except:
|
||||
print(get_error_info())
|
||||
|
||||
#获取证书哈希
|
||||
def get_cert_data(path):
|
||||
import panelSSL
|
||||
get = dict_obj()
|
||||
get.certPath = path
|
||||
data = panelSSL.panelSSL().GetCertName(get)
|
||||
return data
|
||||
|
||||
# 获取系统发行版
|
||||
def get_linux_distribution():
|
||||
distribution = 'ubuntu'
|
||||
redhat_file = '/etc/redhat-release'
|
||||
if os.path.exists(redhat_file):
|
||||
try:
|
||||
tmp = readFile(redhat_file).split()[3][0]
|
||||
if int(tmp) > 7:
|
||||
distribution = 'centos8'
|
||||
except:
|
||||
distribution = 'centos7'
|
||||
return distribution
|
||||
|
||||
|
||||
#取通用对象
|
||||
class dict_obj:
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2017 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 梁凯强 <1249648969@qq.com>
|
||||
# | Author: lkqiang <lkq@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
# +--------------------------------------------------------------------
|
||||
# | 宝塔内置消息通道
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 邹浩文 <627622230@qq.com>
|
||||
# | Author: zhwen <zhw@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
import os
|
||||
os.chdir("/www/server/panel")
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2017 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: 邹浩文 <627622230@qq.com>
|
||||
# Author: zhwen <zhw@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2017 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: 黄文良 <287962566@qq.com>
|
||||
# Author: hwliang <hwl@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
|
||||
+24
-14
@@ -4,7 +4,7 @@
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2017 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: 梁凯强 <1249648969@qq.com>
|
||||
# Author: lkqiang <lkq@bt.cn>
|
||||
#-------------------------------------------------------------------
|
||||
# SSH 安全类
|
||||
#------------------------------
|
||||
@@ -15,6 +15,7 @@ class ssh_security:
|
||||
__SSH_CONFIG='/etc/ssh/sshd_config'
|
||||
__ip_data = None
|
||||
__ClIENT_IP='/www/server/panel/data/host_login_ip.json'
|
||||
__pyenv = 'python'
|
||||
__REPAIR={"1":{"id":1,
|
||||
"type":"file",
|
||||
"harm":"High",
|
||||
@@ -88,11 +89,17 @@ class ssh_security:
|
||||
public.WriteFile(self.__ClIENT_IP,json.dumps([]))
|
||||
self.__mail=send_mail.send_mail()
|
||||
self.__mail_config=self.__mail.get_settings()
|
||||
self._check_pyenv()
|
||||
try:
|
||||
self.__ip_data = json.loads(public.ReadFile(self.__ClIENT_IP))
|
||||
except:
|
||||
self.__ip_data=[]
|
||||
|
||||
def _check_pyenv(self):
|
||||
if os.path.exists('/www/server/panel/pyenv'):
|
||||
self.__pyenv = 'btpython'
|
||||
|
||||
|
||||
def check_files(self):
|
||||
try:
|
||||
json.loads(public.ReadFile(self.__ClIENT_IP))
|
||||
@@ -248,27 +255,30 @@ class ssh_security:
|
||||
if not ip:
|
||||
ip = ["127.0.0.1"]
|
||||
if len(ip[0])==0:return False
|
||||
if ip[0] in self.__ip_data:
|
||||
public.WriteLog('SSH security', 'The server {} login IP is {}, login user is root'.format(public.GetLocalIp(),ip[0]))
|
||||
return False
|
||||
else:
|
||||
self.send_mail_data('Server {} login alarm'.format(public.GetLocalIp()),'There is a login alarm on the server {}, the login IP is {}, the login user is root'.format(public.GetLocalIp(),ip[0]))
|
||||
public.WriteLog('SSH security','There is a login alarm on the server {}, the login IP is {}, login user is root'.format(public.GetLocalIp(),ip [0]))
|
||||
return True
|
||||
try:
|
||||
if ip[0] in self.__ip_data:
|
||||
public.WriteLog('SSH security', 'The server {} login IP is {}, login user is root'.format(public.GetLocalIp(),ip[0]))
|
||||
return False
|
||||
else:
|
||||
self.send_mail_data('Server {} login alarm'.format(public.GetLocalIp()),'There is a login alarm on the server {}, the login IP is {}, the login user is root'.format(public.GetLocalIp(),ip[0]))
|
||||
public.WriteLog('SSH security','There is a login alarm on the server {}, the login IP is {}, login user is root'.format(public.GetLocalIp(),ip [0]))
|
||||
return True
|
||||
except:
|
||||
pass
|
||||
|
||||
#开启监控
|
||||
def start_jian(self,get):
|
||||
data=public.ReadFile('/etc/bashrc')
|
||||
if not re.search('python /www/server/panel/class/ssh_security.py',data):
|
||||
public.WriteFile('/etc/bashrc',data.strip()+'\npython /www/server/panel/class/ssh_security.py login\n')
|
||||
if not re.search('{}\/www\/server\/panel\/class\/ssh_security.py'.format(".*python\s+"),data):
|
||||
public.WriteFile('/etc/bashrc',data.strip()+'\n{} /www/server/panel/class/ssh_security.py login\n'.format(self.__pyenv))
|
||||
return public.returnMsg(True, 'Open successfully')
|
||||
return public.returnMsg(False, 'Open failed')
|
||||
|
||||
#关闭监控
|
||||
def stop_jian(self,get):
|
||||
data = public.ReadFile('/etc/bashrc')
|
||||
if re.search('python /www/server/panel/class/ssh_security.py', data):
|
||||
public.WriteFile('/etc/bashrc',data.replace('python /www/server/panel/class/ssh_security.py login',''))
|
||||
if re.search('{}\/www\/server\/panel\/class\/ssh_security.py'.format(".*python\s+"), data):
|
||||
public.WriteFile('/etc/bashrc',re.sub('\n.*python\s+\/www\/server\/panel\/class\/ssh_security.py.*','',data))
|
||||
return public.returnMsg(True, 'Closed successfully')
|
||||
else:
|
||||
return public.returnMsg(True, 'Closed successfully')
|
||||
@@ -276,7 +286,7 @@ class ssh_security:
|
||||
#监控状态
|
||||
def get_jian(self,get):
|
||||
data = public.ReadFile('/etc/bashrc')
|
||||
if re.search('python /www/server/panel/class/ssh_security.py login', data):
|
||||
if re.search('{}\/www\/server\/panel\/class\/ssh_security.py\s+login'.format(".*python\s+"), data):
|
||||
return public.returnMsg(True, '1')
|
||||
else:
|
||||
return public.returnMsg(False, '1')
|
||||
@@ -418,7 +428,7 @@ class ssh_security:
|
||||
act = 'restart'
|
||||
if not os.path.exists('/etc/redhat-release'):
|
||||
public.ExecShell('service ssh ' + act)
|
||||
elif version.find(' 7.') != -1:
|
||||
elif version.find(' 7.') != -1 or version.find(' 8.') != -1:
|
||||
public.ExecShell("systemctl " + act + " sshd.service")
|
||||
else:
|
||||
public.ExecShell("/etc/init.d/sshd " + act)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
try:
|
||||
import paramiko
|
||||
|
||||
+7
-4
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2016 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
import psutil,time,os,public,re,sys
|
||||
try:
|
||||
@@ -228,7 +228,10 @@ class system:
|
||||
return data
|
||||
|
||||
def GetLoadAverage(self,get):
|
||||
c = os.getloadavg()
|
||||
try:
|
||||
c = os.getloadavg()
|
||||
except:
|
||||
c = [0,0,0]
|
||||
data = {};
|
||||
data['one'] = float(c[0]);
|
||||
data['five'] = float(c[1]);
|
||||
@@ -351,8 +354,8 @@ class system:
|
||||
|
||||
def GetDiskInfo2(self):
|
||||
#取磁盘分区信息
|
||||
temp = public.ExecShell("df -hT -P|grep '/'|grep -v tmpfs")[0]
|
||||
tempInodes = public.ExecShell("df -i -P|grep '/'|grep -v tmpfs")[0]
|
||||
temp = public.ExecShell("df -hT -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev")[0]
|
||||
tempInodes = public.ExecShell("df -i -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev")[0]
|
||||
temp1 = temp.split('\n')
|
||||
tempInodes1 = tempInodes.split('\n')
|
||||
diskInfo = []
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
import sys
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2017 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <2879625666@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <2879625666@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http:#bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
import public,os,sys,db,time,json
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
import random, math
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2017 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 梁凯强 <1249648969@qq.com>
|
||||
# | Author: lkqiang <lkq@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
# +--------------------------------------------------------------------
|
||||
# | 宝塔webshell 内置扫描
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2019 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
import os
|
||||
import sys
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
from os import environ
|
||||
from BTPanel import app,sys
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2016 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <2879625666@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: 黄文良 <287962566@qq.com>
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
|
||||
Reference in New Issue
Block a user