Fix VMess HTTP nodes missing in exported Clash configurations

Add support for parsing VMess HTTP nodes in Clash configurations.
Clean up codes.
This commit is contained in:
Tindy X 2020-07-04 14:14:55 +08:00
parent ff9820b0a3
commit 8d10020f89
No known key found for this signature in database
GPG Key ID: C6AD413169968D58
6 changed files with 119 additions and 224 deletions

View File

@ -98,7 +98,7 @@ std::string convertRuleset(const std::string &content, int type)
/// Source: QuanX type,pattern[,group] /// Source: QuanX type,pattern[,group]
/// Clash payload:\n - 'ipcidr/domain/classic(Surge-like)' /// Clash payload:\n - 'ipcidr/domain/classic(Surge-like)'
std::string output, strLine, strTemp; std::string output, strLine;
if(type == RULESET_SURGE) if(type == RULESET_SURGE)
return content; return content;
@ -182,7 +182,7 @@ std::string getRuleset(RESPONSE_CALLBACK_ARGS)
std::string output_content, dummy; std::string output_content, dummy;
int type_int = to_int(type, 0); int type_int = to_int(type, 0);
if(!url.size() || !type.size() || (type_int == 2 && !group.size()) || (type_int < 1 && type_int > 6)) if(!url.size() || !type.size() || (type_int == 2 && !group.size()) || (type_int < 1 || type_int > 6))
{ {
*status_code = 400; *status_code = 400;
return "Invalid request!"; return "Invalid request!";
@ -377,7 +377,7 @@ int importItems(string_array &target, bool scope_limit = true)
return 0; return 0;
} }
void readRegexMatch(YAML::Node node, std::string delimiter, string_array &dest, bool scope_limit = true) void readRegexMatch(YAML::Node node, const std::string &delimiter, string_array &dest, bool scope_limit = true)
{ {
YAML::Node object; YAML::Node object;
std::string script, url, match, rep, strLine; std::string script, url, match, rep, strLine;
@ -519,7 +519,7 @@ void readRuleset(YAML::Node node, string_array &dest, bool scope_limit = true)
void refreshRulesets(string_array &ruleset_list, std::vector<ruleset_content> &rca) void refreshRulesets(string_array &ruleset_list, std::vector<ruleset_content> &rca)
{ {
eraseElements(rca); eraseElements(rca);
std::string rule_group, rule_url, rule_url_typed, dummy; std::string rule_group, rule_url, rule_url_typed;
ruleset_content rc; ruleset_content rc;
std::string proxy = parseProxy(proxy_ruleset); std::string proxy = parseProxy(proxy_ruleset);
@ -552,14 +552,11 @@ void refreshRulesets(string_array &ruleset_list, std::vector<ruleset_content> &r
const std::map<std::string, ruleset_type> types = {{"clash-domain:", RULESET_CLASH_DOMAIN}, {"clash-ipcidr:", RULESET_CLASH_IPCIDR}, {"clash-classic:", RULESET_CLASH_CLASSICAL}, \ const std::map<std::string, ruleset_type> types = {{"clash-domain:", RULESET_CLASH_DOMAIN}, {"clash-ipcidr:", RULESET_CLASH_IPCIDR}, {"clash-classic:", RULESET_CLASH_CLASSICAL}, \
{"quanx:", RULESET_QUANX}, {"surge:", RULESET_SURGE}}; {"quanx:", RULESET_QUANX}, {"surge:", RULESET_SURGE}};
rule_url_typed = rule_url; rule_url_typed = rule_url;
for(auto &y : types) auto iter = std::find_if(types.begin(), types.end(), [rule_url](auto y){ return startsWith(rule_url, y.first); });
if(iter != types.end())
{ {
if(startsWith(rule_url, y.first)) rule_url.erase(0, iter->first.size());
{ type = iter->second;
rule_url.erase(0, y.first.size());
type = y.second;
break;
}
} }
//std::cerr<<"Updating ruleset url '"<<rule_url<<"' with group '"<<rule_group<<"'."<<std::endl; //std::cerr<<"Updating ruleset url '"<<rule_url<<"' with group '"<<rule_group<<"'."<<std::endl;
writeLog(0, "Updating ruleset url '" + rule_url + "' with group '" + rule_group + "'.", LOG_LEVEL_INFO); writeLog(0, "Updating ruleset url '" + rule_url + "' with group '" + rule_group + "'.", LOG_LEVEL_INFO);
@ -874,9 +871,7 @@ void readConf()
ini.GetAll("exclude_remarks", def_exclude_remarks); ini.GetAll("exclude_remarks", def_exclude_remarks);
if(ini.ItemPrefixExist("include_remarks")) if(ini.ItemPrefixExist("include_remarks"))
ini.GetAll("include_remarks", def_include_remarks); ini.GetAll("include_remarks", def_include_remarks);
filter_script = ini.GetBool("enable_filter") ? replace_all_distinct(ini.Get("filter_script"), "\\n", "\n") : ""; filter_script = ini.GetBool("enable_filter") ? ini.Get("filter_script"): "";
if(startsWith(filter_script, "path:"))
filter_script = fileGet(filter_script.substr(5), false);
ini.GetIfExist("base_path", base_path); ini.GetIfExist("base_path", base_path);
ini.GetIfExist("clash_rule_base", clash_rule_base); ini.GetIfExist("clash_rule_base", clash_rule_base);
ini.GetIfExist("surge_rule_base", surge_rule_base); ini.GetIfExist("surge_rule_base", surge_rule_base);
@ -909,7 +904,7 @@ void readConf()
tfo_flag.set(ini.Get("tcp_fast_open_flag")); tfo_flag.set(ini.Get("tcp_fast_open_flag"));
scv_flag.set(ini.Get("skip_cert_verify_flag")); scv_flag.set(ini.Get("skip_cert_verify_flag"));
ini.GetBoolIfExist("sort_flag", do_sort); ini.GetBoolIfExist("sort_flag", do_sort);
sort_script = replace_all_distinct(ini.Get("sort_script"), "\\n", "\n"); sort_script = ini.Get("sort_script");
ini.GetBoolIfExist("filter_deprecated_nodes", filter_deprecated); ini.GetBoolIfExist("filter_deprecated_nodes", filter_deprecated);
ini.GetBoolIfExist("append_sub_userinfo", append_userinfo); ini.GetBoolIfExist("append_sub_userinfo", append_userinfo);
ini.GetBoolIfExist("clash_use_new_field_name", clash_use_new_field_name); ini.GetBoolIfExist("clash_use_new_field_name", clash_use_new_field_name);
@ -1011,7 +1006,6 @@ void readConf()
if(ini.SectionExist("aliases")) if(ini.SectionExist("aliases"))
{ {
ini.EnterSection("aliases"); ini.EnterSection("aliases");
string_multimap tempmap;
ini.GetItems(tempmap); ini.GetItems(tempmap);
reset_redirect(); reset_redirect();
for(auto &x : tempmap) for(auto &x : tempmap)
@ -1162,7 +1156,7 @@ int loadExternalYAML(YAML::Node &node, ExternalConfig &ext)
int loadExternalConfig(std::string &path, ExternalConfig &ext) int loadExternalConfig(std::string &path, ExternalConfig &ext)
{ {
std::string base_content, dummy, proxy = parseProxy(proxy_config), config = fetchFile(path, proxy, cache_config); std::string base_content, proxy = parseProxy(proxy_config), config = fetchFile(path, proxy, cache_config);
if(render_template(config, *ext.tpl_args, base_content, template_path) != 0) if(render_template(config, *ext.tpl_args, base_content, template_path) != 0)
base_content = config; base_content = config;
@ -1509,7 +1503,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
ext.emoji_array = safe_get_emojis(); ext.emoji_array = safe_get_emojis();
if(ext_rename.size()) if(ext_rename.size())
ext.rename_array = split(ext_rename, "`"); ext.rename_array = split(ext_rename, "`");
else else if(ext.rename_array.empty())
ext.rename_array = safe_get_renames(); ext.rename_array = safe_get_renames();
//check custom include/exclude settings //check custom include/exclude settings
@ -1574,6 +1568,8 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
//run filter script //run filter script
if(filter_script.size()) if(filter_script.size())
{ {
if(startsWith(filter_script, "path:"))
filter_script = fileGet(filter_script.substr(5), false);
duk_context *ctx = duktape_init(); duk_context *ctx = duktape_init();
if(ctx) if(ctx)
{ {
@ -2155,11 +2151,7 @@ std::string getProfile(RESPONSE_CALLBACK_ARGS)
contents.emplace("token", token); contents.emplace("token", token);
contents.emplace("profile_data", base64_encode(managed_config_prefix + "/getprofile?" + argument)); contents.emplace("profile_data", base64_encode(managed_config_prefix + "/getprofile?" + argument));
std::string query; std::string query = std::accumulate(contents.begin(), contents.end(), std::string(), [](const std::string &x, auto y){ return x + y.first + "=" + UrlEncode(y.second) + "&"; });
for(auto &x : contents)
{
query += x.first + "=" + UrlEncode(x.second) + "&";
}
query += argument; query += argument;
request.argument = query; request.argument = query;
return subconverter(request, response); return subconverter(request, response);
@ -2170,7 +2162,7 @@ std::string getScript(RESPONSE_CALLBACK_ARGS)
std::string &argument = request.argument; std::string &argument = request.argument;
std::string url = urlsafe_base64_decode(getUrlArg(argument, "url")), dev_id = getUrlArg(argument, "id"); std::string url = urlsafe_base64_decode(getUrlArg(argument, "url")), dev_id = getUrlArg(argument, "id");
std::string output_content, dummy; std::string output_content;
std::string proxy = parseProxy(proxy_config); std::string proxy = parseProxy(proxy_config);
@ -2195,7 +2187,7 @@ std::string getRewriteRemote(RESPONSE_CALLBACK_ARGS)
std::string &argument = request.argument; std::string &argument = request.argument;
std::string url = urlsafe_base64_decode(getUrlArg(argument, "url")), dev_id = getUrlArg(argument, "id"); std::string url = urlsafe_base64_decode(getUrlArg(argument, "url")), dev_id = getUrlArg(argument, "id");
std::string output_content, dummy; std::string output_content;
std::string proxy = parseProxy(proxy_config); std::string proxy = parseProxy(proxy_config);
@ -2246,7 +2238,7 @@ std::string parseHostname(inja::Arguments &args)
for(std::string &x : urls) for(std::string &x : urls)
{ {
input_content = webGet(x, proxy, cache_config); input_content = webGet(x, proxy, cache_config);
regGetMatch(input_content, matcher, 2, NULL, &hostname); regGetMatch(input_content, matcher, 2, 0, &hostname);
if(hostname.size()) if(hostname.size())
{ {
output_content += hostname + ","; output_content += hostname + ",";
@ -2432,14 +2424,9 @@ int simpleGenerator()
continue; continue;
} }
fileWrite(path, content, true); fileWrite(path, content, true);
for(auto &y : headers) auto iter = std::find_if(headers.begin(), headers.end(), [](auto y){ return y.first == "Subscription-UserInfo"; });
{ if(iter != headers.end())
if(y.first == "Subscription-UserInfo") writeLog(0, "User Info for artifact '" + x + "': " + subInfoToMessage(iter->second), LOG_LEVEL_INFO);
{
writeLog(0, "User Info for artifact '" + x + "': " + subInfoToMessage(y.second), LOG_LEVEL_INFO);
break;
}
}
//std::cerr<<"Artifact '"<<x<<"' generate SUCCESS!\n\n"; //std::cerr<<"Artifact '"<<x<<"' generate SUCCESS!\n\n";
writeLog(0, "Artifact '" + x + "' generate SUCCESS!\n", LOG_LEVEL_INFO); writeLog(0, "Artifact '" + x + "' generate SUCCESS!\n", LOG_LEVEL_INFO);
eraseElements(headers); eraseElements(headers);

View File

@ -21,7 +21,7 @@
#define CONCAT(a,b) a ## b #define CONCAT(a,b) a ## b
#define DO_CONCAT(a,b) CONCAT(a,b) #define DO_CONCAT(a,b) CONCAT(a,b)
template <typename T> class __defer_struct final {private: T fn; bool __cancelled = false; public: __defer_struct(T func) : fn(std::move(func)) {} ~__defer_struct() {if(!__cancelled) fn();} void cancel() {__cancelled = true;} }; template <typename T> class __defer_struct final {private: T fn; bool __cancelled = false; public: explicit __defer_struct(T func) : fn(std::move(func)) {} ~__defer_struct() {if(!__cancelled) fn();} void cancel() {__cancelled = true;} };
//#define defer(x) std::unique_ptr<void> DO_CONCAT(__defer_deleter_,__LINE__) (nullptr, [&](...){x}); //#define defer(x) std::unique_ptr<void> DO_CONCAT(__defer_deleter_,__LINE__) (nullptr, [&](...){x});
#define defer(x) __defer_struct DO_CONCAT(__defer_deleter,__LINE__) ([&](...){x;}); #define defer(x) __defer_struct DO_CONCAT(__defer_deleter,__LINE__) ([&](...){x;});
@ -79,6 +79,7 @@ std::string UTF8ToCodePoint(const std::string &data);
std::string GetEnv(const std::string &name); std::string GetEnv(const std::string &name);
std::string toLower(const std::string &str); std::string toLower(const std::string &str);
std::string toUpper(const std::string &str); std::string toUpper(const std::string &str);
void ProcessEscapeChar(std::string &str);
std::string fileGet(const std::string &path, bool scope_limit = false); std::string fileGet(const std::string &path, bool scope_limit = false);
int fileWrite(const std::string &path, const std::string &content, bool overwrite); int fileWrite(const std::string &path, const std::string &content, bool overwrite);
@ -147,7 +148,7 @@ public:
template <typename T> tribool(const T &value) { set(value); } template <typename T> tribool(const T &value) { set(value); }
tribool(const tribool &value) { *this = value; } explicit tribool(const tribool &value) { *this = value; }
~tribool() = default; ~tribool() = default;

View File

@ -104,9 +104,9 @@ void explodeVmessConf(std::string content, const std::string &custom_port, bool
std::map<std::string, std::string> subdata; std::map<std::string, std::string> subdata;
std::map<std::string, std::string>::iterator iter; std::map<std::string, std::string>::iterator iter;
std::string streamset = "streamSettings", tcpset = "tcpSettings", wsset = "wsSettings"; std::string streamset = "streamSettings", tcpset = "tcpSettings", wsset = "wsSettings";
regGetMatch(content, "((?i)streamsettings)", 2, NULL, &streamset); regGetMatch(content, "((?i)streamsettings)", 2, 0, &streamset);
regGetMatch(content, "((?i)tcpsettings)", 2, NULL, &tcpset); regGetMatch(content, "((?i)tcpsettings)", 2, 0, &tcpset);
regGetMatch(content, "((?1)wssettings)", 2, NULL, &wsset); regGetMatch(content, "((?1)wssettings)", 2, 0, &wsset);
json.Parse(content.data()); json.Parse(content.data());
if(json.HasParseError()) if(json.HasParseError())
@ -276,37 +276,14 @@ void explodeSS(std::string ss, bool libev, const std::string &custom_port, nodeI
} }
if(strFind(ss, "@")) if(strFind(ss, "@"))
{ {
/* if(regGetMatch(ss, "(.*?)@(.*):(.*)", 4, 0, &secret, &server, &port))
ss = regReplace(ss, "(.*?)@(.*):(.*)", "$1|$2|$3");
args = split(ss, "|");
secret = split(urlsafe_base64_decode(args[0]), ":");
if(args.size() < 3 || secret.size() < 2)
return; return;
method = secret[0]; if(regGetMatch(urlsafe_base64_decode(secret), "(.*?):(.*)", 3, 0, &method, &password))
password = secret[1];
server = args[1];
port = custom_port.empty() ? args[2] : custom_port;
*/
if(regGetMatch(ss, "(.*?)@(.*):(.*)", 4, NULL, &secret, &server, &port))
return;
if(regGetMatch(urlsafe_base64_decode(secret), "(.*?):(.*)", 3, NULL, &method, &password))
return; return;
} }
else else
{ {
/* if(regGetMatch(urlsafe_base64_decode(ss), "(.*?):(.*)@(.*):(.*)", 5, 0, &method, &password, &server, &port))
if(!regMatch(urlsafe_base64_decode(ss), "(.*?):(.*?)@(.*):(.*)"))
return;
ss = regReplace(urlsafe_base64_decode(ss), "(.*?):(.*?)@(.*):(.*)", "$1|$2|$3|$4");
args = split(ss, "|");
if(args.size() < 4)
return;
method = args[0];
password = args[1];
server = args[2];
port = custom_port.empty() ? args[3] : custom_port;
*/
if(regGetMatch(urlsafe_base64_decode(ss), "(.*?):(.*)@(.*):(.*)", 5, NULL, &method, &password, &server, &port))
return; return;
} }
if(custom_port.size()) if(custom_port.size())
@ -496,7 +473,6 @@ void explodeSSConf(std::string content, const std::string &custom_port, bool lib
void explodeSSR(std::string ssr, bool ss_libev, bool ssr_libev, const std::string &custom_port, nodeInfo &node) void explodeSSR(std::string ssr, bool ss_libev, bool ssr_libev, const std::string &custom_port, nodeInfo &node)
{ {
std::string strobfs; std::string strobfs;
std::vector<std::string> strcfg;
std::string remarks, group, server, port, method, password, protocol, protoparam, obfs, obfsparam, remarks_base64; std::string remarks, group, server, port, method, password, protocol, protoparam, obfs, obfsparam, remarks_base64;
ssr = replace_all_distinct(ssr.substr(6), "\r", ""); ssr = replace_all_distinct(ssr.substr(6), "\r", "");
ssr = urlsafe_base64_decode(ssr); ssr = urlsafe_base64_decode(ssr);
@ -511,21 +487,7 @@ void explodeSSR(std::string ssr, bool ss_libev, bool ssr_libev, const std::strin
protoparam = regReplace(urlsafe_base64_decode(getUrlArg(strobfs, "protoparam")), "\\s", ""); protoparam = regReplace(urlsafe_base64_decode(getUrlArg(strobfs, "protoparam")), "\\s", "");
} }
/* if(regGetMatch(ssr, "(.*):(.*?):(.*?):(.*?):(.*?):(.*)", 7, 0, &server, &port, &protocol, &method, &obfs, &password))
ssr = regReplace(ssr, "(.*):(.*?):(.*?):(.*?):(.*?):(.*)", "$1|$2|$3|$4|$5|$6");
strcfg = split(ssr, "|");
if(strcfg.size() != 6)
return;
server = strcfg[0];
port = custom_port.empty() ? strcfg[1] : custom_port;
protocol = strcfg[2];
method = strcfg[3];
obfs = strcfg[4];
password = urlsafe_base64_decode(strcfg[5]);
*/
if(regGetMatch(ssr, "(.*):(.*?):(.*?):(.*?):(.*?):(.*)", 7, NULL, &server, &port, &protocol, &method, &obfs, &password))
return; return;
password = urlsafe_base64_decode(password); password = urlsafe_base64_decode(password);
if(custom_port.size()) if(custom_port.size())
@ -677,7 +639,7 @@ void explodeSocks(std::string link, const std::string &custom_port, nodeInfo &no
node.proxyStr = socksConstruct(group, remarks, server, port, username, password); node.proxyStr = socksConstruct(group, remarks, server, port, username, password);
} }
void explodeHTTP(std::string link, const std::string &custom_port, nodeInfo &node) void explodeHTTP(const std::string link, const std::string &custom_port, nodeInfo &node)
{ {
std::string group, remarks, server, port, username, password; std::string group, remarks, server, port, username, password;
server = getUrlArg(link, "server"); server = getUrlArg(link, "server");
@ -708,7 +670,6 @@ void explodeHTTPSub(std::string link, const std::string &custom_port, nodeInfo &
{ {
std::string group, remarks, server, port, username, password; std::string group, remarks, server, port, username, password;
std::string addition; std::string addition;
string_array configs;
bool tls = strFind(link, "https://"); bool tls = strFind(link, "https://");
string_size pos = link.find("?"); string_size pos = link.find("?");
if(pos != link.npos) if(pos != link.npos)
@ -722,30 +683,12 @@ void explodeHTTPSub(std::string link, const std::string &custom_port, nodeInfo &
link = urlsafe_base64_decode(link); link = urlsafe_base64_decode(link);
if(strFind(link, "@")) if(strFind(link, "@"))
{ {
/* if(regGetMatch(link, "(.*?):(.*?)@(.*):(.*)", 5, 0, &username, &password, &server, &port))
link = regReplace(link, "(.*?):(.*?)@(.*):(.*)", "$1|$2|$3|$4");
configs = split(link, "|");
if(configs.size() != 4)
return;
username = configs[0];
password = configs[1];
server = configs[2];
port = configs[3];
*/
if(regGetMatch(link, "(.*?):(.*?)@(.*):(.*)", 5, NULL, &username, &password, &server, &port))
return; return;
} }
else else
{ {
/* if(regGetMatch(link, "(.*):(.*)", 3, 0, &server, &port))
link = regReplace(link, "(.*):(.*)", "$1|$2");
configs = split(link, "|");
if(configs.size() != 2)
return;
server = configs[1];
port = configs[2];
*/
if(regGetMatch(link, "(.*):(.*)", 3, NULL, &server, &port))
return; return;
} }
@ -770,7 +713,6 @@ void explodeTrojan(std::string trojan, const std::string &custom_port, nodeInfo
{ {
std::string server, port, psk, addition, remark, host; std::string server, port, psk, addition, remark, host;
tribool tfo, scv; tribool tfo, scv;
string_array vArray;
trojan.erase(0, 9); trojan.erase(0, 9);
string_size pos = trojan.rfind("#"); string_size pos = trojan.rfind("#");
@ -786,17 +728,7 @@ void explodeTrojan(std::string trojan, const std::string &custom_port, nodeInfo
trojan.erase(pos); trojan.erase(pos);
} }
/* if(regGetMatch(trojan, "(.*?)@(.*):(.*)", 4, 0, &psk, &server, &port))
trojan = regReplace(trojan, "(.*?)@(.*):(.*)", "$1|$2|$3");
vArray = split(trojan, "|");
if(vArray.size() != 3)
return;
psk = vArray[0];
server = vArray[1];
port = custom_port.empty() ? vArray[2] : custom_port;
*/
if(regGetMatch(trojan, "(.*?)@(.*):(.*)", 4, NULL, &psk, &server, &port))
return; return;
if(custom_port.size()) if(custom_port.size())
port = custom_port; port = custom_port;
@ -820,10 +752,10 @@ void explodeTrojan(std::string trojan, const std::string &custom_port, nodeInfo
node.proxyStr = trojanConstruct(node.group, remark, server, port, psk, host, true, tribool(), tfo, scv); node.proxyStr = trojanConstruct(node.group, remark, server, port, psk, host, true, tribool(), tfo, scv);
} }
void explodeQuan(std::string quan, const std::string &custom_port, nodeInfo &node) void explodeQuan(const std::string &quan, const std::string &custom_port, nodeInfo &node)
{ {
std::string strTemp, itemName, itemVal; std::string strTemp, itemName, itemVal;
std::string group = V2RAY_DEFAULT_GROUP, ps, add, port, cipher = "auto", type = "none", id, aid = "0", net = "tcp", path, host, edge, tls; std::string group = V2RAY_DEFAULT_GROUP, ps, add, port, cipher, type = "none", id, aid = "0", net = "tcp", path, host, edge, tls;
string_array configs, vArray, headers; string_array configs, vArray, headers;
strTemp = regReplace(quan, "(.*?) = (.*)", "$1,$2"); strTemp = regReplace(quan, "(.*?) = (.*)", "$1,$2");
configs = split(strTemp, ","); configs = split(strTemp, ",");
@ -980,7 +912,7 @@ void explodeNetch(std::string netch, bool ss_libev, bool ssr_libev, const std::s
if(group.empty()) if(group.empty())
group = TROJAN_DEFAULT_GROUP; group = TROJAN_DEFAULT_GROUP;
node.group = group; node.group = group;
node.proxyStr = trojanConstruct(group, remark, address, port, username, password, tls == "true", udp, tfo, scv); node.proxyStr = trojanConstruct(group, remark, address, port, password, host, tls == "true", udp, tfo, scv);
break; break;
case "Snell"_hash: case "Snell"_hash:
obfs = GetMember(json, "OBFS"); obfs = GetMember(json, "OBFS");
@ -1032,13 +964,22 @@ void explodeClash(Node yamlnode, const std::string &custom_port, std::vector<nod
singleproxy["alterId"] >>= aid; singleproxy["alterId"] >>= aid;
singleproxy["cipher"] >>= cipher; singleproxy["cipher"] >>= cipher;
net = singleproxy["network"].IsDefined() ? safe_as<std::string>(singleproxy["network"]) : "tcp"; net = singleproxy["network"].IsDefined() ? safe_as<std::string>(singleproxy["network"]) : "tcp";
path = singleproxy["ws-path"].IsDefined() ? safe_as<std::string>(singleproxy["ws-path"]) : "/"; if(net == "http")
{
singleproxy["http-opts"]["path"][0] >>= path;
singleproxy["http-opts"]["headers"]["Host"][0] >>= host;
edge.clear();
}
else
{
path = singleproxy["ws-path"].IsDefined() ? safe_as<std::string>(singleproxy["ws-path"]) : "/";
singleproxy["ws-headers"]["Host"] >>= host;
singleproxy["ws-headers"]["Edge"] >>= edge;
}
tls = safe_as<std::string>(singleproxy["tls"]) == "true" ? "tls" : ""; tls = safe_as<std::string>(singleproxy["tls"]) == "true" ? "tls" : "";
singleproxy["ws-headers"]["Host"] >>= host;
singleproxy["ws-headers"]["Edge"] >>= edge;
node.linkType = SPEEDTEST_MESSAGE_FOUNDVMESS; node.linkType = SPEEDTEST_MESSAGE_FOUNDVMESS;
node.proxyStr = vmessConstruct(group, ps, server, port, type, id, aid, net, cipher, path, host, edge, tls, udp, tfo, scv); node.proxyStr = vmessConstruct(group, ps, server, port, "", id, aid, net, cipher, path, host, edge, tls, udp, tfo, scv);
break; break;
case "ss"_hash: case "ss"_hash:
group = SS_DEFAULT_GROUP; group = SS_DEFAULT_GROUP;
@ -1179,22 +1120,12 @@ void explodeShadowrocket(std::string rocket, const std::string &custom_port, nod
std::string add, port, type, id, aid, net = "tcp", path, host, tls, cipher, remarks; std::string add, port, type, id, aid, net = "tcp", path, host, tls, cipher, remarks;
std::string obfs; //for other style of link std::string obfs; //for other style of link
std::string addition; std::string addition;
string_array userinfo;
rocket = rocket.substr(8); rocket = rocket.substr(8);
addition = rocket.substr(rocket.find("?") + 1); addition = rocket.substr(rocket.find("?") + 1);
rocket = rocket.substr(0, rocket.find("?")); rocket = rocket.substr(0, rocket.find("?"));
/* if(regGetMatch(urlsafe_base64_decode(rocket), "(.*?):(.*)@(.*):(.*)", 5, 0, &cipher, &id, &add, &port))
userinfo = split(regReplace(urlsafe_base64_decode(rocket), "(.*?):(.*?)@(.*):(.*)", "$1,$2,$3,$4"), ",");
if(userinfo.size() != 4) // broken link
return;
cipher = userinfo[0];
id = userinfo[1];
add = userinfo[2];
port = custom_port.size() ? custom_port : userinfo[3];
*/
if(regGetMatch(urlsafe_base64_decode(rocket), "(.*?):(.*)@(.*):(.*)", 5, NULL, &cipher, &id, &add, &port))
return; return;
if(custom_port.size()) if(custom_port.size())
port = custom_port; port = custom_port;
@ -1239,7 +1170,6 @@ void explodeKitsunebi(std::string kit, const std::string &custom_port, nodeInfo
std::string add, port, type, id, aid = "0", net = "tcp", path, host, tls, cipher = "auto", remarks; std::string add, port, type, id, aid = "0", net = "tcp", path, host, tls, cipher = "auto", remarks;
std::string addition; std::string addition;
string_size pos; string_size pos;
string_array userinfo;
kit = kit.substr(9); kit = kit.substr(9);
pos = kit.find("#"); pos = kit.find("#");
@ -1253,15 +1183,7 @@ void explodeKitsunebi(std::string kit, const std::string &custom_port, nodeInfo
addition = kit.substr(pos + 1); addition = kit.substr(pos + 1);
kit = kit.substr(0, pos); kit = kit.substr(0, pos);
/* if(regGetMatch(kit, "(.*?)@(.*):(.*)", 4, 0, &id, &add, &port))
userinfo = split(regReplace(kit, "(.*?)@(.*):(.*)", "$1,$2,$3"), ",");
if(userinfo.size() != 3)
return;
id = userinfo[0];
add = userinfo[1];
pos = userinfo[2].find("/");
*/
if(regGetMatch(kit, "(.*?)@(.*):(.*)", 4, NULL, &id, &add, &port))
return; return;
pos = port.find("/"); pos = port.find("/");
if(pos != port.npos) if(pos != port.npos)
@ -1331,7 +1253,7 @@ bool explodeSurge(std::string surge, const std::string &custom_port, std::vector
remarks = regReplace(x.second, proxystr, "$1"); remarks = regReplace(x.second, proxystr, "$1");
configs = split(regReplace(x.second, proxystr, "$2"), ","); configs = split(regReplace(x.second, proxystr, "$2"), ",");
*/ */
regGetMatch(x.second, proxystr, 3, NULL, &remarks, &config); regGetMatch(x.second, proxystr, 3, 0, &remarks, &config);
configs = split(config, ","); configs = split(config, ",");
if(configs.size() < 3) if(configs.size() < 3)
continue; continue;
@ -1880,14 +1802,14 @@ bool chkIgnore(const nodeInfo &node, string_array &exclude_remarks, string_array
//std::string remarks = UTF8ToACP(node.remarks); //std::string remarks = UTF8ToACP(node.remarks);
std::string remarks = node.remarks; std::string remarks = node.remarks;
//writeLog(LOG_TYPE_INFO, "Comparing exclude remarks..."); //writeLog(LOG_TYPE_INFO, "Comparing exclude remarks...");
excluded = std::any_of(exclude_remarks.cbegin(), exclude_remarks.cend(), [&remarks](auto &x) excluded = std::any_of(exclude_remarks.cbegin(), exclude_remarks.cend(), [&remarks](const auto &x)
{ {
return regFind(remarks, x); return regFind(remarks, x);
}); });
if(include_remarks.size() != 0) if(include_remarks.size() != 0)
{ {
//writeLog(LOG_TYPE_INFO, "Comparing include remarks..."); //writeLog(LOG_TYPE_INFO, "Comparing include remarks...");
included = std::any_of(include_remarks.cbegin(), include_remarks.cend(), [&remarks](auto &x) included = std::any_of(include_remarks.cbegin(), include_remarks.cend(), [&remarks](const auto &x)
{ {
return regFind(remarks, x); return regFind(remarks, x);
}); });
@ -1912,7 +1834,7 @@ int explodeConf(std::string filepath, const std::string &custom_port, bool sslib
return explodeConfContent(contentstrm.str(), custom_port, sslibev, ssrlibev, nodes); return explodeConfContent(contentstrm.str(), custom_port, sslibev, ssrlibev, nodes);
} }
int explodeConfContent(std::string content, const std::string &custom_port, bool sslibev, bool ssrlibev, std::vector<nodeInfo> &nodes) int explodeConfContent(const std::string &content, const std::string &custom_port, bool sslibev, bool ssrlibev, std::vector<nodeInfo> &nodes)
{ {
int filetype = -1; int filetype = -1;
@ -2071,7 +1993,7 @@ void filterNodes(std::vector<nodeInfo> &nodes, string_array &exclude_remarks, st
} }
*/ */
bool excluded = false, included = false; bool excluded, included;
std::vector<std::unique_ptr<pcre2_code, decltype(&pcre2_code_free)>> exclude_patterns, include_patterns; std::vector<std::unique_ptr<pcre2_code, decltype(&pcre2_code_free)>> exclude_patterns, include_patterns;
std::vector<std::unique_ptr<pcre2_match_data, decltype(&pcre2_match_data_free)>> exclude_match_data, include_match_data; std::vector<std::unique_ptr<pcre2_match_data, decltype(&pcre2_match_data_free)>> exclude_match_data, include_match_data;
unsigned int i = 0; unsigned int i = 0;
@ -2208,12 +2130,12 @@ time_t dateStringToTimestamp(std::string date)
} }
} }
bool getSubInfoFromHeader(std::string &header, std::string &result) bool getSubInfoFromHeader(const std::string &header, std::string &result)
{ {
std::string pattern = R"(^(?i:Subscription-UserInfo): (.*?)\s*?$)", retStr; std::string pattern = R"(^(?i:Subscription-UserInfo): (.*?)\s*?$)", retStr;
if(regFind(header, pattern)) if(regFind(header, pattern))
{ {
regGetMatch(header, pattern, 2, NULL, &retStr); regGetMatch(header, pattern, 2, 0, &retStr);
if(retStr.size()) if(retStr.size())
{ {
result = retStr; result = retStr;
@ -2223,17 +2145,17 @@ bool getSubInfoFromHeader(std::string &header, std::string &result)
return false; return false;
} }
bool getSubInfoFromNodes(std::vector<nodeInfo> &nodes, string_array &stream_rules, string_array &time_rules, std::string &result) bool getSubInfoFromNodes(const std::vector<nodeInfo> &nodes, const string_array &stream_rules, const string_array &time_rules, std::string &result)
{ {
std::string remarks, pattern, target, stream_info, time_info, retStr; std::string remarks, pattern, target, stream_info, time_info, retStr;
string_size spos; string_size spos;
for(nodeInfo &x : nodes) for(const nodeInfo &x : nodes)
{ {
remarks = x.remarks; remarks = x.remarks;
if(!stream_info.size()) if(!stream_info.size())
{ {
for(std::string &y : stream_rules) for(const std::string &y : stream_rules)
{ {
spos = y.rfind("|"); spos = y.rfind("|");
if(spos == y.npos) if(spos == y.npos)
@ -2257,7 +2179,7 @@ bool getSubInfoFromNodes(std::vector<nodeInfo> &nodes, string_array &stream_rule
remarks = x.remarks; remarks = x.remarks;
if(!time_info.size()) if(!time_info.size())
{ {
for(std::string &y : time_rules) for(const std::string &y : time_rules)
{ {
spos = y.rfind("|"); spos = y.rfind("|");
if(spos == y.npos) if(spos == y.npos)
@ -2286,7 +2208,7 @@ bool getSubInfoFromNodes(std::vector<nodeInfo> &nodes, string_array &stream_rule
return false; return false;
//calculate how much stream left //calculate how much stream left
unsigned long long total = 0, left = 0, used = 0, expire = 0; unsigned long long total = 0, left, used = 0, expire = 0;
std::string total_str = getUrlArg(stream_info, "total"), left_str = getUrlArg(stream_info, "left"), used_str = getUrlArg(stream_info, "used"); std::string total_str = getUrlArg(stream_info, "total"), left_str = getUrlArg(stream_info, "left"), used_str = getUrlArg(stream_info, "used");
if(strFind(total_str, "%")) if(strFind(total_str, "%"))
{ {
@ -2326,7 +2248,7 @@ bool getSubInfoFromNodes(std::vector<nodeInfo> &nodes, string_array &stream_rule
return true; return true;
} }
bool getSubInfoFromSSD(std::string &sub, std::string &result) bool getSubInfoFromSSD(const std::string &sub, std::string &result)
{ {
rapidjson::Document json; rapidjson::Document json;
json.Parse(urlsafe_base64_decode(sub.substr(6)).data()); json.Parse(urlsafe_base64_decode(sub.substr(6)).data());

View File

@ -74,17 +74,8 @@ std::string hostnameToIPAddr(const std::string &host)
return retAddr; return retAddr;
} }
std::string vmessConstruct(std::string group, std::string remarks, std::string add, std::string port, std::string type, std::string id, std::string aid, std::string net, std::string cipher, std::string path, std::string host, std::string edge, std::string tls, tribool udp, tribool tfo, tribool scv) std::string vmessConstruct(const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &type, const std::string &id, const std::string &aid, const std::string &net, const std::string &cipher, const std::string &path, const std::string &host, const std::string &edge, const std::string &tls, tribool udp, tribool tfo, tribool scv)
{ {
if(!path.size())
path = "/";
if(!host.size())
host = add;
if(!id.size())
id = "00000000-0000-0000-0000-000000000000"; //fill this field for node with empty id
host = trim(host);
path = trim(path);
rapidjson::StringBuffer sb; rapidjson::StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer> writer(sb); rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
writer.StartObject(); writer.StartObject();
@ -99,7 +90,7 @@ std::string vmessConstruct(std::string group, std::string remarks, std::string a
writer.Key("Port"); writer.Key("Port");
writer.Int(to_int(port)); writer.Int(to_int(port));
writer.Key("UserID"); writer.Key("UserID");
writer.String(id.data()); writer.String(id.size() ? id.data() : "00000000-0000-0000-0000-000000000000");
writer.Key("AlterID"); writer.Key("AlterID");
writer.Int(to_int(aid)); writer.Int(to_int(aid));
writer.Key("EncryptMethod"); writer.Key("EncryptMethod");
@ -107,13 +98,13 @@ std::string vmessConstruct(std::string group, std::string remarks, std::string a
writer.Key("TransferProtocol"); writer.Key("TransferProtocol");
writer.String(net.data()); writer.String(net.data());
writer.Key("Host"); writer.Key("Host");
writer.String(host.data()); writer.String(host.size() ? trim(host).data() : add.data());
writer.Key("Edge"); writer.Key("Edge");
writer.String(edge.data()); writer.String(edge.data());
if(net == "ws") if(net == "ws" || net == "http")
{ {
writer.Key("Path"); writer.Key("Path");
writer.String(path.data()); writer.String(path.size() ? trim(path).data() : "/");
} }
else else
{ {
@ -148,7 +139,7 @@ std::string vmessConstruct(std::string group, std::string remarks, std::string a
return sb.GetString(); return sb.GetString();
} }
std::string ssrConstruct(std::string group, std::string remarks, std::string remarks_base64, std::string server, std::string port, std::string protocol, std::string method, std::string obfs, std::string password, std::string obfsparam, std::string protoparam, bool libev, tribool udp, tribool tfo, tribool scv) std::string ssrConstruct(const std::string &group, const std::string &remarks, const std::string &remarks_base64, const std::string &server, const std::string &port, const std::string &protocol, const std::string &method, const std::string &obfs, const std::string &password, const std::string &obfsparam, const std::string &protoparam, bool libev, tribool udp, tribool tfo, tribool scv)
{ {
rapidjson::StringBuffer sb; rapidjson::StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer> writer(sb); rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
@ -192,7 +183,7 @@ std::string ssrConstruct(std::string group, std::string remarks, std::string rem
return sb.GetString(); return sb.GetString();
} }
std::string ssConstruct(std::string group, std::string remarks, std::string server, std::string port, std::string password, std::string method, std::string plugin, std::string pluginopts, bool libev, tribool udp, tribool tfo, tribool scv) std::string ssConstruct(const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &method, const std::string &plugin, const std::string &pluginopts, bool libev, tribool udp, tribool tfo, tribool scv)
{ {
rapidjson::StringBuffer sb; rapidjson::StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer> writer(sb); rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
@ -234,7 +225,7 @@ std::string ssConstruct(std::string group, std::string remarks, std::string serv
return sb.GetString(); return sb.GetString();
} }
std::string socksConstruct(std::string group, std::string remarks, std::string server, std::string port, std::string username, std::string password, tribool udp, tribool tfo, tribool scv) std::string socksConstruct(const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &username, const std::string &password, tribool udp, tribool tfo, tribool scv)
{ {
rapidjson::StringBuffer sb; rapidjson::StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer> writer(sb); rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
@ -272,7 +263,7 @@ std::string socksConstruct(std::string group, std::string remarks, std::string s
return sb.GetString(); return sb.GetString();
} }
std::string httpConstruct(std::string group, std::string remarks, std::string server, std::string port, std::string username, std::string password, bool tls, tribool scv) std::string httpConstruct(const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &username, const std::string &password, bool tls, tribool scv)
{ {
rapidjson::StringBuffer sb; rapidjson::StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer> writer(sb); rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
@ -300,7 +291,7 @@ std::string httpConstruct(std::string group, std::string remarks, std::string se
return sb.GetString(); return sb.GetString();
} }
std::string trojanConstruct(std::string group, std::string remarks, std::string server, std::string port, std::string password, std::string host, bool tlssecure, tribool udp, tribool tfo, tribool scv) std::string trojanConstruct(const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &host, bool tlssecure, tribool udp, tribool tfo, tribool scv)
{ {
rapidjson::StringBuffer sb; rapidjson::StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer> writer(sb); rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
@ -340,7 +331,7 @@ std::string trojanConstruct(std::string group, std::string remarks, std::string
return sb.GetString(); return sb.GetString();
} }
std::string snellConstruct(std::string group, std::string remarks, std::string server, std::string port, std::string password, std::string obfs, std::string host, tribool udp, tribool tfo, tribool scv) std::string snellConstruct(const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &obfs, const std::string &host, tribool udp, tribool tfo, tribool scv)
{ {
rapidjson::StringBuffer sb; rapidjson::StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer> writer(sb); rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
@ -380,7 +371,7 @@ std::string snellConstruct(std::string group, std::string remarks, std::string s
return sb.GetString(); return sb.GetString();
} }
std::string vmessLinkConstruct(std::string remarks, std::string add, std::string port, std::string type, std::string id, std::string aid, std::string net, std::string path, std::string host, std::string tls) std::string vmessLinkConstruct(const std::string &remarks, const std::string &add, const std::string &port, const std::string &type, const std::string &id, const std::string &aid, const std::string &net, const std::string &path, const std::string &host, const std::string &tls)
{ {
rapidjson::StringBuffer sb; rapidjson::StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer> writer(sb); rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
@ -411,12 +402,12 @@ std::string vmessLinkConstruct(std::string remarks, std::string add, std::string
return sb.GetString(); return sb.GetString();
} }
bool matchRange(std::string &range, int target) bool matchRange(const std::string &range, int target)
{ {
string_array vArray = split(range, ","); string_array vArray = split(range, ",");
bool match = false; bool match = false;
std::string range_begin_str, range_end_str; std::string range_begin_str, range_end_str;
int range_begin = 0, range_end = 0; int range_begin, range_end;
static const std::string reg_num = "-?\\d+", reg_range = "(\\d+)-(\\d+)", reg_not = "\\!-?(\\d+)", reg_not_range = "\\!(\\d+)-(\\d+)", reg_less = "(\\d+)-", reg_more = "(\\d+)\\+"; static const std::string reg_num = "-?\\d+", reg_range = "(\\d+)-(\\d+)", reg_not = "\\!-?(\\d+)", reg_not_range = "\\!(\\d+)-(\\d+)", reg_less = "(\\d+)-", reg_more = "(\\d+)\\+";
for(std::string &x : vArray) for(std::string &x : vArray)
{ {
@ -431,7 +422,7 @@ bool matchRange(std::string &range, int target)
range_begin = to_int(regReplace(x, reg_range, "$1"), INT_MAX); range_begin = to_int(regReplace(x, reg_range, "$1"), INT_MAX);
range_end = to_int(regReplace(x, reg_range, "$2"), INT_MIN); range_end = to_int(regReplace(x, reg_range, "$2"), INT_MIN);
*/ */
regGetMatch(x, reg_range, 3, NULL, &range_begin_str, &range_end_str); regGetMatch(x, reg_range, 3, 0, &range_begin_str, &range_end_str);
range_begin = to_int(range_begin_str, INT_MAX); range_begin = to_int(range_begin_str, INT_MAX);
range_end = to_int(range_end_str, INT_MIN); range_end = to_int(range_end_str, INT_MIN);
if(target >= range_begin && target <= range_end) if(target >= range_begin && target <= range_end)
@ -448,7 +439,7 @@ bool matchRange(std::string &range, int target)
range_begin = to_int(regReplace(x, reg_range, "$1"), INT_MAX); range_begin = to_int(regReplace(x, reg_range, "$1"), INT_MAX);
range_end = to_int(regReplace(x, reg_range, "$2"), INT_MIN); range_end = to_int(regReplace(x, reg_range, "$2"), INT_MIN);
*/ */
regGetMatch(x, reg_range, 3, NULL, &range_begin_str, &range_end_str); regGetMatch(x, reg_range, 3, 0, &range_begin_str, &range_end_str);
range_begin = to_int(range_begin_str, INT_MAX); range_begin = to_int(range_begin_str, INT_MAX);
range_end = to_int(range_end_str, INT_MIN); range_end = to_int(range_end_str, INT_MIN);
if(target >= range_begin && target <= range_end) if(target >= range_begin && target <= range_end)
@ -474,14 +465,14 @@ bool applyMatcher(const std::string &rule, std::string &real_rule, const nodeInf
static const std::string groupid_regex = R"(^!!(?:GROUPID|INSERT)=([\d\-+!,]+)(?:!!(.*))?$)", group_regex = R"(^!!(?:GROUP)=(.*?)(?:!!(.*))?$)"; static const std::string groupid_regex = R"(^!!(?:GROUPID|INSERT)=([\d\-+!,]+)(?:!!(.*))?$)", group_regex = R"(^!!(?:GROUP)=(.*?)(?:!!(.*))?$)";
if(startsWith(rule, "!!GROUP=")) if(startsWith(rule, "!!GROUP="))
{ {
regGetMatch(rule, group_regex, 3, NULL, &group, &ret_real_rule); regGetMatch(rule, group_regex, 3, 0, &group, &ret_real_rule);
real_rule = ret_real_rule; real_rule = ret_real_rule;
return regFind(node.group, group); return regFind(node.group, group);
} }
else if(startsWith(rule, "!!GROUPID=") || startsWith(rule, "!!INSERT=")) else if(startsWith(rule, "!!GROUPID=") || startsWith(rule, "!!INSERT="))
{ {
int dir = startsWith(rule, "!!INSERT=") ? -1 : 1; int dir = startsWith(rule, "!!INSERT=") ? -1 : 1;
regGetMatch(rule, groupid_regex, 3, NULL, &group, &ret_real_rule); regGetMatch(rule, groupid_regex, 3, 0, &group, &ret_real_rule);
real_rule = ret_real_rule; real_rule = ret_real_rule;
return matchRange(group, dir * node.groupID); return matchRange(group, dir * node.groupID);
} }
@ -618,7 +609,7 @@ void processRemark(std::string &oldremark, std::string &newremark, string_array
void rulesetToClash(YAML::Node &base_rule, std::vector<ruleset_content> &ruleset_content_array, bool overwrite_original_rules, bool new_field_name) void rulesetToClash(YAML::Node &base_rule, std::vector<ruleset_content> &ruleset_content_array, bool overwrite_original_rules, bool new_field_name)
{ {
string_array allRules, vArray; string_array allRules;
std::string rule_group, retrieved_rules, strLine; std::string rule_group, retrieved_rules, strLine;
std::stringstream strStrm; std::stringstream strStrm;
const std::string field_name = new_field_name ? "rules" : "Rule"; const std::string field_name = new_field_name ? "rules" : "Rule";
@ -706,7 +697,6 @@ void rulesetToClash(YAML::Node &base_rule, std::vector<ruleset_content> &ruleset
std::string rulesetToClashStr(YAML::Node &base_rule, std::vector<ruleset_content> &ruleset_content_array, bool overwrite_original_rules, bool new_field_name) std::string rulesetToClashStr(YAML::Node &base_rule, std::vector<ruleset_content> &ruleset_content_array, bool overwrite_original_rules, bool new_field_name)
{ {
string_array allRules, vArray;
std::string rule_group, retrieved_rules, strLine; std::string rule_group, retrieved_rules, strLine;
std::stringstream strStrm; std::stringstream strStrm;
const std::string field_name = new_field_name ? "rules" : "Rule"; const std::string field_name = new_field_name ? "rules" : "Rule";
@ -1016,8 +1006,7 @@ void parseGroupTimes(const std::string &src, int *interval, int *tolerance, int
void groupGenerate(std::string &rule, std::vector<nodeInfo> &nodelist, string_array &filtered_nodelist, bool add_direct) void groupGenerate(std::string &rule, std::vector<nodeInfo> &nodelist, string_array &filtered_nodelist, bool add_direct)
{ {
std::string group, real_rule; std::string real_rule;
const std::string groupid_regex = R"(^!!(?:GROUPID|INSERT)=([\d\-+!,]+)(?:!!(.*))?$)", group_regex = R"(^!!(?:GROUP)=(.*?)(?:!!(.*))?$)";
if(startsWith(rule, "[]") && add_direct) if(startsWith(rule, "[]") && add_direct)
{ {
filtered_nodelist.emplace_back(rule.substr(2)); filtered_nodelist.emplace_back(rule.substr(2));
@ -1066,7 +1055,7 @@ void groupGenerate(std::string &rule, std::vector<nodeInfo> &nodelist, string_ar
} }
} }
void preprocessNodes(std::vector<nodeInfo> &nodes, extra_settings &ext) void preprocessNodes(std::vector<nodeInfo> &nodes, const extra_settings &ext)
{ {
std::for_each(nodes.begin(), nodes.end(), [ext](nodeInfo &x) std::for_each(nodes.begin(), nodes.end(), [ext](nodeInfo &x)
{ {
@ -1128,7 +1117,7 @@ void preprocessNodes(std::vector<nodeInfo> &nodes, extra_settings &ext)
} }
} }
void netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, string_array &extra_proxy_group, bool clashR, extra_settings &ext) void netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, const string_array &extra_proxy_group, bool clashR, const extra_settings &ext)
{ {
YAML::Node proxies, singleproxy, singlegroup, original_groups; YAML::Node proxies, singleproxy, singlegroup, original_groups;
rapidjson::Document json; rapidjson::Document json;
@ -1138,7 +1127,7 @@ void netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, string_arr
std::string id, aid, transproto, faketype, host, edge, path, quicsecure, quicsecret; std::string id, aid, transproto, faketype, host, edge, path, quicsecure, quicsecret;
tribool udp, scv; tribool udp, scv;
std::vector<nodeInfo> nodelist; std::vector<nodeInfo> nodelist;
bool tlssecure, replace_flag; bool tlssecure;
string_array vArray, remarks_list, filtered_nodelist; string_array vArray, remarks_list, filtered_nodelist;
for(nodeInfo &x : nodes) for(nodeInfo &x : nodes)
@ -1235,6 +1224,7 @@ void netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, string_arr
singleproxy["http-opts"]["headers"]["Host"].push_back(host); singleproxy["http-opts"]["headers"]["Host"].push_back(host);
if(edge.size()) if(edge.size())
singleproxy["http-opts"]["headers"]["Edge"].push_back(edge); singleproxy["http-opts"]["headers"]["Edge"].push_back(edge);
break;
default: default:
continue; continue;
} }
@ -1247,8 +1237,6 @@ void netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, string_arr
obfs = GetMember(json, "OBFS"); obfs = GetMember(json, "OBFS");
if(ext.filter_deprecated) if(ext.filter_deprecated)
{ {
if(method == "chacha20" && !clashR) //the mainline core no longer supports chacha20, but clashR core still does
continue;
if(std::find(clashr_protocols.cbegin(), clashr_protocols.cend(), protocol) == clashr_protocols.cend()) if(std::find(clashr_protocols.cbegin(), clashr_protocols.cend(), protocol) == clashr_protocols.cend())
continue; continue;
if(std::find(clashr_obfs.cbegin(), clashr_obfs.cend(), obfs) == clashr_obfs.cend()) if(std::find(clashr_obfs.cbegin(), clashr_obfs.cend(), obfs) == clashr_obfs.cend())
@ -1344,15 +1332,13 @@ void netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, string_arr
else else
yamlnode["Proxy"] = proxies; yamlnode["Proxy"] = proxies;
std::string groupname;
string_array providers; string_array providers;
for(std::string &x : extra_proxy_group) for(const std::string &x : extra_proxy_group)
{ {
singlegroup.reset(); singlegroup.reset();
eraseElements(filtered_nodelist); eraseElements(filtered_nodelist);
eraseElements(providers); eraseElements(providers);
replace_flag = false;
unsigned int rules_upper_bound = 0; unsigned int rules_upper_bound = 0;
vArray = split(x, "`"); vArray = split(x, "`");
@ -1407,6 +1393,7 @@ void netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, string_arr
} }
//singlegroup.SetStyle(YAML::EmitterStyle::Flow); //singlegroup.SetStyle(YAML::EmitterStyle::Flow);
bool replace_flag = false;
for(unsigned int i = 0; i < original_groups.size(); i++) for(unsigned int i = 0; i < original_groups.size(); i++)
{ {
if(original_groups[i]["name"].as<std::string>() == vArray[0]) if(original_groups[i]["name"].as<std::string>() == vArray[0])
@ -1426,7 +1413,7 @@ void netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, string_arr
yamlnode["Proxy Group"] = original_groups; yamlnode["Proxy Group"] = original_groups;
} }
std::string netchToClash(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, bool clashR, extra_settings &ext) std::string netchToClash(std::vector<nodeInfo> &nodes, const std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, const string_array &extra_proxy_group, bool clashR, const extra_settings &ext)
{ {
YAML::Node yamlnode; YAML::Node yamlnode;
@ -1467,7 +1454,7 @@ std::string netchToClash(std::vector<nodeInfo> &nodes, std::string &base_conf, s
return output_content; return output_content;
} }
std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, int surge_ver, extra_settings &ext) std::string netchToSurge(std::vector<nodeInfo> &nodes, const std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, const string_array &extra_proxy_group, int surge_ver, const extra_settings &ext)
{ {
rapidjson::Document json; rapidjson::Document json;
INIReader ini; INIReader ini;
@ -1654,12 +1641,11 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
ini.SetCurrentSection("Proxy Group"); ini.SetCurrentSection("Proxy Group");
ini.EraseSection(); ini.EraseSection();
for(std::string &x : extra_proxy_group) for(const std::string &x : extra_proxy_group)
{ {
//group pref //group pref
std::string url; std::string url;
int interval = 0, tolerance = 0, timeout = 0; int interval = 0, tolerance = 0, timeout = 0;
std::string ssid_default;
eraseElements(filtered_nodelist); eraseElements(filtered_nodelist);
unsigned int rules_upper_bound = 0; unsigned int rules_upper_bound = 0;
url.clear(); url.clear();
@ -1735,7 +1721,7 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
return ini.ToString(); return ini.ToString();
} }
std::string netchToSingle(std::vector<nodeInfo> &nodes, int types, extra_settings &ext) std::string netchToSingle(std::vector<nodeInfo> &nodes, int types, const extra_settings &ext)
{ {
/// types: SS=1 SSR=2 VMess=4 Trojan=8 /// types: SS=1 SSR=2 VMess=4 Trojan=8
rapidjson::Document json; rapidjson::Document json;
@ -1827,7 +1813,7 @@ std::string netchToSingle(std::vector<nodeInfo> &nodes, int types, extra_setting
return base64_encode(allLinks); return base64_encode(allLinks);
} }
std::string netchToSSSub(std::string &base_conf, std::vector<nodeInfo> &nodes, extra_settings &ext) std::string netchToSSSub(std::string &base_conf, std::vector<nodeInfo> &nodes, const extra_settings &ext)
{ {
rapidjson::Document json, base; rapidjson::Document json, base;
std::string remark, hostname, password, method; std::string remark, hostname, password, method;
@ -1899,7 +1885,7 @@ std::string netchToSSSub(std::string &base_conf, std::vector<nodeInfo> &nodes, e
return output_content; return output_content;
} }
std::string netchToQuan(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, extra_settings &ext) std::string netchToQuan(std::vector<nodeInfo> &nodes, const std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, const string_array &extra_proxy_group, const extra_settings &ext)
{ {
INIReader ini; INIReader ini;
ini.store_any_line = true; ini.store_any_line = true;
@ -1923,7 +1909,7 @@ std::string netchToQuan(std::vector<nodeInfo> &nodes, std::string &base_conf, st
return ini.ToString(); return ini.ToString();
} }
void netchToQuan(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, extra_settings &ext) void netchToQuan(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<ruleset_content> &ruleset_content_array, const string_array &extra_proxy_group, const extra_settings &ext)
{ {
rapidjson::Document json; rapidjson::Document json;
std::string type; std::string type;
@ -1931,7 +1917,7 @@ void netchToQuan(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rules
std::string plugin, pluginopts; std::string plugin, pluginopts;
std::string protocol, protoparam, obfs, obfsparam; std::string protocol, protoparam, obfs, obfsparam;
std::string id, aid, transproto, faketype, host, edge, path, quicsecure, quicsecret; std::string id, aid, transproto, faketype, host, edge, path, quicsecure, quicsecret;
std::string proxyStr, allLinks; std::string proxyStr;
bool tlssecure; bool tlssecure;
std::vector<nodeInfo> nodelist; std::vector<nodeInfo> nodelist;
string_array remarks_list; string_array remarks_list;
@ -2091,7 +2077,7 @@ void netchToQuan(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rules
std::string singlegroup; std::string singlegroup;
std::string name, proxies; std::string name, proxies;
string_array vArray; string_array vArray;
for(std::string &x : extra_proxy_group) for(const std::string &x : extra_proxy_group)
{ {
eraseElements(filtered_nodelist); eraseElements(filtered_nodelist);
unsigned int rules_upper_bound = 0; unsigned int rules_upper_bound = 0;
@ -2132,7 +2118,7 @@ void netchToQuan(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rules
std::string content, celluar, celluar_matcher = R"(^(.*?),?celluar\s?=\s?(.*?)(,.*)$)", rem_a, rem_b; std::string content, celluar, celluar_matcher = R"(^(.*?),?celluar\s?=\s?(.*?)(,.*)$)", rem_a, rem_b;
for(auto iter = vArray.begin() + 3; iter != vArray.end(); iter++) for(auto iter = vArray.begin() + 3; iter != vArray.end(); iter++)
{ {
if(regGetMatch(*iter, celluar_matcher, 4, NULL, &rem_a, &celluar, &rem_b)) if(regGetMatch(*iter, celluar_matcher, 4, 0, &rem_a, &celluar, &rem_b))
{ {
content += *iter + "\n"; content += *iter + "\n";
continue; continue;
@ -2176,7 +2162,7 @@ void netchToQuan(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rules
rulesetToSurge(ini, ruleset_content_array, -2, ext.overwrite_original_rules, std::string()); rulesetToSurge(ini, ruleset_content_array, -2, ext.overwrite_original_rules, std::string());
} }
std::string netchToQuanX(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, extra_settings &ext) std::string netchToQuanX(std::vector<nodeInfo> &nodes, const std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, const string_array &extra_proxy_group, const extra_settings &ext)
{ {
INIReader ini; INIReader ini;
ini.store_any_line = true; ini.store_any_line = true;
@ -2207,7 +2193,7 @@ std::string netchToQuanX(std::vector<nodeInfo> &nodes, std::string &base_conf, s
return ini.ToString(); return ini.ToString();
} }
void netchToQuanX(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, extra_settings &ext) void netchToQuanX(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<ruleset_content> &ruleset_content_array, const string_array &extra_proxy_group, const extra_settings &ext)
{ {
rapidjson::Document json; rapidjson::Document json;
std::string type; std::string type;
@ -2335,7 +2321,7 @@ void netchToQuanX(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rule
std::string singlegroup; std::string singlegroup;
std::string name, proxies; std::string name, proxies;
string_array vArray; string_array vArray;
for(std::string &x : extra_proxy_group) for(const std::string &x : extra_proxy_group)
{ {
eraseElements(filtered_nodelist); eraseElements(filtered_nodelist);
unsigned int rules_upper_bound = 0; unsigned int rules_upper_bound = 0;
@ -2476,7 +2462,7 @@ void netchToQuanX(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rule
} }
} }
std::string netchToSSD(std::vector<nodeInfo> &nodes, std::string &group, std::string &userinfo, extra_settings &ext) std::string netchToSSD(std::vector<nodeInfo> &nodes, std::string &group, std::string &userinfo, const extra_settings &ext)
{ {
rapidjson::Document json; rapidjson::Document json;
rapidjson::StringBuffer sb; rapidjson::StringBuffer sb;
@ -2592,7 +2578,7 @@ std::string netchToSSD(std::vector<nodeInfo> &nodes, std::string &group, std::st
return "ssd://" + base64_encode(sb.GetString()); return "ssd://" + base64_encode(sb.GetString());
} }
std::string netchToMellow(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, extra_settings &ext) std::string netchToMellow(std::vector<nodeInfo> &nodes, const std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, const string_array &extra_proxy_group, const extra_settings &ext)
{ {
INIReader ini; INIReader ini;
ini.store_any_line = true; ini.store_any_line = true;
@ -2604,7 +2590,7 @@ std::string netchToMellow(std::vector<nodeInfo> &nodes, std::string &base_conf,
return ini.ToString(); return ini.ToString();
} }
void netchToMellow(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, extra_settings &ext) void netchToMellow(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<ruleset_content> &ruleset_content_array, const string_array &extra_proxy_group, const extra_settings &ext)
{ {
rapidjson::Document json; rapidjson::Document json;
std::string proxy; std::string proxy;
@ -2676,7 +2662,7 @@ void netchToMellow(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rul
ini.SetCurrentSection("EndpointGroup"); ini.SetCurrentSection("EndpointGroup");
for(std::string &x : extra_proxy_group) for(const std::string &x : extra_proxy_group)
{ {
eraseElements(filtered_nodelist); eraseElements(filtered_nodelist);
unsigned int rules_upper_bound = 0; unsigned int rules_upper_bound = 0;
@ -2743,7 +2729,7 @@ void netchToMellow(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rul
rulesetToSurge(ini, ruleset_content_array, 0, ext.overwrite_original_rules, std::string()); rulesetToSurge(ini, ruleset_content_array, 0, ext.overwrite_original_rules, std::string());
} }
std::string netchToLoon(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, extra_settings &ext) std::string netchToLoon(std::vector<nodeInfo> &nodes, const std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, const string_array &extra_proxy_group, const extra_settings &ext)
{ {
rapidjson::Document json; rapidjson::Document json;
INIReader ini; INIReader ini;
@ -2759,7 +2745,6 @@ std::string netchToLoon(std::vector<nodeInfo> &nodes, std::string &base_conf, st
//group pref //group pref
std::string url; std::string url;
int interval = 0; int interval = 0;
std::string ssid_default;
string_array vArray, remarks_list, filtered_nodelist; string_array vArray, remarks_list, filtered_nodelist;
@ -2885,7 +2870,7 @@ std::string netchToLoon(std::vector<nodeInfo> &nodes, std::string &base_conf, st
ini.SetCurrentSection("Proxy Group"); ini.SetCurrentSection("Proxy Group");
ini.EraseSection(); ini.EraseSection();
for(std::string &x : extra_proxy_group) for(const std::string &x : extra_proxy_group)
{ {
eraseElements(filtered_nodelist); eraseElements(filtered_nodelist);
unsigned int rules_upper_bound = 0; unsigned int rules_upper_bound = 0;

View File

@ -32,8 +32,8 @@ struct listener_args
int max_workers; int max_workers;
}; };
void append_response(std::string method, std::string uri, std::string content_type, response_callback response); void append_response(const std::string &method, const std::string &uri, const std::string &content_type, response_callback response);
void append_redirect(std::string uri, std::string target); void append_redirect(const std::string &uri, const std::string &target);
void reset_redirect(); void reset_redirect();
int start_web_server(void *argv); int start_web_server(void *argv);
int start_web_server_multi(void *argv); int start_web_server_multi(void *argv);

View File

@ -185,7 +185,7 @@ void OnReq(evhttp_request *req, void *args)
int start_web_server(void *argv) int start_web_server(void *argv)
{ {
struct listener_args *args = (listener_args*)argv; struct listener_args *args = reinterpret_cast<listener_args*>(argv);
std::string listen_address = args->listen_address; std::string listen_address = args->listen_address;
int port = args->port; int port = args->port;
if (!event_init()) if (!event_init())
@ -219,8 +219,8 @@ int start_web_server(void *argv)
void* httpserver_dispatch(void *arg) void* httpserver_dispatch(void *arg)
{ {
event_base_dispatch((struct event_base*)arg); event_base_dispatch(reinterpret_cast<event_base*>(arg));
event_base_free((struct event_base*)arg); //free resources event_base_free(reinterpret_cast<event_base*>(arg)); //free resources
return NULL; return NULL;
} }
@ -247,7 +247,7 @@ int httpserver_bindsocket(std::string listen_address, int listen_port, int backl
addr.sin_addr.s_addr = inet_addr(listen_address.data()); addr.sin_addr.s_addr = inet_addr(listen_address.data());
addr.sin_port = htons(listen_port); addr.sin_port = htons(listen_port);
ret = ::bind(nfd, (struct sockaddr*)&addr, sizeof(addr)); ret = ::bind(nfd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
if (ret < 0) if (ret < 0)
{ {
closesocket(nfd); closesocket(nfd);
@ -315,7 +315,7 @@ void stop_web_server()
SERVER_EXIT_FLAG = true; SERVER_EXIT_FLAG = true;
} }
void append_response(std::string method, std::string uri, std::string content_type, response_callback response) void append_response(const std::string &method, const std::string &uri, const std::string &content_type, response_callback response)
{ {
responseRoute rr; responseRoute rr;
rr.method = method; rr.method = method;
@ -325,7 +325,7 @@ void append_response(std::string method, std::string uri, std::string content_ty
responses.emplace_back(rr); responses.emplace_back(rr);
} }
void append_redirect(std::string uri, std::string target) void append_redirect(const std::string &uri, const std::string &target)
{ {
redirect_map[uri] = target; redirect_map[uri] = target;
} }