From 53260ee22ff603e89d6437ab8f53c90dacccc7ed Mon Sep 17 00:00:00 2001 From: seven-mile Date: Sat, 2 Sep 2023 22:39:59 +0800 Subject: [PATCH] fix: query string parsing issue `AtlUnescapeString` cannot parse '+' as space in query string, use WinRT Uri class instead. --- DanmakuServer.rc | Bin 6004 -> 6004 bytes app.manifest | 2 +- main.cpp | 2 +- resource.h | 1 - server.cpp | 61 +++++------------------------------------------ 5 files changed, 8 insertions(+), 58 deletions(-) diff --git a/DanmakuServer.rc b/DanmakuServer.rc index aeebd8c221b00983fd8e4980ead396ea410d240c..7134845bc4cc1a337d1421ff9193fd9694b22d07 100644 GIT binary patch delta 58 zcmeyO_eF1m7$2)KgARkiWNAKK2y3%1-%loHV+Os+@A)MsUl0`ATp{?15hk#?PWT%$ E0Nxl8Jpcdz delta 62 zcmeyO_eF1m7$2( - + diff --git a/main.cpp b/main.cpp index 91622d4..ca7a34b 100644 --- a/main.cpp +++ b/main.cpp @@ -90,7 +90,7 @@ class ShellIconWnd td.dwFlags = TDF_ENABLE_HYPERLINKS; td.pszMainIcon = MAKEINTRESOURCE(m_CurrentIconResource); td.pszWindowTitle = L"About"; - td.pszMainInstruction = L"Danmaku Server 1.1"; + td.pszMainInstruction = L"Danmaku Server 1.5.3"; td.pszContent = LR"(Please check our GitHub Repo for more information. The danmaku server is hosted on :7654 port, access this url for sample danmaku effect.)"; diff --git a/resource.h b/resource.h index 87add6e..59c769e 100644 --- a/resource.h +++ b/resource.h @@ -3,7 +3,6 @@ // 供 DanmakuServer.rc 使用 // #define IDI_DANMAKU 101 -#define IDI_ICON1 103 #define IDI_SETTINGS 103 #define IDM_TRAY 40003 #define IDMI_EXIT 40004 diff --git a/server.cpp b/server.cpp index 4324d1a..503f721 100644 --- a/server.cpp +++ b/server.cpp @@ -57,55 +57,6 @@ void SendHttpJsonResponse(HANDLE req_queue, HTTP_REQUEST &req, USHORT status, )); } -std::wstring UrlDecodeWString(std::wstring const &inputw) { - std::string result; - DWORD cnt; - - std::string inputa; - inputa.resize(inputw.size() + 1); - winrt::check_bool(AtlUnicodeToUTF8(inputw.c_str(), inputw.size(), inputa.data(), inputw.size() + 1)); - - AtlUnescapeUrl(inputa.c_str(), result.data(), &cnt, DWORD(result.size())); - result.resize(cnt); - winrt::check_bool(AtlUnescapeUrl(inputa.c_str(), result.data(), &cnt, DWORD(result.size()))); - result.resize(strlen(result.data())); - - return LPWSTR(ATL::CA2W(result.c_str(), CP_UTF8)); -} - -std::map ParseQueryString(std::wstring_view query_string) { - std::map result; - - if (query_string.data() == nullptr) - return result; - - // eat '?' - query_string = query_string.substr(1); - - // Split the query_string by '&' to get individual key-value pairs - std::wstring key_value_pair; - std::wstringstream ss{std::wstring{query_string}}; - while (std::getline(ss, key_value_pair, L'&')) { - // Split each key-value pair by '=' - std::wstring key, value; - size_t equal_pos = key_value_pair.find(L'='); - if (equal_pos != std::wstring::npos) { - key = key_value_pair.substr(0, equal_pos); - value = key_value_pair.substr(equal_pos + 1); - } else { - key = key_value_pair; - value = L""; - } - - key = UrlDecodeWString(key); - value = UrlDecodeWString(value); - - result[key] = value; - } - - return result; -} - DanmakuServer::DanmakuServer(danmaku_handler_t handler) { cancel_event = ::CreateEvent(NULL, TRUE, FALSE, NULL); @@ -166,16 +117,16 @@ DanmakuServer::DanmakuServer(danmaku_handler_t handler) { bool handled = false; if (req.Verb == HttpVerbGET) { - std::wstring_view abs_path{req.CookedUrl.pAbsPath, req.CookedUrl.AbsPathLength / sizeof(wchar_t)}; - std::wstring_view query_string{req.CookedUrl.pQueryString, req.CookedUrl.QueryStringLength / sizeof(wchar_t)}; + winrt::Windows::Foundation::Uri url{req.CookedUrl.pFullUrl}; - if (abs_path.starts_with(L"/version")) { + if (url.Path().starts_with(L"/version")) { handled = true; SendHttpJsonResponse(req_queue, req, 200, "OK", R"({"version": 1, "repo": "https://github.com/seven-mile/DanmakuServer"})"); - } else if (abs_path.starts_with(L"/danmaku")) { + } else if (url.Path().starts_with(L"/danmaku")) { handled = true; - auto args = ParseQueryString(query_string); - auto &name = args[L"name"], &content = args[L"content"]; + auto args = url.QueryParsed(); + auto name = args.GetFirstValueByName(L"name"); + auto content = args.GetFirstValueByName(L"content"); handler(std::format(L"{}: {}", name, content)); SendHttpJsonResponse(req_queue, req, 200, "OK", R"({"code": 0, "message": "ok"})");