Mingw Compatible

This commit is contained in:
Anonymous-275 2021-03-29 11:43:24 +03:00
parent d96f968dde
commit fbc5e28d25
65 changed files with 883 additions and 822 deletions

View File

@ -6,18 +6,22 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
file(GLOB source_files "src/*.cpp" "src/*/*.cpp" "src/*/*.hpp" "include/*.h" "include/*/*.h" "include/*/*/*.h") file(GLOB source_files "src/*.cpp" "src/*/*.cpp" "src/*/*.hpp" "include/*.h" "include/*/*.h" "include/*/*/*.h")
add_executable(${PROJECT_NAME} ${source_files}) add_executable(${PROJECT_NAME} ${source_files})
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "BeamMP-Launcher") set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "BeamMP-Launcher")
find_package(ZLIB REQUIRED)
find_package(CURL CONFIG REQUIRED)
# This might cause issues with old windows headers, but it's worth the trouble to keep the code if (WIN32)
# completely cross platform. For fixes to common issues arising from /permissive- visit: find_package(ZLIB REQUIRED)
# https://docs.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance find_package(CURL REQUIRED)
message(STATUS "MSVC -> forcing use of statically-linked runtime.")
STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
#-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static
set(VcpkgRoot ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET})
include_directories(${VcpkgRoot}/include)
link_directories(${VcpkgRoot}/lib)
target_link_libraries(${PROJECT_NAME} PRIVATE discord-rpc CURL::libcurl ZLIB::ZLIB)
else(WIN32) #MINGW
add_definitions("-D_WIN32_WINNT=0x0600")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s -static-libgcc -static-libstdc++ --static")
target_link_libraries(${PROJECT_NAME} discord-rpc.a ssp z ws2_32)
endif(WIN32)
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /permissive-")
message(STATUS "MSVC -> forcing use of statically-linked runtime.")
STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
#-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static
target_link_libraries(${PROJECT_NAME} PRIVATE rstrtmgr discord-rpc CURL::libcurl ZLIB::ZLIB)
target_include_directories(${PROJECT_NAME} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>) target_include_directories(${PROJECT_NAME} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)

20
README.md Normal file → Executable file
View File

@ -1,10 +1,10 @@
# BeamMP-Launcher # BeamMP-Launcher
The launcher is the way we communitcate to outside the game, it does a few automated actions such as but not limited to: downloading the mod, launching the game, and create a connection to a server. The launcher is the way we communitcate to outside the game, it does a few automated actions such as but not limited to: downloading the mod, launching the game, and create a connection to a server.
Copyright (c) 2019-present Anonymous275. Copyright (c) 2019-present Anonymous275.
BeamMP Launcher code is not in the public domain and is not free software. BeamMP Launcher code is not in the public domain and is not free software.
One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries, One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries,
the only permission that has been granted is to use the software in its compiled form as distributed from the BeamMP.com website. the only permission that has been granted is to use the software in its compiled form as distributed from the BeamMP.com website.
Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.

0
include/Curl/http.h Normal file → Executable file
View File

0
include/Discord/discord_info.h Normal file → Executable file
View File

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include <stdint.h> #include <cstdint>
// clang-format off // clang-format off

22
include/Json.h Normal file → Executable file
View File

@ -1,12 +1,12 @@
// Copyright (c) 2019-present Anonymous275. // Copyright (c) 2019-present Anonymous275.
// BeamMP Launcher code is not in the public domain and is not free software. // BeamMP Launcher code is not in the public domain and is not free software.
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. // One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. // Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
/// ///
/// Created by Anonymous275 on 11/27/2020 /// Created by Anonymous275 on 11/27/2020
/// ///
#pragma once #pragma once
#include "rapidjson/stringbuffer.h" #include "rapidjson/stringbuffer.h"
#include "rapidjson/document.h" #include "rapidjson/document.h"
#include "rapidjson/writer.h" #include "rapidjson/writer.h"
namespace json = rapidjson; namespace json = rapidjson;

0
include/Logger.h Normal file → Executable file
View File

4
include/Network/network.h Normal file → Executable file
View File

@ -5,6 +5,8 @@
/// ///
/// Created by Anonymous275 on 7/18/2020 /// Created by Anonymous275 on 7/18/2020
/// ///
#pragma once #pragma once
#include <string> #include <string>
void NetReset(); void NetReset();
@ -18,7 +20,7 @@ extern bool Terminate;
extern int DEFAULT_PORT; extern int DEFAULT_PORT;
extern uint64_t UDPSock; extern uint64_t UDPSock;
extern uint64_t TCPSock; extern uint64_t TCPSock;
extern std::string Role; extern std::string Branch;
extern bool TCPTerminate; extern bool TCPTerminate;
extern std::string LastIP; extern std::string LastIP;
extern std::string MStatus; extern std::string MStatus;

0
include/Security/Game.h Normal file → Executable file
View File

0
include/Security/Init.h Normal file → Executable file
View File

1
include/Startup.h Normal file → Executable file
View File

@ -12,4 +12,5 @@ std::string GetEP(char*P = nullptr);
std::string GetGamePath(); std::string GetGamePath();
std::string GetVer(); std::string GetVer();
std::string GetEN(); std::string GetEN();
void ConfigInit();
extern bool Dev; extern bool Dev;

0
include/Zlib/Compressor.h Normal file → Executable file
View File

0
include/rapidjson/allocators.h Normal file → Executable file
View File

0
include/rapidjson/cursorstreamwrapper.h Normal file → Executable file
View File

0
include/rapidjson/document.h Normal file → Executable file
View File

0
include/rapidjson/encodedstream.h Normal file → Executable file
View File

0
include/rapidjson/encodings.h Normal file → Executable file
View File

0
include/rapidjson/error/en.h Normal file → Executable file
View File

0
include/rapidjson/error/error.h Normal file → Executable file
View File

0
include/rapidjson/filereadstream.h Normal file → Executable file
View File

0
include/rapidjson/filewritestream.h Normal file → Executable file
View File

0
include/rapidjson/fwd.h Normal file → Executable file
View File

0
include/rapidjson/internal/biginteger.h Normal file → Executable file
View File

0
include/rapidjson/internal/clzll.h Normal file → Executable file
View File

0
include/rapidjson/internal/diyfp.h Normal file → Executable file
View File

0
include/rapidjson/internal/dtoa.h Normal file → Executable file
View File

0
include/rapidjson/internal/ieee754.h Normal file → Executable file
View File

0
include/rapidjson/internal/itoa.h Normal file → Executable file
View File

0
include/rapidjson/internal/meta.h Normal file → Executable file
View File

0
include/rapidjson/internal/pow10.h Normal file → Executable file
View File

0
include/rapidjson/internal/regex.h Normal file → Executable file
View File

0
include/rapidjson/internal/stack.h Normal file → Executable file
View File

0
include/rapidjson/internal/strfunc.h Normal file → Executable file
View File

0
include/rapidjson/internal/strtod.h Normal file → Executable file
View File

0
include/rapidjson/internal/swap.h Normal file → Executable file
View File

0
include/rapidjson/istreamwrapper.h Normal file → Executable file
View File

0
include/rapidjson/memorybuffer.h Normal file → Executable file
View File

0
include/rapidjson/memorystream.h Normal file → Executable file
View File

0
include/rapidjson/msinttypes/inttypes.h Normal file → Executable file
View File

0
include/rapidjson/msinttypes/stdint.h Normal file → Executable file
View File

0
include/rapidjson/ostreamwrapper.h Normal file → Executable file
View File

0
include/rapidjson/pointer.h Normal file → Executable file
View File

