diff --git a/base/config/example_external_config.ini b/base/config/example_external_config.ini index 70c84c1..1f11998 100644 --- a/base/config/example_external_config.ini +++ b/base/config/example_external_config.ini @@ -52,6 +52,6 @@ clash_rule_base=base/forcerule.yml ;emoji=(流量|时间|应急),🏳️‍🌈 ;emoji=阿根廷,🇦🇷 -;Optims for filtering nodes +;Options for filtering nodes ;include_remarks= ;exclude_remarks= diff --git a/base/generate.ini b/base/generate.ini new file mode 100644 index 0000000..db75543 --- /dev/null +++ b/base/generate.ini @@ -0,0 +1,9 @@ +[test] +path=output.conf +target=surge +ver=4 +url=ss://Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTpwYXNzd29yZA@www.example.com:1080#Example + +[test_profile] +path=output.yml +profile=profiles/example_profile.ini diff --git a/src/interfaces.cpp b/src/interfaces.cpp index 68e7d1a..32ae3af 100644 --- a/src/interfaces.cpp +++ b/src/interfaces.cpp @@ -54,7 +54,7 @@ string_array regex_blacklist = {"(.*)*"}; template void operator >> (const YAML::Node& node, T& i) { - if(node.IsDefined()) //fail-safe + if(node.IsDefined() && !node.IsNull()) //fail-safe i = node.as(); }; @@ -864,7 +864,6 @@ void generateBase() if(!enable_base_gen) return; std::string base_content; - int retVal = 0; std::cerr<<"Generating base content for Clash/R...\n"; if(fileExist(clash_rule_base)) base_content = fileGet(clash_rule_base); @@ -888,8 +887,7 @@ void generateBase() base_content = webGet(mellow_rule_base, getSystemProxy()); mellow_base.keep_empty_section = true; mellow_base.store_any_line = true; - retVal = mellow_base.Parse(base_content); - if(retVal != INIREADER_EXCEPTION_NONE) + if(mellow_base.Parse(base_content) != INIREADER_EXCEPTION_NONE) std::cerr<<"Unable to load Mellow base content. Reason: "< dummy_map; + int ret_code = 200; + for(std::string &x : sections) + { + arguments.clear(); + ret_code = 200; + std::cerr<<"Generating artifact '"< &rca); void readConf(); void generateBase(); +void simpleGenerator(); std::string getScript(RESPONSE_CALLBACK_ARGS); std::string getProfile(RESPONSE_CALLBACK_ARGS); diff --git a/src/main.cpp b/src/main.cpp index 7b219e0..e6692c0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,7 +10,7 @@ #include "webget.h" extern std::string pref_path, access_token, listen_address; -extern bool api_mode, cfw_child_process, update_ruleset_on_request; +extern bool api_mode, generator_mode, cfw_child_process, update_ruleset_on_request; extern int listen_port, max_concurrent_threads, max_pending_connections; extern string_array rulesets; extern std::vector ruleset_content_array; @@ -58,6 +58,8 @@ void chkArg(int argc, char *argv[]) } else if(strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "--file") == 0) pref_path.assign(argv[++i]); + else if(strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "--gen") == 0) + generator_mode = true; } } @@ -110,6 +112,12 @@ int main(int argc, char *argv[]) refreshRulesets(rulesets, ruleset_content_array); generateBase(); + if(generator_mode) + { + simpleGenerator(); + return 0; + } + append_response("GET", "/", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string { return std::string("subconverter " VERSION " backend\n"); diff --git a/src/speedtestutil.cpp b/src/speedtestutil.cpp index 0755c54..659846d 100644 --- a/src/speedtestutil.cpp +++ b/src/speedtestutil.cpp @@ -27,10 +27,17 @@ std::string modSSMD5 = "f7653207090ce3389115e9c88541afe0"; template void operator >> (const YAML::Node& node, T& i) { - if(node.IsDefined()) //fail-safe + if(node.IsDefined() && !node.IsNull()) //fail-safe i = node.as(); }; +template T safe_as (const YAML::Node& node) +{ + if(node.IsDefined() && !node.IsNull()) + return node.as(); + return T(); +}; + void explodeVmess(std::string vmess, std::string custom_port, int local_port, nodeInfo &node) { std::string version, ps, add, port, type, id, aid, net, path, host, tls; @@ -162,7 +169,7 @@ void explodeVmessConf(std::string content, std::string custom_port, int local_po group = iter->second; } } - if(ps == "") + if(ps.empty()) { ps = add + ":" + port; } @@ -240,7 +247,7 @@ void explodeSS(std::string ss, bool libev, std::string custom_port, int local_po method = secret[0]; password = secret[1]; server = args[1]; - port = custom_port == "" ? args[2] : custom_port; + port = custom_port.empty() ? args[2] : custom_port; } else { @@ -253,9 +260,9 @@ void explodeSS(std::string ss, bool libev, std::string custom_port, int local_po method = args[0]; password = args[1]; server = args[2]; - port = custom_port == "" ? args[3] : custom_port; + port = custom_port.empty() ? args[3] : custom_port; } - if(ps == "") + if(ps.empty()) ps = server + ":" + port; node.linkType = SPEEDTEST_MESSAGE_FOUNDSS; @@ -337,7 +344,7 @@ void explodeSSAndroid(std::string ss, bool libev, std::string custom_port, int l port = custom_port; else port = GetMember(json["nodes"][i], "server_port"); - if(ps == "") + if(ps.empty()) ps = server + ":" + port; password = GetMember(json["nodes"][i], "password"); method = GetMember(json["nodes"][i], "method"); @@ -388,7 +395,7 @@ void explodeSSConf(std::string content, std::string custom_port, int local_port, port = custom_port; else json["configs"][i]["server_port"] >> port; - if(ps == "") + if(ps.empty()) { ps = server + ":" + port; } @@ -437,15 +444,15 @@ void explodeSSR(std::string ssr, bool ss_libev, bool ssr_libev, std::string cust return; server = strcfg[0]; - port = custom_port == "" ? strcfg[1] : custom_port; + port = custom_port.empty() ? strcfg[1] : custom_port; protocol = strcfg[2]; method = strcfg[3]; obfs = strcfg[4]; password = urlsafe_base64_decode(strcfg[5]); - if(group == "") + if(group.empty()) group = SSR_DEFAULT_GROUP; - if(remarks == "") + if(remarks.empty()) { remarks = server + ":" + port; remarks_base64 = base64_encode(remarks); @@ -455,7 +462,7 @@ void explodeSSR(std::string ssr, bool ss_libev, bool ssr_libev, std::string cust node.remarks = remarks; node.server = server; node.port = to_int(port, 0); - if(find(ss_ciphers.begin(), ss_ciphers.end(), method) != ss_ciphers.end() && (obfs == "" || obfs == "plain") && (protocol == "" || protocol == "origin")) + if(find(ss_ciphers.begin(), ss_ciphers.end(), method) != ss_ciphers.end() && (obfs.empty() || obfs == "plain") && (protocol.empty() || protocol == "origin")) { node.linkType = SPEEDTEST_MESSAGE_FOUNDSS; node.proxyStr = ssConstruct(server, port, password, method, "", "", remarks, local_port, ss_libev); @@ -482,7 +489,7 @@ void explodeSSRConf(std::string content, std::string custom_port, int local_port method = GetMember(json, "method"); obfs = GetMember(json, "obfs"); protocol = GetMember(json, "protocol"); - if(find(ss_ciphers.begin(), ss_ciphers.end(), method) != ss_ciphers.end() && (obfs == "" || obfs == "plain") && (protocol == "" || protocol == "origin")) + if(find(ss_ciphers.begin(), ss_ciphers.end(), method) != ss_ciphers.end() && (obfs.empty() || obfs == "plain") && (protocol.empty() || protocol == "origin")) { explodeSSConf(content, custom_port, local_port, ss_libev, nodes); return; @@ -503,7 +510,7 @@ void explodeSSRConf(std::string content, std::string custom_port, int local_port for(unsigned int i = 0; i < json["configs"].Size(); i++) { json["configs"][i]["group"] >> group; - if(group == "") + if(group.empty()) group = SSR_DEFAULT_GROUP; json["configs"][i]["remarks"] >> remarks; json["configs"][i]["server"] >> server; @@ -511,7 +518,7 @@ void explodeSSRConf(std::string content, std::string custom_port, int local_port port = custom_port; else json["configs"][i]["server_port"] >> port; - if(remarks == "") + if(remarks.empty()) remarks = server + ":" + port; json["configs"][i]["remarks_base64"] >> remarks_base64; @@ -559,7 +566,7 @@ void explodeSocks(std::string link, std::string custom_port, nodeInfo &node) username = getUrlArg(link, "user"); password = getUrlArg(link, "pass"); } - if(remarks == "") + if(remarks.empty()) remarks = server + ":" + port; if(custom_port.size()) port = custom_port; @@ -581,7 +588,7 @@ void explodeHTTP(std::string link, std::string custom_port, nodeInfo &node) password = getUrlArg(link, "pass"); remarks = UrlDecode(getUrlArg(link, "remark")); - if(remarks == "") + if(remarks.empty()) remarks = server + ":" + port; if(custom_port.size()) port = custom_port; @@ -639,7 +646,7 @@ void explodeQuan(std::string quan, std::string custom_port, int local_port, node else if(itemName == "obfs" && itemVal == "ws") net = "ws"; } - if(path == "") + if(path.empty()) path = "/"; node.linkType = SPEEDTEST_MESSAGE_FOUNDVMESS; @@ -666,7 +673,7 @@ void explodeNetch(std::string netch, bool ss_libev, bool ssr_libev, std::string port = custom_port.size() ? custom_port : GetMember(json, "Port"); method = GetMember(json, "EncryptMethod"); password = GetMember(json, "Password"); - if(remark == "") + if(remark.empty()) remark = address + ":" + port; if(type == "SS") { @@ -680,7 +687,7 @@ void explodeNetch(std::string netch, bool ss_libev, bool ssr_libev, std::string { protocol = GetMember(json, "Protocol"); obfs = GetMember(json, "OBFS"); - if(find(ss_ciphers.begin(), ss_ciphers.end(), method) != ss_ciphers.end() && (obfs == "" || obfs == "plain") && (protocol == "" || protocol == "origin")) + if(find(ss_ciphers.begin(), ss_ciphers.end(), method) != ss_ciphers.end() && (obfs.empty() || obfs == "plain") && (protocol.empty() || protocol == "origin")) { plugin = GetMember(json, "Plugin"); pluginopts = GetMember(json, "PluginOption"); @@ -743,7 +750,9 @@ void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::v singleproxy["type"] >> proxytype; singleproxy["name"] >> ps; singleproxy["server"] >> server; - port = custom_port == "" ? singleproxy["port"].as() : custom_port; + port = custom_port.empty() ? safe_as(singleproxy["port"]) : custom_port; + if(port.empty()) + continue; if(proxytype == "vmess") { group = V2RAY_DEFAULT_GROUP; @@ -751,10 +760,10 @@ void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::v singleproxy["uuid"] >> id; singleproxy["alterId"] >> aid; singleproxy["cipher"] >> cipher; - net = singleproxy["network"].IsDefined() ? singleproxy["network"].as() : "tcp"; - path = singleproxy["ws-path"].IsDefined() ? singleproxy["ws-path"].as() : "/"; + net = singleproxy["network"].IsDefined() ? safe_as(singleproxy["network"]) : "tcp"; + path = singleproxy["ws-path"].IsDefined() ? safe_as(singleproxy["ws-path"]) : "/"; if(singleproxy["tls"].IsDefined()) - tls = singleproxy["tls"].as() == "true" ? "tls" : ""; + tls = safe_as(singleproxy["tls"]) == "true" ? "tls" : ""; else tls.clear(); if(singleproxy["ws-headers"].IsDefined()) @@ -777,7 +786,7 @@ void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::v singleproxy["password"] >> password; if(singleproxy["plugin"].IsDefined()) { - if(singleproxy["plugin"].as() == "obfs") + if(safe_as(singleproxy["plugin"]) == "obfs") { plugin = "simple-obfs"; if(singleproxy["plugin-opts"].IsDefined()) @@ -789,7 +798,7 @@ void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::v pluginopts_host.clear(); } } - else if(singleproxy["plugin"].as() == "v2ray-plugin") + else if(safe_as(singleproxy["plugin"]) == "v2ray-plugin") { plugin = "v2ray-plugin"; if(singleproxy["plugin-opts"].IsDefined()) @@ -800,7 +809,7 @@ void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::v else pluginopts_host.clear(); if(singleproxy["plugin-opts"]["tls"].IsDefined()) - tls = singleproxy["plugin-opts"]["tls"].as() ? "tls;" : ""; + tls = safe_as(singleproxy["plugin-opts"]["tls"]) ? "tls;" : ""; else tls.clear(); if(singleproxy["plugin-opts"]["path"].IsDefined()) @@ -808,7 +817,7 @@ void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::v else path.clear(); if(singleproxy["plugin-opts"]["mux"].IsDefined()) - pluginopts_mux = singleproxy["plugin-opts"]["mux"].as() ? "mux=4;" : ""; + pluginopts_mux = safe_as(singleproxy["plugin-opts"]["mux"]) ? "mux=4;" : ""; else pluginopts_mux.clear(); } @@ -827,7 +836,7 @@ void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::v if(plugin == "simple-obfs") { pluginopts = "obfs=" + pluginopts_mode; - pluginopts += pluginopts_host == "" ? "" : ";obfs-host=" + pluginopts_host; + pluginopts += pluginopts_host.empty() ? "" : ";obfs-host=" + pluginopts_host; } else if(plugin == "v2ray-plugin") { @@ -954,10 +963,10 @@ void explodeShadowrocket(std::string rocket, std::string custom_port, int local_ tls = getUrlArg(addition, "tls") == "1" ? "tls" : ""; aid = getUrlArg(addition, "aid"); - if(aid == "") + if(aid.empty()) aid = "0"; - if(remarks == "") + if(remarks.empty()) remarks = add + ":" + port; node.linkType = SPEEDTEST_MESSAGE_FOUNDVMESS; @@ -1002,7 +1011,7 @@ void explodeKitsunebi(std::string kit, std::string custom_port, int local_port, tls = getUrlArg(addition, "tls") == "true" ? "tls" : ""; host = getUrlArg(addition, "ws.host"); - if(remarks == "") + if(remarks.empty()) remarks = add + ":" + port; node.linkType = SPEEDTEST_MESSAGE_FOUNDVMESS; @@ -1067,7 +1076,7 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st //if(mod_md5 == modSSMD5) //is SSEncrypt module { server = trim(configs[1]); - port = custom_port == "" ? trim(configs[2]) : custom_port; + port = custom_port.empty() ? trim(configs[2]) : custom_port; method = trim(configs[3]); password = trim(configs[4]); plugin.clear(); @@ -1090,7 +1099,7 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st if(plugin != "") { pluginopts = "obfs=" + pluginopts_mode; - pluginopts += pluginopts_host == "" ? "" : ";obfs-host=" + pluginopts_host; + pluginopts += pluginopts_host.empty() ? "" : ";obfs-host=" + pluginopts_host; } node.linkType = SPEEDTEST_MESSAGE_FOUNDSS; @@ -1103,7 +1112,7 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st else if(configs[0] == "ss") //surge 3 style ss proxy { server = trim(configs[1]); - port = custom_port == "" ? trim(configs[2]) : custom_port; + port = custom_port.empty() ? trim(configs[2]) : custom_port; plugin.clear(); for(i = 3; i < configs.size(); i++) @@ -1128,7 +1137,7 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st if(plugin != "") { pluginopts = "obfs=" + pluginopts_mode; - pluginopts += pluginopts_host == "" ? "" : ";obfs-host=" + pluginopts_host; + pluginopts += pluginopts_host.empty() ? "" : ";obfs-host=" + pluginopts_host; } node.linkType = SPEEDTEST_MESSAGE_FOUNDSS; @@ -1140,7 +1149,7 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st node.linkType = SPEEDTEST_MESSAGE_FOUNDSOCKS; node.group = SOCKS_DEFAULT_GROUP; server = trim(configs[1]); - port = custom_port == "" ? trim(configs[2]) : custom_port; + port = custom_port.empty() ? trim(configs[2]) : custom_port; if(configs.size() >= 5) { username = trim(configs[2]); @@ -1151,7 +1160,7 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st else if(configs[0] == "vmess") //surge 4 style vmess proxy { server = trim(configs[1]); - port = custom_port == "" ? trim(configs[2]) : custom_port; + port = custom_port.empty() ? trim(configs[2]) : custom_port; net = "tcp"; method = "auto"; @@ -1187,7 +1196,7 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st } } } - if(host == "" && !isIPv4(server) && !isIPv6(server)) + if(host.empty() && !isIPv4(server) && !isIPv6(server)) host = server; node.linkType = SPEEDTEST_MESSAGE_FOUNDVMESS; @@ -1199,7 +1208,7 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st node.linkType = SPEEDTEST_MESSAGE_FOUNDHTTP; node.group = HTTP_DEFAULT_GROUP; server = trim(configs[1]); - port = custom_port == "" ? trim(configs[2]) : custom_port; + port = custom_port.empty() ? trim(configs[2]) : custom_port; if(configs.size() >= 5) { username = trim(configs[2]); @@ -1210,7 +1219,7 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st else if(remarks == "shadowsocks") //quantumult x style ss/ssr link { server = trim(configs[0].substr(0, configs[0].rfind(":"))); - port = custom_port == "" ? trim(configs[0].substr(configs[0].rfind(":") + 1)) : custom_port; + port = custom_port.empty() ? trim(configs[0].substr(configs[0].rfind(":") + 1)) : custom_port; plugin = protocol = remarks = ""; for(i = 1; i < configs.size(); i++) @@ -1238,12 +1247,12 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st else if(itemName == "obfs-host") pluginopts_host = itemVal; } - if(remarks == "") + if(remarks.empty()) remarks = server + ":" + port; if(plugin != "") { pluginopts = "obfs=" + pluginopts_mode; - pluginopts += pluginopts_host == "" ? "" : ";obfs-host=" + pluginopts_host; + pluginopts += pluginopts_host.empty() ? "" : ";obfs-host=" + pluginopts_host; } if(protocol.size()) @@ -1262,7 +1271,7 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st else if(remarks == "vmess") //quantumult x style vmess link { server = trim(configs[0].substr(0, configs[0].rfind(":"))); - port = custom_port == "" ? trim(configs[0].substr(configs[0].rfind(":") + 1)) : custom_port; + port = custom_port.empty() ? trim(configs[0].substr(configs[0].rfind(":") + 1)) : custom_port; plugin = protocol = remarks = ""; net = "tcp"; @@ -1293,10 +1302,10 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st else if(itemName == "over-tls") tls = itemVal == "true" ? "tls" : ""; } - if(remarks == "") + if(remarks.empty()) remarks = server + ":" + port; - if(host == "" && !isIPv4(server) && !isIPv6(server)) + if(host.empty() && !isIPv4(server) && !isIPv6(server)) host = server; node.linkType = SPEEDTEST_MESSAGE_FOUNDVMESS; @@ -1336,7 +1345,7 @@ void explodeSSTap(std::string sstap, std::string custom_port, int local_port, st json["configs"][i]["server"] >> server; port = custom_port.size() ? custom_port : GetMember(json["configs"][i], "server_port"); - if(remarks == "") + if(remarks.empty()) remarks = server + ":" + port; json["configs"][i]["password"] >> pass; diff --git a/src/subexport.cpp b/src/subexport.cpp index 1ee2f6a..9910c5d 100644 --- a/src/subexport.cpp +++ b/src/subexport.cpp @@ -655,6 +655,8 @@ void netchToClash(std::vector &nodes, YAML::Node &yamlnode, string_arr singleproxy["type"] = "ss"; singleproxy["cipher"] = method; singleproxy["password"] = password; + if(std::all_of(password.begin(), password.end(), ::isdigit)) + singleproxy["password"].SetTag("str"); if(plugin == "simple-obfs" || plugin == "obfs-local") { singleproxy["plugin"] = "obfs"; @@ -724,6 +726,8 @@ void netchToClash(std::vector &nodes, YAML::Node &yamlnode, string_arr singleproxy["type"] = "ssr"; singleproxy["cipher"] = method; singleproxy["password"] = password; + if(std::all_of(password.begin(), password.end(), ::isdigit)) + singleproxy["password"].SetTag("str"); singleproxy["protocol"] = protocol; singleproxy["protocolparam"] = protoparam; singleproxy["obfs"] = obfs; @@ -733,6 +737,8 @@ void netchToClash(std::vector &nodes, YAML::Node &yamlnode, string_arr singleproxy["type"] = "socks5"; singleproxy["username"] = username; singleproxy["password"] = password; + if(std::all_of(password.begin(), password.end(), ::isdigit)) + singleproxy["password"].SetTag("str"); if(ext.skip_cert_verify) singleproxy["skip-cert-verify"] = true; break; @@ -740,6 +746,8 @@ void netchToClash(std::vector &nodes, YAML::Node &yamlnode, string_arr singleproxy["type"] = "http"; singleproxy["username"] = username; singleproxy["password"] = password; + if(std::all_of(password.begin(), password.end(), ::isdigit)) + singleproxy["password"].SetTag("str"); singleproxy["tls"] = type == "HTTPS"; if(ext.skip_cert_verify) singleproxy["skip-cert-verify"] = true;