From adeaf41e3ba05304d9295342ed8a13af13acdf01 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sun, 17 Jul 2022 16:58:03 +0100 Subject: [PATCH] [Feature] Add ability to statically maintain disabled/enabled patterns --- src/libserver/symcache/symcache_internal.hxx | 134 +++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/src/libserver/symcache/symcache_internal.hxx b/src/libserver/symcache/symcache_internal.hxx index 063777a71..ea583a199 100644 --- a/src/libserver/symcache/symcache_internal.hxx +++ b/src/libserver/symcache/symcache_internal.hxx @@ -143,6 +143,97 @@ public: sym(_sym), cbref(_cbref), L(_L) {} }; +class delayed_symbol_elt { +private: + std::variant content; +public: + /* Disable copy */ + delayed_symbol_elt() = delete; + delayed_symbol_elt(const delayed_symbol_elt &) = delete; + delayed_symbol_elt &operator=(const delayed_symbol_elt &) = delete; + /* Enable move */ + delayed_symbol_elt(delayed_symbol_elt &&other) noexcept = default; + delayed_symbol_elt &operator=(delayed_symbol_elt &&other) noexcept = default; + + explicit delayed_symbol_elt(std::string_view elt) noexcept { + if (!elt.empty() && elt[0] == '/') { + /* Possibly regexp */ + auto *re = rspamd_regexp_new_len(elt.data(), elt.size(), nullptr, nullptr); + + if (re != nullptr) { + std::get(content) = re; + } + else { + std::get(content) = elt; + } + } + else { + std::get(content) = elt; + } + } + + ~delayed_symbol_elt() { + if (std::holds_alternative(content)) { + rspamd_regexp_unref(std::get(content)); + } + } + + auto matches(std::string_view what) const -> bool { + return std::visit([&](auto &elt) { + using T = typeof(elt); + if constexpr (std::is_same_v) { + if (rspamd_regexp_match(elt, what.data(), what.size(), false)) { + return true; + } + } + else if constexpr (std::is_same_v) { + return elt == what; + } + + return false; + }, + content); + } + + auto to_string_view() const -> std::string_view { + return std::visit([&](auto &elt) { + using T = typeof(elt); + if constexpr (std::is_same_v) { + return std::string_view{rspamd_regexp_get_pattern(elt)}; + } + else if constexpr (std::is_same_v) { + return std::string_view{elt}; + } + + return std::string_view{}; + }, + content); + } +}; + +struct delayed_symbol_elt_equal { + using is_transparent = void; + auto operator()(const delayed_symbol_elt &a, const delayed_symbol_elt &b) const { + return a.to_string_view() == b.to_string_view(); + } + auto operator()(const delayed_symbol_elt &a, const std::string_view &b) const { + return a.to_string_view() == b; + } + auto operator()(const std::string_view &a, const delayed_symbol_elt &b) const { + return a == b.to_string_view(); + } +}; + +struct delayed_symbol_elt_hash { + using is_transparent = void; + auto operator()(const delayed_symbol_elt &a) const { + return ankerl::unordered_dense::hash()(a.to_string_view()); + } + auto operator()(const std::string_view &a) const { + return ankerl::unordered_dense::hash()(a); + } +}; + class symcache { private: using items_ptr_vec = std::vector; @@ -167,6 +258,11 @@ private: /* These are stored within pointer to clean up after init */ std::unique_ptr> delayed_deps; std::unique_ptr> delayed_conditions; + /* Delayed statically enabled or disabled symbols */ + using delayed_symbol_names = ankerl::unordered_dense::set; + std::unique_ptr disabled_symbols; + std::unique_ptr enabled_symbols; rspamd_mempool_t *static_pool; std::uint64_t cksum; @@ -261,6 +357,44 @@ public: delayed_deps->emplace_back(from, to); } + /** + * Adds a symbol to the list of the disabled symbols + * @param sym + * @return + */ + auto disable_symbol_delayed(std::string_view sym) -> bool { + if (!disabled_symbols) { + disabled_symbols = std::make_unique(); + } + + if (!disabled_symbols->contains(sym)) { + disabled_symbols->emplace(sym); + + return true; + } + + return false; + } + + /** + * Adds a symbol to the list of the enabled symbols + * @param sym + * @return + */ + auto enable_symbol_delayed(std::string_view sym) -> bool { + if (!enabled_symbols) { + enabled_symbols = std::make_unique(); + } + + if (!enabled_symbols->contains(sym)) { + enabled_symbols->emplace(sym); + + return true; + } + + return false; + } + /** * Initialises the symbols cache, must be called after all symbols are added * and the config file is loaded -- 2.39.5