Breaking changes

Fix broken /sub2clashr and /surge2clash interface.
Add template support for base configurations.
Add support for exporting HTTP/Socks 5 nodes to Quantumult configurations.
Add support for VMess HTTP nodes in Clash configurations.
Optimize codes.
This commit is contained in:
Tindy X committed 2020-04-02 23:18:26 +08:00
1 parent 58349a086d
commit eeae32f8eb
11 files changed
+27151 -57

No files matched your search

+207
View File
@@ -0,0 +1,207 @@
{% if request.target == "clash" or request.target == "clashr" %}
port: {{ global.clash.http_port }}
socks-port: {{ global.clash.socks_port }}
allow-lan: {{ global.clash.allow_lan }}
mode: Rule
log-level: {{ global.clash.log_level }}
external-controller: :9090
{% if exists("request.clash.dns") %}
{% if request.clash.dns == "1" %}
dns:
enabled: true
listen: 1053
{% endif %}
{% endif %}
{% if local.clash.new_field_name == "true" %}
proxies: ~
proxy-groups: ~
rules: ~
{% else %}
Proxy: ~
Proxy Group: ~
Rule: ~
{% endif %}
{% endif %}
{% if request.target == "surge" %}
[General]
loglevel = notify
bypass-system = true
skip-proxy = 127.0.0.1,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,100.64.0.0/10,localhost,*.local,e.crashlytics.com,captive.apple.com,::ffff:0:0:0:0/1,::ffff:128:0:0:0/1
#DNS设置或根据自己网络情况进行相应设置
bypass-tun = 192.168.0.0/16,10.0.0.0/8,172.16.0.0/12
dns-server = 119.29.29.29,223.5.5.5
[Script]
http-request https?:\/\/.*\.iqiyi\.com\/.*authcookie= script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/iQIYI-DailyBonus/iQIYI_GetCookie.js
{% endif %}
{% if request.target == "loon" %}
[General]
skip-proxy = 192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,localhost,*.local,e.crashlynatics.com
bypass-tun = 10.0.0.0/8,100.64.0.0/10,127.0.0.0/8,169.254.0.0/16,172.16.0.0/12,192.0.0.0/24,192.0.2.0/24,192.88.99.0/24,192.168.0.0/16,198.18.0.0/15,198.51.100.0/24,203.0.113.0/24,224.0.0.0/4,255.255.255.255/32
dns-server = system,119.29.29.29,223.5.5.5
allow-udp-proxy = false
host = 127.0.0.1
[Proxy]
[Remote Proxy]
[Proxy Group]
[Rule]
[Remote Rule]
[URL Rewrite]
enable = true
^https?:\/\/(www.)?(g|google)\.cn https://www.google.com 302
[Remote Rewrite]
https://raw.githubusercontent.com/Loon0x00/LoonExampleConfig/master/Rewrite/AutoRewrite_Example.list,auto
[MITM]
hostname = *.example.com,*.sample.com
enable = true
skip-server-cert-verify = true
#ca-p12 =
#ca-passphrase =
{% endif %}
{% if request.target == "quan" %}
[SERVER]
[SOURCE]
[BACKUP-SERVER]
[SUSPEND-SSID]
[POLICY]
[DNS]
1.1.1.1
[REWRITE]
[URL-REJECTION]
[TCP]
[GLOBAL]
[HOST]
[STATE]
STATE,AUTO
[MITM]
{% endif %}
{% if request.target == "quanx" %}
[general]
excluded_routes=192.168.0.0/16, 172.16.0.0/12, 100.64.0.0/10, 10.0.0.0/8
geo_location_checker=http://ip-api.com/json/?lang=zh-CN, https://github.com/KOP-XIAO/QuantumultX/raw/master/Scripts/IP_API.js
network_check_url=http://www.baidu.com/
server_check_url=http://www.gstatic.com/generate_204
[dns]
server=119.29.29.29
server=223.5.5.5
server=1.0.0.1
server=8.8.8.8
[policy]
static=♻️ 自动选择, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Auto.png
static=🔰 节点选择, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Proxy.png
static=🌍 国外媒体, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/GlobalMedia.png
static=🌏 国内媒体, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/DomesticMedia.png
static=Ⓜ️ 微软服务, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Microsoft.png
static=📲 电报信息, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Telegram.png
static=🍎 苹果服务, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Apple.png
static=🎯 全球直连, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Direct.png
static=🛑 全球拦截, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Advertising.png
static=🐟 漏网之鱼, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Final.png
[server_remote]
[filter_remote]
[rewrite_remote]
[server_local]
[filter_local]
[rewrite_local]
[mitm]
{% endif %}
{% if request.target == "mellow" %}
[Endpoint]
DIRECT, builtin, freedom, domainStrategy=UseIP
REJECT, builtin, blackhole
Dns-Out, builtin, dns
[Routing]
domainStrategy = IPIfNonMatch
[Dns]
hijack = Dns-Out
clientIp = 114.114.114.114
[DnsServer]
localhost
223.5.5.5
8.8.8.8, 53, Remote
8.8.4.4
[DnsRule]
DOMAIN-KEYWORD, geosite:geolocation-!cn, Remote
DOMAIN-SUFFIX, google.com, Remote
[DnsHost]
doubleclick.net = 127.0.0.1
[Log]
loglevel = warning
{% endif %}
{% if request.target == "surfboard" %}
[General]
loglevel = notify
interface = 127.0.0.1
skip-proxy = 127.0.0.1, 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12, 100.64.0.0/10, localhost, *.local
ipv6 = false
dns-server = system, 223.5.5.5
exclude-simple-hostnames = true
enhanced-mode-by-rule = true
{% endif %}
{% if request.target == "sssub" %}
{
"route": "bypass-lan-china",
"remote_dns": "dns.google",
"ipv6": false,
"metered": false,
"proxy_apps": {
"enabled": false,
"bypass": true,
"android_list": [
"com.eg.android.AlipayGphone",
"com.wudaokou.hippo",
"com.zhihu.android"
]
},
"udpdns": false
}
{% endif %}
+4
View File
@@ -55,3 +55,7 @@ clash_rule_base=base/forcerule.yml
;Options for filtering nodes
;include_remarks=
;exclude_remarks=
;[template]
;;variables in the local scope
;clash.dns.port=5353
+2
View File
@@ -23,3 +23,5 @@ custom:
# include_remarks: []
# exclude_remarks: []
# template_args:
# - {key: clash.dns.port, value: 5353}
+16 -8
View File
@@ -5,14 +5,14 @@ common:
insert_url: []
exclude_remarks: ["(到期|剩余流量|时间|官网|产品)"]
include_remarks: []
clash_rule_base: base/simple_base.yml
surge_rule_base: base/surge.conf
surfboard_rule_base: base/surfboard.conf
mellow_rule_base: base/mellow.conf
quan_rule_base: base/quan.conf
quanx_rule_base: base/quanx.conf
loon_rule_base: base/loon.conf
sssub_rule_base: base/shadowsocks_base.json
clash_rule_base: base/all_base.tpl
surge_rule_base: base/all_base.tpl
surfboard_rule_base: base/all_base.tpl
mellow_rule_base: base/all_base.tpl
quan_rule_base: base/all_base.tpl
quanx_rule_base: base/all_base.tpl
loon_rule_base: base/all_base.tpl
sssub_rule_base: base/all_base.tpl
proxy_config: SYSTEM
proxy_ruleset: SYSTEM
proxy_subscription: NONE
@@ -79,6 +79,14 @@ proxy_group:
# - {name: ssid group, type: ssid, rule: ["default_group", "celluar=group0,ssid1=group1,ssid2=group2"]}
- {import: snippets/groups.txt}
template:
template_path: "template"
globals:
- {key: clash.http_port, value: 7890}
- {key: clash.socks_port, value: 7891}
- {key: clash.allow_lan, value: true}
- {key: clash.log_level, value: info}
server:
listen: 0.0.0.0
port: 25500
+15 -8
View File
@@ -19,28 +19,28 @@ exclude_remarks=(到期|剩余流量|时间|官网|产品)
;include_remarks=V3.*港
;Clash config base used by the generator, supports local files/URL
clash_rule_base=base/simple_base.yml
clash_rule_base=base/all_base.tpl
;Surge config base used by the generator, supports local files/URL
surge_rule_base=base/surge.conf
surge_rule_base=base/all_base.tpl
;Surfboard config base used by the generator, supports local files/URL
surfboard_rule_base=base/surfboard.conf
surfboard_rule_base=base/all_base.tpl
;Mellow config base used by the generator, supports local files/URL
mellow_rule_base=base/mellow.conf
mellow_rule_base=base/all_base.tpl
;Quantumult config base used by the generator, supports local files/URL
quan_rule_base=base/quan.conf
quan_rule_base=base/all_base.tpl
;Quantumult X config base used by the generator, supports local files/URL
quanx_rule_base=base/quanx.conf
quanx_rule_base=base/all_base.tpl
;Loon config base used by the generator, supports local files/URL
loon_rule_base=base/loon.conf
loon_rule_base=base/all_base.tpl
;Shadowsocks Android config base used by the generator, supports local files/URL
sssub_rule_base=base/shadowsocks_base.json
sssub_rule_base=base/all_base.tpl
;Proxy used to download configs, rulesets or subscriptions, set to NONE or empty to disable it, set to SYSTEM to use system proxy.
;Accept cURL-supported proxies (http:// https:// socks4a:// socks5://)
@@ -164,6 +164,13 @@ surge_ruleset=!!import:snippets/rulesets.txt
;for Surge rulesets
custom_proxy_group=!!import:snippets/groups.txt
[template]
template_path=template
clash.http_port=7890
clash.socks_port=7891
clash.allow_lan=true
clash.log_level=info
[server]
;Address to bind on for Web Server
listen=0.0.0.0
+3705
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+182 -40
View File
@@ -16,6 +16,7 @@
#include "multithread.h"
#include "logger.h"
#include "string_hash.h"
#include "templates.h"
//common settings
std::string pref_path = "pref.ini";
@@ -29,6 +30,10 @@ std::string access_token;
extern std::string custom_group;
extern int global_log_level;
//global variables for template
std::string template_path;
string_map global_vars;
//generator settings
bool generator_mode = false;
std::string gen_profile;
@@ -513,6 +518,22 @@ void readYAMLConf(YAML::Node &node)
if(node["proxy_group"].IsDefined() && node["proxy_group"]["custom_proxy_group"].IsDefined())
readGroup(node["proxy_group"]["custom_proxy_group"], clash_extra_group, false);
if(node["template"].IsDefined())
{
node["template"]["template_path"] >> template_path;
if(node["template"]["globals"].IsSequence())
{
eraseElements(global_vars);
std::string key, value;
for(size_t i = 0; i < node["template"]["globals"].size(); i++)
{
node["template"]["globals"][i]["key"] >> key;
node["template"]["globals"][i]["value"] >> value;
global_vars[key] = value;
}
}
}
if(node["server"].IsDefined())
{
node["server"]["listen"] >> listen_address;
@@ -715,6 +736,18 @@ void readConf()
importItems(clash_extra_group, false);
}
ini.EnterSection("template");
ini.GetIfExist("template_path", template_path);
string_multimap tempmap;
ini.GetItems(tempmap);
eraseElements(global_vars);
for(auto &x : tempmap)
{
if(x.first == "template_path")
continue;
global_vars[x.first] = x.second;
}
ini.EnterSection("server");
ini.GetIfExist("listen", listen_address);
ini.GetIntIfExist("port", listen_port);
@@ -788,6 +821,7 @@ struct ExternalConfig
string_array emoji;
string_array include;
string_array exclude;
string_map template_args;
bool overwrite_original_rules = false;
bool enable_rule_generator = true;
};
@@ -822,6 +856,17 @@ int loadExternalYAML(YAML::Node &node, ExternalConfig &ext)
section["include_remarks"] >> ext.include;
section["exclude_remarks"] >> ext.exclude;
if(node["template_args"].IsSequence())
{
std::string key, value;
for(size_t i = 0; i < node["template_args"].size(); i++)
{
node["template_args"][i]["key"] >> key;
node["template_args"][i]["value"] >> value;
ext.template_args[key] = value;
}
}
return 0;
}
@@ -891,6 +936,15 @@ int loadExternalConfig(std::string &path, ExternalConfig &ext)
if(ini.ItemPrefixExist("exclude_remarks"))
ini.GetAll("exclude_remarks", ext.exclude);
if(ini.SectionExist("template"))
{
ini.EnterSection("template");
string_multimap tempmap;
ini.GetItems(tempmap);
for(auto &x : tempmap)
ext.template_args[x.first] = x.second;
}
return 0;
}
@@ -962,6 +1016,23 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
return "Invalid request!";
}
//load request arguments as template variables
string_array req_args = split(argument, "&");
string_size pos;
string_map req_arg_map;
for(std::string &x : req_args)
{
pos = x.find("=");
if(pos == x.npos)
continue;
req_arg_map[x.substr(0, pos)] = x.substr(pos + 1);
}
//save template variables
template_args tpl_args;
tpl_args.global_vars = global_vars;
tpl_args.request_params = req_arg_map;
//check if we need to read configuration
if((!api_mode || cfw_child_process) && !generator_mode)
readConf();
@@ -1034,6 +1105,8 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
ext.rename_array = extconf.rename;
if(extconf.emoji.size())
ext.emoji_array = extconf.emoji;
if(extconf.template_args.size())
tpl_args.local_vars = extconf.template_args;
ext.enable_rule_generator = extconf.enable_rule_generator;
//load custom group
if(extconf.custom_proxy_group.size())
@@ -1153,6 +1226,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
case "clash"_hash: case "clashr"_hash:
//std::cerr<<"Clash"<<((target == "clashr") ? "R" : "")<<std::endl;
writeLog(0, target == "clashr" ? "Generate target: ClashR" : "Generate target: Clash", LOG_LEVEL_INFO);
tpl_args.local_vars["clash.new_field_name"] = ext.clash_new_field_name ? "true" : "false";
if(ext.nodelist)
{
YAML::Node yamlnode;
@@ -1161,7 +1235,12 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
}
else if(ruleset_updated || update_ruleset_on_request || ext_clash_base != clash_rule_base || !enable_base_gen)
{
base_content = fetchFile(ext_clash_base, proxy, cache_config);
if(render_template(fetchFile(ext_clash_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
{
*status_code = 400;
return base_content;
}
//base_content = fetchFile(ext_clash_base, proxy, cache_config);
output_content = netchToClash(nodes, base_content, rca, extra_group, target == "clashr", ext);
}
else
@@ -1188,7 +1267,12 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
}
else
{
base_content = fetchFile(ext_surge_base, proxy, cache_config);
if(render_template(fetchFile(ext_surge_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
{
*status_code = 400;
return base_content;
}
//base_content = fetchFile(ext_surge_base, proxy, cache_config);
output_content = netchToSurge(nodes, base_content, rca, extra_group, surge_ver, ext);
if(upload == "true")
@@ -1203,7 +1287,12 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
//std::cerr<<"Surfboard"<<std::endl;
writeLog(0, "Generate target: Surfboard", LOG_LEVEL_INFO);
base_content = fetchFile(ext_surfboard_base, proxy, cache_config);
if(render_template(fetchFile(ext_surfboard_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
{
*status_code = 400;
return base_content;
}
//base_content = fetchFile(ext_surfboard_base, proxy, cache_config);
output_content = netchToSurge(nodes, base_content, rca, extra_group, -3, ext);
if(upload == "true")
uploadGist("surfboard", upload_path, output_content, true);
@@ -1218,7 +1307,12 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
// mellow base generator removed for now
//if(ruleset_updated || update_ruleset_on_request || ext_mellow_base != mellow_rule_base || !enable_base_gen)
{
base_content = fetchFile(ext_mellow_base, proxy, cache_config);
if(render_template(fetchFile(ext_mellow_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
{
*status_code = 400;
return base_content;
}
//base_content = fetchFile(ext_mellow_base, proxy, cache_config);
output_content = netchToMellow(nodes, base_content, rca, extra_group, ext);
}
/*
@@ -1245,7 +1339,12 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
//std::cerr<<"SS Subscription"<<std::endl;
writeLog(0, "Generate target: SS Subscription", LOG_LEVEL_INFO);
base_content = fetchFile(ext_sssub_base, proxy, cache_config);
if(render_template(fetchFile(ext_sssub_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
{
*status_code = 400;
return base_content;
}
//base_content = fetchFile(ext_sssub_base, proxy, cache_config);
output_content = netchToSSSub(base_content, nodes, ext);
if(upload == "true")
uploadGist("sssub", upload_path, output_content, false);
@@ -1268,7 +1367,14 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
//std::cerr<<"Quantumult"<<std::endl;
writeLog(0, "Generate target: Quantumult", LOG_LEVEL_INFO);
if(!ext.nodelist)
base_content = fetchFile(ext_quan_base, proxy, cache_config);
{
if(render_template(fetchFile(ext_quan_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
{
*status_code = 400;
return base_content;
}
//base_content = fetchFile(ext_quan_base, proxy, cache_config);
}
output_content = netchToQuan(nodes, base_content, rca, extra_group, ext);
@@ -1279,7 +1385,15 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
//std::cerr<<"Quantumult X"<<std::endl;
writeLog(0, "Generate target: Quantumult X", LOG_LEVEL_INFO);
if(!ext.nodelist)
base_content = fetchFile(ext_quanx_base, proxy, cache_config);
{
if(render_template(fetchFile(ext_quanx_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
{
*status_code = 400;
return base_content;
}
//base_content = fetchFile(ext_quanx_base, proxy, cache_config);
}
output_content = netchToQuanX(nodes, base_content, rca, extra_group, ext);
@@ -1290,7 +1404,14 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
//std::cerr<<"Loon"<<std::endl;
writeLog(0, "Generate target: Loon", LOG_LEVEL_INFO);
if(!ext.nodelist)
base_content = fetchFile(ext_loon_base, proxy, cache_config);
{
if(render_template(fetchFile(ext_loon_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
{
*status_code = 400;
return base_content;
}
//base_content = fetchFile(ext_loon_base, proxy, cache_config);
}
output_content = netchToLoon(nodes, base_content, rca, extra_group, ext);
@@ -1385,17 +1506,35 @@ std::string simpleToClashR(RESPONSE_CALLBACK_ARGS)
return "No nodes were found!";
}
std::cerr<<"Generate target: ClashR\n";
writeLog(0, "Generate target: ClashR", LOG_LEVEL_INFO);
YAML::Node yamlnode = safe_get_clash_base();
netchToClash(nodes, yamlnode, extra_group, true, ext);
return YAML::Dump(yamlnode);
template_args tpl_args;
tpl_args.global_vars = global_vars;
tpl_args.local_vars["clash.new_field_name"] = clash_use_new_field_name ? "true" : "false";
tpl_args.request_params["target"] = "clashr";
tpl_args.request_params["url"] = url;
if(!enable_base_gen)
{
if(render_template(fetchFile(clash_rule_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
{
*status_code = 400;
return base_content;
}
//base_content = fetchFile(clash_rule_base, proxy, cache_config);
return netchToClash(nodes, base_content, rca, extra_group, true, ext);
}
else
{
YAML::Node yamlnode = safe_get_clash_base();
netchToClash(nodes, yamlnode, extra_group, true, ext);
return YAML::Dump(yamlnode);
}
}
std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS)
{
INIReader ini;
YAML::Node clash = safe_get_clash_base();
string_array dummy_str_array;
std::vector<nodeInfo> nodes;
std::string base_content, url = argument.size() <= 5 ? "" : argument.substr(5), dummy;
@@ -1417,6 +1556,28 @@ std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS)
}
std::string proxy = parseProxy(proxy_config);
YAML::Node clash;
template_args tpl_args;
tpl_args.global_vars = global_vars;
tpl_args.local_vars["clash.new_field_name"] = clash_use_new_field_name ? "true" : "false";
tpl_args.request_params["target"] = "clash";
tpl_args.request_params["url"] = url;
if(!enable_base_gen)
{
if(render_template(fetchFile(clash_rule_base, proxy, cache_config), tpl_args, base_content, template_path) != 0)
{
*status_code = 400;
return base_content;
}
//base_content = fetchFile(clash_rule_base, proxy, cache_config);
clash = YAML::Load(base_content);
}
else
{
clash = safe_get_clash_base();
}
base_content = fetchFile(url, proxy, cache_config);
if(ini.Parse(base_content) != INIREADER_EXCEPTION_NONE)
@@ -1436,8 +1597,6 @@ std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS)
return errmsg;
}
proxy = parseProxy(proxy_subscription);
//scan groups first, get potential policy-path
string_multimap section;
ini.GetItems("Proxy Group", section);
@@ -1472,12 +1631,15 @@ std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS)
clash[proxygroup_name].push_back(singlegroup);
}
proxy = parseProxy(proxy_subscription);
eraseElements(dummy_str_array);
std::string subInfo;
for(std::string &x : links)
{
//std::cerr<<"Fetching node data from url '"<<x<<"'."<<std::endl;
writeLog(0, "Fetching node data from url '" + x + "'.", LOG_LEVEL_INFO);
if(addNodes(x, nodes, 0, proxy, dummy_str_array, dummy_str_array, dummy_str_array, dummy_str_array, subInfo, false) == -1)
if(addNodes(x, nodes, 0, proxy, dummy_str_array, dummy_str_array, dummy_str_array, dummy_str_array, subInfo, !api_mode) == -1)
{
*status_code = 400;
return std::string("The following link doesn't contain any valid node info: " + x);
@@ -1703,9 +1865,9 @@ std::string getRewriteRemote(RESPONSE_CALLBACK_ARGS)
static inline std::string intToStream(unsigned long long stream)
{
char chrs[16] = {};
char chrs[16] = {}, units[6] = {' ', 'K', 'M', 'G', 'T', 'P'};
double streamval = stream;
int level = 0;
unsigned int level = 0;
while(streamval > 1024.0)
{
if(level >= 5)
@@ -1713,27 +1875,7 @@ static inline std::string intToStream(unsigned long long stream)
level++;
streamval /= 1024.0;
}
switch(level)
{
case 3:
snprintf(chrs, 15, "%.2f GB", streamval);
break;
case 4:
snprintf(chrs, 15, "%.2f TB", streamval);
break;
case 5:
snprintf(chrs, 15, "%.2f PB", streamval);
break;
case 2:
snprintf(chrs, 15, "%.2f MB", streamval);
break;
case 1:
snprintf(chrs, 15, "%.2f KB", streamval);
break;
case 0:
snprintf(chrs, 15, "%.2f B", streamval);
break;
}
snprintf(chrs, 15, "%.2f %cB", streamval, units[level]);
return std::string(chrs);
}
@@ -1813,7 +1955,7 @@ int simpleGenerator()
string_multimap allItems;
std::string dummy_str;
std::string proxy = parseProxy(proxy_subscription);
std::map<std::string, std::string> headers;
string_map headers;
int ret_code = 200;
for(std::string &x : sections)
{
+56 -1
View File
@@ -855,6 +855,13 @@ void netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, string_arr
if(edge.size())
singleproxy["ws-headers"]["Edge"] = edge;
break;
case "http"_hash:
singleproxy["network"] = transproto;
singleproxy["http-opts"]["method"] = "GET";
singleproxy["http-opts"]["path"].push_back(path);
singleproxy["http-opts"]["headers"]["Host"].push_back(host);
if(edge.size())
singleproxy["http-opts"]["headers"]["Edge"].push_back(edge);
default:
continue;
}
@@ -1591,7 +1598,7 @@ void netchToQuan(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rules
{
rapidjson::Document json;
std::string type;
std::string remark, hostname, port, method, password;
std::string remark, hostname, port, method, username, password;
std::string plugin, pluginopts;
std::string protocol, protoparam, obfs, obfsparam;
std::string id, aid, transproto, faketype, host, edge, path, quicsecure, quicsecret;
@@ -1644,6 +1651,8 @@ void netchToQuan(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rules
proxyStr += "[Rr][Nn]Edge: " + edge;
proxyStr += "\"";
}
if(ext.skip_cert_verify)
proxyStr += ", certificate=0";
if(ext.nodelist)
proxyStr = "vmess://" + urlsafe_base64_encode(proxyStr);
@@ -1691,6 +1700,52 @@ void netchToQuan(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rules
}
}
break;
case SPEEDTEST_MESSAGE_FOUNDHTTP:
username = GetMember(json, "Username");
host = GetMember(json, "Host");
tlssecure = GetMember(json, "TLSSecure") == "true";
proxyStr = remark + " = http, upstream-proxy-address=" + hostname + ", upstream-proxy-port=" + port + ", group=" + x.group;
if(username.size() && password.size())
proxyStr += ", upstream-proxy-auth=true, upstream-proxy-username=" + username + ", upstream-proxy-password=" + password;
else
proxyStr += ", upstream-proxy-auth=false";
if(tlssecure)
{
proxyStr += ", over-tls=true";
if(host.size())
proxyStr += ", tls-host=" + host;
}
if(ext.skip_cert_verify)
proxyStr += ", certificate=0";
if(ext.nodelist)
proxyStr = "http://" + urlsafe_base64_encode(proxyStr);
break;
case SPEEDTEST_MESSAGE_FOUNDSOCKS:
username = GetMember(json, "Username");
host = GetMember(json, "Host");
tlssecure = GetMember(json, "TLSSecure") == "true";
proxyStr = remark + " = socks, upstream-proxy-address=" + hostname + ", upstream-proxy-port=" + port + ", group=" + x.group;
if(username.size() && password.size())
proxyStr += ", upstream-proxy-auth=true, upstream-proxy-username=" + username + ", upstream-proxy-password=" + password;
else
proxyStr += ", upstream-proxy-auth=false";
if(tlssecure)
{
proxyStr += ", over-tls=true";
if(host.size())
proxyStr += ", tls-host=" + host;
}
if(ext.skip_cert_verify)
proxyStr += ", certificate=0";
if(ext.nodelist)
proxyStr = "socks://" + urlsafe_base64_encode(proxyStr);
break;
default:
continue;
}
+71
View File
@@ -0,0 +1,71 @@
#include <string>
#include <map>
#include <sstream>
#include <inja.hpp>
#include <nlohmann/json.hpp>
#include "templates.h"
#include "logger.h"
#include "misc.h"
static inline void parse_json_pointer(nlohmann::json &json, const std::string &path, const std::string &value)
{
std::string pointer = "/" + replace_all_distinct(path, ".", "/");
json[nlohmann::json::json_pointer(pointer)] = value;
}
int render_template(const std::string &content, const template_args &vars, std::string &output, const std::string &include_scope)
{
nlohmann::json data;
for(auto &x : vars.global_vars)
parse_json_pointer(data["global"], x.first, x.second);
for(auto &x : vars.request_params)
parse_json_pointer(data["request"], x.first, x.second);
for(auto &x : vars.local_vars)
parse_json_pointer(data["local"], x.first, x.second);
inja::LexerConfig m_lexer_config;
inja::FunctionStorage m_callbacks;
inja::TemplateStorage m_included_templates;
inja::ParserConfig m_parser_config;
m_lexer_config.trim_blocks = true;
m_lexer_config.lstrip_blocks = true;
m_callbacks.add_callback("UrlDecode", 1, [](inja::Arguments &args)
{
std::string data = args.at(0)->get<std::string>();
return UrlDecode(data);
});
m_callbacks.add_callback("trim_of", 2, [](inja::Arguments &args)
{
std::string data = args.at(0)->get<std::string>(), target = args.at(1)->get<std::string>();
if(target.empty())
return data;
return trim_of(data, target[0]);
});
m_callbacks.add_callback("trim", 1, [](inja::Arguments &args)
{
std::string data = args.at(0)->get<std::string>();
return trim(data);
});
inja::Parser parser(m_parser_config, m_lexer_config, m_included_templates);
parser.include_scope_limit = true;
parser.include_scope = include_scope;
inja::Renderer renderer(m_included_templates, m_callbacks);
try
{
std::stringstream out;
renderer.render_to(out, parser.parse(content), data);
output = out.str();
return 0;
}
catch (std::exception &e)
{
output = "Template render failed! Reason: " + std::string(e.what());
writeLog(0, output, LOG_LEVEL_ERROR);
return -1;
}
return -2;
}
+18
View File
@@ -0,0 +1,18 @@
#ifndef TEMPLATES_H_INCLUDED
#define TEMPLATES_H_INCLUDED
#include <string>
#include <map>
typedef std::map<std::string, std::string> string_map;
struct template_args
{
string_map global_vars;
string_map request_params;
string_map local_vars;
};
int render_template(const std::string &content, const template_args &vars, std::string &output, const std::string &include_scope = "template");
#endif // TEMPLATES_H_INCLUDED