From 302f08dd57f0b9641ad592697362b7888b21fe8b Mon Sep 17 00:00:00 2001 From: bicarus-dev <202771338+bicarus-dev@users.noreply.github.com> Date: Wed, 2 Apr 2025 18:32:15 -0700 Subject: [PATCH] patcher: show errors on invalid json response from remote (#281) ## Link to GitHub Issue, if one exists #0 ## Description of change When patcher URL returns an invalid response (as in, cannot be parsed as JSON), show an error message to user. Add a "copy text" button to copy the error message. Fix WarnTooltip so that can handle the case where description is an empty string for a patch - previously this was just showing as multiple lines of empty space and then the warning. ## Compiling It's fine except Docker build currently fails due to cmake version issue. ## Testing Tested valid / invalid datecodes and checked against responses. --- src/spice2x/overlay/imgui/extensions.cpp | 4 +- src/spice2x/overlay/windows/patch_manager.cpp | 42 +++++++++++++++++-- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/spice2x/overlay/imgui/extensions.cpp b/src/spice2x/overlay/imgui/extensions.cpp index 00d5119..56382fc 100644 --- a/src/spice2x/overlay/imgui/extensions.cpp +++ b/src/spice2x/overlay/imgui/extensions.cpp @@ -39,12 +39,12 @@ namespace ImGui { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); - if (desc) { + if (desc && desc[0]) { ImGui::TextUnformatted(desc); ImGui::TextUnformatted(""); } ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.f, 1.f, 0.f, 1.f)); - if (warn) { + if (warn && warn[0]) { ImGui::TextUnformatted("WARNING:"); ImGui::TextUnformatted(warn); } diff --git a/src/spice2x/overlay/windows/patch_manager.cpp b/src/spice2x/overlay/windows/patch_manager.cpp index 5324afa..54fdaec 100644 --- a/src/spice2x/overlay/windows/patch_manager.cpp +++ b/src/spice2x/overlay/windows/patch_manager.cpp @@ -151,7 +151,7 @@ namespace overlay::windows { url_fetch_errors += fmt::format("WinHttpSendRequest failed: {}\n", gle); if (gle == 12175) { url_fetch_errors += "\nThis is ERROR_WINHTTP_SECURE_FAILURE - most likely TLS 1.1 / TLS 1.2 error on old OS versions.\n\n"; - url_fetch_errors += "Look up MSDN article on 'Update to enable TLS 1.1 and TLS 1.2 as default secure protocols in WinHTTP in Windows' for a fix."; + url_fetch_errors += "Look up MSDN article on 'Update to enable TLS 1.1 and TLS 1.2 as default secure protocols in WinHTTP in Windows' for a fix.\n"; } return result; } @@ -183,7 +183,7 @@ namespace overlay::windows { statusCode, netutils::http_status_reason_phrase(statusCode)); if (statusCode == 404) { - url_fetch_errors += "(Patch server did not find any patches for this game version)"; + url_fetch_errors += "(Patch server did not find any patches for this game version)\n"; } return result; } @@ -550,7 +550,7 @@ namespace overlay::windows { ImGui::Text("Failed to import patches from URL."); if (!url_fetch_errors.empty()) { ImGui::TextUnformatted(""); - ImGui::PushTextWrapPos(ImGui::GetIO().DisplaySize.x * 0.5); + ImGui::PushTextWrapPos(ImGui::GetIO().DisplaySize.x * 0.7); ImGui::TextUnformatted(url_fetch_errors.c_str()); ImGui::PopTextWrapPos(); } @@ -558,6 +558,12 @@ namespace overlay::windows { if (ImGui::Button("OK")) { ImGui::CloseCurrentPopup(); } + if (!url_fetch_errors.empty()) { + ImGui::SameLine(); + if (ImGui::Button("Copy Error")) { + clipboard::copy_text(url_fetch_errors); + } + } ImGui::EndPopup(); } @@ -1517,16 +1523,44 @@ namespace overlay::windows { try { auto patches_json = getFromUrl(dll_name, json_path); if (!patches_json.empty()) { - if (!fileutils::dir_exists(LOCAL_PATCHES_PATH)) + + // see if this is valid JSON + Document doc_temp; + doc_temp.Parse(patches_json.c_str()); + const auto error = doc_temp.GetParseError(); + if (error) { + log_warning( + "patchmanager", + "remotely fetched JSON file parse error: {}", + rapidjson::GetParseError_En(error)); + url_fetch_errors += fmt::format( + "Invalid JSON received from remote URL.\n" + "Your DLL version might not be supported.\n" + "URL: {}\n" + "JSON Parse Error: {}\n", + json_path, + rapidjson::GetParseError_En(error)); + return false; + } else { + log_info("patchmanager", "remotely fetched JSON was successfully parsed"); + } + + // create patches dir + if (!fileutils::dir_exists(LOCAL_PATCHES_PATH)) { fileutils::dir_create(LOCAL_PATCHES_PATH); + } + // save to file std::filesystem::path save_path = LOCAL_PATCHES_PATH / (identifier + ".json"); fileutils::text_write(save_path, patches_json); + log_info("patchmanager", "remotely fetched JSON saved to: {}", save_path.string()); return true; } else { log_warning("patchmanager", "failed to fetch patches JSON for {}", dll_name); } } catch (const std::exception& e) { log_warning("patchmanager", "exception occurred while loading remote patches JSON for {}: {}", dll_name, e.what()); + url_fetch_errors += fmt::format( + "Exception while loading remote patches for {}: {}\n", dll_name, e.what()); } return false; }