From 9699be211067136779a5a3300878ff00da05fab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 26 Sep 2024 01:09:56 +0200 Subject: [PATCH] RetroAchievements: Cleanup better on login failure --- Common/System/NativeApp.h | 7 +++++-- Core/RetroAchievements.cpp | 15 +++++++++++++-- UI/NativeApp.cpp | 10 ++++++---- Windows/GEDebugger/VertexPreview.cpp | 1 + headless/Headless.cpp | 4 ++-- libretro/libretro.cpp | 4 ++-- unittest/UnitTest.cpp | 5 +++-- 7 files changed, 32 insertions(+), 14 deletions(-) diff --git a/Common/System/NativeApp.h b/Common/System/NativeApp.h index 9b69b7f179..3f1a74a6a4 100644 --- a/Common/System/NativeApp.h +++ b/Common/System/NativeApp.h @@ -78,6 +78,9 @@ void NativeShutdown(); void PostLoadConfig(); // Returns false on failure. Shouldn't really happen, though. -bool NativeSaveSecret(const char *nameOfSecret, const std::string &data); +bool NativeSaveSecret(std::string_view nameOfSecret, std::string_view data); +inline bool NativeClearSecret(std::string_view nameOfSecret) { + return NativeSaveSecret(nameOfSecret, ""); +} // On failure, returns an empty string. Good enough since any real secret is non-empty. -std::string NativeLoadSecret(const char *nameOfSecret); +std::string NativeLoadSecret(std::string_view nameOfSecret); diff --git a/Core/RetroAchievements.cpp b/Core/RetroAchievements.cpp index 7ca969c7fc..7171691871 100644 --- a/Core/RetroAchievements.cpp +++ b/Core/RetroAchievements.cpp @@ -503,8 +503,19 @@ static void login_token_callback(int result, const char *error_message, rc_clien auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); g_OSD.Show(OSDType::MESSAGE_WARNING, ac->T("Failed logging in to RetroAchievements"), "", g_RAImageID); } + + // Clear the token. + if (result == RC_INVALID_CREDENTIALS || result == RC_EXPIRED_TOKEN) { + g_Config.sAchievementsUserName.clear(); + NativeClearSecret(RA_TOKEN_SECRET_NAME); + g_loginResult = RC_OK; + } else { + g_loginResult = result; + } + OnAchievementsLoginStateChange(); - break; + g_isLoggingIn = false; + return; } } g_loginResult = result; @@ -718,7 +729,7 @@ void Logout() { rc_client_logout(g_rcClient); // remove from config g_Config.sAchievementsUserName.clear(); - NativeSaveSecret(RA_TOKEN_SECRET_NAME, ""); + NativeClearSecret(RA_TOKEN_SECRET_NAME); g_Config.Save("Achievements logout"); g_activeChallenges.clear(); g_loginResult = RC_OK; // Allow trying again diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 377ca7ddb4..96a53ea7ac 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1536,14 +1536,16 @@ void NativeShutdown() { // In the future, we might make this more sophisticated, such as storing in the app private directory on Android. // Right now we just store secrets in separate files next to ppsspp.ini. The important thing is keeping them out of it // since we often ask people to post or send the ini for debugging. -static Path GetSecretPath(const char *nameOfSecret) { +static Path GetSecretPath(std::string_view nameOfSecret) { return GetSysDirectory(DIRECTORY_SYSTEM) / ("ppsspp_" + std::string(nameOfSecret) + ".dat"); } // name should be simple alphanumerics to avoid problems on Windows. -bool NativeSaveSecret(const char *nameOfSecret, const std::string &data) { +bool NativeSaveSecret(std::string_view nameOfSecret, std::string_view data) { Path path = GetSecretPath(nameOfSecret); - if (!File::WriteDataToFile(false, data.data(), data.size(), path)) { + if (data.empty() && File::Exists(path)) { + return File::Delete(path); + } else if (!File::WriteDataToFile(false, data.data(), data.size(), path)) { WARN_LOG(Log::System, "Failed to write secret '%s' to path '%s'", nameOfSecret, path.c_str()); return false; } @@ -1551,7 +1553,7 @@ bool NativeSaveSecret(const char *nameOfSecret, const std::string &data) { } // On failure, returns an empty string. Good enough since any real secret is non-empty. -std::string NativeLoadSecret(const char *nameOfSecret) { +std::string NativeLoadSecret(std::string_view nameOfSecret) { Path path = GetSecretPath(nameOfSecret); std::string data; if (!File::ReadBinaryFileToString(path, &data)) { diff --git a/Windows/GEDebugger/VertexPreview.cpp b/Windows/GEDebugger/VertexPreview.cpp index f508037f49..bc2a69b4ee 100644 --- a/Windows/GEDebugger/VertexPreview.cpp +++ b/Windows/GEDebugger/VertexPreview.cpp @@ -348,6 +348,7 @@ void CGEDebugger::UpdatePrimPreview(u32 op, int which) { u16 minIndex = 0; u16 maxIndex = count - 1; if (!indices.empty()) { + _dbg_assert_(count <= indices.size()); minIndex = 0xFFFF; maxIndex = 0; for (int i = 0; i < count; ++i) { diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 59be04616f..20a3359790 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -142,8 +142,8 @@ void System_AudioClear() {} void System_AudioPushSamples(const s32 *audio, int numSamples) {} // TODO: To avoid having to define these here, these should probably be turned into system "requests". -bool NativeSaveSecret(const char *nameOfSecret, const std::string &data) { return false; } -std::string NativeLoadSecret(const char *nameOfSecret) { +bool NativeSaveSecret(std::string_view nameOfSecret, std::string_view data) { return false; } +std::string NativeLoadSecret(std::string_view nameOfSecret) { return ""; } diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 11007d5c5d..c24f1e43d0 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -1962,7 +1962,7 @@ bool System_AudioRecordingState() { return false; } #endif // TODO: To avoid having to define these here, these should probably be turned into system "requests". -bool NativeSaveSecret(const char *nameOfSecret, const std::string &data) { return false; } -std::string NativeLoadSecret(const char *nameOfSecret) { +bool NativeSaveSecret(std::string_view nameOfSecret, std::string_view data) { return false; } +std::string NativeLoadSecret(std::string_view nameOfSecret) { return ""; } diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index b68e5e43ae..2502bb235d 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -108,8 +108,9 @@ void System_AudioClear() {} void System_AudioPushSamples(const s32 *audio, int numSamples) {} // TODO: To avoid having to define these here, these should probably be turned into system "requests". -bool NativeSaveSecret(const char *nameOfSecret, const std::string &data) { return false; } -std::string NativeLoadSecret(const char *nameOfSecret) { +// To clear the secret entirely, just save an empty string. +bool NativeSaveSecret(std::string_view nameOfSecret, std::string_view data) { return false; } +std::string NativeLoadSecret(std::string_view nameOfSecret) { return ""; }