Compare commits

...
56 Commits
Author SHA1 Message Date
Mr Chen 411798f4bf Merge pull request #221 from midoks/dev
0.10.0
2022-10-26 23:25:55 +08:00
midoks 2179db5f8b 0.10.0 2022-10-26 23:24:33 +08:00
midoks dcced8c0fb Update crontab_api.py 2022-10-26 22:08:29 +08:00
midoks 3e0e42d8a1 优化 2022-10-26 19:41:51 +08:00
midoks e5355d3e2f Update ftp_client.py 2022-10-26 18:56:57 +08:00
midoks 0a22e25611 Update ftp_client.py 2022-10-26 18:49:05 +08:00
midoks 5f7a3e5bf6 Update index.py 2022-10-26 18:43:48 +08:00
midoks 3518548c61 backup ftp 80% 2022-10-26 17:47:40 +08:00
midoks 08c4b0845d Update crontab_api.py 2022-10-26 11:34:52 +08:00
midoks 8f5fae8e79 Update index.py 2022-10-26 02:50:11 +08:00
midoks a151db1c30 Update install.sh 2022-10-26 02:48:08 +08:00
midoks 628c69ed22 Update index.html 2022-10-26 02:48:05 +08:00
midoks 13bcbc0f3e Update soft.js 2022-10-26 02:47:57 +08:00
midoks c94838462c backup_ftp 50% 2022-10-26 02:42:10 +08:00
midoks a147ef6962 Update centos.sh 2022-10-25 22:06:32 +08:00
midoks 4ccda15933 Update ftp.js 2022-10-25 14:11:49 +08:00
midoks 01074c743d Update pure-ftpd.conf 2022-10-25 14:10:46 +08:00
midoks 0871fa1763 up 2022-10-25 13:51:24 +08:00
midoks aade0ccd98 Update install.sh 2022-10-25 12:28:57 +08:00
midoks 4aed2f91de Update ftp.js 2022-10-25 12:28:49 +08:00
midoks d49dd9f2ac Update install.sh 2022-10-25 03:37:48 +08:00
midoks cff29194f4 Revert "安装优化"
This reverts commit ecbfb2500f.
2022-10-25 03:34:00 +08:00
midoks ecbfb2500f 安装优化 2022-10-25 03:20:35 +08:00
midoks 9c43170d4b Update install.sh 2022-10-25 03:11:06 +08:00
midoks 1239a2807f up 2022-10-25 02:53:19 +08:00
midoks 1c0a130b49 up 2022-10-25 01:43:29 +08:00
midoks ffb1eb34e0 waf 0.2.3 2022-10-25 00:41:27 +08:00
midoks 82874d1f7a Update url_white.json 2022-10-24 23:42:26 +08:00
midoks 4e05f29fcd OP防火墙-0.2.3 2022-10-24 23:12:45 +08:00
midoks d5f3b0d442 初始安装 ipv6 优化 2022-10-24 21:55:44 +08:00
midoks 81eec04037 Update mw.tpl 2022-10-24 21:44:34 +08:00
midoks 5a5dc43e17 Update mw.tpl 2022-10-24 21:38:10 +08:00
midoks b4eb2b3192 Update mw.tpl 2022-10-24 21:20:04 +08:00
midoks 2d1c070e1b Update mw.tpl 2022-10-24 21:16:17 +08:00
midoks 81364fdfa3 Update common.lua 2022-10-24 21:12:41 +08:00
midoks 9d0d88d465 Update init.lua 2022-10-24 20:56:18 +08:00
midoks 7e2eef8bbf Update init.lua 2022-10-24 20:54:41 +08:00
midoks 8d1315e5be Update init.lua 2022-10-24 20:39:07 +08:00
midoks fe6a51540e Update init.lua 2022-10-24 20:38:24 +08:00
midoks 6e35683505 Update init.lua 2022-10-24 20:35:39 +08:00
midoks 713c0d1a3c up 2022-10-24 20:18:34 +08:00
midoks 8323e0ec73 up 2022-10-24 20:06:38 +08:00
midoks 6eae94658f up 2022-10-24 19:55:09 +08:00
midoks 07d173d2cf up 2022-10-24 19:11:48 +08:00
midoks 23f2b9efac Update index.py 2022-10-24 15:14:14 +08:00
midoks 9b2ab9276c Update common.lua 2022-10-24 14:53:54 +08:00
midoks 7903e1a286 Update common.lua 2022-10-24 14:53:39 +08:00
midoks 662e05511f Update common.lua 2022-10-24 14:51:58 +08:00
midoks 1f8785acbc Update init.lua 2022-10-24 14:49:20 +08:00
midoks 3eb87cf953 Update init.lua 2022-10-24 11:57:46 +08:00
midoks 124b24885e Update op_waf.js 2022-10-24 11:23:35 +08:00
midoks 2196983455 Update ip_white.json 2022-10-24 11:22:39 +08:00
midoks 80a67c4f58 Update webstats_log.lua 2022-10-24 11:10:23 +08:00
midoks ff06f7ef91 Update webstats_common.lua 2022-10-24 11:06:35 +08:00
midoks b16506c8bc #211 优化
phpmyadmin安全设置处修改端口保存后当前用修改后的端口能打开,一旦停止phpmyadmin后,再重启phpmyadmin端口又变为888,需要手工再次改变
2022-10-23 14:07:18 +08:00
midoks 2d3801dcc0 up 2022-10-23 13:49:08 +08:00
43 changed files with 1317 additions and 81 deletions
+7 -3
View File
@@ -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安装地址
+1 -1
View File
@@ -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
+1 -1
View File
@@ -15,7 +15,7 @@ from flask import request
class config_api:
__version = '0.9.14'
__version = '0.10.0'
def __init__(self):
pass
+22 -5
View File
@@ -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
View File
@@ -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)
+1 -1
View File
@@ -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()
+418
View File
@@ -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

+101
View File
@@ -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>
+250
View File
@@ -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')
+17
View File
@@ -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"
}
+32
View File
@@ -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
+258
View File
@@ -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
View File
@@ -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)
+1 -1
View File
@@ -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"]
}
+71 -1
View File
@@ -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);
});
+9 -3
View File
@@ -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 -11
View File
@@ -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
View File
@@ -1 +1 @@
[[[127, 0, 0, 2], [127, 0, 0, 255]]]
[[[127, 0, 0, 1], [127, 0, 0, 255]]]
+1
View File
@@ -0,0 +1 @@
[[1,"^/(phpmyadmin)","MySQL[phpMyAdmin]", 0]]
-1
View File
@@ -1 +0,0 @@
^/phpmyadmin_
+2 -2
View File
@@ -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):
+3 -3
View File
@@ -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');
+2 -2
View File
@@ -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):
+3 -3
View File
@@ -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');
+2 -2
View File
@@ -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):
+3 -3
View File
@@ -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');
+3 -2
View File
@@ -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>
+6
View File
@@ -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, '修改成功!')
+11 -1
View File
@@ -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'
+4 -1
View File
@@ -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
+3 -2
View File
@@ -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)
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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"
+22 -4
View File
@@ -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 -11
View File
@@ -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);
}
+1 -1
View File
@@ -132,7 +132,7 @@ def loadLuaSiteFile():
tmp = {
"name": "unset",
"domain": [],
"domains": [],
}
content.append(tmp)
listToLuaFile(lua_site, content)
+1 -1
View File
@@ -1,6 +1,6 @@
{
"sort": 7,
"ps": "[DEV]网站统计报表[此插件-需要小白鼠反馈问题,慎用!]",
"ps": "网站统计报表",
"name": "webstats",
"title": "网站统计",
"shell": "install.sh",
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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)
+9 -1
View File
@@ -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
+2 -1
View File
@@ -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