diff -r ef0f2497843e -r 730a5638c4ad src/settings.cpp --- a/src/settings.cpp Sat Feb 01 15:42:48 2025 +0100 +++ b/src/settings.cpp Sat Feb 01 16:01:14 2025 +0100 @@ -26,24 +26,75 @@ #include #include +#include using namespace fm; +static bool check_author(std::string_view author, std::string_view allowed) { + // check for exact match + if (author == allowed) return true; + + // check mail address matching + if (author.contains(std::format("<{}>", allowed))) return true; + + // check local-part from mail address matching + if (author.contains(std::format("<{}@", allowed))) return true; + + return false; +} + [[nodiscard]] bool settings::exclude_author(const std::string &author) const { // no allow-list means: always allowed if (authors.empty()) return false; // check all allowed authors - return std::ranges::all_of(authors, [&](const auto &allowed) { - // check for exact match - if (author == allowed) return false; - - // check mail address matching - if (author.contains(std::format("<{}>", allowed))) return false; - - // check local-part from mail address matching - if (author.contains(std::format("<{}@", allowed))) return false; - - return true; + return !std::ranges::any_of(authors, [&](const auto &allowed) { + return check_author(author, allowed); }); } + +std::string_view trim(const std::string& str) { + size_t s = str.find_first_not_of(" \t"); + size_t l = str.find_last_not_of(" \t") + 1 - s; + return std::string_view{str}.substr(s, l); +} + +int settings::parse_authormap(const std::string& path) { + std::ifstream file(path); + + if (!file.is_open()) { + return -1; + } + + std::string line; + while (std::getline(file, line)) { + line = trim(line); + + // skip empty lines and comments + if (line.empty() || line[0] == '#') { + continue; + } + + // find delimiter + size_t delimPos = line.find('='); + if (delimPos == std::string::npos) { + return -1; + } + + auto key = std::string{trim(line.substr(0, delimPos))}; + auto value = std::string{trim(line.substr(delimPos + 1))}; + authormap[std::move(key)] = std::move(value); + } + + return 0; +} + +std::string settings::map_author(std::string_view author) const { + if (authormap.empty()) return std::string{author}; + + for (const auto &[old_name, new_name] : authormap) { + if (check_author(author, old_name)) return new_name; + } + + return std::string{author}; +}