@@ -140,7 +140,7 @@ insert_metric_result (struct rspamd_task *task, | |||
/* Add metric score */ | |||
if ((s = g_hash_table_lookup (metric_res->symbols, symbol)) != NULL) { | |||
if (sdef && sdef->one_shot) { | |||
if (sdef && (sdef->flags & RSPAMD_SYMBOL_FLAG_ONESHOT)) { | |||
/* | |||
* For one shot symbols we do not need to add them again, so | |||
* we just force single behaviour here |
@@ -89,6 +89,9 @@ struct rspamd_symbols_group { | |||
gboolean one_shot; | |||
}; | |||
#define RSPAMD_SYMBOL_FLAG_ONESHOT (1 << 0) | |||
#define RSPAMD_SYMBOL_FLAG_IGNORE (1 << 1) | |||
/** | |||
* Symbol definition | |||
*/ | |||
@@ -99,7 +102,7 @@ struct rspamd_symbol_def { | |||
gdouble score; | |||
struct rspamd_symbols_group *gr; | |||
GList *groups; | |||
gboolean one_shot; | |||
guint flags; | |||
}; | |||
@@ -321,6 +321,7 @@ rspamd_rcl_symbol_handler (rspamd_mempool_t *pool, const ucl_object_t *obj, | |||
struct rspamd_symbol_def *sym_def; | |||
struct metric *metric; | |||
struct rspamd_config *cfg; | |||
const ucl_object_t *elt; | |||
GList *metric_list; | |||
g_assert (key != NULL); | |||
@@ -359,6 +360,18 @@ rspamd_rcl_symbol_handler (rspamd_mempool_t *pool, const ucl_object_t *obj, | |||
msg_warn_config ("redefining symbol '%s' in metric '%s'", key, metric->name); | |||
} | |||
if ((elt = ucl_object_find_key (obj, "one_shot")) != NULL) { | |||
if (ucl_object_toboolean (elt)) { | |||
sym_def->flags |= RSPAMD_SYMBOL_FLAG_ONESHOT; | |||
} | |||
} | |||
if ((elt = ucl_object_find_key (obj, "ignore")) != NULL) { | |||
if (ucl_object_toboolean (elt)) { | |||
sym_def->flags |= RSPAMD_SYMBOL_FLAG_IGNORE; | |||
} | |||
} | |||
if (!rspamd_rcl_section_parse_defaults (section, pool, obj, | |||
sym_def, err)) { | |||
return FALSE; | |||
@@ -408,11 +421,13 @@ rspamd_rcl_metric_handler (rspamd_mempool_t *pool, const ucl_object_t *obj, | |||
const gchar *key, gpointer ud, | |||
struct rspamd_rcl_section *section, GError **err) | |||
{ | |||
const ucl_object_t *val, *cur; | |||
const ucl_object_t *val, *cur, *elt; | |||
ucl_object_iter_t it; | |||
struct rspamd_config *cfg = ud; | |||
struct metric *metric; | |||
struct rspamd_rcl_section *subsection; | |||
struct rspamd_rcl_symbol_data sd; | |||
struct rspamd_symbol_def *sym_def; | |||
g_assert (key != NULL); | |||
@@ -483,6 +498,29 @@ rspamd_rcl_metric_handler (rspamd_mempool_t *pool, const ucl_object_t *obj, | |||
} | |||
} | |||
/* Handle ignored symbols */ | |||
val = ucl_object_find_key (obj, "ignore"); | |||
if (val != NULL && ucl_object_type (val) == UCL_ARRAY) { | |||
LL_FOREACH (val, cur) { | |||
it = NULL; | |||
while ((elt = ucl_iterate_object (cur, &it, true)) != NULL) { | |||
if (ucl_object_type (elt) == UCL_STRING) { | |||
sym_def = g_hash_table_lookup (metric->symbols, | |||
ucl_object_tostring (elt)); | |||
if (sym_def != NULL) { | |||
sym_def->flags |= RSPAMD_SYMBOL_FLAG_IGNORE; | |||
} | |||
else { | |||
msg_warn ("cannot find symbol %s to set ignore flag", | |||
ucl_object_tostring (elt)); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
return TRUE; | |||
} | |||
@@ -1515,11 +1553,6 @@ rspamd_rcl_config_init (void) | |||
rspamd_rcl_parse_struct_string, | |||
G_STRUCT_OFFSET (struct rspamd_symbol_def, description), | |||
0); | |||
rspamd_rcl_add_default_handler (ssub, | |||
"one_shot", | |||
rspamd_rcl_parse_struct_boolean, | |||
G_STRUCT_OFFSET (struct rspamd_symbol_def, one_shot), | |||
0); | |||
rspamd_rcl_add_default_handler (ssub, | |||
"score", | |||
rspamd_rcl_parse_struct_double, | |||
@@ -1574,11 +1607,6 @@ rspamd_rcl_config_init (void) | |||
rspamd_rcl_parse_struct_string, | |||
G_STRUCT_OFFSET (struct rspamd_symbol_def, description), | |||
0); | |||
rspamd_rcl_add_default_handler (sssub, | |||
"one_shot", | |||
rspamd_rcl_parse_struct_boolean, | |||
G_STRUCT_OFFSET (struct rspamd_symbol_def, one_shot), | |||
0); | |||
rspamd_rcl_add_default_handler (sssub, | |||
"score", | |||
rspamd_rcl_parse_struct_double, |
@@ -1246,7 +1246,10 @@ rspamd_config_add_metric_symbol (struct rspamd_config *cfg, | |||
sym_def->score = score; | |||
sym_def->weight_ptr = score_ptr; | |||
sym_def->name = rspamd_mempool_strdup (cfg->cfg_pool, symbol); | |||
sym_def->one_shot = one_shot; | |||
if (one_shot) { | |||
sym_def->flags |= RSPAMD_SYMBOL_FLAG_ONESHOT; | |||
} | |||
if (description) { | |||
sym_def->description = rspamd_mempool_strdup (cfg->cfg_pool, description); |
@@ -848,7 +848,12 @@ rspamd_symbols_cache_validate (struct symbols_cache *cache, | |||
gboolean strict) | |||
{ | |||
struct cache_item *item; | |||
GList *cur, *metric_symbols; | |||
GHashTableIter it; | |||
GList *cur; | |||
gpointer k, v; | |||
struct rspamd_symbol_def *sym_def; | |||
struct metric *metric; | |||
gboolean ignore_symbol = FALSE, ret = TRUE; | |||
if (cache == NULL) { | |||
msg_err_cache ("empty cache is invalid"); | |||
@@ -866,28 +871,42 @@ rspamd_symbols_cache_validate (struct symbols_cache *cache, | |||
rspamd_symbols_cache_validate_cb, | |||
cache); | |||
/* Now check each metric item and find corresponding symbol in a cache */ | |||
metric_symbols = g_hash_table_get_keys (cfg->metrics_symbols); | |||
cur = metric_symbols; | |||
while (cur) { | |||
item = g_hash_table_lookup (cache->items_by_symbol, cur->data); | |||
if (item == NULL) { | |||
msg_warn_cache ( | |||
"symbol '%s' has its score defined but there is no " | |||
"corresponding rule registered", | |||
cur->data); | |||
if (strict) { | |||
g_list_free (metric_symbols); | |||
return FALSE; | |||
g_hash_table_iter_init (&it, cfg->metrics_symbols); | |||
while (g_hash_table_iter_next (&it, &k, &v)) { | |||
ignore_symbol = FALSE; | |||
cur = v; | |||
while (cur) { | |||
metric = cur->data; | |||
sym_def = g_hash_table_lookup (metric->symbols, k); | |||
if (sym_def && (sym_def->flags & RSPAMD_SYMBOL_FLAG_IGNORE)) { | |||
ignore_symbol = TRUE; | |||
break; | |||
} | |||
cur = g_list_next (cur); | |||
} | |||
if (!ignore_symbol) { | |||
item = g_hash_table_lookup (cache->items_by_symbol, k); | |||
if (item == NULL) { | |||
msg_warn_cache ( | |||
"symbol '%s' has its score defined but there is no " | |||
"corresponding rule registered", | |||
k); | |||
if (strict) { | |||
ret = FALSE; | |||
} | |||
} | |||
} | |||
cur = g_list_next (cur); | |||
} | |||
g_list_free (metric_symbols); | |||
post_cache_init (cache); | |||
return TRUE; | |||
return ret; | |||
} | |||
static gboolean |