From 406b0f20228b81d7ce06f2c4d49a5044fe015c23 Mon Sep 17 00:00:00 2001 From: Tindy X <49061470+tindy2013@users.noreply.github.com> Date: Sun, 20 Mar 2022 17:34:01 +0800 Subject: [PATCH] Enhancements Fix incorrect order of tolerance and timeout field in custom group config. Fix Content-Disposition header for better support on browsers. Fix parsing of some Shadowrocket links. Support HEAD request that only return Subscription-UserInfo (#434). Add more detail info to crash report. --- src/config/binding.h | 2 +- src/handler/interfaces.cpp | 13 ++++++++----- src/parser/subparser.cpp | 13 +++++++------ src/server/webserver_libevent.cpp | 10 +++++++--- src/utils/logger.cpp | 25 +++++++++++++++++++++++++ src/utils/logger.h | 8 ++++++++ 6 files changed, 56 insertions(+), 15 deletions(-) diff --git a/src/config/binding.h b/src/config/binding.h index f0f0a8a..347ef29 100644 --- a/src/config/binding.h +++ b/src/config/binding.h @@ -224,7 +224,7 @@ namespace INIBinding continue; rules_upper_bound -= 2; conf.Url = vArray[rules_upper_bound]; - parseGroupTimes(vArray[rules_upper_bound + 1], &conf.Interval, &conf.Tolerance, &conf.Timeout); + parseGroupTimes(vArray[rules_upper_bound + 1], &conf.Interval, &conf.Timeout, &conf.Tolerance); } for(unsigned int i = 2; i < rules_upper_bound; i++) diff --git a/src/handler/interfaces.cpp b/src/handler/interfaces.cpp index 976878d..80dacbd 100644 --- a/src/handler/interfaces.cpp +++ b/src/handler/interfaces.cpp @@ -342,7 +342,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) std::string argGroupName = urlDecode(getUrlArg(argument, "group")), argUploadPath = getUrlArg(argument, "upload_path"); std::string argIncludeRemark = urlDecode(getUrlArg(argument, "include")), argExcludeRemark = urlDecode(getUrlArg(argument, "exclude")); std::string argCustomGroups = urlSafeBase64Decode(getUrlArg(argument, "groups")), argCustomRulesets = urlSafeBase64Decode(getUrlArg(argument, "ruleset")), argExternalConfig = urlDecode(getUrlArg(argument, "config")); - std::string argDeviceID = getUrlArg(argument, "dev_id"), argFilename = getUrlArg(argument, "filename"), argUpdateInterval = getUrlArg(argument, "interval"), argUpdateStrict = getUrlArg(argument, "strict"); + std::string argDeviceID = getUrlArg(argument, "dev_id"), argFilename = urlDecode(getUrlArg(argument, "filename")), argUpdateInterval = getUrlArg(argument, "interval"), argUpdateStrict = getUrlArg(argument, "strict"); std::string argRenames = urlDecode(getUrlArg(argument, "rename")), argFilterScript = urlDecode(getUrlArg(argument, "filter_script")); /// switches with default value @@ -612,6 +612,12 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) *status_code = 400; return "No nodes were found!"; } + if(subInfo.size() && argAppendUserinfo.get(global.appendUserinfo)) + response.headers.emplace("Subscription-UserInfo", subInfo); + + if(request.method == "HEAD") + return ""; + argPrependInsert.define(global.prependInsert); if(argPrependInsert) { @@ -673,9 +679,6 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) for(Proxy &x : nodes) x.Group = argGroupName; - if(subInfo.size() && argAppendUserinfo.get(global.appendUserinfo)) - response.headers.emplace("Subscription-UserInfo", subInfo); - //do pre-process now preprocessNodes(nodes, ext); @@ -886,7 +889,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) } writeLog(0, "Generate completed.", LOG_LEVEL_INFO); if(argFilename.size()) - response.headers.emplace("Content-Disposition", "attachment; filename=\"" + argFilename + "\""); + response.headers.emplace("Content-Disposition", "attachment; filename=\"" + argFilename + "\"; filename*=utf-8''" + urlEncode(argFilename)); return output_content; } diff --git a/src/parser/subparser.cpp b/src/parser/subparser.cpp index 43c1c71..9798395 100644 --- a/src/parser/subparser.cpp +++ b/src/parser/subparser.cpp @@ -120,16 +120,17 @@ void explodeVmess(std::string vmess, Proxy &node) std::string version, ps, add, port, type, id, aid, net, path, host, tls, sni; Document jsondata; std::vector vArray; - if(regMatch(vmess, "vmess://(.*?)@(.*)")) - { - explodeStdVMess(vmess, node); - return; - } - else if(regMatch(vmess, "vmess://(.*?)\\?(.*)")) //shadowrocket style link + + if(regMatch(vmess, "vmess://([A-Za-z0-9-_]+)\\?(.*)")) //shadowrocket style link { explodeShadowrocket(vmess, node); return; } + else if(regMatch(vmess, "vmess://(.*?)@(.*)")) + { + explodeStdVMess(vmess, node); + return; + } else if(regMatch(vmess, "vmess1://(.*?)\\?(.*)")) //kitsunebi style link { explodeKitsunebi(vmess, node); diff --git a/src/server/webserver_libevent.cpp b/src/server/webserver_libevent.cpp index dc36cec..9d821ed 100644 --- a/src/server/webserver_libevent.cpp +++ b/src/server/webserver_libevent.cpp @@ -146,7 +146,10 @@ inline int WebServer::process_request(Request &request, Response &response, std: } catch(std::exception &e) { - return_data = "Internal server error while processing request path '" + request.url + "' with arguments '" + request.argument + "'!\n what(): "; + return_data = "Internal server error while processing request path '" + request.url + "' with arguments '" + request.argument + "'!"; + return_data += "\n exception: "; + return_data += type(e); + return_data += "\n what(): "; return_data += e.what(); response.content_type = "text/plain"; response.status_code = 500; @@ -234,6 +237,7 @@ void WebServer::on_request(evhttp_request *req, void *args) case EVHTTP_REQ_PUT: request.method = "PUT"; break; case EVHTTP_REQ_PATCH: request.method = "PATCH"; break; case EVHTTP_REQ_DELETE: request.method = "DELETE"; break; + case EVHTTP_REQ_HEAD: request.method = "HEAD"; break; default: break; } request.url = uri; @@ -315,7 +319,7 @@ int WebServer::start_web_server(void *argv) auto call_on_request = [&](evhttp_request *req, void *args) { on_request(req, args); }; - evhttp_set_allowed_methods(server.get(), EVHTTP_REQ_GET | EVHTTP_REQ_POST | EVHTTP_REQ_OPTIONS | EVHTTP_REQ_PUT | EVHTTP_REQ_PATCH | EVHTTP_REQ_DELETE); + evhttp_set_allowed_methods(server.get(), EVHTTP_REQ_GET | EVHTTP_REQ_POST | EVHTTP_REQ_OPTIONS | EVHTTP_REQ_PUT | EVHTTP_REQ_PATCH | EVHTTP_REQ_DELETE | EVHTTP_REQ_HEAD); evhttp_set_gencb(server.get(), wrap(call_on_request), nullptr); evhttp_set_timeout(server.get(), 30); if (event_dispatch() == -1) @@ -399,7 +403,7 @@ int WebServer::start_web_server_multi(void *argv) if (evhttp_accept_socket(httpd, nfd) != 0) return -1; - evhttp_set_allowed_methods(httpd, EVHTTP_REQ_GET | EVHTTP_REQ_POST | EVHTTP_REQ_OPTIONS | EVHTTP_REQ_PUT | EVHTTP_REQ_PATCH | EVHTTP_REQ_DELETE); + evhttp_set_allowed_methods(httpd, EVHTTP_REQ_GET | EVHTTP_REQ_POST | EVHTTP_REQ_OPTIONS | EVHTTP_REQ_PUT | EVHTTP_REQ_PATCH | EVHTTP_REQ_DELETE | EVHTTP_REQ_HEAD); evhttp_set_gencb(httpd, wrap(call_on_request), nullptr); evhttp_set_timeout(httpd, 30); if (pthread_create(&ths[i], nullptr, httpserver_dispatch, base[i]) != 0) diff --git a/src/utils/logger.cpp b/src/utils/logger.cpp index 9d52c27..a51ebe6 100644 --- a/src/utils/logger.cpp +++ b/src/utils/logger.cpp @@ -42,3 +42,28 @@ void writeLog(int type, const std::string &content, int level) std::cerr< +#include +#include + +std::string demangle(const char* name) +{ + int status = -4; + std::unique_ptr res { + abi::__cxa_demangle(name, NULL, NULL, &status), + std::free + }; + return (status == 0) ? res.get() : name; +} + +#else + +std::string demangle(const char* name) +{ + return name; +} + +#endif diff --git a/src/utils/logger.h b/src/utils/logger.h index 6b3040e..86919db 100644 --- a/src/utils/logger.h +++ b/src/utils/logger.h @@ -2,6 +2,7 @@ #define LOGGER_H_INCLUDED #include +#include enum { @@ -30,5 +31,12 @@ enum std::string getTime(int type); void writeLog(int type, const std::string &content, int level = LOG_LEVEL_VERBOSE); +std::string demangle(const char* name); + +template +std::string type(const T& t) { + + return demangle(typeid(t).name()); +} #endif // LOGGER_H_INCLUDED