Parcourir la source

Enhancements

Add SNI host parsing support for Trojan subscriptions.
Add detailed log report.
Optimize codes.
Update build scripts.
Tindy X il y a 5 ans
Parent
commit
ef8b4e39ef
8 fichiers modifiés avec 148 ajouts et 116 suppressions
  1. 1 0
      CMakeLists.txt
  2. 1 0
      scripts/build.clang.sh
  3. 12 0
      src/interfaces.cpp
  4. 6 2
      src/speedtestutil.cpp
  5. 0 111
      src/subexport.cpp
  6. 0 3
      src/subexport.h
  7. 119 0
      src/upload.cpp
  8. 9 0
      src/upload.h

+ 1 - 0
CMakeLists.txt

@@ -48,6 +48,7 @@ ADD_EXECUTABLE(subconverter
     src/speedtestutil.cpp
     src/subexport.cpp
     src/templates.cpp
+    src/upload.cpp
     src/webget.cpp
     src/webserver_libevent.cpp)
 INCLUDE_DIRECTORIES(src)

+ 1 - 0
scripts/build.clang.sh

@@ -12,6 +12,7 @@ c++ -std=c++17 -Wall -fexceptions -c src/nodemanip.cpp -o obj/nodemanip.o
 c++ -std=c++17 -Wall -fexceptions -c src/rapidjson_extra.cpp -o obj/rapidjson_extra.o
 c++ -std=c++17 -Wall -fexceptions -c src/speedtestutil.cpp -o obj/speedtestutil.o
 c++ -std=c++17 -Wall -fexceptions -c src/subexport.cpp -o obj/subexport.o
+c++ -std=c++17 -Wall -fexceptions -c src/upload.cpp -o obj/upload.o
 c++ -std=c++17 -Wall -fexceptions -c src/templates.cpp -o obj/templates.o
 c++ -std=c++17 -Wall -fexceptions -c src/webget.cpp -o obj/webget.o
 c++ -std=c++17 -Wall -fexceptions -c src/webserver_libevent.cpp -o obj/webserver_libevent.o

+ 12 - 0
src/interfaces.cpp

@@ -18,6 +18,7 @@
 #include "logger.h"
 #include "string_hash.h"
 #include "templates.h"
+#include "upload.h"
 
 //common settings
 std::string pref_path = "pref.ini", def_ext_config;
@@ -1580,6 +1581,7 @@ std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS)
         *status_code = 400;
         return "Please insert your subscription link instead of clicking the default link.";
     }
+    writeLog(0, "SurgeConfToClash called with url '" + url + "'.", LOG_LEVEL_INFO);
 
     std::string proxy = parseProxy(proxy_config);
     YAML::Node clash;
@@ -1758,6 +1760,7 @@ std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS)
     }
     clash[rule_name] = rule;
 
+    writeLog(0, "Conversion completed.", LOG_LEVEL_INFO);
     return YAML::Dump(clash);
 }
 
@@ -1917,12 +1920,14 @@ std::string parseHostname(inja::Arguments &args)
 std::string template_webGet(inja::Arguments &args)
 {
     std::string data = args.at(0)->get<std::string>(), proxy = parseProxy(proxy_config);
+    writeLog(0, "Template called fetch with url '" + data + "'.", LOG_LEVEL_INFO);
     return webGet(data, proxy, cache_config);
 }
 
 std::string jinja2_webGet(const std::string &url)
 {
     std::string proxy = parseProxy(proxy_config);
+    writeLog(0, "Template called fetch with url '" + url + "'.", LOG_LEVEL_INFO);
     return webGet(url, proxy, cache_config);
 }
 