0
include/rapidjson/prettywriter.h Normal file → Executable file
View File

0
include/rapidjson/rapidjson.h Normal file → Executable file
View File

0
include/rapidjson/reader.h Normal file → Executable file
View File

0
include/rapidjson/schema.h Normal file → Executable file
View File

0
include/rapidjson/stream.h Normal file → Executable file
View File

0
include/rapidjson/stringbuffer.h Normal file → Executable file
View File

0
include/rapidjson/writer.h Normal file → Executable file
View File

0
src/Compressor.cpp Normal file → Executable file
View File

60
src/Config.cpp Executable file
View File

@ -0,0 +1,60 @@
///
/// Created by Anonymous275 on 2/23/2021
///
#include "Network/network.h"
#include <filesystem>
#include "Logger.h"
#include <fstream>
#include "Json.h"
#include <cstdint>
namespace fs = std::filesystem;
std::string Branch;
void ParseConfig(const json::Document& d){
if(d["Port"].IsInt()){
DEFAULT_PORT = d["Port"].GetInt();
}
//Default -1
//Release 1
//EA 2
//Dev 3
//Custom 3
if(d["Build"].IsString()){
Branch = d["Build"].GetString();
for(char& c : Branch)c = char(tolower(c));
}
}
void ConfigInit(){
if(fs::exists("Launcher.cfg")){
std::ifstream cfg("Launcher.cfg");
if(cfg.is_open()){
auto Size = fs::file_size("Launcher.cfg");
std::string Buffer(Size, 0);
cfg.read(&Buffer[0], Size);
cfg.close();
json::Document d;
d.Parse(Buffer.c_str());
if(d.HasParseError()){
fatal("Config failed to parse make sure it's valid JSON! Code : " + std::to_string(d.GetParseError()));
}
ParseConfig(d);
}else fatal("Failed to open Launcher.cfg!");
}else{
std::ofstream cfg("Launcher.cfg");
if(cfg.is_open()){
cfg <<
R"({
"Port": 4444,
"Build": "Default"
})";
cfg.close();
}else{
fatal("Failed to write config on disk!");
}
}
}

2
src/Discord.cpp Normal file → Executable file
View File

@ -7,7 +7,7 @@
/// ///
#include "Discord/discord_rpc.h" #include "Discord/discord_rpc.h"
#include "Logger.h" #include "Logger.h"
#include <iostream> #include <cstring>
#include <thread> #include <thread>
#include <ctime> #include <ctime>

2
src/GameStart.cpp Normal file → Executable file
View File

@ -6,7 +6,7 @@
/// Created by Anonymous275 on 7/19/2020 /// Created by Anonymous275 on 7/19/2020
/// ///
#include <Windows.h> #include <windows.h>
#include "Startup.h" #include "Startup.h"
#include "Logger.h" #include "Logger.h"
#include <iostream> #include <iostream>

0
src/Logger.cpp Normal file → Executable file
View File

8
src/Network/Core.cpp Normal file → Executable file
View File

@ -9,8 +9,8 @@
#include "Security/Init.h" #include "Security/Init.h"
#include "Curl/http.h" #include "Curl/http.h"
#include <WinSock2.h> #include <winsock2.h>
#include <WS2tcpip.h> #include <ws2tcpip.h>
#include "Startup.h" #include "Startup.h"
#include "Logger.h" #include "Logger.h"
#include <charconv> #include <charconv>
@ -242,9 +242,13 @@ int Handle(EXCEPTION_POINTERS *ep){
void CoreNetwork(){ void CoreNetwork(){
while(TraceBack >= 4){ while(TraceBack >= 4){
#ifndef __MINGW32__
__try{ __try{
#endif
CoreMain(); CoreMain();
#ifndef __MINGW32__
}__except(Handle(GetExceptionInformation())){} }__except(Handle(GetExceptionInformation())){}
#endif
std::this_thread::sleep_for(std::chrono::seconds(1)); std::this_thread::sleep_for(std::chrono::seconds(1));
} }
} }

0
src/Network/DNS.cpp Normal file → Executable file
View File

6
src/Network/GlobalHandler.cpp Normal file → Executable file
View File

@ -6,15 +6,15 @@
/// Created by Anonymous275 on 7/25/2020 /// Created by Anonymous275 on 7/25/2020
/// ///
#include "Network/network.h" #include "Network/network.h"
#include <WinSock2.h> #include <winsock2.h>
#include <WS2tcpip.h> #include <ws2tcpip.h>
#include "Logger.h" #include "Logger.h"
#include <charconv> #include <charconv>
#include <string> #include <string>
#include <thread> #include <thread>
#include <mutex> #include <mutex>
std::chrono::time_point<std::chrono::steady_clock> PingStart,PingEnd; std::chrono::time_point<std::chrono::high_resolution_clock> PingStart,PingEnd;
bool GConnected = false; bool GConnected = false;
bool CServer = true; bool CServer = true;
SOCKET CSocket = -1; SOCKET CSocket = -1;

282
src/Network/Http.cpp Normal file → Executable file
View File

@ -1,140 +1,144 @@
// Copyright (c) 2019-present Anonymous275. // Copyright (c) 2019-present Anonymous275.
// BeamMP Launcher code is not in the public domain and is not free software. // BeamMP Launcher code is not in the public domain and is not free software.
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. // One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. // Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
/// ///
/// Created by Anonymous275 on 7/18/2020 /// Created by Anonymous275 on 7/18/2020
/// ///
#include <curl/curl.h> #include <curl/curl.h>
#include <iostream> #include <iostream>
#include <Logger.h> #include <Logger.h>
#include <mutex> #include <mutex>
#include <cmath>
class CurlManager{
public: class CurlManager{
CurlManager(){ public:
curl = curl_easy_init(); CurlManager(){
} curl = curl_easy_init();
~CurlManager(){ }
curl_easy_cleanup(curl); ~CurlManager(){
} curl_easy_cleanup(curl);
inline CURL* Get(){ }
return curl; inline CURL* Get(){
} return curl;
private: }
CURL *curl; private:
}; CURL *curl;
};
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp){
((std::string*)userp)->append((char*)contents, size * nmemb); static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp){
return size * nmemb; ((std::string*)userp)->append((char*)contents, size * nmemb);
} return size * nmemb;
}
std::string HTTP_REQUEST(const std::string& IP,int port){
static thread_local CurlManager M; std::string HTTP_REQUEST(const std::string& IP,int port){
static std::mutex Lock; static thread_local CurlManager M;
std::scoped_lock Guard(Lock); static std::mutex Lock;
CURL *curl = M.Get(); std::scoped_lock Guard(Lock);
CURLcode res; CURL *curl = M.Get();
std::string readBuffer; CURLcode res;
if(curl) { std::string readBuffer;
curl_easy_setopt(curl, CURLOPT_URL, IP.c_str()); if(curl) {
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); curl_easy_setopt(curl, CURLOPT_URL, IP.c_str());
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
curl_easy_setopt(curl, CURLOPT_PORT, port); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_PORT, port);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
res = curl_easy_perform(curl); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
if(res != CURLE_OK)return "-1"; res = curl_easy_perform(curl);
} if(res != CURLE_OK)return "-1";
return readBuffer; }
} return readBuffer;
}
int nb_bar;
double last_progress, progress_bar_adv; int nb_bar;
bool Downloaded; double last_progress, progress_bar_adv;
int progress_bar (void *bar, double t, double d){ bool Downloaded;
if(t > 0 && last_progress != round(d/t*100)){ int progress_bar (void *bar, double t, double d){
nb_bar = 25; if(t > 0 && last_progress != round(d/t*100)){
progress_bar_adv = round(d/t*nb_bar); nb_bar = 25;
std::cout<<"\r"; progress_bar_adv = round(d/t*nb_bar);
std::cout<< "Progress : [ "; std::cout<<"\r";
std::cout<<round(d/t*100); std::cout<< "Progress : [ ";
std::cout << "% ] ["; std::cout<<round(d/t*100);
int i; std::cout << "% ] [";
for(i = 0; i <= progress_bar_adv; i++)std::cout<<"#"; int i;
for(i = 0; i < nb_bar - progress_bar_adv; i++)std::cout<<"."; for(i = 0; i <= progress_bar_adv; i++)std::cout<<"#";
std::cout<<"]"; for(i = 0; i < nb_bar - progress_bar_adv; i++)std::cout<<".";
last_progress = round(d/t*100); std::cout<<"]";
if(round(d/t*100) == 100){ last_progress = round(d/t*100);
Downloaded = true; if(round(d/t*100) == 100){
} Downloaded = true;
} }
return 0; }
} return 0;
struct File { }
const char *filename; struct File {
FILE *stream; const char *filename;
}; FILE *stream;
static size_t my_fwrite(void *buffer,size_t size,size_t nmemb,void *stream){ };
auto *out = (struct File*)stream; static size_t my_fwrite(void *buffer,size_t size,size_t nmemb,void *stream){
if(!out->stream) { auto *out = (struct File*)stream;
fopen_s(&out->stream,out->filename,"wb"); if(!out->stream) {
if(!out->stream)return -1; fopen_s(&out->stream,out->filename,"wb");
} if(!out->stream)return -1;
return fwrite(buffer, size, nmemb, out->stream); }
} return fwrite(buffer, size, nmemb, out->stream);
int Download(const std::string& URL,const std::string& Path,bool close){ }
static thread_local CurlManager M; int Download(const std::string& URL,const std::string& Path,bool close){
CURL *curl = M.Get(); static thread_local CurlManager M;
CURLcode res; CURL *curl = M.Get();
struct File file = {Path.c_str(),nullptr}; CURLcode res;
Downloaded = false; struct File file = {Path.c_str(),nullptr};
if(curl){ Downloaded = false;
curl_easy_setopt(curl, CURLOPT_URL,URL.c_str()); if(curl){
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); curl_easy_setopt(curl, CURLOPT_URL,URL.c_str());
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_bar); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL); curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_bar);
res = curl_easy_perform(curl); curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
if(res != CURLE_OK){ res = curl_easy_perform(curl);
return res; if(res != CURLE_OK){
} return res;
} }
if(file.stream)fclose(file.stream); }
if(!Downloaded){ if(file.stream)fclose(file.stream);
remove(Path.c_str()); if(!Downloaded){
fatal("Failed to download please try again later!"); remove(Path.c_str());
} fatal("Failed to download please try again later!");
std::cout << std::endl; }
return -1; std::cout << std::endl;
} return -1;
std::string PostHTTP(const std::string& IP, const std::string& Fields) { }
static auto *header = new curl_slist{(char*)"Content-Type: application/json"}; std::string PostHTTP(const std::string& IP, const std::string& Fields) {
static thread_local CurlManager M; static auto *header = new curl_slist{(char*)"Content-Type: application/json"};
static std::mutex Lock; static thread_local CurlManager M;
std::scoped_lock Guard(Lock); static std::mutex Lock;
CURL* curl = M.Get(); std::scoped_lock Guard(Lock);
CURLcode res; CURL* curl = M.Get();
std::string readBuffer; CURLcode res;
std::string readBuffer;
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, IP.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header); if (curl) {
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, Fields.size()); curl_easy_setopt(curl, CURLOPT_URL, IP.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, Fields.c_str()); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, Fields.size());
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, Fields.c_str());
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
res = curl_easy_perform(curl); //curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
if (res != CURLE_OK) curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
return "-1";
} res = curl_easy_perform(curl);
return readBuffer;
if (res != CURLE_OK)
return "-1";
}
return readBuffer;
} }

