diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2018-10-09 12:37:02 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2018-10-09 12:37:02 +0100 |
commit | a532a2ddf2797a6c3156edc42310e5708363eefb (patch) | |
tree | 8407eb278f6d290b1c1a4d1535c19be2f96a7a32 /src | |
parent | 01e6bf680b28286083ed4ccf359c394b7190ceb8 (diff) | |
download | rspamd-a532a2ddf2797a6c3156edc42310e5708363eefb.tar.gz rspamd-a532a2ddf2797a6c3156edc42310e5708363eefb.zip |
[Feature] Allow `g+:` and `g-:` composite atoms
Diffstat (limited to 'src')
-rw-r--r-- | src/libserver/composites.c | 186 |
1 files changed, 128 insertions, 58 deletions
diff --git a/src/libserver/composites.c b/src/libserver/composites.c index 83f3a35d4..d553ce7ef 100644 --- a/src/libserver/composites.c +++ b/src/libserver/composites.c @@ -94,7 +94,7 @@ rspamd_composite_expr_parse (const gchar *line, gsize len, /* * Composites are just sequences of symbols */ - clen = strcspn (line, ", \t()><+!|&\n"); + clen = strcspn (line, ", \t()><!|&\n"); if (clen == 0) { /* Invalid composite atom */ g_set_error (err, rspamd_composites_quark (), 100, "Invalid composite: %s", @@ -172,13 +172,86 @@ rspamd_composite_process_single_symbol (struct composites_data *cd, return rc; } +static void +rspamd_composite_process_symbol_removal (rspamd_expression_atom_t *atom, + struct composites_data *cd, + struct rspamd_symbol_result *ms, + const gchar *beg) +{ + gchar t; + struct symbol_remove_data *rd, *nrd; + + if (ms == NULL) { + return; + } + + /* + * At this point we know that we need to do something about this symbol, + * however, we don't know whether we need to delete it unfortunately, + * that depends on the later decisions when the complete expression is + * evaluated. + */ + rd = g_hash_table_lookup (cd->symbols_to_remove, ms->name); + + nrd = rspamd_mempool_alloc (cd->task->task_pool, sizeof (*nrd)); + nrd->sym = ms->name; + + /* By default remove symbols */ + switch (cd->composite->policy) { + case RSPAMD_COMPOSITE_POLICY_REMOVE_ALL: + default: + nrd->action = (RSPAMD_COMPOSITE_REMOVE_SYMBOL|RSPAMD_COMPOSITE_REMOVE_WEIGHT); + break; + case RSPAMD_COMPOSITE_POLICY_REMOVE_SYMBOL: + nrd->action = RSPAMD_COMPOSITE_REMOVE_SYMBOL; + break; + case RSPAMD_COMPOSITE_POLICY_REMOVE_WEIGHT: + nrd->action = RSPAMD_COMPOSITE_REMOVE_WEIGHT; + break; + case RSPAMD_COMPOSITE_POLICY_LEAVE: + nrd->action = 0; + break; + } + + for (;;) { + t = *beg; + + if (t == '~') { + nrd->action &= ~RSPAMD_COMPOSITE_REMOVE_SYMBOL; + } + else if (t == '-') { + nrd->action &= ~(RSPAMD_COMPOSITE_REMOVE_WEIGHT| + RSPAMD_COMPOSITE_REMOVE_SYMBOL); + } + else if (t == '^') { + nrd->action |= RSPAMD_COMPOSITE_REMOVE_FORCED; + } + else { + break; + } + + beg ++; + } + + nrd->comp = cd->composite; + nrd->parent = atom->parent; + + if (rd == NULL) { + DL_APPEND (rd, nrd); + g_hash_table_insert (cd->symbols_to_remove, (gpointer)ms->name, rd); + } + else { + DL_APPEND (rd, nrd); + } +} + static gdouble -rspamd_composite_expr_process (struct rspamd_expr_process_data *process_data, rspamd_expression_atom_t *atom) +rspamd_composite_expr_process (struct rspamd_expr_process_data *process_data, + rspamd_expression_atom_t *atom) { struct composites_data *cd = process_data->cd; const gchar *beg = atom->data, *sym = NULL; - gchar t; - struct symbol_remove_data *rd, *nrd; + struct rspamd_symbol_result *ms = NULL; struct rspamd_symbols_group *gr; struct rspamd_symbol *sdef; @@ -225,73 +298,70 @@ rspamd_composite_expr_process (struct rspamd_expr_process_data *process_data, rs rc = rspamd_composite_process_single_symbol (cd, sdef->name, &ms); if (rc) { - break; + rspamd_composite_process_symbol_removal (atom, + cd, + ms, + beg); } } } } - else { - rc = rspamd_composite_process_single_symbol (cd, sym, &ms); - } + else if (strncmp (sym, "g+:", 3) == 0) { + /* Group, positive symbols only */ + gr = g_hash_table_lookup (cd->task->cfg->groups, sym + 3); - if (rc != 0 && ms) { - /* - * At this point we know that we need to do something about this symbol, - * however, we don't know whether we need to delete it unfortunately, - * that depends on the later decisions when the complete expression is - * evaluated. - */ - rd = g_hash_table_lookup (cd->symbols_to_remove, ms->name); + if (gr != NULL) { + g_hash_table_iter_init (&it, gr->symbols); - nrd = rspamd_mempool_alloc (cd->task->task_pool, sizeof (*nrd)); - nrd->sym = ms->name; + while (g_hash_table_iter_next (&it, &k, &v)) { + sdef = v; - /* By default remove symbols */ - switch (cd->composite->policy) { - case RSPAMD_COMPOSITE_POLICY_REMOVE_ALL: - default: - nrd->action = (RSPAMD_COMPOSITE_REMOVE_SYMBOL|RSPAMD_COMPOSITE_REMOVE_WEIGHT); - break; - case RSPAMD_COMPOSITE_POLICY_REMOVE_SYMBOL: - nrd->action = RSPAMD_COMPOSITE_REMOVE_SYMBOL; - break; - case RSPAMD_COMPOSITE_POLICY_REMOVE_WEIGHT: - nrd->action = RSPAMD_COMPOSITE_REMOVE_WEIGHT; - break; - case RSPAMD_COMPOSITE_POLICY_LEAVE: - nrd->action = 0; - break; + if (sdef->score > 0) { + rc = rspamd_composite_process_single_symbol (cd, + sdef->name, + &ms); + + if (rc) { + rspamd_composite_process_symbol_removal (atom, + cd, + ms, + beg); + } + } + } } + } + else if (strncmp (sym, "g-:", 3) == 0) { + /* Group, positive symbols only */ + gr = g_hash_table_lookup (cd->task->cfg->groups, sym + 3); - for (;;) { - t = *beg; - - if (t == '~') { - nrd->action &= ~RSPAMD_COMPOSITE_REMOVE_SYMBOL; - } - else if (t == '-') { - nrd->action &= ~(RSPAMD_COMPOSITE_REMOVE_WEIGHT| - RSPAMD_COMPOSITE_REMOVE_SYMBOL); - } - else if (t == '^') { - nrd->action |= RSPAMD_COMPOSITE_REMOVE_FORCED; - } - else { - break; - } + if (gr != NULL) { + g_hash_table_iter_init (&it, gr->symbols); - beg ++; - } + while (g_hash_table_iter_next (&it, &k, &v)) { + sdef = v; - nrd->comp = cd->composite; - nrd->parent = atom->parent; + if (sdef->score < 0) { + rc = rspamd_composite_process_single_symbol (cd, sdef->name, &ms); - if (rd == NULL) { - DL_APPEND (rd, nrd); - g_hash_table_insert (cd->symbols_to_remove, (gpointer)ms->name, rd); + if (rc) { + rspamd_composite_process_symbol_removal (atom, + cd, + ms, + beg); + } + } + } } - else { - DL_APPEND (rd, nrd); + } + else { + rc = rspamd_composite_process_single_symbol (cd, sym, &ms); + + if (rc) { + rspamd_composite_process_symbol_removal (atom, + cd, + ms, + beg); } } |