summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rambler-co.ru>2012-06-14 22:20:50 +0400
committerVsevolod Stakhov <vsevolod@rambler-co.ru>2012-06-14 22:20:50 +0400
commit56b591bcb2c91ab8af7def656f115e2e794a2b8a (patch)
tree47e1100e382e1b5fe104b6f0a357902f1e3c2d34
parent32e13585b6bd05acb30b7747f6ce22b94079bbb0 (diff)
downloadrspamd-56b591bcb2c91ab8af7def656f115e2e794a2b8a.tar.gz
rspamd-56b591bcb2c91ab8af7def656f115e2e794a2b8a.zip
* Allow to use other composites inside a composite's expression
Fix for cmake 2.6.
-rw-r--r--CMakeLists.txt29
-rw-r--r--config.h.in1
-rw-r--r--src/cfg_xml.c6
-rw-r--r--src/filter.c60
-rw-r--r--src/filter.h8
5 files changed, 91 insertions, 13 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fa5fff1d6..0a4924d93 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -55,26 +55,38 @@ MACRO(_AddModulesForced MLIST WLIST)
STRING(RANDOM LENGTH 8 _MODULES_ID)
SET(MODULES_ID ${_MODULES_ID} CACHE INTERNAL "Modules ID" FORCE)
FILE(WRITE "src/modules.c" "/* ${MODULES_ID} */\n#include \"config.h\"\n")
- FOREACH(MOD IN LISTS ${MLIST})
+
+ # Handle even old cmake
+ LIST(LENGTH ${MLIST} MLIST_COUNT)
+ LIST(LENGTH ${WLIST} WLIST_COUNT)
+ MATH(EXPR MLIST_MAX ${MLIST_COUNT}-1)
+ MATH(EXPR WLIST_MAX ${WLIST_COUNT}-1)
+
+ FOREACH(MOD_IDX RANGE ${MLIST_MAX})
+ LIST(GET ${MLIST} ${MOD_IDX} MOD)
FILE(APPEND "src/modules.c" "extern module_t ${MOD}_module;\n")
- ENDFOREACH(MOD IN LISTS ${MLIST})
+ ENDFOREACH(MOD_IDX RANGE ${MLIST_MAX})
FILE(APPEND "src/modules.c" "\n\nmodule_t *modules[] = {\n")
- FOREACH(MOD IN LISTS ${MLIST})
+ FOREACH(MOD_IDX RANGE ${MLIST_MAX})
+ LIST(GET ${MLIST} ${MOD_IDX} MOD)
FILE(APPEND "src/modules.c" "&${MOD}_module,\n")
- ENDFOREACH(MOD IN LISTS ${MLIST})
+ ENDFOREACH(MOD_IDX RANGE ${MLIST_MAX})
+
FILE(APPEND "src/modules.c" "NULL\n};\n")
- FOREACH(WRK IN LISTS ${WLIST})
+ FOREACH(MOD_IDX RANGE ${WLIST_MAX})
+ LIST(GET ${WLIST} ${MOD_IDX} WRK)
FILE(APPEND "src/modules.c" "extern worker_t ${WRK}_worker;\n")
- ENDFOREACH(WRK IN LISTS ${WLIST})
+ ENDFOREACH(MOD_IDX RANGE ${WLIST_MAX})
FILE(APPEND "src/modules.c" "\n\nworker_t *workers[] = {\n")
- FOREACH(WRK IN LISTS ${WLIST})
+ FOREACH(MOD_IDX RANGE ${WLIST_MAX})
+ LIST(GET ${WLIST} ${MOD_IDX} WRK)
FILE(APPEND "src/modules.c" "&${WRK}_worker,\n")
- ENDFOREACH(WRK IN LISTS ${WLIST})
+ ENDFOREACH(MOD_IDX RANGE ${WLIST_MAX})
FILE(APPEND "src/modules.c" "NULL\n};\n")
ENDMACRO(_AddModulesForced MLIST WLIST)
@@ -814,6 +826,7 @@ CHECK_SYMBOL_EXISTS(posix_fallocate fcntl.h HAVE_POSIX_FALLOCATE)
CHECK_SYMBOL_EXISTS(fallocate fcntl.h HAVE_FALLOCATE)
CHECK_SYMBOL_EXISTS(fdatasync unistd.h HAVE_FDATASYNC)
CHECK_SYMBOL_EXISTS(_SC_NPROCESSORS_ONLN unistd.h HAVE_SC_NPROCESSORS_ONLN)
+CHECK_SYMBOL_EXISTS(setbit sys/param.h PARAM_H_HAS_BITSET)
IF(HAVE_SIGINFO_H)
CHECK_SYMBOL_EXISTS(SA_SIGINFO "signal.h;siginfo.h" HAVE_SA_SIGINFO)
ELSE(HAVE_SIGINFO_H)
diff --git a/config.h.in b/config.h.in
index eefb541bc..c1ac287cb 100644
--- a/config.h.in
+++ b/config.h.in
@@ -191,6 +191,7 @@
#cmakedefine GLIB_RE_COMPAT 1
#cmakedefine GLIB_UNISCRIPT_COMPAT 1
#cmakedefine GLIB_HASH_COMPAT 1
+#cmakedefine PARAM_H_HAS_BITSET 1
#define RVERSION "${RSPAMD_VERSION}"
#define RID "${ID}"
diff --git a/src/cfg_xml.c b/src/cfg_xml.c
index 6c21fa14d..ad542265d 100644
--- a/src/cfg_xml.c
+++ b/src/cfg_xml.c
@@ -1276,6 +1276,7 @@ handle_composite (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHas
{
gchar *val;
struct expression *expr;
+ struct rspamd_composite *composite;
if (attrs == NULL || (val = g_hash_table_lookup (attrs, "name")) == NULL) {
msg_err ("'name' attribute is required for tag 'composite'");
@@ -1286,7 +1287,10 @@ handle_composite (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHas
msg_err ("cannot parse composite expression: %s", data);
return FALSE;
}
- g_hash_table_insert (cfg->composite_symbols, val, expr);
+ composite = memory_pool_alloc (cfg->cfg_pool, sizeof (struct rspamd_composite));
+ composite->expr = expr;
+ composite->id = g_hash_table_size (cfg->composite_symbols) + 1;
+ g_hash_table_insert (cfg->composite_symbols, val, composite);
register_virtual_symbol (&cfg->cache, val, 1);
return TRUE;
diff --git a/src/filter.c b/src/filter.c
index 1d6f19e21..d7d2a0c15 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -43,6 +43,19 @@
#define COMMON_PART_FACTOR 95
+#ifndef PARAM_H_HAS_BITSET
+/* Bit map related macros. */
+#define NBBY 8 /* number of bits in a byte */
+#define setbit(a,i) (((unsigned char *)(a))[(i)/NBBY] |= 1<<((i)%NBBY))
+#define clrbit(a,i) (((unsigned char *)(a))[(i)/NBBY] &= ~(1<<((i)%NBBY)))
+#define isset(a,i) \
+ (((const unsigned char *)(a))[(i)/NBBY] & (1<<((i)%NBBY)))
+#define isclr(a,i) \
+ ((((const unsigned char *)(a))[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
+#endif
+#define BITSPERBYTE (8*sizeof (gchar))
+#define NBYTES(nbits) (((nbits) + BITSPERBYTE - 1) / BITSPERBYTE)
+
static inline GQuark
filter_error_quark (void)
{
@@ -286,10 +299,12 @@ process_filters (struct worker_task *task)
return 1;
}
+
struct composites_data {
struct worker_task *task;
struct metric_result *metric_res;
GTree *symbols_to_remove;
+ guint8 *checked;
};
struct symbol_remove_data {
@@ -310,15 +325,23 @@ static void
composites_foreach_callback (gpointer key, gpointer value, void *data)
{
struct composites_data *cd = (struct composites_data *)data;
- struct expression *expr = (struct expression *)value;
+ struct rspamd_composite *composite = value, *ncomp;
+ struct expression *expr;
GQueue *stack;
GList *symbols = NULL, *s;
gsize cur, op1, op2;
- gchar logbuf[256], *sym;
+ 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;
+ }
+
stack = g_queue_new ();
while (expr) {
@@ -330,6 +353,16 @@ composites_foreach_callback (gpointer key, gpointer value, void *data)
}
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;
+ }
+ }
+ }
}
else {
cur = 1;
@@ -342,6 +375,7 @@ composites_foreach_callback (gpointer key, gpointer value, void *data)
/* 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) {
@@ -376,10 +410,23 @@ composites_foreach_callback (gpointer key, gpointer value, void *data)
while (s) {
sym = s->data;
if (*sym == '~' || *sym == '-') {
- ms = g_hash_table_lookup (cd->metric_res->symbols, sym + 1);
+ check_sym = sym + 1;
}
else {
- ms = g_hash_table_lookup (cd->metric_res->symbols, sym);
+ 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) {
@@ -401,6 +448,9 @@ composites_foreach_callback (gpointer key, gpointer value, void *data)
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);
@@ -416,6 +466,7 @@ composites_foreach_callback (gpointer key, gpointer value, void *data)
}
}
+ setbit (cd->checked, composite->id);
g_queue_free (stack);
g_list_free (symbols);
@@ -517,6 +568,7 @@ composites_metric_callback (gpointer key, gpointer value, gpointer data)
cd->task = task;
cd->metric_res = (struct metric_result *)metric_res;
cd->symbols_to_remove = g_tree_new (remove_compare_data);
+ cd->checked = memory_pool_alloc0 (task->task_pool, NBYTES (g_hash_table_size (task->cfg->composite_symbols)));
/* Process hash table */
g_hash_table_foreach (task->cfg->composite_symbols, composites_foreach_callback, cd);
diff --git a/src/filter.h b/src/filter.h
index 5cd6e4ff2..5dc141af8 100644
--- a/src/filter.h
+++ b/src/filter.h
@@ -81,6 +81,14 @@ struct metric_result {
};
/**
+ * Composite structure
+ */
+struct rspamd_composite {
+ struct expression *expr;
+ gint id;
+};
+
+/**
* Process all filters
* @param task worker's task that present message from user
* @return 0 - if there is non-finished tasks and 1 if processing is completed