mirror of
https://github.com/midoks/mdserver-web.git
synced 2026-10-11 11:59:26 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
411798f4bf | ||
|
|
2179db5f8b | ||
|
|
dcced8c0fb | ||
|
|
3e0e42d8a1 | ||
|
|
e5355d3e2f | ||
|
|
0a22e25611 | ||
|
|
5f7a3e5bf6 | ||
|
|
3518548c61 | ||
|
|
08c4b0845d | ||
|
|
8f5fae8e79 | ||
|
|
a151db1c30 | ||
|
|
628c69ed22 | ||
|
|
13bcbc0f3e | ||
|
|
c94838462c | ||
|
|
a147ef6962 | ||
|
|
4ccda15933 | ||
|
|
01074c743d | ||
|
|
0871fa1763 | ||
|
|
aade0ccd98 | ||
|
|
4aed2f91de | ||
|
|
d49dd9f2ac | ||
|
|
cff29194f4 | ||
|
|
ecbfb2500f | ||
|
|
9c43170d4b | ||
|
|
1239a2807f | ||
|
|
1c0a130b49 | ||
|
|
ffb1eb34e0 | ||
|
|
82874d1f7a | ||
|
|
4e05f29fcd | ||
|
|
d5f3b0d442 | ||
|
|
81eec04037 | ||
|
|
5a5dc43e17 | ||
|
|
b4eb2b3192 | ||
|
|
2d1c070e1b | ||
|
|
81364fdfa3 | ||
|
|
9d0d88d465 | ||
|
|
7e2eef8bbf | ||
|
|
8d1315e5be | ||
|
|
fe6a51540e | ||
|
|
6e35683505 | ||
|
|
713c0d1a3c | ||
|
|
8323e0ec73 | ||
|
|
6eae94658f | ||
|
|
07d173d2cf | ||
|
|
23f2b9efac | ||
|
|
9b2ab9276c | ||
|
|
7903e1a286 | ||
|
|
662e05511f | ||
|
|
1f8785acbc | ||
|
|
3eb87cf953 | ||
|
|
124b24885e | ||
|
|
2196983455 | ||
|
|
80a67c4f58 | ||
|
|
ff06f7ef91 | ||
|
|
b16506c8bc | ||
|
|
2d3801dcc0 |
@@ -92,11 +92,15 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
|
||||
```
|
||||
|
||||
|
||||
### 版本更新 0.9.14
|
||||
### 版本更新 0.10.0
|
||||
|
||||
* 优化网站统计插件,提搞速度和并发数。
|
||||
* mysql8安装地址更新。
|
||||
* OP防火墙优化。
|
||||
* OP防火墙-添加URL白名单功能。
|
||||
* 网站统计优化。
|
||||
* 添加`FTP存储空间`插件。
|
||||
* 初始安装IPv6安装。
|
||||
* phpMyAdmin优化。
|
||||
|
||||
|
||||
### JSDelivr安装地址
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ def initInitD():
|
||||
mw.execShell('mkdir -p /etc/init.d')
|
||||
|
||||
# initd
|
||||
if os.path.exists("/etc/init.d"):
|
||||
if os.path.exists('/etc/init.d'):
|
||||
initd_bin = '/etc/init.d/mw'
|
||||
if not os.path.exists(initd_bin):
|
||||
import shutil
|
||||
|
||||
@@ -15,7 +15,7 @@ from flask import request
|
||||
|
||||
class config_api:
|
||||
|
||||
__version = '0.9.14'
|
||||
__version = '0.10.0'
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@@ -68,8 +68,8 @@ class crontab_api:
|
||||
_list[i]['where_hour']), str(_list[i]['where_minute'])))
|
||||
data.append(tmp)
|
||||
|
||||
_ret = {}
|
||||
_ret['data'] = data
|
||||
rdata = {}
|
||||
rdata['data'] = data
|
||||
|
||||
count = mw.M('crontab').where('', ()).count()
|
||||
_page = {}
|
||||
@@ -78,9 +78,17 @@ class crontab_api:
|
||||
_page['row'] = psize
|
||||
_page['tojs'] = "getCronData"
|
||||
|
||||
_ret['list'] = mw.getPage(_page)
|
||||
_ret['p'] = p
|
||||
return mw.getJson(_ret)
|
||||
rdata['list'] = mw.getPage(_page)
|
||||
rdata['p'] = p
|
||||
|
||||
# backup hock
|
||||
bh_file = mw.getPanelDataDir() + "/hook_backup.json"
|
||||
if os.path.exists(bh_file):
|
||||
hb_data = mw.readFile(bh_file)
|
||||
hb_data = json.loads(hb_data)
|
||||
rdata['backup_hook'] = hb_data
|
||||
|
||||
return mw.getJson(rdata)
|
||||
|
||||
# 设置计划任务状态
|
||||
def setCronStatusApi(self):
|
||||
@@ -409,6 +417,15 @@ class crontab_api:
|
||||
shell = param.sFile
|
||||
else:
|
||||
head = "#!/bin/bash\nPATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin\nexport PATH\n"
|
||||
|
||||
source_bin_activate = '''
|
||||
MW_PATH=%s/bin/activate
|
||||
if [ -f $MW_PATH ];then
|
||||
source $MW_PATH
|
||||
fi
|
||||
''' % (mw.getRunDir(),)
|
||||
|
||||
head = head + source_bin_activate + "\n"
|
||||
log = '.log'
|
||||
|
||||
script_dir = mw.getServerDir() + "/mdserver-web/scripts"
|
||||
|
||||
+1
-1
@@ -724,7 +724,7 @@ def checkIp(ip):
|
||||
|
||||
def checkPort(port):
|
||||
# 检查端口是否合法
|
||||
ports = ['21', '25', '7200', '888']
|
||||
ports = ['21', '25', '443', '888']
|
||||
if port in ports:
|
||||
return False
|
||||
intport = int(port)
|
||||
|
||||
@@ -9,7 +9,7 @@ if [ -f bin/activate ];then
|
||||
source bin/activate
|
||||
fi
|
||||
|
||||
# export LC_ALL="en_US.UTF-8"
|
||||
export LC_ALL="en_US.UTF-8"
|
||||
|
||||
|
||||
mw_start_task()
|
||||
|
||||
@@ -0,0 +1,418 @@
|
||||
# coding:utf-8
|
||||
|
||||
'''
|
||||
doc: https://docs.python.org/zh-cn/3/library/ftplib.html
|
||||
'''
|
||||
|
||||
import sys
|
||||
import io
|
||||
import os
|
||||
import time
|
||||
import re
|
||||
import json
|
||||
|
||||
import paramiko
|
||||
import ftplib
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
import mw
|
||||
|
||||
DEBUG = True
|
||||
BLOCK_SIZE = 1024 * 1024 * 2
|
||||
# BLOCK_SIZE = 50
|
||||
PROGRESS_FILE_NAME = "PROGRESS_FILE_NAME"
|
||||
|
||||
"""
|
||||
=============自定义异常===================
|
||||
"""
|
||||
|
||||
|
||||
class OsError(Exception):
|
||||
"""OS端异常"""
|
||||
|
||||
|
||||
class ObjectNotFound(OsError):
|
||||
"""对象不存在时抛出的异常"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
message = "文件对象不存在。"
|
||||
super(ObjectNotFound, self).__init__(message, *args, **kwargs)
|
||||
|
||||
|
||||
class APIError(Exception):
|
||||
"""API参数错误异常"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
_api_error_msg = 'API资料校验失败,请核实!'
|
||||
super(APIError, self).__init__(_api_error_msg, *args, **kwargs)
|
||||
|
||||
|
||||
class FtpPSClient:
|
||||
_title = "FTP"
|
||||
_name = "ftp"
|
||||
__host = None
|
||||
__port = None
|
||||
__user = None
|
||||
__password = None
|
||||
default_port = 21
|
||||
default_backup_path = "/backup/"
|
||||
config_file = "cfg.json"
|
||||
|
||||
def __init__(self, load_config=True, timeout=10):
|
||||
self.timeout = timeout
|
||||
if load_config:
|
||||
data = self.get_config()
|
||||
self.injection_config(data)
|
||||
|
||||
def get_config(self):
|
||||
default_config = {
|
||||
"ftp_host": '',
|
||||
"ftp_user": '',
|
||||
"ftp_pass": '',
|
||||
"backup_path": self.default_backup_path
|
||||
}
|
||||
|
||||
cfg = mw.getServerDir() + "/backup_ftp/" + self.config_file
|
||||
if os.path.exists(cfg):
|
||||
data = mw.readFile(cfg)
|
||||
return json.loads(data)
|
||||
else:
|
||||
return default_config
|
||||
|
||||
def injection_config(self, data):
|
||||
host = data["ftp_host"].strip()
|
||||
if host.find(':') == -1:
|
||||
self.__port = self.default_port
|
||||
|
||||
self.__host = data['ftp_host'].strip()
|
||||
self.__user = data['ftp_user'].strip()
|
||||
self.__password = data['ftp_pass'].strip()
|
||||
bp = data['backup_path'].strip()
|
||||
if bp:
|
||||
self.backup_path = self.getPath(bp)
|
||||
else:
|
||||
self.backup_path = self.getPath(self.default_backup_path)
|
||||
|
||||
def authorize(self):
|
||||
try:
|
||||
if self.timeout is not None:
|
||||
ftp = ftplib.FTP(timeout=self.timeout)
|
||||
else:
|
||||
ftp = ftplib.FTP()
|
||||
|
||||
debuglevel = 0
|
||||
# if DEBUG:
|
||||
# debuglevel = 3
|
||||
ftp.set_debuglevel(debuglevel)
|
||||
# ftp.set_pasv(True)
|
||||
ftp.connect(self.__host, int(self.__port))
|
||||
ftp.login(self.__user, self.__password)
|
||||
return ftp
|
||||
except Exception as e:
|
||||
raise OsError("无法连接FTP客户端,请检查配置参数是否正确!")
|
||||
|
||||
# 取目录路径
|
||||
def getPath(self, path):
|
||||
if path[-1:] != '/':
|
||||
path += '/'
|
||||
if path[:1] != '/':
|
||||
path = '/' + path
|
||||
return path.replace('//', '/')
|
||||
|
||||
def generateDownloadUrl(self, object_name):
|
||||
|
||||
return 'ftp://' + \
|
||||
self.__user + ':' + \
|
||||
self.__password + '@' + \
|
||||
self.__host + ':' + \
|
||||
"/" + object_name
|
||||
|
||||
def buildDirName(self, data_type, file_name):
|
||||
import re
|
||||
prefix_dict = {
|
||||
"site": "web",
|
||||
"database": "db",
|
||||
"path": "path",
|
||||
}
|
||||
file_regx = prefix_dict.get(data_type) + "_(.+)_20\d+_\d+\."
|
||||
sub_search = re.search(file_regx, file_name)
|
||||
sub_path_name = ""
|
||||
if sub_search:
|
||||
sub_path_name = sub_search.groups()[0]
|
||||
sub_path_name += '/'
|
||||
|
||||
# 构建OS存储路径
|
||||
object_name = self.backup_path + \
|
||||
data_type + '/' + \
|
||||
sub_path_name + \
|
||||
file_name
|
||||
return object_name
|
||||
|
||||
def uploadFile(self, filename, data_type=None, *args, **kwargs):
|
||||
|
||||
client = self.authorize()
|
||||
|
||||
local_file_name = filename
|
||||
filename = os.path.abspath(filename)
|
||||
dirname = os.path.dirname(filename)
|
||||
temp_name = os.path.split(filename)[1]
|
||||
|
||||
object_name = self.buildDirName(data_type, temp_name)
|
||||
|
||||
upload_tmp_dir = os.path.join(dirname, ".upload_tmp")
|
||||
if not os.path.exists(upload_tmp_dir):
|
||||
os.mkdir(upload_tmp_dir)
|
||||
|
||||
print("|-正在上传文件到 {}".format(object_name))
|
||||
|
||||
total_bytes = os.path.getsize(filename)
|
||||
object_md5_name = mw.md5(object_name)
|
||||
pg_file = os.path.join(upload_tmp_dir, object_md5_name + ".pl")
|
||||
|
||||
block_size = BLOCK_SIZE
|
||||
if kwargs.get("block_size"):
|
||||
try:
|
||||
block_size = float(kwargs.get("block_size"))
|
||||
except:
|
||||
pass
|
||||
|
||||
remote_file_size = None
|
||||
if not os.path.exists(pg_file):
|
||||
# import uuid
|
||||
# uid = str(uuid.uuid1())
|
||||
progress_info = {
|
||||
"filename": local_file_name,
|
||||
"total_bytes": total_bytes,
|
||||
"uploaded_bytes": 0,
|
||||
}
|
||||
mw.writeFile(pg_file, json.dumps(progress_info))
|
||||
else:
|
||||
progress_info = json.loads(public.readFile(pg_file))
|
||||
if total_bytes == progress_info.get("total_bytes"):
|
||||
# 取远程文件大小
|
||||
_max_loop = 10
|
||||
while _max_loop > 0:
|
||||
try:
|
||||
time.sleep(1)
|
||||
remote_file_size = client.size(object_name)
|
||||
if remote_file_size > total_bytes:
|
||||
remote_file_size = None
|
||||
break
|
||||
except Exception as e:
|
||||
if DEBUG:
|
||||
print(type(e))
|
||||
print(e)
|
||||
_max_loop -= 1
|
||||
else:
|
||||
remote_file_size = None
|
||||
|
||||
uploaded_bytes = 0 if remote_file_size is None else remote_file_size
|
||||
|
||||
dir_name = os.path.split(object_name)[0]
|
||||
if dir_name:
|
||||
self.createDirP(dir_name)
|
||||
|
||||
upload_start = time.time()
|
||||
|
||||
try:
|
||||
if total_bytes > 1024 * 1024 * 1024:
|
||||
with open(local_file_name, 'rb') as file_handler:
|
||||
if remote_file_size is not None:
|
||||
file_handler.seek(remote_file_size)
|
||||
|
||||
client.voidcmd("TYPE I")
|
||||
datasock = ''
|
||||
esize = ''
|
||||
|
||||
datasock, esize = client.ntransfercmd(
|
||||
"STOR " + object_name, remote_file_size)
|
||||
|
||||
while True:
|
||||
buf = file_handler.read(block_size)
|
||||
if not len(buf):
|
||||
break
|
||||
datasock.sendall(buf)
|
||||
uploaded_bytes += len(buf)
|
||||
if DEBUG:
|
||||
print('\ruploading %.2f%%' %
|
||||
(float(uploaded_bytes) / total_bytes * 100))
|
||||
|
||||
print("uploaded_bytes", uploaded_bytes)
|
||||
if uploaded_bytes == total_bytes:
|
||||
break
|
||||
datasock.close()
|
||||
|
||||
if DEBUG:
|
||||
print('close data handle')
|
||||
try:
|
||||
client.voidcmd('NOOP')
|
||||
except Exception as e:
|
||||
if DEBUG:
|
||||
print("Send NOOP command error:")
|
||||
print(e)
|
||||
else:
|
||||
if DEBUG:
|
||||
print('keep alive cmd success')
|
||||
client.voidresp()
|
||||
if DEBUG:
|
||||
print('No loop cmd')
|
||||
else:
|
||||
# 小于1G文件直接上传
|
||||
file_handler = open(local_file_name, "rb")
|
||||
client.storbinary('STOR %s' % object_name,
|
||||
file_handler, blocksize=block_size)
|
||||
file_handler.close()
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
|
||||
completed_file_size = None
|
||||
_max_loop = 10
|
||||
while _max_loop > 0:
|
||||
try:
|
||||
time.sleep(1)
|
||||
completed_file_size = client.size(object_name)
|
||||
break
|
||||
except Exception as e:
|
||||
_max_loop -= 1
|
||||
if DEBUG:
|
||||
print("size error:" + str(e))
|
||||
|
||||
# 上传完成
|
||||
if completed_file_size == total_bytes:
|
||||
if DEBUG:
|
||||
upload_completed = time.time()
|
||||
upload_diff = upload_completed - upload_start
|
||||
print("文件上传成功, 耗时: {}s。".format(upload_diff))
|
||||
if os.path.exists(pg_file):
|
||||
os.remove(pg_file)
|
||||
return True
|
||||
else:
|
||||
if os.path.exists(pg_file):
|
||||
os.remove(pg_file)
|
||||
print("文件上传后大小不一致!")
|
||||
|
||||
print("completed_file_size:" + str(completed_file_size))
|
||||
print("total_bytes:", total_bytes)
|
||||
print("object_md5_name:", object_md5_name)
|
||||
print("pg_file:", pg_file)
|
||||
print("filename:", filename)
|
||||
print("dirname:", dirname)
|
||||
print("object_name:", object_name)
|
||||
return False
|
||||
|
||||
def createDirP(self, dir_name):
|
||||
"""创建远程目录
|
||||
|
||||
:param dir_name: 目录名称
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
dirnames = dir_name.split('/')
|
||||
ftp = self.authorize()
|
||||
# ftp.cwd(get.path);
|
||||
for dirname in dirnames:
|
||||
if not dirname or not dirname.strip():
|
||||
continue
|
||||
try:
|
||||
flist = ftp.nlst()
|
||||
if not dirname in flist:
|
||||
ftp.mkd(dirname)
|
||||
except:
|
||||
# print("mlsd mode.")
|
||||
try:
|
||||
flist = list(ftp.mlsd())[1:]
|
||||
for f in flist:
|
||||
if dirname == f[0]:
|
||||
break
|
||||
else:
|
||||
ftp.mkd(dirname)
|
||||
except:
|
||||
return False
|
||||
ftp.cwd(dirname)
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
def createDir(self, path, name):
|
||||
ftp = self.authorize()
|
||||
path = self.getPath(path)
|
||||
ftp.cwd(path)
|
||||
try:
|
||||
ftp.mkd(name)
|
||||
ftp.close()
|
||||
return True
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
ftp.close()
|
||||
return False
|
||||
|
||||
def deleteDir(self, path, dir_name):
|
||||
try:
|
||||
ftp = self.authorize()
|
||||
ftp.rmd(dir_name)
|
||||
return True
|
||||
except ftplib.error_perm as e:
|
||||
print(str(e) + ":" + dir_name)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return False
|
||||
|
||||
def deleteFile(self, filename):
|
||||
try:
|
||||
ftp = self.authorize()
|
||||
ftp.delete(filename)
|
||||
return True
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
return False
|
||||
|
||||
def getList(self, path="/"):
|
||||
ftp = self.authorize()
|
||||
path = self.getPath(path)
|
||||
ftp.cwd(path)
|
||||
mlsd = False
|
||||
try:
|
||||
files = list(ftp.mlsd())
|
||||
mlsd = True
|
||||
except:
|
||||
try:
|
||||
files = ftp.nlst(path)
|
||||
mlsd = False
|
||||
except:
|
||||
raise RuntimeError("FTP服务器数据返回异常!")
|
||||
ftp.close()
|
||||
# print(files)
|
||||
f_list = []
|
||||
dirs = []
|
||||
data = []
|
||||
default_time = '1971/01/01 01:01:01'
|
||||
for dt in files:
|
||||
# print(dt)
|
||||
if mlsd:
|
||||
dt_name = dt[0]
|
||||
dt_info = dt[1]
|
||||
else:
|
||||
if dt.find("/") >= 0:
|
||||
dt = dt.split("/")[-1]
|
||||
tmp = {}
|
||||
tmp['name'] = dt_name
|
||||
if dt_name == '.' or dt_name == '..':
|
||||
continue
|
||||
|
||||
tmp['time'] = dt_info['modify']
|
||||
try:
|
||||
tmp['size'] = dt_info['size']
|
||||
tmp['type'] = "File"
|
||||
tmp['download'] = self.generateDownloadUrl(path + dt_name)
|
||||
f_list.append(tmp)
|
||||
except:
|
||||
tmp['size'] = dt_info['sizd']
|
||||
tmp['type'] = None
|
||||
tmp['download'] = ''
|
||||
dirs.append(tmp)
|
||||
data = dirs + f_list
|
||||
|
||||
mlist = {}
|
||||
mlist['path'] = path
|
||||
mlist['list'] = data
|
||||
return mlist
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
Executable
+101
@@ -0,0 +1,101 @@
|
||||
<style>
|
||||
.upyunCon {
|
||||
height: 428px;
|
||||
}
|
||||
|
||||
.up-place {
|
||||
height: 62px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.up-place .btn {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.up-place .place-input {
|
||||
background-color: #f3f3f3;
|
||||
border: 1px solid #ccc;
|
||||
height: 30px;
|
||||
line-height: 28px;
|
||||
overflow: hidden;
|
||||
margin: 1px 0 0 -1px;
|
||||
width: 340px;
|
||||
}
|
||||
|
||||
.place-input ul {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.place-input ul li {
|
||||
background: url("/static/img/ico/ico-ltr.png") no-repeat right center;
|
||||
float: left;
|
||||
padding-left: 10px;
|
||||
padding-right: 18px;
|
||||
}
|
||||
|
||||
.place-input ul li a {
|
||||
height: 28px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.upyunlist {
|
||||
height: 516px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.up-bottom {
|
||||
background-color: #fafafa;
|
||||
border-top: 1px solid #eee;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.up-use {
|
||||
line-height: 50px
|
||||
}
|
||||
|
||||
.list-list .cursor span {
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.btn-title {
|
||||
margin-top: 1px
|
||||
}
|
||||
|
||||
.tip {
|
||||
font-size: 10px;
|
||||
font-style: oblique;
|
||||
color: green;
|
||||
}
|
||||
</style>
|
||||
<div class="upyunCon">
|
||||
<div class="up-place pd15">
|
||||
<button id="backBtn" class="btn btn-default btn-sm glyphicon glyphicon-arrow-left pull-left" title="后退"></button>
|
||||
<input id="myPath" style="display:none;" type="text" value="">
|
||||
<div class="place-input pull-left">
|
||||
<div style="width:1400px;height:28px"><ul></ul></div>
|
||||
</div>
|
||||
<button class="refreshBtn btn btn-default btn-sm glyphicon glyphicon-refresh pull-left mr20" title="刷新" style="margin-left:-1px;"></button>
|
||||
<button class="btn btn-default btn-sm pull-right btn-title" onclick="upyunApi()">帐户设置</button>
|
||||
<button class="btn btn-default btn-sm pull-right mr20 btn-title" onclick="createDir()">新建文件夹</button>
|
||||
</div>
|
||||
|
||||
<div class="upyunlist pd15">
|
||||
<div class="divtable" style="margin-bottom:15px">
|
||||
<table class="table table-hover">
|
||||
<thead><tr><th>名称</th><th>大小</th><th>更新时间</th><th class="text-right">操作</th></tr></thead>
|
||||
<tbody class="list-list"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$.getScript( "/plugins/file?name=backup_ftp&f=js/backup_ftp.js", function(){
|
||||
osList('/');
|
||||
});
|
||||
</script>
|
||||
Executable
+250
@@ -0,0 +1,250 @@
|
||||
# coding:utf-8
|
||||
|
||||
import sys
|
||||
import io
|
||||
import os
|
||||
import time
|
||||
import re
|
||||
import json
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
import mw
|
||||
|
||||
_ver = sys.version_info
|
||||
is_py2 = (_ver[0] == 2)
|
||||
is_py3 = (_ver[0] == 3)
|
||||
|
||||
DEBUG = False
|
||||
|
||||
if is_py2:
|
||||
reload(sys)
|
||||
sys.setdefaultencoding('utf-8')
|
||||
|
||||
app_debug = False
|
||||
if mw.isAppleSystem():
|
||||
app_debug = True
|
||||
|
||||
|
||||
def getPluginName():
|
||||
return 'backup_ftp'
|
||||
|
||||
|
||||
def getPluginDir():
|
||||
return mw.getPluginDir() + '/' + getPluginName()
|
||||
|
||||
|
||||
sys.path.append(getPluginDir() + "/class")
|
||||
from ftp_client import FtpPSClient
|
||||
|
||||
|
||||
def getServerDir():
|
||||
return mw.getServerDir() + '/' + getPluginName()
|
||||
|
||||
|
||||
def getArgs():
|
||||
args = sys.argv[2:]
|
||||
tmp = {}
|
||||
args_len = len(args)
|
||||
|
||||
if args_len == 1:
|
||||
t = args[0].strip('{').strip('}')
|
||||
t = t.split(':')
|
||||
tmp[t[0]] = t[1]
|
||||
elif args_len > 1:
|
||||
for i in range(len(args)):
|
||||
t = args[i].split(':')
|
||||
tmp[t[0]] = t[1]
|
||||
|
||||
return tmp
|
||||
|
||||
|
||||
def checkArgs(data, ck=[]):
|
||||
for i in range(len(ck)):
|
||||
if not ck[i] in data:
|
||||
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
|
||||
return (True, mw.returnJson(True, 'ok'))
|
||||
|
||||
|
||||
def status():
|
||||
return 'start'
|
||||
|
||||
|
||||
def getConf():
|
||||
cfg = getServerDir() + "/cfg.json"
|
||||
if not os.path.exists(cfg):
|
||||
return mw.returnJson(False, "未配置", [])
|
||||
data = mw.readFile(cfg)
|
||||
data = json.loads(data)
|
||||
return mw.returnJson(True, "OK", data)
|
||||
|
||||
|
||||
def setConf():
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['use_sftp', 'ftp_user',
|
||||
'ftp_pass', 'ftp_host', 'backup_path'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
cfg = getServerDir() + "/cfg.json"
|
||||
|
||||
values = ['ftp_user',
|
||||
'ftp_pass',
|
||||
'ftp_host']
|
||||
for v in values:
|
||||
if args[v] == '':
|
||||
return mw.returnJson(False, '必填资料不能为空,请核实!', [])
|
||||
|
||||
if args['backup_path'] == '':
|
||||
args['backup_path'] = "/backup"
|
||||
|
||||
try:
|
||||
ftp = FtpPSClient(load_config=False)
|
||||
ftp.injection_config(args)
|
||||
data = ftp.getList("/")
|
||||
if data:
|
||||
mw.writeFile(cfg, mw.getJson(args))
|
||||
return mw.returnJson(True, '设置成功', [])
|
||||
except Exception as e:
|
||||
return mw.returnJson(False, "FTP校验失败,请核实!\n" + str(e), [])
|
||||
|
||||
|
||||
def getList():
|
||||
cfg = getServerDir() + "/cfg.json"
|
||||
if not os.path.exists(cfg):
|
||||
return mw.returnJson(False, "未配置FTP,请点击`账户设置`", [])
|
||||
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['path'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
try:
|
||||
ftp = FtpPSClient()
|
||||
flist = ftp.getList(args['path'])
|
||||
return mw.returnJson(True, "ok", flist)
|
||||
except Exception as e:
|
||||
return mw.returnJson(False, str(e), [])
|
||||
|
||||
|
||||
def createDir():
|
||||
cfg = getServerDir() + "/cfg.json"
|
||||
if not os.path.exists(cfg):
|
||||
return mw.returnJson(False, "未配置FTP,请点击`账户设置`", [])
|
||||
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['path', 'name'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
ftp = FtpPSClient()
|
||||
isok = ftp.createDir(args['path'], args['name'])
|
||||
if isok:
|
||||
return mw.returnJson(True, "创建成功")
|
||||
return mw.returnJson(False, "创建失败")
|
||||
|
||||
|
||||
def deleteDir():
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['dir_name', 'path'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
ftp = FtpPSClient()
|
||||
isok = ftp.deleteDir(args['path'], args['dir_name'])
|
||||
if isok:
|
||||
return mw.returnJson(True, "删除成功")
|
||||
return mw.returnJson(False, "删除失败")
|
||||
|
||||
|
||||
def deleteFile():
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['path', 'filename'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
ftp = FtpPSClient()
|
||||
isok = ftp.deleteFile(args['path'] + "/" + args['filename'])
|
||||
if isok:
|
||||
return mw.returnJson(True, "删除成功")
|
||||
return mw.returnJson(False, "删除失败")
|
||||
|
||||
|
||||
def backupAllFunc(stype):
|
||||
os.chdir(mw.getRunDir())
|
||||
|
||||
name = sys.argv[2]
|
||||
num = sys.argv[3]
|
||||
|
||||
args = stype + " " + name + " " + num
|
||||
|
||||
cmd = 'python3 ' + mw.getRunDir() + '/scripts/backup.py ' + args
|
||||
os.system(cmd)
|
||||
|
||||
# 开始执行上传信息
|
||||
|
||||
prefix_dict = {
|
||||
"site": "web",
|
||||
"database": "db",
|
||||
"path": "path",
|
||||
}
|
||||
|
||||
find_path = mw.getBackupDir() + '/' + stype + '/' + \
|
||||
prefix_dict[stype] + '_' + name
|
||||
|
||||
find_new_file = "ls " + find_path + \
|
||||
"_* | grep tar.gz | cut -d \ -f 1 | awk 'END {print}'"
|
||||
|
||||
filename = mw.execShell(find_new_file)[0].strip()
|
||||
# print("filename:", filename)
|
||||
|
||||
ftp = FtpPSClient()
|
||||
ftp.uploadFile(filename, stype)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def backupSite():
|
||||
# 备份站点
|
||||
pass
|
||||
|
||||
|
||||
def in_array(name, arr=[]):
|
||||
for x in arr:
|
||||
if name == x:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def installPreInspection():
|
||||
return 'ok'
|
||||
|
||||
if __name__ == "__main__":
|
||||
func = sys.argv[1]
|
||||
if func == 'status':
|
||||
print(status())
|
||||
elif func == 'start':
|
||||
print(start())
|
||||
elif func == 'stop':
|
||||
print(stop())
|
||||
elif func == 'restart':
|
||||
print(restart())
|
||||
elif func == 'reload':
|
||||
print(reload())
|
||||
elif func == 'install_pre_inspection':
|
||||
print(installPreInspection())
|
||||
elif func == 'conf':
|
||||
print(getConf())
|
||||
elif func == 'set_config':
|
||||
print(setConf())
|
||||
elif func == "get_list":
|
||||
print(getList())
|
||||
elif func == "create_dir":
|
||||
print(createDir())
|
||||
elif func == "delete_dir":
|
||||
print(deleteDir())
|
||||
elif func == 'delete_file':
|
||||
print(deleteFile())
|
||||
elif in_array(func, ['site', 'database', 'path']):
|
||||
print(backupAllFunc(func))
|
||||
else:
|
||||
print('error')
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"title":"FTP存储空间",
|
||||
"hook":["backup"],
|
||||
"tip":"soft",
|
||||
"name":"backup_ftp",
|
||||
"type":"运行环境",
|
||||
"ps":"将网站或数据库打包备份到FTP存储空间",
|
||||
"versions":["1.0"],
|
||||
"install_pre_inspection":false,
|
||||
"shell":"install.sh",
|
||||
"checks":"server/backup_ftp",
|
||||
"path": "server/backup_ftp",
|
||||
"author":"midoks",
|
||||
"home":"",
|
||||
"date":"2022-10-23",
|
||||
"pid": "4"
|
||||
}
|
||||
Executable
+32
@@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
curPath=`pwd`
|
||||
rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
|
||||
install_tmp=${rootPath}/tmp/mw_install.pl
|
||||
sys_os=`uname`
|
||||
|
||||
|
||||
Install_App()
|
||||
{
|
||||
mkdir -p ${serverPath}/backup_ftp
|
||||
echo "${1}" > ${serverPath}/backup_ftp/version.pl
|
||||
echo '安装完成' > $install_tmp
|
||||
|
||||
}
|
||||
|
||||
Uninstall_App()
|
||||
{
|
||||
rm -rf ${serverPath}/backup_ftp
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
Install_App $2
|
||||
else
|
||||
Uninstall_App $2
|
||||
fi
|
||||
Executable
+258
@@ -0,0 +1,258 @@
|
||||
|
||||
|
||||
function bkfPost(method,args,callback){
|
||||
var _args = null;
|
||||
if (typeof(args) == 'string'){
|
||||
_args = JSON.stringify(toArrayObject(args));
|
||||
} else {
|
||||
_args = JSON.stringify(args);
|
||||
}
|
||||
|
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
|
||||
$.post('/plugins/run', {name:'backup_ftp', func:method, args:_args}, function(data) {
|
||||
layer.close(loadT);
|
||||
if (!data.status){
|
||||
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
|
||||
if(typeof(callback) == 'function'){
|
||||
callback(data);
|
||||
}
|
||||
},'json');
|
||||
}
|
||||
|
||||
function getFtpLocalTime(data){
|
||||
var str = data.slice(0,4)+"/"+data.slice(4,6)+"/"+data.slice(6,8)
|
||||
+ " " + data.slice(8,10)+":"+data.slice(10,12)+":"+data.slice(12,14);
|
||||
return str;
|
||||
}
|
||||
|
||||
// 自定义部分
|
||||
var i = null;
|
||||
//设置API
|
||||
function upyunApi(){
|
||||
|
||||
bkfPost('conf', {}, function(rdata){
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
var token = rdata.data;
|
||||
var check_status = token.use_sftp;
|
||||
var sftp_checked = check_status === "true" ? " checked=\"checked\"" : "";
|
||||
|
||||
if (typeof(token.ftp_host) == 'undefined'){
|
||||
token.ftp_host = '';
|
||||
}
|
||||
|
||||
if (typeof(token.ftp_user) == 'undefined'){
|
||||
token.ftp_user = '';
|
||||
}
|
||||
|
||||
if (typeof(token.ftp_pass) == 'undefined'){
|
||||
token.ftp_pass = '';
|
||||
}
|
||||
|
||||
if (typeof(token.backup_path) == 'undefined'){
|
||||
token.backup_path = '';
|
||||
}
|
||||
|
||||
var apicon = '<div class="bingfa mtb15" style="padding-bottom:0px;">\
|
||||
<p>\
|
||||
<span class="span_tit">使用SFTP:</span>\ <input style="width: 20px; vertical-align:middle;" type="checkbox" name="use_sftp"'+sftp_checked+'> 是否使用SFTP进行数据传输 \
|
||||
</p>\
|
||||
<p>\
|
||||
<span class="span_tit">Host:</span>\
|
||||
<input placeholder="请输入主机地址" style="width: 200px;" type="text" name="upyun_service" value="'+token.ftp_host+'"> *服务器地址,FTP默认端口21, SFTP默认端口22\
|
||||
</p>\
|
||||
<p>\
|
||||
<span class="span_tit">用户名:</span>\
|
||||
<input style="width: 200px;" type="text" name="ftp_username" value="'+token.ftp_user+'"> *指定用户名\
|
||||
</p>\
|
||||
<p>\
|
||||
<span class="span_tit">密码:</span>\
|
||||
<input style="width: 200px;" type="password" name="ftp_password" value="'+token.ftp_pass+'"> *登录密码\
|
||||
</p>\
|
||||
<p>\
|
||||
<span class="span_tit">存储位置:</span>\
|
||||
<input placeholder="请输入存储位置" style="width: 200px;" type="text" name="backup_path" value="'+token.backup_path+'"> *相对于根目录的路径,默认是/backup\
|
||||
</p>\
|
||||
</div>';
|
||||
layer.open({
|
||||
type: 1,
|
||||
area: "600px",
|
||||
title: "FTP/SFTP帐户设置",
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
btn: ['确定','取消'],
|
||||
content:apicon,
|
||||
yes:function(index,layero){
|
||||
var data = {
|
||||
use_sftp:$("input[name='use_sftp']").prop('checked'),
|
||||
ftp_user:$("input[name='ftp_username']").val(),
|
||||
ftp_pass:$("input[name='ftp_password']").val(),
|
||||
ftp_host:$("input[name='upyun_service']").val(),
|
||||
backup_path:$("input[name='backup_path']").val()
|
||||
}
|
||||
bkfPost('set_config', data, function(rdata){
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
if (rdata.status){
|
||||
showMsg(rdata.msg,function(){
|
||||
layer.close(index);
|
||||
osList("/");
|
||||
},{icon:1},2000);
|
||||
} else{
|
||||
layer.msg(rdata.msg,{icon:2});
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function createDir(){
|
||||
layer.open({
|
||||
type: 1,
|
||||
area: "400px",
|
||||
title: "创建目录",
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
btn: ['确定','取消'],
|
||||
content:'<div class="bingfa bt-form c6" style="padding-bottom: 10px;">\
|
||||
<p>\
|
||||
<span class="span_tit">目录名称:</span>\
|
||||
<input style="width: 200px;" type="text" name="newPath" value="">\
|
||||
</p>\
|
||||
</div>',
|
||||
success:function(){
|
||||
$("input[name='newPath']").focus().keyup(function(e){
|
||||
if(e.keyCode == 13) $(".layui-layer-btn0").click();
|
||||
});
|
||||
},
|
||||
yes:function(index,layero){
|
||||
var name = $("input[name='newPath']").val();
|
||||
if(name == ''){
|
||||
layer.msg('目录名称不能为空!',{icon:2});
|
||||
return;
|
||||
}
|
||||
var path = $("#myPath").val();
|
||||
var dirname = name;
|
||||
// var loadT = layer.msg('正在创建目录['+dirname+']...',{icon:16,time:0,shade: [0.3, '#000']});
|
||||
bkfPost('create_dir', {path:path,name:dirname}, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
if(rdata.status) {
|
||||
showMsg(rdata.msg, function(){
|
||||
layer.close(index);
|
||||
osList(path);
|
||||
} ,{icon:1}, 2000);
|
||||
} else{
|
||||
layer.msg(rdata.msg,{icon:2});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//删除文件
|
||||
function deleteFile(name, is_dir){
|
||||
if (is_dir === false){
|
||||
safeMessage('删除文件','删除后将无法恢复,真的要删除['+name+']吗?',function(){
|
||||
var path = $("#myPath").val();
|
||||
var filename = name;
|
||||
bkfPost('delete_file', {filename:filename,path:path}, function(rdata){
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
showMsg(rdata.msg,function(){
|
||||
osList(path);
|
||||
},{icon:rdata.status?1:2},2000);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
safeMessage('删除文件夹','删除后将无法恢复,真的要删除['+name+']吗?',function(){
|
||||
var path = $("#myPath").val();
|
||||
bkfPost('delete_dir', {dir_name:name,path:path}, function(rdata){
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
showMsg(rdata.msg,function(){
|
||||
osList(path);
|
||||
},{icon:rdata.status?1:2},2000);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function osList(path){
|
||||
bkfPost('get_list', {path:path}, function(rdata){
|
||||
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
if(rdata.status === false){
|
||||
showMsg(rdata.msg,function(){
|
||||
upyunApi();
|
||||
},{icon:2},2000);
|
||||
return;
|
||||
}
|
||||
|
||||
var mlist = rdata.data;
|
||||
// console.log(mlist);
|
||||
var listBody = ''
|
||||
var listFiles = ''
|
||||
for(var i=0;i<mlist.list.length;i++){
|
||||
if(mlist.list[i].type == null){
|
||||
listBody += '<tr><td class="cursor" onclick="osList(\''+(path+'/'+mlist.list[i].name).replace('//','/')+'\')"><span class="ico ico-folder"></span>\<span>'+mlist.list[i].name+'</span></td>\
|
||||
<td>-</td>\
|
||||
<td>-</td>\
|
||||
<td class="text-right"><a class="btlink" onclick="deleteFile(\''+mlist.list[i].name+'\', true)">删除</a></td></tr>'
|
||||
}else{
|
||||
listFiles += '<tr><td class="cursor"><span class="ico ico-file"></span>\<span>'+mlist.list[i].name+'</span></td>\
|
||||
<td>'+toSize(mlist.list[i].size)+'</td>\
|
||||
<td>'+getFtpLocalTime(mlist.list[i].time)+'</td>\
|
||||
<td class="text-right"><a target="_blank" href="'+mlist.list[i].download+'" class="btlink">下载</a> | <a class="btlink" onclick="deleteFile(\''+mlist.list[i].name+'\', false)">删除</a></td></tr>'
|
||||
}
|
||||
}
|
||||
listBody += listFiles;
|
||||
|
||||
var pathLi='';
|
||||
var tmp = path.split('/')
|
||||
var pathname = '';
|
||||
var n = 0;
|
||||
for(var i=0;i<tmp.length;i++){
|
||||
if(n > 0 && tmp[i] == '') continue;
|
||||
var dirname = tmp[i];
|
||||
if(dirname == '') {
|
||||
dirname = '根目录';
|
||||
n++;
|
||||
}
|
||||
pathname += '/' + tmp[i];
|
||||
pathname = pathname.replace('//','/');
|
||||
pathLi += '<li><a title="'+pathname+'" onclick="osList(\''+pathname+'\')">'+dirname+'</a></li>';
|
||||
}
|
||||
var um = 1;
|
||||
if(tmp[tmp.length-1] == '') um = 2;
|
||||
var backPath = tmp.slice(0,tmp.length-um).join('/') || '/';
|
||||
$('#myPath').val(path);
|
||||
$(".upyunCon .place-input ul").html(pathLi);
|
||||
$(".upyunlist .list-list").html(listBody);
|
||||
|
||||
upPathLeft();
|
||||
|
||||
$('#backBtn').unbind().click(function() {
|
||||
osList(backPath);
|
||||
});
|
||||
|
||||
$('.upyunCon .refreshBtn').unbind().click(function(){
|
||||
osList(path);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//计算当前目录偏移
|
||||
function upPathLeft(){
|
||||
var UlWidth = $(".place-input ul").width();
|
||||
var SpanPathWidth = $(".place-input").width() - 20;
|
||||
var Ml = UlWidth - SpanPathWidth;
|
||||
if(UlWidth > SpanPathWidth ){
|
||||
$(".place-input ul").css("left",-Ml)
|
||||
}
|
||||
else{
|
||||
$(".place-input ul").css("left",0)
|
||||
}
|
||||
}
|
||||
// $('.layui-layer-page').css('height','670px');
|
||||
+12
-2
@@ -146,7 +146,7 @@ def initSiteInfo():
|
||||
site_contents_new[name] = site_contents[name]
|
||||
else:
|
||||
tmp = {}
|
||||
tmp['cdn'] = False
|
||||
tmp['cdn'] = True
|
||||
tmp['log'] = True
|
||||
tmp['get'] = True
|
||||
tmp['post'] = True
|
||||
@@ -253,6 +253,7 @@ def contentReplace(content):
|
||||
|
||||
|
||||
def autoMakeLuaConfSingle(file):
|
||||
# path = getPluginDir() + "/waf/rule/" + file + ".json"
|
||||
path = getServerDir() + "/waf/rule/" + file + ".json"
|
||||
to_path = getServerDir() + "/waf/conf/rule_" + file + ".lua"
|
||||
content = mw.readFile(path)
|
||||
@@ -280,7 +281,7 @@ def autoMakeLuaHtmlSingle(file):
|
||||
def autoMakeLuaConf():
|
||||
conf_list = ['args', 'cookie', 'ip_black', 'ip_white',
|
||||
'ipv6_black', 'post', 'scan_black', 'url',
|
||||
'user_agent']
|
||||
'url_white', 'user_agent']
|
||||
for x in conf_list:
|
||||
autoMakeLuaConfSingle(x)
|
||||
|
||||
@@ -424,6 +425,15 @@ def restart():
|
||||
def reload():
|
||||
stop()
|
||||
|
||||
path = getServerDir()
|
||||
path_tpl = getPluginDir()
|
||||
|
||||
config = path + "/waf/lua/init.lua"
|
||||
config_tpl = path_tpl + "/waf/lua/init.lua"
|
||||
content = mw.readFile(config_tpl)
|
||||
content = contentReplace(content)
|
||||
mw.writeFile(config, content)
|
||||
|
||||
errlog = mw.getServerDir() + "/openresty/nginx/logs/error.log"
|
||||
mw.execShell('rm -rf ' + errlog)
|
||||
|
||||
|
||||
@@ -11,5 +11,5 @@
|
||||
"home":"https://github.com/loveshell/ngx_lua_waf",
|
||||
"date":"2019-04-21",
|
||||
"pid": "1",
|
||||
"versions": ["0.2.2"]
|
||||
"versions": ["0.2.3"]
|
||||
}
|
||||
@@ -691,6 +691,71 @@ function ipWhite(type) {
|
||||
});
|
||||
}
|
||||
|
||||
//IP白名单
|
||||
function urlWhite(type) {
|
||||
|
||||
var ruleName = "url_white";
|
||||
|
||||
if (type == undefined) {
|
||||
create_l = layer.open({
|
||||
type: 1,
|
||||
title: "管理URL白名单",
|
||||
area: ['700px', '530px'],
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="pd15">\
|
||||
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
|
||||
<input class="bt-input-text" name="ruleValue" type="text" value="" style="width:470px;margin-right:12px;" placeholder="规则内容,请使用正则表达式">\
|
||||
<input class="bt-input-text mr5" name="rulePs" type="text" style="width:120px;" placeholder="描述">\
|
||||
<button class="btn btn-success btn-sm va0 pull-right" onclick="addRule(\''+ ruleName + '\');">添加</button>\</div>\
|
||||
<div class="divtable">\
|
||||
<div id="jc-file-table" class="table_head_fix" style="max-height:300px;overflow:auto;border:#ddd 1px solid">\
|
||||
<table class="table table-hover" style="border:none">\
|
||||
<thead>\
|
||||
<tr>\
|
||||
<th width="360">规则</th>\
|
||||
<th>说明</th>\
|
||||
<th>操作</th>\
|
||||
<th style="text-align: right;">状态</th>\
|
||||
</tr>\
|
||||
</thead>\
|
||||
<tbody id="set_obj_conf_con" class="gztr"></tbody>\
|
||||
</table>\
|
||||
</div>\
|
||||
</div>\
|
||||
<ul class="help-info-text c7 ptb10">\
|
||||
<li style="color:red;">注意:如果您不了解正则表达式,请不要随意修改规则内容</li>\
|
||||
<li>您可以添加或修改规则内容,但请使用正则表达式</li>\
|
||||
<li>内置规则允许修改,但不可以直接删除,您可以设置规则状态来定义防火墙是否使用此规则</li>\
|
||||
</ul></div>'
|
||||
});
|
||||
tableFixed("jc-file-table");
|
||||
}
|
||||
|
||||
getRuleByName(ruleName, function(data){
|
||||
var tmp = $.parseJSON(data.data);
|
||||
var rdata = $.parseJSON(tmp.data);
|
||||
console.log(rdata);
|
||||
var tbody = ''
|
||||
for (var i = 0; i < rdata.length; i++) {
|
||||
var removeRule = ''
|
||||
if (rdata[i][3] != 0) removeRule = ' | <a class="btlink" onclick="removeRule(\'' + ruleName + '\',' + i + ')">删除</a>';
|
||||
tbody += '<tr>\
|
||||
<td class="rule_body_'+ i + '">' + rdata[i][1] + '</td>\
|
||||
<td class="rule_ps_'+ i + '">' + rdata[i][2] + '</td>\
|
||||
<td class="rule_modify_'+ i + '"><a class="btlink" onclick="modifyRule(' + i + ',\'' + ruleName + '\')">编辑</a>' + removeRule + '</td>\
|
||||
<td class="text-right">\
|
||||
<div class="pull-right">\
|
||||
<input class="btswitch btswitch-ios" id="closeua_'+ i + '" type="checkbox" ' + (rdata[i][0] ? 'checked' : '') + '>\
|
||||
<label class="btswitch-btn" style="width:2.0em;height:1.2em;margin-bottom: 0" for="closeua_'+ i + '" onclick="setRuleState(\'' + ruleName + '\',' + i + ')"></label>\
|
||||
</div>\
|
||||
</td>\
|
||||
</tr>'
|
||||
}
|
||||
$("#set_obj_conf_con").html(tbody);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 获取IPV4黑名单
|
||||
function getIpv4Address(callback){
|
||||
@@ -1003,6 +1068,11 @@ function wafGloabl(){
|
||||
<label class="btswitch-btn" for="closescan" onclick="setObjOpen(\'scan\')"></label>\
|
||||
</div></td><td class="text-right"><a class="btlink" onclick="scanRule()">设置</a></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td>URL白名单</td><td>所有规则对URL白名单无效</td><td style="text-align: center;">--</td>\
|
||||
<td style="text-align: center;">--</td>\
|
||||
<td class="text-right"><a class="btlink" onclick="urlWhite()">设置</a></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td>IP白名单</td><td>所有规则对IP白名单无效</td><td style="text-align: center;">--</td>\
|
||||
<td style="text-align: center;">--</td>\
|
||||
@@ -1025,7 +1095,7 @@ function wafGloabl(){
|
||||
|
||||
con += '<div style="width:645px;margin-top:10px;"><ul class="help-info-text c7">\
|
||||
<li>继承: 全局设置将在站点配置中自动继承为默认值</li>\
|
||||
<li>优先级: IP白名单>IP黑名单>URL白名单>URL黑名单>CC防御>禁止国外IP访问>User-Agent>URI过滤>URL参数>Cookie>POST</li>\
|
||||
<li>优先级: IP白名单>IP黑名单>URL白名单>URL黑名单>CC防御>User-Agent>URI过滤>URL参数>Cookie>POST</li>\
|
||||
</ul></div>';
|
||||
$(".soft-man-con").html(con);
|
||||
});
|
||||
|
||||
@@ -76,10 +76,16 @@ function _M.cron(self)
|
||||
|
||||
local db = self:initDB()
|
||||
|
||||
db:exec([[BEGIN TRANSACTION]])
|
||||
|
||||
local stmt2 = db:prepare[[INSERT INTO logs(time, ip, domain, server_name, method, status_code, uri, user_agent, rule_name, reason)
|
||||
VALUES(:time, :ip, :domain, :server_name, :method, :status_code, :uri, :user_agent, :rule_name, :reason)]]
|
||||
|
||||
db:exec([[BEGIN TRANSACTION]])
|
||||
|
||||
if not stmt2 then
|
||||
self:D("waf timer db:prepare fail!:"..tostring(stmt2))
|
||||
return false
|
||||
end
|
||||
|
||||
for i=1,llen do
|
||||
local data, _ = ngx.shared.waf_limit:lpop('waf_limit_logs')
|
||||
@@ -105,7 +111,7 @@ function _M.cron(self)
|
||||
|
||||
local res, err = stmt2:step()
|
||||
if tostring(res) == "5" then
|
||||
self.D("waf the step database connection is busy, so it will be stored later.")
|
||||
self:D("waf the step database connection is busy, so it will be stored later.")
|
||||
return false
|
||||
end
|
||||
stmt2:reset()
|
||||
@@ -522,7 +528,7 @@ function _M.get_sn(self, config_domains)
|
||||
end
|
||||
end
|
||||
end
|
||||
return request_name
|
||||
return "unset"
|
||||
end
|
||||
|
||||
function _M.get_random(self,n)
|
||||
|
||||
@@ -22,6 +22,7 @@ local post_html = require "html_post"
|
||||
local other_html = require "html_other"
|
||||
local user_agent_html = require "html_user_agent"
|
||||
local cc_safe_js_html = require "html_safe_js"
|
||||
local cookie_html = require "html_cookie"
|
||||
|
||||
local args_rules = require "rule_args"
|
||||
local ip_white_rules = require "rule_ip_white"
|
||||
@@ -32,6 +33,7 @@ local user_agent_rules = require "rule_user_agent"
|
||||
local post_rules = require "rule_post"
|
||||
local cookie_rules = require "rule_cookie"
|
||||
local url_rules = require "rule_url"
|
||||
local url_white_rules = require "rule_url_white"
|
||||
|
||||
|
||||
local server_name = string.gsub(C:get_sn(config_domains),'_','.')
|
||||
@@ -42,10 +44,10 @@ local function initParams()
|
||||
data['ip'] = C:get_real_ip(server_name)
|
||||
data['ipn'] = C:arrip(data['ip'])
|
||||
data['request_header'] = ngx.req.get_headers()
|
||||
data['uri'] = ngx.unescape_uri(ngx.var.uri)
|
||||
data['uri'] = tostring(ngx.unescape_uri(ngx.var.uri))
|
||||
data['uri_request_args'] = ngx.req.get_uri_args()
|
||||
data['method'] = ngx.req.get_method()
|
||||
data['request_uri'] = ngx.var.request_uri
|
||||
data['request_uri'] = tostring(ngx.var.request_uri)
|
||||
data['status_code'] = ngx.status
|
||||
data['user_agent'] = data['request_header']['user-agent']
|
||||
data['cookie'] = ngx.var.http_cookie
|
||||
@@ -180,6 +182,13 @@ local function waf_ip_white()
|
||||
return false
|
||||
end
|
||||
|
||||
local function waf_url_white()
|
||||
if C:ngx_match_list(url_white_rules, params['uri']) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function waf_ip_black()
|
||||
-- ipv4 ip black
|
||||
for _,rule in ipairs(ip_black_rules)
|
||||
@@ -207,7 +216,7 @@ local function waf_user_agent()
|
||||
-- if not config['user-agent']['open'] or not C:is_site_config('user-agent') then return false end
|
||||
|
||||
-- C:D("waf_user_agent;user_agent_rules:"..json.encode(user_agent_rules)..",ua:"..tostring(params['request_header']['user-agent']))
|
||||
if C:is_ngx_match_ua(user_agent_rules, params['request_header']['user-agent']) then
|
||||
if C:ngx_match_list(user_agent_rules, params['request_header']['user-agent']) then
|
||||
-- C:D("waf_user_agent........... true")
|
||||
C:write_log('user_agent','regular')
|
||||
C:return_html(config['user-agent']['status'], user_agent_html)
|
||||
@@ -295,16 +304,15 @@ local function is_open_waf_cc_increase()
|
||||
return true
|
||||
end
|
||||
|
||||
if site_config[server_name]['safe_verify']['open'] then
|
||||
return true
|
||||
end
|
||||
|
||||
-- C:D("waf config:"..json.encode(config))
|
||||
if cpu_percent >= config['safe_verify']['cpu'] then
|
||||
return true
|
||||
end
|
||||
|
||||
if cpu_percent >= site_config[server_name]['safe_verify']['cpu'] then
|
||||
return true
|
||||
if site_config[server_name] and site_config[server_name]['safe_verify']['open'] then
|
||||
if cpu_percent >= site_config[server_name]['safe_verify']['cpu'] then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
@@ -440,7 +448,7 @@ local function post_X_Forwarded()
|
||||
if not config['post']['open'] or not C:is_site_config('post') then return false end
|
||||
if params['method'] ~= "POST" then return false end
|
||||
if not params["request_header"]['X-forwarded-For'] then return false end
|
||||
if C:is_ngx_match_list(post_rules, params["request_header"]['X-forwarded-For']) then
|
||||
if C:ngx_match_list(post_rules, params["request_header"]['X-forwarded-For']) then
|
||||
C:write_log('post','regular')
|
||||
C:return_html(config['post']['status'], post_html)
|
||||
return true
|
||||
@@ -467,7 +475,7 @@ end
|
||||
|
||||
local function disable_upload_ext(ext)
|
||||
if not ext then return false end
|
||||
ext = string.lower(ext)
|
||||
local ext = string.lower(ext)
|
||||
if C:is_key(site_config[server_name]['disable_upload_ext'], ext) then
|
||||
C:write_log('upload_ext', '上传扩展名黑名单')
|
||||
C:return_html(config['other']['status'],other_html)
|
||||
@@ -517,6 +525,9 @@ function waf()
|
||||
-- white ip
|
||||
if waf_ip_white() then return true end
|
||||
|
||||
-- url white
|
||||
if waf_url_white() then return true end
|
||||
|
||||
-- black ip
|
||||
if waf_ip_black() then return true end
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
[[[127, 0, 0, 2], [127, 0, 0, 255]]]
|
||||
[[[127, 0, 0, 1], [127, 0, 0, 255]]]
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
[[1,"^/(phpmyadmin)","MySQL[phpMyAdmin]", 0]]
|
||||
@@ -1 +0,0 @@
|
||||
^/phpmyadmin_
|
||||
@@ -537,7 +537,7 @@ def setSessionConf(version):
|
||||
passwd = args['passwd']
|
||||
save_handler = args['save_handler']
|
||||
|
||||
if save_handler != "file":
|
||||
if save_handler != "files":
|
||||
iprep = r"(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})"
|
||||
if not re.search(iprep, ip):
|
||||
return mw.returnJson(False, '请输入正确的IP地址')
|
||||
@@ -605,7 +605,7 @@ def setSessionConf(version):
|
||||
phpini = re.sub('\n;session.save_path = "' + "/var/lib/php/sessions" + '"',
|
||||
'\n;session.save_path = "' + "/var/lib/php/sessions" + '"' + val, phpini)
|
||||
|
||||
if save_handler == "file":
|
||||
if save_handler == "files":
|
||||
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
|
||||
val = r'\nsession.save_path = "' + session_tmp + '"\n'
|
||||
if re.search(rep, phpini):
|
||||
|
||||
@@ -380,7 +380,7 @@ function getSessionConfig(version){
|
||||
}
|
||||
var rdata = rdata.data;
|
||||
|
||||
var cacheList = "<option value='file' " + (rdata.save_handler == "file" ? 'selected' : '') + ">file</option>" +
|
||||
var cacheList = "<option value='files' " + (rdata.save_handler == "files" ? 'selected' : '') + ">files</option>" +
|
||||
"<option value='redis' " + (rdata.save_handler == "redis" ? 'selected' : '') + ">redis</option>" +
|
||||
"<option value='memcache' " + (rdata.save_handler == "memcache" ? 'selected' : '') + ">memcache</option>" +
|
||||
"<option value='memcached' " + (rdata.save_handler == "memcached" ? 'selected' : '') + ">memcached</option>";
|
||||
@@ -405,7 +405,7 @@ function getSessionConfig(version){
|
||||
|
||||
$(".soft-man-con").html(con);
|
||||
|
||||
if (rdata.save_handler == 'file'){
|
||||
if (rdata.save_handler == 'files'){
|
||||
$('input[name="ip"]').attr('disabled','disabled');
|
||||
$('input[name="port"]').attr('disabled','disabled');
|
||||
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
|
||||
@@ -436,7 +436,7 @@ function getSessionConfig(version){
|
||||
$('input[name="port"]').removeAttr('disabled');
|
||||
$('input[name="passwd"]').removeAttr('disabled');
|
||||
break;
|
||||
case 'file':
|
||||
case 'files':
|
||||
$('input[name="ip"]').val("").attr('disabled','disabled');
|
||||
$('input[name="port"]').val("").attr('disabled','disabled');
|
||||
$('input[name="passwd"]').val("").attr('disabled','disabled');
|
||||
|
||||
@@ -539,7 +539,7 @@ def setSessionConf(version):
|
||||
passwd = args['passwd']
|
||||
save_handler = args['save_handler']
|
||||
|
||||
if save_handler != "file":
|
||||
if save_handler != "files":
|
||||
iprep = r"(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})"
|
||||
if not re.search(iprep, ip):
|
||||
return mw.returnJson(False, '请输入正确的IP地址')
|
||||
@@ -607,7 +607,7 @@ def setSessionConf(version):
|
||||
phpini = re.sub('\n;session.save_path = "/tmp"',
|
||||
'\n;session.save_path = "/tmp"' + val, phpini)
|
||||
|
||||
if save_handler == "file":
|
||||
if save_handler == "files":
|
||||
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
|
||||
val = r'\nsession.save_path = "' + session_tmp + '"\n'
|
||||
if re.search(rep, phpini):
|
||||
|
||||
@@ -349,7 +349,7 @@ function getSessionConfig(version){
|
||||
}
|
||||
var rdata = rdata.data;
|
||||
|
||||
var cacheList = "<option value='file' " + (rdata.save_handler == "file" ? 'selected' : '') + ">file</option>" +
|
||||
var cacheList = "<option value='files' " + (rdata.save_handler == "files" ? 'selected' : '') + ">files</option>" +
|
||||
"<option value='redis' " + (rdata.save_handler == "redis" ? 'selected' : '') + ">redis</option>" +
|
||||
"<option value='memcache' " + (rdata.save_handler == "memcache" ? 'selected' : '') + ">memcache</option>" +
|
||||
"<option value='memcached' " + (rdata.save_handler == "memcached" ? 'selected' : '') + ">memcached</option>";
|
||||
@@ -374,7 +374,7 @@ function getSessionConfig(version){
|
||||
|
||||
$(".soft-man-con").html(con);
|
||||
|
||||
if (rdata.save_handler == 'file'){
|
||||
if (rdata.save_handler == 'files'){
|
||||
$('input[name="ip"]').attr('disabled','disabled');
|
||||
$('input[name="port"]').attr('disabled','disabled');
|
||||
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
|
||||
@@ -405,7 +405,7 @@ function getSessionConfig(version){
|
||||
$('input[name="port"]').removeAttr('disabled');
|
||||
$('input[name="passwd"]').removeAttr('disabled');
|
||||
break;
|
||||
case 'file':
|
||||
case 'files':
|
||||
$('input[name="ip"]').val("").attr('disabled','disabled');
|
||||
$('input[name="port"]').val("").attr('disabled','disabled');
|
||||
$('input[name="passwd"]').val("").attr('disabled','disabled');
|
||||
|
||||
@@ -679,7 +679,7 @@ def setSessionConf(version):
|
||||
passwd = args['passwd']
|
||||
save_handler = args['save_handler']
|
||||
|
||||
if save_handler != "file":
|
||||
if save_handler != "files":
|
||||
iprep = r"(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})"
|
||||
if not re.search(iprep, ip):
|
||||
return mw.returnJson(False, '请输入正确的IP地址')
|
||||
@@ -743,7 +743,7 @@ def setSessionConf(version):
|
||||
phpini = re.sub('\n;session.save_path = "' + session_tmp + '"',
|
||||
'\n;session.save_path = "' + session_tmp + '"' + val, phpini)
|
||||
|
||||
if save_handler == "file":
|
||||
if save_handler == "files":
|
||||
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
|
||||
val = r'\nsession.save_path = "' + session_tmp + '"\n'
|
||||
if re.search(rep, phpini):
|
||||
|
||||
@@ -339,7 +339,7 @@ function getSessionConfig(version){
|
||||
}
|
||||
var rdata = rdata.data;
|
||||
|
||||
var cacheList = "<option value='file' " + (rdata.save_handler == "file" ? 'selected' : '') + ">file</option>" +
|
||||
var cacheList = "<option value='files' " + (rdata.save_handler == "files" ? 'selected' : '') + ">files</option>" +
|
||||
"<option value='redis' " + (rdata.save_handler == "redis" ? 'selected' : '') + ">redis</option>" +
|
||||
"<option value='memcache' " + (rdata.save_handler == "memcache" ? 'selected' : '') + ">memcache</option>" +
|
||||
"<option value='memcached' " + (rdata.save_handler == "memcached" ? 'selected' : '') + ">memcached</option>";
|
||||
@@ -364,7 +364,7 @@ function getSessionConfig(version){
|
||||
|
||||
$(".soft-man-con").html(con);
|
||||
|
||||
if (rdata.save_handler == 'file'){
|
||||
if (rdata.save_handler == 'files'){
|
||||
$('input[name="ip"]').attr('disabled','disabled');
|
||||
$('input[name="port"]').attr('disabled','disabled');
|
||||
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
|
||||
@@ -395,7 +395,7 @@ function getSessionConfig(version){
|
||||
$('input[name="port"]').removeAttr('disabled');
|
||||
$('input[name="passwd"]').removeAttr('disabled');
|
||||
break;
|
||||
case 'file':
|
||||
case 'files':
|
||||
$('input[name="ip"]').val("").attr('disabled','disabled');
|
||||
$('input[name="port"]').val("").attr('disabled','disabled');
|
||||
$('input[name="passwd"]').val("").attr('disabled','disabled');
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
$.getScript( "/plugins/file?name=phpmyadmin&f=js/phpmyadmin.js");
|
||||
pluginService('phpmyadmin');
|
||||
$.getScript( "/plugins/file?name=phpmyadmin&f=js/phpmyadmin.js", function(){
|
||||
pluginService('phpmyadmin');
|
||||
});
|
||||
</script>
|
||||
@@ -124,6 +124,10 @@ def contentReplace(content):
|
||||
content = content.replace('{$CHOOSE_DB}', 'MariaDB')
|
||||
content = content.replace('{$CHOOSE_DB_DIR}', 'mariadb')
|
||||
|
||||
port = cfg["port"]
|
||||
rep = 'listen\s*(.*);'
|
||||
content = re.sub(rep, "listen " + port + ';', content)
|
||||
|
||||
return content
|
||||
|
||||
|
||||
@@ -284,6 +288,8 @@ def setPmaPort():
|
||||
rep = 'listen\s*(.*);'
|
||||
content = re.sub(rep, "listen " + port + ';', content)
|
||||
mw.writeFile(file, content)
|
||||
|
||||
setCfg("port", port)
|
||||
mw.restartWeb()
|
||||
return mw.returnJson(True, '修改成功!')
|
||||
|
||||
|
||||
@@ -10,10 +10,20 @@ serverPath=$(dirname "$rootPath")
|
||||
install_tmp=${rootPath}/tmp/mw_install.pl
|
||||
|
||||
|
||||
if [ -f ${rootPath}/bin/activate ];then
|
||||
source ${rootPath}/bin/activate
|
||||
fi
|
||||
|
||||
if [ "$sys_os" == "Darwin" ];then
|
||||
BAK='_bak'
|
||||
else
|
||||
BAK=''
|
||||
fi
|
||||
|
||||
sysName=`uname`
|
||||
echo "use system: ${sysName}"
|
||||
|
||||
if [ ${sysName} == "Darwin" ]; then
|
||||
if [ "${sysName}" == "Darwin" ]; then
|
||||
OSNAME='macos'
|
||||
elif grep -Eqi "CentOS" /etc/issue || grep -Eq "CentOS" /etc/*-release; then
|
||||
OSNAME='centos'
|
||||
|
||||
@@ -25,5 +25,8 @@ AutoRename no
|
||||
AnonymousCantUpload no
|
||||
MaxDiskUsage 99
|
||||
CustomerProof yes
|
||||
PIDFile /var/run/pure-ftpd.pid
|
||||
PassivePortRange 48000 50000
|
||||
PIDFile {$SERVER_PATH}/pureftp/etc/pure-ftpd.pid
|
||||
PureDB {$SERVER_PATH}/pureftp/etc/pureftpd.pdb
|
||||
|
||||
VerboseLog yes
|
||||
@@ -110,8 +110,9 @@ def initDreplace():
|
||||
pureFtpdConfigBak = getServerDir() + "/etc/pure-ftpd.bak.conf"
|
||||
pureFtpdConfigTpl = getPluginDir() + "/conf/pure-ftpd.conf"
|
||||
|
||||
if not os.path.exists(pureFtpdConfigBak):
|
||||
shutil.copyfile(pureFtpdConfig, pureFtpdConfigBak)
|
||||
if not os.path.exists(pureFtpdConfigBak) or not os.path.exists(pureFtpdConfig):
|
||||
if os.path.exists(pureFtpdConfig):
|
||||
shutil.copyfile(pureFtpdConfig, pureFtpdConfigBak)
|
||||
content = mw.readFile(pureFtpdConfigTpl)
|
||||
content = contentReplace(content)
|
||||
mw.writeFile(pureFtpdConfig, content)
|
||||
|
||||
@@ -10,7 +10,7 @@ my ($conffile, @flg) = @ARGV;
|
||||
my $PUREFTPD;
|
||||
-x && ($PUREFTPD=$_, last) for qw(
|
||||
{$SERVER_PATH}/pureftp/sbin/pure-ftpd
|
||||
/www/server/pure-ftpd/sbin/pure-ftpd
|
||||
/www/server/pureftp/sbin/pure-ftpd
|
||||
/www/server/pureftpd/sbin/pure-ftpd
|
||||
/www/server/sbin/pure-ftpd
|
||||
/usr/sbin/pure-ftpd
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
# Pure-FTPd Settings
|
||||
PURE_PERL="{$SERVER_PATH}/pureftp/sbin/pure-config.pl"
|
||||
PURE_CONF="{$SERVER_PATH}/pureftp/etc/pure-ftpd.conf"
|
||||
PURE_PID="/var/run/pure-ftpd.pid"
|
||||
PURE_PID="{$SERVER_PATH}/pureftp/etc/pure-ftpd.pid"
|
||||
RETVAL=0
|
||||
prog="Pure-FTPd"
|
||||
|
||||
|
||||
@@ -53,8 +53,8 @@ Install_pureftp()
|
||||
|
||||
# curl -sSLo pure-ftpd-1.0.49.tar.gz https://download.pureftpd.org/pub/pure-ftpd/releases/pure-ftpd-1.0.49.tar.gz
|
||||
if [ ! -f $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz ];then
|
||||
# wget --no-check-certificate -O $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz $DOWNLOAD
|
||||
curl -sSLo $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz $DOWNLOAD
|
||||
wget --no-check-certificate -O $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz $DOWNLOAD
|
||||
# curl -sSLo $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz $DOWNLOAD
|
||||
fi
|
||||
|
||||
#检测文件是否损坏.
|
||||
@@ -66,7 +66,8 @@ Install_pureftp()
|
||||
else
|
||||
# 重新下载
|
||||
rm -rf $serverPath/source/pureftp/pure-ftpd-${VER}
|
||||
curl -sSLo $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz $DOWNLOAD
|
||||
wget --no-check-certificate -O $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz $DOWNLOAD
|
||||
# curl -sSLo $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz $DOWNLOAD
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -75,7 +76,24 @@ Install_pureftp()
|
||||
fi
|
||||
|
||||
cd $serverPath/source/pureftp/pure-ftpd-${VER} && ./configure --prefix=${serverPath}/pureftp \
|
||||
--with-everything && make && make install && make clean
|
||||
CFLAGS=-O2 \
|
||||
--with-puredb \
|
||||
--with-quotas \
|
||||
--with-cookie \
|
||||
--with-virtualhosts \
|
||||
--with-diraliases \
|
||||
--with-sysquotas \
|
||||
--with-ratios \
|
||||
--with-altlog \
|
||||
--with-paranoidmsg \
|
||||
--with-shadow \
|
||||
--with-welcomemsg \
|
||||
--with-throttling \
|
||||
--with-uploadscript \
|
||||
--with-language=english \
|
||||
--with-rfc2640 \
|
||||
--with-ftpwho \
|
||||
--with-tls && make && make install && make clean
|
||||
|
||||
if [ -d ${serverPath}/pureftp ];then
|
||||
echo "${1}" > ${serverPath}/pureftp/version.pl
|
||||
|
||||
@@ -1,18 +1,8 @@
|
||||
function str2Obj(str){
|
||||
var data = {};
|
||||
kv = str.split('&');
|
||||
for(i in kv){
|
||||
v = kv[i].split('=');
|
||||
data[v[0]] = v[1];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function ftpPost(method,args,callback){
|
||||
|
||||
var _args = null;
|
||||
if (typeof(args) == 'string'){
|
||||
_args = JSON.stringify(str2Obj(args));
|
||||
_args = JSON.stringify(toArrayObject(args));
|
||||
} else {
|
||||
_args = JSON.stringify(args);
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ def loadLuaSiteFile():
|
||||
|
||||
tmp = {
|
||||
"name": "unset",
|
||||
"domain": [],
|
||||
"domains": [],
|
||||
}
|
||||
content.append(tmp)
|
||||
listToLuaFile(lua_site, content)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"sort": 7,
|
||||
"ps": "[DEV]网站统计报表[此插件-需要小白鼠反馈问题,慎用!]",
|
||||
"ps": "网站统计报表",
|
||||
"name": "webstats",
|
||||
"title": "网站统计",
|
||||
"shell": "install.sh",
|
||||
|
||||
@@ -149,7 +149,7 @@ function _M.get_sn(self, input_sn)
|
||||
cache:set(input_sn, v['name'], 86400)
|
||||
return v["name"]
|
||||
end
|
||||
|
||||
-- self:D("get_sn:"..json.encode(v))
|
||||
for _,dst_domain in ipairs(v['domains'])
|
||||
do
|
||||
if input_sn == dst_domain then
|
||||
@@ -423,7 +423,7 @@ function _M.cron(self)
|
||||
-- url统计
|
||||
if local_url_stats then
|
||||
for url_md5,url_val in pairs(local_url_stats) do
|
||||
self:update_statistics_uri( db, url_val["uri"],url_md5, url_val["url_num"], url_val["body_length"])
|
||||
self:update_statistics_uri( db, tostring(url_val["uri"]),url_md5, url_val["url_num"], url_val["body_length"])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -332,7 +332,7 @@ log_by_lua_block {
|
||||
local request_time = C:get_request_time()
|
||||
local client_port = ngx.var.remote_port
|
||||
local real_server_name = input_sn
|
||||
local uri = ngx.var.uri
|
||||
local uri = tostring(ngx.var.uri)
|
||||
local status_code = ngx.status
|
||||
local protocol = ngx.var.server_protocol
|
||||
local request_uri = ngx.var.request_uri
|
||||
|
||||
+8
-4
@@ -42,14 +42,18 @@ class backupTools:
|
||||
|
||||
filename = backup_path + "/web_" + name + "_" + \
|
||||
time.strftime('%Y%m%d_%H%M%S', time.localtime()) + '.tar.gz'
|
||||
mw.execShell("cd " + os.path.dirname(path) + " && tar zcvf '" +
|
||||
filename + "' '" + os.path.basename(path) + "' > /dev/null")
|
||||
|
||||
cmd = "cd " + os.path.dirname(path) + " && tar zcvf '" + \
|
||||
filename + "' '" + os.path.basename(path) + "' > /dev/null"
|
||||
|
||||
# print(cmd)
|
||||
mw.execShell(cmd)
|
||||
|
||||
endDate = time.strftime('%Y/%m/%d %X', time.localtime())
|
||||
|
||||
print(filename)
|
||||
if not os.path.exists(filename):
|
||||
log = "网站[" + name + u"]备份失败!"
|
||||
log = "网站[" + name + "]备份失败!"
|
||||
print("★[" + endDate + "] " + log)
|
||||
print(
|
||||
"----------------------------------------------------------------------------")
|
||||
@@ -60,7 +64,7 @@ class backupTools:
|
||||
sql.table('backup').add('type,name,pid,filename,addtime,size', ('0', os.path.basename(
|
||||
filename), pid, filename, endDate, os.path.getsize(filename)))
|
||||
log = "网站[" + name + "]备份成功,用时[" + str(round(outTime, 2)) + "]秒"
|
||||
mw.writeLog(u'计划任务', log)
|
||||
mw.writeLog('计划任务', log)
|
||||
print("★[" + endDate + "] " + log)
|
||||
print("|---保留最新的[" + count + "]份备份")
|
||||
print("|---文件名:" + filename)
|
||||
|
||||
@@ -243,8 +243,16 @@ case "$1" in
|
||||
elif [ "$v4" != "" ]; then
|
||||
address="MW-Panel-Url: http://$v4:$port$auth_path"
|
||||
elif [ "$v6" != "" ]; then
|
||||
echo 'True' > $mw_path/data/ipv6.pl
|
||||
|
||||
if [ ! -f $mw_path/data/ipv6.pl ];then
|
||||
# Need to restart ipv6 to take effect
|
||||
mw_stop
|
||||
mw_start
|
||||
echo 'True' > $mw_path/data/ipv6.pl
|
||||
fi
|
||||
|
||||
address="MW-Panel-Url: http://[$v6]:$port$auth_path"
|
||||
|
||||
else
|
||||
address="MW-Panel-Url: http://you-network-ip:$port$auth_path"
|
||||
fi
|
||||
|
||||
@@ -101,7 +101,8 @@ yum install -y pcre pcre-devel
|
||||
yum install -y icu libicu-devel
|
||||
yum install -y freetype freetype-devel
|
||||
yum install -y openssl openssl-devel
|
||||
yum install -y graphviz libxml2 libxml2-devel
|
||||
yum install -y libxml2 libxml2-devel
|
||||
yum install -y graphviz
|
||||
yum install -y sqlite-devel
|
||||
yum install -y oniguruma oniguruma-devel
|
||||
yum install -y ImageMagick ImageMagick-devel
|
||||
|
||||
Reference in New Issue
Block a user