From ad7788f290535bbbfef2f57d23faeaa8f44dfa24 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Sat, 1 Feb 2025 23:45:42 +0100 Subject: [PATCH] Refactor pfServerIni to return error messages via out parameters --- .../Plasma/Apps/plClient/win32/winmain.cpp | 4 +- .../Apps/plUruLauncher/plClientLauncher.cpp | 4 +- .../Apps/plUruLauncher/plClientLauncher.h | 2 +- Sources/Plasma/Apps/plUruLauncher/winmain.cpp | 4 +- .../FeatureLib/pfConsoleCore/pfServerIni.cpp | 88 +++++++++++-------- .../FeatureLib/pfConsoleCore/pfServerIni.h | 6 +- Sources/Tools/plFilePatcher/plFilePatcher.cpp | 4 +- 7 files changed, 62 insertions(+), 50 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/win32/winmain.cpp b/Sources/Plasma/Apps/plClient/win32/winmain.cpp index 32308beabd..6bfffb95c2 100644 --- a/Sources/Plasma/Apps/plClient/win32/winmain.cpp +++ b/Sources/Plasma/Apps/plClient/win32/winmain.cpp @@ -1202,8 +1202,8 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC if (serverIniFile) { fclose(serverIniFile); - ST::string errorMsg = pfServerIni::Load(serverIni); - if (!errorMsg.empty()) { + ST::string errorMsg; + if (!pfServerIni::Load(serverIni, errorMsg)) { hsMessageBox(ST::format("Error in server.ini file. Please check your URU installation.\n{}", errorMsg), ST_LITERAL("Error"), hsMessageBoxNormal); return PARABLE_NORMAL_EXIT; } diff --git a/Sources/Plasma/Apps/plUruLauncher/plClientLauncher.cpp b/Sources/Plasma/Apps/plUruLauncher/plClientLauncher.cpp index 2435cd27e6..e44241d754 100644 --- a/Sources/Plasma/Apps/plUruLauncher/plClientLauncher.cpp +++ b/Sources/Plasma/Apps/plUruLauncher/plClientLauncher.cpp @@ -440,9 +440,9 @@ void plClientLauncher::ShutdownNetCore() // =================================================== -ST::string plClientLauncher::LoadServerIni() const +bool plClientLauncher::LoadServerIni(ST::string& errorMsg) const { - return pfServerIni::Load(fServerIni); + return pfServerIni::Load(fServerIni, errorMsg); } void plClientLauncher::ParseArguments() diff --git a/Sources/Plasma/Apps/plUruLauncher/plClientLauncher.h b/Sources/Plasma/Apps/plUruLauncher/plClientLauncher.h index 8f37ba801d..f443ee2e64 100644 --- a/Sources/Plasma/Apps/plUruLauncher/plClientLauncher.h +++ b/Sources/Plasma/Apps/plUruLauncher/plClientLauncher.h @@ -138,7 +138,7 @@ class plClientLauncher /** Load the server configuration file. Note that you MUST parse the command * arguments before calling this function! */ - ST::string LoadServerIni() const; + bool LoadServerIni(ST::string& errorMsg) const; /** Parse the command line options. */ void ParseArguments(); diff --git a/Sources/Plasma/Apps/plUruLauncher/winmain.cpp b/Sources/Plasma/Apps/plUruLauncher/winmain.cpp index 620cc71deb..a758d2922d 100644 --- a/Sources/Plasma/Apps/plUruLauncher/winmain.cpp +++ b/Sources/Plasma/Apps/plUruLauncher/winmain.cpp @@ -408,8 +408,8 @@ int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdL return PLASMA_OK; // see you on the other side... // Load the doggone server.ini - ST::string errorMsg = launcher.LoadServerIni(); - if (!errorMsg.empty()) { + ST::string errorMsg; + if (!launcher.LoadServerIni(errorMsg)) { IShowErrorDialog(ST::format("server.ini file not found or invalid. Please check your URU installation.\n{}", errorMsg)); return PLASMA_PHAILURE; } diff --git a/Sources/Plasma/FeatureLib/pfConsoleCore/pfServerIni.cpp b/Sources/Plasma/FeatureLib/pfConsoleCore/pfServerIni.cpp index 3ccb6907d7..b09530e1cf 100644 --- a/Sources/Plasma/FeatureLib/pfConsoleCore/pfServerIni.cpp +++ b/Sources/Plasma/FeatureLib/pfConsoleCore/pfServerIni.cpp @@ -51,37 +51,42 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plFile/plEncryptedStream.h" -static ST::string ParseIntegerInto(const ST::string& value, unsigned int& out) +static bool ParseIntegerInto(const ST::string& value, unsigned int& out, ST::string& errorMsg) { ST::conversion_result res; out = value.to_uint(res); if (res.ok() && res.full_match()) { - return {}; + return true; } else { - return ST::format("Invalid integer value: {}", value); + errorMsg = ST::format("Invalid integer value: {}", value); + return false; } } -static ST::string ParseBase64KeyInto(const ST::string& base64key, NetDhKey& output) +static bool ParseBase64KeyInto(const ST::string& base64key, NetDhKey& output, ST::string& errorMsg) { ST_ssize_t base64len = ST::base64_decode(base64key, nullptr, 0); if (base64len < 0) { - return ST::format("Invalid key: Invalid base-64 data (did you forget to put quotes around the value?)"); + errorMsg = ST::format("Invalid key: Invalid base-64 data (did you forget to put quotes around the value?)"); + return false; } else if (sizeof(output) != base64len) { - return ST::format("Invalid key: Should be exactly {} bytes, not {}", sizeof(output), base64len); + errorMsg = ST::format("Invalid key: Should be exactly {} bytes, not {}", sizeof(output), base64len); + return false; } ST_ssize_t bytes = ST::base64_decode(base64key, output, sizeof(output)); if (bytes < 0) { - return ST::format("Invalid key: Invalid base-64 data"); + errorMsg = ST::format("Invalid key: Invalid base-64 data"); + return false; } - return {}; + return true; } -ST::string pfServerIni::IParseOption(const std::vector& name, const ST::string& value) +bool pfServerIni::IParseOption(const std::vector& name, const ST::string& value, ST::string& errorMsg) { if (name.empty() || name[0].compare_i("Server") != 0) { - return ST_LITERAL("Unknown option name"); + errorMsg = ST_LITERAL("Unknown option name"); + return false; } if (name.size() == 2 && name[1].compare_i("Status") == 0) { @@ -91,55 +96,60 @@ ST::string pfServerIni::IParseOption(const std::vector& name, const } else if (name.size() == 2 && name[1].compare_i("DispName") == 0) { fDisplayName = value; } else if (name.size() == 2 && name[1].compare_i("Port") == 0) { - return ParseIntegerInto(value, fPort); + return ParseIntegerInto(value, fPort, errorMsg); } else if (name.size() == 3 && name[1].compare_i("File") == 0 && name[2].compare_i("Host") == 0) { fFileHostname = value; } else if (name.size() == 3 && name[1].compare_i("Auth") == 0) { if (name[2].compare_i("Host") == 0) { fAuthHostname = value; } else if (name[2].compare_i("N") == 0) { - return ParseBase64KeyInto(value, fAuthDhConstants.n); + return ParseBase64KeyInto(value, fAuthDhConstants.n, errorMsg); } else if (name[2].compare_i("X") == 0) { - return ParseBase64KeyInto(value, fAuthDhConstants.x); + return ParseBase64KeyInto(value, fAuthDhConstants.x, errorMsg); } else if (name[2].compare_i("G") == 0) { - return ParseIntegerInto(value, fAuthDhConstants.g); + return ParseIntegerInto(value, fAuthDhConstants.g, errorMsg); } else { - return ST_LITERAL("Unknown option name"); + errorMsg = ST_LITERAL("Unknown option name"); + return false; } } else if (name.size() == 3 && name[1].compare_i("Game") == 0) { if (name[2].compare_i("N") == 0) { - return ParseBase64KeyInto(value, fGameDhConstants.n); + return ParseBase64KeyInto(value, fGameDhConstants.n, errorMsg); } else if (name[2].compare_i("X") == 0) { - return ParseBase64KeyInto(value, fGameDhConstants.x); + return ParseBase64KeyInto(value, fGameDhConstants.x, errorMsg); } else if (name[2].compare_i("G") == 0) { - return ParseIntegerInto(value, fGameDhConstants.g); + return ParseIntegerInto(value, fGameDhConstants.g, errorMsg); } else { - return ST_LITERAL("Unknown option name"); + errorMsg = ST_LITERAL("Unknown option name"); + return false; } } else if (name.size() == 3 && name[1].compare_i("Gate") == 0) { if (name[2].compare_i("Host") == 0) { fGateKeeperHostname = value; } else if (name[2].compare_i("N") == 0) { - return ParseBase64KeyInto(value, fGateKeeperDhConstants.n); + return ParseBase64KeyInto(value, fGateKeeperDhConstants.n, errorMsg); } else if (name[2].compare_i("X") == 0) { - return ParseBase64KeyInto(value, fGateKeeperDhConstants.x); + return ParseBase64KeyInto(value, fGateKeeperDhConstants.x, errorMsg); } else if (name[2].compare_i("G") == 0) { - return ParseIntegerInto(value, fGateKeeperDhConstants.g); + return ParseIntegerInto(value, fGateKeeperDhConstants.g, errorMsg); } else { - return ST_LITERAL("Unknown option name"); + errorMsg = ST_LITERAL("Unknown option name"); + return false; } } else { - return ST_LITERAL("Unknown option name"); + errorMsg = ST_LITERAL("Unknown option name"); + return false; } - return {}; + return true; } -ST::string pfServerIni::Parse(const plFileName& fileName) +bool pfServerIni::Parse(const plFileName& fileName, ST::string& errorMsg) { std::unique_ptr stream = plEncryptedStream::OpenEncryptedFile(fileName); if (!stream) { - return ST::format("File not found or could not be opened: {}", fileName); + errorMsg = ST::format("File not found or could not be opened: {}", fileName); + return false; } ST::string line; @@ -149,7 +159,8 @@ ST::string pfServerIni::Parse(const plFileName& fileName) auto name = parser.ParseUnknownCommandName(); if (name.empty()) { if (!parser.GetErrorMsg().empty()) { - return ST::format("Line {}: {}", lineno, parser.GetErrorMsg()); + errorMsg = ST::format("Line {}: {}", lineno, parser.GetErrorMsg()); + return false; } else { // No error, just an empty line. continue; @@ -158,19 +169,21 @@ ST::string pfServerIni::Parse(const plFileName& fileName) auto args = parser.ParseArguments(); if (!args) { - return ST::format("Line {}: {}", lineno, parser.GetErrorMsg()); + errorMsg = ST::format("Line {}: {}", lineno, parser.GetErrorMsg()); + return false; } // TODO Warn/error if there isn't exactly one argument after the name? ST::string value = args->empty() ? ST::string() : std::move((*args)[0]); - ST::string errorMsg = IParseOption(name, value); - if (!errorMsg.empty()) { - return ST::format("Line {}: {}", lineno, errorMsg); + ST::string parseOptionError; + if (!IParseOption(name, value, parseOptionError)) { + errorMsg = ST::format("Line {}: {}", lineno, parseOptionError); + return false; } } // Everything went ok! - return {}; + return true; } void pfServerIni::Apply() @@ -187,15 +200,14 @@ void pfServerIni::Apply() gNetGateKeeperDhConstants = fGateKeeperDhConstants; } -ST::string pfServerIni::Load(const plFileName& fileName) +bool pfServerIni::Load(const plFileName& fileName, ST::string& errorMsg) { pfServerIni ini; - ST::string errorMsg = ini.Parse(fileName); - if (!errorMsg.empty()) { - return errorMsg; + if (!ini.Parse(fileName, errorMsg)) { + return false; } ini.Apply(); - return {}; + return true; } diff --git a/Sources/Plasma/FeatureLib/pfConsoleCore/pfServerIni.h b/Sources/Plasma/FeatureLib/pfConsoleCore/pfServerIni.h index ab974aaeb2..3e47c2dfd8 100644 --- a/Sources/Plasma/FeatureLib/pfConsoleCore/pfServerIni.h +++ b/Sources/Plasma/FeatureLib/pfConsoleCore/pfServerIni.h @@ -79,13 +79,13 @@ class pfServerIni {} private: - ST::string IParseOption(const std::vector& name, const ST::string& value); + bool IParseOption(const std::vector& name, const ST::string& value, ST::string& errorMsg); public: - ST::string Parse(const plFileName& fileName); + bool Parse(const plFileName& fileName, ST::string& errorMsg); void Apply(); - static ST::string Load(const plFileName& fileName); + static bool Load(const plFileName& fileName, ST::string& errorMsg); }; #endif // _pfServerIni_h diff --git a/Sources/Tools/plFilePatcher/plFilePatcher.cpp b/Sources/Tools/plFilePatcher/plFilePatcher.cpp index 3e9b3b734e..7809fa7858 100644 --- a/Sources/Tools/plFilePatcher/plFilePatcher.cpp +++ b/Sources/Tools/plFilePatcher/plFilePatcher.cpp @@ -61,8 +61,8 @@ plFilePatcher::plFilePatcher(plFileName serverIni) bool plFilePatcher::ILoadServerIni() { - ST::string errorMsg = pfServerIni::Load(fServerIni); - if (!errorMsg.empty()) { + ST::string errorMsg; + if (!pfServerIni::Load(fServerIni, errorMsg)) { ISetNetError(ST::format("Error in server config file {}: {}", fServerIni, errorMsg)); return false; } else {