#include #include #include #include #include #include "socket.h" #include "misc.h" #include "nodeinfo.h" #include "speedtestutil.h" #include "nodemanip.h" #include "ini_reader.h" #include "webget.h" #include "webserver.h" #include "subexport.h" #include "multithread.h" //common settings string_array def_exclude_remarks, def_include_remarks, rulesets; std::vector ruleset_content_array; std::string listen_address = "127.0.0.1", default_url, managed_config_prefix; int listen_port = 25500, max_pending_connections = 10, max_concurrent_threads = 4; bool api_mode = true, write_managed_config = false, update_ruleset_on_request = false, overwrite_original_rules = true; bool print_debug_info = false, cfw_child_process = false; extern std::string custom_group; //multi-thread lock extern std::mutex on_configuring; //preferences string_array renames, emojis; bool add_emoji = false, remove_old_emoji = false, append_proxy_type = true; std::string proxy_ruleset, proxy_subscription; std::string clash_rule_base; string_array clash_extra_group; std::string surge_rule_base, surfboard_rule_base, mellow_rule_base; void setcd(char *argv[]) { std::string path; char szTmp[1024]; #ifndef _WIN32 path.assign(argv[0]); if(path[0] != '/') { getcwd(szTmp, 1023); path.assign(szTmp); path.append("/"); path.append(argv[0]); } path = path.substr(0, path.rfind("/") + 1); #else GetModuleFileName(NULL, szTmp, 1023); strrchr(szTmp, '\\')[1] = '\0'; path.assign(szTmp); #endif // _WIN32 chdir(path.data()); } std::string refreshRulesets() { guarded_mutex guard(on_configuring); eraseElements(ruleset_content_array); string_array vArray; std::string rule_group, rule_url; ruleset_content rc; std::string proxy; if(proxy_ruleset == "SYSTEM") proxy = getSystemProxy(); else if(proxy_ruleset == "NONE") proxy = ""; else proxy = proxy_ruleset; for(std::string &x : rulesets) { /* vArray = split(x, ","); if(vArray.size() != 2) continue; rule_group = trim(vArray[0]); rule_url = trim(vArray[1]); */ if(x.find(",") == x.npos) continue; rule_group = trim(x.substr(0, x.find(","))); rule_url = trim(x.substr(x.find(",") + 1)); if(rule_url.find("[]") == 0) { std::cerr<<"Adding rule '"< nodes; int groupID = 0; if(include.size()) { eraseElements(ext.include_remarks); ext.include_remarks.emplace_back(include); } if(group.size()) custom_group = group; for(std::string &x : urls) { x = trim(x); std::cerr<<"Fetching node data from url '"< std::string { return refreshRulesets(); }); append_response("GET", "/readconf", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string { readConf(); return "done"; }); append_response("GET", "/sub", "text/plain;charset=utf-8", subconverter); append_response("GET", "/clash", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string { return subconverter(argument + "&target=clash", postdata); }); append_response("GET", "/clashr", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string { return subconverter(argument + "&target=clashr", postdata); }); append_response("GET", "/surge", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string { return subconverter(argument + "&target=surge", postdata); }); append_response("GET", "/surfboard", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string { return subconverter(argument + "&target=surfboard", postdata); }); append_response("GET", "/mellow", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string { return subconverter(argument + "&target=mellow", postdata); }); append_response("GET", "/ss", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string { return subconverter(argument + "&target=ss", postdata); }); append_response("GET", "/ssr", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string { return subconverter(argument + "&target=ssr", postdata); }); append_response("GET", "/v2ray", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string { return subconverter(argument + "&target=v2ray", postdata); }); append_response("GET", "/quan", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string { return subconverter(argument + "&target=quan", postdata); }); append_response("GET", "/quanx", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string { return subconverter(argument + "&target=quanx", postdata); }); append_response("GET", "/ssd", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string { return subconverter(argument + "&target=ssd", postdata); }); if(!api_mode) { append_response("GET", "/get", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string { std::string url = UrlDecode(getUrlArg(argument, "url")); return webGet(url, ""); }); append_response("GET", "/getlocal", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string { return fileGet(UrlDecode(getUrlArg(argument, "path"))); }); } listener_args args = {listen_address, listen_port, max_pending_connections, max_concurrent_threads}; std::cout<<"Serving HTTP @ http://"<