From 4db29b218dee98cc3866d5c23b9e1e6a10e0e53a Mon Sep 17 00:00:00 2001 From: Tindy X <49061470+tindy2013@users.noreply.github.com> Date: Tue, 12 Nov 2019 18:06:08 +0800 Subject: [PATCH] Enhancements Fix incorrect working directory when double-click to run on MacOS/Linux. Fix Socks 5 proxy support. Add ShadowsocksR nodes support for Quantumult X subscriptions. Change default running mode to non-API mode. --- main.cpp | 25 +++++++++++++++++++- pref.ini | 3 +++ speedtestutil.cpp | 60 +++++++++++++++++++++++++++++++++++++---------- speedtestutil.h | 1 + subexport.cpp | 36 +++++++++++++++++++++++++++- 5 files changed, 110 insertions(+), 15 deletions(-) diff --git a/main.cpp b/main.cpp index bfd7eef..dafcab2 100644 --- a/main.cpp +++ b/main.cpp @@ -37,6 +37,28 @@ string_array clash_extra_group; //surge custom std::string surge_rule_base; +void setcd(char *argv[]) +{ + #ifndef _WIN32 + std::string path, prgpath; + char szTmp[1024]; + prgpath.assign(argv[0]); + if(prgpath[0] == '/') + { + path = prgpath.substr(0, prgpath.rfind("/") + 1); + } + else + { + getcwd(szTmp, 1023); + path.append(szTmp); + path.append("/"); + path.append(argv[0]); + path = path.substr(0, path.rfind("/") + 1); + } + chdir(path.data()); + #endif // _WIN32 +} + std::string refreshRulesets() { guarded_mutex guard(on_configuring); @@ -157,7 +179,7 @@ void readConf() std::cerr<<"Read preference settings completed."< &nodes, bool libev) { - std::string line, remarks, server, port, method, username, password, plugin, pluginopts, pluginopts_mode, pluginopts_host = "cloudfront.net", mod_url, mod_md5; - std::string id, net, tls, host, path; + std::string line, remarks, server, port, method, username, password; //common + std::string plugin, pluginopts, pluginopts_mode, pluginopts_host = "cloudfront.net", mod_url, mod_md5; //ss + std::string id, net, tls, host, path; //v2 + std::string protocol, protoparam; //ssr std::string itemName, itemVal; std::stringstream data; std::vector configs, vArray, headers, header; @@ -1160,7 +1169,7 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st username = trim(configs[2]); password = trim(configs[3]); } - node.proxyStr = "user=" + username + "&pass=" + password; + node.proxyStr = socksConstruct(remarks, server, port, username, password); } else if(configs[0] == "vmess") //surge 4 style vmess proxy { @@ -1207,11 +1216,11 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st node.group = V2RAY_DEFAULT_GROUP; node.proxyStr = vmessConstruct(server, port, "", id, "0", net, method, path, host, tls, local_port); } - else if(remarks == "shadowsocks") //quantumult style ss link + else if(remarks == "shadowsocks") //quantumult 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; - plugin = remarks = ""; + plugin = protocol = remarks = ""; for(i = 1; i < configs.size(); i++) { @@ -1224,13 +1233,38 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st password = vArray[1]; else if(vArray[0] == "tag") remarks = vArray[1]; + else if(vArray[0] == "ssr-protocol") + protocol = vArray[1]; + else if(vArray[0] == "ssr-protocol-param") + protoparam = vArray[1]; + else if(vArray[0] == "obfs") + { + plugin = "simple-obfs"; + pluginopts_mode = vArray[1]; + } + else if(vArray[0] == "obfs-host") + pluginopts_host = vArray[1]; } if(remarks == "") remarks = server + ":" + port; + if(plugin != "") + { + pluginopts = "obfs=" + pluginopts_mode; + pluginopts += pluginopts_host == "" ? "" : ";obfs-host=" + pluginopts_host; + } - node.linkType = SPEEDTEST_MESSAGE_FOUNDSS; - node.group = SS_DEFAULT_GROUP; - node.proxyStr = ssConstruct(server, port, password, method, plugin, pluginopts, remarks, local_port, libev); + if(protocol.size()) + { + node.linkType = SPEEDTEST_MESSAGE_FOUNDSSR; + node.group = SSR_DEFAULT_GROUP; + node.proxyStr = ssrConstruct(node.group, remarks, base64_encode(remarks), server, port, protocol, method, pluginopts_mode, password, pluginopts_host, protoparam, local_port, libev); + } + else + { + node.linkType = SPEEDTEST_MESSAGE_FOUNDSS; + node.group = SS_DEFAULT_GROUP; + node.proxyStr = ssConstruct(server, port, password, method, plugin, pluginopts, remarks, local_port, libev); + } } else continue; @@ -1281,7 +1315,7 @@ void explodeSSTap(std::string sstap, std::string custom_port, int local_port, st { json["configs"][i]["username"] >> user; node.linkType = SPEEDTEST_MESSAGE_FOUNDSOCKS; - node.proxyStr = "user=" + user + "&pass=" + pass; + node.proxyStr = socksConstruct(remarks, server, port, user, pass); } else if(configType == "6") //ss/ssr { diff --git a/speedtestutil.h b/speedtestutil.h index b32be41..10bb54c 100644 --- a/speedtestutil.h +++ b/speedtestutil.h @@ -10,6 +10,7 @@ std::string vmessConstruct(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 tls, int local_port); 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, int local_port, bool libev); 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); 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); diff --git a/subexport.cpp b/subexport.cpp index 6b0a884..457aed2 100644 --- a/subexport.cpp +++ b/subexport.cpp @@ -119,6 +119,27 @@ std::string ssConstruct(std::string server, std::string port, std::string passwo return sb.GetString(); } +std::string socksConstruct(std::string remarks, std::string server, std::string port, std::string username, std::string password) +{ + rapidjson::StringBuffer sb; + rapidjson::Writer writer(sb); + writer.StartObject(); + writer.Key("Type"); + writer.String("Socks"); + writer.Key("Remark"); + writer.String(remarks.data()); + writer.Key("Hostname"); + writer.String(server.data()); + writer.Key("Port"); + writer.Int(stoi(port)); + writer.Key("Username"); + writer.String(username.data()); + 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; @@ -334,7 +355,6 @@ std::string netchToClash(std::vector &nodes, std::string &baseConf, st return std::string(); } - for(nodeInfo &x : nodes) { singleproxy.reset(); @@ -853,6 +873,7 @@ std::string netchToQuanX(std::vector &nodes) std::string remark, hostname, port, method; std::string password, plugin, pluginopts; std::string id, aid, transproto, host, path; + std::string protocol, protoparam, obfs, obfsparam; std::string proxyStr, allLinks; for(nodeInfo &x : nodes) { @@ -883,6 +904,19 @@ std::string netchToQuanX(std::vector &nodes) if(plugin.size() && pluginopts.size()) proxyStr += ", " + replace_all_distinct(pluginopts, ";", ", "); break; + case SPEEDTEST_MESSAGE_FOUNDSSR: + password = GetMember(json, "Password"); + protocol = GetMember(json, "Protocol"); + protoparam = GetMember(json, "ProtocolParam"); + obfs = GetMember(json, "OBFS"); + obfsparam = GetMember(json, "OBFSParam"); + proxyStr = "shadowsocks = " + hostname + ":" + port + ", method=" + method + ", password=" + password + ", ssr-protocol=" + protocol; + if(protoparam.size()) + proxyStr += ", ssr-protocol-param=" + protoparam; + proxyStr += ", obfs=" + obfs; + if(obfsparam.size()) + proxyStr += ", obfs-host=" + obfsparam; + break; default: continue; }