From 845e195ba5f70d7daed3854d765a5ab5a87c4a48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20B=C3=A1lint=20Misius?= Date: Fri, 23 Jun 2023 21:58:49 +0200 Subject: [PATCH] Emscripten: Sync session with the website one Also fix a cursed length-related problem with passing strings from JS to C++. --- src/client/AuthUserCommon.cpp | 30 +++++++++++++ src/client/AuthUserEmscripten.cpp | 42 +++++++++++++++++++ src/client/Client.cpp | 23 +--------- src/client/Client.h | 3 ++ src/client/http/GetCommentsRequest.cpp | 2 +- src/client/http/Request.cpp | 2 +- src/client/http/requestmanager/Emscripten.cpp | 19 +++------ src/client/meson.build | 5 +++ 8 files changed, 90 insertions(+), 36 deletions(-) create mode 100644 src/client/AuthUserCommon.cpp create mode 100644 src/client/AuthUserEmscripten.cpp diff --git a/src/client/AuthUserCommon.cpp b/src/client/AuthUserCommon.cpp new file mode 100644 index 000000000..389927004 --- /dev/null +++ b/src/client/AuthUserCommon.cpp @@ -0,0 +1,30 @@ +#include "Client.h" +#include "prefs/GlobalPrefs.h" + +void Client::LoadAuthUser() +{ + auto &prefs = GlobalPrefs::Ref(); + authUser.UserID = prefs.Get("User.ID", 0); + authUser.Username = prefs.Get("User.Username", ByteString("")); + authUser.SessionID = prefs.Get("User.SessionID", ByteString("")); + authUser.SessionKey = prefs.Get("User.SessionKey", ByteString("")); + authUser.UserElevation = prefs.Get("User.Elevation", User::ElevationNone); +} + +void Client::SaveAuthUser() +{ + auto &prefs = GlobalPrefs::Ref(); + Prefs::DeferWrite dw(prefs); + if (authUser.UserID) + { + prefs.Set("User.ID", authUser.UserID); + prefs.Set("User.SessionID", authUser.SessionID); + prefs.Set("User.SessionKey", authUser.SessionKey); + prefs.Set("User.Username", authUser.Username); + prefs.Set("User.Elevation", authUser.UserElevation); + } + else + { + prefs.Clear("User"); + } +} diff --git a/src/client/AuthUserEmscripten.cpp b/src/client/AuthUserEmscripten.cpp new file mode 100644 index 000000000..2fcff3277 --- /dev/null +++ b/src/client/AuthUserEmscripten.cpp @@ -0,0 +1,42 @@ +#include "Client.h" +#include "prefs/GlobalPrefs.h" +#include + +void Client::LoadAuthUser() +{ + std::optional newUsername; + if (EM_ASM_INT({ + return document.querySelector("#PowderSessionInfo [name='Username']") ? 1 : 0; + })) + { + newUsername = ByteString(std::unique_ptr((char *)EM_ASM_PTR({ + return stringToNewUTF8(document.querySelector("#PowderSessionInfo [name='Username']").value); + }), free).get()); + } + std::optional newSessionKey; + if (EM_ASM_INT({ + return document.querySelector("#PowderSessionInfo [name='SessionKey']") ? 1 : 0; + })) + { + newSessionKey = ByteString(std::unique_ptr((char *)EM_ASM_PTR({ + return stringToNewUTF8(document.querySelector("#PowderSessionInfo [name='SessionKey']").value); + }), free).get()); + } + if (newUsername && newSessionKey) + { + authUser.UserID = -1; // Not quite valid but evaluates to true and that's all that matters for this codebase. + authUser.Username = *newUsername; + authUser.SessionID = "(invalid)"; + authUser.SessionKey = *newSessionKey; + authUser.UserElevation = User::ElevationNone; // We don't deal with this in the browser. + } + else + { + authUser.UserID = 0; + } +} + +void Client::SaveAuthUser() +{ + // Nothing is; the cookie headers in the login and logout responses take care of state management. +} diff --git a/src/client/Client.cpp b/src/client/Client.cpp index 29ae55f80..8e2b1e54c 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -32,12 +32,8 @@ Client::Client(): updateAvailable(false), authUser(0, "") { + LoadAuthUser(); auto &prefs = GlobalPrefs::Ref(); - authUser.UserID = prefs.Get("User.ID", 0); - authUser.Username = prefs.Get("User.Username", ByteString("")); - authUser.SessionID = prefs.Get("User.SessionID", ByteString("")); - authUser.SessionKey = prefs.Get("User.SessionKey", ByteString("")); - authUser.UserElevation = prefs.Get("User.Elevation", User::ElevationNone); firstRun = !prefs.BackedByFile(); } @@ -239,22 +235,7 @@ Client::~Client() void Client::SetAuthUser(User user) { authUser = user; - { - auto &prefs = GlobalPrefs::Ref(); - Prefs::DeferWrite dw(prefs); - if (authUser.UserID) - { - prefs.Set("User.ID", authUser.UserID); - prefs.Set("User.SessionID", authUser.SessionID); - prefs.Set("User.SessionKey", authUser.SessionKey); - prefs.Set("User.Username", authUser.Username); - prefs.Set("User.Elevation", authUser.UserElevation); - } - else - { - prefs.Clear("User"); - } - } + SaveAuthUser(); notifyAuthUserChanged(); } diff --git a/src/client/Client.h b/src/client/Client.h index 9bfdb7d25..b81a5b14f 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -53,6 +53,9 @@ private: void MigrateStampsDef(); void WriteStamps(); + void LoadAuthUser(); + void SaveAuthUser(); + public: std::vector listeners; diff --git a/src/client/http/GetCommentsRequest.cpp b/src/client/http/GetCommentsRequest.cpp index 4207555ef..c29858241 100644 --- a/src/client/http/GetCommentsRequest.cpp +++ b/src/client/http/GetCommentsRequest.cpp @@ -21,7 +21,7 @@ namespace http comments.push_back({ comment["Username"].asString(), User::ElevationFromString(comment["Elevation"].asString()), - ByteString(comment["UserID"].asString()).ToNumber() == user.UserID, + comment["Username"].asString() == user.Username, comment["IsBanned"].asBool(), ByteString(comment["Text"].asString()).FromUtf8(), }); diff --git a/src/client/http/Request.cpp b/src/client/http/Request.cpp index deb21b877..874e86d29 100644 --- a/src/client/http/Request.cpp +++ b/src/client/http/Request.cpp @@ -60,7 +60,7 @@ namespace http void Request::AuthHeaders(ByteString ID, ByteString session) { assert(handle->state == RequestHandle::ready); - if (ID.size()) + if (ID.size() && ID != "-1") // -1 is an emscripten hack, see AuthUserEmscripten.cpp { if (session.size()) { diff --git a/src/client/http/requestmanager/Emscripten.cpp b/src/client/http/requestmanager/Emscripten.cpp index acfeec8a8..0ff7017ea 100644 --- a/src/client/http/requestmanager/Emscripten.cpp +++ b/src/client/http/requestmanager/Emscripten.cpp @@ -252,7 +252,6 @@ namespace http method: request.fetchMethod, headers: request.fetchHeaders, body: request.fetchBody, - credentials: 'omit', signal: request.fetchController.signal, }).then(response => { request.statusEarly = response.status; @@ -344,18 +343,12 @@ namespace http handle->responseHeaders.resize(headerCount); for (auto i = 0; i < headerCount; ++i) { - handle->responseHeaders[i].name.resize(EM_ASM_INT({ - return lengthBytesUTF8(Module.emscriptenRequestManager.requests[$0].responseHeaders[$1].name); - }, handle->id, i)); - EM_ASM({ - stringToUTF8(Module.emscriptenRequestManager.requests[$0].responseHeaders[$1].name, $2, $3); - }, handle->id, i, &handle->responseHeaders[i].name[0], handle->responseHeaders[i].name.size()); - handle->responseHeaders[i].value.resize(EM_ASM_INT({ - return lengthBytesUTF8(Module.emscriptenRequestManager.requests[$0].responseHeaders[$1].value); - }, handle->id, i)); - EM_ASM({ - stringToUTF8(Module.emscriptenRequestManager.requests[$0].responseHeaders[$1].value, $2, $3); - }, handle->id, i, &handle->responseHeaders[i].value[0], handle->responseHeaders[i].value.size()); + handle->responseHeaders[i].name = ByteString(std::unique_ptr((char *)EM_ASM_PTR({ + return stringToNewUTF8(Module.emscriptenRequestManager.requests[$0].responseHeaders[$1].name); + }, handle->id, i), free).get()); + handle->responseHeaders[i].value = ByteString(std::unique_ptr((char *)EM_ASM_PTR({ + return stringToNewUTF8(Module.emscriptenRequestManager.requests[$0].responseHeaders[$1].value); + }, handle->id, i), free).get()); } handle->gotResponse = true; HandleWake(); diff --git a/src/client/meson.build b/src/client/meson.build index 55503feee..4335cc4ee 100644 --- a/src/client/meson.build +++ b/src/client/meson.build @@ -7,6 +7,11 @@ client_files = files( 'GameSave.cpp', 'User.cpp', ) +if host_platform == 'emscripten' + client_files += files('AuthUserEmscripten.cpp') +else + client_files += files('AuthUserCommon.cpp') +endif subdir('http')