diff --git a/src/config.cpp b/src/config.cpp index 31b6d800..fb1c0c37 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -1087,7 +1087,11 @@ namespace config { } for (auto &[name, val] : vars) { - BOOST_LOG(info) << "config: '"sv << name << "' = "sv << val; + #ifdef _WIN32 + BOOST_LOG(info) << "config: ["sv << name << "] -- ["sv << utf8ToAcp(val) << ']'; + #else + BOOST_LOG(info) << "config: ["sv << name << "] -- ["sv << val << ']'; + #endif } bool_f(vars, "headless_mode", video.headless_mode); diff --git a/src/confighttp.cpp b/src/confighttp.cpp index d42e4c29..ffbbd5cf 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -40,6 +40,10 @@ #include "uuid.h" #include "version.h" +#ifdef _WIN32 + #include "platform/windows/utils.h" +#endif + using namespace std::literals; namespace confighttp { @@ -943,7 +947,12 @@ namespace confighttp { print_req(request); std::string content = file_handler::read_file(config::sunshine.log_file.c_str()); SimpleWeb::CaseInsensitiveMultimap headers; - headers.emplace("Content-Type", "text/plain"); + std::string contentType = "text/plain"; + #ifdef _WIN32 + contentType += "; charset="; + contentType += currentCodePageToCharset(); + #endif + headers.emplace("Content-Type", contentType); response->write(SimpleWeb::StatusCode::success_ok, content, headers); } diff --git a/src/platform/windows/utils.cpp b/src/platform/windows/utils.cpp index 66c043d4..22f91e7a 100644 --- a/src/platform/windows/utils.cpp +++ b/src/platform/windows/utils.cpp @@ -1,5 +1,7 @@ #include "utils.h" +#include + #include #include "src/utility.h" @@ -67,6 +69,46 @@ std::string acpToUtf8(const std::string& origStr) { return utf8Str; } +std::string currentCodePageToCharset() { + // Map of Windows code pages to their corresponding charset strings + static const std::unordered_map codePageCharsetMap = { + {65001, "UTF-8"}, + {1200, "UTF-16LE"}, + {1201, "UTF-16BE"}, + {1250, "windows-1250"}, + {1251, "windows-1251"}, + {1252, "windows-1252"}, + {1253, "windows-1253"}, + {1254, "windows-1254"}, + {1255, "windows-1255"}, + {1256, "windows-1256"}, + {1257, "windows-1257"}, + {1258, "windows-1258"}, + {936, "GBK"}, // Simplified Chinese + {949, "EUC-KR"}, // Korean + {950, "Big5"}, // Traditional Chinese + {932, "Shift_JIS"} // Japanese + }; + + static std::string charsetStr; + + if (charsetStr.empty()) { + // Get the active Windows code page + int codePage = GetACP(); + // Find the charset in the map + auto it = codePageCharsetMap.find(codePage); + if (it != codePageCharsetMap.end()) { + charsetStr = it->second; + } else { + // Fallback charset if code page is not found in the map + charsetStr = "ISO-8859-1"; + } + } + + return charsetStr; +} + + // Modified from https://github.com/FrogTheFrog/Sunshine/blob/b6f8573d35eff7c55da6965dfa317dc9722bd4ef/src/platform/windows/display_device/windows_utils.cpp std::string diff --git a/src/platform/windows/utils.h b/src/platform/windows/utils.h index de181aff..59ea2ab0 100644 --- a/src/platform/windows/utils.h +++ b/src/platform/windows/utils.h @@ -10,6 +10,7 @@ std::wstring acpToUtf16(const std::string& origStr); std::string utf16ToAcp(const std::wstring& utf16Str); std::string utf8ToAcp(const std::string& utf8Str); std::string acpToUtf8(const std::string& currentStr); +std::string currentCodePageToCharset(); std::string get_error_string(LONG error_code); diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index 5e2e91ff..9c3cb688 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -183,10 +183,23 @@ methods: { refreshLogs() { fetch("./api/logs", { credentials: 'include' }) - .then((r) => r.text()) - .then((r) => { - this.logs = r; - }); + .then(response => { + // Retrieve the Content-Type header + const contentType = response.headers.get("Content-Type") || ""; + // Attempt to extract charset from the header + const charsetMatch = contentType.match(/charset=([^;]+)/i); + const charset = charsetMatch ? charsetMatch[1].trim() : "utf-8"; + + // Read response as an ArrayBuffer and decode it with the correct charset + return response.arrayBuffer().then(buffer => { + const decoder = new TextDecoder(charset); + return decoder.decode(buffer); + }); + }) + .then(text => { + this.logs = text; + }) + .catch(error => console.error("Error fetching logs:", error)); }, closeApp() { this.closeAppPressed = true;