aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rspamd.com>2023-06-25 19:37:58 +0100
committerVsevolod Stakhov <vsevolod@rspamd.com>2023-06-25 19:37:58 +0100
commit2872db14ef3052bffcdd66d78b20c4b519b3aee0 (patch)
tree709fe9e4f040b923678977c40ce38b415033c59c /src
parent0a040522ca656f1e689335e821968e37b43ee5c1 (diff)
downloadrspamd-2872db14ef3052bffcdd66d78b20c4b519b3aee0.tar.gz
rspamd-2872db14ef3052bffcdd66d78b20c4b519b3aee0.zip
[Feature] Preliminary implementation of dynamic composites
Diffstat (limited to 'src')
-rw-r--r--src/libserver/composites/composites_internal.hxx2
-rw-r--r--src/libserver/composites/composites_manager.cxx111
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