commit 2872db1: [Feature] Preliminary implementation of dynamic composites

Vsevolod Stakhov vsevolod at rspamd.com
Sun Jun 25 18:42:03 UTC 2023


Author: Vsevolod Stakhov
Date: 2023-06-25 19:37:58 +0100
URL: https://github.com/rspamd/rspamd/commit/2872db14ef3052bffcdd66d78b20c4b519b3aee0 (HEAD -> master)

[Feature] Preliminary implementation of dynamic composites

---
 src/libserver/composites/composites_internal.hxx |   2 +-
 src/libserver/composites/composites_manager.cxx  | 111 ++++++++++++++++++++++-
 2 files changed, 109 insertions(+), 4 deletions(-)

diff --git a/src/libserver/composites/composites_internal.hxx b/src/libserver/composites/composites_internal.hxx
index 5b311fc6c..af05b95df 100644
--- a/src/libserver/composites/composites_internal.hxx
+++ b/src/libserver/composites/composites_internal.hxx
@@ -72,7 +72,7 @@ public:
 	}
 
 	auto add_composite(std::string_view, const ucl_object_t *, bool silent_duplicate) -> rspamd_composite *;
-	auto add_composite(std::string_view name, std::string_view expression, bool silent_duplicate) -> rspamd_composite *;
+	auto add_composite(std::string_view name, std::string_view expression, bool silent_duplicate, double score = NAN) -> rspamd_composite *;
 private:
 	~composites_manager() = default;
 	static void composites_manager_dtor(void *ptr) {
diff --git a/src/libserver/composites/composites_manager.cxx b/src/libserver/composites/composites_manager.cxx
index bf4491097..c0f6d3a49 100644
--- a/src/libserver/composites/composites_manager.cxx
+++ b/src/libserver/composites/composites_manager.cxx
@@ -23,6 +23,8 @@
 #include "composites_internal.hxx"
 #include "libserver/cfg_file.h"
 #include "libserver/logger.h"
+#include "libserver/maps/map.h"
+#include "libutil/cxx/util.hxx"
 
 namespace rspamd::composites {
 
@@ -149,7 +151,7 @@ composites_manager::add_composite(std::string_view composite_name, const ucl_obj
 auto
 composites_manager::add_composite(std::string_view composite_name,
 								  std::string_view composite_expression,
-								  bool silent_duplicate) -> rspamd_composite *
+								  bool silent_duplicate, double score) -> rspamd_composite *
 {
 	GError *err = nullptr;
 	rspamd_expression *expr = nullptr;
@@ -178,8 +180,8 @@ composites_manager::add_composite(std::string_view composite_name,
 		return nullptr;
 	}
 
-	auto score = std::isnan(cfg->unknown_weight) ? 0.0 : cfg->unknown_weight;
-	rspamd_config_add_symbol(cfg, composite_name.data(), score,
+	auto final_score = std::isnan(score) ? (std::isnan(cfg->unknown_weight) ? 0.0 : cfg->unknown_weight) : score;
+	rspamd_config_add_symbol(cfg, composite_name.data(), final_score,
 			composite_name.data(), "composite",
 			0,
 			0,
@@ -188,6 +190,89 @@ composites_manager::add_composite(std::string_view composite_name,
 	return new_composite(composite_name, expr, composite_expression).get();
 }
 
+struct map_cbdata {
+	composites_manager *cm;
+	struct rspamd_config *cfg;
+	std::string buf;
+
+	explicit map_cbdata(struct rspamd_config *cfg) : cfg(cfg) {
+		cm = COMPOSITE_MANAGER_FROM_PTR(cfg->composites_manager);
+	}
+
+	static char *map_read(char *chunk, int len,
+				  struct map_cb_data *data,
+				  gboolean _final) {
+
+		if (data->cur_data == nullptr) {
+			data->cur_data = data->prev_data;
+			reinterpret_cast<map_cbdata *>(data->cur_data)->buf.clear();
+		}
+
+		auto *cbd = reinterpret_cast<map_cbdata *>(data->cur_data);
+
+		cbd->buf.append(chunk, len);
+		return nullptr;
+	}
+
+	static void
+	map_fin(struct map_cb_data *data, void **target) {
+		auto *cbd = reinterpret_cast<map_cbdata *>(data->cur_data);
+
+		if (data->errored) {
+			if (cbd) {
+				cbd->buf.clear();
+			}
+		}
+		else if (cbd != nullptr) {
+			if (target) {
+				*target = data->cur_data;
+			}
+
+			rspamd::string_foreach_line(cbd->buf, [&](std::string_view line) {
+				auto [name_and_score, expr] = rspamd::string_split_on(line, ' ');
+				auto [name, score] = rspamd::string_split_on(name_and_score, ':');
+
+				if (!score.empty()) {
+					/* I wish it was supported properly */
+					//auto conv_res = std::from_chars(value->data(), value->size(), num);
+					char numbuf[128], *endptr = nullptr;
+					rspamd_strlcpy(numbuf, score.data(), MIN(score.size(), sizeof(numbuf)));
+					auto num = g_ascii_strtod(numbuf, &endptr);
+
+					if (fabs(num) >= G_MAXFLOAT || std::isnan(num)) {
+						msg_err("invalid score for %*s", (int)name_and_score.size(), name_and_score.data());
+						return;
+					}
+
+					auto ret = cbd->cm->add_composite(name, expr, true, num);
+
+					if (ret == nullptr) {
+						msg_err("cannot add composite %*s", (int)name_and_score.size(), name_and_score.data());
+						return;
+					}
+				}
+				else {
+					msg_err("missing score for %*s", (int)name_and_score.size(), name_and_score.data());
+					return;
+				}
+			});
+
+		}
+		else {
+			msg_err ("no data read for composites map");
+		}
+	}
+
+	static void
+	map_dtor (struct map_cb_data *data) {
+		auto *cbd = reinterpret_cast<map_cbdata *>(data->cur_data);
+
+		if (cbd) {
+			delete cbd;
+		}
+	}
+};
+
 }
 
 
@@ -229,3 +314,23 @@ rspamd_composites_manager_add_from_string_silent(void *cm, const char *sym, cons
 {
 	return reinterpret_cast<void *>(COMPOSITE_MANAGER_FROM_PTR(cm)->add_composite(sym, expr, true));
 }
+
+
+
+bool
+rspamd_composites_add_map_handlers(const ucl_object_t *obj, struct rspamd_config *cfg)
+{
+	auto **pcbdata = rspamd_mempool_alloc_type(cfg->cfg_pool, rspamd::composites::map_cbdata *);
+	auto *cbdata = new rspamd::composites::map_cbdata{cfg};
+	*pcbdata = cbdata;
+
+	if (struct rspamd_map *m; (m = rspamd_map_add_from_ucl(cfg, obj, "composites map",
+		rspamd::composites::map_cbdata::map_read, rspamd::composites::map_cbdata::map_fin,
+		rspamd::composites::map_cbdata::map_dtor, (void **)pcbdata,
+		nullptr, RSPAMD_MAP_DEFAULT)) == nullptr) {
+		msg_err_config("cannot load composites map from %s", ucl_object_key(obj));
+		return false;
+	}
+
+	return true;
+}
\ No newline at end of file


More information about the Commits mailing list