/* Copyright© 2021 John Sennesael UsenetSearch is Free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. UsenetSearch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with UsenetSearch. If not, see . */ #include "usenetsearch/Configuration.h" #include "usenetsearch/Logger.h" #include "usenetsearch/ScopeExit.h" #include "usenetsearch/StringUtils.h" #include #include #include #include namespace usenetsearch { std::uint16_t Configuration::BatchSize() const { return m_batchSize; } std::filesystem::path Configuration::DatabasePath() const { return m_databasePath; } std::vector& Configuration::FilterEraseSubtoken() { return m_filterEraseSubtoken; } std::vector& Configuration::FilterNewsgroupBlacklist() { return m_filterNewsgroupBlacklist; } std::vector& Configuration::FilterNewsgroupWhitelist() { return m_filterNewsgroupWhitelist; } std::vector& Configuration::FilterWordsNoSubtoken() { return m_filterWordsNoSubtoken; } std::uint16_t Configuration::MaxThreads() const { return m_maxThreads; } std::uint8_t Configuration::MaxTreeDepth() const { return m_maxTreeDepth; } std::uint16_t Configuration::MinSubtokenWords() const { return m_minSubtokenWords; } std::string Configuration::NNTPServerHost() const { return m_nntpServerHost; } std::string Configuration::NNTPServerPassword() const { return m_nntpServerPassword; } int Configuration::NNTPServerPort() const { return m_nntpServerPort; } bool Configuration::NNTPServerSSL() const { return m_nntpServerSSL; } std::string Configuration::NNTPServerUser() const { return m_nntpServerUser; } void Configuration::Open(const std::string& filename) { std::string line; std::ifstream fin(filename.c_str()); if (!fin.is_open()) { Logger::Get().Fatal( LOGID("Configuration"), "Could not open configuration file: " + filename ); } ScopeExit finCloser([&fin](){ fin.close(); }); int line_nr = 0; while(std::getline(fin,line)) { line_nr++; line = StringTrim(line); // Immediately skip blank lines. if (line == "") continue; // Skip comments. if (StringStartsWith("#",line)==true) continue; // Split line in key-value pair. const auto kvp = StringSplit(line, std::string{":"}, 2); if (kvp.size() != 2) { Logger::Get().Fatal( LOGID("Configuration"), std::string("Invalid configuration in ") + filename + std::string(" line ") + std::to_string(line_nr) ); } const std::string key = StringToLower(kvp[0]); const std::string value = StringTrim(kvp[1]); if (key == "batch_size") { m_batchSize = stoi(value); } else if (key == "database_path") { m_databasePath = value; } else if (key == "filter_erase_subtoken") { const auto tokens = StringSplit(value, std::string{","}); for (const auto& token: tokens) { const auto trimmedToken = StringToLower(StringTrim(token)); if (trimmedToken != "") { m_filterEraseSubtoken.emplace_back(trimmedToken); } } } else if (key == "filter_newsgroup_blacklist") { try { std::regex re(value); m_filterNewsgroupBlacklist.emplace_back(re); } catch (const std::regex_error& e) { Logger::Get().Fatal( LOGID("Configuration"), std::string("Invalid configuration in ") + filename + std::string(" line ") + std::to_string(line_nr) + " : Regular expression \"" + value + "\" did not parse: " + e.what() ); } } else if (key == "filter_newsgroup_whitelist") { try { std::regex re(value); m_filterNewsgroupWhitelist.emplace_back(re); } catch (const std::regex_error& e) { Logger::Get().Fatal( LOGID("Configuration"), std::string("Invalid configuration in ") + filename + std::string(" line ") + std::to_string(line_nr) + " : Regular expression \"" + value + "\" did not parse: " + e.what() ); } } else if (key == "filter_no_subtoken") { const auto tokens = StringSplit(value, std::string{","}); for (const auto& token: tokens) { const auto trimmedToken = StringToLower(StringTrim(token)); if (trimmedToken != "") { m_filterWordsNoSubtoken.emplace_back(trimmedToken); } } } else if (key == "max_threads") { m_maxThreads = stoi(value); } else if (key == "max_tree_depth") { m_maxTreeDepth = stoi(value); } else if (key == "minimum_subtoken_words") { m_minSubtokenWords = stoi(value); } else if (key == "nntp_server_host") { m_nntpServerHost = value; } else if (key == "nntp_server_pass") { m_nntpServerPassword = value; } else if (key == "nntp_server_port") { m_nntpServerPort = stoi(value); } else if (key == "nntp_server_use_ssl") { try { m_nntpServerSSL = StringToBoolean(value); } catch (const StringException& e) { fin.close(); Logger::Get().Fatal( LOGID("Configuration"), std::string("Invalid configuration in ") + filename + std::string(" line ") + std::to_string(line_nr) + " - " + e.what() ); } } else if (key == "nntp_server_user") { m_nntpServerUser = value; } else { Logger::Get().Fatal( LOGID("Configuration"), std::string("Invalid configuration in ") + filename + std::string(" line ") + std::to_string(line_nr) ); } } } } // namespace usenetsearch