* fixed a bug in settings parser where lines with single characters would be completely removed when stripped of spaces

* refactored and moved all helper functions into the relevant helpers source file
This commit is contained in:
otavepto 2024-03-08 12:48:49 +02:00 committed by otavepto
parent a83d55707b
commit 88203b5c6f
8 changed files with 118 additions and 124 deletions

View File

@ -165,7 +165,7 @@ static std::vector<uint8_t> sign_auth_data(const std::string &private_key_conten
#ifndef EMU_RELEASE_BUILD
// we nedd a live object until the printf does its job, hence this special handling
auto str = uint8_vector_to_hex_string(signature);
auto str = common_helpers::uint8_vector_to_hex_string(signature);
PRINT_DEBUG("sign_auth_data final signature [%zu bytes]:\n %s\n", signature.size(), str.c_str());
#endif
@ -296,7 +296,7 @@ public:
#ifndef EMU_RELEASE_BUILD
// we nedd a live object until the printf does its job, hence this special handling
auto str = uint8_vector_to_hex_string(buffer);
auto str = common_helpers::uint8_vector_to_hex_string(buffer);
PRINT_DEBUG("AUTH::AppTicketGC::SER final data [%zu bytes]:\n %s\n", buffer.size(), str.c_str());
#endif
@ -407,7 +407,7 @@ struct AppTicket {
#ifndef EMU_RELEASE_BUILD
{
// we nedd a live object until the printf does its job, hence this special handling
auto str = uint8_vector_to_hex_string(buffer);
auto str = common_helpers::uint8_vector_to_hex_string(buffer);
PRINT_DEBUG("AUTH::AppTicket::SER (before licenses + DLCs):\n %s\n", str.c_str());
}
#endif
@ -460,7 +460,7 @@ struct AppTicket {
#ifndef EMU_RELEASE_BUILD
{
// we nedd a live object until the printf does its job, hence this special handling
auto str = uint8_vector_to_hex_string(buffer);
auto str = common_helpers::uint8_vector_to_hex_string(buffer);
PRINT_DEBUG("AUTH::AppTicket::SER final data [%zu bytes]:\n %s\n", buffer.size(), str.c_str());
}
#endif
@ -602,7 +602,7 @@ struct Auth_Data {
#ifndef EMU_RELEASE_BUILD
{
// we nedd a live object until the printf does its job, hence this special handling
auto str = uint8_vector_to_hex_string(buffer);
auto str = common_helpers::uint8_vector_to_hex_string(buffer);
PRINT_DEBUG("AUTH::Auth_Data::SER final data (before signature) [%zu bytes]:\n %s\n", buffer.size(), str.c_str());
}
#endif
@ -615,7 +615,7 @@ struct Auth_Data {
#ifndef EMU_RELEASE_BUILD
{
// we nedd a live object until the printf does its job, hence this special handling
auto str = uint8_vector_to_hex_string(buffer);
auto str = common_helpers::uint8_vector_to_hex_string(buffer);
PRINT_DEBUG("AUTH::Auth_Data::SER final data (after signature) [%zu bytes]:\n %s\n", buffer.size(), str.c_str());
}
#endif

View File

@ -167,8 +167,6 @@ static inline void reset_LastError()
#include "utfcpp/utf8.h"
#include "controller/gamepad.h"
constexpr const char * const whitespaces = " \t\r\n";
// common includes
#include "common_helpers/common_helpers.hpp"
@ -215,56 +213,6 @@ constexpr const char * const whitespaces = " \t\r\n";
#define PRINT_DEBUG(...)
#endif // EMU_RELEASE_BUILD
static inline std::string ascii_to_lowercase(std::string data) {
std::transform(data.begin(), data.end(), data.begin(),
[](unsigned char c){ return std::tolower(c); });
return data;
}
static inline void thisThreadYieldFor(std::chrono::microseconds u)
{
PRINT_DEBUG("Thread is waiting for %lld us\n", (long long int)u.count());
const auto start = std::chrono::high_resolution_clock::now();
const auto end = start + u;
do
{
std::this_thread::yield();
}
while (std::chrono::high_resolution_clock::now() < end);
PRINT_DEBUG("Thread finished waiting\n");
}
static std::string uint8_vector_to_hex_string(const std::vector<uint8_t>& v)
{
std::string result{};
result.reserve(v.size() * 2); // two digits per character
static constexpr const char hex[] = "0123456789ABCDEF";
for (uint8_t c : v)
{
result.push_back(hex[c / 16]);
result.push_back(hex[c % 16]);
}
return result;
}
static inline void consume_bom(std::ifstream &input)
{
if (!input.is_open()) return;
auto pos = input.tellg();
int bom[3]{};
bom[0] = input.get();
bom[1] = input.get();
bom[2] = input.get();
if (bom[0] != 0xEF || bom[1] != 0xBB || bom[2] != 0xBF) {
input.clear();
input.seekg(pos, std::ios::beg);
}
}
// Emulator includes
// add them here after the inline functions definitions
#include "net.pb.h"

View File

@ -237,7 +237,7 @@ public:
//stats
std::map<std::string, Stat_config> getStats() { return stats; }
void setStatDefiniton(std::string name, struct Stat_config stat_config) {stats[ascii_to_lowercase(name)] = stat_config; }
void setStatDefiniton(std::string name, struct Stat_config stat_config) {stats[common_helpers::ascii_to_lowercase(name)] = stat_config; }
// bypass to make SetAchievement() always return true, prevent some games from breaking
bool achievement_bypass = false;

View File

@ -911,7 +911,7 @@ void Callback(Common_Message *msg)
"Steam_Networking: got msg from: " "%" PRIu64 " to: " "%" PRIu64 " size %zu type %u | messages %p: %zu\n",
msg->source_id(), msg->dest_id(), msg->network().data().size(), msg->network().type(), &messages, messages.size()
);
PRINT_DEBUG("Steam_Networking msg data: '%s'\n", uint8_vector_to_hex_string( std::vector<uint8_t>(msg->network().data().begin(), msg->network().data().end()) ).c_str());
PRINT_DEBUG("Steam_Networking msg data: '%s'\n", common_helpers::uint8_vector_to_hex_string( std::vector<uint8_t>(msg->network().data().begin(), msg->network().data().end()) ).c_str());
#endif
if (msg->network().type() == Network_pb::DATA) {

View File

@ -142,7 +142,7 @@ void save_leaderboard_score(Steam_Leaderboard *leaderboard)
output.push_back(s);
}
std::string leaderboard_name = ascii_to_lowercase(leaderboard->name);
std::string leaderboard_name = common_helpers::ascii_to_lowercase(leaderboard->name);
local_storage->store_data(Local_Storage::leaderboard_storage_folder, leaderboard_name, (char* )output.data(), sizeof(uint32_t) * output.size());
}
@ -150,7 +150,7 @@ std::vector<Steam_Leaderboard_Score> load_leaderboard_scores(std::string name)
{
std::vector<Steam_Leaderboard_Score> out;
std::string leaderboard_name = ascii_to_lowercase(name);
std::string leaderboard_name = common_helpers::ascii_to_lowercase(name);
unsigned size = local_storage->file_size(Local_Storage::leaderboard_storage_folder, leaderboard_name);
if (size == 0 || (size % sizeof(uint32_t)) != 0) return out;
@ -254,7 +254,7 @@ Steam_User_Stats(Settings *settings, Local_Storage *local_storage, class SteamCa
achievement_trigger trig;
trig.name = name;
trig.value_operation = static_cast<std::string const&>(it["progress"]["value"]["operation"]);
std::string stat_name = ascii_to_lowercase(static_cast<std::string const&>(it["progress"]["value"]["operand1"]));
std::string stat_name = common_helpers::ascii_to_lowercase(static_cast<std::string const&>(it["progress"]["value"]["operand1"]));
trig.min_value = static_cast<std::string const&>(it["progress"]["min_val"]);
trig.max_value = static_cast<std::string const&>(it["progress"]["max_val"]);
achievement_stat_trigger[stat_name].push_back(trig);
@ -299,7 +299,7 @@ bool GetStat( const char *pchName, int32 *pData )
std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (!pchName || !pData) return false;
std::string stat_name = ascii_to_lowercase(pchName);
std::string stat_name = common_helpers::ascii_to_lowercase(pchName);
auto stats_config = settings->getStats();
auto stats_data = stats_config.find(stat_name);
@ -331,7 +331,7 @@ bool GetStat( const char *pchName, float *pData )
std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (!pchName || !pData) return false;
std::string stat_name = ascii_to_lowercase(pchName);
std::string stat_name = common_helpers::ascii_to_lowercase(pchName);
auto stats_config = settings->getStats();
auto stats_data = stats_config.find(stat_name);
@ -365,7 +365,7 @@ bool SetStat( const char *pchName, int32 nData )
std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (!pchName) return false;
std::string stat_name = ascii_to_lowercase(pchName);
std::string stat_name = common_helpers::ascii_to_lowercase(pchName);
auto stats_config = settings->getStats();
auto stats_data = stats_config.find(stat_name);
@ -400,7 +400,7 @@ bool SetStat( const char *pchName, float fData )
std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (!pchName) return false;
std::string stat_name = ascii_to_lowercase(pchName);
std::string stat_name = common_helpers::ascii_to_lowercase(pchName);
auto stats_config = settings->getStats();
auto stats_data = stats_config.find(stat_name);
@ -435,7 +435,7 @@ bool UpdateAvgRateStat( const char *pchName, float flCountThisSession, double dS
std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (!pchName) return false;
std::string stat_name = ascii_to_lowercase(pchName);
std::string stat_name = common_helpers::ascii_to_lowercase(pchName);
auto stats_config = settings->getStats();
auto stats_data = stats_config.find(stat_name);

View File

@ -21,7 +21,7 @@ static void load_custom_broadcasts(std::string broadcasts_filepath, std::set<IP_
{
PRINT_DEBUG("Broadcasts file path: %s\n", broadcasts_filepath.c_str());
std::ifstream broadcasts_file(utf8_decode(broadcasts_filepath));
consume_bom(broadcasts_file);
common_helpers::consume_bom(broadcasts_file);
if (broadcasts_file.is_open()) {
std::string line;
while (std::getline(broadcasts_file, line)) {
@ -36,7 +36,7 @@ static void load_subscribed_groups_clans(std::string clans_filepath, Settings *s
PRINT_DEBUG("Group clans file path: %s\n", clans_filepath.c_str());
std::ifstream clans_file(utf8_decode(clans_filepath));
if (clans_file.is_open()) {
consume_bom(clans_file);
common_helpers::consume_bom(clans_file);
std::string line;
while (std::getline(clans_file, line)) {
if (line.length() < 0) continue;
@ -76,7 +76,7 @@ static void load_overlay_appearance(std::string appearance_filepath, Settings *s
std::ifstream appearance_file(utf8_decode(appearance_filepath));
if (appearance_file.is_open()) {
PRINT_DEBUG("Parsing overlay appearance file: '%s'\n", appearance_filepath.c_str());
consume_bom(appearance_file);
common_helpers::consume_bom(appearance_file);
std::string line{};
while (std::getline(appearance_file, line)) {
if (line.length() <= 0) continue;
@ -86,12 +86,10 @@ static void load_overlay_appearance(std::string appearance_filepath, Settings *s
std::string value{};
if (seperator != std::string::npos) {
name = line.substr(0, seperator);
name.erase(0, name.find_first_not_of(whitespaces));
name.erase(name.find_last_not_of(whitespaces) + 1);
name = common_helpers::string_strip(name);
value = line.substr(seperator);
value.erase(0, value.find_first_not_of(whitespaces));
value.erase(value.find_last_not_of(whitespaces) + 1);
value = line.substr(seperator + 1);
value = common_helpers::string_strip(value);
}
// comments
@ -239,7 +237,7 @@ static void load_gamecontroller_settings(Settings *settings)
std::string controller_config_path = path + PATH_SEPARATOR + p;
std::ifstream input( utf8_decode(controller_config_path) );
if (input.is_open()) {
consume_bom(input);
common_helpers::consume_bom(input);
std::map<std::string, std::pair<std::set<std::string>, std::string>> button_pairs;
for( std::string line; getline( input, line ); ) {
@ -464,7 +462,7 @@ std::set<std::string> parse_supported_languages(class Local_Storage *local_stora
std::string first_language;
if (input.is_open()) {
consume_bom(input);
common_helpers::consume_bom(input);
for( std::string line; getline( input, line ); ) {
if (!line.empty() && line[line.length()-1] == '\n') {
line.pop_back();
@ -500,7 +498,7 @@ static void parse_dlc(class Settings *settings_client, Settings *settings_server
std::string dlc_config_path = Local_Storage::get_game_settings_path() + "DLC.txt";
std::ifstream input( utf8_decode(dlc_config_path) );
if (input.is_open()) {
consume_bom(input);
common_helpers::consume_bom(input);
settings_client->unlockAllDLC(false);
settings_server->unlockAllDLC(false);
PRINT_DEBUG("Locking all DLC\n");
@ -545,7 +543,7 @@ static void parse_app_paths(class Settings *settings_client, Settings *settings_
std::ifstream input( utf8_decode(dlc_config_path) );
if (input.is_open()) {
consume_bom(input);
common_helpers::consume_bom(input);
for( std::string line; getline( input, line ); ) {
if (!line.empty() && line[line.length()-1] == '\n') {
line.pop_back();
@ -582,7 +580,7 @@ static void parse_leaderboards(class Settings *settings_client, Settings *settin
std::string dlc_config_path = Local_Storage::get_game_settings_path() + "leaderboards.txt";
std::ifstream input( utf8_decode(dlc_config_path) );
if (input.is_open()) {
consume_bom(input);
common_helpers::consume_bom(input);
settings_client->setCreateUnknownLeaderboards(false);
settings_server->setCreateUnknownLeaderboards(false);
@ -627,7 +625,7 @@ static void parse_stats(class Settings *settings_client, Settings *settings_serv
std::string stats_config_path = Local_Storage::get_game_settings_path() + "stats.txt";
std::ifstream input( utf8_decode(stats_config_path) );
if (input.is_open()) {
consume_bom(input);
common_helpers::consume_bom(input);
for( std::string line; getline( input, line ); ) {
if (!line.empty() && line[line.length()-1] == '\n') {
line.pop_back();
@ -695,7 +693,7 @@ static void parse_depots(class Settings *settings_client, Settings *settings_ser
std::string depots_config_path = Local_Storage::get_game_settings_path() + "depots.txt";
std::ifstream input( utf8_decode(depots_config_path) );
if (input.is_open()) {
consume_bom(input);
common_helpers::consume_bom(input);
for( std::string line; getline( input, line ); ) {
if (!line.empty() && line[line.length()-1] == '\n') {
line.pop_back();
@ -722,7 +720,7 @@ static void parse_subscribed_groups(class Settings *settings_client, Settings *s
std::string depots_config_path = Local_Storage::get_game_settings_path() + "subscribed_groups.txt";
std::ifstream input( utf8_decode(depots_config_path) );
if (input.is_open()) {
consume_bom(input);
common_helpers::consume_bom(input);
for( std::string line; getline( input, line ); ) {
if (!line.empty() && line[line.length()-1] == '\n') {
line.pop_back();
@ -752,7 +750,7 @@ static void parse_installed_app_Ids(class Settings *settings_client, Settings *s
settings_client->assume_any_app_installed = false;
settings_server->assume_any_app_installed = false;
PRINT_DEBUG("Limiting/Locking installed apps\n");
consume_bom(input);
common_helpers::consume_bom(input);
for( std::string line; getline( input, line ); ) {
if (!line.empty() && line[line.length()-1] == '\n') {
line.pop_back();
@ -783,16 +781,10 @@ static void parse_force_branch_name(class Settings *settings_client, Settings *s
std::string installed_apps_list_path = Local_Storage::get_game_settings_path() + "force_branch_name.txt";
std::ifstream input( utf8_decode(installed_apps_list_path) );
if (input.is_open()) {
consume_bom(input);
common_helpers::consume_bom(input);
std::string line;
getline( input, line );
size_t start = line.find_first_not_of(whitespaces);
size_t end = line.find_last_not_of(whitespaces);
line = start == end
? std::string()
: line.substr(start, end - start + 1);
line = common_helpers::string_strip(line);
if (!line.empty()) {
settings_client->current_branch_name = line;
settings_server->current_branch_name = line;
@ -1072,16 +1064,10 @@ static void parse_crash_printer_location()
std::string installed_apps_list_path = Local_Storage::get_game_settings_path() + "crash_printer_location.txt";
std::ifstream input( utf8_decode(installed_apps_list_path) );
if (input.is_open()) {
consume_bom(input);
common_helpers::consume_bom(input);
std::string line;
std::getline( input, line );
size_t start = line.find_first_not_of(whitespaces);
size_t end = line.find_last_not_of(whitespaces);
line = start == end
? std::string()
: line.substr(start, end - start + 1);
line = common_helpers::string_strip(line);
if (!line.empty()) {
auto crash_path = utf8_decode(get_full_program_path() + line);
if (crash_printer::init(crash_path)) {
@ -1100,15 +1086,9 @@ static void parse_auto_accept_invite(class Settings *settings_client, Settings *
std::ifstream input( utf8_decode(auto_accept_list_path) );
if (input.is_open()) {
bool accept_any_invite = true;
consume_bom(input);
common_helpers::consume_bom(input);
for( std::string line; getline( input, line ); ) {
size_t start = line.find_first_not_of(whitespaces);
size_t end = line.find_last_not_of(whitespaces);
line = start == end
? std::string()
: line.substr(start, end - start + 1);
line = common_helpers::string_strip(line);
if (!line.empty()) {
accept_any_invite = false;
try {
@ -1137,16 +1117,10 @@ static void parse_ip_country(class Settings *settings_client, Settings *settings
std::string setting_file = Local_Storage::get_game_settings_path() + "ip_country.txt";
std::ifstream input( utf8_decode(setting_file) );
if (input.is_open()) {
consume_bom(input);
common_helpers::consume_bom(input);
std::string line{};
std::getline( input, line );
size_t start = line.find_first_not_of(whitespaces);
size_t end = line.find_last_not_of(whitespaces);
line = start == end
? std::string()
: line.substr(start, end - start + 1);
line = common_helpers::string_strip(line);
// ISO 3166-1-alpha-2 format is 2 chars only
if (line.size() == 2) {
std::transform(line.begin(), line.end(), line.begin(), [](char c) { return std::toupper(c); });
@ -1164,15 +1138,10 @@ static void parse_overlay_hook_delay_sec(class Settings *settings_client, Settin
std::ifstream input( utf8_decode(auto_accept_list_path) );
if (input.is_open()) {
bool accept_any_invite = true;
consume_bom(input);
common_helpers::consume_bom(input);
std::string line{};
std::getline( input, line );
size_t start = line.find_first_not_of(whitespaces);
size_t end = line.find_last_not_of(whitespaces);
line = start == end
? std::string()
: line.substr(start, end - start + 1);
line = common_helpers::string_strip(line);
if (!line.empty()) {
try {
auto delay_sec = std::stoi(line);

View File

@ -2,6 +2,7 @@
#include <fstream>
#include <cwchar>
#include <algorithm>
#include <thread>
static bool create_dir_impl(std::filesystem::path &dirpath)
{
@ -106,6 +107,71 @@ bool common_helpers::ends_with_i(const std::wstring &target, const std::wstring
}
std::string common_helpers::string_strip(const std::string& str)
{
static constexpr const char whitespaces[] = " \t\r\n";
size_t start = str.find_first_not_of(whitespaces);
size_t end = str.find_last_not_of(whitespaces);
if (start == std::string::npos) return {};
if (start == end) {
auto c = str[start];
for (auto c_white = whitespaces; *c_white; ++c_white) {
if (c == *c_white) return {};
}
}
return str.substr(start, end - start + 1);
}
std::string common_helpers::uint8_vector_to_hex_string(const std::vector<uint8_t>& v)
{
std::string result{};
result.reserve(v.size() * 2); // two digits per character
static constexpr const char hex[] = "0123456789ABCDEF";
for (uint8_t c : v)
{
result.push_back(hex[c / 16]);
result.push_back(hex[c % 16]);
}
return result;
}
std::string common_helpers::ascii_to_lowercase(std::string data) {
std::transform(data.begin(), data.end(), data.begin(),
[](unsigned char c){ return std::tolower(c); });
return data;
}
void common_helpers::thisThreadYieldFor(std::chrono::microseconds u)
{
const auto start = std::chrono::high_resolution_clock::now();
const auto end = start + u;
do {
std::this_thread::yield();
} while (std::chrono::high_resolution_clock::now() < end);
}
void common_helpers::consume_bom(std::ifstream &input)
{
if (!input.is_open()) return;
auto pos = input.tellg();
int bom[3]{};
bom[0] = input.get();
bom[1] = input.get();
bom[2] = input.get();
if (bom[0] != 0xEF || bom[1] != 0xBB || bom[2] != 0xBF) {
input.clear();
input.seekg(pos, std::ios::beg);
}
}
std::string common_helpers::to_lower(std::string str)
{
std::string _str(str.size(), '\0');

View File

@ -3,6 +3,7 @@
#include <string>
#include <fstream>
#include <filesystem>
#include <chrono>
namespace common_helpers {
@ -24,6 +25,16 @@ bool ends_with_i(const std::string &target, const std::string &query);
bool ends_with_i(const std::wstring &target, const std::wstring &query);
std::string string_strip(const std::string& str);
std::string uint8_vector_to_hex_string(const std::vector<uint8_t>& v);
std::string ascii_to_lowercase(std::string data);
void thisThreadYieldFor(std::chrono::microseconds u);
void consume_bom(std::ifstream &input);
std::string to_lower(std::string str);
std::wstring to_lower(std::wstring wstr);