From f110ef2bc8a3d379595bed94e4cafd1ae39c87f3 Mon Sep 17 00:00:00 2001 From: Anonymous275 <36374260+Anonymous-275@users.noreply.github.com> Date: Mon, 17 Jan 2022 18:20:57 +0200 Subject: [PATCH] Added HTTP logic and login --- .gitmodules | 3 ++ CMakeLists.txt | 4 +- include/Http.h | 17 +++++++ include/Launcher.h | 21 +++++--- include/cpp-httplib | 1 + src/Config.cpp | 10 ++++ src/Launcher.cpp | 20 +++++++- src/Login.cpp | 115 ++++++++++++++++++++++++++++++++++++++++++ src/Network/Http.cpp | 117 +++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 3 +- 10 files changed, 302 insertions(+), 9 deletions(-) create mode 100644 include/Http.h create mode 160000 include/cpp-httplib create mode 100644 src/Config.cpp create mode 100644 src/Login.cpp create mode 100644 src/Network/Http.cpp diff --git a/.gitmodules b/.gitmodules index 16c1f6f..f7802b6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "rapidjson"] path = include/rapidjson url = https://github.com/Tencent/rapidjson.git +[submodule "include/cpp-httplib"] + path = include/cpp-httplib + url = https://github.com/yhirose/cpp-httplib.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 3288abd..154217d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ set(wxBUILD_MSVC_MULTIPROC ON) set(wxBUILD_USE_STATIC_RUNTIME ON) add_subdirectory(include/wxWidgets) add_subdirectory(include/rapidjson) - +add_subdirectory(include/cpp-httplib) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") @@ -32,6 +32,8 @@ add_executable(${PROJECT_NAME} src/Logger.cpp include/Logger.h src/gui/Gui.cpp include/Json.h src/gui/gifs.cpp src/gui/gifs.h + src/Network/Http.cpp include/Http.h + src/Login.cpp src/Config.cpp ) diff --git a/include/Http.h b/include/Http.h new file mode 100644 index 0000000..7be6ce3 --- /dev/null +++ b/include/Http.h @@ -0,0 +1,17 @@ +/// +/// Created by Anonymous275 on 1/17/22 +/// Copyright (c) 2021-present Anonymous275 read the LICENSE file for more info. +/// + +#pragma once +#include + +class HTTP { +public: + static bool Download(const std::string &IP, const std::string &Path); + static std::string Post(const std::string& IP, const std::string& Fields); + static std::string Get(const std::string &IP); + static bool ProgressBar(size_t c, size_t t); +public: + static bool isDownload; +}; \ No newline at end of file diff --git a/include/Launcher.h b/include/Launcher.h index c065116..8b6fbcb 100644 --- a/include/Launcher.h +++ b/include/Launcher.h @@ -7,16 +7,25 @@ #include class Launcher { -public: +public: //constructors Launcher(int argc, char* argv[]); - const std::string& getFullVersion(){return FullVersion;} - const std::string& getWorkingDir(){return DirPath;} - const std::string& getVersion(){return Version;} +public: //available functions + std::string Login(const std::string& fields); + void checkLocalKey(); + void loadConfig(); void launchGame(); -private: +public: //Getters + const std::string& getFullVersion(); + const std::string& getWorkingDir(); + const std::string& getUserRole(); + const std::string& getVersion(); +private: //functions void WindowsInit(); -private: +private: //variables std::string DirPath; + std::string UserRole; + std::string PublicKey; + bool LoginAuth = false; std::string Version{"3.0"}; std::string FullVersion{Version + ".0"}; }; diff --git a/include/cpp-httplib b/include/cpp-httplib new file mode 160000 index 0000000..33f53aa --- /dev/null +++ b/include/cpp-httplib @@ -0,0 +1 @@ +Subproject commit 33f53aa4583c132e70dc21f2d7fe004706267784 diff --git a/src/Config.cpp b/src/Config.cpp new file mode 100644 index 0000000..d368359 --- /dev/null +++ b/src/Config.cpp @@ -0,0 +1,10 @@ +/// +/// Created by Anonymous275 on 1/17/22 +/// Copyright (c) 2021-present Anonymous275 read the LICENSE file for more info. +/// + +#include "Launcher.h" + +void Launcher::loadConfig() { + +} \ No newline at end of file diff --git a/src/Launcher.cpp b/src/Launcher.cpp index 8b03b91..1797084 100644 --- a/src/Launcher.cpp +++ b/src/Launcher.cpp @@ -24,4 +24,22 @@ void Launcher::launchGame() { void Launcher::WindowsInit() { system("cls"); SetConsoleTitleA(("BeamMP Launcher v" + FullVersion).c_str()); -} \ No newline at end of file +} + +const std::string& Launcher::getFullVersion() { + return FullVersion; +} + +const std::string& Launcher::getWorkingDir() { + return DirPath; +} + +const std::string &Launcher::getVersion() { + return Version; +} + +const std::string& Launcher::getUserRole() { + return UserRole; +} + + diff --git a/src/Login.cpp b/src/Login.cpp new file mode 100644 index 0000000..409b4c8 --- /dev/null +++ b/src/Login.cpp @@ -0,0 +1,115 @@ +/// +/// Created by Anonymous275 on 1/17/22 +/// Copyright (c) 2021-present Anonymous275 read the LICENSE file for more info. +/// + +#include "Launcher.h" +#include +#include "Logger.h" +#include +#include "Http.h" +#include "Json.h" + +namespace fs = std::filesystem; + +void UpdateKey(const char* newKey){ + if(newKey){ + std::ofstream Key("key"); + if(Key.is_open()){ + Key << newKey; + Key.close(); + }else LOG(FATAL) << "Cannot write to disk!"; + }else if(fs::exists("key")){ + remove("key"); + } +} + +/// "username":"value","password":"value" +/// "Guest":"Name" +/// "pk":"private_key" + +std::string GetFail(const std::string& R){ + std::string DRet = R"({"success":false,"message":)"; + DRet += "\""+R+"\"}"; + LOG(ERROR) << R; + return DRet; +} + +std::string Launcher::Login(const std::string& fields) { + if(fields == "LO"){ + LoginAuth = false; + UpdateKey(nullptr); + return ""; + } + LOG(INFO) << "Attempting to authenticate..."; + std::string Buffer = HTTP::Post("https://auth.beammp.com/userlogin", fields); + Json::Document d; + d.Parse(Buffer.c_str()); + + if(Buffer == "-1"){ + return GetFail("Failed to communicate with the auth system!"); + } + + if (Buffer.at(0) != '{' || d.HasParseError()) { + LOG(ERROR) << Buffer; + return GetFail("Invalid answer from authentication servers, please try again later!"); + } + + if(!d["success"].IsNull() && d["success"].GetBool()){ + LoginAuth = true; + if(!d["private_key"].IsNull()){ + UpdateKey(d["private_key"].GetString()); + } + if(!d["public_key"].IsNull()){ + PublicKey = d["public_key"].GetString(); + } + LOG(INFO) << "Authentication successful!"; + }else LOG(WARNING) << "Authentication failed!"; + + if(!d["message"].IsNull()) { + d.RemoveMember("private_key"); + d.RemoveMember("public_key"); + Json::StringBuffer buffer; + Json::Writer writer(buffer); + d.Accept(writer); + return buffer.GetString(); + } + return GetFail("Invalid message parsing!"); +} + +void Launcher::checkLocalKey() { + if(fs::exists("key") && fs::file_size("key") < 100){ + std::ifstream Key("key"); + if(Key.is_open()) { + auto Size = fs::file_size("key"); + std::string Buffer(Size, 0); + Key.read(&Buffer[0], std::streamsize(Size)); + Key.close(); + + Buffer = HTTP::Post("https://auth.beammp.com/userlogin", R"({"pk":")" + Buffer + "\"}"); + + Json::Document d; + d.Parse(Buffer.c_str()); + if (Buffer == "-1" || Buffer.at(0) != '{' || d.HasParseError()) { + LOG(ERROR) << Buffer; + LOG(FATAL) << "Invalid answer from authentication servers, please try again later!"; + } + if(d["success"].GetBool()){ + LoginAuth = true; + UpdateKey(d["private_key"].GetString()); + PublicKey = d["public_key"].GetString(); + UserRole = d["role"].GetString(); + //info(Role); + }else{ + LOG(WARNING) << "Auto-Authentication unsuccessful please re-login!"; + UpdateKey(nullptr); + } + }else{ + LOG(WARNING) << "Could not open saved key!"; + UpdateKey(nullptr); + } + }else UpdateKey(nullptr); +} + + + diff --git a/src/Network/Http.cpp b/src/Network/Http.cpp new file mode 100644 index 0000000..73dcbb1 --- /dev/null +++ b/src/Network/Http.cpp @@ -0,0 +1,117 @@ +/// +/// Created by Anonymous275 on 1/17/22 +/// Copyright (c) 2021-present Anonymous275 read the LICENSE file for more info. +/// + +#define CPPHTTPLIB_OPENSSL_SUPPORT + +#include +#include +#include "Logger.h" +#include +#include "Http.h" +#include +#include + +bool HTTP::isDownload = false; +std::string HTTP::Get(const std::string &IP) { + static std::mutex Lock; + std::scoped_lock Guard(Lock); + + auto pos = IP.find('/',10); + + httplib::Client cli(IP.substr(0, pos)); + cli.set_connection_timeout(std::chrono::seconds(10)); + auto res = cli.Get(IP.substr(pos).c_str(), ProgressBar); + std::string Ret; + + if(res.error() == httplib::Error::Success){ + if(res->status == 200){ + Ret = res->body; + }else LOG(ERROR) << res->reason; + + }else{ + if(isDownload) { + std::cout << "\n"; + } + LOG(ERROR) << "HTTP Get failed on " << httplib::to_string(res.error()); + } + + return Ret; +} + +std::string HTTP::Post(const std::string& IP, const std::string& Fields) { + static std::mutex Lock; + std::scoped_lock Guard(Lock); + + auto pos = IP.find('/',10); + + httplib::Client cli(IP.substr(0, pos)); + cli.set_connection_timeout(std::chrono::seconds(10)); + std::string Ret; + + if(!Fields.empty()) { + httplib::Result res = cli.Post(IP.substr(pos).c_str(), Fields, "application/json"); + + if(res.error() == httplib::Error::Success) { + if(res->status != 200) { + LOG(ERROR) << res->reason; + } + Ret = res->body; + } else{ + LOG(ERROR) << "HTTP Post failed on " << httplib::to_string(res.error()); + } + } else { + httplib::Result res = cli.Post(IP.substr(pos).c_str()); + if(res.error() == httplib::Error::Success) { + if (res->status != 200) { + LOG(ERROR) << res->reason; + } + Ret = res->body; + } else { + LOG(ERROR) << "HTTP Post failed on " << httplib::to_string(res.error()); + } + } + + if(Ret.empty())return "-1"; + else return Ret; +} + +bool HTTP::ProgressBar(size_t c, size_t t){ + if(isDownload) { + static double progress_bar_adv; + progress_bar_adv = round(double(c) / double(t) * 25); + std::cout << "\r"; + std::cout << "Progress : [ "; + std::cout << round(double(c) / double(t) * 100); + std::cout << "% ] ["; + int i; + for (i = 0; i <= progress_bar_adv; i++)std::cout << "#"; + for (i = 0; i < 25 - progress_bar_adv; i++)std::cout << "."; + std::cout << "]"; + } + return true; +} + +bool HTTP::Download(const std::string &IP, const std::string &Path) { + static std::mutex Lock; + std::scoped_lock Guard(Lock); + + isDownload = true; + std::string Ret = Get(IP); + isDownload = false; + + if(Ret.empty())return false; + + std::ofstream File(Path, std::ios::binary); + if(File.is_open()) { + File << Ret; + File.close(); + std::cout << "\n"; + LOG(INFO) << "Download Complete!"; + } else { + LOG(INFO) << "Failed to open file directory: " << Path; + return false; + } + return true; +} diff --git a/src/main.cpp b/src/main.cpp index 66887c6..2ed20c8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,6 +7,7 @@ #include "Logger.h" int main(int argc, char* argv[]) { Launcher launcher(argc, argv); - launcher.launchGame(); + launcher.checkLocalKey(); + return 0; }