Compare commits

...
60 Commits
Author SHA1 Message Date
Mr Chen b6f7334f5e Merge pull request #449 from midoks/dev
0.16.1
2023-09-11 11:52:37 +08:00
midoks 27b77f8570 Update push_notice_msg.py 2023-09-10 23:18:13 +08:00
midoks 3d888961bc Update zip.sh 2023-09-10 22:02:43 +08:00
midoks 5edc4fb713 Update install.sh 2023-09-10 21:33:37 +08:00
midoks 214954b298 Update install.sh 2023-09-10 21:29:29 +08:00
midoks 13b0b2752e Update info.json 2023-09-10 21:23:27 +08:00
midoks a2918e651f Update common.py 2023-09-10 14:26:00 +08:00
midoks 55dd1d7d5a update 2023-09-10 14:06:41 +08:00
midoks df50eceeed update 2023-09-10 14:06:19 +08:00
midoks e1de6dd514 Update install_dev.sh 2023-09-10 14:04:13 +08:00
midoks 08328bbb86 Update install_dev.sh 2023-09-10 14:03:53 +08:00
midoks 6abc5b365b Update README.md 2023-09-10 12:37:34 +08:00
midoks 6cc1279729 update 2023-09-10 12:36:23 +08:00
midoks aeafaa2832 update 2023-09-10 12:25:51 +08:00
midoks e74a511763 Update euler.sh 2023-09-10 12:25:01 +08:00
midoks f86159eeac Update README.md 2023-09-10 12:20:02 +08:00
midoks 8097164475 支持华为欧拉系统 2023-09-10 12:19:14 +08:00
midoks 4ebb44e4c0 Update info.json 2023-09-09 22:32:52 +08:00
midoks 584f93461a update 2023-09-09 12:13:16 +08:00
midoks e21f0a53e5 Update update_dev.sh 2023-09-09 11:57:34 +08:00
midoks 1d31a0eae0 Update update.sh 2023-09-09 11:57:15 +08:00
midoks ded33ed6b4 update 2023-09-09 11:55:40 +08:00
midoks b703758d0e update 2023-09-09 11:37:18 +08:00
midoks 33493ac03c up 2023-09-09 11:35:08 +08:00
midoks 74e63c5bbd Update install.sh 2023-09-09 11:33:38 +08:00
midoks f2d34e5551 Update lib.sh 2023-09-09 11:32:02 +08:00
midoks 89c529f44c Update install_dev.sh 2023-09-09 11:28:53 +08:00
midoks 56b728601b MySQL/MYSQL-YUM/MySQL-APT添加重置master功能。
mysql主从同步数据过期时,可使用此命令
2023-09-07 21:17:56 +08:00
midoks bf1d2daeaa Update push_notice_msg.py 2023-09-07 20:37:46 +08:00
midoks cac45b3732 update 2023-09-07 13:36:54 +08:00
midoks ee498b7094 Update install.sh 2023-09-07 13:04:30 +08:00
midoks 385113fe4d Update push_notice_msg.py 2023-09-07 12:58:53 +08:00
midoks 5dbfc5bd51 Update README.md 2023-09-06 19:34:09 +08:00
midoks b76e0f606a Update install.sh 2023-09-06 19:24:25 +08:00
midoks 047702f26d Update debian.sh 2023-09-06 17:48:40 +08:00
midoks eb219caada Update config_api.py 2023-09-04 18:45:49 +08:00
midoks 78b2046f19 Update README.md 2023-09-04 18:45:10 +08:00
Mr Chen 5fe85730e6 Merge pull request #447 from midoks/dev
0.16.1-提前版,合并不release.
2023-09-04 18:44:41 +08:00
midoks adb72ef33b Update config_api.py 2023-09-04 18:40:39 +08:00
midoks d9c8a46031 Update install.sh 2023-09-04 18:35:12 +08:00
midoks 24f520bdc9 Update install.sh 2023-09-04 18:30:40 +08:00
midoks 7492756997 Update install.sh 2023-09-04 18:23:08 +08:00
midoks 616af16635 Update install.sh 2023-09-04 18:15:53 +08:00
midoks 916d39e205 Update install.sh 2023-09-04 18:15:21 +08:00
midoks 017958b6b0 Update install.sh 2023-09-04 18:07:52 +08:00
midoks d403c4c4ad Update opensuse.sh 2023-09-04 17:43:28 +08:00
midoks 9f1481db07 Update mw_api.py 2023-09-04 13:16:42 +08:00
midoks 47e0ec5fae update 2023-09-04 13:14:08 +08:00
midoks a2377d960e 给防盗链增加禁止空来源 2023-09-04 12:47:12 +08:00
midoks 60f1ce2575 update 2023-09-03 00:16:01 +08:00
midoks 0e368f7157 Update index.py 2023-09-03 00:01:20 +08:00
midoks 3cf5c5b190 Update gdriveclient.py 2023-09-02 23:45:33 +08:00
midoks 4ed07beca3 Update gdriveclient.py 2023-09-02 23:43:30 +08:00
midoks cee9619883 update 2023-09-02 23:30:02 +08:00
midoks 5db4a96fc9 Update install.sh 2023-09-02 23:17:38 +08:00
midoks 2e6b7bf5cd Update install.sh 2023-09-02 23:15:52 +08:00
midoks f404caa763 Update install.sh 2023-09-02 22:59:37 +08:00
midoks 062a518492 gdrive云备份开始测试 2023-09-02 22:47:01 +08:00
midoks 0310cab3ae Update msonedrive.js 2023-09-02 21:06:30 +08:00
midoks 4a0b8df57f Update index.html 2023-09-01 16:28:44 +08:00
50 changed files with 1973 additions and 119 deletions
-1
View File
@@ -163,7 +163,6 @@ plugins/l2tp
plugins/openlitespeed
plugins/tamper_proof
plugins/cryptocurrency_trade
plugins/gdrive
plugins/mtproxy
plugins/zimg
plugins/bk_demo
+8 -14
View File
@@ -10,7 +10,7 @@
简单的Linux面板,感谢BT.CN写出如此好的web管理软件。我一看到,就知道这是我一直想要的页面化管理方式。
复制了后台管理界面,按照自己想要的方式写了一版。
![EulerOS](https://img.shields.io/badge/LINUX-EulerOS-blue?style=for-the-badge&logo=EulerOS)
![Debian](https://img.shields.io/badge/LINUX-Debian-blue?style=for-the-badge&logo=Debian)
![Ubuntu](https://img.shields.io/badge/LINUX-Ubuntu-blue?style=for-the-badge&logo=Ubuntu)
![Fedora](https://img.shields.io/badge/LINUX-Fedora-blue?style=for-the-badge&logo=Fedora)
@@ -100,20 +100,14 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
```
### 版本更新 0.16.0
### 版本更新 0.16.1
yum install -y libargon2-devel
apt install -y libargon2-dev
OP防火墙 - 重载即可
* 增加PHP83。
* 面板日志单独为一页并加入日志审计功能。
* 修复webssh服务器读取问题。
* 站点批量删除修复。
* OP防火墙-修复`自动强制验证`关闭不生效。
* 新增OneDrive备份插件。
* FTP备份优化。
* 给防盗链增加禁止空来源。
* OpenResty安装兼容。
* Debian10安装优化。
* 安装时默认监控开启。
* MySQL/MYSQL-YUM/MySQL-APT添加重置master功能。
* 支持华为欧拉系统。
### JSDelivr安装地址
+13
View File
@@ -32,6 +32,7 @@ from flask import redirect
def init():
initSystemControl()
initDB()
initDBSshPort()
initUserInfo()
@@ -145,10 +146,22 @@ def initInitTask():
api.createCertCron()
def initSystemControl():
path = 'data/default.db'
if os.path.exists(path):
return False
import system_api
sapi = system_api.system_api()
r = sapi.setControl(1, 30)
print(r)
def initUserInfo():
data = mw.M('users').where('id=?', (1,)).getField('password')
if data == '21232f297a57a5a743894a0e4a801fc3':
pwd = mw.getRandomString(8).lower()
file_pw = mw.getRunDir() + '/data/default.pl'
mw.writeFile(file_pw, pwd)
+1 -1
View File
@@ -27,7 +27,7 @@ from flask import request
class config_api:
__version = '0.16.0'
__version = '0.16.1'
__api_addr = 'data/api.json'
def __init__(self):
+36 -8
View File
@@ -1149,8 +1149,9 @@ class site_api:
domains = request.form.get('domains', '')
status = request.form.get('status', '')
name = request.form.get('name', '')
none = request.form.get('none', '')
sid = request.form.get('id', '')
return self.setSecurity(sid, name, fix, domains, status)
return self.setSecurity(sid, name, fix, domains, status, none)
def getLogsApi(self):
siteName = request.form.get('siteName', '')
@@ -2430,9 +2431,28 @@ location ^~ {from} {\n\
tmp = re.search(rep, conf).group()
data['fix'] = re.search(
"\(.+\)\$", tmp).group().replace('(', '').replace(')$', '').replace('|', ',')
data['domains'] = ','.join(re.search(
"valid_referers\s+none\s+blocked\s+(.+);\n", tmp).groups()[0].split())
data['status'] = True
data['status'] = False
data['none'] = False
valid_referers = re.search(
"valid_referers\s+(.+);\n", tmp)
valid_referers_none = re.search(
"valid_referers\s+none\s+blocked\s+(.+);\n", tmp)
if valid_referers or valid_referers_none:
data['status'] = True
if valid_referers_none:
domain_t = valid_referers_none.groups()[0].split()
data['domains'] = ','.join(domain_t)
data['none'] = True
elif valid_referers:
domain_t = valid_referers.groups()[0].split()
data['domains'] = ','.join(domain_t)
data['none'] = False
# print(data)
else:
data['fix'] = 'jpg,jpeg,gif,png,js,css'
domains = mw.M('domain').where(
@@ -2442,19 +2462,27 @@ location ^~ {from} {\n\
tmp.append(domain['name'])
data['domains'] = ','.join(tmp)
data['status'] = False
data['none'] = False
return mw.getJson(data)
def setSecurity(self, sid, name, fix, domains, status):
def setSecurity(self, sid, name, fix, domains, status, none=''):
if len(fix) < 2:
return mw.returnJson(False, 'URL后缀不能为空!')
file = self.getHostConf(name)
if os.path.exists(file):
conf = mw.readFile(file)
if conf.find('SECURITY-START') != -1:
if status == 'false':
rep = "\s{0,4}#SECURITY-START(\n|.){1,500}#SECURITY-END\n?"
conf = re.sub(rep, '', conf)
mw.writeLog('网站管理', '站点[' + name + ']已关闭防盗链设置!')
else:
rep = "\s{0,4}#SECURITY-START(\n|.){1,500}#SECURITY-END\n?"
conf = re.sub(rep, '', conf)
valid_referers = domains.strip().replace(',', ' ')
if none == 'true':
valid_referers = 'none blocked ' + valid_referers
pre_path = self.setupPath + "/php/conf"
re_path = "include\s+" + pre_path + "/enable-php-"
rconf = '''#SECURITY-START 防盗链配置
@@ -2462,13 +2490,13 @@ location ^~ {from} {\n\
{
expires 30d;
access_log /dev/null;
valid_referers none blocked %s;
valid_referers %s;
if ($invalid_referer){
return 404;
}
}
#SECURITY-END
include %s/enable-php-''' % (fix.strip().replace(',', '|'), domains.strip().replace(',', ' '), pre_path)
include %s/enable-php-''' % (fix.strip().replace(',', '|'), valid_referers, pre_path)
conf = re.sub(re_path, rconf, conf)
mw.writeLog('网站管理', '站点[' + name + ']已开启防盗链!')
mw.writeFile(file, conf)
+365
View File
@@ -0,0 +1,365 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import json
import io
sys.path.append(os.getcwd() + "/class/core")
import mw
# -----------------------------
import google.oauth2.credentials
import google_auth_oauthlib.flow
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from googleapiclient.http import MediaFileUpload
from googleapiclient.http import MediaIoBaseDownload
class gdriveclient():
__plugin_dir = ''
__server_dir = ''
__credentials = "/root/credentials.json"
__backup_dir_name = "backup"
__creds = None
__exclude = ""
__scpos = ['https://www.googleapis.com/auth/drive.file']
_title = 'Google Drive'
_name = 'Google Drive'
__debug = False
_DEFAULT_AUTH_PROMPT_MESSAGE = (
'Please visit this URL to authorize this application: {url}')
"""str: The message to display when prompting the user for
authorization."""
_DEFAULT_AUTH_CODE_MESSAGE = (
'Enter the authorization code: ')
"""str: The message to display when prompting the user for the
authorization code. Used only by the console strategy."""
_DEFAULT_WEB_SUCCESS_MESSAGE = (
'The authentication flow has completed, you may close this window.')
def __init__(self, plugin_dir, server_dir):
self.__plugin_dir = plugin_dir
self.__server_dir = server_dir
self.set_creds()
# self.get_exclode()
def setDebug(self, d=False):
self.__debug = d
def D(self, msg=''):
if self.__debug:
print(msg)
# 检查gdrive连接
def _check_connect(self):
try:
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().list(
pageSize=10, fields="nextPageToken, files(id, name)").execute()
results.get('files', [])
except:
return False
return True
# 设置creds
def set_creds(self):
token_file = self.__server_dir + '/token.json'
if os.path.exists(token_file):
with open(token_file, 'rb') as token:
tmp_data = json.load(token)['credentials']
self.__creds = google.oauth2.credentials.Credentials(
tmp_data['token'],
tmp_data['refresh_token'],
tmp_data['id_token'],
tmp_data['token_uri'],
tmp_data['client_id'],
tmp_data['client_secret'],
tmp_data['scopes'])
# if not self._check_connect():
# return False
# else:
# return True
def get_sign_in_url(self):
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
self.__plugin_dir + '/credentials.json',
scopes=self.__scpos)
# flow.redirect_uri = 'https://drive.aapanel.com'
flow.redirect_uri = 'https://drive.aapanel.com'
auth_url, state = flow.authorization_url(
access_type='offline',
prompt='consent',
include_granted_scopes='false')
return auth_url, state
def set_auth_url(self, url):
token_file = self.__server_dir + '/token.json'
if os.path.exists(token_file):
return mw.returnJson(True, "验证成功")
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
self.__plugin_dir + '/credentials.json',
scopes=self.__scpos,
state=url.split('state=')[1].split('&code=')[0])
# flow.redirect_uri = 'https://localhost'
flow.redirect_uri = 'https://drive.aapanel.com'
flow.fetch_token(authorization_response=url)
credentials = flow.credentials
credentials_data = {}
credentials_data['credentials'] = {
'token': credentials.token,
'id_token': credentials.id_token,
'refresh_token': credentials.refresh_token,
'token_uri': credentials.token_uri,
'client_id': credentials.client_id,
'client_secret': credentials.client_secret,
'scopes': credentials.scopes}
with open(token_file, 'w') as token:
json.dump(credentials_data, token)
if not self.set_creds():
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证")
return mw.returnJson(True, "验证成功")
# 获取token
def get_token(self, get):
token_file = self.__server_dir + '/token.json'
import requests
try:
respone = requests.get("https://www.google.com", timeout=2)
except:
return mw.returnJson(False, "连接谷歌失败")
if respone.status_code != 200:
return mw.returnJson(False, "连接谷歌失败")
if not self.set_creds():
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证")
if not os.path.exists(token_file):
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证")
return mw.returnJson(True, "验证成功")
# 获取auth_url
def get_auth_url(self, get):
self.get_sign_in_url()
if os.path.exists("/tmp/auth_url"):
return mw.readFile("/tmp/auth_url")
# 检查连接
def check_connect(self, get):
token_file = self.__server_dir + '/token.json'
if os.path.exists(token_file):
with open(token_file, 'rb') as token:
self.set_creds()
else:
self.D("Failed to get Google token, please verify before use")
return mw.returnJson(True, "Failed to get Google token, please verify before use")
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().list(
pageSize=10, fields="nextPageToken, files(id, name)").execute()
try:
results.get('files', [])
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证")
return mw.returnJson(True, "验证成功")
except:
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证")
def _get_filename(self, filename):
l = filename.split("/")
return l[-1]
def _create_folder_cycle(self, filepath):
l = filepath.split("/")
fid_list = []
for i in l:
if not i:
continue
fid = self.__get_folder_id(i)
if fid:
fid_list.append(fid)
continue
if not fid_list:
fid_list.append("")
fid_list.append(self.create_folder(i, fid_list[-1]))
return fid_list[-1]
def build_object_name(self, data_type, file_name):
"""根据数据类型构建对象存储名称
:param data_type:
:param file_name:
:return:
"""
import re
prefix_dict = {
"site": "web",
"database": "db",
"path": "path",
}
if not prefix_dict.get(data_type):
print("data_type 类型错误!!!")
exit(1)
file_regx = prefix_dict.get(data_type) + "_(.+)_20\d+_\d+\."
sub_search = re.search(file_regx.lower(), file_name)
sub_path_name = ""
if sub_search:
sub_path_name = sub_search.groups()[0]
sub_path_name += '/'
# 构建OS存储路径
object_name = self.__backup_dir_name + \
'/{}/{}'.format(data_type, sub_path_name)
if object_name[:1] == "/":
object_name = object_name[1:]
return object_name
# 上传文件
def upload_file(self, filename, data_type=None):
"""
get.filename 上传后的文件名
get.filepath 上传文件路径
被面板新版计划任务调用时
get表示file_name
:param get:
:return:
"""
# filename = filename
filepath = self.build_object_name(data_type, filename)
_filename = self._get_filename(filename)
self.D(filepath)
self.D(filename)
parents = self._create_folder_cycle(filepath)
self.D(parents)
drive_service = build('drive', 'v3', credentials=self.__creds)
file_metadata = {'name': _filename, 'parents': [parents]}
media = MediaFileUpload(filename, resumable=True)
file = drive_service.files().create(
body=file_metadata, media_body=media, fields='id').execute()
self.D('Upload Success ,File ID: %s' % file.get('id'))
return True
def _get_file_id(self, filename):
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().list(pageSize=10, q="name='{}'".format(
filename), fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
if not items:
return []
else:
for item in items:
return item["id"]
def delete_file(self, filename=None, data_type=None):
file_id = self._get_file_id(filename)
self.delete_file_by_id(file_id)
return True
def delete_file_by_id(self, file_id):
self.D("delete id:{}".format(file_id))
try:
drive_service = build('drive', 'v3', credentials=self.__creds)
drive_service.files().delete(fileId=file_id).execute()
return True
except Exception as e:
return False
# 创建目录
def create_folder(self, folder_name, parents=""):
self.D(self.__creds)
self.D("folder_name: {}".format(folder_name))
self.D("parents: {}".format(parents))
service = build('drive', 'v3', credentials=self.__creds)
file_metadata = {
'name': folder_name,
'mimeType': 'application/vnd.google-apps.folder'
}
if parents:
file_metadata['parents'] = [parents]
folder = service.files().create(body=file_metadata, fields='id').execute()
self.D('Create Folder ID: %s' % folder.get('id'))
return folder.get('id')
def get_rootdir_id(self, folder_name='backup'):
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().list(pageSize=10, q="name='{}' and mimeType='application/vnd.google-apps.folder'".format(folder_name),
fields="nextPageToken, files(id, name,size,parents,webViewLink)").execute()
items = results.get('files', [])
if len(items) == 0:
self.create_folder(folder_name)
return self.get_rootdir_id(folder_name)
return items[0]['parents'][0]
# 获取目录id
def __get_folder_id(self, floder_name):
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().list(pageSize=10, q="name='{}' and mimeType='application/vnd.google-apps.folder'".format(floder_name),
fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
if not items:
return []
else:
for item in items:
return item["id"]
def get_res_info(self, rid):
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().get(fileId='{}'.format(rid)).execute()
return results
def get_id_list(self, driveId=''):
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().list(pageSize=10, driveId="{}".format(driveId),
fields="nextPageToken, files(id, name,size,parents)").execute()
items = results.get('files', [])
return items
def get_list(self, dir_id='', next_page_token=''):
if dir_id == '':
dir_id = self.get_rootdir_id(self.__backup_dir_name)
service = build('drive', 'v3', credentials=self.__creds)
cmd_query = "trashed=false and '{}' in parents".format(dir_id)
results = service.files().list(pageSize=10, q=cmd_query, orderBy='folder asc',
fields="nextPageToken, files(id, name,size,createdTime,parents,webViewLink)").execute()
items = results.get('files', [])
nextPageToken = results.get('nextPageToken', [])
# print(items)
# print(nextPageToken)
return items
def get_exclode(self, exclude=[]):
if not exclude:
tmp_exclude = os.getenv('MW_EXCLUDE')
if tmp_exclude:
exclude = tmp_exclude.split(',')
if not exclude:
return ""
for ex in exclude:
self.__exclude += " --exclude=\"" + ex + "\""
self.__exclude += " "
return self.__exclude
def download_file(self, filename):
file_id = self._get_file_id(filename)
service = build('drive', 'v3', credentials=self.__creds)
request = service.files().get_media(fileId=file_id)
with open('/tmp/{}'.format(filename), 'wb') as fh:
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
print("Download %d%%." % int(status.progress() * 100))
+13
View File
@@ -0,0 +1,13 @@
{
"web": {
"client_id": "226011946234-d3e1vashgag64utjedu1ljt9u39ncrpq.apps.googleusercontent.com",
"project_id": "light-willow-341609",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_secret": "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",
"redirect_uris": [
"https://drive.aapanel.com"
]
}
}
+11
View File
@@ -0,0 +1,11 @@
{
"web": {
"client_id": "540181629246-1horo9i4htamdbhiqar9rcbq33bqe2ob.apps.googleusercontent.com",
"project_id": "plated-inn-369901",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_secret": "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",
"redirect_uris": ["https://drive.aapanel.com"]
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

+310
View File
@@ -0,0 +1,310 @@
<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" type="hidden" value="">
<input id="curPath" type="hidden" 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="authApi()">授权</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>
<style type="text/css">
.check_api {
padding: 20px;
}
.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: 546px;
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
}
.step_item{
clear: both;
}
.step_item .serial_box{
display: inline-block;
clear: both;
}
.step_item .serial{
width: 70px;
height: 30px;
line-height: 30px;
text-align: center;
display: inline-block;
float: left;
}
.step_item .serial span{
display: inline-block;
width: 30px;
height: 30px;
text-align: center;
line-height: 28px;
font-size: 11px;
border-radius: 50%;
color: #20a53a;
border: 2px solid #20a53a;
}
.step_item .serial_title{
margin-bottom: 10px;
font-size: 15px;
line-height: 30px;
color: #666;
}
.step_two_url{
display: inline-block;
overflow: hidden;
width: 380px;
/*text-overflow: ellipsis;*/
white-space: nowrap;
height: 35px;
line-height: 35px;
margin-right: 15px;
border-radius: 2px;
padding: 0 10px;
float: left;
width:360px;
padding-right: 35px;
}
.btn_btlink{
display: inline-block;
padding: 5px 10px;
font-size: 12px;
line-height: 1.5;
border-radius: 3px;
text-align: center;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
border: 1px solid #20a53a;
color: #fff;
background-color: #20a53a;
margin-right:10px;
}
.btn_btlink:hover{
color: #fff;
background-color: #10952a;
border-color: #398439;
}
.btn_btlink a:visited{
color: #fff;
background-color: #10952a;
border-color: #398439;
}
.view_video{
margin-bottom: 10px;
}
.view_video ul li{
line-height: 20px;
font-size: 13px;
}
.setp_one i{
position: absolute;
top: 8px;
left: 25px;
width: 30px;
height: 30px;
}
.google_drive{
width:465px;
height:100px;
margin-bottom:10px;
}
</style>
<script type="text/html" id="check_api">
<div class="check_api">
<div class="step_two">
<div class="step_item">
<div class="serial"><span>1</span></div>
<div class="serial_box">
<div class="serial_title">阅读简易操作教程:如何获取Google Drive授权?</div>
<div class="serial_conter">
<div class="view_video">
<ul>
<li>1. 点击下面第<div class="serial" style="float: none;width: 45px;"><span>2</span></div>步中的 打开授权链接。<li>
<li>2. 在新窗口页面上登录Google Drive账号。阅读授权权限,并同意。<li>
<li>3. 页面跳转后,将浏览器的地址栏地址复制到第<div class="serial" style="float: none;width: 45px;"><span>3</span></div>步的文本框中。<li>
<li>4. 点击 获取授权,随即完成授权。<li>
</ul>
</div>
<hr/>
</div>
</div>
</div>
<div class="step_item pb15">
<div class="serial"><span>2</span></div>
<div class="serial_box">
<div class="serial_title">操作1:👇打开授权链接,根据网页提示对插件进行授权。</div>
<div class="serial_conter step_two" style="width: 500px;">
<input class="bt-input-text mr5 step_two_url" type="text" disabled>
<span class="ico-copy mr10" data-copy="" style="vertical-align: middle;cursor: pointer;margin-left: -37px;margin-right: 20px;"></span>
<a href="" class="btn_btlink open_btlink" target="_blank" style="padding: 7px 10px;">打开授权链接</a>
</div>
</div>
</div>
<div class="step_item">
<div class="serial"><span>3</span></div>
<div class="serial_box">
<div class="serial_title">操作2:复制回浏览器跳转后的地址:</div>
<div class="serial_conter">
<textarea row="3" placeholder="验证URL地址" class="bt-input-text google_drive" style="resize: none;"/></br>
<button type="button" class="btn btn-success btn-sm set_auth_btn">获取授权</button>
</div>
</div>
</div>
</div>
</div>
</script>
<script type="text/javascript" src="/plugins/file?name=gdrive&f=js/gdrive.js"></script>
<script type="text/javascript">
$.getScript( "/plugins/file?name=gdrive&f=js/gdrive.js", function(){
gdList('');
});
</script>
+338
View File
@@ -0,0 +1,338 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import json
# print(sys.platform)
if sys.platform != "darwin":
os.chdir("/www/server/mdserver-web")
sys.path.append(os.getcwd() + "/class/core")
import mw
import db
_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 'gdrive'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def in_array(name, arr=[]):
for x in arr:
if name == x:
return True
return False
sys.path.append(getPluginDir() + "/class")
from gdriveclient import gdriveclient
gd = gdriveclient(getPluginDir(), getServerDir())
gd.setDebug(False)
def getArgs():
args = sys.argv[2:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
if t.strip() == '':
tmp = []
else:
t = t.split(':', 1)
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':', 1)
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 isAuthApi():
cfg = getServerDir() + "/token.json"
if os.path.exists(cfg):
return True
return False
def getConf():
if not isAuthApi():
sign_in_url, state = gd.get_sign_in_url()
return mw.returnJson(False, "未授权!", {'auth_url': sign_in_url})
return mw.returnJson(True, "OK")
def setAuthUrl():
args = getArgs()
data = checkArgs(args, ['url'])
if not data[0]:
return data[1]
url = args['url']
try:
if url.startswith("http://"):
url = url.replace("http://", "https://")
token = gd.set_auth_url(url)
# gd.store_token(token)
# gd.store_user()
return mw.returnJson(True, "授权成功!")
except Exception as e:
return mw.returnJson(False, "授权失败2!:" + str(e))
return mw.returnJson(False, "授权失败!:" + str(e))
def clearAuth():
token = getServerDir() + "/token.json"
if os.path.exists(token):
os.remove(token)
return mw.returnJson(True, "清空授权成功!")
def getList():
if not isAuthApi():
return mw.returnJson(False, "未配置,请点击`授权`", [])
args = getArgs()
data = checkArgs(args, ['file_id'])
if not data[0]:
return data[1]
try:
flist = gd.get_list(args['file_id'])
return mw.returnJson(True, "ok", flist)
except Exception as e:
return mw.returnJson(False, str(e), [])
def createDir():
if not isAuthApi():
return mw.returnJson(False, "未配置,请点击`授权`", [])
args = getArgs()
data = checkArgs(args, ['parents', 'name'])
if not data[0]:
return data[1]
isok = gd.create_folder(args['name'], args['parents'])
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]
isok = gd.delete_file_by_id(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]
isok = gd.delete_file(args['filename'])
if isok:
return mw.returnJson(True, "删除成功")
return mw.returnJson(False, "删除失败")
def findPathName(path, filename):
f = os.scandir(path)
l = []
for ff in f:
t = {}
if ff.name.find(filename) > -1:
t['filename'] = path + '/' + ff.name
l.append(t)
return l
def backupAllFunc(stype):
if not isAuthApi():
mw.echoInfo("未授权API,无法使用!!!")
return ''
os.chdir(mw.getRunDir())
backup_dir = mw.getBackupDir()
run_dir = mw.getRunDir()
stype = sys.argv[1]
name = sys.argv[2]
num = sys.argv[3]
prefix_dict = {
"site": "web",
"database": "db",
"path": "path",
}
backups = []
sql = db.Sql()
# print("stype:", stype)
# 提前获取-清理多余备份
if stype == 'site':
pid = sql.table('sites').where('name=?', (name,)).getField('id')
backups = sql.table('backup').where(
'type=? and pid=?', ('0', pid)).field('id,filename').select()
if stype == 'database':
db_path = mw.getServerDir() + '/mysql'
pid = mw.M('databases').dbPos(db_path, 'mysql').where(
'name=?', (name,)).getField('id')
backups = sql.table('backup').where(
'type=? and pid=?', ('1', pid)).field('id,filename').select()
if stype == 'path':
backup_path = backup_dir + '/path'
_name = 'path_{}'.format(os.path.basename(name))
backups = findPathName(backup_path, _name)
# 其他类型关系性数据库(mysql类的)
if stype.find('database_') > -1:
plugin_name = stype.replace('database_', '')
db_path = mw.getServerDir() + '/' + plugin_name
pid = mw.M('databases').dbPos(db_path, 'mysql').where(
'name=?', (name,)).getField('id')
backups = sql.table('backup').where(
'type=? and pid=?', ('1', pid)).field('id,filename').select()
args = stype + " " + name + " " + num
cmd = 'python3 ' + run_dir + '/scripts/backup.py ' + args
if stype.find('database_') > -1:
plugin_name = stype.replace('database_', '')
args = "database " + name + " " + num
cmd = 'python3 ' + run_dir + '/plugins/' + \
plugin_name + '/scripts/backup.py ' + args
if stype == 'path':
name = os.path.basename(name)
# print("cmd:", cmd)
os.system(cmd)
# 开始执行上传信息.
if stype.find('database_') > -1:
bk_name = 'database'
plugin_name = stype.replace('database_', '')
bk_prefix = plugin_name + '/db'
stype = 'database'
else:
bk_prefix = prefix_dict[stype]
bk_name = stype
find_path = backup_dir + '/' + bk_name + '/' + bk_prefix + '_' + name
find_new_file = "ls " + find_path + \
"_* | grep '.gz' | cut -d \ -f 1 | awk 'END {print}'"
# print(find_new_file)
filename = mw.execShell(find_new_file)[0].strip()
if filename == "":
mw.echoInfo("not find upload file!")
return False
mw.echoInfo("准备上传文件 {}".format(filename))
mw.echoStart('开始上传')
# gd.setDebug(False)
gd.upload_file(filename, stype)
mw.echoEnd('上传成功')
# print(backups)
backups = sorted(backups, key=lambda x: x['filename'], reverse=False)
mw.echoStart('开始删除远程备份')
num = int(num)
sep = len(backups) - num
if sep > -1:
for backup in backups:
fn = os.path.basename(backup['filename'])
gd.delete_file(fn, stype)
mw.echoInfo("---已清理远程过期备份文件:" + fn)
sep -= 1
if sep < 0:
break
mw.echoEnd('结束删除远程备份')
return ''
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_auth_url':
print(setAuthUrl())
elif func == 'clear_auth':
print(clearAuth())
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']) or func.find('database_') > -1:
print(backupAllFunc(func))
else:
print('error')
+19
View File
@@ -0,0 +1,19 @@
{
"hook":["backup"],
"id":998,
"title":"谷歌云网盘",
"tip":"lib",
"name":"gdrive",
"type":"扩展",
"ps":"备份你的数据到谷歌云网盘",
"versions":"2.0",
"shell":"install.sh",
"checks": "server/gdrive",
"path":"server/gdrive",
"author":"google",
"home":"https://drive.google.com/",
"api_doc":"https://developers.google.com/drive/api/guides/about-sdk?hl=zh_CN",
"api_doc2":"https://developers.google.cn/drive/api/reference/rest/v3/comments/list?hl=zh-cn",
"date":"2022-06-26",
"pid":"4"
}
+87
View File
@@ -0,0 +1,87 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# cd /www/server/mdserver-web/plugins/gdrive && /bin/bash install.sh install 2.0
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
PATH=$PATH:${rootPath}/bin
export PATH
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
VERSION=$2
Install_App()
{
tmp_ping=`ping -c 1 google.com 2>&1`
echo $tmp_ping
if [ $? -eq 0 ];then
tmp=`python -V 2>&1|awk '{print $2}'`
pVersion=${tmp:0:3}
which pip
if [ "$?" -eq "0" ];then
tmp=$(pip list|grep google-api-python-client|awk '{print $2}')
if [ "$tmp" != '2.39.0' ];then
pip install --upgrade google-api-python-client
# pip uninstall google-api-python-client -y
pip install -I google-api-python-client==2.39.0 -i https://pypi.Python.org/simple
fi
tmp=$(pip list|grep google-auth-httplib2|awk '{print $2}')
if [ "$tmp" != '0.1.0' ];then
pip uninstall google-auth-httplib2 -y
pip install -I google-auth-httplib2==0.1.0 -i https://pypi.Python.org/simple
fi
tmp=$(pip list|grep google-auth-oauthlib|awk '{print $2}')
if [ "$tmp" != '0.5.0' ];then
# pip uninstall google-auth-oauthlib -y
pip install -I google-auth-oauthlib==0.5.0 -i https://pypi.Python.org/simple
fi
tmp=$(pip list|grep -E '^httplib2'|awk '{print $2}')
if [ "$tmp" != '0.18.1' ];then
# pip uninstall httplib2 -y
pip install -I httplib2==0.18.1 -i https://pypi.Python.org/simple
fi
else
pip install -I pyOpenSSL
pip install -I google-api-python-client==2.39.0 google-auth-httplib2==0.1.0 google-auth-oauthlib==0.5.0 -i https://pypi.Python.org/simple
pip install -I httplib2==0.18.1 -i https://pypi.Python.org/simple
fi
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/gdrive
echo "${VERSION}" > $serverPath/gdrive/version.pl
echo '安装完成' > $install_tmp
else
echo '服务器连接不上谷歌云!安装失败!' > $install_tmp
exit 1
fi
}
Uninstall_App()
{
rm -rf $serverPath/gdrive
echo '卸载完成' > $install_tmp
}
action=$1
type=$2
echo $action $type
if [ "${action}" == 'install' ];then
Install_App
else
Uninstall_App
fi
+260
View File
@@ -0,0 +1,260 @@
function gdPost(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:'gdrive', 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 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 parents = $("#myPath").val();
var cur_file_id = $('#curPath').val();
if (cur_file_id!=''){
parents = cur_file_id;
}
var dirname = name;
var loadT = layer.msg('正在创建目录['+dirname+']...',{icon:16,time:0,shade: [0.3, '#000']});
gdPost('create_dir', {parents:parents,name:dirname}, function(data){
layer.close(loadT);
var rdata = $.parseJSON(data.data);
if(rdata.status) {
showMsg(rdata.msg, function(){
layer.close(index);
var file_id = $('#myPath').val();
if (cur_file_id!=''){
file_id = cur_file_id;
}
gdList(file_id);
} ,{icon:1}, 2000);
} else{
layer.msg(rdata.msg,{icon:2});
}
});
}
});
}
//设置API
function authApi(){
gdPost('conf', {}, function(rdata){
var rdata = $.parseJSON(rdata.data);
// console.log(rdata);
// console.log(rdata.data.auth_url);
var apicon = '';
if (rdata.status){
var html = '';
html += '<button id="clear_auth" onclick="clearAuth();" class="btn btn-default btn-sm">清空配置</button>';
var loadOpen = layer.open({
type: 1,
title: '已授权',
area: '240px',
content:'<div class="change-default pd20">'+html+'</div>',
success: function(){
$('#clear_auth').click(function(){
gdPost('clear_auth', {}, function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg,function(){
layer.close(loadOpen);
gdList('');
},{icon:rdata.status?1:2},2000);
});
});
}
});
return true;
} else{
apicon = '<div class="new_form">'+$("#check_api").html()+'</div>';
}
var layer_auth = layer.open({
type: 1,
area: "620px",
title: "Google Drive 授权",
closeBtn: 1,
shift: 5,
shadeClose: false,
content:apicon,
success:function(layero,index){
// console.log(layero,index);
if (!rdata.status){
$('.check_api .step_two_url').val(rdata.data['auth_url']);
$('.check_api .open_btlink').attr('href',rdata.data['auth_url']);
$('.check_api .ico-copy').click(function(){
copyPass(rdata.data['auth_url']);
});
$('.check_api .set_auth_btn').click(function(){
var url = $('.check_api .google_drive').val();
if ( url == ''){
layer.msg("验证URL不能为空",{icon:2});
return;
}
// console.log(url);
gdPost('set_auth_url', {url:url}, function(rdata){
var rdata = $.parseJSON(rdata.data);
var show_time = 2000;
if (!rdata.status){
show_time = 10000;
}
showMsg(rdata.msg,function(){
if (rdata.status){
layer.close(layer_auth);
gdList('');
}
},{icon:rdata.status?1:2},show_time);
});
});
}
}
});
});
}
//计算当前目录偏移
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)
}
}
function getGDTime(a) {
return new Date(a).format("yyyy/MM/dd hh:mm:ss")
}
function gdList(file_id){
$('#curPath').val(file_id);
gdPost('get_list', {file_id:file_id}, function(rdata){
var rdata = $.parseJSON(rdata.data);
console.log(rdata);
if(rdata.status === false){
showMsg(rdata.msg,function(){
authApi();
},{icon:2},2000);
return;
}
var mlist = rdata.data;
var listBody = '';
var listFiles = '';
for(var i=0;i<mlist.length;i++){
if(mlist[i].size == null){
listFiles += '<tr><td class="cursor" onclick="gdList(\''+(mlist[i].id).replace('//','/')+'\')"><span class="ico ico-folder"></span>\<span>'+mlist[i].name+'</span></td>\
<td>-</td>\
<td>-</td>\
<td class="text-right"><a class="btlink" onclick="deleteFile(\''+mlist[i].id+'\', true)">删除</a></td></tr>'
}else{
listFiles += '<tr><td class="cursor"><span class="ico ico-file"></span><span>'+mlist[i].name+'</span></td>\
<td>'+toSize(mlist[i].size)+'</td>\
<td>'+getGDTime(mlist[i].createdTime)+'</td>\
<td class="text-right"><a target="_blank" href="'+mlist[i].webViewLink+'" class="btlink">下载</a> | <a class="btlink" onclick="deleteFile(\''+mlist[i].name+'\', false)">删除</a></td></tr>'
}
}
listBody += listFiles;
var pathLi = '<li><a title="根目录" onclick="gdList(\'\')">根目录</a></li>';
if (mlist.length>0){
$('#myPath').val(mlist[0]['parents'][0]);
}
$(".upyunCon .place-input ul").html(pathLi);
$(".upyunlist .list-list").html(listBody);
$('#backBtn').unbind().click(function() {
gdList('');
});
$('.upyunCon .refreshBtn').unbind().click(function(){
var file_id = $('#myPath').val();
gdList(file_id);
});
});
}
//删除文件
function deleteFile(name, is_dir){
if (is_dir === false){
safeMessage('删除文件','删除后将无法恢复,真的要删除['+name+']吗?',function(){
var path = $("#myPath").val();
var filename = name;
gdPost('delete_file', {filename:filename,path:path}, function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg,function(){
var file_id = $('#myPath').val();
gdList(file_id);
},{icon:rdata.status?1:2},2000);
});
});
} else {
safeMessage('删除文件夹','删除后将无法恢复,真的要删除文件资源['+name+']吗?',function(){
var path = $("#myPath").val();
gdPost('delete_dir', {dir_name:name,path:path}, function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg,function(){
var file_id = $('#myPath').val();
gdList(file_id);
},{icon:rdata.status?1:2},2000);
});
});
}
}
+113
View File
@@ -0,0 +1,113 @@
#!/usr/bin/python
# coding: utf-8
# python3 plugins/gdrive/t/test.py
# https://console.cloud.google.com/apis/credentials/consent?project=plated-inn-369901
# https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=226011946234-d3e1vashgag64utjedu1ljt9u39ncrpq.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fdrive.aapanel.com&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.file&state=I2da4aZUwqgmikrgrqAwwSjyoEHVs1&access_type=offline&prompt=consent&include_granted_scopes=false
# https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/Overview/appId/08125e6b-6502-4ac9-9548-ad682f00848d/objectId/62b1d655-9828-47ed-be99-65eb18c3a929/isMSAApp~/false/defaultBlade/Overview/appSignInAudience/AzureADandPersonalMicrosoftAccount/servicePrincipalCreated~/true
# 0WA8Q~sZkZFZKv50ryP4ux~.fpVtbHw7BuTZmbQB
# client_id:d9878fac-8526-4ff6-8036-e1c92dd9dd80
# 08125e6b-6502-4ac9-9548-ad682f00848d
# /drive/v2internal/files?openDrive=false&reason=102&syncType=0&errorRecovery=false&q=trashed = false and '1-z6gUXseXmlxmntvkLzOe_tYFT5tdhM9' in parents&fields=kind,nextPageToken,items(kind,modifiedDate,hasVisitorPermissions,containsUnsubscribedChildren,modifiedByMeDate,lastViewedByMeDate,alternateLink,fileSize,owners(kind,permissionId,emailAddressFromAccount,id),lastModifyingUser(kind,permissionId,emailAddressFromAccount,id),customerId,ancestorHasAugmentedPermissions,hasThumbnail,thumbnailVersion,title,id,resourceKey,abuseIsAppealable,abuseNoticeReason,shared,accessRequestsCount,sharedWithMeDate,userPermission(role),explicitlyTrashed,mimeType,quotaBytesUsed,copyable,subscribed,folderColor,hasChildFolders,fileExtension,primarySyncParentId,sharingUser(kind,permissionId,emailAddressFromAccount,id),flaggedForAbuse,folderFeatures,spaces,sourceAppId,recency,recencyReason,version,actionItems,teamDriveId,hasAugmentedPermissions,createdDate,primaryDomainName,organizationDisplayName,passivelySubscribed,trashingUser(kind,permissionId,emailAddressFromAccount,id),trashedDate,parents(id),capabilities(canMoveItemIntoTeamDrive,canUntrash,canModifyContentRestriction,canMoveItemWithinTeamDrive,canMoveItemOutOfTeamDrive,canDeleteChildren,canTrashChildren,canRequestApproval,canReadCategoryMetadata,canEditCategoryMetadata,canAddMyDriveParent,canRemoveMyDriveParent,canShareChildFiles,canShareChildFolders,canRead,canMoveItemWithinDrive,canMoveChildrenWithinDrive,canAddFolderFromAnotherDrive,canChangeSecurityUpdateEnabled,canBlockOwner,canReportSpamOrAbuse,canCopy,canDownload,canEdit,canAddChildren,canDelete,canRemoveChildren,canShare,canTrash,canRename,canReadTeamDrive,canMoveTeamDriveItem),contentRestrictions(readOnly),approvalMetadata(approvalVersion,approvalSummaries,hasIncomingApproval),shortcutDetails(targetId,targetMimeType,targetLookupStatus,targetFile,canRequestAccessToTarget),spamMetadata(markedAsSpamDate,inSpamView),labels(starred,trashed,restricted,viewed)),incompleteSearch&appDataFilter=NO_APP_DATA&spaces=drive&maxResults=200&supportsTeamDrives=true&includeItemsFromAllDrives=true&corpora=default&orderBy=folder,title_natural asc&retryCount=0&key=AIzaSyD_InbmSFufIEps5UAt2NmB_3LvBH3Sz_8 HTTP/1.1
# http://localhost/?code=M.C106_BAY.2.3e12c859-6107-0c5b-9ef4-14b3fb8269ba&state=JzHdzHXmA7x6zl7Be6cJ6uOlf9Bg69
# python3 /www/mdserver-web/plugins/gdrive/index.py site bbs.midoks.me 3
# python3 /www/mdserver-web/plugins/gdrive/index.py database t1 3
# python3 /www/server/mdserver-web/plugins/msonedrive/index.py path
# /Users/midoks/Desktop/dev/python 3
import sys
import io
import os
import time
import re
import json
sys.path.append(os.getcwd() + "/class/core")
import mw
def getPluginName():
return 'gdrive'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
# print(getPluginDir())
sys.path.append(getPluginDir() + "/class")
from gdriveclient import gdriveclient
gd = gdriveclient(getPluginDir(), getServerDir())
gd.setDebug(True)
# sign_in_url, state = gd.get_sign_in_url()
# print(sign_in_url)
# url = 'https://localhost/?state=GH2YZ1VeytzVB1BqJJpQZIBk2GGAub&code=4/0Adeu5BXnD2dQvXx8Sg0WPn1XiMpihcRBNaG1yaFKIo86gUiG7q65KU1MaNCxrj_f2bjkwQ&scope=https://www.googleapis.com/auth/drive.file'
# t = gd.set_auth_url(url)
# print(t)
# def set_auth_url(url):
# try:
# if url.startswith("http://"):
# url = url.replace("http://", "https://")
# token = msodc.get_token_from_authorized_url(
# authorized_url=url)
# msodc.store_token(token)
# msodc.store_user()
# return mw.returnJson(True, "授权成功!")
# except Exception as e:
# print(e)
# return mw.returnJson(False, "授权失败2!:" + str(e))
# return mw.returnJson(False, "授权失败!:" + str(e))
# url = 'http://localhost/?code=M.C106_BAY.2.310112f3-a158-c400-9667-d158cbd1de6c&state=jEJz0ucR9bpZYD9PGxp2GgRDotrzO6'
# token = set_auth_url(url)
# print(token)
# token = msodc.get_token()
# print("token:", token)
# t = gd.get_list('')
# print(t)
# t = gd.get_id_list('1u7LjXGj1KoN-ltAdTRaib7IZJpsEnPdz')
# print(t)
# t = gd.create_folder('backup_demo')
# print(t)
# t = msodc.delete_object('backup')
# print(t)
# t = gd.upload_file('web_t1.cn_20230830_134549.tar.gz', 'site')
# print(t)
# print(gd.error_msg)
# /Users/midoks/Desktop/mwdev/server/mdserver-web/paramiko.log
# backup/site/paramiko.log
# |-正在上传到 backup/site/paramiko.log...
# True
t = gd.upload_file(
'db_zzzvps_20230830_210727.sql.gz', 'datebase')
print(t)
+1 -1
View File
@@ -2,7 +2,7 @@
"ps": "Gogs是一款极易搭建的自助Git服务",
"name": "gogs",
"title": "Gogs",
"versions": ["0.11.86","0.12.9"],
"versions": ["0.11.86","0.12.9","0.13.0"],
"tip": "soft",
"checks": "server/gogs",
"path":"server/gogs",
+4
View File
@@ -9,6 +9,10 @@ serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
GOGS_DOWNLOAD='https://dl.gogs.io'
+1 -1
View File
@@ -5,7 +5,7 @@
"title": "Memcached",
"shell": "install.sh",
"versions":["1.6"],
"updates":["1.6.15"],
"updates":["1.6.21"],
"tip": "soft",
"checks": "server/memcached",
"path":"server/memcached",
+5
View File
@@ -406,6 +406,11 @@ class msodclient:
"database": "db",
"path": "path",
}
if not prefix_dict.get(data_type):
print("data_type 类型错误!!!")
exit(1)
file_regx = prefix_dict.get(data_type) + "_(.+)_20\d+_\d+(?:\.|_)"
sub_search = re.search(file_regx, file_name)
sub_path_name = ""
+1 -2
View File
@@ -302,8 +302,7 @@
</div>
</script>
<script type="text/javascript" src="/plugins/file?name=msonedrive&f=js/msonedrive.js"></script>
<!-- <script type="text/javascript" src="/plugins/file?name=msonedrive&f=js/msonedrive.js"></script> -->
<script type="text/javascript">
$.getScript( "/plugins/file?name=msonedrive&f=js/msonedrive.js", function(){
odList('/');
+1 -1
View File
@@ -209,7 +209,7 @@ function odList(path){
}
pathname += '/' + tmp[i];
pathname = pathname.replace('//','/');
pathLi += '<li><a title="'+pathname+'" onclick="osList(\''+pathname+'\')">'+dirname+'</a></li>';
pathLi += '<li><a title="'+pathname+'" onclick="odList(\''+pathname+'\')">'+dirname+'</a></li>';
}
var um = 1;
if(tmp[tmp.length-1] == '') um = 2;
+11
View File
@@ -1596,6 +1596,15 @@ def setDbMasterAccess():
return mw.returnJson(True, '设置成功!')
def resetMaster(version=''):
pdb = pMysqlDb()
r = pdb.execute('reset master')
isError = isSqlError(r)
if isError != None:
return isError
return mw.returnJson(True, '重置成功!')
def getMasterDbList(version=''):
try:
args = getArgs()
@@ -2850,6 +2859,8 @@ if __name__ == "__main__":
print(getDbrunMode(version))
elif func == 'set_dbrun_mode':
print(setDbrunMode(version))
elif func == 'reset_master':
print(resetMaster(version))
elif func == 'get_masterdb_list':
print(getMasterDbList(version))
elif func == 'get_master_status':
+9
View File
@@ -1601,6 +1601,14 @@ function setDbMasterAccess(username){
});
}
function resetMaster(){
myPost('reset_master', '', function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
},{icon: rdata.status ? 1 : 2});
},'正在执行重置master命令[reset master]');
}
function getMasterRepSlaveList(){
var _data = {};
if (typeof(page) =='undefined'){
@@ -2446,6 +2454,7 @@ function masterOrSlaveConf(version=''){
<p class="conf_p">\
<span class="f14 c6 mr20">Master[主]配置</span><span class="f14 c6 mr20"></span>\
<button class="btn '+(!rdata.status ? 'btn-danger' : 'btn-success')+' btn-xs btn-master">'+(!rdata.status ? '未开启' : '已开启') +'</button>\
<button class="btn btn-success btn-xs" onclick="resetMaster()" >重置</button>\
</p>\
<hr/>\
<!-- master list -->\
+11
View File
@@ -1577,6 +1577,15 @@ def setDbMasterAccess():
return mw.returnJson(True, '设置成功!')
def resetMaster(version=''):
pdb = pMysqlDb()
r = pdb.execute('reset master')
isError = isSqlError(r)
if isError != None:
return isError
return mw.returnJson(True, '重置成功!')
def getMasterDbList(version=''):
try:
args = getArgs()
@@ -2827,6 +2836,8 @@ if __name__ == "__main__":
print(getDbrunMode(version))
elif func == 'set_dbrun_mode':
print(setDbrunMode(version))
elif func == 'reset_master':
print(resetMaster(version))
elif func == 'get_masterdb_list':
print(getMasterDbList(version))
elif func == 'get_master_status':
+9
View File
@@ -1601,6 +1601,14 @@ function setDbMasterAccess(username){
});
}
function resetMaster(){
myPost('reset_master', '', function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
},{icon: rdata.status ? 1 : 2});
},'正在执行重置master命令[reset master]');
}
function getMasterRepSlaveList(){
var _data = {};
if (typeof(page) =='undefined'){
@@ -2446,6 +2454,7 @@ function masterOrSlaveConf(version=''){
<p class="conf_p">\
<span class="f14 c6 mr20">Master[主]配置</span><span class="f14 c6 mr20"></span>\
<button class="btn '+(!rdata.status ? 'btn-danger' : 'btn-success')+' btn-xs btn-master">'+(!rdata.status ? '未开启' : '已开启') +'</button>\
<button class="btn btn-success btn-xs" onclick="resetMaster()" >重置</button>\
</p>\
<hr/>\
<!-- master list -->\
+11
View File
@@ -1811,6 +1811,15 @@ def setDbMasterAccess():
return mw.returnJson(True, '设置成功!')
def resetMaster(version=''):
pdb = pMysqlDb()
r = pdb.execute('reset master')
isError = isSqlError(r)
if isError != None:
return isError
return mw.returnJson(True, '重置成功!')
def getMasterDbList(version=''):
try:
args = getArgs()
@@ -3073,6 +3082,8 @@ if __name__ == "__main__":
print(getDbrunMode(version))
elif func == 'set_dbrun_mode':
print(setDbrunMode(version))
elif func == 'reset_master':
print(resetMaster(version))
elif func == 'get_masterdb_list':
print(getMasterDbList(version))
elif func == 'get_master_status':
+10
View File
@@ -1601,6 +1601,15 @@ function setDbMasterAccess(username){
});
}
function resetMaster(){
myPost('reset_master', '', function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
},{icon: rdata.status ? 1 : 2});
},'正在执行重置master命令[reset master]');
}
function getMasterRepSlaveList(){
var _data = {};
if (typeof(page) =='undefined'){
@@ -2446,6 +2455,7 @@ function masterOrSlaveConf(version=''){
<p class="conf_p">\
<span class="f14 c6 mr20">Master[主]配置</span><span class="f14 c6 mr20"></span>\
<button class="btn '+(!rdata.status ? 'btn-danger' : 'btn-success')+' btn-xs btn-master">'+(!rdata.status ? '未开启' : '已开启') +'</button>\
<button class="btn btn-success btn-xs" onclick="resetMaster()" >重置</button>\
</p>\
<hr/>\
<!-- master list -->\
+9 -3
View File
@@ -72,15 +72,16 @@ Install_openresty()
# Last Download Method
if [ ! -f ${openrestyDir}/openresty-${VERSION}.tar.gz ];then
wget --no-check-certificate -O ${openrestyDir}/openresty-${VERSION}.tar.gz https://dl.midoks.me/soft/openresty/openresty-${VERSION}.tar.gz -T 3
wget --no-check-certificate -O ${openrestyDir}/openresty-${VERSION}.tar.gz http://dl.midoks.me/soft/openresty/openresty-${VERSION}.tar.gz -T 3
fi
cd ${openrestyDir} && tar -zxvf openresty-${VERSION}.tar.gz
OPTIONS=''
if [ "$VERSION" != "1.21.4.2" ];then
if [ "$VERSION" == "1.19.3.1" ]; then
OPTIONS=" ${OPTIONS} --with-ipv6 "
fi
# --with-openssl=$serverPath/source/lib/openssl-1.0.2q
cd ${openrestyDir}/openresty-${VERSION} && ./configure \
--prefix=$serverPath/openresty \
@@ -96,7 +97,12 @@ Install_openresty()
# --with-debug
# 用于调式
gmake -j${cpuCore} && gmake install && gmake clean
CMD_MAKE=`which gmake`
if [ "$?" == "0" ];then
gmake -j${cpuCore} && gmake install && gmake clean
else
make -j${cpuCore} && make install && make clean
fi
if [ -d $serverPath/openresty ];then
echo "${VERSION}" > $serverPath/openresty/version.pl
+2 -2
View File
@@ -13,9 +13,9 @@ rootPath=$(dirname "$rootPath")
SERVER_ROOT=$rootPath/lib
SOURCE_ROOT=$rootPath/source/lib
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
HTTP_PREFIX="https://"
if [ ! -z "$cn" ];then
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
if [ ! -z "$cn" ] || [ "$?" != "0" ] ;then
HTTP_PREFIX="https://ghproxy.com/"
fi
+2 -2
View File
@@ -13,9 +13,9 @@ rootPath=$(dirname "$rootPath")
SERVER_ROOT=$rootPath/lib
SOURCE_ROOT=$rootPath/source/lib
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
HTTP_PREFIX="https://"
if [ ! -z "$cn" ];then
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
if [ ! -z "$cn" ] || [ "$?" != "0" ] ;then
HTTP_PREFIX="https://ghproxy.com/"
fi
+2 -2
View File
@@ -14,9 +14,9 @@ SERVER_ROOT=$rootPath/lib
SOURCE_ROOT=$rootPath/source/lib
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
HTTP_PREFIX="https://"
if [ ! -z "$cn" ];then
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
if [ ! -z "$cn" ] || [ "$?" != "0" ] ;then
HTTP_PREFIX="https://ghproxy.com/"
fi
+2 -2
View File
@@ -13,9 +13,9 @@ rootPath=$(dirname "$rootPath")
SERVER_ROOT=$rootPath/lib
SOURCE_ROOT=$rootPath/source/lib
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
HTTP_PREFIX="https://"
if [ ! -z "$cn" ];then
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
if [ ! -z "$cn" ] || [ "$?" != "0" ] ;then
HTTP_PREFIX="https://ghproxy.com/"
fi
+2 -2
View File
@@ -13,9 +13,9 @@ rootPath=$(dirname "$rootPath")
SERVER_ROOT=$rootPath/lib
SOURCE_ROOT=$rootPath/source/lib
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
HTTP_PREFIX="https://"
if [ ! -z "$cn" ];then
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
if [ ! -z "$cn" ] || [ "$?" != "0" ] ;then
HTTP_PREFIX="https://ghproxy.com/"
fi
+2 -2
View File
@@ -13,9 +13,9 @@ rootPath=$(dirname "$rootPath")
SERVER_ROOT=$rootPath/lib
SOURCE_ROOT=$rootPath/source/lib
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
HTTP_PREFIX="https://"
if [ ! -z "$cn" ];then
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
if [ ! -z "$cn" ] || [ "$?" != "0" ] ;then
HTTP_PREFIX="https://ghproxy.com/"
fi
+2 -2
View File
@@ -33,7 +33,7 @@ if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
if [ ! -z "$cn" ] || [ "$?" != "0" ] ;then
LOCAL_ADDR=cn
fi
@@ -70,7 +70,7 @@ fi
ZIP_OPTION='--enable-zip'
libzip_version=`pkg-config libzip --modversion`
if version_lt "$libzip_version" "0.11.0" ;then
if [ "$?" != "0" ] || version_lt "$libzip_version" "0.11.0" ;then
cd ${rootPath}/plugins/php/lib && /bin/bash libzip.sh
export PKG_CONFIG_PATH=$serverPath/lib/libzip/lib/pkgconfig
ZIP_OPTION="--with-libzip=$serverPath/lib/libzip"
+5
View File
@@ -40,6 +40,10 @@ else
BAK=''
fi
if [ ! -d $serverPath/lib/libzip ];then
cd ${rootPath}/plugins/php/lib && /bin/bash libzip.sh
fi
export PKG_CONFIG_PATH=/www/server/lib/libzip/lib/pkgconfig
Install_lib()
@@ -51,6 +55,7 @@ Install_lib()
return
fi
if [ ! -f "$extFile" ];then
if [ ! -d $sourcePath/php${version}/ext ];then
@@ -52,9 +52,9 @@ def send_msg(bot, tag='ad', trigger_time=300):
# https://t.me/gjgzs2022 | 22/m
# 高价收量 👑 集团收量 ❤️ 流量变现/支付宝代付 ❤️ 微信代付/实名认证/过人脸🕵️‍♀️各种账号处理✅ | 28/m
# https://zhaoziyuan.la/ | web | 15/m | 2m | next,9/15
# https://zhaoziyuan.pw/ | web | 15/m | 2m | next,9/15 | @baleite
# 腾云机场 |9/m
# 🚀鲲鹏VPN | 13/m
# 🚀鲲鹏VPN | 13/m | next,10/10
keyboard = [
[
types.InlineKeyboardButton(
+2 -1
View File
@@ -481,7 +481,8 @@ def api(reqClass=None, reqAction=None, reqData=None):
return mw.returnJson(False, '请指定请求方法')
classFile = ('config_api', 'crontab_api', 'files_api', 'firewall_api',
'plugins_api', 'system_api', 'site_api', 'task_api')
'plugins_api', 'system_api', 'site_api', 'task_api',
'logs_api')
className = reqClass + '_api'
if not className in classFile:
return mw.returnJson(False, 'external api request error')
+19 -14
View File
@@ -1108,11 +1108,13 @@ function getSiteErrorLogs(siteName){
function security(id,name){
var loadT = layer.msg(lan.site.the_msg,{icon:16,time:0,shade: [0.3, '#000']});
$.post('/site/get_security',{id:id,name:name},function(rdata){
console.log(rdata);
layer.close(loadT);
var mbody = '<div>'
+'<p style="margin-bottom:8px"><span style="display: inline-block; width: 60px;">URL后缀</span><input class="bt-input-text" type="text" name="sec_fix" value="'+rdata.fix+'" style="margin-left: 5px;width: 425px;height: 30px;margin-right:10px;'+(rdata.status?'background-color: #eee;':'')+'" placeholder="多个请用逗号隔开,例:png,jpeg,jpg,gif,zip" '+(rdata.status?'readonly':'')+'></p>'
+'<p style="margin-bottom:8px"><span style="display: inline-block; width: 60px;">许可域名</span><input class="bt-input-text" type="text" name="sec_domains" value="'+rdata.domains+'" style="margin-left: 5px;width: 425px;height: 30px;margin-right:10px;'+(rdata.status?'background-color: #eee;':'')+'" placeholder="支持通配符,多个域名请用逗号隔开,例:*.test.com,test.com" '+(rdata.status?'readonly':'')+'></p>'
+'<div class="label-input-group ptb10"><label style="font-weight:normal"><input type="checkbox" name="sec_status" onclick="setSecurity(\''+name+'\','+id+')" '+(rdata.status?'checked':'')+'>启用防盗链</label></div>'
+'<div class="label-input-group ptb10"><label style="font-weight:normal"><input type="checkbox" name="sec_none_status" onclick="setSecurity(\''+name+'\','+id+')" '+(rdata.none?'checked':'')+'>允许空HTTP_REFERER请求</label></div>'
+'<ul class="help-info-text c7 ptb10">'
+'<li>默认允许资源被直接访问,即不限制HTTP_REFERER为空的请求</li>'
+'<li>多个URL后缀与域名请使用逗号(,)隔开,如: png,jpeg,zip,js</li>'
@@ -1124,20 +1126,23 @@ function security(id,name){
}
//设置防盗链
function setSecurity(name,id){
var data = {
fix:$("input[name='sec_fix']").val(),
domains:$("input[name='sec_domains']").val(),
status:$("input[name='sec_status']").val(),
name:name,
id:id
}
var loadT = layer.msg(lan.site.the_msg,{icon:16,time:0,shade: [0.3, '#000']});
$.post('/site/set_security',data,function(rdata){
layer.close(loadT);
layer.msg(rdata.msg,{icon:rdata.status?1:2});
if(rdata.status) setTimeout(function(){security(id,name);},1000);
},'json');
function setSecurity(name,id, none){
setTimeout(function(){
var data = {
fix:$("input[name='sec_fix']").val(),
domains:$("input[name='sec_domains']").val(),
status:$("input[name='sec_status']").prop("checked"),
none:$("input[name='sec_none_status']").prop("checked"),
name:name,
id:id
}
var loadT = layer.msg(lan.site.the_msg,{icon:16,time:0,shade: [0.3, '#000']});
$.post('/site/set_security',data,function(rdata){
layer.close(loadT);
layer.msg(rdata.msg,{icon:rdata.status?1:2});
if(rdata.status) setTimeout(function(){security(id,name);},1000);
},'json');
},100);
}
+5 -2
View File
@@ -28,6 +28,9 @@ elif grep -Eqi "openSUSE" /etc/*-release; then
zypper install cron wget curl zip unzip
elif grep -Eqi "FreeBSD" /etc/*-release; then
OSNAME='freebsd'
elif grep -Eq "EulerOS" /etc/*-release || grep -Eq "openEuler" /etc/*-release; then
OSNAME='euler'
yum install -y wget curl zip unzip tar crontabs
elif grep -Eqi "CentOS" /etc/issue || grep -Eqi "CentOS" /etc/*-release; then
OSNAME='rhel'
yum install -y wget curl zip unzip tar crontabs
@@ -64,10 +67,10 @@ fi
# HTTP_PREFIX="https://ghproxy.com/"
# fi
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
HTTP_PREFIX="https://"
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
if [ ! -z "$cn" ] || [ "$?" != "0" ] ;then
LOCAL_ADDR=cn
HTTP_PREFIX="https://ghproxy.com/"
fi
+27 -15
View File
@@ -13,6 +13,13 @@ VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -
setenforce 0
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
SSH_PORT=`netstat -ntpl|grep sshd|grep -v grep | sed -n "1,1p" | awk '{print $4}' | awk -F : '{print $2}'`
if [ "$SSH_PORT" == "" ];then
SSH_PORT_LINE=`cat /etc/ssh/sshd_config | grep "Port \d*" | tail -1`
SSH_PORT=${SSH_PORT_LINE/"Port "/""}
fi
echo "SSH PORT:${SSH_PORT}"
yum install -y wget lsof crontabs
yum install -y python3-devel
yum install -y python3-pip
@@ -25,32 +32,37 @@ yum install -y mysql-devel
yum install -y expect
if [ -f /usr/sbin/iptables ];then
# if [ -f /usr/sbin/iptables ];then
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 888 -j ACCEPT
service iptables save
# iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
# iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
# iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
# iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 888 -j ACCEPT
# service iptables save
iptables_status=`service iptables status | grep 'not running'`
if [ "${iptables_status}" == '' ];then
service iptables restart
fi
# iptables_status=`service iptables status | grep 'not running'`
# if [ "${iptables_status}" == '' ];then
# service iptables restart
# fi
#安装时不开启
service iptables stop
fi
# #安装时不开启
# service iptables stop
# fi
if [ ! -f /usr/sbin/iptables ];then
if [ ! -f /usr/sbin/firewalld ];then
yum install firewalld -y
systemctl enable firewalld
#取消服务锁定
systemctl unmask firewalld
systemctl start firewalld
firewall-cmd --permanent --zone=public --add-port=22/tcp
if [ "$SSH_PORT" != "" ];then
firewall-cmd --permanent --zone=public --add-port=${SSH_PORT}/tcp
else
firewall-cmd --permanent --zone=public --add-port=22/tcp
fi
firewall-cmd --permanent --zone=public --add-port=80/tcp
firewall-cmd --permanent --zone=public --add-port=443/tcp
firewall-cmd --permanent --zone=public --add-port=888/tcp
+5
View File
@@ -17,6 +17,11 @@ if [ "$__GET_BIT" == "32" ];then
apt install -y rustc
fi
if [ "$VERSION_ID" == "10" ];then
apt install -y rustc
fi
# synchronize time first
apt-get install ntpdate -y
NTPHOST='time.nist.gov'
+152
View File
@@ -0,0 +1,152 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
LANG=en_US.UTF-8
if [ ! -f /usr/bin/applydeltarpm ];then
yum -y provides '*/applydeltarpm'
yum -y install deltarpm
fi
VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
setenforce 0
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
SSH_PORT=`netstat -ntpl|grep sshd|grep -v grep | sed -n "1,1p" | awk '{print $4}' | awk -F : '{print $2}'`
if [ "$SSH_PORT" == "" ];then
SSH_PORT_LINE=`cat /etc/ssh/sshd_config | grep "Port \d*" | tail -1`
SSH_PORT=${SSH_PORT_LINE/"Port "/""}
fi
echo "SSH PORT:${SSH_PORT}"
yum install -y wget lsof crontabs
yum install -y python3-devel
yum install -y python3-pip
yum install -y python-devel
yum install -y vixie-cron
yum install -y curl-devel
yum install -y libmcrypt
yum install -y libmcrypt-devel
yum install -y mysql-devel
yum install -y expect
# if [ -f /usr/sbin/iptables ];then
# iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
# iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
# iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
# iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 888 -j ACCEPT
# service iptables save
# iptables_status=`service iptables status | grep 'not running'`
# if [ "${iptables_status}" == '' ];then
# service iptables restart
# fi
# #安装时不开启
# service iptables stop
# fi
if [ ! -f /usr/sbin/firewalld ];then
yum install firewalld -y
systemctl enable firewalld
#取消服务锁定
systemctl unmask firewalld
systemctl start firewalld
if [ "$SSH_PORT" != "" ];then
firewall-cmd --permanent --zone=public --add-port=${SSH_PORT}/tcp
else
firewall-cmd --permanent --zone=public --add-port=22/tcp
fi
firewall-cmd --permanent --zone=public --add-port=80/tcp
firewall-cmd --permanent --zone=public --add-port=443/tcp
firewall-cmd --permanent --zone=public --add-port=888/tcp
sed -i 's#AllowZoneDrifting=yes#AllowZoneDrifting=no#g' /etc/firewalld/firewalld.conf
firewall-cmd --reload
#安装时不开启
systemctl stop firewalld
fi
yum groupinstall -y "Development Tools"
yum install -y epel-release
yum install -y oniguruma oniguruma-devel
#centos8 stream | use dnf
if [ "$?" != "0" ];then
yum install -y dnf dnf-plugins-core
dnf config-manager --set-enabled powertools
yum install -y oniguruma oniguruma-devel
dnf upgrade -y libmodulemd
fi
yum install -y libtirpc libtirpc-devel
yum install -y rpcgen
yum install -y openldap openldap-devel
yum install -y bison re2c
yum install -y cmake3
yum install -y autoconf
yum install -y make cmake gcc gcc-c++
yum install -y libmemcached libmemcached-devel
yum install -y curl curl-devel
yum install -y zlib zlib-devel
yum install -y libzip libzip-devel
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 libxml2 libxml2-devel
yum install -y graphviz
yum install -y sqlite-devel
yum install -y oniguruma oniguruma-devel
yum install -y ImageMagick ImageMagick-devel
yum install -y libzstd-devel
yum install -y libevent libevent-devel unzip zip
# yum install -y python-imaging
yum install -y libicu-devel bzip2-devel pcre pcre-devel
yum install -y gd gd-devel
yum install -y libjpeg-devel libpng-devel libwebp libwebp-devel
yum install -y net-tools
yum install -y ncurses-devel
yum install -y libXpm-devel
yum install -y libargon2-devel
for yumPack in flex file libtool libtool-libs kernel-devel patch wget glib2 glib2-devel tar bzip2 bzip2-devel libevent libevent-devel ncurses ncurses-devel curl curl-devel libcurl libcurl-devel e2fsprogs e2fsprogs-devel libidn libidn-devel vim-minimal gettext gettext-devel ncurses-devel gmp-devel libcap diffutils ca-certificates net-tools psmisc git-core c-ares-devel libicu-devel libxslt libxslt-devel zip unzip glibc.i686 libstdc++.so.6 cairo-devel ncurses-devel libaio-devel perl perl-devel perl-Data-Dumper expat-devel readline-devel;
do yum -y install $yumPack;done
if [ "$VERSION_ID" -eq "8" ];then
dnf upgrade -y libmodulemd
fi
if [ "$VERSION_ID" -eq "9" ];then
yum install -y patchelf
dnf --enablerepo=crb install -y libtirpc-devel
dnf --enablerepo=crb install -y libmemcached libmemcached-devel
dnf --enablerepo=crb install -y libtool libtool-libs
dnf --enablerepo=crb install -y gnutls-devel
dnf --enablerepo=crb install -y mysql-devel
dnf --enablerepo=crb install -y libvpx-devel libXpm-devel libwebp libwebp-devel
dnf --enablerepo=crb install -y libjpeg-devel libpng-devel
dnf --enablerepo=crb install -y oniguruma oniguruma-devel
dnf --enablerepo=crb install -y libzip libzip-devel
# yum remove -y chardet
fi
cd /www/server/mdserver-web/scripts && bash lib.sh
chmod 755 /www/server/mdserver-web/data
-20
View File
@@ -60,24 +60,6 @@ if [ "$SSH_PORT" == "" ];then
fi
echo "SSH PORT:${SSH_PORT}"
# if [ -f /usr/sbin/iptables ];then
# iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
# iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
# iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
# iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 888 -j ACCEPT
# service iptables save
# iptables_status=`service iptables status | grep 'not running'`
# if [ "${iptables_status}" == '' ];then
# service iptables restart
# fi
# #安装时不开启
# service iptables stop
# fi
if [ ! -f /usr/sbin/firewalld ];then
zypper install -y firewalld
systemctl enable firewalld
@@ -99,8 +81,6 @@ if [ ! -f /usr/sbin/firewalld ];then
systemctl stop firewalld
fi
cd /www/server/mdserver-web/scripts && bash lib.sh
chmod 755 /www/server/mdserver-web/data
+5 -2
View File
@@ -32,6 +32,9 @@ elif grep -Eq "openSUSE" /etc/*-release; then
zypper refresh
elif grep -Eq "FreeBSD" /etc/*-release; then
OSNAME='freebsd'
elif grep -Eq "EulerOS" /etc/*-release || grep -Eq "openEuler" /etc/*-release; then
OSNAME='euler'
yum install -y wget curl zip unzip tar crontabs
elif grep -Eqi "CentOS" /etc/issue || grep -Eqi "CentOS" /etc/*-release; then
OSNAME='rhel'
yum install -y wget zip unzip
@@ -68,10 +71,10 @@ fi
# HTTP_PREFIX="https://ghproxy.com/"
# fi
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
HTTP_PREFIX="https://"
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
if [ ! -z "$cn" ] || [ "$?" != "0" ] ;then
LOCAL_ADDR=cn
HTTP_PREFIX="https://ghproxy.com/"
fi
+2 -3
View File
@@ -64,11 +64,10 @@ fi
# LOCAL_ADDR=cn
# HTTP_PREFIX="https://ghproxy.com/"
# fi
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
HTTP_PREFIX="https://"
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
if [ ! -z "$cn" ] || [ "$?" != "0" ] ;then
LOCAL_ADDR=cn
HTTP_PREFIX="https://ghproxy.com/"
fi
+6 -5
View File
@@ -25,6 +25,8 @@ if [ ${_os} == "Darwin" ]; then
elif grep -Eqi "openSUSE" /etc/*-release; then
OSNAME='opensuse'
zypper refresh
elif grep -Eq "EulerOS" /etc/*-release || grep -Eq "openEuler" /etc/*-release; then
OSNAME='euler'
elif grep -Eqi "FreeBSD" /etc/*-release; then
OSNAME='freebsd'
elif grep -Eqi "CentOS" /etc/issue || grep -Eqi "CentOS" /etc/*-release; then
@@ -55,15 +57,14 @@ else
fi
# cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
HTTP_PREFIX="https://"
LOCAL_ADDR=common
ping -c 1 github.com > /dev/null 2>&1
if [ "$?" != "0" ];then
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
if [ ! -z "$cn" ] || [ "$?" != "0" ] ;then
LOCAL_ADDR=cn
HTTP_PREFIX="https://ghproxy.com/"
HTTP_PREFIX="https://ghproxy.com/"
fi
echo "local:${LOCAL_ADDR}"
CP_CMD=/usr/bin/cp
if [ -f /bin/cp ];then
+58
View File
@@ -0,0 +1,58 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
export LANG=en_US.UTF-8
if [ -f /etc/motd ];then
echo "welcome to mdserver-web panel" > /etc/motd
fi
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
yum install -y curl-devel libmcrypt libmcrypt-devel python3-devel
cd /www/server/mdserver-web/scripts && bash lib.sh
chmod 755 /www/server/mdserver-web/data
if [ -f /etc/rc.d/init.d/mw ];then
bash /etc/rc.d/init.d/mw stop && rm -rf /www/server/mdserver-web/scripts/init.d/mw && rm -rf /etc/rc.d/init.d/mw
fi
echo -e "stop mw"
isStart=`ps -ef|grep 'gunicorn -c setting.py app:app' |grep -v grep|awk '{print $2}'`
port=7200
if [ -f /www/server/mdserver-web/data/port.pl ]; then
port=$(cat /www/server/mdserver-web/data/port.pl)
fi
n=0
while [[ "$isStart" != "" ]];
do
echo -e ".\c"
sleep 0.5
isStart=$(lsof -n -P -i:$port|grep LISTEN|grep -v grep|awk '{print $2}'|xargs)
let n+=1
if [ $n -gt 15 ];then
break;
fi
done
echo -e "start mw"
cd /www/server/mdserver-web && bash cli.sh start
isStart=`ps -ef|grep 'gunicorn -c setting.py app:app' |grep -v grep|awk '{print $2}'`
n=0
while [[ ! -f /etc/rc.d/init.d/mw ]];
do
echo -e ".\c"
sleep 1
let n+=1
if [ $n -gt 20 ];then
echo -e "start mw fail"
exit 1
fi
done
echo -e "start mw success"
+5 -3
View File
@@ -25,6 +25,8 @@ if [ ${_os} == "Darwin" ]; then
elif grep -Eqi "openSUSE" /etc/*-release; then
OSNAME='opensuse'
zypper refresh
elif grep -Eq "EulerOS" /etc/*-release || grep -Eq "openEuler" /etc/*-release; then
OSNAME='euler'
elif grep -Eqi "FreeBSD" /etc/*-release; then
OSNAME='freebsd'
elif grep -Eqi "CentOS" /etc/issue || grep -Eqi "CentOS" /etc/*-release; then
@@ -61,15 +63,15 @@ fi
# LOCAL_ADDR=cn
# HTTP_PREFIX="https://ghproxy.com/"
# fi
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
HTTP_PREFIX="https://"
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
if [ ! -z "$cn" ] || [ "$?" != "0" ] ;then
LOCAL_ADDR=cn
HTTP_PREFIX="https://ghproxy.com/"
fi
echo "local:${LOCAL_ADDR}"
CP_CMD=/usr/bin/cp
if [ -f /bin/cp ];then
+9 -6
View File
@@ -18,7 +18,7 @@ import json
class mwApi:
__MW_KEY = 'j7GQhzNcBV4KU9QKYPXvtjSzCcmfkc0e'
__MW_KEY = 'uATE5NrKDWIlZuDcYpvLVhoUo1c7A1Pk'
__MW_PANEL = 'http://127.0.0.1:7200'
# 如果希望多台面板,可以在实例化对象时,将面板地址与密钥传入
@@ -48,7 +48,7 @@ class mwApi:
#@timeout 超时时间默认1800秒
# return string
def __http_post_cookie(self, url, p_data, timeout=1800):
cookie_file = './' + self.__get_md5(self.__MW_PANEL) + '.cookie'
cookie_file = '/tmp/' + self.__get_md5(self.__MW_PANEL) + '.cookie'
if sys.version_info[0] == 2:
# Python2
import urllib
@@ -81,8 +81,11 @@ class mwApi:
import ssl
import http.cookiejar
cookie_obj = http.cookiejar.MozillaCookieJar(cookie_file)
cookie_obj.load(cookie_file, ignore_discard=True,
ignore_expires=True)
# 加载已保存的cookie
if os.path.exists(cookie_file):
cookie_obj.load(cookie_file, ignore_discard=True,
ignore_expires=True)
handler = urllib.request.HTTPCookieProcessor(cookie_obj)
data = urllib.parse.urlencode(p_data).encode('utf-8')
req = urllib.request.Request(url, data)
@@ -97,7 +100,7 @@ class mwApi:
# 取面板日志
def getLogs(self):
# 拼接URL地址
url = self.__MW_PANEL + '/api/firewall/get_log_list'
url = self.__MW_PANEL + '/api/logs/get_log_list'
# 准备POST数据
post_data = self.__get_key_data() # 取签名
@@ -112,7 +115,7 @@ class mwApi:
if __name__ == '__main__':
# 实例化宝塔API对象
# 实例化MW-API对象
api = mwApi()
# 调用get_logs方法