From 592ce877887c48c4362b9017ffdf68d596559a07 Mon Sep 17 00:00:00 2001 From: Tindy X <49061470+tindy2013@users.noreply.github.com> Date: Wed, 29 Apr 2020 00:38:19 +0800 Subject: [PATCH] Bug fixes Fix program crash when processing broken template variables passed. Fix trying to load other arguments when no supported target is provided. Optimize codes. --- src/interfaces.cpp | 92 ++++++++++++++++++++++++++-------------------- src/misc.h | 83 +++++++++++++++++++++++++++++++++++++++++ src/templates.cpp | 9 ++++- 3 files changed, 143 insertions(+), 41 deletions(-) diff --git a/src/interfaces.cpp b/src/interfaces.cpp index 0322447..81b2f97 100644 --- a/src/interfaces.cpp +++ b/src/interfaces.cpp @@ -1100,25 +1100,40 @@ void generateBase() std::string subconverter(RESPONSE_CALLBACK_ARGS) { + std::string target = getUrlArg(argument, "target"); + switch(hash_(target)) + { + case "clash"_hash: case "clashr"_hash: case "surge"_hash: case "quan"_hash: case "quanx"_hash: case "loon"_hash: case "surfboard"_hash: case "mellow"_hash: case "ss"_hash: case "ssd"_hash: case "ssr"_hash: case "sssub"_hash: case "v2ray"_hash: case "trojan"_hash: + break; + default: + *status_code = 400; + return "Invalid target!"; + } //check if we need to read configuration if((!api_mode || cfw_child_process) && !generator_mode) readConf(); - std::string target = getUrlArg(argument, "target"), url = UrlDecode(getUrlArg(argument, "url")), emoji = getUrlArg(argument, "emoji"); - std::string group = UrlDecode(getUrlArg(argument, "group")), upload = getUrlArg(argument, "upload"), upload_path = getUrlArg(argument, "upload_path"), version = getUrlArg(argument, "ver"); - 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")), sort_flag = getUrlArg(argument, "sort"); - std::string scv = getUrlArg(argument, "scv"), fdn = getUrlArg(argument, "fdn"), expand = getUrlArg(argument, "expand"), append_sub_userinfo = getUrlArg(argument, "append_info"); + + /// string values + std::string url = UrlDecode(getUrlArg(argument, "url")); + std::string group = UrlDecode(getUrlArg(argument, "group")), upload_path = getUrlArg(argument, "upload_path"), version = getUrlArg(argument, "ver"); + std::string include = UrlDecode(getUrlArg(argument, "include")), exclude = UrlDecode(getUrlArg(argument, "exclude")); + std::string groups = urlsafe_base64_decode(getUrlArg(argument, "groups")), ruleset = urlsafe_base64_decode(getUrlArg(argument, "ruleset")), config = UrlDecode(getUrlArg(argument, "config")); std::string dev_id = getUrlArg(argument, "dev_id"), filename = getUrlArg(argument, "filename"), interval_str = getUrlArg(argument, "interval"), strict_str = getUrlArg(argument, "strict"); - std::string clash_new_field = getUrlArg(argument, "new_name"), clash_script = getUrlArg(argument, "script"), add_insert = getUrlArg(argument, "insert"); + + /// switches with default value + tribool upload = getUrlArg(argument, "upload"), emoji = getUrlArg(argument, "emoji"); + tribool append_type = getUrlArg(argument, "append_type"), tfo = getUrlArg(argument, "tfo"), udp = getUrlArg(argument, "udp"), nodelist = getUrlArg(argument, "list"); + tribool sort_flag = getUrlArg(argument, "sort"); + tribool clash_new_field = getUrlArg(argument, "new_name"), clash_script = getUrlArg(argument, "script"), add_insert = getUrlArg(argument, "insert"); + tribool scv = getUrlArg(argument, "scv"), fdn = getUrlArg(argument, "fdn"), expand = getUrlArg(argument, "expand"), append_sub_userinfo = getUrlArg(argument, "append_info"); + std::string base_content, output_content; string_array extra_group, extra_ruleset, include_remarks = def_include_remarks, exclude_remarks = def_exclude_remarks; - std::string groups = urlsafe_base64_decode(getUrlArg(argument, "groups")), ruleset = urlsafe_base64_decode(getUrlArg(argument, "ruleset")), config = UrlDecode(getUrlArg(argument, "config")); std::vector rca; extra_settings ext; std::string subInfo, dummy; int interval = interval_str.size() ? to_int(interval_str, config_update_interval) : config_update_interval; bool ruleset_updated = false, authorized = !api_mode || getUrlArg(argument, "token") == access_token, strict = strict_str.size() ? strict_str == "true" : config_update_strict; - bool insert_flag = add_insert.empty() || add_insert == "true"; if(std::find(regex_blacklist.cbegin(), regex_blacklist.cend(), include) != regex_blacklist.cend() || std::find(regex_blacklist.cbegin(), regex_blacklist.cend(), exclude) != regex_blacklist.cend()) return "Invalid request!"; @@ -1130,7 +1145,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) //validate urls if(!url.size() && (!api_mode || authorized)) url = default_url; - if(insert_url.size() && insert_flag) + if(insert_url.size() && add_insert) url = insert_url + "|" + url; if(!url.size() || !target.size()) { @@ -1164,9 +1179,9 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) ext.rename_array = safe_get_renames(); //check other flags - if(emoji.size()) + if(!emoji.is_undef()) { - ext.add_emoji = emoji == "true"; + ext.add_emoji = emoji; ext.remove_emoji = true; } else @@ -1174,25 +1189,22 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) ext.add_emoji = add_emoji; ext.remove_emoji = remove_old_emoji; } - if(append_type.size()) - ext.append_proxy_type = append_type == "true"; - else - ext.append_proxy_type = append_proxy_type; + ext.append_proxy_type = append_type.get(append_proxy_type); - ext.tfo = tfo.size() ? tfo == "true" : tfo_flag; - ext.udp = udp.size() ? udp == "true" : udp_flag; - ext.sort_flag = sort_flag.size() ? sort_flag == "true" : do_sort; - ext.skip_cert_verify = scv.size() ? scv == "true" : scv_flag; - ext.filter_deprecated = fdn.size() ? fdn == "true" : filter_deprecated; - ext.clash_new_field_name = clash_new_field.size() ? clash_new_field == "true" : clash_use_new_field_name; - ext.clash_script = clash_script == "true"; + ext.tfo = tfo.get(tfo_flag); + ext.udp = udp.get(udp_flag); + ext.sort_flag = sort_flag.get(do_sort); + ext.skip_cert_verify = scv.get(scv_flag); + ext.filter_deprecated = fdn.get(filter_deprecated); + ext.clash_new_field_name = clash_new_field.get(clash_use_new_field_name); + ext.clash_script = clash_script.get(); - ext.nodelist = nodelist == "true"; + ext.nodelist = nodelist; ext.surge_ssr_path = surge_ssr_path; ext.quanx_dev_id = dev_id.size() ? dev_id : quanx_script_id; ext.enable_rule_generator = enable_rule_generator; ext.overwrite_original_rules = overwrite_original_rules; - if(expand != "true") + if(expand) ext.managed_config_prefix = managed_config_prefix; //load external configuration @@ -1293,7 +1305,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) string_array urls = split(url, "|"); std::vector nodes; int groupID = 0; - groupID -= insert_url.empty() || !insert_flag ? 0 : std::count(insert_url.begin(), insert_url.end(), '|') + 1; + groupID -= insert_url.empty() || !add_insert ? 0 : std::count(insert_url.begin(), insert_url.end(), '|') + 1; //check custom include/exclude settings if(include.size() && regValid(include)) @@ -1327,7 +1339,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) for(nodeInfo &x : nodes) x.group = group; - if(subInfo.size() && (append_sub_userinfo.size() ? append_sub_userinfo == "true" : append_userinfo)) + if(subInfo.size() && append_sub_userinfo.get(append_userinfo)) extra_headers.emplace("Subscription-UserInfo", subInfo); //do pre-process now @@ -1371,7 +1383,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) output_content = YAML::Dump(yamlnode); } - if(upload == "true") + if(upload) uploadGist(target, upload_path, output_content, false); break; case "surge"_hash: @@ -1383,7 +1395,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) { output_content = netchToSurge(nodes, base_content, dummy_ruleset, dummy_group, surge_ver, ext); - if(upload == "true") + if(upload) uploadGist("surge" + version + "list", upload_path, output_content, true); } else @@ -1396,7 +1408,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) //base_content = fetchFile(ext_surge_base, proxy, cache_config); output_content = netchToSurge(nodes, base_content, rca, extra_group, surge_ver, ext); - if(upload == "true") + if(upload) uploadGist("surge" + version, upload_path, output_content, true); if(write_managed_config && managed_config_prefix.size()) @@ -1415,7 +1427,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) } //base_content = fetchFile(ext_surfboard_base, proxy, cache_config); output_content = netchToSurge(nodes, base_content, rca, extra_group, -3, ext); - if(upload == "true") + if(upload) uploadGist("surfboard", upload_path, output_content, true); if(write_managed_config && managed_config_prefix.size()) @@ -1446,14 +1458,14 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) } */ - if(upload == "true") + if(upload) uploadGist("mellow", upload_path, output_content, true); break; case "ss"_hash: //std::cerr<<"SS"< #include #include +#include +#include #include +#include "string_hash.h" + #ifdef _WIN32 #include #define PATH_SLASH "\\" @@ -30,6 +34,85 @@ static const std::string base64_chars = "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; +class tribool +{ +private: + + int _M_VALUE = -1; + +public: + + tribool() { _M_VALUE = -1; } + + tribool(const std::string &src) { set(src); } + + tribool(const bool &src) { set(src); } + + tribool(const int &src) { set(src); } + + ~tribool() = default; + + tribool& operator=(const tribool &src) + { + _M_VALUE = src._M_VALUE; + return *this; + } + + tribool& operator=(const std::string &src) + { + set(src); + return *this; + } + + operator bool() const { return _M_VALUE == 1; } + + tribool& operator=(const bool &src) + { + _M_VALUE = src; + return *this; + } + + bool is_undef() { return _M_VALUE == -1; } + + bool get(const bool &def_value = false) + { + if(_M_VALUE == -1) + return def_value; + return _M_VALUE; + } + + bool set(const bool &value) + { + _M_VALUE = value; + return _M_VALUE; + } + + bool set(const int &value) + { + _M_VALUE = value != 0; + return _M_VALUE; + } + + bool set(const std::string &str) + { + std::string temp = str; + std::transform(temp.begin(), temp.end(), temp.begin(), [](unsigned char c){ return std::tolower(c); }); + switch(hash_(temp)) + { + case "true"_hash: + _M_VALUE = 1; + break; + case "false"_hash: + _M_VALUE = 0; + break; + default: + _M_VALUE = -1; + break; + } + return _M_VALUE; + } +}; + std::string UrlEncode(const std::string& str); std::string UrlDecode(const std::string& str); std::string base64_decode(const std::string &encoded_string, bool accept_urlsafe = false); diff --git a/src/templates.cpp b/src/templates.cpp index 8762b44..373e14e 100644 --- a/src/templates.cpp +++ b/src/templates.cpp @@ -12,7 +12,14 @@ static inline void parse_json_pointer(nlohmann::json &json, const std::string &path, const std::string &value) { std::string pointer = "/" + replace_all_distinct(path, ".", "/"); - json[nlohmann::json::json_pointer(pointer)] = value; + try + { + json[nlohmann::json::json_pointer(pointer)] = value; + } + catch (std::exception&) + { + //ignore broken pointer + } } int render_template(const std::string &content, const template_args &vars, std::string &output, const std::string &include_scope)