From ef665f12a41e9dfd06b27b98238306d896d6d7b7 Mon Sep 17 00:00:00 2001 From: R2DLiu Date: Sat, 25 Jul 2020 17:50:48 -0400 Subject: [PATCH] up to 4307319 --- Source/Core/Core/Slippi/SlippiUser.cpp | 148 ++++++++++++++++++------- Source/Core/Core/Slippi/SlippiUser.h | 11 +- 2 files changed, 117 insertions(+), 42 deletions(-) diff --git a/Source/Core/Core/Slippi/SlippiUser.cpp b/Source/Core/Core/Slippi/SlippiUser.cpp index bed9f05533..1e9452254a 100644 --- a/Source/Core/Core/Slippi/SlippiUser.cpp +++ b/Source/Core/Core/Slippi/SlippiUser.cpp @@ -12,6 +12,7 @@ #include "Common/StringUtil.h" #include "Common/Thread.h" +#include "Common/Common.h" #include "Core/ConfigManager.h" #include @@ -53,12 +54,51 @@ static void RunSystemCommand(const std::string& command) #endif } +static size_t receive(char* ptr, size_t size, size_t nmemb, void* rcvBuf) +{ + size_t len = size * nmemb; + INFO_LOG(SLIPPI_ONLINE, "[User] Received data: %d", len); + + std::string* buf = (std::string*)rcvBuf; + + buf->insert(buf->end(), ptr, ptr + len); + + return len; +} + +SlippiUser::SlippiUser() +{ + CURL* curl = curl_easy_init(); + if (curl) + { + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &receive); + curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 5000); + + // Set up HTTP Headers + m_curlHeaderList = curl_slist_append(m_curlHeaderList, "Content-Type: application/json"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, m_curlHeaderList); + +#ifdef _WIN32 + // ALPN support is enabled by default but requires Windows >= 8.1. + curl_easy_setopt(curl, CURLOPT_SSL_ENABLE_ALPN, false); +#endif + + m_curl = curl; + } +} + SlippiUser::~SlippiUser() { // Wait for thread to terminate runThread = false; if (fileListenThread.joinable()) fileListenThread.join(); + + if (m_curl) + { + curl_slist_free_all(m_curlHeaderList); + curl_easy_cleanup(m_curl); + } } bool SlippiUser::AttemptLogin() @@ -68,21 +108,20 @@ bool SlippiUser::AttemptLogin() INFO_LOG(SLIPPI_ONLINE, "Looking for file at: %s", userFilePath.c_str()); { - // Put the filename here in its own scope because we don't really need it elsewhere - std::string userFilePathTxt = userFilePath + ".txt"; + std::string userFilePathTxt = + userFilePath + ".txt"; // Put the filename here in its own scope because we don't really need it elsewhere if (File::Exists(userFilePathTxt)) { // If both files exist we just log they exist and take no further action if (File::Exists(userFilePath)) { - INFO_LOG(SLIPPI_ONLINE, "Found both .json.txt and .json file for user data. Using .json " - "and ignoring the .json.txt"); + INFO_LOG(SLIPPI_ONLINE, + "Found both .json.txt and .json file for user data. Using .json and ignoring the .json.txt"); } // If only the .txt file exists move the contents to a json file and log if it fails else if (!File::Rename(userFilePathTxt, userFilePath)) { - WARN_LOG(SLIPPI_ONLINE, "Could not move file %s to %s", userFilePathTxt.c_str(), - userFilePath.c_str()); + WARN_LOG(SLIPPI_ONLINE, "Could not move file %s to %s", userFilePathTxt.c_str(), userFilePath.c_str()); } } } @@ -96,6 +135,7 @@ bool SlippiUser::AttemptLogin() isLoggedIn = !userInfo.uid.empty(); if (isLoggedIn) { + overwriteFromServer(); WARN_LOG(SLIPPI_ONLINE, "Found user %s (%s)", userInfo.displayName.c_str(), userInfo.uid.c_str()); } @@ -104,22 +144,25 @@ bool SlippiUser::AttemptLogin() void SlippiUser::OpenLogInPage() { -#ifdef _WIN32 - std::string folderSep = "%5C"; -#else - std::string folderSep = "%2F"; -#endif - std::string url = "https://slippi.gg/online/enable"; std::string path = getUserFilePath(); -#if defined(__APPLE__) -#else - path = ReplaceAll(path, "\\", folderSep); - path = ReplaceAll(path, "/", folderSep); +#ifdef _WIN32 + // On windows, sometimes the path can have backslashes and slashes mixed, convert all to backslashes + path = ReplaceAll(path, "\\", "\\"); + path = ReplaceAll(path, "/", "\\"); #endif + +#ifndef __APPLE__ + char* escapedPath = curl_easy_escape(nullptr, path.c_str(), (int)path.length()); + path = std::string(escapedPath); + curl_free(escapedPath); +#endif + std::string fullUrl = url + "?path=" + path; + INFO_LOG(SLIPPI_ONLINE, "[User] Login at path: %s", fullUrl.c_str()); + #ifdef _WIN32 std::string command = "explorer \"" + fullUrl + "\""; #elif defined(__APPLE__) @@ -131,41 +174,32 @@ void SlippiUser::OpenLogInPage() RunSystemCommand(command); } -void SlippiUser::UpdateFile() -{ -#ifdef _WIN32 - std::string path = File::GetExeDirectory() + "/dolphin-slippi-tools.exe"; - std::string command = path + " user-update"; - system_hidden(command.c_str()); -#elif defined(__APPLE__) -#else - std::string path = "dolphin-slippi-tools"; - std::string command = path + " user-update"; - system(command.c_str()); -#endif -} - void SlippiUser::UpdateApp() { #ifdef _WIN32 - auto isoPath = SConfig::GetInstance().m_strIsoPath; + auto isoPath = SConfig::GetInstance().m_strFilename; std::string path = File::GetExeDirectory() + "/dolphin-slippi-tools.exe"; std::string echoMsg = "echo Starting update process. If nothing happen after a few " "minutes, you may need to update manually from https://slippi.gg/netplay ..."; - std::string command = "start /b cmd /c " + echoMsg + " && \"" + path + "\" app-update -launch -iso \"" + isoPath + "\""; - WARN_LOG(SLIPPI, "Executing app update command: %s", command.c_str()); + // std::string command = + // "start /b cmd /c " + echoMsg + " && \"" + path + "\" app-update -launch -iso \"" + isoPath + "\""; + std::string command = "start /b cmd /c " + echoMsg + " && \"" + path + "\" app-update -launch -iso \"" + isoPath + + "\" -version \"" + scm_slippi_semver_str + "\""; + WARN_LOG(SLIPPI, "Executing app update command: %s", command); RunSystemCommand(command); #elif defined(__APPLE__) #else const char* appimage_path = getenv("APPIMAGE"); + const char* appmount_path = getenv("APPDIR"); if (!appimage_path) { CriticalAlertT("Automatic updates are not available for non-AppImage Linux builds."); return; } std::string path(appimage_path); - std::string command = "appimageupdatetool " + path; + std::string mount_path(appmount_path); + std::string command = mount_path + "/usr/bin/appimageupdatetool " + path; WARN_LOG(SLIPPI, "Executing app update command: %s", command.c_str()); RunSystemCommand(command); #endif @@ -222,20 +256,18 @@ void SlippiUser::FileListenThread() } } -// On Linux platforms, the user.json file lives in the Sys/ directory in -// order to deal with the fact that we want the configuration for AppImage +// On Linux platforms, the user.json file lives in the XDG_CONFIG_HOME/SlippiOnline +// directory in order to deal with the fact that we want the configuration for AppImage // builds to be mutable. std::string SlippiUser::getUserFilePath() { #if defined(__APPLE__) - std::string dirPath = File::GetBundleDirectory() + "/Contents/Resources"; + std::string userFilePath = File::GetBundleDirectory() + "/Contents/Resources" + DIR_SEP + "user.json"; #elif defined(_WIN32) - std::string dirPath = File::GetExeDirectory(); + std::string userFilePath = File::GetExeDirectory() + DIR_SEP + "user.json"; #else - std::string dirPath = File::GetSysDirectory(); - dirPath.pop_back(); + std::string userFilePath = File::GetUserPath(F_USERJSON_IDX); #endif - std::string userFilePath = dirPath + DIR_SEP + "user.json"; return userFilePath; } @@ -275,3 +307,37 @@ void SlippiUser::deleteFile() std::string userFilePath = getUserFilePath(); File::Delete(userFilePath); } + +void SlippiUser::overwriteFromServer() +{ + if (!m_curl) + return; + + // Perform curl request + std::string resp; + curl_easy_setopt(m_curl, CURLOPT_URL, (URL_START + "/" + userInfo.uid).c_str()); + curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &resp); + CURLcode res = curl_easy_perform(m_curl); + + if (res != 0) + { + ERROR_LOG(SLIPPI, "[User] Error fetching user info from server, code: %d", res); + return; + } + + long responseCode; + curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &responseCode); + if (responseCode != 200) + { + ERROR_LOG(SLIPPI, "[User] Server responded with non-success status: %d", responseCode); + return; + } + + // Overwrite userInfo with data from server + auto r = json::parse(resp); + userInfo.connectCode = r.value("connectCode", userInfo.connectCode); + userInfo.latestVersion = r.value("latestVersion", userInfo.latestVersion); + + // TODO: Once it's possible to change Display name from website, uncomment below + // userInfo.displayName = r.value("displayName", userInfo.displayName); +} diff --git a/Source/Core/Core/Slippi/SlippiUser.h b/Source/Core/Core/Slippi/SlippiUser.h index e35276801f..f12b66f774 100644 --- a/Source/Core/Core/Slippi/SlippiUser.h +++ b/Source/Core/Core/Slippi/SlippiUser.h @@ -2,8 +2,11 @@ #include "Common/CommonTypes.h" #include +#include #include #include +#include +#include class SlippiUser { @@ -18,11 +21,11 @@ public: std::string fileContents = ""; }; + SlippiUser(); ~SlippiUser(); bool AttemptLogin(); void OpenLogInPage(); - void UpdateFile(); void UpdateApp(); void ListenForLogIn(); void LogOut(); @@ -35,10 +38,16 @@ protected: std::string getUserFilePath(); UserInfo parseFile(std::string fileContents); void deleteFile(); + void overwriteFromServer(); UserInfo userInfo; bool isLoggedIn = false; + const std::string URL_START = "https://users-rest-dot-slippi.uc.r.appspot.com/user"; + CURL* m_curl = nullptr; + struct curl_slist* m_curlHeaderList = nullptr; + std::vector receiveBuf; + std::thread fileListenThread; std::atomic runThread; };