mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-08-26 12:16:20 +00:00
up to 4307319
This commit is contained in:
parent
be07a173c3
commit
ef665f12a4
2 changed files with 117 additions and 42 deletions
|
@ -12,6 +12,7 @@
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "Common/Thread.h"
|
#include "Common/Thread.h"
|
||||||
|
|
||||||
|
#include "Common/Common.h"
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
|
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
|
@ -53,12 +54,51 @@ static void RunSystemCommand(const std::string& command)
|
||||||
#endif
|
#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()
|
SlippiUser::~SlippiUser()
|
||||||
{
|
{
|
||||||
// Wait for thread to terminate
|
// Wait for thread to terminate
|
||||||
runThread = false;
|
runThread = false;
|
||||||
if (fileListenThread.joinable())
|
if (fileListenThread.joinable())
|
||||||
fileListenThread.join();
|
fileListenThread.join();
|
||||||
|
|
||||||
|
if (m_curl)
|
||||||
|
{
|
||||||
|
curl_slist_free_all(m_curlHeaderList);
|
||||||
|
curl_easy_cleanup(m_curl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SlippiUser::AttemptLogin()
|
bool SlippiUser::AttemptLogin()
|
||||||
|
@ -68,21 +108,20 @@ bool SlippiUser::AttemptLogin()
|
||||||
INFO_LOG(SLIPPI_ONLINE, "Looking for file at: %s", userFilePath.c_str());
|
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 =
|
||||||
std::string userFilePathTxt = userFilePath + ".txt";
|
userFilePath + ".txt"; // Put the filename here in its own scope because we don't really need it elsewhere
|
||||||
if (File::Exists(userFilePathTxt))
|
if (File::Exists(userFilePathTxt))
|
||||||
{
|
{
|
||||||
// If both files exist we just log they exist and take no further action
|
// If both files exist we just log they exist and take no further action
|
||||||
if (File::Exists(userFilePath))
|
if (File::Exists(userFilePath))
|
||||||
{
|
{
|
||||||
INFO_LOG(SLIPPI_ONLINE, "Found both .json.txt and .json file for user data. Using .json "
|
INFO_LOG(SLIPPI_ONLINE,
|
||||||
"and ignoring the .json.txt");
|
"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
|
// If only the .txt file exists move the contents to a json file and log if it fails
|
||||||
else if (!File::Rename(userFilePathTxt, userFilePath))
|
else if (!File::Rename(userFilePathTxt, userFilePath))
|
||||||
{
|
{
|
||||||
WARN_LOG(SLIPPI_ONLINE, "Could not move file %s to %s", userFilePathTxt.c_str(),
|
WARN_LOG(SLIPPI_ONLINE, "Could not move file %s to %s", userFilePathTxt.c_str(), userFilePath.c_str());
|
||||||
userFilePath.c_str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,6 +135,7 @@ bool SlippiUser::AttemptLogin()
|
||||||
isLoggedIn = !userInfo.uid.empty();
|
isLoggedIn = !userInfo.uid.empty();
|
||||||
if (isLoggedIn)
|
if (isLoggedIn)
|
||||||
{
|
{
|
||||||
|
overwriteFromServer();
|
||||||
WARN_LOG(SLIPPI_ONLINE, "Found user %s (%s)", userInfo.displayName.c_str(), userInfo.uid.c_str());
|
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()
|
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 url = "https://slippi.gg/online/enable";
|
||||||
std::string path = getUserFilePath();
|
std::string path = getUserFilePath();
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#ifdef _WIN32
|
||||||
#else
|
// On windows, sometimes the path can have backslashes and slashes mixed, convert all to backslashes
|
||||||
path = ReplaceAll(path, "\\", folderSep);
|
path = ReplaceAll(path, "\\", "\\");
|
||||||
path = ReplaceAll(path, "/", folderSep);
|
path = ReplaceAll(path, "/", "\\");
|
||||||
#endif
|
#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;
|
std::string fullUrl = url + "?path=" + path;
|
||||||
|
|
||||||
|
INFO_LOG(SLIPPI_ONLINE, "[User] Login at path: %s", fullUrl.c_str());
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
std::string command = "explorer \"" + fullUrl + "\"";
|
std::string command = "explorer \"" + fullUrl + "\"";
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
|
@ -131,41 +174,32 @@ void SlippiUser::OpenLogInPage()
|
||||||
RunSystemCommand(command);
|
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()
|
void SlippiUser::UpdateApp()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#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 path = File::GetExeDirectory() + "/dolphin-slippi-tools.exe";
|
||||||
std::string echoMsg = "echo Starting update process. If nothing happen after a few "
|
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 ...";
|
"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 + "\"";
|
// std::string command =
|
||||||
WARN_LOG(SLIPPI, "Executing app update command: %s", command.c_str());
|
// "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);
|
RunSystemCommand(command);
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
#else
|
#else
|
||||||
const char* appimage_path = getenv("APPIMAGE");
|
const char* appimage_path = getenv("APPIMAGE");
|
||||||
|
const char* appmount_path = getenv("APPDIR");
|
||||||
if (!appimage_path)
|
if (!appimage_path)
|
||||||
{
|
{
|
||||||
CriticalAlertT("Automatic updates are not available for non-AppImage Linux builds.");
|
CriticalAlertT("Automatic updates are not available for non-AppImage Linux builds.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::string path(appimage_path);
|
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());
|
WARN_LOG(SLIPPI, "Executing app update command: %s", command.c_str());
|
||||||
RunSystemCommand(command);
|
RunSystemCommand(command);
|
||||||
#endif
|
#endif
|
||||||
|
@ -222,20 +256,18 @@ void SlippiUser::FileListenThread()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// On Linux platforms, the user.json file lives in the Sys/ directory in
|
// On Linux platforms, the user.json file lives in the XDG_CONFIG_HOME/SlippiOnline
|
||||||
// order to deal with the fact that we want the configuration for AppImage
|
// directory in order to deal with the fact that we want the configuration for AppImage
|
||||||
// builds to be mutable.
|
// builds to be mutable.
|
||||||
std::string SlippiUser::getUserFilePath()
|
std::string SlippiUser::getUserFilePath()
|
||||||
{
|
{
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
std::string dirPath = File::GetBundleDirectory() + "/Contents/Resources";
|
std::string userFilePath = File::GetBundleDirectory() + "/Contents/Resources" + DIR_SEP + "user.json";
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
std::string dirPath = File::GetExeDirectory();
|
std::string userFilePath = File::GetExeDirectory() + DIR_SEP + "user.json";
|
||||||
#else
|
#else
|
||||||
std::string dirPath = File::GetSysDirectory();
|
std::string userFilePath = File::GetUserPath(F_USERJSON_IDX);
|
||||||
dirPath.pop_back();
|
|
||||||
#endif
|
#endif
|
||||||
std::string userFilePath = dirPath + DIR_SEP + "user.json";
|
|
||||||
return userFilePath;
|
return userFilePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,3 +307,37 @@ void SlippiUser::deleteFile()
|
||||||
std::string userFilePath = getUserFilePath();
|
std::string userFilePath = getUserFilePath();
|
||||||
File::Delete(userFilePath);
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -2,8 +2,11 @@
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <curl/curl.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class SlippiUser
|
class SlippiUser
|
||||||
{
|
{
|
||||||
|
@ -18,11 +21,11 @@ public:
|
||||||
std::string fileContents = "";
|
std::string fileContents = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SlippiUser();
|
||||||
~SlippiUser();
|
~SlippiUser();
|
||||||
|
|
||||||
bool AttemptLogin();
|
bool AttemptLogin();
|
||||||
void OpenLogInPage();
|
void OpenLogInPage();
|
||||||
void UpdateFile();
|
|
||||||
void UpdateApp();
|
void UpdateApp();
|
||||||
void ListenForLogIn();
|
void ListenForLogIn();
|
||||||
void LogOut();
|
void LogOut();
|
||||||
|
@ -35,10 +38,16 @@ protected:
|
||||||
std::string getUserFilePath();
|
std::string getUserFilePath();
|
||||||
UserInfo parseFile(std::string fileContents);
|
UserInfo parseFile(std::string fileContents);
|
||||||
void deleteFile();
|
void deleteFile();
|
||||||
|
void overwriteFromServer();
|
||||||
|
|
||||||
UserInfo userInfo;
|
UserInfo userInfo;
|
||||||
bool isLoggedIn = false;
|
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<char> receiveBuf;
|
||||||
|
|
||||||
std::thread fileListenThread;
|
std::thread fileListenThread;
|
||||||
std::atomic<bool> runThread;
|
std::atomic<bool> runThread;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue