From f57c6e2c50e05aebbc9020fc9fe58b647b15b9dd Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Tue, 15 May 2018 14:21:41 +0100 Subject: [PATCH] [Feature] Allow multiple groups for symbols --- src/libmime/filter.c | 4 +- src/libserver/cfg_file.h | 26 +++++++--- src/libserver/cfg_rcl.c | 34 ++++++++++++- src/libserver/cfg_utils.c | 101 ++++++++++++++++++++++++++++++++------ src/lua/lua_config.c | 65 ++++++++++++++++++++++++ src/lua/lua_task.c | 12 +++++ src/plugins/dkim_check.c | 3 +- src/plugins/regexp.c | 16 ++++++ 8 files changed, 237 insertions(+), 24 deletions(-) diff --git a/src/libmime/filter.c b/src/libmime/filter.c index f7d4e3410..c9367514f 100644 --- a/src/libmime/filter.c +++ b/src/libmime/filter.c @@ -92,6 +92,7 @@ insert_metric_result (struct rspamd_task *task, struct rspamd_symbols_group *gr = NULL; const ucl_object_t *mobj, *sobj; gint max_shots; + guint i; gboolean single = !!(flags & RSPAMD_SYMBOL_INSERT_SINGLE); metric_res = rspamd_create_metric_result (task); @@ -113,9 +114,8 @@ insert_metric_result (struct rspamd_task *task, } else { final_score = (*sdef->weight_ptr) * weight; - gr = sdef->gr; - if (gr != NULL) { + PTR_ARRAY_FOREACH (sdef->groups, i, gr) { gr_score = g_hash_table_lookup (metric_res->sym_groups, gr); if (gr_score == NULL) { diff --git a/src/libserver/cfg_file.h b/src/libserver/cfg_file.h index 7a6cc1c8a..5a846a1f5 100644 --- a/src/libserver/cfg_file.h +++ b/src/libserver/cfg_file.h @@ -123,8 +123,8 @@ struct rspamd_symbol { gdouble *weight_ptr; gdouble score; guint priority; - struct rspamd_symbols_group *gr; - GList *groups; + struct rspamd_symbols_group *gr; /* Main group */ + GPtrArray *groups; /* Other groups */ guint flags; gint nshots; }; @@ -585,10 +585,24 @@ gboolean rspamd_init_filters (struct rspamd_config *cfg, bool reconfig); * @return TRUE if symbol has been inserted or FALSE if symbol already exists with higher priority */ gboolean rspamd_config_add_symbol (struct rspamd_config *cfg, - const gchar *symbol, gdouble score, const gchar *description, - const gchar *group, guint flags, - guint priority, - gint nshots); + const gchar *symbol, + gdouble score, + const gchar *description, + const gchar *group, + guint flags, + guint priority, + gint nshots); + +/** + * Adds new group for a symbol + * @param cfg + * @param symbol + * @param group + * @return + */ +gboolean rspamd_config_add_symbol_group (struct rspamd_config *cfg, + const gchar *symbol, + const gchar *group); /** * Sets action score for a specified metric with the specified priority diff --git a/src/libserver/cfg_rcl.c b/src/libserver/cfg_rcl.c index 47e730af0..d4aa5314b 100644 --- a/src/libserver/cfg_rcl.c +++ b/src/libserver/cfg_rcl.c @@ -438,6 +438,22 @@ rspamd_rcl_symbol_handler (rspamd_mempool_t *pool, const ucl_object_t *obj, description, NULL, flags, priority, nshots); } + elt = ucl_object_lookup (obj, "groups"); + + if (elt) { + ucl_object_iter_t gr_it; + const ucl_object_t *cur_gr; + + gr_it = ucl_object_iterate_new (elt); + + while ((cur_gr = ucl_object_iterate_safe (gr_it, true)) != NULL) { + rspamd_config_add_symbol_group (cfg, key, + ucl_object_tostring (cur_gr)); + } + + ucl_object_iterate_free (gr_it); + } + return TRUE; } @@ -1423,7 +1439,7 @@ rspamd_rcl_composite_handler (rspamd_mempool_t *pool, struct rspamd_rcl_section *section, GError **err) { - const ucl_object_t *val; + const ucl_object_t *val, *elt; struct rspamd_expression *expr; struct rspamd_config *cfg = ud; struct rspamd_composite *composite; @@ -1500,6 +1516,22 @@ rspamd_rcl_composite_handler (rspamd_mempool_t *pool, rspamd_config_add_symbol (cfg, composite_name, score, description, group, FALSE, FALSE, 1); + + elt = ucl_object_lookup (obj, "groups"); + + if (elt) { + ucl_object_iter_t gr_it; + const ucl_object_t *cur_gr; + + gr_it = ucl_object_iterate_new (elt); + + while ((cur_gr = ucl_object_iterate_safe (gr_it, true)) != NULL) { + rspamd_config_add_symbol_group (cfg, key, + ucl_object_tostring (cur_gr)); + } + + ucl_object_iterate_free (gr_it); + } } val = ucl_object_lookup (obj, "policy"); diff --git a/src/libserver/cfg_utils.c b/src/libserver/cfg_utils.c index ed9876b8d..bf63b2188 100644 --- a/src/libserver/cfg_utils.c +++ b/src/libserver/cfg_utils.c @@ -1470,6 +1470,9 @@ rspamd_config_new_symbol (struct rspamd_config *cfg, const gchar *symbol, sym_def->priority = priority; sym_def->flags = flags; sym_def->nshots = nshots; + sym_def->groups = g_ptr_array_sized_new (1); + rspamd_mempool_add_destructor (cfg->cfg_pool, rspamd_ptr_array_free_hard, + sym_def->groups); if (description) { sym_def->description = rspamd_mempool_strdup (cfg->cfg_pool, description); @@ -1502,30 +1505,49 @@ rspamd_config_new_symbol (struct rspamd_config *cfg, const gchar *symbol, gboolean rspamd_config_add_symbol (struct rspamd_config *cfg, - const gchar *symbol, - gdouble score, const gchar *description, const gchar *group, - guint flags, guint priority, gint nshots) + const gchar *symbol, + gdouble score, const gchar *description, + const gchar *group, + guint flags, guint priority, gint nshots) { struct rspamd_symbol *sym_def; + struct rspamd_symbols_group *sym_group; + guint i; + g_assert (cfg != NULL); g_assert (symbol != NULL); - struct rspamd_symbols_group *sym_group; sym_def = g_hash_table_lookup (cfg->symbols, symbol); if (sym_def != NULL) { - if (sym_def->flags & RSPAMD_SYMBOL_FLAG_UNGROUPPED && group != NULL) { - /* Non-empty group has a priority over non-groupped one */ - sym_group = g_hash_table_lookup (cfg->groups, group); - - if (sym_group == NULL) { - /* Create new group */ - sym_group = rspamd_config_new_group (cfg, group); + if (group != NULL) { + gboolean has_group = FALSE; + + PTR_ARRAY_FOREACH (sym_def->groups, i, sym_group) { + if (g_ascii_strcasecmp (sym_group->name, group) == 0) { + /* Group is already here */ + has_group = TRUE; + break; + } } - sym_def->gr = sym_group; - g_hash_table_insert (sym_group->symbols, sym_def->name, sym_def); - sym_def->flags &= ~(RSPAMD_SYMBOL_FLAG_UNGROUPPED); + if (!has_group) { + /* Non-empty group has a priority over non-groupped one */ + sym_group = g_hash_table_lookup (cfg->groups, group); + + if (sym_group == NULL) { + /* Create new group */ + sym_group = rspamd_config_new_group (cfg, group); + } + + if (!sym_def->gr) { + sym_def->gr = sym_group; + } + + g_hash_table_insert (sym_group->symbols, sym_def->name, sym_def); + sym_def->flags &= ~(RSPAMD_SYMBOL_FLAG_UNGROUPPED); + g_ptr_array_add (sym_def->groups, sym_group); + } } if (sym_def->priority > priority) { @@ -1592,6 +1614,57 @@ rspamd_config_add_symbol (struct rspamd_config *cfg, return TRUE; } +gboolean +rspamd_config_add_symbol_group (struct rspamd_config *cfg, + const gchar *symbol, + const gchar *group) +{ + struct rspamd_symbol *sym_def; + struct rspamd_symbols_group *sym_group; + guint i; + + g_assert (cfg != NULL); + g_assert (symbol != NULL); + g_assert (group != NULL); + + sym_def = g_hash_table_lookup (cfg->symbols, symbol); + + if (sym_def != NULL) { + gboolean has_group = FALSE; + + PTR_ARRAY_FOREACH (sym_def->groups, i, sym_group) { + if (g_ascii_strcasecmp (sym_group->name, group) == 0) { + /* Group is already here */ + has_group = TRUE; + break; + } + } + + if (!has_group) { + /* Non-empty group has a priority over non-groupped one */ + sym_group = g_hash_table_lookup (cfg->groups, group); + + if (sym_group == NULL) { + /* Create new group */ + sym_group = rspamd_config_new_group (cfg, group); + } + + if (!sym_def->gr) { + sym_def->gr = sym_group; + } + + g_hash_table_insert (sym_group->symbols, sym_def->name, sym_def); + sym_def->flags &= ~(RSPAMD_SYMBOL_FLAG_UNGROUPPED); + g_ptr_array_add (sym_def->groups, sym_group); + + return TRUE; + } + } + + return FALSE; +} + + gboolean rspamd_config_is_module_enabled (struct rspamd_config *cfg, const gchar *module_name) diff --git a/src/lua/lua_config.c b/src/lua/lua_config.c index a42f33b37..6e502d6e7 100644 --- a/src/lua/lua_config.c +++ b/src/lua/lua_config.c @@ -1641,6 +1641,23 @@ lua_config_register_symbol (lua_State * L) rspamd_config_add_symbol (cfg, name, score, description, group, flags, (guint) priority, nshots); + + lua_pushstring (L, "groups"); + lua_gettable (L, 2); + + if (lua_istable (L, -1)) { + for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) { + if (lua_isstring (L, -1)) { + rspamd_config_add_symbol_group (cfg, name, + lua_tostring (L, -1)); + } + else { + return luaL_error (L, "invalid groups element"); + } + } + } + + lua_pop (L, 1); } } else { @@ -1997,6 +2014,25 @@ lua_config_set_metric_symbol (lua_State * L) rspamd_config_add_symbol (cfg, name, weight, description, group, flags, (guint) priority, nshots); + + + if (lua_type (L, 2) == LUA_TTABLE) { + lua_pushstring (L, "groups"); + lua_gettable (L, 2); + + if (lua_istable (L, -1)) { + for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) { + if (lua_isstring (L, -1)) { + rspamd_config_add_symbol_group (cfg, name, + lua_tostring (L, -1)); + } else { + return luaL_error (L, "invalid groups element"); + } + } + } + + lua_pop (L, 1); + } } else { return luaL_error (L, "invalid arguments, rspamd_config expected"); @@ -2011,6 +2047,8 @@ lua_config_get_metric_symbol (lua_State * L) struct rspamd_config *cfg = lua_check_config (L, 1); const gchar *sym_name = luaL_checkstring (L, 2); struct rspamd_symbol *sym_def; + struct rspamd_symbols_group *sym_group; + guint i; if (cfg && sym_name) { sym_def = g_hash_table_lookup (cfg->symbols, sym_name); @@ -2035,6 +2073,16 @@ lua_config_get_metric_symbol (lua_State * L) lua_pushstring (L, sym_def->gr->name); lua_settable (L, -3); } + + lua_pushstring (L, "groups"); + lua_createtable (L, sym_def->groups->len, 0); + + PTR_ARRAY_FOREACH (sym_def->groups, i, sym_group) { + lua_pushstring (L, sym_group->name); + lua_rawseti (L, -2, i + 1); + } + + lua_settable (L, -3); } } else { @@ -2376,6 +2424,23 @@ lua_config_newindex (lua_State *L) */ rspamd_config_add_symbol (cfg, name, score, description, group, flags, 0, nshots); + + lua_pushstring (L, "groups"); + lua_gettable (L, -2); + + if (lua_istable (L, -1)) { + for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) { + if (lua_isstring (L, -1)) { + rspamd_config_add_symbol_group (cfg, name, + lua_tostring (L, -1)); + } + else { + return luaL_error (L, "invalid groups element"); + } + } + } + + lua_pop (L, 1); } else { lua_pop (L, 1); diff --git a/src/lua/lua_task.c b/src/lua/lua_task.c index 17aee10b8..3aa24e88b 100644 --- a/src/lua/lua_task.c +++ b/src/lua/lua_task.c @@ -3053,6 +3053,8 @@ lua_push_symbol_result (lua_State *L, struct rspamd_metric_result *metric_res; struct rspamd_symbol_result *s = NULL; struct rspamd_symbol_option *opt; + struct rspamd_symbols_group *sym_group; + guint i; gint j = 1, e = 4; if (!symbol_result) { @@ -3089,6 +3091,16 @@ lua_push_symbol_result (lua_State *L, lua_pushstring (L, "group"); lua_pushstring (L, s->sym->gr->name); lua_settable (L, -3); + + lua_pushstring (L, "groups"); + lua_createtable (L, s->sym->groups->len, 0); + + PTR_ARRAY_FOREACH (s->sym->groups, i, sym_group) { + lua_pushstring (L, sym_group->name); + lua_rawseti (L, -2, i + 1); + } + + lua_settable (L, -3); } else { lua_pushstring (L, "group"); diff --git a/src/plugins/dkim_check.c b/src/plugins/dkim_check.c index d666289ec..8f63a167d 100644 --- a/src/plugins/dkim_check.c +++ b/src/plugins/dkim_check.c @@ -559,7 +559,8 @@ dkim_module_config (struct rspamd_config *cfg) rspamd_config_add_symbol (cfg, "DKIM_TRACE", 0.0, "DKIM trace symbol", "policies", RSPAMD_SYMBOL_FLAG_IGNORE, 1, 1); - + rspamd_config_add_symbol_group (cfg, "DKIM_SIGN", "dkim"); + rspamd_config_add_symbol_group (cfg, "DKIM_TRACE", "dkim"); } else { msg_err_config ("lua script must return " diff --git a/src/plugins/regexp.c b/src/plugins/regexp.c index 03dd21734..57b8e524e 100644 --- a/src/plugins/regexp.c +++ b/src/plugins/regexp.c @@ -305,6 +305,22 @@ regexp_module_config (struct rspamd_config *cfg) rspamd_config_add_symbol (cfg, cur_item->symbol, score, description, group, flags, priority, nshots); + + elt = ucl_object_lookup (value, "groups"); + + if (elt) { + ucl_object_iter_t gr_it; + const ucl_object_t *cur_gr; + + gr_it = ucl_object_iterate_new (elt); + + while ((cur_gr = ucl_object_iterate_safe (gr_it, true)) != NULL) { + rspamd_config_add_symbol_group (cfg, cur_item->symbol, + ucl_object_tostring (cur_gr)); + } + + ucl_object_iterate_free (gr_it); + } } } else { -- 2.39.5