修复漏洞
This commit is contained in:
parent
bc34e592ce
commit
173a5d4be3
@ -19,7 +19,7 @@ from utils.encode import base64Encode, base64Decode, fetch, post, request, getCr
|
|||||||
from utils.encode import verifyCode, setDetail, join, urljoin2, parseText, requireCache, forceOrder, base64ToImage, \
|
from utils.encode import verifyCode, setDetail, join, urljoin2, parseText, requireCache, forceOrder, base64ToImage, \
|
||||||
encodeStr, decodeStr
|
encodeStr, decodeStr
|
||||||
from utils.encode import md5 as mmd5
|
from utils.encode import md5 as mmd5
|
||||||
from utils.safePython import safePython
|
from utils.safePython import safePython, safe_eval
|
||||||
from utils.parser import runPy, runJScode, JsObjectWrapper, PyJsObject, PyJsString
|
from utils.parser import runPy, runJScode, JsObjectWrapper, PyJsObject, PyJsString
|
||||||
from utils.htmlParser import jsoup
|
from utils.htmlParser import jsoup
|
||||||
from urllib.parse import urljoin, quote, unquote
|
from urllib.parse import urljoin, quote, unquote
|
||||||
@ -185,7 +185,7 @@ class CMS:
|
|||||||
if isinstance(HOST, PyJsString): # JsObjectWrapper
|
if isinstance(HOST, PyJsString): # JsObjectWrapper
|
||||||
HOST = parseText(str(HOST))
|
HOST = parseText(str(HOST))
|
||||||
host = HOST.rstrip('/')
|
host = HOST.rstrip('/')
|
||||||
print('host:',host)
|
print('host:', host)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.info(f'执行{hostJs}获取host发生错误:{e}')
|
logger.info(f'执行{hostJs}获取host发生错误:{e}')
|
||||||
|
|
||||||
@ -828,8 +828,9 @@ class CMS:
|
|||||||
# print(url_rep)
|
# print(url_rep)
|
||||||
# print(cnt_page)
|
# print(cnt_page)
|
||||||
cnt_ctx = {}
|
cnt_ctx = {}
|
||||||
exec(f'cnt_pg={cnt_page}', cnt_ctx)
|
safe_eval(f'cnt_pg={cnt_page}', cnt_ctx)
|
||||||
cnt_pg = str(cnt_ctx['cnt_pg']) # 计算表达式的结果
|
# exec(f'cnt_pg={cnt_page}', cnt_ctx)
|
||||||
|
cnt_pg = str(cnt_ctx['cnt_pg']) if cnt_ctx.get('cnt_pg') else 1 # 计算表达式的结果
|
||||||
url = url.replace(url_rep, str(cnt_pg)).replace('(', '').replace(')', '')
|
url = url.replace(url_rep, str(cnt_pg)).replace('(', '').replace(')', '')
|
||||||
# print(url)
|
# print(url)
|
||||||
else:
|
else:
|
||||||
@ -1351,8 +1352,9 @@ class CMS:
|
|||||||
# print(url_rep)
|
# print(url_rep)
|
||||||
# print(cnt_page)
|
# print(cnt_page)
|
||||||
cnt_ctx = {}
|
cnt_ctx = {}
|
||||||
exec(f'cnt_pg={cnt_page}', cnt_ctx)
|
# exec(f'cnt_pg={cnt_page}', cnt_ctx)
|
||||||
cnt_pg = str(cnt_ctx['cnt_pg']) # 计算表达式的结果
|
safe_eval(f'cnt_pg={cnt_page}', cnt_ctx)
|
||||||
|
cnt_pg = str(cnt_ctx['cnt_pg']) if cnt_ctx.get('cnt_pg') else 1 # 计算表达式的结果
|
||||||
url = url.replace(url_rep, str(cnt_pg)).replace('(', '').replace(')', '')
|
url = url.replace(url_rep, str(cnt_pg)).replace('(', '').replace(')', '')
|
||||||
# print(url)
|
# print(url)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -8,33 +8,35 @@ import ujson
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from flask import Blueprint,abort,render_template,render_template_string,url_for,redirect,make_response,send_from_directory,request
|
from flask import Blueprint, abort, render_template, render_template_string, url_for, redirect, make_response, \
|
||||||
from controllers.service import storage_service,rules_service,parse_service
|
send_from_directory, request
|
||||||
from controllers.classes import getClasses,getClassInfo
|
from controllers.service import storage_service, rules_service, parse_service
|
||||||
|
from controllers.classes import getClasses, getClassInfo
|
||||||
|
|
||||||
from utils.files import getPics,custom_merge,getAlist,get_live_url,get_multi_rules,getCustonDict
|
from utils.files import getPics, custom_merge, getAlist, get_live_url, get_multi_rules, getCustonDict
|
||||||
from js.rules import getRules,getPys
|
from js.rules import getRules, getPys
|
||||||
from utils.encode import parseText,base64Encode,base64Decode
|
from utils.encode import parseText, base64Encode, base64Decode
|
||||||
from base.R import R
|
from base.R import R
|
||||||
from utils.system import getHost,is_linux
|
from utils.system import getHost, is_linux
|
||||||
from utils.cfg import cfg
|
from utils.cfg import cfg
|
||||||
from utils import parser
|
from utils import parser
|
||||||
from utils.ua import time,get_interval
|
from utils.ua import time, get_interval
|
||||||
from utils.log import logger
|
from utils.log import logger
|
||||||
from utils.update import getLocalVer,getHotSuggest
|
from utils.update import getLocalVer, getHotSuggest
|
||||||
from js.rules import getJxs
|
from js.rules import getJxs
|
||||||
import random
|
import random
|
||||||
from utils.web import getParmas,verfy_token
|
from utils.web import getParmas, verfy_token
|
||||||
from utils.common_api import js_render
|
from utils.common_api import js_render
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
|
home = Blueprint("home", __name__, static_folder='/static')
|
||||||
|
|
||||||
home = Blueprint("home", __name__,static_folder='/static')
|
|
||||||
|
|
||||||
@home.route('/')
|
@home.route('/')
|
||||||
def forbidden(): # put application's code here
|
def forbidden(): # put application's code here
|
||||||
abort(403)
|
abort(403)
|
||||||
|
|
||||||
|
|
||||||
@home.route('/favicon.ico') # 设置icon
|
@home.route('/favicon.ico') # 设置icon
|
||||||
def favicon():
|
def favicon():
|
||||||
# return home.send_static_file('img/favicon.svg')
|
# return home.send_static_file('img/favicon.svg')
|
||||||
@ -42,6 +44,7 @@ def favicon():
|
|||||||
# 对于当前文件所在路径,比如这里是static下的favicon.ico
|
# 对于当前文件所在路径,比如这里是static下的favicon.ico
|
||||||
# return send_from_directory(os.path.join(app.root_path, 'static'), 'img/favicon.svg', mimetype='image/vnd.microsoft.icon')
|
# return send_from_directory(os.path.join(app.root_path, 'static'), 'img/favicon.svg', mimetype='image/vnd.microsoft.icon')
|
||||||
|
|
||||||
|
|
||||||
@home.route('/index')
|
@home.route('/index')
|
||||||
def index():
|
def index():
|
||||||
sup_port = cfg.get('SUP_PORT', 9001)
|
sup_port = cfg.get('SUP_PORT', 9001)
|
||||||
@ -49,7 +52,7 @@ def index():
|
|||||||
pid_url = lsg.getItem('PID_URL')
|
pid_url = lsg.getItem('PID_URL')
|
||||||
manager0 = ':'.join(getHost(0).split(':')[0:2])
|
manager0 = ':'.join(getHost(0).split(':')[0:2])
|
||||||
manager1 = ':'.join(getHost(1).split(':')[0:2])
|
manager1 = ':'.join(getHost(1).split(':')[0:2])
|
||||||
manager2 = pid_url or ':'.join(getHost(2).split(':')[0:2]).replace('https','http')
|
manager2 = pid_url or ':'.join(getHost(2).split(':')[0:2]).replace('https', 'http')
|
||||||
if sup_port:
|
if sup_port:
|
||||||
manager0 += f':{sup_port}'
|
manager0 += f':{sup_port}'
|
||||||
manager1 += f':{sup_port}'
|
manager1 += f':{sup_port}'
|
||||||
@ -57,15 +60,25 @@ def index():
|
|||||||
manager2 += f':{sup_port}'
|
manager2 += f':{sup_port}'
|
||||||
# print(manager2)
|
# print(manager2)
|
||||||
ver = getLocalVer()
|
ver = getLocalVer()
|
||||||
return render_template('index.html',ver=ver,getHost=getHost,manager0=manager0,manager1=manager1,manager2=manager2,is_linux=is_linux())
|
return render_template('index.html', ver=ver, getHost=getHost, manager0=manager0, manager1=manager1,
|
||||||
|
manager2=manager2, is_linux=is_linux())
|
||||||
|
|
||||||
|
|
||||||
@home.route('/rules/clear')
|
@home.route('/rules/clear')
|
||||||
def rules_to_clear():
|
def rules_to_clear():
|
||||||
return render_template('rules_to_clear.html',rules=getRules(),classes=getClasses())
|
if not verfy_token():
|
||||||
|
# return render_template('login.html')
|
||||||
|
return R.error('请登录后再试')
|
||||||
|
return render_template('rules_to_clear.html', rules=getRules(), classes=getClasses())
|
||||||
|
|
||||||
|
|
||||||
@home.route('/rules/view')
|
@home.route('/rules/view')
|
||||||
def rules_to_view():
|
def rules_to_view():
|
||||||
return render_template('rules_to_view.html',rules=getRules(),classes=getClasses())
|
if not verfy_token():
|
||||||
|
# return render_template('login.html')
|
||||||
|
return R.error('请登录后再试')
|
||||||
|
return render_template('rules_to_view.html', rules=getRules(), classes=getClasses())
|
||||||
|
|
||||||
|
|
||||||
@home.route('/pics')
|
@home.route('/pics')
|
||||||
def random_pics():
|
def random_pics():
|
||||||
@ -92,6 +105,7 @@ def random_pics():
|
|||||||
else:
|
else:
|
||||||
return redirect(new_conf.WALL_PAPER)
|
return redirect(new_conf.WALL_PAPER)
|
||||||
|
|
||||||
|
|
||||||
@home.route('/clear')
|
@home.route('/clear')
|
||||||
def clear_rule():
|
def clear_rule():
|
||||||
rule = getParmas('rule')
|
rule = getParmas('rule')
|
||||||
@ -99,24 +113,26 @@ def clear_rule():
|
|||||||
return R.failed('规则字段必填')
|
return R.failed('规则字段必填')
|
||||||
cache_path = os.path.abspath(f'cache/{rule}.js')
|
cache_path = os.path.abspath(f'cache/{rule}.js')
|
||||||
if not os.path.exists(cache_path):
|
if not os.path.exists(cache_path):
|
||||||
return R.failed('服务端没有此规则的缓存文件!'+cache_path)
|
return R.failed('服务端没有此规则的缓存文件!' + cache_path)
|
||||||
os.remove(cache_path)
|
os.remove(cache_path)
|
||||||
return R.success('成功删除文件:'+cache_path)
|
return R.success('成功删除文件:' + cache_path)
|
||||||
|
|
||||||
@home.route("/plugin/<name>",methods=['GET'])
|
|
||||||
|
@home.route("/plugin/<name>", methods=['GET'])
|
||||||
def plugin(name):
|
def plugin(name):
|
||||||
# name=道长影视模板.js
|
# name=道长影视模板.js
|
||||||
if not name or not name.split('.')[-1] in ['js','txt','py','json']:
|
if not name or not name.split('.')[-1] in ['js', 'txt', 'py', 'json']:
|
||||||
return R.failed(f'非法猥亵,未指定文件名。必须包含js|txt|json|py')
|
return R.failed(f'非法猥亵,未指定文件名。必须包含js|txt|json|py')
|
||||||
try:
|
try:
|
||||||
return parser.toJs(name)
|
return parser.toJs(name)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return R.failed(f'非法猥亵\n{e}')
|
return R.failed(f'非法猥亵\n{e}')
|
||||||
|
|
||||||
|
|
||||||
@home.route('/files/<name>')
|
@home.route('/files/<name>')
|
||||||
def get_files(name):
|
def get_files(name):
|
||||||
base_path = 'base/files'
|
base_path = 'base/files'
|
||||||
os.makedirs(base_path,exist_ok=True)
|
os.makedirs(base_path, exist_ok=True)
|
||||||
file_path = os.path.join(base_path, f'{name}')
|
file_path = os.path.join(base_path, f'{name}')
|
||||||
if not os.path.exists(file_path):
|
if not os.path.exists(file_path):
|
||||||
return R.failed(f'{file_path}文件不存在')
|
return R.failed(f'{file_path}文件不存在')
|
||||||
@ -129,34 +145,39 @@ def get_files(name):
|
|||||||
response.headers['Content-Disposition'] = f'attachment;filename="{filename}"'
|
response.headers['Content-Disposition'] = f'attachment;filename="{filename}"'
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@home.route('/txt/<path:filename>')
|
@home.route('/txt/<path:filename>')
|
||||||
def custom_static_txt(filename):
|
def custom_static_txt(filename):
|
||||||
# 自定义静态目录 {{ url_for('custom_static',filename='help.txt')}}
|
# 自定义静态目录 {{ url_for('custom_static',filename='help.txt')}}
|
||||||
# print(filename)
|
# print(filename)
|
||||||
return send_from_directory('txt', filename)
|
return send_from_directory('txt', filename)
|
||||||
|
|
||||||
|
|
||||||
@home.route('/libs/<path:filename>')
|
@home.route('/libs/<path:filename>')
|
||||||
def custom_static_libs(filename):
|
def custom_static_libs(filename):
|
||||||
# 自定义静态目录 {{ url_for('custom_static',filename='help.txt')}}
|
# 自定义静态目录 {{ url_for('custom_static',filename='help.txt')}}
|
||||||
# print(filename)
|
# print(filename)
|
||||||
return send_from_directory('libs', filename)
|
return send_from_directory('libs', filename)
|
||||||
|
|
||||||
|
|
||||||
# @home.route('/js/<path:filename>')
|
# @home.route('/js/<path:filename>')
|
||||||
# def custom_static_js(filename):
|
# def custom_static_js(filename):
|
||||||
# # 自定义静态目录 {{ url_for('custom_static',filename='help.txt')}}
|
# # 自定义静态目录 {{ url_for('custom_static',filename='help.txt')}}
|
||||||
# # print(filename)
|
# # print(filename)
|
||||||
# return send_from_directory('js', filename)
|
# return send_from_directory('js', filename)
|
||||||
|
|
||||||
@home.route('/js/<path:name>',methods=['GET'])
|
@home.route('/js/<path:name>', methods=['GET'])
|
||||||
def custom_static_js(name):
|
def custom_static_js(name):
|
||||||
# 自定义静态目录 {{ url_for('custom_static',filename='help.txt')}}
|
# 自定义静态目录 {{ url_for('custom_static',filename='help.txt')}}
|
||||||
# print(name)
|
# print(name)
|
||||||
return js_render(name)
|
return js_render(name)
|
||||||
|
|
||||||
|
|
||||||
@home.route('/raw/js/<path:filename>')
|
@home.route('/raw/js/<path:filename>')
|
||||||
def custom_raw_js(filename):
|
def custom_raw_js(filename):
|
||||||
return send_from_directory('js', filename)
|
return send_from_directory('js', filename)
|
||||||
|
|
||||||
|
|
||||||
# @home.route('/txt/<name>')
|
# @home.route('/txt/<name>')
|
||||||
# def get_txt_files(name):
|
# def get_txt_files(name):
|
||||||
# base_path = 'txt'
|
# base_path = 'txt'
|
||||||
@ -177,14 +198,15 @@ def get_lives():
|
|||||||
# ?path=base/live.txt
|
# ?path=base/live.txt
|
||||||
path = getParmas('path')
|
path = getParmas('path')
|
||||||
live_path = path or 'base/直播.txt'
|
live_path = path or 'base/直播.txt'
|
||||||
if not re.search('(txt|json|conf)$',live_path,re.M|re.S) or not re.search('^(txt|base)',live_path,re.M|re.S):
|
if not re.search('(txt|json|conf)$', live_path, re.M | re.S) or not re.search('^(txt|base)', live_path,
|
||||||
|
re.M | re.S):
|
||||||
abort(403)
|
abort(403)
|
||||||
if not os.path.exists(live_path):
|
if not os.path.exists(live_path):
|
||||||
# with open(live_path,mode='w+',encoding='utf-8') as f:
|
# with open(live_path,mode='w+',encoding='utf-8') as f:
|
||||||
# f.write('')
|
# f.write('')
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
with open(live_path,encoding='utf-8') as f:
|
with open(live_path, encoding='utf-8') as f:
|
||||||
live_text = f.read()
|
live_text = f.read()
|
||||||
if len(live_text) > 100 and live_text.find('http') < 0:
|
if len(live_text) > 100 and live_text.find('http') < 0:
|
||||||
try:
|
try:
|
||||||
@ -196,6 +218,7 @@ def get_lives():
|
|||||||
response.headers['Content-Type'] = 'text/plain; charset=utf-8'
|
response.headers['Content-Type'] = 'text/plain; charset=utf-8'
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@home.route('/liveslib')
|
@home.route('/liveslib')
|
||||||
def get_liveslib():
|
def get_liveslib():
|
||||||
lsg = storage_service()
|
lsg = storage_service()
|
||||||
@ -203,10 +226,10 @@ def get_liveslib():
|
|||||||
live_path = f'libs/jar/{SPIDER_JAR}'
|
live_path = f'libs/jar/{SPIDER_JAR}'
|
||||||
logger.info(f'SPIDER_JAR:{SPIDER_JAR}>>当前系统挂载的指定jar文件位置:{live_path}')
|
logger.info(f'SPIDER_JAR:{SPIDER_JAR}>>当前系统挂载的指定jar文件位置:{live_path}')
|
||||||
if not os.path.exists(live_path):
|
if not os.path.exists(live_path):
|
||||||
with open(live_path,mode='w+',encoding='utf-8') as f:
|
with open(live_path, mode='w+', encoding='utf-8') as f:
|
||||||
f.write('')
|
f.write('')
|
||||||
|
|
||||||
with open(live_path,mode='rb') as f:
|
with open(live_path, mode='rb') as f:
|
||||||
live_text = f.read()
|
live_text = f.read()
|
||||||
response = make_response(live_text)
|
response = make_response(live_text)
|
||||||
filename = 'custom_spider.jar'
|
filename = 'custom_spider.jar'
|
||||||
@ -214,12 +237,14 @@ def get_liveslib():
|
|||||||
response.headers['Content-Disposition'] = f'attachment;filename="{filename}"'
|
response.headers['Content-Disposition'] = f'attachment;filename="{filename}"'
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@home.route('/hotsugg')
|
@home.route('/hotsugg')
|
||||||
def get_hot_search():
|
def get_hot_search():
|
||||||
s_from = getParmas('from')
|
s_from = getParmas('from')
|
||||||
size = getParmas('size')
|
size = getParmas('size')
|
||||||
data = getHotSuggest(s_from,size)
|
data = getHotSuggest(s_from, size)
|
||||||
return R.success('获取成功',data)
|
return R.success('获取成功', data)
|
||||||
|
|
||||||
|
|
||||||
def merged_hide(merged_config):
|
def merged_hide(merged_config):
|
||||||
t1 = time()
|
t1 = time()
|
||||||
@ -230,14 +255,16 @@ def merged_hide(merged_config):
|
|||||||
all_cnt = len(merged_config['sites'])
|
all_cnt = len(merged_config['sites'])
|
||||||
|
|
||||||
def filter_show(x):
|
def filter_show(x):
|
||||||
name = x['api'].split('rule=')[1].split('&')[0] if 'rule=' in x['api'] else x['key'].replace('dr_','')
|
name = x['api'].split('rule=')[1].split('&')[0] if 'rule=' in x['api'] else x['key'].replace('dr_', '')
|
||||||
# print(name)
|
# print(name)
|
||||||
if not str(x['key']).startswith('dr_') and name == 'drpy':
|
if not str(x['key']).startswith('dr_') and name == 'drpy':
|
||||||
name = x['key']
|
name = x['key']
|
||||||
return name not in hide_rule_names
|
return name not in hide_rule_names
|
||||||
|
|
||||||
merged_config['sites'] = list(filter(filter_show, merged_config['sites']))
|
merged_config['sites'] = list(filter(filter_show, merged_config['sites']))
|
||||||
logger.info(f'数据库筛选隐藏规则耗时{get_interval(t1)}毫秒,共计{all_cnt}条规则,隐藏后可渲染{len(merged_config["sites"])}条规则')
|
logger.info(
|
||||||
|
f'数据库筛选隐藏规则耗时{get_interval(t1)}毫秒,共计{all_cnt}条规则,隐藏后可渲染{len(merged_config["sites"])}条规则')
|
||||||
|
|
||||||
|
|
||||||
@home.route('/config/<int:mode>')
|
@home.route('/config/<int:mode>')
|
||||||
def config_render(mode):
|
def config_render(mode):
|
||||||
@ -248,7 +275,7 @@ def config_render(mode):
|
|||||||
m = getParmas('mode')
|
m = getParmas('mode')
|
||||||
sp = getParmas('sp') # 优选
|
sp = getParmas('sp') # 优选
|
||||||
logger.info(f'ver:{ver},UA:{UA}')
|
logger.info(f'ver:{ver},UA:{UA}')
|
||||||
if ver not in ['1','2']:
|
if ver not in ['1', '2']:
|
||||||
ISTVB = 'okhttp/3' in UA
|
ISTVB = 'okhttp/3' in UA
|
||||||
elif ver == '1':
|
elif ver == '1':
|
||||||
ISTVB = False
|
ISTVB = False
|
||||||
@ -278,7 +305,7 @@ def config_render(mode):
|
|||||||
pass
|
pass
|
||||||
print(f'{type(js_mode)} jsmode:{js_mode}')
|
print(f'{type(js_mode)} jsmode:{js_mode}')
|
||||||
# print(ali_token)
|
# print(ali_token)
|
||||||
customConfig = getCustonDict(host,ali_token,js0_password)
|
customConfig = getCustonDict(host, ali_token, js0_password)
|
||||||
# print(customConfig)
|
# print(customConfig)
|
||||||
jxs = getJxs(host=host)
|
jxs = getJxs(host=host)
|
||||||
use_py = lsg.getItem('USE_PY')
|
use_py = lsg.getItem('USE_PY')
|
||||||
@ -286,8 +313,8 @@ def config_render(mode):
|
|||||||
# print(pys)
|
# print(pys)
|
||||||
alists = getAlist()
|
alists = getAlist()
|
||||||
alists_str = json.dumps(alists, ensure_ascii=False)
|
alists_str = json.dumps(alists, ensure_ascii=False)
|
||||||
live_url = get_live_url(new_conf,mode)
|
live_url = get_live_url(new_conf, mode)
|
||||||
rules = getRules('js',js_mode)
|
rules = getRules('js', js_mode)
|
||||||
rules = get_multi_rules(rules)
|
rules = get_multi_rules(rules)
|
||||||
# html = render_template('config.txt',rules=getRules('js'),host=host,mode=mode,jxs=jxs,base64Encode=base64Encode,config=new_conf)
|
# html = render_template('config.txt',rules=getRules('js'),host=host,mode=mode,jxs=jxs,base64Encode=base64Encode,config=new_conf)
|
||||||
if new_conf.EXT_FUNC and new_conf.EXT_FUNC.strip():
|
if new_conf.EXT_FUNC and new_conf.EXT_FUNC.strip():
|
||||||
@ -300,23 +327,25 @@ def config_render(mode):
|
|||||||
else:
|
else:
|
||||||
new_conf.EXT_FUNC = []
|
new_conf.EXT_FUNC = []
|
||||||
|
|
||||||
html = render_template('config.txt',js0_password=js0_password,UA=UA,xr_mode=xr_mode,ISTVB=ISTVB,pys=pys,rules=rules,host=host,mode=mode,js_mode=js_mode,jxs=jxs,alists=alists,alists_str=alists_str,live_url=live_url,config=new_conf)
|
html = render_template('config.txt', js0_password=js0_password, UA=UA, xr_mode=xr_mode, ISTVB=ISTVB, pys=pys,
|
||||||
merged_config = custom_merge(parseText(html),customConfig)
|
rules=rules, host=host, mode=mode, js_mode=js_mode, jxs=jxs, alists=alists,
|
||||||
|
alists_str=alists_str, live_url=live_url, config=new_conf)
|
||||||
|
merged_config = custom_merge(parseText(html), customConfig)
|
||||||
# print(merged_config['sites'])
|
# print(merged_config['sites'])
|
||||||
merged_hide(merged_config)
|
merged_hide(merged_config)
|
||||||
# response = make_response(html)
|
# response = make_response(html)
|
||||||
# print(len(merged_config['sites']))
|
# print(len(merged_config['sites']))
|
||||||
# print(merged_config['sites'])
|
# print(merged_config['sites'])
|
||||||
merged_config['sites'] = sort_sites_by_order(merged_config['sites'],js_mode)
|
merged_config['sites'] = sort_sites_by_order(merged_config['sites'], js_mode)
|
||||||
# print(merged_config['sites'])
|
# print(merged_config['sites'])
|
||||||
if sp: # 执行动态优选源
|
if sp: # 执行动态优选源
|
||||||
special_rule(merged_config,lsg)
|
special_rule(merged_config, lsg)
|
||||||
|
|
||||||
# print(merged_config['parses'])
|
# print(merged_config['parses'])
|
||||||
parses = sort_parses_by_order(merged_config['parses'],host)
|
parses = sort_parses_by_order(merged_config['parses'], host)
|
||||||
# print(parses)
|
# print(parses)
|
||||||
merged_config['parses'] = parses
|
merged_config['parses'] = parses
|
||||||
config_text = json.dumps(merged_config,ensure_ascii=False,indent=1)
|
config_text = json.dumps(merged_config, ensure_ascii=False, indent=1)
|
||||||
|
|
||||||
# 依赖代理逻辑修改,改为admin/view去动态代理
|
# 依赖代理逻辑修改,改为admin/view去动态代理
|
||||||
# if js_proxy:
|
# if js_proxy:
|
||||||
@ -333,7 +362,8 @@ def config_render(mode):
|
|||||||
logger.info(f'自动生成动态配置共计耗时:{get_interval(tt)}毫秒')
|
logger.info(f'自动生成动态配置共计耗时:{get_interval(tt)}毫秒')
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def special_rule(merged_config,lsg):
|
|
||||||
|
def special_rule(merged_config, lsg):
|
||||||
# print(merged_config['sites'])
|
# print(merged_config['sites'])
|
||||||
special = lsg.getItem('SPECIAL').strip()
|
special = lsg.getItem('SPECIAL').strip()
|
||||||
# print('SPECIAL:',special)
|
# print('SPECIAL:',special)
|
||||||
@ -350,6 +380,7 @@ def special_rule(merged_config,lsg):
|
|||||||
merged_config['sites'] = special_st
|
merged_config['sites'] = special_st
|
||||||
merged_config['dr_count'] = len(special_st)
|
merged_config['dr_count'] = len(special_st)
|
||||||
|
|
||||||
|
|
||||||
def comp(x, y):
|
def comp(x, y):
|
||||||
if x['order'] > y['order']:
|
if x['order'] > y['order']:
|
||||||
return 1
|
return 1
|
||||||
@ -363,7 +394,8 @@ def comp(x, y):
|
|||||||
else:
|
else:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def sort_sites_by_order(sites,js_mode=0):
|
|
||||||
|
def sort_sites_by_order(sites, js_mode=0):
|
||||||
rules = rules_service()
|
rules = rules_service()
|
||||||
rule_list = rules.query_all()
|
rule_list = rules.query_all()
|
||||||
# print(rule_list)
|
# print(rule_list)
|
||||||
@ -374,7 +406,7 @@ def sort_sites_by_order(sites,js_mode=0):
|
|||||||
# sites[i]['id'] = i+1
|
# sites[i]['id'] = i+1
|
||||||
site_name = sites[i]['api'].split('rule=')[1].split('&')[0] if 'rule=' in sites[i]['api'] else sites[i]['key']
|
site_name = sites[i]['api'].split('rule=')[1].split('&')[0] if 'rule=' in sites[i]['api'] else sites[i]['key']
|
||||||
if js_mode and str(site_name).startswith('dr'):
|
if js_mode and str(site_name).startswith('dr'):
|
||||||
site_name = site_name.replace('dr_','')
|
site_name = site_name.replace('dr_', '')
|
||||||
if not str(sites[i]['key']).startswith('dr_') and site_name == 'drpy':
|
if not str(sites[i]['key']).startswith('dr_') and site_name == 'drpy':
|
||||||
site_name = sites[i]['key']
|
site_name = sites[i]['key']
|
||||||
# print(sites[i])
|
# print(sites[i])
|
||||||
@ -399,7 +431,8 @@ def sort_sites_by_order(sites,js_mode=0):
|
|||||||
del site['write_date']
|
del site['write_date']
|
||||||
return sites
|
return sites
|
||||||
|
|
||||||
def sort_parses_by_order(parses,host):
|
|
||||||
|
def sort_parses_by_order(parses, host):
|
||||||
t1 = time()
|
t1 = time()
|
||||||
parse = parse_service()
|
parse = parse_service()
|
||||||
parse_list = parse.query_all()
|
parse_list = parse.query_all()
|
||||||
@ -413,7 +446,7 @@ def sort_parses_by_order(parses,host):
|
|||||||
# print(f"重复的解析:{parses[i]['name']},{parses[i]['url']}")
|
# print(f"重复的解析:{parses[i]['name']},{parses[i]['url']}")
|
||||||
continue
|
continue
|
||||||
if str(parses[i]['url']).startswith(host):
|
if str(parses[i]['url']).startswith(host):
|
||||||
parses[i]['url'] = parses[i]['url'].replace(host,'')
|
parses[i]['url'] = parses[i]['url'].replace(host, '')
|
||||||
if parses[i]['url'] in parse_url_list:
|
if parses[i]['url'] in parse_url_list:
|
||||||
parse_rule = parse_list[parse_url_list.index(parses[i]['url'])]
|
parse_rule = parse_list[parse_url_list.index(parses[i]['url'])]
|
||||||
parses[i]['state'] = 1 if parse_rule['state'] is None else parse_rule['state']
|
parses[i]['state'] = 1 if parse_rule['state'] is None else parse_rule['state']
|
||||||
@ -441,12 +474,13 @@ def sort_parses_by_order(parses,host):
|
|||||||
logger.info(f'{len(new_parses)}/{len(parses)}条解析解析排序耗时:{get_interval(t1)}毫秒')
|
logger.info(f'{len(new_parses)}/{len(parses)}条解析解析排序耗时:{get_interval(t1)}毫秒')
|
||||||
return new_parses
|
return new_parses
|
||||||
|
|
||||||
|
|
||||||
@home.route('/configs')
|
@home.route('/configs')
|
||||||
def config_gen():
|
def config_gen():
|
||||||
if not verfy_token():
|
if not verfy_token():
|
||||||
return R.failed('请登录后再试')
|
return R.failed('请登录后再试')
|
||||||
# 生成文件
|
# 生成文件
|
||||||
os.makedirs('txt',exist_ok=True)
|
os.makedirs('txt', exist_ok=True)
|
||||||
new_conf = cfg
|
new_conf = cfg
|
||||||
lsg = storage_service()
|
lsg = storage_service()
|
||||||
store_conf_dict = lsg.getStoreConfDict()
|
store_conf_dict = lsg.getStoreConfDict()
|
||||||
@ -466,24 +500,30 @@ def config_gen():
|
|||||||
js0_password = new_conf.JS0_PASSWORD
|
js0_password = new_conf.JS0_PASSWORD
|
||||||
pys = getPys() if use_py else False
|
pys = getPys() if use_py else False
|
||||||
alists = getAlist()
|
alists = getAlist()
|
||||||
alists_str = json.dumps(alists,ensure_ascii=False)
|
alists_str = json.dumps(alists, ensure_ascii=False)
|
||||||
rules = getRules('js',js_mode)
|
rules = getRules('js', js_mode)
|
||||||
rules = get_multi_rules(rules)
|
rules = get_multi_rules(rules)
|
||||||
host0 = getHost(0)
|
host0 = getHost(0)
|
||||||
jxs = getJxs(host=host0)
|
jxs = getJxs(host=host0)
|
||||||
set_local = render_template('config.txt',js0_password=js0_password,pys=pys,rules=rules,alists=alists,alists_str=alists_str,live_url=get_live_url(new_conf,0),mode=0,js_mode=js_mode,host=host0,jxs=jxs,config=new_conf)
|
set_local = render_template('config.txt', js0_password=js0_password, pys=pys, rules=rules, alists=alists,
|
||||||
|
alists_str=alists_str, live_url=get_live_url(new_conf, 0), mode=0, js_mode=js_mode,
|
||||||
|
host=host0, jxs=jxs, config=new_conf)
|
||||||
# print(set_local)
|
# print(set_local)
|
||||||
host1 = getHost(1)
|
host1 = getHost(1)
|
||||||
jxs = getJxs(host=host1)
|
jxs = getJxs(host=host1)
|
||||||
set_area = render_template('config.txt',js0_password=js0_password,pys=pys,rules=rules,alists=alists,alists_str=alists_str,live_url=get_live_url(new_conf,1),mode=1,js_mode=js_mode,host=host1,jxs=jxs,config=new_conf)
|
set_area = render_template('config.txt', js0_password=js0_password, pys=pys, rules=rules, alists=alists,
|
||||||
|
alists_str=alists_str, live_url=get_live_url(new_conf, 1), mode=1, js_mode=js_mode,
|
||||||
|
host=host1, jxs=jxs, config=new_conf)
|
||||||
host2 = getHost(2) or host1
|
host2 = getHost(2) or host1
|
||||||
# print('远程地址:'+host2)
|
# print('远程地址:'+host2)
|
||||||
jxs = getJxs(host=host2)
|
jxs = getJxs(host=host2)
|
||||||
set_online = render_template('config.txt',js0_password=js0_password,pys=pys,rules=rules,alists=alists,alists_str=alists_str,live_url=get_live_url(new_conf,2),mode=1,js_mode=js_mode,host=host2,jxs=jxs,config=new_conf)
|
set_online = render_template('config.txt', js0_password=js0_password, pys=pys, rules=rules, alists=alists,
|
||||||
|
alists_str=alists_str, live_url=get_live_url(new_conf, 2), mode=1, js_mode=js_mode,
|
||||||
|
host=host2, jxs=jxs, config=new_conf)
|
||||||
ali_token = new_conf.ALI_TOKEN
|
ali_token = new_conf.ALI_TOKEN
|
||||||
# parses = []
|
# parses = []
|
||||||
with open('txt/pycms0.json','w+',encoding='utf-8') as f:
|
with open('txt/pycms0.json', 'w+', encoding='utf-8') as f:
|
||||||
customConfig = getCustonDict(host0,ali_token,js0_password)
|
customConfig = getCustonDict(host0, ali_token, js0_password)
|
||||||
set_dict = custom_merge(parseText(set_local), customConfig)
|
set_dict = custom_merge(parseText(set_local), customConfig)
|
||||||
merged_hide(set_dict)
|
merged_hide(set_dict)
|
||||||
set_dict['sites'] = sort_sites_by_order(set_dict['sites'], js_mode)
|
set_dict['sites'] = sort_sites_by_order(set_dict['sites'], js_mode)
|
||||||
@ -491,33 +531,37 @@ def config_gen():
|
|||||||
# print('生成静态配置时初始化排序parses')
|
# print('生成静态配置时初始化排序parses')
|
||||||
# parses = sort_parses_by_order(set_dict['parses'])
|
# parses = sort_parses_by_order(set_dict['parses'])
|
||||||
# set_dict['parses'] = parses
|
# set_dict['parses'] = parses
|
||||||
set_dict['parses'] = sort_parses_by_order(set_dict['parses'],host0)
|
set_dict['parses'] = sort_parses_by_order(set_dict['parses'], host0)
|
||||||
# set_dict = json.loads(set_local)
|
# set_dict = json.loads(set_local)
|
||||||
f.write(json.dumps(set_dict,ensure_ascii=False,indent=4))
|
f.write(json.dumps(set_dict, ensure_ascii=False, indent=4))
|
||||||
with open('txt/pycms1.json','w+',encoding='utf-8') as f:
|
with open('txt/pycms1.json', 'w+', encoding='utf-8') as f:
|
||||||
customConfig = getCustonDict(host1,ali_token,js0_password)
|
customConfig = getCustonDict(host1, ali_token, js0_password)
|
||||||
set_dict = custom_merge(parseText(set_area), customConfig)
|
set_dict = custom_merge(parseText(set_area), customConfig)
|
||||||
merged_hide(set_dict)
|
merged_hide(set_dict)
|
||||||
set_dict['sites'] = sort_sites_by_order(set_dict['sites'], js_mode)
|
set_dict['sites'] = sort_sites_by_order(set_dict['sites'], js_mode)
|
||||||
set_dict['parses'] = sort_parses_by_order(set_dict['parses'],host1)
|
set_dict['parses'] = sort_parses_by_order(set_dict['parses'], host1)
|
||||||
# set_dict = json.loads(set_area)
|
# set_dict = json.loads(set_area)
|
||||||
f.write(json.dumps(set_dict,ensure_ascii=False,indent=4))
|
f.write(json.dumps(set_dict, ensure_ascii=False, indent=4))
|
||||||
|
|
||||||
with open('txt/pycms2.json','w+',encoding='utf-8') as f:
|
with open('txt/pycms2.json', 'w+', encoding='utf-8') as f:
|
||||||
customConfig = getCustonDict(host2,ali_token,js0_password)
|
customConfig = getCustonDict(host2, ali_token, js0_password)
|
||||||
set_dict = custom_merge(parseText(set_online), customConfig)
|
set_dict = custom_merge(parseText(set_online), customConfig)
|
||||||
merged_hide(set_dict)
|
merged_hide(set_dict)
|
||||||
set_dict['sites'] = sort_sites_by_order(set_dict['sites'], js_mode)
|
set_dict['sites'] = sort_sites_by_order(set_dict['sites'], js_mode)
|
||||||
set_dict['parses'] = sort_parses_by_order(set_dict['parses'],host2)
|
set_dict['parses'] = sort_parses_by_order(set_dict['parses'], host2)
|
||||||
# set_dict = json.loads(set_online)
|
# set_dict = json.loads(set_online)
|
||||||
f.write(json.dumps(set_dict,ensure_ascii=False,indent=4))
|
f.write(json.dumps(set_dict, ensure_ascii=False, indent=4))
|
||||||
files = [os.path.abspath(rf'txt\pycms{i}.json') for i in range(3)]
|
files = [os.path.abspath(rf'txt\pycms{i}.json') for i in range(3)]
|
||||||
# print(files)
|
# print(files)
|
||||||
return R.success('猫配置生成完毕,文件位置在:\n'+'\n'.join(files))
|
return R.success('猫配置生成完毕,文件位置在:\n' + '\n'.join(files))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return R.failed(f'配置文件生成错误:\n{e}')
|
return R.failed(f'配置文件生成错误:\n{e}')
|
||||||
|
|
||||||
@home.route("/info",methods=['get'])
|
|
||||||
|
@home.route("/info", methods=['get'])
|
||||||
def info_all():
|
def info_all():
|
||||||
|
if not verfy_token():
|
||||||
|
# return render_template('login.html')
|
||||||
|
return R.error('请登录后再试')
|
||||||
data = storage_service.query_all()
|
data = storage_service.query_all()
|
||||||
return R.ok(data=data)
|
return R.ok(data=data)
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
###### 2024/01/02
|
||||||
|
- [X] 3.9.49beta11 fixed issues#49
|
||||||
|
|
||||||
###### 2023/11/25
|
###### 2023/11/25
|
||||||
- [X] 3.9.49beta8 增加直播转换小工具
|
- [X] 3.9.49beta8 增加直播转换小工具
|
||||||
|
|
||||||
@ -11,6 +14,7 @@
|
|||||||
```shell
|
```shell
|
||||||
git config --global http.proxy http://127.0.0.1:10808
|
git config --global http.proxy http://127.0.0.1:10808
|
||||||
git config --global https.proxy http://127.0.0.1:10808
|
git config --global https.proxy http://127.0.0.1:10808
|
||||||
|
git config --global --unset http.proxy
|
||||||
# 我的v2vary在10808上系统代理
|
# 我的v2vary在10808上系统代理
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
3.9.49beta10
|
3.9.49beta11
|
||||||
@ -9,7 +9,7 @@ import tokenize
|
|||||||
|
|
||||||
from func_timeout import func_set_timeout
|
from func_timeout import func_set_timeout
|
||||||
from func_timeout.exceptions import FunctionTimedOut
|
from func_timeout.exceptions import FunctionTimedOut
|
||||||
from urllib.parse import urljoin,quote,unquote
|
from urllib.parse import urljoin, quote, unquote
|
||||||
import requests
|
import requests
|
||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
@ -20,6 +20,8 @@ import base64
|
|||||||
from utils.log import logger
|
from utils.log import logger
|
||||||
|
|
||||||
time_out_sec = 8 # 安全执行python代码超时
|
time_out_sec = 8 # 安全执行python代码超时
|
||||||
|
|
||||||
|
|
||||||
class my_exception(Exception):
|
class my_exception(Exception):
|
||||||
def __init__(self, message):
|
def __init__(self, message):
|
||||||
self.message = message
|
self.message = message
|
||||||
@ -28,10 +30,12 @@ class my_exception(Exception):
|
|||||||
message = f'函数执行超时: "{self.message}"'
|
message = f'函数执行超时: "{self.message}"'
|
||||||
return message
|
return message
|
||||||
|
|
||||||
|
|
||||||
@func_set_timeout(time_out_sec)
|
@func_set_timeout(time_out_sec)
|
||||||
def excute(*args):
|
def excute(*args):
|
||||||
exec(*args)
|
exec(*args)
|
||||||
|
|
||||||
|
|
||||||
def check_unsafe_attributes(string):
|
def check_unsafe_attributes(string):
|
||||||
"""
|
"""
|
||||||
安全检测需要exec执行的python代码
|
安全检测需要exec执行的python代码
|
||||||
@ -48,6 +52,7 @@ def check_unsafe_attributes(string):
|
|||||||
elif toktype == tokenize.OP:
|
elif toktype == tokenize.OP:
|
||||||
pre_op = tokval
|
pre_op = tokval
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_PYTHON_CODE = """# 可用内置环境变量:
|
DEFAULT_PYTHON_CODE = """# 可用内置环境变量:
|
||||||
# - log: log(message): 打印日志功能
|
# - log: log(message): 打印日志功能
|
||||||
# - error: 弹出用户错误的弹窗
|
# - error: 弹出用户错误的弹窗
|
||||||
@ -57,12 +62,45 @@ zyw_lists = env['hikerule.zyw.list'].with_context(active_test=True).sudo().searc
|
|||||||
result = env['hikerule.zyw.list2data.wizard'].sudo().get_publish_value(zyw_lists)
|
result = env['hikerule.zyw.list2data.wizard'].sudo().get_publish_value(zyw_lists)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def safe_eval(code: str = '', localdict: dict = None):
|
||||||
|
code = code.strip()
|
||||||
|
logger.info('code:' + code)
|
||||||
|
if not code:
|
||||||
|
return {}
|
||||||
|
if localdict is None:
|
||||||
|
localdict = {}
|
||||||
|
builtins = __builtins__
|
||||||
|
builtins = dict(builtins).copy()
|
||||||
|
for key in ['__import__', 'eval', 'exec', 'globals', 'dir', 'copyright', 'open', 'quit']:
|
||||||
|
del builtins[key] # 删除不安全的关键字
|
||||||
|
# print(builtins)
|
||||||
|
global_dict = {'__builtins__': builtins,
|
||||||
|
'requests': requests, 'urljoin': urljoin, 'quote': quote, 'unquote': unquote,
|
||||||
|
'log': logger.info, 'json': json, 'print': print,
|
||||||
|
're': re, 'etree': etree, 'time': time, 'datetime': datetime, 'base64': base64
|
||||||
|
} # 禁用内置函数,不允许导入包
|
||||||
|
try:
|
||||||
|
check_unsafe_attributes(code)
|
||||||
|
# 待解决windows下运行超时的问题
|
||||||
|
try:
|
||||||
|
# excute(to_run_code, global_dict, localdict)
|
||||||
|
excute(code, global_dict, localdict)
|
||||||
|
return localdict
|
||||||
|
except FunctionTimedOut:
|
||||||
|
raise my_exception(f'safe_eval运行时间超过{time_out_sec}秒,疑似死循环,已被系统切断')
|
||||||
|
except Exception as e:
|
||||||
|
ret = f'执行报错:{e}'
|
||||||
|
logger.info(ret)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
class safePython:
|
class safePython:
|
||||||
def __init__(self,name, code):
|
def __init__(self, name, code):
|
||||||
self.name = name or '未定义'
|
self.name = name or '未定义'
|
||||||
self.code = code
|
self.code = code
|
||||||
|
|
||||||
def action_task_exec(self,call=None,params=None):
|
def action_task_exec(self, call=None, params=None):
|
||||||
"""
|
"""
|
||||||
接口调用执行函数
|
接口调用执行函数
|
||||||
:return:
|
:return:
|
||||||
@ -71,13 +109,13 @@ class safePython:
|
|||||||
params = []
|
params = []
|
||||||
builtins = __builtins__
|
builtins = __builtins__
|
||||||
builtins = dict(builtins).copy()
|
builtins = dict(builtins).copy()
|
||||||
for key in ['__import__','eval','exec','globals','dir','copyright','open','quit']:
|
for key in ['__import__', 'eval', 'exec', 'globals', 'dir', 'copyright', 'open', 'quit']:
|
||||||
del builtins[key] # 删除不安全的关键字
|
del builtins[key] # 删除不安全的关键字
|
||||||
# print(builtins)
|
# print(builtins)
|
||||||
global_dict = {'__builtins__': builtins,
|
global_dict = {'__builtins__': builtins,
|
||||||
'requests': requests, 'urljoin':urljoin,'quote':quote,'unquote': unquote,
|
'requests': requests, 'urljoin': urljoin, 'quote': quote, 'unquote': unquote,
|
||||||
'log': logger.info, 'json': json,'print':print,
|
'log': logger.info, 'json': json, 'print': print,
|
||||||
're':re,'etree':etree,'time':time,'datetime':datetime,'base64':base64
|
're': re, 'etree': etree, 'time': time, 'datetime': datetime, 'base64': base64
|
||||||
} # 禁用内置函数,不允许导入包
|
} # 禁用内置函数,不允许导入包
|
||||||
try:
|
try:
|
||||||
check_unsafe_attributes(self.code)
|
check_unsafe_attributes(self.code)
|
||||||
@ -102,4 +140,4 @@ class safePython:
|
|||||||
# print(global_dict)
|
# print(global_dict)
|
||||||
# print(localdict)
|
# print(localdict)
|
||||||
ret = localdict['result']
|
ret = localdict['result']
|
||||||
return ret
|
return ret
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user