7
src/Network/Resources.cpp Normal file → Executable file
View File

@ -7,8 +7,7 @@
/// ///
#include "Network/network.h" #include "Network/network.h"
#include <ws2tcpip.h>
#include <WS2tcpip.h>
#include <filesystem> #include <filesystem>
#include "Startup.h" #include "Startup.h"
#include "Logger.h" #include "Logger.h"
@ -20,6 +19,7 @@
#include <atomic> #include <atomic>
#include <vector> #include <vector>
#include <future> #include <future>
#include <cmath>
namespace fs = std::filesystem; namespace fs = std::filesystem;
std::string ListOfMods; std::string ListOfMods;
@ -37,8 +37,7 @@ std::vector<std::string> Split(const std::string& String,const std::string& deli
} }
void CheckForDir(){ void CheckForDir(){
struct stat info{}; if(!fs::exists("Resources")){
if(stat( "Resources", &info) != 0){
_wmkdir(L"Resources"); _wmkdir(L"Resources");
} }
} }

2
src/Network/VehicleData.cpp Normal file → Executable file
View File

@ -8,7 +8,7 @@
#include "Zlib/Compressor.h" #include "Zlib/Compressor.h"
#include "Network/network.h" #include "Network/network.h"
#include <WS2tcpip.h> #include <ws2tcpip.h>
#include "Logger.h" #include "Logger.h"
#include <string> #include <string>
#include <set> #include <set>

4
src/Network/VehicleEvent.cpp Normal file → Executable file
View File

