diff --git a/src/Utils/Tokeer/TokeerBridge.cpp b/src/Utils/Tokeer/TokeerBridge.cpp index e9e73d19..b4b0883e 100644 --- a/src/Utils/Tokeer/TokeerBridge.cpp +++ b/src/Utils/Tokeer/TokeerBridge.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -48,6 +49,36 @@ namespace { return out; } + // Minimal JSON string escaping for a value that is embedded into a request + // body. JSON requires that ", \\ and control characters are escaped; without + // this a bare quote in the value would terminate the string early and change + // the structure of the request. + std::string JsonEscape(std::string_view s) { + std::string out; + out.reserve(s.size() + 8); + for (const char c : s) { + switch (c) { + case '"': out += "\\\""; break; + case '\\': out += "\\\\"; break; + case '\b': out += "\\b"; break; + case '\f': out += "\\f"; break; + case '\n': out += "\\n"; break; + case '\r': out += "\\r"; break; + case '\t': out += "\\t"; break; + default: + if (static_cast(c) < 0x20) { + char buf[7]; + std::snprintf(buf, sizeof(buf), "\\u%04x", + static_cast(c)); + out += buf; + } else { + out += c; + } + } + } + return out; + } + // Minimal "key":"value" string extraction from the server's flat JSON reply. bool JsonString(std::string_view body, std::string_view key, std::string& out) { const std::string needle = "\"" + std::string(key) + "\""; @@ -90,7 +121,7 @@ void Redeem(const std::string& code) { namespace CS = OSTPlatform::SteamCredentialStore; const std::string url = TokeerBaseUrl() + "/drm/redeem"; - const std::string reqBody = "{\"code\":\"" + code + "\"}"; + const std::string reqBody = "{\"code\":\"" + JsonEscape(code) + "\"}"; OSTPlatform::Http::Result r = OSTPlatform::Http::Execute( L"POST", url.c_str(), reqBody.data(), static_cast(reqBody.size()),