mirror of
https://github.com/asdlokj1qpi233/subconverter.git
synced 2025-10-30 21:32:42 +00:00
Bug fixes
Add custom proxy groups and rulesets with URI arguments. Fix when running Linux version, if a request URI is too long, the program will crash. Optimize codes. Update LAN ruleset.
This commit is contained in:
11
ini_reader.h
11
ini_reader.h
@@ -7,6 +7,7 @@
|
||||
|
||||
typedef std::map<std::string, std::multimap<std::string, std::string>> ini_data_struct;
|
||||
typedef std::multimap<std::string, std::string> string_multimap;
|
||||
typedef std::vector<std::string> string_array;
|
||||
|
||||
class INIReader
|
||||
{
|
||||
@@ -31,13 +32,9 @@ private:
|
||||
bool chkIgnore(std::string section)
|
||||
{
|
||||
bool excluded = false, included = false;
|
||||
if(count(exclude_sections.begin(), exclude_sections.end(), section) > 0)
|
||||
excluded = true;
|
||||
if(include_sections.size() != 0)
|
||||
{
|
||||
if(count(include_sections.begin(), include_sections.end(), section) > 0)
|
||||
included = true;
|
||||
}
|
||||
excluded = std::find(exclude_sections.cbegin(), exclude_sections.cend(), section) != exclude_sections.cend();
|
||||
if(include_sections.size())
|
||||
included = std::find(include_sections.cbegin(), include_sections.cend(), section) != include_sections.cend();
|
||||
else
|
||||
included = true;
|
||||
|
||||
|
||||
91
main.cpp
91
main.cpp
@@ -17,6 +17,7 @@
|
||||
#include "multithread.h"
|
||||
|
||||
//common settings
|
||||
std::string pref_path = "pref.ini";
|
||||
string_array def_exclude_remarks, def_include_remarks, rulesets;
|
||||
std::vector<ruleset_content> ruleset_content_array;
|
||||
std::string listen_address = "127.0.0.1", default_url, managed_config_prefix;
|
||||
@@ -61,10 +62,9 @@ void setcd(char *argv[])
|
||||
}
|
||||
|
||||
|
||||
std::string refreshRulesets()
|
||||
std::string refreshRulesets(string_array &ruleset_list, std::vector<ruleset_content> &rca)
|
||||
{
|
||||
guarded_mutex guard(on_configuring);
|
||||
eraseElements(ruleset_content_array);
|
||||
eraseElements(rca);
|
||||
std::string rule_group, rule_url;
|
||||
ruleset_content rc;
|
||||
|
||||
@@ -76,7 +76,7 @@ std::string refreshRulesets()
|
||||
else
|
||||
proxy = proxy_ruleset;
|
||||
|
||||
for(std::string &x : rulesets)
|
||||
for(std::string &x : ruleset_list)
|
||||
{
|
||||
/*
|
||||
vArray = split(x, ",");
|
||||
@@ -93,7 +93,7 @@ std::string refreshRulesets()
|
||||
{
|
||||
std::cerr<<"Adding rule '"<<rule_url.substr(2)<<","<<rule_group<<"'."<<std::endl;
|
||||
rc = {rule_group, "", rule_url};
|
||||
ruleset_content_array.emplace_back(rc);
|
||||
rca.emplace_back(rc);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
@@ -103,13 +103,15 @@ std::string refreshRulesets()
|
||||
{
|
||||
rc = {rule_group, rule_url, fileGet(rule_url, false)};
|
||||
}
|
||||
else
|
||||
else if(rule_url.find("http://") == 0 || rule_url.find("https://") == 0)
|
||||
{
|
||||
rc = {rule_group, rule_url, webGet(rule_url, proxy)};
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
if(rc.rule_content.size())
|
||||
ruleset_content_array.emplace_back(rc);
|
||||
rca.emplace_back(rc);
|
||||
else
|
||||
std::cerr<<"Warning: No data was fetched from this link. Skipping..."<<std::endl;
|
||||
}
|
||||
@@ -127,8 +129,9 @@ void readConf()
|
||||
eraseElements(rulesets);
|
||||
string_array emojis_temp, renames_temp;
|
||||
INIReader ini;
|
||||
ini.allow_dup_section_titles = true;
|
||||
//ini.do_utf8_to_gbk = true;
|
||||
ini.ParseFile("pref.ini");
|
||||
ini.ParseFile(pref_path);
|
||||
|
||||
ini.EnterSection("common");
|
||||
if(ini.ItemExist("api_mode"))
|
||||
@@ -227,9 +230,46 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
||||
std::string append_type = getUrlArg(argument, "append_type"), tfo = getUrlArg(argument, "tfo"), udp = getUrlArg(argument, "udp"), nodelist = getUrlArg(argument, "list");
|
||||
std::string include = UrlDecode(getUrlArg(argument, "include")), exclude = UrlDecode(getUrlArg(argument, "exclude"));
|
||||
std::string base_content, output_content;
|
||||
string_array extra_group, include_remarks, exclude_remarks;
|
||||
std::string groups = urlsafe_base64_decode(getUrlArg(argument, "groups"));
|
||||
extra_group = split(groups, "`");
|
||||
string_array extra_group, extra_ruleset, include_remarks, exclude_remarks;
|
||||
std::string groups = urlsafe_base64_decode(getUrlArg(argument, "groups")), ruleset = urlsafe_base64_decode(getUrlArg(argument, "ruleset"));
|
||||
std::vector<ruleset_content> rca;
|
||||
|
||||
if(!url.size())
|
||||
url = default_url;
|
||||
if(!url.size() || !target.size())
|
||||
return "Invalid request!";
|
||||
if(!api_mode || cfw_child_process)
|
||||
readConf();
|
||||
|
||||
if(groups.size())
|
||||
{
|
||||
extra_group = split(groups, "@");
|
||||
if(!extra_group.size())
|
||||
extra_group = clash_extra_group;
|
||||
}
|
||||
else
|
||||
extra_group = clash_extra_group;
|
||||
|
||||
if(ruleset.size())
|
||||
{
|
||||
extra_ruleset = split(ruleset, "@");
|
||||
if(!extra_ruleset.size())
|
||||
{
|
||||
if(update_ruleset_on_request || cfw_child_process)
|
||||
refreshRulesets(rulesets, ruleset_content_array);
|
||||
rca = ruleset_content_array;
|
||||
}
|
||||
else
|
||||
{
|
||||
refreshRulesets(extra_ruleset, rca);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(update_ruleset_on_request || cfw_child_process)
|
||||
refreshRulesets(rulesets, ruleset_content_array);
|
||||
rca = ruleset_content_array;
|
||||
}
|
||||
|
||||
extra_settings ext;
|
||||
if(emoji == "true")
|
||||
@@ -259,13 +299,6 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
||||
ext.nodelist = nodelist == "true";
|
||||
ext.surge_ssr_path = surge_ssr_path;
|
||||
|
||||
if(!url.size())
|
||||
url = default_url;
|
||||
if(!url.size() || !target.size())
|
||||
return "Invalid request!";
|
||||
if(!api_mode || cfw_child_process)
|
||||
readConf();
|
||||
|
||||
string_array urls = split(url, "|");
|
||||
std::vector<nodeInfo> nodes;
|
||||
int groupID = 0;
|
||||
@@ -290,8 +323,6 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
||||
}
|
||||
if(!nodes.size())
|
||||
return "No nodes were found!";
|
||||
if(update_ruleset_on_request || cfw_child_process)
|
||||
refreshRulesets();
|
||||
|
||||
std::cerr<<"Generate target: ";
|
||||
if(target == "clash" || target == "clashr")
|
||||
@@ -302,21 +333,22 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
||||
else
|
||||
base_content = webGet(clash_rule_base, getSystemProxy());
|
||||
|
||||
output_content = netchToClash(nodes, base_content, ruleset_content_array, clash_extra_group, target == "clashr", ext);
|
||||
output_content = netchToClash(nodes, base_content, rca, extra_group, target == "clashr", ext);
|
||||
if(upload == "true")
|
||||
uploadGist("clash", upload_path, output_content, false);
|
||||
return output_content;
|
||||
}
|
||||
else if(target == "surge")
|
||||
{
|
||||
std::cerr<<"Surge "<<version<<std::endl;
|
||||
int surge_ver = version.size() ? stoi(version) : 3;
|
||||
int surge_ver = version.size() ? to_int(version, 3) : 3;
|
||||
std::cerr<<"Surge "<<surge_ver<<std::endl;
|
||||
|
||||
if(fileExist(surge_rule_base))
|
||||
base_content = fileGet(surge_rule_base, false);
|
||||
else
|
||||
base_content = webGet(surge_rule_base, getSystemProxy());
|
||||
|
||||
output_content = netchToSurge(nodes, base_content, ruleset_content_array, clash_extra_group, surge_ver, ext);
|
||||
output_content = netchToSurge(nodes, base_content, rca, extra_group, surge_ver, ext);
|
||||
if(upload == "true")
|
||||
uploadGist("surge" + version, upload_path, output_content, true);
|
||||
|
||||
@@ -332,7 +364,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
||||
else
|
||||
base_content = webGet(surfboard_rule_base, getSystemProxy());
|
||||
|
||||
output_content = netchToSurge(nodes, base_content, ruleset_content_array, clash_extra_group, 2, ext);
|
||||
output_content = netchToSurge(nodes, base_content, rca, extra_group, 2, ext);
|
||||
if(upload == "true")
|
||||
uploadGist("surfboard", upload_path, output_content, true);
|
||||
|
||||
@@ -348,7 +380,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
||||
else
|
||||
base_content = webGet(mellow_rule_base, getSystemProxy());
|
||||
|
||||
output_content = netchToMellow(nodes, base_content, ruleset_content_array, clash_extra_group, ext);
|
||||
output_content = netchToMellow(nodes, base_content, rca, extra_group, ext);
|
||||
if(upload == "true")
|
||||
uploadGist("mellow", upload_path, output_content, true);
|
||||
|
||||
@@ -415,6 +447,8 @@ void chkArg(int argc, char *argv[])
|
||||
{
|
||||
if(strcmp(argv[i], "-cfw") == 0)
|
||||
cfw_child_process = true;
|
||||
else if(strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "--file") == 0)
|
||||
pref_path.assign(argv[++i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,13 +467,14 @@ int main(int argc, char *argv[])
|
||||
#ifndef _DEBUG
|
||||
setcd(argv);
|
||||
#endif // _DEBUG
|
||||
chkArg(argc, argv);
|
||||
readConf();
|
||||
if(!update_ruleset_on_request)
|
||||
refreshRulesets();
|
||||
refreshRulesets(rulesets, ruleset_content_array);
|
||||
|
||||
append_response("GET", "/refreshrules", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string
|
||||
{
|
||||
return refreshRulesets();
|
||||
return refreshRulesets(rulesets, ruleset_content_array);
|
||||
});
|
||||
|
||||
append_response("GET", "/readconf", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string
|
||||
|
||||
44
misc.cpp
44
misc.cpp
@@ -402,6 +402,7 @@ std::string trim(const std::string& str)
|
||||
std::string getUrlArg(std::string url, std::string request)
|
||||
{
|
||||
std::smatch result;
|
||||
/*
|
||||
if (regex_search(url.cbegin(), url.cend(), result, std::regex(request + "=(.*?)&")))
|
||||
{
|
||||
return result[1];
|
||||
@@ -414,6 +415,15 @@ std::string getUrlArg(std::string url, std::string request)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
*/
|
||||
|
||||
string_array vArray, arglist = split(url, "&");
|
||||
for(std::string &x : arglist)
|
||||
{
|
||||
if(regex_search(x.cbegin(), x.cend(), result, std::regex("^" + request + "=(.*)$")))
|
||||
return result[1];
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string replace_all_distinct(std::string str, std::string old_value, std::string new_value)
|
||||
@@ -429,24 +439,45 @@ std::string replace_all_distinct(std::string str, std::string old_value, std::st
|
||||
}
|
||||
|
||||
bool regFind(std::string src, std::string target)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::regex reg(target);
|
||||
return regex_search(src, reg);
|
||||
}
|
||||
catch (std::regex_error &e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string regReplace(std::string src, std::string match, std::string rep)
|
||||
{
|
||||
std::string result = "";
|
||||
try
|
||||
{
|
||||
std::regex reg(match);
|
||||
regex_replace(back_inserter(result), src.begin(), src.end(), reg, rep);
|
||||
}
|
||||
catch (std::regex_error &e)
|
||||
{
|
||||
result = src;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool regMatch(std::string src, std::string match)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::regex reg(match);
|
||||
return regex_match(src, reg);
|
||||
}
|
||||
catch (std::regex_error &e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string speedCalc(double speed)
|
||||
{
|
||||
@@ -735,6 +766,19 @@ std::string to_string(const YAML::Node &node)
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
int to_int(std::string &s, int def_vaule)
|
||||
{
|
||||
int retval = 0;
|
||||
char c;
|
||||
std::stringstream ss(s);
|
||||
if(!(ss >> retval))
|
||||
return def_vaule;
|
||||
else if(ss >> c)
|
||||
return def_vaule;
|
||||
else
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::string getFormData(const std::string &raw_data)
|
||||
{
|
||||
std::stringstream strstrm;
|
||||
|
||||
1
misc.h
1
misc.h
@@ -52,6 +52,7 @@ void removeUTF8BOM(std::string &data);
|
||||
int shortAssemble(unsigned short num_a, unsigned short num_b);
|
||||
void shortDisassemble(int source, unsigned short &num_a, unsigned short &num_b);
|
||||
std::string to_string(const YAML::Node &node);
|
||||
int to_int(std::string &s, int def_vaule = 0);
|
||||
|
||||
std::string fileGet(std::string path, bool binary = true);
|
||||
int fileWrite(std::string path, std::string content, bool overwrite);
|
||||
|
||||
@@ -4,7 +4,7 @@ IP-CIDR,10.0.0.0/8
|
||||
IP-CIDR,172.16.0.0/12
|
||||
IP-CIDR,127.0.0.0/8
|
||||
IP-CIDR,100.64.0.0/10
|
||||
IP-CIDR,::1/128
|
||||
IP-CIDR,fc00::/7
|
||||
IP-CIDR,fe80::/10
|
||||
IP-CIDR,fd00::/8
|
||||
IP-CIDR6,::1/128
|
||||
IP-CIDR6,fc00::/7
|
||||
IP-CIDR6,fe80::/10
|
||||
IP-CIDR6,fd00::/8
|
||||
|
||||
@@ -610,7 +610,7 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
|
||||
|
||||
ini.SetCurrentSection("Proxy");
|
||||
ini.EraseSection();
|
||||
ini.Set("DIRECT", "direct");
|
||||
ini.Set("{NONAME}", "DIRECT = direct");
|
||||
for(nodeInfo &x : nodes)
|
||||
{
|
||||
json.Parse(x.proxyStr.data());
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "webserver.h"
|
||||
|
||||
typedef std::vector<std::string> string_array;
|
||||
int def_timeout = 5;
|
||||
|
||||
struct responseRoute
|
||||
{
|
||||
@@ -21,7 +22,7 @@ struct responseRoute
|
||||
|
||||
std::vector<responseRoute> responses;
|
||||
|
||||
//for use of multi-thread socket test
|
||||
//for use of multi-thread
|
||||
typedef std::lock_guard<std::mutex> guarded_mutex;
|
||||
int working_thread = 0, max_send_failure = 10;
|
||||
bool SERVER_EXIT_FLAG = false;
|
||||
@@ -206,6 +207,21 @@ void send_file(std::string arguments, int sock)
|
||||
sendall(sock, "0\r\n\r\n");
|
||||
}
|
||||
|
||||
int setTimeout(SOCKET s, int timeout)
|
||||
{
|
||||
int ret = -1;
|
||||
#ifdef _WIN32
|
||||
ret = setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(int));
|
||||
ret = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(int));
|
||||
#else
|
||||
struct timeval timeo = {0, timeout * 1000};
|
||||
ret = setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeo, sizeof(timeo));
|
||||
ret = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeo, sizeof(timeo));
|
||||
#endif
|
||||
def_timeout = timeout;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void handle_req(std::string request, int client_sock)
|
||||
{
|
||||
working_acc();
|
||||
@@ -220,8 +236,7 @@ void handle_req(std::string request, int client_sock)
|
||||
goto end;
|
||||
}
|
||||
|
||||
printf("handle_cmd: %s\n", command);
|
||||
printf("handle_path: %s\n", arguments);
|
||||
std::cerr<<"handle_cmd: "<<command<<"\n"<<"handle_path: "<<arguments<<"\n";
|
||||
|
||||
vArray = split(arguments, "?");
|
||||
|
||||
@@ -277,7 +292,7 @@ void append_response(std::string type, std::string request, std::string content_
|
||||
responses.push_back(rr);
|
||||
}
|
||||
|
||||
void* start_web_server(void *argv)
|
||||
int start_web_server_multi(void *argv)
|
||||
{
|
||||
//log startup
|
||||
struct listener_args *args = (listener_args*)argv;
|
||||
@@ -295,7 +310,7 @@ void* start_web_server(void *argv)
|
||||
{
|
||||
//log socket error
|
||||
std::cerr<<"socket build error!"<<std::endl;
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZeroMemory(&server_addr, sizeof(server_addr));
|
||||
@@ -307,14 +322,14 @@ void* start_web_server(void *argv)
|
||||
//log bind error
|
||||
std::cerr<<"socket bind error!"<<std::endl;
|
||||
closesocket(server_socket);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
if (listen(server_socket, max_conn) == -1 )
|
||||
{
|
||||
//log listen error
|
||||
std::cerr<<"socket listen error!"<<std::endl;
|
||||
closesocket(server_socket);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
setTimeout(server_socket, 500);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <evhttp.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -22,10 +23,18 @@ struct responseRoute
|
||||
|
||||
std::vector<responseRoute> responses;
|
||||
|
||||
static inline void buffer_cleanup(struct evbuffer *eb)
|
||||
{
|
||||
evbuffer_free(eb);
|
||||
#ifdef MALLOC_TRIM
|
||||
malloc_trim(0);
|
||||
#endif // MALLOC_TRIM
|
||||
}
|
||||
|
||||
static inline int process_request(const char *method_str, std::string uri, std::string &postdata, std::string &content_type, std::string &return_data)
|
||||
{
|
||||
std::string path, arguments;
|
||||
//std::cerr << "handle_cmd: " << method_str << std::endl << "handle_uri: " << uri << std::endl;
|
||||
std::cerr << "handle_cmd: " << method_str << std::endl << "handle_uri: " << uri << std::endl;
|
||||
|
||||
if(strFind(uri, "?"))
|
||||
{
|
||||
@@ -56,7 +65,7 @@ static inline int process_request(const char *method_str, std::string uri, std::
|
||||
void OnReq(evhttp_request *req, void *args)
|
||||
{
|
||||
const char *req_content_type = evhttp_find_header(req->input_headers, "Content-Type"), *req_ac_method = evhttp_find_header(req->input_headers, "Access-Control-Request-Method");
|
||||
const char *req_method = req_ac_method == NULL ? EVBUFFER_LENGTH(req->input_buffer) == 0 ? "GET" : "POST" : "OPTIONS", *uri = evhttp_request_get_uri(req);
|
||||
const char *req_method = req_ac_method == NULL ? EVBUFFER_LENGTH(req->input_buffer) == 0 ? "GET" : "POST" : "OPTIONS", *uri = req->uri;
|
||||
int retVal;
|
||||
std::string postdata, content_type, return_data;
|
||||
|
||||
@@ -73,7 +82,8 @@ void OnReq(evhttp_request *req, void *args)
|
||||
|
||||
retVal = process_request(req_method, uri, postdata, content_type, return_data);
|
||||
|
||||
auto *OutBuf = evhttp_request_get_output_buffer(req);
|
||||
//auto *OutBuf = evhttp_request_get_output_buffer(req);
|
||||
struct evbuffer *OutBuf = evbuffer_new();
|
||||
if (!OutBuf)
|
||||
return;
|
||||
|
||||
@@ -83,7 +93,6 @@ void OnReq(evhttp_request *req, void *args)
|
||||
evhttp_add_header(req->output_headers, "Access-Control-Allow-Origin", "*");
|
||||
evhttp_add_header(req->output_headers, "Access-Control-Allow-Headers", "*");
|
||||
evhttp_send_reply(req, HTTP_OK, "", NULL);
|
||||
return;
|
||||
break;
|
||||
case 0: //found normal
|
||||
if(content_type.size())
|
||||
@@ -92,6 +101,7 @@ void OnReq(evhttp_request *req, void *args)
|
||||
{
|
||||
evhttp_add_header(req->output_headers, "Location", return_data.c_str());
|
||||
evhttp_send_reply(req, HTTP_MOVETEMP, "", NULL);
|
||||
buffer_cleanup(OutBuf);
|
||||
return;
|
||||
}
|
||||
else
|
||||
@@ -108,6 +118,7 @@ void OnReq(evhttp_request *req, void *args)
|
||||
default: //undefined behavior
|
||||
evhttp_send_error(req, HTTP_INTERNAL, "");
|
||||
}
|
||||
buffer_cleanup(OutBuf);
|
||||
}
|
||||
|
||||
int start_web_server(void *argv)
|
||||
|
||||
Reference in New Issue
Block a user