forked from MrBesen/lolautoaccept
190 lines
4.7 KiB
C++
190 lines
4.7 KiB
C++
#include "clientaccess.h"
|
|
|
|
#include <cstring>
|
|
#include <dirent.h>
|
|
#include <fcntl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/mman.h>
|
|
#include <unistd.h>
|
|
|
|
#include <algorithm>
|
|
#include <fstream>
|
|
#include <iomanip>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <Log.h>
|
|
|
|
#include "defer.h"
|
|
|
|
static bool endsWith(const std::string& all, const std::string& end) {
|
|
return all.rfind(end) == all.size() - end.size();
|
|
}
|
|
|
|
// reads a procfile into a vector (strings are \0 seperated)
|
|
static std::vector<std::string> readProcFile(const std::string& path) {
|
|
std::ifstream in(path);
|
|
std::vector<std::string> out;
|
|
std::string line;
|
|
while(std::getline(in, line, '\0')) {
|
|
if(!line.empty()) {
|
|
out.push_back(line);
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
|
|
ClientAccess::ClientAccess() {}
|
|
|
|
ClientAccess::ClientAccess(const std::string& token, uint16_t port) : authcode(token), port(port) {}
|
|
|
|
std::shared_ptr<ClientAccess> ClientAccess::find(bool uselockfile) {
|
|
|
|
DIR* procdir = opendir("/proc");
|
|
if(!procdir) return nullptr;
|
|
|
|
defer( closedir(procdir) );
|
|
|
|
dirent* entry = nullptr;
|
|
while ((entry = readdir(procdir)) != NULL) {
|
|
if (entry->d_type != DT_DIR) continue;
|
|
|
|
std::string name(entry->d_name);
|
|
|
|
pid_t pid = -1;
|
|
try {
|
|
pid = std::stoi(name);
|
|
} catch(std::exception& e) {
|
|
// could not parse -> not a pid
|
|
continue;
|
|
}
|
|
|
|
// get info on the exe
|
|
std::string cmdfile = "/proc/" + std::to_string(pid) + "/cmdline";
|
|
std::vector<std::string> args = readProcFile(cmdfile);
|
|
|
|
// Log::debug << "process: " << pid << " has " << args.size() << " args";
|
|
|
|
if(args.empty()) continue;
|
|
|
|
std::string& exename = args.at(0);
|
|
if(endsWith(exename, "LeagueClientUx.exe")) {
|
|
Log::info << "LeagueClientUx.exe found";
|
|
|
|
std::shared_ptr<ClientAccess> out;
|
|
|
|
if(uselockfile) {
|
|
out = findUsingLockfile(args, pid);
|
|
} else {
|
|
out = findUsingArgs(args);
|
|
}
|
|
|
|
if(out) {
|
|
return out;
|
|
}
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
std::string ClientAccess::parseArg(const std::string& input, std::string& value) {
|
|
if(input.find("--") != 0) return {};
|
|
|
|
size_t pos = input.find('=');
|
|
if(pos == std::string::npos) return {};
|
|
|
|
value = input.substr(pos+1);
|
|
return input.substr(2, pos-2);
|
|
}
|
|
|
|
std::shared_ptr<ClientAccess> ClientAccess::findUsingArgs(const std::vector<std::string>& cmdline) {
|
|
// parse args
|
|
std::shared_ptr<ClientAccess> access(new ClientAccess());
|
|
for(const std::string& arg : cmdline) {
|
|
std::string value;
|
|
std::string argname = parseArg(arg, value);
|
|
|
|
if(argname == "riotclient-auth-token") {
|
|
access->authcode = value;
|
|
} else if(argname == "riotclient-app-port") {
|
|
try {
|
|
access->port = std::stoi(value);
|
|
} catch(std::exception& e) {
|
|
Log::warn << "could not parse port: " << std::quoted(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(access->port > 0 && !access->authcode.empty()) {
|
|
return access;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
std::shared_ptr<ClientAccess> ClientAccess::findUsingLockfile(const std::vector<std::string>& cmdline, pid_t pid) {
|
|
// get WINEPREFIX env
|
|
std::vector<std::string> envs = readProcFile("/proc/" + std::to_string(pid) + "/environ");
|
|
|
|
const static std::string WINEPREFIX = "WINEPREFIX=";
|
|
|
|
// find WINEPREFIX
|
|
auto found = std::find_if(envs.begin(), envs.end(), [](const std::string& s) {
|
|
return s.find(WINEPREFIX) == 0;
|
|
});
|
|
|
|
// WINEPREFIX env not present
|
|
if(found == envs.end()) {
|
|
Log::debug << "WINEPREFIX environment variable not set";
|
|
return {};
|
|
}
|
|
|
|
const std::string wineprefix = found->substr(WINEPREFIX.size());
|
|
const std::string binarypath = cmdline.at(0);
|
|
std::string gamefolder = binarypath.substr(2, binarypath.rfind('/')-1); // remove the "C:" and the name of the binary
|
|
// TODO: gamefoldre could contain '\' so replacing every occurance with '/' would be a good idea
|
|
const std::string lockfilepath = wineprefix + "/drive_c/" + gamefolder + "/lockfile";
|
|
|
|
Log::debug << "lockfilepath: " << std::quoted(lockfilepath);
|
|
|
|
// read lockfile
|
|
std::ifstream lockfile(lockfilepath);
|
|
std::vector<std::string> parts;
|
|
std::string content;
|
|
while(std::getline(lockfile, content, ':')) {
|
|
parts.push_back(content);
|
|
}
|
|
|
|
if(parts.size() != 5) {
|
|
Log::error << "lockfile contained " << parts.size() << " parts, expected 5";
|
|
return {};
|
|
}
|
|
|
|
const std::string portstr = parts.at(2);
|
|
const std::string token = parts.at(3);
|
|
|
|
// try to parse port
|
|
try {
|
|
uint16_t port = std::stoi(portstr);
|
|
|
|
return std::shared_ptr<ClientAccess>(new ClientAccess(token, port));
|
|
} catch(std::exception& e) {
|
|
Log::error << "could not parse port: " << std::quoted(portstr);
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
std::string ClientAccess::getBasicAuth() const {
|
|
return "riot:" + authcode;
|
|
}
|
|
|
|
uint16_t ClientAccess::getPort() const {
|
|
return port;
|
|
}
|
|
|
|
std::string ClientAccess::getURL() const {
|
|
return "https://127.0.0.1:" + std::to_string(port) + "/";
|
|
}
|