@ -10,7 +10,7 @@
#include <vector> #include <vector>
#include "Logger.h" #include "Logger.h"
#include <iostream> #include <iostream>
#include <WS2tcpip.h> #include <ws2tcpip.h>
#include <Zlib/Compressor.h> #include <Zlib/Compressor.h>
#include "Network/network.h" #include "Network/network.h"
@ -133,7 +133,7 @@ void TCPClientMain(const std::string& IP,int Port){
RetCode = connect(TCPSock, (SOCKADDR *) &ServerAddr, sizeof(ServerAddr)); RetCode = connect(TCPSock, (SOCKADDR *) &ServerAddr, sizeof(ServerAddr));
if(RetCode != 0){ if(RetCode != 0){
UlStatus = "UlConnection Failed!"; UlStatus = "UlConnection Failed!";
std::cout << "Client: connect failed! Error code: " << WSAGetLastError() << std::endl; error("Client: connect failed! Error code: " + std::to_string(WSAGetLastError()));
KillSocket(TCPSock); KillSocket(TCPSock);
WSACleanup(); WSACleanup();
Terminate = true; Terminate = true;

635
src/Security/BeamNG.cpp Normal file → Executable file
View File

@ -1,318 +1,317 @@
// Copyright (c) 2019-present Anonymous275. // Copyright (c) 2019-present Anonymous275.
// BeamMP Launcher code is not in the public domain and is not free software. // BeamMP Launcher code is not in the public domain and is not free software.
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. // One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. // Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
/// ///
/// Created by Anonymous275 on 7/18/2020 /// Created by Anonymous275 on 7/18/2020
/// ///
#include <filesystem> #include <filesystem>
#include <Windows.h> #include <windows.h>
#include "Logger.h" #include "Logger.h"
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <thread> #include <thread>
#include <ShlDisp.h>
#define MAX_KEY_LENGTH 255
#define MAX_KEY_LENGTH 255 #define MAX_VALUE_NAME 16383
#define MAX_VALUE_NAME 16383
int TraceBack = 0;
int TraceBack = 0; std::string GameDir;
std::string GameDir;
void lowExit(int code){
void lowExit(int code){ TraceBack = 0;
TraceBack = 0; std::string msg =
std::string msg = "Failed to find the game please launch it. Report this if the issue persists code ";
"Failed to find the game please launch it. Report this if the issue persists code "; error(msg+std::to_string(code));
error(msg+std::to_string(code)); std::this_thread::sleep_for(std::chrono::seconds(10));
std::this_thread::sleep_for(std::chrono::seconds(10)); exit(2);
exit(2); }
} void Exit(int code){
void Exit(int code){ TraceBack = 0;
TraceBack = 0; std::string msg =
std::string msg = "Sorry. We do not support cracked copies report this if you believe this is a mistake code ";
"Sorry. We do not support cracked copies report this if you believe this is a mistake code "; error(msg+std::to_string(code));
error(msg+std::to_string(code)); std::this_thread::sleep_for(std::chrono::seconds(10));
std::this_thread::sleep_for(std::chrono::seconds(10)); exit(3);
exit(3); }
} void SteamExit(int code){
void SteamExit(int code){ TraceBack = 0;
TraceBack = 0; std::string msg =
std::string msg = "Illegal steam modifications detected report this if you believe this is a mistake code ";
"Illegal steam modifications detected report this if you believe this is a mistake code "; error(msg+std::to_string(code));
error(msg+std::to_string(code)); std::this_thread::sleep_for(std::chrono::seconds(10));
std::this_thread::sleep_for(std::chrono::seconds(10)); exit(4);
exit(4); }
} std::string GetGameDir(){
std::string GetGameDir(){ if(TraceBack != 4)Exit(0);
if(TraceBack != 4)Exit(0); return GameDir.substr(0,GameDir.find_last_of('\\'));
return GameDir.substr(0,GameDir.find_last_of('\\')); }
} LONG OpenKey(HKEY root,const char* path,PHKEY hKey){
LONG OpenKey(HKEY root,const char* path,PHKEY hKey){ return RegOpenKeyEx(root, reinterpret_cast<LPCSTR>(path), 0, KEY_READ, hKey);
return RegOpenKeyEx(root, reinterpret_cast<LPCSTR>(path), 0, KEY_READ, hKey); }
} std::string QueryKey(HKEY hKey,int ID){
std::string QueryKey(HKEY hKey,int ID){ TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name
TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name DWORD cbName; // size of name string
DWORD cbName; // size of name string TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name
TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name DWORD cchClassName = MAX_PATH; // size of class string
DWORD cchClassName = MAX_PATH; // size of class string DWORD cSubKeys=0; // number of subkeys
DWORD cSubKeys=0; // number of subkeys DWORD cbMaxSubKey; // longest subkey size
DWORD cbMaxSubKey; // longest subkey size DWORD cchMaxClass; // longest class string
DWORD cchMaxClass; // longest class string DWORD cValues; // number of values for key
DWORD cValues; // number of values for key DWORD cchMaxValue; // longest value name
DWORD cchMaxValue; // longest value name DWORD cbMaxValueData; // longest value data
DWORD cbMaxValueData; // longest value data DWORD cbSecurityDescriptor; // size of security descriptor
DWORD cbSecurityDescriptor; // size of security descriptor FILETIME ftLastWriteTime; // last write time
FILETIME ftLastWriteTime; // last write time
DWORD i, retCode;
DWORD i, retCode;
TCHAR achValue[MAX_VALUE_NAME];
TCHAR achValue[MAX_VALUE_NAME]; DWORD cchValue = MAX_VALUE_NAME;
DWORD cchValue = MAX_VALUE_NAME;
retCode = RegQueryInfoKey(
retCode = RegQueryInfoKey( hKey, // key handle
hKey, // key handle achClass, // buffer for class name
achClass, // buffer for class name &cchClassName, // size of class string
&cchClassName, // size of class string nullptr, // reserved
nullptr, // reserved &cSubKeys, // number of subkeys
&cSubKeys, // number of subkeys &cbMaxSubKey, // longest subkey size
&cbMaxSubKey, // longest subkey size &cchMaxClass, // longest class string
&cchMaxClass, // longest class string &cValues, // number of values for this key
&cValues, // number of values for this key &cchMaxValue, // longest value name
&cchMaxValue, // longest value name &cbMaxValueData, // longest value data
&cbMaxValueData, // longest value data &cbSecurityDescriptor, // security descriptor
&cbSecurityDescriptor, // security descriptor &ftLastWriteTime); // last write time
&ftLastWriteTime); // last write time
BYTE* buffer = new BYTE[cbMaxValueData];
BYTE* buffer = new BYTE[cbMaxValueData]; ZeroMemory(buffer, cbMaxValueData);
ZeroMemory(buffer, cbMaxValueData); if (cSubKeys){
if (cSubKeys){ for (i=0; i<cSubKeys; i++){
for (i=0; i<cSubKeys; i++){ cbName = MAX_KEY_LENGTH;
cbName = MAX_KEY_LENGTH; retCode = RegEnumKeyEx(hKey, i,achKey,&cbName,nullptr,nullptr,nullptr,&ftLastWriteTime);
retCode = RegEnumKeyEx(hKey, i,achKey,&cbName,nullptr,nullptr,nullptr,&ftLastWriteTime); if (retCode == ERROR_SUCCESS){
if (retCode == ERROR_SUCCESS){ if(strcmp(achKey,"Steam App 284160") == 0){
if(strcmp(achKey,"Steam App 284160") == 0){ return achKey;
return achKey; }
} }
} }
} }
} if (cValues){
if (cValues){ for (i=0, retCode = ERROR_SUCCESS; i<cValues; i++){
for (i=0, retCode = ERROR_SUCCESS; i<cValues; i++){ cchValue = MAX_VALUE_NAME;
cchValue = MAX_VALUE_NAME; achValue[0] = '\0';
achValue[0] = '\0'; retCode = RegEnumValue(hKey, i,achValue,&cchValue,nullptr,nullptr,nullptr,nullptr);
retCode = RegEnumValue(hKey, i,achValue,&cchValue,nullptr,nullptr,nullptr,nullptr); if (retCode == ERROR_SUCCESS ){
if (retCode == ERROR_SUCCESS ){ DWORD lpData = cbMaxValueData;
DWORD lpData = cbMaxValueData; buffer[0] = '\0';
buffer[0] = '\0'; LONG dwRes = RegQueryValueEx(hKey, achValue, nullptr, nullptr, buffer, &lpData);
LONG dwRes = RegQueryValueEx(hKey, achValue, nullptr, nullptr, buffer, &lpData); std::string data = (char *)(buffer);
std::string data = (char *)(buffer); std::string key = achValue;
std::string key = achValue;
switch (ID){
switch (ID){ case 1: if(key == "SteamExe"){
case 1: if(key == "SteamExe"){ auto p = data.find_last_of("/\\");
auto p = data.find_last_of("/\\"); if(p != std::string::npos){
if(p != std::string::npos){ return data.substr(0,p);
return data.substr(0,p); }
} }
} break;
break; case 2: if(key == "Name" && data == "BeamNG.drive")return data;break;
case 2: if(key == "Name" && data == "BeamNG.drive")return data;break; case 3: if(key == "rootpath")return data;break;
case 3: if(key == "rootpath")return data;break; case 4: if(key == "userpath_override")return data;
case 4: if(key == "userpath_override")return data; case 5: if(key == "Personal")return data;
case 5: if(key == "Personal")return data; default: break;
default: break; }
} }
} }
} }
} delete [] buffer;
delete [] buffer; return "";
return ""; }
} namespace fs = std::filesystem;
namespace fs = std::filesystem;
bool NameValid(const std::string& N){
bool NameValid(const std::string& N){ if(N == "config" || N == "librarycache"){
if(N == "config" || N == "librarycache"){ return true;
return true; }
} if(N.find_first_not_of("0123456789") == std::string::npos){
if(N.find_first_not_of("0123456789") == std::string::npos){ return true;
return true; }
} return false;
return false; }
} void FileList(std::vector<std::string>&a,const std::string& Path){
void FileList(std::vector<std::string>&a,const std::string& Path){ for (const auto &entry : fs::directory_iterator(Path)) {
for (const auto &entry : fs::directory_iterator(Path)) { const auto& DPath = entry.path();
const auto& DPath = entry.path(); if (!entry.is_directory()) {
if (!entry.is_directory()) { a.emplace_back(DPath.u8string());
a.emplace_back(DPath.u8string()); }else if(NameValid(DPath.filename().u8string())){
}else if(NameValid(DPath.filename().u8string())){ FileList(a, DPath.u8string());
FileList(a, DPath.u8string()); }
} }
} }
} bool Find(const std::string& FName,const std::string& Path){
bool Find(const std::string& FName,const std::string& Path){ std::vector<std::string> FS;
std::vector<std::string> FS; FileList(FS,Path+"\\userdata");
FileList(FS,Path+"\\userdata"); for(std::string&a : FS){
for(std::string&a : FS){ if(a.find(FName) != std::string::npos){
if(a.find(FName) != std::string::npos){ FS.clear();
FS.clear(); return true;
return true; }
} }
} FS.clear();
FS.clear(); return false;
return false; }
} bool FindHack(const std::string& Path){
bool FindHack(const std::string& Path){ bool s = true;
bool s = true; for (const auto &entry : fs::directory_iterator(Path)) {
for (const auto &entry : fs::directory_iterator(Path)) { std::string Name = entry.path().filename().u8string();
std::string Name = entry.path().filename().u8string(); for(char&c : Name)c = char(tolower(c));
for(char&c : Name)c = char(tolower(c)); if(Name == "steam.exe")s = false;
if(Name == "steam.exe")s = false; if(Name.find("greenluma") != -1){
if(Name.find("greenluma") != -1){ error("Found malicious file/folder \"" + Name+"\"");
error("Found malicious file/folder \"" + Name+"\""); return true;
return true; }
} Name.clear();
Name.clear(); }
} return s;
return s; }
} std::vector<std::string> GetID(const std::string& log){
std::vector<std::string> GetID(const std::string& log){ std::string vec,t,r;
std::string vec,t,r; std::vector<std::string> Ret;
std::vector<std::string> Ret; std::ifstream f(log.c_str(), std::ios::binary);
std::ifstream f(log.c_str(), std::ios::binary); f.seekg(0, std::ios_base::end);
f.seekg(0, std::ios_base::end); std::streampos fileSize = f.tellg();
std::streampos fileSize = f.tellg(); vec.resize(size_t(fileSize) + 1);
vec.resize(size_t(fileSize) + 1); f.seekg(0, std::ios_base::beg);
f.seekg(0, std::ios_base::beg); f.read(&vec[0], fileSize);
f.read(&vec[0], fileSize); f.close();
f.close(); std::stringstream ss(vec);
std::stringstream ss(vec); bool S = false;
bool S = false; while (std::getline(ss, t, '{')) {
while (std::getline(ss, t, '{')) { if(!S)S = true;
if(!S)S = true; else{
else{ for(char& c : t){
for(char& c : t){ if(isdigit(c))r += c;
if(isdigit(c))r += c; }
} break;
break; }
} }
} Ret.emplace_back(r);
Ret.emplace_back(r); r.clear();
r.clear(); S = false;
S = false; bool L = true;
bool L = true; while (std::getline(ss, t, '}')) {
while (std::getline(ss, t, '}')) { if(L){
if(L){ L = false;
L = false; continue;
continue; }
} for(char& c : t){
for(char& c : t){ if(c == '"'){
if(c == '"'){ if(!S)S = true;
if(!S)S = true; else{
else{ if(r.length() > 10) {
if(r.length() > 10) { Ret.emplace_back(r);
Ret.emplace_back(r); }
} r.clear();
r.clear(); S = false;
S = false; continue;
continue; }
} }
} if(isdigit(c))r += c;
if(isdigit(c))r += c; }
} }
} vec.clear();
vec.clear(); return Ret;
return Ret; }
} std::string GetManifest(const std::string& Man){
std::string GetManifest(const std::string& Man){ std::string vec;
std::string vec; std::ifstream f(Man.c_str(), std::ios::binary);
std::ifstream f(Man.c_str(), std::ios::binary); f.seekg(0, std::ios_base::end);
f.seekg(0, std::ios_base::end); std::streampos fileSize = f.tellg();
std::streampos fileSize = f.tellg(); vec.resize(size_t(fileSize) + 1);
vec.resize(size_t(fileSize) + 1); f.seekg(0, std::ios_base::beg);
f.seekg(0, std::ios_base::beg); f.read(&vec[0], fileSize);
f.read(&vec[0], fileSize); f.close();
f.close(); std::string ToFind = "\"LastOwner\"\t\t\"";
std::string ToFind = "\"LastOwner\"\t\t\""; int pos = int(vec.find(ToFind));
int pos = int(vec.find(ToFind)); if(pos != -1){
if(pos != -1){ pos += int(ToFind.length());
pos += int(ToFind.length()); vec = vec.substr(pos);
vec = vec.substr(pos); return vec.substr(0,vec.find('\"'));
return vec.substr(0,vec.find('\"')); }else return "";
}else return ""; }
} bool IDCheck(std::string Man, std::string steam){
bool IDCheck(std::string Man, std::string steam){ bool a = false,b = true;
bool a = false,b = true; int pos = int(Man.rfind("steamapps"));
int pos = int(Man.rfind("steamapps")); if(pos == -1)Exit(5);
if(pos == -1)Exit(5); Man = Man.substr(0,pos+9) + "\\appmanifest_284160.acf";
Man = Man.substr(0,pos+9) + "\\appmanifest_284160.acf"; steam += "\\config\\loginusers.vdf";
steam += "\\config\\loginusers.vdf"; if(fs::exists(Man) && fs::exists(steam)){
if(fs::exists(Man) && fs::exists(steam)){ for(const std::string&ID : GetID(steam)){
for(const std::string&ID : GetID(steam)){ if(ID == GetManifest(Man))b = false;
if(ID == GetManifest(Man))b = false; }
} if(b)Exit(6);
if(b)Exit(6); }else a = true;
}else a = true; return a;
return a; }
} void LegitimacyCheck(){
void LegitimacyCheck(){ std::string Result,T;
std::string Result,T; std::string K1 = R"(Software\Valve\Steam)";
std::string K1 = R"(Software\Valve\Steam)"; std::string K2 = R"(Software\Valve\Steam\Apps\284160)";
std::string K2 = R"(Software\Valve\Steam\Apps\284160)"; std::string K3 = R"(Software\BeamNG\BeamNG.drive)";
std::string K3 = R"(Software\BeamNG\BeamNG.drive)"; HKEY hKey;
HKEY hKey;
LONG dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K1.c_str(), &hKey);
LONG dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K1.c_str(), &hKey);
if(dwRegOPenKey == ERROR_SUCCESS) {
if(dwRegOPenKey == ERROR_SUCCESS) { Result = QueryKey(hKey, 1);
Result = QueryKey(hKey, 1); if(Result.empty())Exit(1);
if(Result.empty())Exit(1);
if(fs::exists(Result)){
if(fs::exists(Result)){ if(!Find("284160.json",Result))Exit(2);
if(!Find("284160.json",Result))Exit(2); if(FindHack(Result))SteamExit(1);
if(FindHack(Result))SteamExit(1); }else Exit(3);
}else Exit(3);
T = Result;
T = Result; Result.clear();
Result.clear(); TraceBack++;
TraceBack++; }else Exit(4);
}else Exit(4);
K1.clear();
K1.clear(); RegCloseKey(hKey);
RegCloseKey(hKey); dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K2.c_str(), &hKey);
dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K2.c_str(), &hKey); if(dwRegOPenKey == ERROR_SUCCESS) {
if(dwRegOPenKey == ERROR_SUCCESS) { Result = QueryKey(hKey, 2);
Result = QueryKey(hKey, 2); if(Result.empty())lowExit(1);
if(Result.empty())lowExit(1); TraceBack++;
TraceBack++; }else lowExit(2);
}else lowExit(2); K2.clear();
K2.clear(); RegCloseKey(hKey);
RegCloseKey(hKey); dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K3.c_str(), &hKey);
dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K3.c_str(), &hKey); if(dwRegOPenKey == ERROR_SUCCESS) {
if(dwRegOPenKey == ERROR_SUCCESS) { Result = QueryKey(hKey, 3);
Result = QueryKey(hKey, 3); if(Result.empty())lowExit(3);
if(Result.empty())lowExit(3); if(IDCheck(Result,T))lowExit(5);
if(IDCheck(Result,T))lowExit(5); GameDir = Result;
GameDir = Result; TraceBack++;
TraceBack++; }else lowExit(4);
}else lowExit(4); K3.clear();
K3.clear(); Result.clear();
Result.clear(); RegCloseKey(hKey);
RegCloseKey(hKey); if(TraceBack < 3)exit(-1);
if(TraceBack < 3)exit(-1); }
} std::string CheckVer(const std::string &dir){
std::string CheckVer(const std::string &dir){ std::string temp,Path = dir + "\\integrity.json";
std::string temp,Path = dir + "\\integrity.json"; std::ifstream f(Path.c_str(), std::ios::binary);
std::ifstream f(Path.c_str(), std::ios::binary); int Size = int(std::filesystem::file_size(Path));
int Size = int(std::filesystem::file_size(Path)); std::string vec(Size,0);
std::string vec(Size,0); f.read(&vec[0], Size);
f.read(&vec[0], Size); f.close();
f.close();
vec = vec.substr(vec.find_last_of("version"),vec.find_last_of('"'));
vec = vec.substr(vec.find_last_of("version"),vec.find_last_of('"')); for(const char &a : vec){
for(const char &a : vec){ if(isdigit(a) || a == '.')temp+=a;
if(isdigit(a) || a == '.')temp+=a; }
} return temp;
return temp; }
}

