From 17ef7c6150b3a5800ba96ebe3f9c316f683f7bc2 Mon Sep 17 00:00:00 2001 From: Tindy X <49061470+tindy2013@users.noreply.github.com> Date: Thu, 12 Mar 2020 23:20:55 +0800 Subject: [PATCH] Enhancements Add basic support for Trojan node subscriptions. Fix a bug that some Shadowsocks nodes are missing from Loon configurations. Optimize codes. --- src/interfaces.cpp | 74 +++++++++++------------- src/main.cpp | 5 ++ src/printout.h | 2 + src/speedtestutil.cpp | 131 ++++++++++++++++++++++++++++++------------ src/speedtestutil.h | 24 ++++---- src/subexport.cpp | 77 ++++++++++++++++++++++++- src/subexport.h | 1 + 7 files changed, 224 insertions(+), 90 deletions(-) diff --git a/src/interfaces.cpp b/src/interfaces.cpp index e6d860d..90c4cc6 100644 --- a/src/interfaces.cpp +++ b/src/interfaces.cpp @@ -1198,8 +1198,10 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) std::vector dummy_ruleset; //std::cerr<<"Generate target: "; - if(target == "clash" || target == "clashr") + int surge_ver; + switch(hash_(target)) { + case "clash"_hash: case "clashr"_hash: //std::cerr<<"Clash"<<((target == "clashr") ? "R" : "")< std::string + { + return subconverter(argument + "&target=trojan", postdata, status_code, extra_headers); + }); + if(!api_mode) { append_response("GET", "/get", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string diff --git a/src/printout.h b/src/printout.h index 2655811..95814a2 100644 --- a/src/printout.h +++ b/src/printout.h @@ -63,6 +63,7 @@ enum SPEEDTEST_MESSAGE_FOUNDSSTAP, SPEEDTEST_MESSAGE_FOUNDNETCH, SPEEDTEST_MESSAGE_FOUNDHTTP, + SPEEDTEST_MESSAGE_FOUNDTROJAN, SPEEDTEST_MESSAGE_EOF }; @@ -71,6 +72,7 @@ enum #define V2RAY_DEFAULT_GROUP "V2RayProvider" #define SOCKS_DEFAULT_GROUP "SocksProvider" #define HTTP_DEFAULT_GROUP "HTTPProvider" +#define TROJAN_DEFAULT_GROUP "TrojanProvider" void printMsg(int index, nodeInfo *node, bool rpcmode); void printMsgWithDict(int index, bool rpcmode, std::vector dict, std::vector trans); diff --git a/src/speedtestutil.cpp b/src/speedtestutil.cpp index 1c2929a..12ec6a2 100644 --- a/src/speedtestutil.cpp +++ b/src/speedtestutil.cpp @@ -39,7 +39,7 @@ template T safe_as (const YAML::Node& node) return T(); }; -void explodeVmess(std::string vmess, std::string custom_port, int local_port, nodeInfo &node) +void explodeVmess(std::string vmess, const std::string &custom_port, int local_port, nodeInfo &node) { std::string version, ps, add, port, type, id, aid, net, path, host, tls; Document jsondata; @@ -82,7 +82,7 @@ void explodeVmess(std::string vmess, std::string custom_port, int local_port, no GetMember(jsondata, "host", host); if(version == "1") { - if(host != "") + if(host.size()) { vArray = split(host, ";"); if(vArray.size() == 2) @@ -105,7 +105,7 @@ void explodeVmess(std::string vmess, std::string custom_port, int local_port, no node.proxyStr = vmessConstruct(add, port, type, id, aid, net, "auto", path, host, "", tls, local_port); } -void explodeVmessConf(std::string content, std::string custom_port, int local_port, bool libev, std::vector &nodes) +void explodeVmessConf(std::string content, const std::string &custom_port, int local_port, bool libev, std::vector &nodes) { nodeInfo node; Document json; @@ -143,37 +143,30 @@ void explodeVmessConf(std::string content, std::string custom_port, int local_po } //read all subscribe remark as group name for(unsigned int i = 0; i < json["subItem"].Size(); i++) - { subdata.insert(std::pair(json["subItem"][i]["id"].GetString(), json["subItem"][i]["remarks"].GetString())); - } for(unsigned int i = 0; i < json["vmess"].Size(); i++) { if(json["vmess"][i]["address"].IsNull() || json["vmess"][i]["port"].IsNull() || json["vmess"][i]["id"].IsNull()) - { continue; - } + //common info json["vmess"][i]["remarks"] >> ps; json["vmess"][i]["address"] >> add; if(custom_port.size()) port = custom_port; else - json["vmess"][i]["port"] >>port; + json["vmess"][i]["port"] >> port; json["vmess"][i]["subid"] >> subid; - if(subid != "") + if(subid.size()) { iter = subdata.find(subid); if(iter != subdata.end()) - { group = iter->second; - } } if(ps.empty()) - { ps = add + ":" + port; - } json["vmess"][i]["configType"] >> configType; switch(configType) @@ -217,15 +210,15 @@ void explodeVmessConf(std::string content, std::string custom_port, int local_po return; } -void explodeSS(std::string ss, bool libev, std::string custom_port, int local_port, nodeInfo &node) +void explodeSS(std::string ss, bool libev, const std::string &custom_port, int local_port, nodeInfo &node) { std::string ps, password, method, server, port, plugins, plugin, pluginopts, addition, group = SS_DEFAULT_GROUP; std::vector args, secret; - ss = replace_all_distinct(replace_all_distinct(ss.substr(5), "\r", ""), "/?", "?"); + ss = replace_all_distinct(ss.substr(5), "/?", "?"); if(strFind(ss, "#")) { ps = UrlDecode(ss.substr(ss.find("#") + 1)); - ss = ss.substr(0, ss.find("#")); + ss.erase(ss.find("#")); } if(strFind(ss, "?")) @@ -234,9 +227,9 @@ void explodeSS(std::string ss, bool libev, std::string custom_port, int local_po plugins = UrlDecode(getUrlArg(addition, "plugin")); plugin = plugins.substr(0, plugins.find(";")); pluginopts = plugins.substr(plugins.find(";") + 1); - if(getUrlArg(addition, "group") != "") + if(getUrlArg(addition, "group").size()) group = urlsafe_base64_decode(getUrlArg(addition, "group")); - ss = ss.substr(0, ss.find("?")); + ss.erase(ss.find("?")); } if(strFind(ss, "@")) { @@ -274,7 +267,7 @@ void explodeSS(std::string ss, bool libev, std::string custom_port, int local_po node.proxyStr = ssConstruct(server, port, password, method, plugin, pluginopts, ps, local_port, libev); } -void explodeSSD(std::string link, bool libev, std::string custom_port, int local_port, std::vector &nodes) +void explodeSSD(std::string link, bool libev, const std::string &custom_port, int local_port, std::vector &nodes) { Document jsondata; nodeInfo node; @@ -322,7 +315,7 @@ void explodeSSD(std::string link, bool libev, std::string custom_port, int local return; } -void explodeSSAndroid(std::string ss, bool libev, std::string custom_port, int local_port, std::vector &nodes) +void explodeSSAndroid(std::string ss, bool libev, const std::string &custom_port, int local_port, std::vector &nodes) { Document json; nodeInfo node; @@ -365,7 +358,7 @@ void explodeSSAndroid(std::string ss, bool libev, std::string custom_port, int l } } -void explodeSSConf(std::string content, std::string custom_port, int local_port, bool libev, std::vector &nodes) +void explodeSSConf(std::string content, const std::string &custom_port, int local_port, bool libev, std::vector &nodes) { nodeInfo node; Document json; @@ -421,7 +414,7 @@ void explodeSSConf(std::string content, std::string custom_port, int local_port, return; } -void explodeSSR(std::string ssr, bool ss_libev, bool ssr_libev, std::string custom_port, int local_port, nodeInfo &node) +void explodeSSR(std::string ssr, bool ss_libev, bool ssr_libev, const std::string &custom_port, int local_port, nodeInfo &node) { std::string strobfs; std::vector strcfg; @@ -476,7 +469,7 @@ void explodeSSR(std::string ssr, bool ss_libev, bool ssr_libev, std::string cust } } -void explodeSSRConf(std::string content, std::string custom_port, int local_port, bool ss_libev, bool ssr_libev, std::vector &nodes) +void explodeSSRConf(std::string content, const std::string &custom_port, int local_port, bool ss_libev, bool ssr_libev, std::vector &nodes) { nodeInfo node; Document json; @@ -545,7 +538,7 @@ void explodeSSRConf(std::string content, std::string custom_port, int local_port return; } -void explodeSocks(std::string link, std::string custom_port, nodeInfo &node) +void explodeSocks(std::string link, const std::string &custom_port, nodeInfo &node) { std::string remarks, server, port, username, password; if(strFind(link, "socks://")) //v2rayn socks link @@ -554,7 +547,7 @@ void explodeSocks(std::string link, std::string custom_port, nodeInfo &node) if(strFind(link, "#")) { remarks = UrlDecode(link.substr(link.find("#") + 1)); - link = link.substr(0, link.find("#")); + link.erase(link.find("#")); } link = urlsafe_base64_decode(link.substr(8)); arguments = split(link, ":"); @@ -583,7 +576,7 @@ void explodeSocks(std::string link, std::string custom_port, nodeInfo &node) node.proxyStr = socksConstruct(remarks, server, port, username, password); } -void explodeHTTP(std::string link, std::string custom_port, nodeInfo &node) +void explodeHTTP(std::string link, const std::string &custom_port, nodeInfo &node) { std::string remarks, server, port, username, password; server = getUrlArg(link, "server"); @@ -605,7 +598,46 @@ void explodeHTTP(std::string link, std::string custom_port, nodeInfo &node) node.proxyStr = httpConstruct(remarks, server, port, username, password, strFind(link, "/https")); } -void explodeQuan(std::string quan, std::string custom_port, int local_port, nodeInfo &node) +void explodeTrojan(std::string trojan, const std::string &custom_port, int local_port, nodeInfo &node) +{ + std::string server, port, psk, addition, remark; + string_array vArray; + trojan.erase(0, 9); + string_size pos = trojan.rfind("#"); + + if(pos != trojan.npos) + { + remark = UrlDecode(trojan.substr(pos + 1)); + trojan.erase(pos); + } + pos = trojan.rfind("?"); + if(pos != trojan.npos) + { + addition = trojan.substr(pos + 1); + trojan.erase(pos); + } + + 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(remark.empty()) + remark = server + ":" + port; + + node.linkType = SPEEDTEST_MESSAGE_FOUNDTROJAN; + node.group = TROJAN_DEFAULT_GROUP; + node.remarks = remark; + node.server = server; + node.port = to_int(port, 0); + node.proxyStr = trojanConstruct(remark, server, port, psk); +} + +void explodeQuan(std::string quan, const std::string &custom_port, int local_port, nodeInfo &node) { 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; @@ -665,7 +697,7 @@ void explodeQuan(std::string quan, std::string custom_port, int local_port, node } } -void explodeNetch(std::string netch, bool ss_libev, bool ssr_libev, std::string custom_port, int local_port, nodeInfo &node) +void explodeNetch(std::string netch, bool ss_libev, bool ssr_libev, const std::string &custom_port, int local_port, nodeInfo &node) { Document json; std::string type, remark, address, port, username, password, method, plugin, pluginopts, protocol, protoparam, obfs, obfsparam, id, aid, transprot, faketype, host, edge, path, tls; @@ -740,7 +772,7 @@ void explodeNetch(std::string netch, bool ss_libev, bool ssr_libev, std::string node.port = (unsigned short)to_int(port, 0);; } -void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::vector &nodes, bool ss_libev, bool ssr_libev) +void explodeClash(Node yamlnode, const std::string &custom_port, int local_port, std::vector &nodes, bool ss_libev, bool ssr_libev) { nodeInfo node; Node singleproxy; @@ -935,7 +967,7 @@ void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::v return; } -void explodeShadowrocket(std::string rocket, std::string custom_port, int local_port, nodeInfo &node) +void explodeShadowrocket(std::string rocket, const std::string &custom_port, int local_port, nodeInfo &node) { std::string add, port, type, id, aid, net = "tcp", path, host, tls, cipher, remarks; std::string obfs; //for other style of link @@ -987,7 +1019,7 @@ void explodeShadowrocket(std::string rocket, std::string custom_port, int local_ node.proxyStr = vmessConstruct(add, port, type, id, aid, net, cipher, path, host, "", tls, local_port); } -void explodeKitsunebi(std::string kit, std::string custom_port, int local_port, nodeInfo &node) +void explodeKitsunebi(std::string kit, const std::string &custom_port, int local_port, nodeInfo &node) { std::string add, port, type, id, aid = "0", net = "tcp", path, host, tls, cipher = "auto", remarks; std::string addition; @@ -1034,7 +1066,7 @@ void explodeKitsunebi(std::string kit, std::string custom_port, int local_port, node.proxyStr = vmessConstruct(add, port, type, id, aid, net, cipher, path, host, "", tls, local_port); } -bool explodeSurge(std::string surge, std::string custom_port, int local_port, std::vector &nodes, bool libev) +bool explodeSurge(std::string surge, const std::string &custom_port, int local_port, std::vector &nodes, bool libev) { std::multimap proxies; nodeInfo node; @@ -1230,6 +1262,25 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st } node.proxyStr = httpConstruct(remarks, server, port, username, password); } + else if(configs[0] == "trojan") // surge 4 style trojan proxy + { + node.linkType = SPEEDTEST_MESSAGE_FOUNDTROJAN; + node.group = TROJAN_DEFAULT_GROUP; + server = trim(configs[1]); + port = custom_port.empty() ? trim(configs[2]) : custom_port; + + for(i = 3; i < configs.size(); i++) + { + vArray = split(configs[i], "="); + if(vArray.size() != 2) + continue; + itemName = trim(vArray[0]); + itemVal = trim(vArray[1]); + if(itemName == "password") + password = itemVal; + } + node.proxyStr = trojanConstruct(remarks, server, port, password); + } else if(remarks == "shadowsocks") //quantumult x style ss/ssr link { server = trim(configs[0].substr(0, configs[0].rfind(":"))); @@ -1338,7 +1389,7 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st return index; } -void explodeSSTap(std::string sstap, std::string custom_port, int local_port, std::vector &nodes, bool ss_libev, bool ssr_libev) +void explodeSSTap(std::string sstap, const std::string &custom_port, int local_port, std::vector &nodes, bool ss_libev, bool ssr_libev) { Document json; nodeInfo node; @@ -1400,7 +1451,7 @@ void explodeSSTap(std::string sstap, std::string custom_port, int local_port, st } } -void explodeNetchConf(std::string netch, bool ss_libev, bool ssr_libev, std::string custom_port, int local_port, std::vector &nodes) +void explodeNetchConf(std::string netch, bool ss_libev, bool ssr_libev, const std::string &custom_port, int local_port, std::vector &nodes) { Document json; nodeInfo node; @@ -1449,7 +1500,7 @@ bool chkIgnore(const nodeInfo &node, string_array &exclude_remarks, string_array return excluded || !included; } -int explodeConf(std::string filepath, std::string custom_port, int local_port, bool sslibev, bool ssrlibev, std::vector &nodes) +int explodeConf(std::string filepath, const std::string &custom_port, int local_port, bool sslibev, bool ssrlibev, std::vector &nodes) { std::ifstream infile; std::stringstream contentstrm; @@ -1461,7 +1512,7 @@ int explodeConf(std::string filepath, std::string custom_port, int local_port, b return explodeConfContent(contentstrm.str(), custom_port, local_port, sslibev, ssrlibev, nodes); } -int explodeConfContent(std::string content, std::string custom_port, int local_port, bool sslibev, bool ssrlibev, std::vector &nodes) +int explodeConfContent(std::string content, const std::string &custom_port, int local_port, bool sslibev, bool ssrlibev, std::vector &nodes) { int filetype = -1; @@ -1511,7 +1562,7 @@ int explodeConfContent(std::string content, std::string custom_port, int local_p return SPEEDTEST_ERROR_NONE; } -void explode(std::string link, bool sslibev, bool ssrlibev, std::string custom_port, int local_port, nodeInfo &node) +void explode(std::string link, bool sslibev, bool ssrlibev, const std::string &custom_port, int local_port, nodeInfo &node) { // TODO: replace strFind with startsWith if appropriate if(strFind(link, "ssr://")) @@ -1526,9 +1577,11 @@ void explode(std::string link, bool sslibev, bool ssrlibev, std::string custom_p explodeHTTP(link, custom_port, node); else if(strFind(link, "Netch://")) explodeNetch(link, sslibev, ssrlibev, custom_port, local_port, node); + else if(strFind(link, "trojan://")) + explodeTrojan(link, custom_port, local_port, node); } -void explodeSub(std::string sub, bool sslibev, bool ssrlibev, std::string custom_port, int local_port, std::vector &nodes) +void explodeSub(std::string sub, bool sslibev, bool ssrlibev, const std::string &custom_port, int local_port, std::vector &nodes) { std::stringstream strstream; std::string strLink; @@ -1574,6 +1627,8 @@ void explodeSub(std::string sub, bool sslibev, bool ssrlibev, std::string custom char delimiter = count(sub.begin(), sub.end(), '\n') < 1 ? count(sub.begin(), sub.end(), '\r') < 1 ? ' ' : '\r' : '\n'; while(getline(strstream, strLink, delimiter)) { + if(strLink.rfind("\r") != strLink.npos) + strLink.erase(strLink.size() - 1); node.linkType = -1; explode(strLink, sslibev, ssrlibev, custom_port, local_port, node); if(strLink.size() == 0 || node.linkType == -1) diff --git a/src/speedtestutil.h b/src/speedtestutil.h index 858ac5c..5650f96 100644 --- a/src/speedtestutil.h +++ b/src/speedtestutil.h @@ -12,18 +12,20 @@ std::string ssrConstruct(std::string group, std::string remarks, std::string rem std::string ssConstruct(std::string server, std::string port, std::string password, std::string method, std::string plugin, std::string pluginopts, std::string remarks, int local_port, bool libev); std::string socksConstruct(std::string remarks, std::string server, std::string port, std::string username, std::string password); std::string httpConstruct(std::string remarks, std::string server, std::string port, std::string username, std::string password, bool tls = false); -void explodeVmess(std::string vmess, std::string custom_port, int local_port, nodeInfo &node); -void explodeSSR(std::string ssr, bool ss_libev, bool libev, std::string custom_port, int local_port, nodeInfo &node); -void explodeSS(std::string ss, bool libev, std::string custom_port, int local_port, nodeInfo &node); -void explodeQuan(std::string quan, std::string custom_port, int local_port, nodeInfo &node); -void explodeShadowrocket(std::string kit, std::string custom_port, int local_port, nodeInfo &node); -void explodeKitsunebi(std::string kit, std::string custom_port, int local_port, nodeInfo &node); +std::string trojanConstruct(std::string remarks, std::string server, std::string port, std::string password); +void explodeVmess(std::string vmess, const std::string &custom_port, int local_port, nodeInfo &node); +void explodeSSR(std::string ssr, bool ss_libev, bool libev, const std::string &custom_port, int local_port, nodeInfo &node); +void explodeSS(std::string ss, bool libev, const std::string &custom_port, int local_port, nodeInfo &node); +void explodeTrojan(std::string trojan, const std::string &custom_port, int local_port, nodeInfo &node); +void explodeQuan(std::string quan, const std::string &custom_port, int local_port, nodeInfo &node); +void explodeShadowrocket(std::string kit, const std::string &custom_port, int local_port, nodeInfo &node); +void explodeKitsunebi(std::string kit, const std::string &custom_port, int local_port, nodeInfo &node); /// Parse a link -void explode(std::string link, bool sslibev, bool ssrlibev, std::string custom_port, int local_port, nodeInfo &node); -void explodeSSD(std::string link, bool libev, std::string custom_port, int local_port, std::vector &nodes); -void explodeSub(std::string sub, bool sslibev, bool ssrlibev, std::string custom_port, int local_port, std::vector &nodes); -int explodeConf(std::string filepath, std::string custom_port, int local_port, bool sslibev, bool ssrlibev, std::vector &nodes); -int explodeConfContent(std::string content, std::string custom_port, int local_port, bool sslibev, bool ssrlibev, std::vector &nodes); +void explode(std::string link, bool sslibev, bool ssrlibev, const std::string &custom_port, int local_port, nodeInfo &node); +void explodeSSD(std::string link, bool libev, const std::string &custom_port, int local_port, std::vector &nodes); +void explodeSub(std::string sub, bool sslibev, bool ssrlibev, const std::string &custom_port, int local_port, std::vector &nodes); +int explodeConf(std::string filepath, const std::string &custom_port, int local_port, bool sslibev, bool ssrlibev, std::vector &nodes); +int explodeConfContent(std::string content, const std::string &custom_port, int local_port, bool sslibev, bool ssrlibev, std::vector &nodes); bool chkIgnore(const nodeInfo &node, string_array &exclude_remarks, string_array &include_remarks); void filterNodes(std::vector &nodes, string_array &exclude_remarks, string_array &include_remarks, int groupID); bool getSubInfoFromHeader(std::string &header, std::string &result); diff --git a/src/subexport.cpp b/src/subexport.cpp index 369570d..64e9b0f 100644 --- a/src/subexport.cpp +++ b/src/subexport.cpp @@ -215,6 +215,25 @@ std::string httpConstruct(std::string remarks, std::string server, std::string p return sb.GetString(); } +std::string trojanConstruct(std::string remarks, std::string server, std::string port, std::string password) +{ + rapidjson::StringBuffer sb; + rapidjson::Writer writer(sb); + writer.StartObject(); + writer.Key("Type"); + writer.String("Trojan"); + writer.Key("Remark"); + writer.String(remarks.data()); + writer.Key("Hostname"); + writer.String(server.data()); + writer.Key("Port"); + writer.Int(to_int(port)); + writer.Key("Password"); + writer.String(password.data()); + writer.EndObject(); + 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) { rapidjson::StringBuffer sb; @@ -1064,11 +1083,18 @@ std::string netchToSurge(std::vector &nodes, std::string &base_conf, s proxy += ", skip-cert-verify=1"; break; case SPEEDTEST_MESSAGE_FOUNDHTTP: - proxy = "http," + hostname + "," + port + ", " + username + ", " + password; + proxy = "http, " + hostname + ", " + port + ", " + username + ", " + password; proxy += std::string(", tls=") + (type == "HTTPS" ? "true" : "false"); if(ext.skip_cert_verify) proxy += ", skip-cert-verify=1"; break; + case SPEEDTEST_MESSAGE_FOUNDTROJAN: + if(surge_ver < 4) + continue; + proxy = "trojan, " + hostname + ", " + port + ", password=" + password; + if(ext.skip_cert_verify) + proxy += ", skip-cert-verify=1"; + break; default: continue; } @@ -1419,6 +1445,53 @@ std::string netchToVMess(std::vector &nodes, extra_settings &ext) return base64_encode(allLinks); } +std::string netchToTrojan(std::vector &nodes, extra_settings &ext) +{ + rapidjson::Document json; + std::string server, port, psk, remark; + std::string proxyStr, allLinks; + + std::for_each(nodes.begin(), nodes.end(), [ext](nodeInfo &x) + { + x.remarks = nodeRename(x.remarks, x.groupID, ext.rename_array); + if(ext.remove_emoji) + x.remarks = trim(removeEmoji(x.remarks)); + + if(ext.add_emoji) + x.remarks = addEmoji(x.remarks, x.groupID, ext.emoji_array); + }); + + if(ext.sort_flag) + { + std::sort(nodes.begin(), nodes.end(), [](const nodeInfo &a, const nodeInfo &b) + { + return a.remarks < b.remarks; + }); + } + + for(nodeInfo &x : nodes) + { + json.Parse(x.proxyStr.data()); + + remark = x.remarks; + server = GetMember(json, "Hostname"); + port = std::to_string((unsigned short)stoi(GetMember(json, "Port"))); + psk = GetMember(json, "Password"); + + switch(x.linkType) + { + case SPEEDTEST_MESSAGE_FOUNDTROJAN: + proxyStr = "trojan://" + psk + "@" + server + ":" + port + "#" + UrlEncode(remark); + break; + default: + continue; + } + allLinks += proxyStr + "\n"; + } + + return base64_encode(allLinks); +} + std::string netchToQuan(std::vector &nodes, std::string &base_conf, std::vector &ruleset_content_array, string_array &extra_proxy_group, extra_settings &ext) { INIReader ini; @@ -2291,7 +2364,7 @@ std::string netchToLoon(std::vector &nodes, std::string &base_conf, st pluginopts = GetMember(json, "PluginOption"); proxy = "Shadowsocks," + hostname + "," + port + "," + method + ",\"" + password + "\""; - if(plugin == "simple-obfs") + if(plugin == "simple-obfs" || plugin == "obfs-local") { if(pluginopts.size()) proxy += "," + replace_all_distinct(replace_all_distinct(pluginopts, ";obfs-host=", ","), "obfs=", ""); diff --git a/src/subexport.h b/src/subexport.h index 7521919..a6dec30 100644 --- a/src/subexport.h +++ b/src/subexport.h @@ -47,6 +47,7 @@ std::string netchToSS(std::vector &nodes, extra_settings &ext); std::string netchToSSSub(std::vector &nodes, extra_settings &ext); std::string netchToSSR(std::vector &nodes, extra_settings &ext); std::string netchToVMess(std::vector &nodes, extra_settings &ext); +std::string netchToTrojan(std::vector &nodes, extra_settings &ext); std::string netchToQuanX(std::vector &nodes, std::string &base_conf, std::vector &ruleset_content_array, string_array &extra_proxy_group, extra_settings &ext); void netchToQuanX(std::vector &nodes, INIReader &ini, std::vector &ruleset_content_array, string_array &extra_proxy_group, extra_settings &ext); std::string netchToQuan(std::vector &nodes, std::string &base_conf, std::vector &ruleset_content_array, string_array &extra_proxy_group, extra_settings &ext);