From e1b675baf0daf04422d4f99cd218adb821a60ff8 Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 26 Apr 2024 17:19:39 +0200 Subject: [PATCH] Fix key validation --- src/sources/CommandLineHandler.cpp | 202 ++++++++++++++--------------- src/sources/KeyValidator.cpp | 39 +++--- 2 files changed, 125 insertions(+), 116 deletions(-) diff --git a/src/sources/CommandLineHandler.cpp b/src/sources/CommandLineHandler.cpp index 5e1cf7210..6e3a0cb3b 100644 --- a/src/sources/CommandLineHandler.cpp +++ b/src/sources/CommandLineHandler.cpp @@ -20,119 +20,119 @@ namespace cli { void CommandLineHandler::printHelp() { - LOG_INFO << "Printing help message..."; - OUTPUT << BOLD << "Usage:\n" - << RESET << "----------\n" - << config::EXECUTABLE_NAME << " [options] [filenames]\n" - << "\n" - << BOLD << "Options:\n" - << RESET << "----------\n" - << "-o, --outdir\t [path]\t\tOutput the batch file to the given " - "dir\n" - << "-h, --help\t\t\tPrint this help message\n" - << "-v, --version\t\t\tPrint the version number\n" - << "-c, --credits\t\t\tPrint the credits\n\n" - << " --verbose\t\t\tStart the application in verbose mode\n" - << ITALIC - << " \t\t\tNote: Verbose flag should be passed first!\n\n" - << RESET << BOLD << "Filenames:\n" - << RESET << "----------\n" - << "The json files to be processed into batch files.\n" - << "Multiple files should be seperated by spaces!\n\n"; - exit(0); + LOG_INFO << "Printing help message..."; + OUTPUT << BOLD << "Usage:\n" + << RESET << "----------\n" + << config::EXECUTABLE_NAME << " [options] [filenames]\n" + << "\n" + << BOLD << "Options:\n" + << RESET << "----------\n" + << "-o, --outdir\t [path]\t\tOutput the batch file to the given " + "dir\n" + << "-h, --help\t\t\tPrint this help message\n" + << "-v, --version\t\t\tPrint the version number\n" + << "-c, --credits\t\t\tPrint the credits\n\n" + << " --verbose\t\t\tStart the application in verbose mode\n" + << ITALIC + << " \t\t\tNote: Verbose flag should be passed first!\n\n" + << RESET << BOLD << "Filenames:\n" + << RESET << "----------\n" + << "The json files to be processed into batch files.\n" + << "Multiple files should be seperated by spaces!\n\n"; + exit(0); } void CommandLineHandler::printVersion() { - LOG_INFO << "Printing version number..."; - OUTPUT << config::PROJECT_NAME << " v" << config::MAJOR_VERSION << "." - << config::MINOR_VERSION << "." << config::PATCH_VERSION << "\n"; - exit(0); + LOG_INFO << "Printing version number..."; + OUTPUT << config::PROJECT_NAME << " v" << config::MAJOR_VERSION << "." + << config::MINOR_VERSION << "." << config::PATCH_VERSION << "\n"; + exit(0); } void CommandLineHandler::printCredits() { - LOG_INFO << "Printing credits..."; - OUTPUT << BOLD << "Project information:\n" - << RESET << "----------\n" - << CYAN << BOLD << config::PROJECT_NAME << RESET << " v" - << config::MAJOR_VERSION << "." << config::MINOR_VERSION << "." - << config::PATCH_VERSION << "\n" - << "\n" - << config::DESCRIPTION << "\n" - << "\n" - << GREEN << "Authors: " << RESET << ITALIC << config::AUTHORS << RESET - << "\n" - << GREEN << "Documentation: " << RESET << ITALIC - << config::HOMEPAGE_URL << RESET << GREEN << "\nContact: " << RESET - << ITALIC << "simon21.blum@gmail.com" << "\n"; - exit(0); + LOG_INFO << "Printing credits..."; + OUTPUT << BOLD << "Project information:\n" + << RESET << "----------\n" + << CYAN << BOLD << config::PROJECT_NAME << RESET << " v" + << config::MAJOR_VERSION << "." << config::MINOR_VERSION << "." + << config::PATCH_VERSION << "\n" + << "\n" + << config::DESCRIPTION << "\n" + << "\n" + << GREEN << "Authors: " << RESET << ITALIC << config::AUTHORS << RESET + << "\n" + << GREEN << "Documentation: " << RESET << ITALIC + << config::HOMEPAGE_URL << RESET << GREEN << "\nContact: " << RESET + << ITALIC << "simon21.blum@gmail.com" << "\n"; + exit(0); } std::tuple, std::vector> CommandLineHandler::parseArguments(int argc, char *argv[]) { - LOG_INFO << "Parsing arguments..."; - std::vector files; - std::optional outDir; - - while (true) { - int optIndex = -1; - struct option longOption = {}; - const auto result = getopt_long(argc, argv, "hvco:", options, &optIndex); - - if (result == -1) { - LOG_INFO << "End of options reached"; - break; + LOG_INFO << "Parsing arguments..."; + std::vector files; + std::optional outDir; + + while (true) { + int optIndex = -1; + struct option longOption = {}; + const auto result = getopt_long(argc, argv, "hvco:", options, &optIndex); + + if (result == -1) { + LOG_INFO << "End of options reached"; + break; + } + + switch (result) { + case '?': + LOG_ERROR << "Invalid Option (argument)"; + CommandLineHandler::printHelp(); + + case 'h': + LOG_INFO << "Help option detected"; + CommandLineHandler::printHelp(); + + case 'v': + LOG_INFO << "Version option detected"; + CommandLineHandler::printVersion(); + + case 'c': + LOG_INFO << "Credit option detected"; + CommandLineHandler::printCredits(); + + case 'o': + LOG_INFO << "Output option detected"; + outDir = optarg; + break; + + case 0: + LOG_INFO << "Long option without short version detected"; + longOption = options[optIndex]; + LOG_INFO << "Option: " << longOption.name << " given"; + + if (strcmp(longOption.name, "verbose") == 0) { + logging::setVerboseMode(true); + LOG_INFO << "Verbose mode activated"; + } + + break; + + default: + LOG_ERROR << "Default case for options reached!"; + break; + } } - switch (result) { - case '?': - LOG_ERROR << "Invalid Option (argument)"; - CommandLineHandler::printHelp(); + LOG_INFO << "Options have been parsed"; + LOG_INFO << "Checking for arguments..."; - case 'h': - LOG_INFO << "Help option detected"; - CommandLineHandler::printHelp(); - - case 'v': - LOG_INFO << "Version option detected"; - CommandLineHandler::printVersion(); - - case 'c': - LOG_INFO << "Credit option detected"; - CommandLineHandler::printCredits(); - - case 'o': - LOG_INFO << "Output option detected"; - outDir = optarg; - break; - - case 0: - LOG_INFO << "Long option without short version detected"; - longOption = options[optIndex]; - LOG_INFO << "Option: " << longOption.name << " given"; - - if (strcmp(longOption.name, "verbose") == 0) { - logging::setVerboseMode(true); - LOG_INFO << "Verbose mode activated"; - } - - break; - - default: - LOG_ERROR << "Default case for options reached!"; - break; + // Loop for {reqFunc5} + while (optind < argc) { + LOG_INFO << "Adding file: " << argv[optind]; + // Vector for {reqFunc7} + files.emplace_back(argv[optind++]); } - } - - LOG_INFO << "Options have been parsed"; - LOG_INFO << "Checking for arguments..."; - - // Loop for {reqFunc5} - while (optind < argc) { - LOG_INFO << "Adding file: " << argv[optind]; - // Vector for {reqFunc7} - files.emplace_back(argv[optind++]); - } - LOG_DEBUG << files.size(); - LOG_INFO << "Arguments and options have been parsed"; - return {outDir, files}; + LOG_DEBUG << files.size(); + LOG_INFO << "Arguments and options have been parsed"; + return {outDir, files}; } } // namespace cli diff --git a/src/sources/KeyValidator.cpp b/src/sources/KeyValidator.cpp index ef6267db4..e9f985b71 100644 --- a/src/sources/KeyValidator.cpp +++ b/src/sources/KeyValidator.cpp @@ -23,36 +23,43 @@ KeyValidator &KeyValidator::getInstance() { return keyValidator; } -std::vector> KeyValidator::validateKeys( - const Json::Value &root, - const std::string &filename) { +std::vector> +KeyValidator::validateKeys(const Json::Value &root, + const std::string &filename) { + LOG_INFO << "Validating keys for file " << filename; std::vector> wrongKeys = getWrongKeys(root, filename); // Inline declaration to prevent leaking in outer scope for (Json::Value entries = root.get("entries", ""); const auto &entry : entries) { + LOG_INFO << "Validating entry"; const auto entryKeys = entry.getMemberNames(); // Create a set of the entry keys for faster lookup (O(1) instead of O(n)) std::unordered_set entryKeysSet(entryKeys.begin(), entryKeys.end()); + const auto wrongEntries = validateEntries(filename, entryKeysSet); + // Combine wrong keys wrongKeys.insert(wrongKeys.end(), wrongEntries.begin(), wrongEntries.end()); - // Validate that each entry has it's necessary keys + + LOG_INFO << "Validating types for entry"; validateTypes(filename, entry, entryKeysSet); } return wrongKeys; } -std::vector> KeyValidator::getWrongKeys( - const Json::Value &root, - const std::string &filename) const { +std::vector> +KeyValidator::getWrongKeys(const Json::Value &root, + const std::string &filename) const { std::vector> wrongKeys = {}; + LOG_INFO << "Checcking for wrong keys in file " << filename << "!"; for (const auto &key : root.getMemberNames()) { if (!validKeys.contains(key)) { + LOG_WARNING << "Found wrong key " << key << "!"; const auto error = getUnknownKeyLine(filename, key); if (!error.has_value()) { @@ -74,6 +81,7 @@ std::vector> KeyValidator::validateEntries( std::vector> wrongKeys = {}; for (const auto &key : entryKeys) { + LOG_INFO << "Checking key " << key << "!"; if (!validEntryKeys.contains(key)) { const auto error = getUnknownKeyLine(filename, key); @@ -94,14 +102,14 @@ void KeyValidator::validateTypes( const std::unordered_set &entryKeys) { // Gett the type of the entry - error if not found const std::string type = entry.get("type", "ERROR").asString(); + LOG_INFO << "Validating type " << type; // If the type is not found, throw an exception if (type == "ERROR") { throw exceptions::MissingTypeException(); // If the type is not known, throw an exception // @note This should already have been checked - } - else if (typeToKeys.contains(type)) { + } else if (!typeToKeys.contains(type)) { const std::optional line = getUnknownKeyLine(filename, std::string(type)); @@ -111,18 +119,19 @@ void KeyValidator::validateTypes( throw exceptions::InvalidTypeException(std::string(type), line.value()); // If the type is known, check if all necessary keys are present - } - else { + } else { for (const auto &key : typeToKeys[type]) { - if (entryKeys.contains(key)) { - throw exceptions::MissingKeyException(key, std::string(type)); + LOG_INFO << "Checking key " << key << " for type " << type; + if (!entryKeys.contains(key)) { + throw exceptions::MissingKeyException(key, type); } } } } -std::optional KeyValidator::getUnknownKeyLine(const std::string &filename, - const std::string &wrongKey) { +std::optional +KeyValidator::getUnknownKeyLine(const std::string &filename, + const std::string &wrongKey) { std::ifstream file(filename); if (!file.is_open()) {