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

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 "Logger.h"
#include <iostream>
#include <cstring>
#include <thread>
#include <ctime>

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

@@ -6,7 +6,7 @@
/// Created by Anonymous275 on 7/19/2020
///
#include <Windows.h>
#include <windows.h>
#include "Startup.h"
#include "Logger.h"
#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 "Curl/http.h"
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include "Startup.h"
#include "Logger.h"
#include <charconv>
@@ -242,9 +242,13 @@ int Handle(EXCEPTION_POINTERS *ep){
void CoreNetwork(){
while(TraceBack >= 4){
#ifndef __MINGW32__
__try{
#endif
CoreMain();
#ifndef __MINGW32__
}__except(Handle(GetExceptionInformation())){}
#endif
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
///
#include "Network/network.h"
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include "Logger.h"
#include <charconv>
#include <string>
#include <thread>
#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 CServer = true;
SOCKET CSocket = -1;

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

@@ -1,140 +1,144 @@
// Copyright (c) 2019-present Anonymous275.
// 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.
// 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
///
#include <curl/curl.h>
#include <iostream>
#include <Logger.h>
#include <mutex>
class CurlManager{
public:
CurlManager(){
curl = curl_easy_init();
}
~CurlManager(){
curl_easy_cleanup(curl);
}
inline CURL* Get(){
return 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);
return size * nmemb;
}
std::string HTTP_REQUEST(const std::string& IP,int port){
static thread_local CurlManager M;
static std::mutex Lock;
std::scoped_lock Guard(Lock);
CURL *curl = M.Get();
CURLcode res;
std::string readBuffer;
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, IP.c_str());
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl, CURLOPT_PORT, port);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
res = curl_easy_perform(curl);
if(res != CURLE_OK)return "-1";
}
return readBuffer;
}
int nb_bar;
double last_progress, progress_bar_adv;
bool Downloaded;
int progress_bar (void *bar, double t, double d){
if(t > 0 && last_progress != round(d/t*100)){
nb_bar = 25;
progress_bar_adv = round(d/t*nb_bar);
std::cout<<"\r";
std::cout<< "Progress : [ ";
std::cout<<round(d/t*100);
std::cout << "% ] [";
int i;
for(i = 0; i <= progress_bar_adv; i++)std::cout<<"#";
for(i = 0; i < nb_bar - progress_bar_adv; i++)std::cout<<".";
std::cout<<"]";
last_progress = round(d/t*100);
if(round(d/t*100) == 100){
Downloaded = true;
}
}
return 0;
}
struct File {
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;
if(!out->stream) {
fopen_s(&out->stream,out->filename,"wb");
if(!out->stream)return -1;
}
return fwrite(buffer, size, nmemb, out->stream);
}
int Download(const std::string& URL,const std::string& Path,bool close){
static thread_local CurlManager M;
CURL *curl = M.Get();
CURLcode res;
struct File file = {Path.c_str(),nullptr};
Downloaded = false;
if(curl){
curl_easy_setopt(curl, CURLOPT_URL,URL.c_str());
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_bar);
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
res = curl_easy_perform(curl);
if(res != CURLE_OK){
return res;
}
}
if(file.stream)fclose(file.stream);
if(!Downloaded){
remove(Path.c_str());
fatal("Failed to download please try again later!");
}
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"};
static thread_local CurlManager M;
static std::mutex Lock;
std::scoped_lock Guard(Lock);
CURL* curl = M.Get();
CURLcode res;
std::string readBuffer;
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, IP.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, Fields.size());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, Fields.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
res = curl_easy_perform(curl);
if (res != CURLE_OK)
return "-1";
}
return readBuffer;
// Copyright (c) 2019-present Anonymous275.
// 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.
// 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
///
#include <curl/curl.h>
#include <iostream>
#include <Logger.h>
#include <mutex>
#include <cmath>
class CurlManager{
public:
CurlManager(){
curl = curl_easy_init();
}
~CurlManager(){
curl_easy_cleanup(curl);
}
inline CURL* Get(){
return 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);
return size * nmemb;
}
std::string HTTP_REQUEST(const std::string& IP,int port){
static thread_local CurlManager M;
static std::mutex Lock;
std::scoped_lock Guard(Lock);
CURL *curl = M.Get();
CURLcode res;
std::string readBuffer;
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, IP.c_str());
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl, CURLOPT_PORT, port);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
res = curl_easy_perform(curl);
if(res != CURLE_OK)return "-1";
}
return readBuffer;
}
int nb_bar;
double last_progress, progress_bar_adv;
bool Downloaded;
int progress_bar (void *bar, double t, double d){
if(t > 0 && last_progress != round(d/t*100)){
nb_bar = 25;
progress_bar_adv = round(d/t*nb_bar);
std::cout<<"\r";
std::cout<< "Progress : [ ";
std::cout<<round(d/t*100);
std::cout << "% ] [";
int i;
for(i = 0; i <= progress_bar_adv; i++)std::cout<<"#";
for(i = 0; i < nb_bar - progress_bar_adv; i++)std::cout<<".";
std::cout<<"]";
last_progress = round(d/t*100);
if(round(d/t*100) == 100){
Downloaded = true;
}
}
return 0;
}
struct File {
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;
if(!out->stream) {
fopen_s(&out->stream,out->filename,"wb");
if(!out->stream)return -1;
}
return fwrite(buffer, size, nmemb, out->stream);
}
int Download(const std::string& URL,const std::string& Path,bool close){
static thread_local CurlManager M;
CURL *curl = M.Get();
CURLcode res;
struct File file = {Path.c_str(),nullptr};
Downloaded = false;
if(curl){
curl_easy_setopt(curl, CURLOPT_URL,URL.c_str());
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_bar);
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
res = curl_easy_perform(curl);
if(res != CURLE_OK){
return res;
}
}
if(file.stream)fclose(file.stream);
if(!Downloaded){
remove(Path.c_str());
fatal("Failed to download please try again later!");
}
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"};
static thread_local CurlManager M;
static std::mutex Lock;
std::scoped_lock Guard(Lock);
CURL* curl = M.Get();
CURLcode res;
std::string readBuffer;
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, IP.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, Fields.size());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, Fields.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
//curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
res = curl_easy_perform(curl);
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 <WS2tcpip.h>
#include <ws2tcpip.h>
#include <filesystem>
#include "Startup.h"
#include "Logger.h"
@@ -20,6 +19,7 @@
#include <atomic>
#include <vector>
#include <future>
#include <cmath>
namespace fs = std::filesystem;
std::string ListOfMods;
@@ -37,8 +37,7 @@ std::vector<std::string> Split(const std::string& String,const std::string& deli
}
void CheckForDir(){
struct stat info{};
if(stat( "Resources", &info) != 0){
if(!fs::exists("Resources")){
_wmkdir(L"Resources");
}
}

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

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

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

@@ -10,7 +10,7 @@
#include <vector>
#include "Logger.h"
#include <iostream>
#include <WS2tcpip.h>
#include <ws2tcpip.h>
#include <Zlib/Compressor.h>
#include "Network/network.h"
@@ -133,7 +133,7 @@ void TCPClientMain(const std::string& IP,int Port){
RetCode = connect(TCPSock, (SOCKADDR *) &ServerAddr, sizeof(ServerAddr));
if(RetCode != 0){
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);
WSACleanup();
Terminate = true;

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

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

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

@@ -1,109 +1,114 @@
// Copyright (c) 2019-present Anonymous275.
// 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.
// 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
///
#include "Curl/http.h"
#include <filesystem>
#include "Logger.h"
#include <fstream>
#include "Json.h"
using namespace std::filesystem;
std::string PublicKey;
extern bool LoginAuth;
std::string Role;
void UpdateKey(const char* newKey){
if(newKey){
std::ofstream Key("key");
if(Key.is_open()){
Key << newKey;
Key.close();
}else fatal("Cannot write to disk!");
}else if(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+"\"}";
error(R);
return DRet;
}
std::string Login(const std::string& fields){
if(fields == "LO"){
LoginAuth = false;
UpdateKey(nullptr);
return "";
}
info("Attempting to authenticate...");
std::string Buffer = PostHTTP("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()) {
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();
}
info("Authentication successful!");
}else info("Authentication failed!");
if(!d["message"].IsNull()){
d.RemoveMember("private_key");
d.RemoveMember("public_key");
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
d.Accept(writer);
return buffer.GetString();
}
return GetFail("Invalid message parsing!");
}
void CheckLocalKey(){
if(exists("key") && file_size("key") < 100){
std::ifstream Key("key");
if(Key.is_open()) {
auto Size = file_size("key");
std::string Buffer(Size, 0);
Key.read(&Buffer[0], Size);
Key.close();
Buffer = PostHTTP("https://auth.beammp.com/userlogin", R"({"pk":")"+Buffer+"\"}");
json::Document d;
d.Parse(Buffer.c_str());
if (Buffer == "-1" || Buffer.at(0) != '{' || d.HasParseError()) {
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();
Role = d["role"].GetString();
}else{
info("Auto-Authentication unsuccessful please re-login!");
UpdateKey(nullptr);
}
}else{
warn("Could not open saved key!");
UpdateKey(nullptr);
}
}else UpdateKey(nullptr);
}
// Copyright (c) 2019-present Anonymous275.
// 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.
// 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
///
#include "Curl/http.h"
#include <filesystem>
#include "Logger.h"
#include <fstream>
#include "Json.h"
namespace fs = std::filesystem;
std::string PublicKey;
extern bool LoginAuth;
std::string Role;
void UpdateKey(const char* newKey){
if(newKey){
std::ofstream Key("key");
if(Key.is_open()){
Key << newKey;
Key.close();
}else 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+"\"}";
error(R);
return DRet;
}
std::string Login(const std::string& fields){
if(fields == "LO"){
LoginAuth = false;
UpdateKey(nullptr);
return "";
}
info("Attempting to authenticate...");
std::string Buffer = PostHTTP("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()) {
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();
}
info("Authentication successful!");
}else info("Authentication failed!");
if(!d["message"].IsNull()){
d.RemoveMember("private_key");
d.RemoveMember("public_key");
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
d.Accept(writer);
return buffer.GetString();
}
return GetFail("Invalid message parsing!");
}
void 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], Size);
Key.close();
Buffer = PostHTTP("https://auth.beammp.com/userlogin", R"({"pk":")"+Buffer+"\"}");
json::Document d;
d.Parse(Buffer.c_str());
if (Buffer == "-1" || Buffer.at(0) != '{' || d.HasParseError()) {
error(Buffer);
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();
Role = d["role"].GetString();
//info(Role);
}else{
info("Auto-Authentication unsuccessful please re-login!");
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.
// 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.
// 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
///
#include "Discord/discord_info.h"
#include "Network/network.h"
#include "Security/Init.h"
#include "Curl/http.h"
#include <curl/curl.h>
#include <filesystem>
#include "Startup.h"
#include "Logger.h"
#include <thread>
extern int TraceBack;
bool Dev = false;
namespace fs = std::filesystem;
std::string GetEN(){
return "BeamMP-Launcher.exe";
}
std::string GetVer(){
return "1.81";
}
std::string GetPatch(){
return ".0";
}
std::string GetEP(char*P){
static std::string Ret = [&](){
std::string path(P);
return path.substr(0, path.find_last_of("\\/") + 1);
} ();
return Ret;
}
void ReLaunch(int argc,char*args[]){
std::string Arg;
for(int c = 2; c <= argc; c++){
Arg += " ";
Arg += args[c-1];
}
system("cls");
ShellExecute(nullptr,"runas",(GetEP() + GetEN()).c_str(),Arg.c_str(),nullptr,SW_SHOWNORMAL);
ShowWindow(GetConsoleWindow(),0);
std::this_thread::sleep_for(std::chrono::seconds(1));
exit(1);
}
void URelaunch(int argc,char* args[]){
std::string Arg;
for(int c = 2; c <= argc; c++){
Arg += " ";
Arg += args[c-1];
}
ShellExecute(nullptr,"open",(GetEP() + GetEN()).c_str(),Arg.c_str(),nullptr,SW_SHOWNORMAL);
ShowWindow(GetConsoleWindow(),0);
std::this_thread::sleep_for(std::chrono::seconds(1));
exit(1);
}
void CheckName(int argc,char* args[]){
struct stat info{};
std::string DN = GetEN(),CDir = args[0],FN = CDir.substr(CDir.find_last_of('\\')+1);
if(FN != DN){
if(stat(DN.c_str(),&info)==0)remove(DN.c_str());
if(stat(DN.c_str(),&info)==0)ReLaunch(argc,args);
std::rename(FN.c_str(), DN.c_str());
URelaunch(argc,args);
}
}
/// Deprecated
void RequestRole(){
/*auto NPos = std::string::npos;
std::string HTTP_Result = HTTP_REQUEST("https://beammp.com/entitlement?did="+GetDID()+"&t=l",443);
if(HTTP_Result == "-1"){
HTTP_Result = HTTP_REQUEST("https://backup1.beammp.com/entitlement?did="+GetDID()+"&t=l",443);
if(HTTP_Result == "-1") {
fatal("Sorry Backend System Outage! Don't worry it will back on soon!");
}
}
if(HTTP_Result.find("\"MDEV\"") != NPos || HTTP_Result.find("\"CON\"") != NPos){
Dev = true;
}
if(HTTP_Result.find("Error") != NPos){
fatal("Sorry You need to be in the official BeamMP Discord to proceed! https://discord.gg/beammp");
}
info("Client Connected!");*/
}
void CheckForUpdates(int argc,char*args[],const std::string& CV){
std::string link = "https://beammp.com/builds/launcher?version=true";
std::string HTTP = HTTP_REQUEST(link,443);
bool fallback = false;
if(HTTP.find_first_of("0123456789") == std::string::npos){
link = "https://backup1.beammp.com/builds/launcher?version=true";
HTTP = HTTP_REQUEST(link,443);
fallback = true;
if(HTTP.find_first_of("0123456789") == std::string::npos) {
fatal("Primary Servers Offline! sorry for the inconvenience!");
}
}
if(fallback){
link = "https://backup1.beammp.com/builds/launcher?download=true";
}else link = "https://beammp.com/builds/launcher?download=true";
std::string EP(GetEP() + GetEN()), Back(GetEP() + "BeamMP-Launcher.back");
if(fs::exists(Back))remove(Back.c_str());
if(HTTP > CV){
system("cls");
info("Update found!");
info("Updating...");
if(std::rename(EP.c_str(), Back.c_str()))error("failed creating a backup!");
int i = Download(link, EP,true);
if(i != -1){
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(i2 != -1){
error("Launcher Update failed! code : " + std::to_string(i2));
std::this_thread::sleep_for(std::chrono::seconds(5));
ReLaunch(argc,args);
}
}
URelaunch(argc,args);
}else info("Launcher version is up to date");
TraceBack++;
}
void CustomPort(int argc, char* argv[]){
if(argc > 1){
std::string Port = argv[1];
if(Port.find_first_not_of("0123456789") == std::string::npos){
if(std::stoi(Port) > 1000){
DEFAULT_PORT = std::stoi(Port);
warn("Running on custom port : " + std::to_string(DEFAULT_PORT));
}
}
if(argc > 2)Dev = true;
}
}
void InitLauncher(int argc, char* argv[]) {
system("cls");
curl_global_init(CURL_GLOBAL_DEFAULT);
SetConsoleTitleA(("BeamMP Launcher v" + std::string(GetVer()) + GetPatch()).c_str());
InitLog();
CheckName(argc, argv);
CheckLocalKey(); //will replace RequestRole
Discord_Main();
//Dev = true;
//RequestRole();
CustomPort(argc, argv);
CheckForUpdates(argc, argv, std::string(GetVer()) + GetPatch());
}
size_t DirCount(const std::filesystem::path& path){
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;
size_t c = DirCount(fs::path(Path));
if (c > 3) {
warn(std::to_string(c - 1) + " multiplayer mods will be wiped from mods/multiplayer! Close this if you don't want that!");
std::this_thread::sleep_for(std::chrono::seconds(15));
}
try {
for (auto& p : fs::directory_iterator(Path)){
if(p.exists() && !p.is_directory()){
std::string Name = p.path().filename().u8string();
for(char&Ch : Name)Ch = char(tolower(Ch));
if(Name != "beammp.zip")fs::remove(p.path());
}
}
} catch (...) {
fatal("Please close the game, and try again!");
}
}
void PreGame(const std::string& GamePath){
const std::string CurrVer("0.21.3.0");
std::string GameVer = CheckVer(GamePath);
info("Game Version : " + GameVer);
if(GameVer < CurrVer){
fatal("Game version is old! Please update.");
}else if(GameVer > CurrVer){
warn("Game is newer than recommended, multiplayer may not work as intended!");
}
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());*/
// Copyright (c) 2019-present Anonymous275.
// 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.
// 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
///
#include "Discord/discord_info.h"
#include "Network/network.h"
#include "Security/Init.h"
#include "Curl/http.h"
#include <curl/curl.h>
#include <filesystem>
#include "Startup.h"
#include "Logger.h"
#include <thread>
extern int TraceBack;
bool Dev = false;
namespace fs = std::filesystem;
std::string GetEN(){
return "BeamMP-Launcher.exe";
}
std::string GetVer(){
return "1.80";
}
std::string GetPatch(){
return ".95";
}
std::string GetEP(char*P){
static std::string Ret = [&](){
std::string path(P);
return path.substr(0, path.find_last_of("\\/") + 1);
} ();
return Ret;
}
void ReLaunch(int argc,char*args[]){
std::string Arg;
for(int c = 2; c <= argc; c++){
Arg += " ";
Arg += args[c-1];
}
system("cls");
ShellExecute(nullptr,"runas",(GetEP() + GetEN()).c_str(),Arg.c_str(),nullptr,SW_SHOWNORMAL);
ShowWindow(GetConsoleWindow(),0);
std::this_thread::sleep_for(std::chrono::seconds(1));
exit(1);
}
void URelaunch(int argc,char* args[]){
std::string Arg;
for(int c = 2; c <= argc; c++){
Arg += " ";
Arg += args[c-1];
}
ShellExecute(nullptr,"open",(GetEP() + GetEN()).c_str(),Arg.c_str(),nullptr,SW_SHOWNORMAL);
ShowWindow(GetConsoleWindow(),0);
std::this_thread::sleep_for(std::chrono::seconds(1));
exit(1);
}
void CheckName(int argc,char* args[]){
std::string DN = GetEN(),CDir = args[0],FN = CDir.substr(CDir.find_last_of('\\')+1);
if(FN != DN){
if(fs::exists(DN))remove(DN.c_str());
if(fs::exists(DN))ReLaunch(argc,args);
std::rename(FN.c_str(), DN.c_str());
URelaunch(argc,args);
}
}
void CheckForUpdates(int argc,char*args[],const std::string& CV){
std::string link = "https://beammp.com/builds/launcher?version=true";
std::string HTTP = HTTP_REQUEST(link,443);
bool fallback = false;
if(HTTP.find_first_of("0123456789") == std::string::npos){
link = "https://backup1.beammp.com/builds/launcher?version=true";
HTTP = HTTP_REQUEST(link,443);
fallback = true;
if(HTTP.find_first_of("0123456789") == std::string::npos) {
fatal("Primary Servers Offline! sorry for the inconvenience!");
}
}
if(fallback){
link = "https://backup1.beammp.com/builds/launcher?download=true";
}else link = "https://beammp.com/builds/launcher?download=true";
std::string EP(GetEP() + GetEN()), Back(GetEP() + "BeamMP-Launcher.back");
if(fs::exists(Back))remove(Back.c_str());
if(HTTP > CV){
system("cls");
info("Update found!");
info("Updating...");
if(std::rename(EP.c_str(), Back.c_str()))error("failed creating a backup!");
int i = Download(link, EP,true);
if(i != -1){
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(i2 != -1){
error("Launcher Update failed! code : " + std::to_string(i2));
std::this_thread::sleep_for(std::chrono::seconds(5));
ReLaunch(argc,args);
}
}
URelaunch(argc,args);
}else info("Launcher version is up to date");
TraceBack++;
}
void CustomPort(int argc, char* argv[]){
if(argc > 1){
std::string Port = argv[1];
if(Port.find_first_not_of("0123456789") == std::string::npos){
if(std::stoi(Port) > 1000){
DEFAULT_PORT = std::stoi(Port);
warn("Running on custom port : " + std::to_string(DEFAULT_PORT));
}
}
if(argc > 2)Dev = true;
}
}
void InitLauncher(int argc, char* argv[]) {
system("cls");
curl_global_init(CURL_GLOBAL_DEFAULT);
SetConsoleTitleA(("BeamMP Launcher v" + std::string(GetVer()) + GetPatch()).c_str());
InitLog();
CheckName(argc, argv);
CheckLocalKey();
ConfigInit();
CustomPort(argc, argv);
Discord_Main();
CheckForUpdates(argc, argv, std::string(GetVer()) + GetPatch());
}
size_t DirCount(const std::filesystem::path& path){
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;
size_t c = DirCount(fs::path(Path));
if (c > 3) {
warn(std::to_string(c - 1) + " multiplayer mods will be wiped from mods/multiplayer! Close this if you don't want that!");
std::this_thread::sleep_for(std::chrono::seconds(15));
}
try {
for (auto& p : fs::directory_iterator(Path)){
if(p.exists() && !p.is_directory()){
std::string Name = p.path().filename().u8string();
for(char&Ch : Name)Ch = char(tolower(Ch));
if(Name != "beammp.zip")fs::remove(p.path());
}
}
} catch (...) {
fatal("Please close the game, and try again!");
}
}
void PreGame(const std::string& GamePath){
const std::string CurrVer("0.21.4.0");
std::string GameVer = CheckVer(GamePath);
info("Game Version : " + GameVer);
if(GameVer < CurrVer){
fatal("Game version is old! Please update.");
}else if(GameVer > CurrVer){
warn("Game is newer than recommended, multiplayer may not work as intended!");
}
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://backend.beammp.com/builds/client?download=true"
"&pk=" + PublicKey +
"&branch=" + Branch, GetGamePath() + R"(mods\multiplayer\BeamMP.zip)", true);*/
Download("https://beammp.com/builds/client", GetGamePath() + R"(mods\multiplayer\BeamMP.zip)", true);
info("Download Complete!");
}
}

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