223
src/Security/Login.cpp Normal file → Executable file
View File

@ -1,109 +1,114 @@
// Copyright (c) 2019-present Anonymous275. // Copyright (c) 2019-present Anonymous275.
// BeamMP Launcher code is not in the public domain and is not free software. // BeamMP Launcher code is not in the public domain and is not free software.
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. // One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. // Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
/// ///
/// Created by Anonymous275 on 11/26/2020 /// Created by Anonymous275 on 11/26/2020
/// ///
#include "Curl/http.h" #include "Curl/http.h"
#include <filesystem> #include <filesystem>
#include "Logger.h" #include "Logger.h"
#include <fstream> #include <fstream>
#include "Json.h" #include "Json.h"
using namespace std::filesystem; namespace fs = std::filesystem;
std::string PublicKey; std::string PublicKey;
extern bool LoginAuth; extern bool LoginAuth;
std::string Role; std::string Role;
void UpdateKey(const char* newKey){ void UpdateKey(const char* newKey){
if(newKey){ if(newKey){
std::ofstream Key("key"); std::ofstream Key("key");
if(Key.is_open()){ if(Key.is_open()){
Key << newKey; Key << newKey;
Key.close(); Key.close();
}else fatal("Cannot write to disk!"); }else fatal("Cannot write to disk!");
}else if(exists("key")){ }else if(fs::exists("key")){
remove("key"); remove("key");
} }
} }
/// "username":"value","password":"value" /// "username":"value","password":"value"
/// "Guest":"Name" /// "Guest":"Name"
/// "pk":"private_key" /// "pk":"private_key"
std::string GetFail(const std::string& R){ std::string GetFail(const std::string& R){
std::string DRet = R"({"success":false,"message":)"; std::string DRet = R"({"success":false,"message":)";
DRet += "\""+R+"\"}"; DRet += "\""+R+"\"}";
error(R); error(R);
return DRet; return DRet;
} }
std::string Login(const std::string& fields){ std::string Login(const std::string& fields){
if(fields == "LO"){ if(fields == "LO"){
LoginAuth = false; LoginAuth = false;
UpdateKey(nullptr); UpdateKey(nullptr);
return ""; return "";
} }
info("Attempting to authenticate..."); info("Attempting to authenticate...");
std::string Buffer = PostHTTP("https://auth.beammp.com/userlogin", fields); std::string Buffer = PostHTTP("https://auth.beammp.com/userlogin", fields);
json::Document d; json::Document d;
d.Parse(Buffer.c_str()); d.Parse(Buffer.c_str());
if(Buffer == "-1"){ if(Buffer == "-1"){
return GetFail("Failed to communicate with the auth system!"); return GetFail("Failed to communicate with the auth system!");
} }
if (Buffer.at(0) != '{' || d.HasParseError()) { if (Buffer.at(0) != '{' || d.HasParseError()) {
return GetFail("Invalid answer from authentication servers, please try again later!"); error(Buffer);
} return GetFail("Invalid answer from authentication servers, please try again later!");
if(!d["success"].IsNull() && d["success"].GetBool()){ }
LoginAuth = true; if(!d["success"].IsNull() && d["success"].GetBool()){
if(!d["private_key"].IsNull()){ LoginAuth = true;
UpdateKey(d["private_key"].GetString()); if(!d["private_key"].IsNull()){
} UpdateKey(d["private_key"].GetString());
if(!d["public_key"].IsNull()){ }
PublicKey = d["public_key"].GetString(); if(!d["public_key"].IsNull()){
} PublicKey = d["public_key"].GetString();
info("Authentication successful!"); }
}else info("Authentication failed!"); info("Authentication successful!");
if(!d["message"].IsNull()){ }else info("Authentication failed!");
d.RemoveMember("private_key"); if(!d["message"].IsNull()){
d.RemoveMember("public_key"); d.RemoveMember("private_key");
rapidjson::StringBuffer buffer; d.RemoveMember("public_key");
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); rapidjson::StringBuffer buffer;
d.Accept(writer); rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
return buffer.GetString(); d.Accept(writer);
} return buffer.GetString();
return GetFail("Invalid message parsing!"); }
} return GetFail("Invalid message parsing!");
}
void CheckLocalKey(){
if(exists("key") && file_size("key") < 100){ void CheckLocalKey(){
std::ifstream Key("key"); if(fs::exists("key") && fs::file_size("key") < 100){
if(Key.is_open()) { std::ifstream Key("key");
auto Size = file_size("key"); if(Key.is_open()) {
std::string Buffer(Size, 0); auto Size = fs::file_size("key");
Key.read(&Buffer[0], Size); std::string Buffer(Size, 0);
Key.close(); Key.read(&Buffer[0], Size);
Buffer = PostHTTP("https://auth.beammp.com/userlogin", R"({"pk":")"+Buffer+"\"}"); Key.close();
json::Document d;
d.Parse(Buffer.c_str()); Buffer = PostHTTP("https://auth.beammp.com/userlogin", R"({"pk":")"+Buffer+"\"}");
if (Buffer == "-1" || Buffer.at(0) != '{' || d.HasParseError()) {
fatal("Invalid answer from authentication servers, please try again later!"); json::Document d;
} d.Parse(Buffer.c_str());
if(d["success"].GetBool()){ if (Buffer == "-1" || Buffer.at(0) != '{' || d.HasParseError()) {
LoginAuth = true; error(Buffer);
UpdateKey(d["private_key"].GetString()); fatal("Invalid answer from authentication servers, please try again later!");
PublicKey = d["public_key"].GetString(); }
Role = d["role"].GetString(); if(d["success"].GetBool()){
}else{ LoginAuth = true;
info("Auto-Authentication unsuccessful please re-login!"); UpdateKey(d["private_key"].GetString());
UpdateKey(nullptr); PublicKey = d["public_key"].GetString();
} Role = d["role"].GetString();
}else{ //info(Role);
warn("Could not open saved key!"); }else{
UpdateKey(nullptr); info("Auto-Authentication unsuccessful please re-login!");
} UpdateKey(nullptr);
}else UpdateKey(nullptr); }
} }else{
warn("Could not open saved key!");
UpdateKey(nullptr);
}
}else UpdateKey(nullptr);
}

