aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2018-10-09 12:37:02 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2018-10-09 12:37:02 +0100
commita532a2ddf2797a6c3156edc42310e5708363eefb (patch)
tree8407eb278f6d290b1c1a4d1535c19be2f96a7a32 /src
parent01e6bf680b28286083ed4ccf359c394b7190ceb8 (diff)
downloadrspamd-a532a2ddf2797a6c3156edc42310e5708363eefb.tar.gz
rspamd-a532a2ddf2797a6c3156edc42310e5708363eefb.zip
[Feature] Allow `g+:` and `g-:` composite atoms
Diffstat (limited to 'src')
-rw-r--r--src/libserver/composites.c186
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);
}
}