@@ -2097,6 +2102,7 @@ int simpleGenerator()
 std::string renderTemplate(RESPONSE_CALLBACK_ARGS)
 {
     std::string path = UrlDecode(getUrlArg(argument, "path"));
+    writeLog(0, "Trying to render template '" + path + "'...", LOG_LEVEL_INFO);
 
     if(path.find(template_path) != 0)
     {
@@ -2132,6 +2138,12 @@ std::string renderTemplate(RESPONSE_CALLBACK_ARGS)
 
     std::string output_content;
     if(render_template(template_content, tpl_args, output_content, template_path) != 0)
+    {
         *status_code = 400;
+        writeLog(0, "Render failed with error.", LOG_LEVEL_WARNING);
+    }
+    else
+        writeLog(0, "Render completed.", LOG_LEVEL_INFO);
+
     return output_content;
 }

+ 6 - 2
src/speedtestutil.cpp

@@ -733,7 +733,7 @@ void explodeHTTPSub(std::string link, const std::string &custom_port, nodeInfo &
 
 void explodeTrojan(std::string trojan, const std::string &custom_port, int local_port, nodeInfo &node)
 {
-    std::string server, port, psk, addition, remark;
+    std::string server, port, psk, addition, remark, host;
     string_array vArray;
     trojan.erase(0, 9);
     string_size pos = trojan.rfind("#");
@@ -759,15 +759,19 @@ void explodeTrojan(std::string trojan, const std::string &custom_port, int local
     server = vArray[1];
     port = custom_port.empty() ? vArray[2] : custom_port;
 
+    host = getUrlArg(addition, "peer");
+
     if(remark.empty())
         remark = server + ":" + port;
+    if(host.empty() && !isIPv4(server) && !isIPv6(server))
+        host = server;
 
     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, "", false);
+    node.proxyStr = trojanConstruct(remark, server, port, psk, host, true);
 }
 
 void explodeQuan(std::string quan, const std::string &custom_port, int local_port, nodeInfo &node)

+ 0 - 111
src/subexport.cpp

@@ -583,7 +583,6 @@ void rulesetToSurge(INIReader &base_rule, std::vector<ruleset_content> &ruleset_
         }
     }
 
-
     const std::string rule_match_regex = "^(.*?,.*?)(,.*)(,.*)$";
 
     for(ruleset_content &x : ruleset_content_array)
@@ -2678,113 +2677,3 @@ std::string netchToLoon(std::vector<nodeInfo> &nodes, std::string &base_conf, st
 
     return ini.ToString();
 }
-
-std::string buildGistData(std::string name, std::string content)
-{
-    rapidjson::StringBuffer sb;
-    rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
-    writer.StartObject();
-    writer.Key("description");
-    writer.String("subconverter");
-    writer.Key("public");
-    writer.Bool(false);
-    writer.Key("files");
-    writer.StartObject();
-    writer.Key(name.data());
-    writer.StartObject();
-    writer.Key("content");
-    writer.String(content.data());
-    writer.EndObject();
-    writer.EndObject();
-    writer.EndObject();
-    return sb.GetString();
-}
-
-int uploadGist(std::string name, std::string path, std::string content, bool writeManageURL)
-{
-    INIReader ini;
-    rapidjson::Document json;
-    std::string token, id, username, retData, url;
-    int retVal = 0;
-
-    if(!fileExist("gistconf.ini"))
-    {
-        //std::cerr<<"gistconf.ini not found. Skipping...\n";
-        writeLog(0, "gistconf.ini not found. Skipping...", LOG_LEVEL_ERROR);
-        return -1;
-    }
-
-    ini.ParseFile("gistconf.ini");
-    if(ini.EnterSection("common") != 0)
-    {
-        //std::cerr<<"gistconf.ini has incorrect format. Skipping...\n";
-        writeLog(0, "gistconf.ini has incorrect format. Skipping...", LOG_LEVEL_ERROR);
-        return -1;
-    }
-
-    token = ini.Get("token");
-    if(!token.size())
-    {
-        //std::cerr<<"No token is provided. Skipping...\n";
-        writeLog(0, "No token is provided. Skipping...", LOG_LEVEL_ERROR);
-        return -1;
-    }
-
-    id = ini.Get("id");
-    username = ini.Get("username");
-    if(!path.size())
-    {
-        if(ini.ItemExist("path"))
-            path = ini.Get(name, "path");
-        else
-            path = name;
-    }
-
-    if(!id.size())
-    {
-        //std::cerr<<"No gist id is provided. Creating new gist...\n";
-        writeLog(0, "No Gist id is provided. Creating new Gist...", LOG_LEVEL_ERROR);
-        retVal = webPost("https://api.github.com/gists", buildGistData(path, content), getSystemProxy(), token, &retData);
-        if(retVal != 201)
-        {
-            //std::cerr<<"Create new Gist failed! Return data:\n"<<retData<<"\n";
-            writeLog(0, "Create new Gist failed! Return data:\n" + retData, LOG_LEVEL_ERROR);
-            return -1;
-        }
-    }
-    else
-    {
-        url = "https://gist.githubusercontent.com/" + username + "/" + id + "/raw/" + path;
-        //std::cerr<<"Gist id provided. Modifying Gist...\n";
-        writeLog(0, "Gist id provided. Modifying Gist...", LOG_LEVEL_INFO);
-        if(writeManageURL)
-            content = "#!MANAGED-CONFIG " + url + "\n" + content;
-        retVal = webPatch("https://api.github.com/gists/" + id, buildGistData(path, content), getSystemProxy(), token, &retData);
-        if(retVal != 200)
-        {
-            //std::cerr<<"Modify gist failed! Return data:\n"<<retData<<"\n";
-            writeLog(0, "Modify Gist failed! Return data:\n" + retData, LOG_LEVEL_ERROR);
-            return -1;
-        }
-    }
-    json.Parse(retData.data());
-    GetMember(json, "id", id);
-    if(json.HasMember("owner"))
-        GetMember(json["owner"], "login", username);
-    url = "https://gist.githubusercontent.com/" + username + "/" + id + "/raw/" + path;
-    //std::cerr<<"Writing to Gist success!\nGenerator: "<<name<<"\nPath: "<<path<<"\nRaw URL: "<<url<<"\nGist owner: "<<username<<"\n";
-    writeLog(0, "Writing to Gist success!\nGenerator: " + name + "\nPath: " + path + "\nRaw URL: " + url + "\nGist owner: " + username, LOG_LEVEL_INFO);
-
-    ini.EraseSection();
-    ini.Set("token", token);
-    ini.Set("id", id);
-    ini.Set("username", username);
-
-    ini.SetCurrentSection(path);
-    ini.EraseSection();
-    ini.Set("type", name);
-    ini.Set("url", url);
-
-    ini.ToFile("gistconf.ini");
-    return 0;
-}

+ 0 - 3
src/subexport.h

@@ -58,7 +58,4 @@ std::string netchToQuan(std::vector<nodeInfo> &nodes, std::string &base_conf, st
 void netchToQuan(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, extra_settings &ext);
 std::string netchToSSD(std::vector<nodeInfo> &nodes, std::string &group, std::string &userinfo, extra_settings &ext);
 
-std::string buildGistData(std::string name, std::string content);
-int uploadGist(std::string name, std::string path, std::string content, bool writeManageURL);
-
 #endif // SUBEXPORT_H_INCLUDED

+ 119 - 0
src/upload.cpp

@@ -0,0 +1,119 @@
+#include <string>
+
+#include <rapidjson/writer.h>
+#include <rapidjson/document.h>
+
+#include "webget.h"
+#include "ini_reader.h"
+#include "logger.h"
+#include "rapidjson_extra.h"
+
+std::string buildGistData(std::string name, std::string content)
+{
+    rapidjson::StringBuffer sb;
+    rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
+    writer.StartObject();
+    writer.Key("description");
+    writer.String("subconverter");
+    writer.Key("public");
+    writer.Bool(false);
+    writer.Key("files");
+    writer.StartObject();
+    writer.Key(name.data());
+    writer.StartObject();
+    writer.Key("content");
+    writer.String(content.data());
+    writer.EndObject();
+    writer.EndObject();
+    writer.EndObject();
+    return sb.GetString();
+}
+
+int uploadGist(std::string name, std::string path, std::string content, bool writeManageURL)
+{
+    INIReader ini;
+    rapidjson::Document json;
+    std::string token, id, username, retData, url;
+    int retVal = 0;
+
+    if(!fileExist("gistconf.ini"))
+    {
+        //std::cerr<<"gistconf.ini not found. Skipping...\n";
+        writeLog(0, "gistconf.ini not found. Skipping...", LOG_LEVEL_ERROR);
+        return -1;
+    }
+
+    ini.ParseFile("gistconf.ini");
+    if(ini.EnterSection("common") != 0)
+    {
+        //std::cerr<<"gistconf.ini has incorrect format. Skipping...\n";
+        writeLog(0, "gistconf.ini has incorrect format. Skipping...", LOG_LEVEL_ERROR);
+        return -1;
+    }
+
+    token = ini.Get("token");
+    if(!token.size())
+    {
+        //std::cerr<<"No token is provided. Skipping...\n";
+        writeLog(0, "No token is provided. Skipping...", LOG_LEVEL_ERROR);
+        return -1;
+    }
+
+    id = ini.Get("id");
+    username = ini.Get("username");
+    if(!path.size())
+    {
+        if(ini.ItemExist("path"))
+            path = ini.Get(name, "path");
+        else
+            path = name;
+    }
+
+    if(!id.size())
+    {
+        //std::cerr<<"No gist id is provided. Creating new gist...\n";
+        writeLog(0, "No Gist id is provided. Creating new Gist...", LOG_LEVEL_ERROR);
+        retVal = webPost("https://api.github.com/gists", buildGistData(path, content), getSystemProxy(), token, &retData);
+        if(retVal != 201)
+        {
+            //std::cerr<<"Create new Gist failed! Return data:\n"<<retData<<"\n";
+            writeLog(0, "Create new Gist failed! Return data:\n" + retData, LOG_LEVEL_ERROR);
+            return -1;
+        }
+    }
+    else
+    {
+        url = "https://gist.githubusercontent.com/" + username + "/" + id + "/raw/" + path;
+        //std::cerr<<"Gist id provided. Modifying Gist...\n";
+        writeLog(0, "Gist id provided. Modifying Gist...", LOG_LEVEL_INFO);
+        if(writeManageURL)
+            content = "#!MANAGED-CONFIG " + url + "\n" + content;
+        retVal = webPatch("https://api.github.com/gists/" + id, buildGistData(path, content), getSystemProxy(), token, &retData);
+        if(retVal != 200)
+        {
+            //std::cerr<<"Modify gist failed! Return data:\n"<<retData<<"\n";
+            writeLog(0, "Modify Gist failed! Return data:\n" + retData, LOG_LEVEL_ERROR);
+            return -1;
+        }
+    }
+    json.Parse(retData.data());
+    GetMember(json, "id", id);
+    if(json.HasMember("owner"))
+        GetMember(json["owner"], "login", username);
+    url = "https://gist.githubusercontent.com/" + username + "/" + id + "/raw/" + path;
+    //std::cerr<<"Writing to Gist success!\nGenerator: "<<name<<"\nPath: "<<path<<"\nRaw URL: "<<url<<"\nGist owner: "<<username<<"\n";
+    writeLog(0, "Writing to Gist success!\nGenerator: " + name + "\nPath: " + path + "\nRaw URL: " + url + "\nGist owner: " + username, LOG_LEVEL_INFO);
+
+    ini.EraseSection();
+    ini.Set("token", token);
+    ini.Set("id", id);
+    ini.Set("username", username);
+
+    ini.SetCurrentSection(path);
+    ini.EraseSection();
+    ini.Set("type", name);
+    ini.Set("url", url);
+
+    ini.ToFile("gistconf.ini");
+    return 0;
+}

+ 9 - 0
src/upload.h

@@ -0,0 +1,9 @@
+#ifndef UPLOAD_H_INCLUDED
+#define UPLOAD_H_INCLUDED
+
+#include <string>
+
+std::string buildGistData(std::string name, std::string content);
+int uploadGist(std::string name, std::string path, std::string content, bool writeManageURL);
+
+#endif // UPLOAD_H_INCLUDED