397
src/Startup.cpp Normal file → Executable file
View File

@ -1,208 +1,191 @@
// Copyright (c) 2019-present Anonymous275. // Copyright (c) 2019-present Anonymous275.
// BeamMP Launcher code is not in the public domain and is not free software. // BeamMP Launcher code is not in the public domain and is not free software.
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. // One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. // Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
/// ///
/// Created by Anonymous275 on 7/16/2020 /// Created by Anonymous275 on 7/16/2020
/// ///
#include "Discord/discord_info.h"
#include "Network/network.h"
#include "Security/Init.h" #include "Discord/discord_info.h"
#include "Curl/http.h" #include "Network/network.h"
#include <curl/curl.h> #include "Security/Init.h"
#include <filesystem> #include "Curl/http.h"
#include "Startup.h" #include <curl/curl.h>
#include "Logger.h" #include <filesystem>
#include <thread> #include "Startup.h"
#include "Logger.h"
extern int TraceBack; #include <thread>
bool Dev = false;
namespace fs = std::filesystem; extern int TraceBack;
bool Dev = false;
std::string GetEN(){ namespace fs = std::filesystem;
return "BeamMP-Launcher.exe";
} std::string GetEN(){
std::string GetVer(){ return "BeamMP-Launcher.exe";
return "1.81"; }
} std::string GetVer(){
std::string GetPatch(){ return "1.80";
return ".0"; }
} std::string GetPatch(){
std::string GetEP(char*P){ return ".95";
static std::string Ret = [&](){ }
std::string path(P); std::string GetEP(char*P){
return path.substr(0, path.find_last_of("\\/") + 1); static std::string Ret = [&](){
} (); std::string path(P);
return Ret; return path.substr(0, path.find_last_of("\\/") + 1);
} } ();
void ReLaunch(int argc,char*args[]){ return Ret;
std::string Arg; }
for(int c = 2; c <= argc; c++){ void ReLaunch(int argc,char*args[]){
Arg += " "; std::string Arg;
Arg += args[c-1]; for(int c = 2; c <= argc; c++){
} Arg += " ";
system("cls"); Arg += args[c-1];
ShellExecute(nullptr,"runas",(GetEP() + GetEN()).c_str(),Arg.c_str(),nullptr,SW_SHOWNORMAL); }
ShowWindow(GetConsoleWindow(),0); system("cls");
std::this_thread::sleep_for(std::chrono::seconds(1)); ShellExecute(nullptr,"runas",(GetEP() + GetEN()).c_str(),Arg.c_str(),nullptr,SW_SHOWNORMAL);
exit(1); ShowWindow(GetConsoleWindow(),0);
} std::this_thread::sleep_for(std::chrono::seconds(1));
void URelaunch(int argc,char* args[]){ exit(1);
std::string Arg; }
for(int c = 2; c <= argc; c++){ void URelaunch(int argc,char* args[]){
Arg += " "; std::string Arg;
Arg += args[c-1]; for(int c = 2; c <= argc; c++){
} Arg += " ";
ShellExecute(nullptr,"open",(GetEP() + GetEN()).c_str(),Arg.c_str(),nullptr,SW_SHOWNORMAL); Arg += args[c-1];
ShowWindow(GetConsoleWindow(),0); }
std::this_thread::sleep_for(std::chrono::seconds(1)); ShellExecute(nullptr,"open",(GetEP() + GetEN()).c_str(),Arg.c_str(),nullptr,SW_SHOWNORMAL);
exit(1); ShowWindow(GetConsoleWindow(),0);
} std::this_thread::sleep_for(std::chrono::seconds(1));
void CheckName(int argc,char* args[]){ exit(1);
struct stat info{}; }
std::string DN = GetEN(),CDir = args[0],FN = CDir.substr(CDir.find_last_of('\\')+1); void CheckName(int argc,char* args[]){
if(FN != DN){ std::string DN = GetEN(),CDir = args[0],FN = CDir.substr(CDir.find_last_of('\\')+1);
if(stat(DN.c_str(),&info)==0)remove(DN.c_str()); if(FN != DN){
if(stat(DN.c_str(),&info)==0)ReLaunch(argc,args); if(fs::exists(DN))remove(DN.c_str());
std::rename(FN.c_str(), DN.c_str()); if(fs::exists(DN))ReLaunch(argc,args);
URelaunch(argc,args); std::rename(FN.c_str(), DN.c_str());
} URelaunch(argc,args);
} }
}
/// Deprecated
void RequestRole(){ void CheckForUpdates(int argc,char*args[],const std::string& CV){
/*auto NPos = std::string::npos; std::string link = "https://beammp.com/builds/launcher?version=true";
std::string HTTP_Result = HTTP_REQUEST("https://beammp.com/entitlement?did="+GetDID()+"&t=l",443); std::string HTTP = HTTP_REQUEST(link,443);
if(HTTP_Result == "-1"){ bool fallback = false;
HTTP_Result = HTTP_REQUEST("https://backup1.beammp.com/entitlement?did="+GetDID()+"&t=l",443); if(HTTP.find_first_of("0123456789") == std::string::npos){
if(HTTP_Result == "-1") { link = "https://backup1.beammp.com/builds/launcher?version=true";
fatal("Sorry Backend System Outage! Don't worry it will back on soon!"); HTTP = HTTP_REQUEST(link,443);
} fallback = true;
} if(HTTP.find_first_of("0123456789") == std::string::npos) {
if(HTTP_Result.find("\"MDEV\"") != NPos || HTTP_Result.find("\"CON\"") != NPos){ fatal("Primary Servers Offline! sorry for the inconvenience!");
Dev = true; }
} }
if(HTTP_Result.find("Error") != NPos){ if(fallback){
fatal("Sorry You need to be in the official BeamMP Discord to proceed! https://discord.gg/beammp"); link = "https://backup1.beammp.com/builds/launcher?download=true";
} }else link = "https://beammp.com/builds/launcher?download=true";
info("Client Connected!");*/
} std::string EP(GetEP() + GetEN()), Back(GetEP() + "BeamMP-Launcher.back");
void CheckForUpdates(int argc,char*args[],const std::string& CV){ if(fs::exists(Back))remove(Back.c_str());
std::string link = "https://beammp.com/builds/launcher?version=true";
std::string HTTP = HTTP_REQUEST(link,443); if(HTTP > CV){
bool fallback = false; system("cls");
if(HTTP.find_first_of("0123456789") == std::string::npos){ info("Update found!");
link = "https://backup1.beammp.com/builds/launcher?version=true"; info("Updating...");
HTTP = HTTP_REQUEST(link,443); if(std::rename(EP.c_str(), Back.c_str()))error("failed creating a backup!");
fallback = true; int i = Download(link, EP,true);
if(HTTP.find_first_of("0123456789") == std::string::npos) { if(i != -1){
fatal("Primary Servers Offline! sorry for the inconvenience!"); error("Launcher Update failed! trying again... code : " + std::to_string(i));
} std::this_thread::sleep_for(std::chrono::seconds(2));
} int i2 = Download(link, EP,true);
if(fallback){ if(i2 != -1){
link = "https://backup1.beammp.com/builds/launcher?download=true"; error("Launcher Update failed! code : " + std::to_string(i2));
}else link = "https://beammp.com/builds/launcher?download=true"; std::this_thread::sleep_for(std::chrono::seconds(5));
ReLaunch(argc,args);
std::string EP(GetEP() + GetEN()), Back(GetEP() + "BeamMP-Launcher.back"); }
}
if(fs::exists(Back))remove(Back.c_str()); URelaunch(argc,args);
}else info("Launcher version is up to date");
if(HTTP > CV){ TraceBack++;
system("cls"); }
info("Update found!");
info("Updating..."); void CustomPort(int argc, char* argv[]){
if(std::rename(EP.c_str(), Back.c_str()))error("failed creating a backup!"); if(argc > 1){
int i = Download(link, EP,true); std::string Port = argv[1];
if(i != -1){ if(Port.find_first_not_of("0123456789") == std::string::npos){
error("Launcher Update failed! trying again... code : " + std::to_string(i)); if(std::stoi(Port) > 1000){
std::this_thread::sleep_for(std::chrono::seconds(2)); DEFAULT_PORT = std::stoi(Port);
int i2 = Download(link, EP,true); warn("Running on custom port : " + std::to_string(DEFAULT_PORT));
if(i2 != -1){ }
error("Launcher Update failed! code : " + std::to_string(i2)); }
std::this_thread::sleep_for(std::chrono::seconds(5)); if(argc > 2)Dev = true;
ReLaunch(argc,args); }
} }
} void InitLauncher(int argc, char* argv[]) {
URelaunch(argc,args); system("cls");
}else info("Launcher version is up to date"); curl_global_init(CURL_GLOBAL_DEFAULT);
TraceBack++; SetConsoleTitleA(("BeamMP Launcher v" + std::string(GetVer()) + GetPatch()).c_str());
} InitLog();
CheckName(argc, argv);
void CustomPort(int argc, char* argv[]){ CheckLocalKey();
if(argc > 1){ ConfigInit();
std::string Port = argv[1]; CustomPort(argc, argv);
if(Port.find_first_not_of("0123456789") == std::string::npos){ Discord_Main();
if(std::stoi(Port) > 1000){ CheckForUpdates(argc, argv, std::string(GetVer()) + GetPatch());
DEFAULT_PORT = std::stoi(Port);
warn("Running on custom port : " + std::to_string(DEFAULT_PORT)); }
} size_t DirCount(const std::filesystem::path& path){
} return (size_t)std::distance(std::filesystem::directory_iterator{path}, std::filesystem::directory_iterator{});
if(argc > 2)Dev = true; }
} void CheckMP(const std::string& Path) {
} if (!fs::exists(Path))return;
void InitLauncher(int argc, char* argv[]) { size_t c = DirCount(fs::path(Path));
system("cls"); if (c > 3) {
curl_global_init(CURL_GLOBAL_DEFAULT); warn(std::to_string(c - 1) + " multiplayer mods will be wiped from mods/multiplayer! Close this if you don't want that!");
SetConsoleTitleA(("BeamMP Launcher v" + std::string(GetVer()) + GetPatch()).c_str()); std::this_thread::sleep_for(std::chrono::seconds(15));
InitLog(); }
CheckName(argc, argv); try {
CheckLocalKey(); //will replace RequestRole for (auto& p : fs::directory_iterator(Path)){
Discord_Main(); if(p.exists() && !p.is_directory()){
//Dev = true; std::string Name = p.path().filename().u8string();
//RequestRole(); for(char&Ch : Name)Ch = char(tolower(Ch));
if(Name != "beammp.zip")fs::remove(p.path());
CustomPort(argc, argv); }
CheckForUpdates(argc, argv, std::string(GetVer()) + GetPatch()); }
} } catch (...) {
size_t DirCount(const std::filesystem::path& path){ fatal("Please close the game, and try again!");
return (size_t)std::distance(std::filesystem::directory_iterator{path}, std::filesystem::directory_iterator{}); }
}
void CheckMP(const std::string& Path) { }
if (!fs::exists(Path))return; void PreGame(const std::string& GamePath){
size_t c = DirCount(fs::path(Path)); const std::string CurrVer("0.21.4.0");
if (c > 3) { std::string GameVer = CheckVer(GamePath);
warn(std::to_string(c - 1) + " multiplayer mods will be wiped from mods/multiplayer! Close this if you don't want that!"); info("Game Version : " + GameVer);
std::this_thread::sleep_for(std::chrono::seconds(15)); if(GameVer < CurrVer){
} fatal("Game version is old! Please update.");
try { }else if(GameVer > CurrVer){
for (auto& p : fs::directory_iterator(Path)){ warn("Game is newer than recommended, multiplayer may not work as intended!");
if(p.exists() && !p.is_directory()){ }
std::string Name = p.path().filename().u8string(); CheckMP(GetGamePath() + "mods/multiplayer");
for(char&Ch : Name)Ch = char(tolower(Ch));
if(Name != "beammp.zip")fs::remove(p.path()); if(!Dev) {
} info("Downloading mod...");
} try {
} catch (...) { if (!fs::exists(GetGamePath() + "mods/multiplayer")) {
fatal("Please close the game, and try again!"); fs::create_directories(GetGamePath() + "mods/multiplayer");
} }
}catch(std::exception&e){
} fatal(e.what());
void PreGame(const std::string& GamePath){ }
const std::string CurrVer("0.21.3.0");
std::string GameVer = CheckVer(GamePath); /* Download("https://backend.beammp.com/builds/client?download=true"
info("Game Version : " + GameVer); "&pk=" + PublicKey +
if(GameVer < CurrVer){ "&branch=" + Branch, GetGamePath() + R"(mods\multiplayer\BeamMP.zip)", true);*/
fatal("Game version is old! Please update.");
}else if(GameVer > CurrVer){ Download("https://beammp.com/builds/client", GetGamePath() + R"(mods\multiplayer\BeamMP.zip)", true);
warn("Game is newer than recommended, multiplayer may not work as intended!"); info("Download Complete!");
} }
CheckMP(GetGamePath() + "mods/multiplayer");
if(!Dev) {
info("Downloading mod...");
try {
if (!fs::exists(GetGamePath() + "mods/multiplayer")) {
fs::create_directories(GetGamePath() + "mods/multiplayer");
}
}catch(std::exception&e){
fatal(e.what());
}
Download("https://beammp.com/builds/client", GetGamePath() + R"(mods\multiplayer\BeamMP.zip)", true);
info("Download Complete!");
}
/*debug("Name : " + GetDName());
debug("Discriminator : " + GetDTag());
debug("Unique ID : " + GetDID());*/
} }

0
src/main.cpp Normal file → Executable file
View File