aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2015-03-21 01:14:05 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2015-03-21 01:14:05 +0000
commit307141215273ecd45e02dd55915f1cbd85c89ee0 (patch)
treebae0fe3d55425f1da1ecb5a24fd32a9b88c2414b
parent4d56fed92bbbcee00056d448940f1edc422292c6 (diff)
downloadrspamd-307141215273ecd45e02dd55915f1cbd85c89ee0.tar.gz
rspamd-307141215273ecd45e02dd55915f1cbd85c89ee0.zip
Start to rework composites.
-rw-r--r--src/libmime/filter.c283
-rw-r--r--src/libmime/filter.h2
2 files changed, 120 insertions, 165 deletions
diff --git a/src/libmime/filter.c b/src/libmime/filter.c
index 7736ba4cf..5ad162163 100644
--- a/src/libmime/filter.c
+++ b/src/libmime/filter.c
@@ -29,7 +29,7 @@
#include "message.h"
#include "cfg_file.h"
#include "util.h"
-#include "expressions.h"
+#include "expression.h"
#include "diff.h"
#include "libstat/stat_api.h"
@@ -54,6 +54,19 @@
#define BITSPERBYTE (8 * sizeof (gchar))
#define NBYTES(nbits) (((nbits) + BITSPERBYTE - 1) / BITSPERBYTE)
+static rspamd_expression_atom_t * rspamd_composite_expr_parse (const gchar *line, gsize len,
+ rspamd_mempool_t *pool, gpointer ud, GError **err);
+static gint rspamd_composite_expr_process (gpointer input, rspamd_expression_atom_t *atom);
+static gint rspamd_composite_expr_priority (rspamd_expression_atom_t *atom);
+static void rspamd_composite_expr_destroy (rspamd_expression_atom_t *atom);
+
+const struct rspamd_atom_subr composite_expr_subr = {
+ .parse = rspamd_composite_expr_parse,
+ .process = rspamd_composite_expr_process,
+ .priority = rspamd_composite_expr_priority,
+ .destroy = rspamd_composite_expr_destroy
+};
+
static inline GQuark
filter_error_quark (void)
{
@@ -398,6 +411,7 @@ rspamd_process_filters (struct rspamd_task *task)
struct composites_data {
struct rspamd_task *task;
+ struct rspamd_composite *composite;
struct metric_result *metric_res;
GTree *symbols_to_remove;
guint8 *checked;
@@ -409,184 +423,125 @@ struct symbol_remove_data {
gboolean remove_symbol;
};
-static gint
-remove_compare_data (gconstpointer a, gconstpointer b)
-{
- const gchar *ca = a, *cb = b;
-
- return strcmp (ca, cb);
-}
-static void
-composites_foreach_callback (gpointer key, gpointer value, void *data)
+/*
+ * Composites are just sequences of symbols
+ */
+static rspamd_expression_atom_t *
+rspamd_composite_expr_parse (const gchar *line, gsize len,
+ rspamd_mempool_t *pool, gpointer ud, GError **err)
{
- struct composites_data *cd = (struct composites_data *)data;
- struct rspamd_composite *composite = value, *ncomp;
- struct expression *expr;
- GQueue *stack;
- GList *symbols = NULL, *s;
- gsize cur, op1, op2;
- gchar logbuf[256], *sym, *check_sym;
- gint r;
- struct symbol *ms;
- struct symbol_remove_data *rd;
-
-
- expr = composite->expr;
- if (isset (cd->checked, composite->id)) {
- /* Symbol was already checked */
- return;
+ gsize clen;
+ rspamd_expression_atom_t *res;
+
+ clen = strcspn (line, ", \t(+!|&\n");
+ if (clen == 0) {
+ /* Invalid composite atom */
+ g_set_error (err, filter_error_quark (), 100, "Invalid composite: %s",
+ line);
+ return NULL;
}
- stack = g_queue_new ();
+ res = rspamd_mempool_alloc0 (pool, sizeof (*res));
+ res->len = clen;
+ res->data = line;
- while (expr) {
- if (expr->type == EXPR_STR) {
- /* Find corresponding symbol */
- sym = expr->content.operand;
- if (*sym == '~' || *sym == '-') {
- sym++;
- }
- if (g_hash_table_lookup (cd->metric_res->symbols, sym) == NULL) {
- cur = 0;
- if ((ncomp =
- g_hash_table_lookup (cd->task->cfg->composite_symbols,
- sym)) != NULL) {
- /* Set checked for this symbol to avoid cyclic references */
- if (isclr (cd->checked, ncomp->id)) {
- setbit (cd->checked, composite->id);
- composites_foreach_callback (sym, ncomp, cd);
- if (g_hash_table_lookup (cd->metric_res->symbols,
- sym) != NULL) {
- cur = 1;
- }
- }
- }
+ return res;
+}
+static gint
+rspamd_composite_expr_process (gpointer input, rspamd_expression_atom_t *atom)
+{
+ struct composites_data *cd = (struct composites_data *)input;
+ const gchar *sym = atom->str;
+ struct rspamd_composite *ncomp;
+ struct symbol_remove_data *rd;
+ struct symbol *ms;
+ gint ret = 0, rc = 0;
+ gchar t;
+
+ if (*sym == '~' || *sym == '-') {
+ t = *sym ++;
+ }
+
+ if ((ms = g_hash_table_lookup (cd->metric_res->symbols, sym)) == NULL) {
+ if ((ncomp =
+ g_hash_table_lookup (cd->task->cfg->composite_symbols,
+ sym)) != NULL) {
+ /* Set checked for this symbol to avoid cyclic references */
+ if (isclr (cd->checked, ncomp->id * 2)) {
+ setbit (cd->checked, cd->composite->id * 2);
+ rc = rspamd_process_expression (ncomp->expr, cd);
+ clrbit (cd->checked, cd->composite->id * 2);
+ ms = g_hash_table_lookup (cd->metric_res->symbols, sym);
}
else {
- cur = 1;
- symbols = g_list_prepend (symbols, expr->content.operand);
+ /*
+ * XXX: in case of cyclic references this would return 0
+ */
+ rc = isset (cd->checked, ncomp->id * 2 + 1);
}
- g_queue_push_head (stack, GSIZE_TO_POINTER (cur));
+ }
+ }
+ else {
+ rc = 1;
+ }
+
+ if (rc && 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 = rspamd_mempool_alloc (cd->task->task_pool, sizeof (*cd));
+ rd->ms = ms;
+ if (G_UNLIKELY (*sym == '~')) {
+ rd->remove_weight = FALSE;
+ rd->remove_symbol = TRUE;
+ }
+ else if (G_UNLIKELY (*sym == '-')) {
+ rd->remove_symbol = FALSE;
+ rd->remove_weight = FALSE;
}
else {
- if (g_queue_is_empty (stack)) {
- /* Queue has no operands for operation, exiting */
- g_list_free (symbols);
- g_queue_free (stack);
- setbit (cd->checked, composite->id);
- return;
- }
- switch (expr->content.operation) {
- case '!':
- op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- op1 = !op1;
- g_queue_push_head (stack, GSIZE_TO_POINTER (op1));
- break;
- case '&':
- op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- g_queue_push_head (stack, GSIZE_TO_POINTER (op1 && op2));
- break;
- case '|':
- op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- g_queue_push_head (stack, GSIZE_TO_POINTER (op1 || op2));
- break;
- default:
- expr = expr->next;
- continue;
- }
+ rd->remove_symbol = TRUE;
+ rd->remove_weight = TRUE;
}
- expr = expr->next;
- }
- if (!g_queue_is_empty (stack)) {
- op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- if (op1) {
- /* Remove all symbols that are in composite symbol */
- s = g_list_first (symbols);
- r = rspamd_snprintf (logbuf,
- sizeof (logbuf),
- "<%s>, insert symbol %s instead of symbols: ",
- cd->task->message_id,
- key);
- while (s) {
- sym = s->data;
- if (*sym == '~' || *sym == '-') {
- check_sym = sym + 1;
- }
- else {
- check_sym = sym;
- }
- ms = g_hash_table_lookup (cd->metric_res->symbols, check_sym);
-
- if (ms == NULL) {
- /* Try to process other composites */
- if ((ncomp =
- g_hash_table_lookup (cd->task->cfg->composite_symbols,
- check_sym)) != NULL) {
- /* Set checked for this symbol to avoid cyclic references */
- if (isclr (cd->checked, ncomp->id)) {
- setbit (cd->checked, composite->id);
- composites_foreach_callback (check_sym, ncomp, cd);
- ms = g_hash_table_lookup (cd->metric_res->symbols,
- check_sym);
- }
- }
- }
-
- if (ms != NULL) {
- rd =
- rspamd_mempool_alloc (cd->task->task_pool,
- sizeof (struct symbol_remove_data));
- rd->ms = ms;
- if (G_UNLIKELY (*sym == '~')) {
- rd->remove_weight = FALSE;
- rd->remove_symbol = TRUE;
- }
- else if (G_UNLIKELY (*sym == '-')) {
- rd->remove_symbol = FALSE;
- rd->remove_weight = FALSE;
- }
- else {
- rd->remove_symbol = TRUE;
- rd->remove_weight = TRUE;
- }
- if (!g_tree_lookup (cd->symbols_to_remove, ms->name)) {
- g_tree_insert (cd->symbols_to_remove,
- (gpointer)ms->name,
- rd);
- }
- }
- else {
-
- }
-
- if (s->next) {
- r += rspamd_snprintf (logbuf + r,
- sizeof (logbuf) - r,
- "%s, ",
- s->data);
- }
- else {
- r += rspamd_snprintf (logbuf + r,
- sizeof (logbuf) - r,
- "%s",
- s->data);
- }
- s = g_list_next (s);
- }
- /* Add new symbol */
- rspamd_task_insert_result_single (cd->task, key, 1.0, NULL);
- msg_info ("%s", logbuf);
+ if (!g_tree_lookup (cd->symbols_to_remove, ms->name)) {
+ g_tree_insert (cd->symbols_to_remove,
+ (gpointer)ms->name,
+ rd);
}
}
+}
- setbit (cd->checked, composite->id);
- g_queue_free (stack);
- g_list_free (symbols);
+/*
+ * We don't have preferences for composites
+ */
+static gint
+rspamd_composite_expr_priority (rspamd_expression_atom_t *atom)
+{
+ return 0;
+}
+
+static void
+rspamd_composite_expr_destroy (rspamd_expression_atom_t *atom)
+{
+
+}
+
+static gint
+remove_compare_data (gconstpointer a, gconstpointer b)
+{
+ const gchar *ca = a, *cb = b;
+
+ return strcmp (ca, cb);
+}
+
+static void
+composites_foreach_callback (gpointer key, gpointer value, void *data)
+{
- return;
}
diff --git a/src/libmime/filter.h b/src/libmime/filter.h
index de324caf7..41093b05d 100644
--- a/src/libmime/filter.h
+++ b/src/libmime/filter.h
@@ -75,7 +75,7 @@ struct metric_result {
* Composite structure
*/
struct rspamd_composite {
- struct expression *expr;
+ struct rspamd_expression *expr;
gint id;
};