From 9d703560099beea2b2b53c533e7f71dc926293b2 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 1 Mar 2012 20:14:32 +0400 Subject: [PATCH] Separate librspamdserver API from plugins and workers functions. Make tests compileable again. --- src/expressions.c | 596 +-------------------------------------- src/plugins/regexp.c | 596 ++++++++++++++++++++++++++++++++++++++- src/util.c | 4 +- test/CMakeLists.txt | 4 + test/rspamd_dns_test.c | 9 +- test/rspamd_fuzzy_test.c | 3 +- test/rspamd_test_suite.c | 10 +- 7 files changed, 619 insertions(+), 603 deletions(-) diff --git a/src/expressions.c b/src/expressions.c index 488ea5600..f552a5a77 100644 --- a/src/expressions.c +++ b/src/expressions.c @@ -35,14 +35,8 @@ gboolean rspamd_compare_encoding (struct worker_task *task, GList * args, void *unused); gboolean rspamd_header_exists (struct worker_task *task, GList * args, void *unused); -gboolean rspamd_content_type_compare_param (struct worker_task *task, GList * args, void *unused); -gboolean rspamd_content_type_has_param (struct worker_task *task, GList * args, void *unused); -gboolean rspamd_content_type_is_subtype (struct worker_task *task, GList * args, void *unused); -gboolean rspamd_content_type_is_type (struct worker_task *task, GList * args, void *unused); gboolean rspamd_parts_distance (struct worker_task *task, GList * args, void *unused); gboolean rspamd_recipients_distance (struct worker_task *task, GList * args, void *unused); -gboolean rspamd_has_content_part (struct worker_task *task, GList * args, void *unused); -gboolean rspamd_has_content_part_len (struct worker_task *task, GList * args, void *unused); gboolean rspamd_has_only_html_part (struct worker_task *task, GList * args, void *unused); gboolean rspamd_is_recipients_sorted (struct worker_task *task, GList * args, void *unused); gboolean rspamd_compare_transfer_encoding (struct worker_task *task, GList * args, void *unused); @@ -63,12 +57,6 @@ static struct _fl { {"compare_parts_distance", rspamd_parts_distance, NULL}, {"compare_recipients_distance", rspamd_recipients_distance, NULL}, {"compare_transfer_encoding", rspamd_compare_transfer_encoding, NULL}, - {"content_type_compare_param", rspamd_content_type_compare_param, NULL}, - {"content_type_has_param", rspamd_content_type_has_param, NULL}, - {"content_type_is_subtype", rspamd_content_type_is_subtype, NULL}, - {"content_type_is_type", rspamd_content_type_is_type, NULL}, - {"has_content_part", rspamd_has_content_part, NULL}, - {"has_content_part_len", rspamd_has_content_part_len, NULL}, {"has_fake_html", rspamd_has_fake_html, NULL}, {"has_html_tag", rspamd_has_html_tag, NULL}, {"has_only_html_part", rspamd_has_only_html_part, NULL}, @@ -800,13 +788,13 @@ gboolean call_expression_function (struct expression_function * func, struct worker_task * task) { struct _fl *selected, key; - gboolean res; key.name = func->name; selected = bsearch (&key, list_ptr, functions_number, sizeof (struct _fl), fl_cmp); if (selected == NULL) { /* Try to check lua function */ +#if 0 if (! lua_call_expression_func (NULL, func->name, task, func->args, &res)) { msg_warn ("call to undefined function %s", key.name); return FALSE; @@ -814,6 +802,9 @@ call_expression_function (struct expression_function * func, struct worker_task else { return res; } +#else + return FALSE; +#endif } return selected->func (task, func->args, selected->user_data); @@ -1106,384 +1097,6 @@ rspamd_parts_distance (struct worker_task * task, GList * args, void *unused) return FALSE; } -gboolean -rspamd_content_type_compare_param (struct worker_task * task, GList * args, void *unused) -{ - gchar *param_name, *param_pattern; - const gchar *param_data; - struct rspamd_regexp *re; - struct expression_argument *arg, *arg1; - GMimeObject *part; - GMimeContentType *ct; - gint r; - gboolean recursive = FALSE, result = FALSE; - GList *cur = NULL; - struct mime_part *cur_part; - - if (args == NULL) { - msg_warn ("no parameters to function"); - return FALSE; - } - arg = get_function_arg (args->data, task, TRUE); - param_name = arg->data; - args = g_list_next (args); - if (args == NULL) { - msg_warn ("too few params to function"); - return FALSE; - } - arg = get_function_arg (args->data, task, TRUE); - param_pattern = arg->data; - - - part = g_mime_message_get_mime_part (task->message); - if (part) { - ct = (GMimeContentType *)g_mime_object_get_content_type (part); - if (args->next) { - args = g_list_next (args); - arg1 = get_function_arg (args->data, task, TRUE); - if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { - recursive = TRUE; - } - } - else { - /* - * If user did not specify argument, let's assume that he wants - * recursive search if mime part is multipart/mixed - */ - if (g_mime_content_type_is_type (ct, "multipart", "*")) { - recursive = TRUE; - } - } - - if (recursive) { - cur = task->parts; - } - -#ifndef GMIME24 - g_object_unref (part); -#endif - for (;;) { - if ((param_data = g_mime_content_type_get_parameter ((GMimeContentType *)ct, param_name)) == NULL) { - result = FALSE; - } - else { - if (*param_pattern == '/') { - /* This is regexp, so compile and create g_regexp object */ - if ((re = re_cache_check (param_pattern, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, param_pattern, task->cfg->raw_mode); - if (re == NULL) { - msg_warn ("cannot compile regexp for function"); - return FALSE; - } - re_cache_add (param_pattern, re, task->cfg->cfg_pool); - } - if ((r = task_cache_check (task, re)) == -1) { - if (g_regex_match (re->regexp, param_data, 0, NULL) == TRUE) { - task_cache_add (task, re, 1); - return TRUE; - } - task_cache_add (task, re, 0); - } - else { - - } - } - else { - /* Just do strcasecmp */ - if (g_ascii_strcasecmp (param_data, param_pattern) == 0) { - return TRUE; - } - } - } - /* Get next part */ - if (! recursive) { - return result; - } - else if (cur != NULL) { - cur_part = cur->data; - if (cur_part->type != NULL) { - ct = cur_part->type; - } - cur = g_list_next (cur); - } - else { - /* All is done */ - return result; - } - } - - } - - return FALSE; -} - -gboolean -rspamd_content_type_has_param (struct worker_task * task, GList * args, void *unused) -{ - gchar *param_name; - const gchar *param_data; - struct expression_argument *arg, *arg1; - GMimeObject *part; - GMimeContentType *ct; - gboolean recursive = FALSE, result = FALSE; - GList *cur = NULL; - struct mime_part *cur_part; - - if (args == NULL) { - msg_warn ("no parameters to function"); - return FALSE; - } - arg = get_function_arg (args->data, task, TRUE); - param_name = arg->data; - - part = g_mime_message_get_mime_part (task->message); - if (part) { - ct = (GMimeContentType *)g_mime_object_get_content_type (part); - if (args->next) { - args = g_list_next (args); - arg1 = get_function_arg (args->data, task, TRUE); - if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { - recursive = TRUE; - } - } - else { - /* - * If user did not specify argument, let's assume that he wants - * recursive search if mime part is multipart/mixed - */ - if (g_mime_content_type_is_type (ct, "multipart", "*")) { - recursive = TRUE; - } - } - - if (recursive) { - cur = task->parts; - } - -#ifndef GMIME24 - g_object_unref (part); -#endif - for (;;) { - if ((param_data = g_mime_content_type_get_parameter ((GMimeContentType *)ct, param_name)) != NULL) { - return TRUE; - } - /* Get next part */ - if (! recursive) { - return result; - } - else if (cur != NULL) { - cur_part = cur->data; - if (cur_part->type != NULL) { - ct = cur_part->type; - } - cur = g_list_next (cur); - } - else { - /* All is done */ - return result; - } - } - - } - - return TRUE; -} - -gboolean -rspamd_content_type_is_subtype (struct worker_task *task, GList * args, void *unused) -{ - gchar *param_pattern; - struct rspamd_regexp *re; - struct expression_argument *arg, *arg1; - GMimeObject *part; - GMimeContentType *ct; - gint r; - gboolean recursive = FALSE, result = FALSE; - GList *cur = NULL; - struct mime_part *cur_part; - - if (args == NULL) { - msg_warn ("no parameters to function"); - return FALSE; - } - arg = get_function_arg (args->data, task, TRUE); - param_pattern = arg->data; - - part = g_mime_message_get_mime_part (task->message); - if (part) { - ct = (GMimeContentType *)g_mime_object_get_content_type (part); - if (args->next) { - args = g_list_next (args); - arg1 = get_function_arg (args->data, task, TRUE); - if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { - recursive = TRUE; - } - } - else { - /* - * If user did not specify argument, let's assume that he wants - * recursive search if mime part is multipart/mixed - */ - if (g_mime_content_type_is_type (ct, "multipart", "*")) { - recursive = TRUE; - } - } - - if (recursive) { - cur = task->parts; - } - -#ifndef GMIME24 - g_object_unref (part); -#endif - for (;;) { - if (*param_pattern == '/') { - /* This is regexp, so compile and create g_regexp object */ - if ((re = re_cache_check (param_pattern, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, param_pattern, task->cfg->raw_mode); - if (re == NULL) { - msg_warn ("cannot compile regexp for function"); - return FALSE; - } - re_cache_add (param_pattern, re, task->cfg->cfg_pool); - } - if ((r = task_cache_check (task, re)) == -1) { - if (g_regex_match (re->regexp, ct->subtype, 0, NULL) == TRUE) { - task_cache_add (task, re, 1); - return TRUE; - } - task_cache_add (task, re, 0); - } - else { - - } - } - else { - /* Just do strcasecmp */ - if (g_ascii_strcasecmp (ct->subtype, param_pattern) == 0) { - return TRUE; - } - } - /* Get next part */ - if (! recursive) { - return result; - } - else if (cur != NULL) { - cur_part = cur->data; - if (cur_part->type != NULL) { - ct = cur_part->type; - } - cur = g_list_next (cur); - } - else { - /* All is done */ - return result; - } - } - - } - - return FALSE; -} - -gboolean -rspamd_content_type_is_type (struct worker_task * task, GList * args, void *unused) -{ - gchar *param_pattern; - struct rspamd_regexp *re; - struct expression_argument *arg, *arg1; - GMimeObject *part; - GMimeContentType *ct; - gint r; - gboolean recursive = FALSE, result = FALSE; - GList *cur = NULL; - struct mime_part *cur_part; - - if (args == NULL) { - msg_warn ("no parameters to function"); - return FALSE; - } - arg = get_function_arg (args->data, task, TRUE); - param_pattern = arg->data; - - - part = g_mime_message_get_mime_part (task->message); - if (part) { - ct = (GMimeContentType *)g_mime_object_get_content_type (part); - if (args->next) { - args = g_list_next (args); - arg1 = get_function_arg (args->data, task, TRUE); - if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { - recursive = TRUE; - } - } - else { - /* - * If user did not specify argument, let's assume that he wants - * recursive search if mime part is multipart/mixed - */ - if (g_mime_content_type_is_type (ct, "multipart", "*")) { - recursive = TRUE; - } - } - - if (recursive) { - cur = task->parts; - } - -#ifndef GMIME24 - g_object_unref (part); -#endif - for (;;) { - if (*param_pattern == '/') { - /* This is regexp, so compile and create g_regexp object */ - if ((re = re_cache_check (param_pattern, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, param_pattern, task->cfg->raw_mode); - if (re == NULL) { - msg_warn ("cannot compile regexp for function"); - return FALSE; - } - re_cache_add (param_pattern, re, task->cfg->cfg_pool); - } - if ((r = task_cache_check (task, re)) == -1) { - if (g_regex_match (re->regexp, ct->type, 0, NULL) == TRUE) { - task_cache_add (task, re, 1); - return TRUE; - } - task_cache_add (task, re, 0); - } - else { - - } - } - else { - /* Just do strcasecmp */ - if (g_ascii_strcasecmp (ct->type, param_pattern) == 0) { - return TRUE; - } - } - /* Get next part */ - if (! recursive) { - return result; - } - else if (cur != NULL) { - cur_part = cur->data; - if (cur_part->type != NULL) { - ct = cur_part->type; - } - cur = g_list_next (cur); - } - else { - /* All is done */ - return result; - } - } - - } - - return FALSE; -} - struct addr_list { const gchar *name; const gchar *addr; @@ -1668,207 +1281,6 @@ rspamd_is_recipients_sorted (struct worker_task * task, GList * args, void *unus return FALSE; } -static inline gboolean -compare_subtype (struct worker_task *task, GMimeContentType * ct, gchar *subtype) -{ - struct rspamd_regexp *re; - gint r; - - if (*subtype == '/') { - /* This is regexp, so compile and create g_regexp object */ - if ((re = re_cache_check (subtype, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, subtype, task->cfg->raw_mode); - if (re == NULL) { - msg_warn ("cannot compile regexp for function"); - return FALSE; - } - re_cache_add (subtype, re, task->cfg->cfg_pool); - } - if ((r = task_cache_check (task, re)) == -1) { - if (g_regex_match (re->regexp, subtype, 0, NULL) == TRUE) { - task_cache_add (task, re, 1); - return TRUE; - } - task_cache_add (task, re, 0); - } - else { - return r == 1; - } - } - else { - /* Just do strcasecmp */ - if (ct->subtype && g_ascii_strcasecmp (ct->subtype, subtype) == 0) { - return TRUE; - } - } - - return FALSE; -} - -static inline gboolean -compare_len (struct mime_part *part, guint min, guint max) -{ - if (min == 0 && max == 0) { - return TRUE; - } - - if (min == 0) { - return part->content->len <= max; - } - else if (max == 0) { - return part->content->len >= min; - } - else { - return part->content->len >= min && part->content->len <= max; - } -} - -gboolean -common_has_content_part (struct worker_task * task, gchar *param_type, gchar *param_subtype, gint min_len, gint max_len) -{ - struct rspamd_regexp *re; - struct mime_part *part; - GList *cur; - GMimeContentType *ct; - gint r; - - cur = g_list_first (task->parts); - while (cur) { - part = cur->data; - ct = part->type; - if (ct == NULL) { - cur = g_list_next (cur); - continue; - } - - if (*param_type == '/') { - /* This is regexp, so compile and create g_regexp object */ - if ((re = re_cache_check (param_type, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, param_type, task->cfg->raw_mode); - if (re == NULL) { - msg_warn ("cannot compile regexp for function"); - cur = g_list_next (cur); - continue; - } - re_cache_add (param_type, re, task->cfg->cfg_pool); - } - if ((r = task_cache_check (task, re)) == -1) { - if (ct->type && g_regex_match (re->regexp, ct->type, 0, NULL) == TRUE) { - if (param_subtype) { - if (compare_subtype (task, ct, param_subtype)) { - if (compare_len (part, min_len, max_len)) { - return TRUE; - } - } - } - else { - if (compare_len (part, min_len, max_len)) { - return TRUE; - } - } - task_cache_add (task, re, 1); - } - else { - task_cache_add (task, re, 0); - } - } - else { - if (r == 1) { - if (compare_subtype (task, ct, param_subtype)) { - if (compare_len (part, min_len, max_len)) { - return TRUE; - } - } - } - } - } - else { - /* Just do strcasecmp */ - if (ct->type && g_ascii_strcasecmp (ct->type, param_type) == 0) { - if (param_subtype) { - if (compare_subtype (task, ct, param_subtype)) { - if (compare_len (part, min_len, max_len)) { - return TRUE; - } - } - } - else { - if (compare_len (part, min_len, max_len)) { - return TRUE; - } - } - } - } - cur = g_list_next (cur); - } - - return FALSE; -} - -gboolean -rspamd_has_content_part (struct worker_task * task, GList * args, void *unused) -{ - gchar *param_type = NULL, *param_subtype = NULL; - struct expression_argument *arg; - - if (args == NULL) { - msg_warn ("no parameters to function"); - return FALSE; - } - - arg = get_function_arg (args->data, task, TRUE); - param_type = arg->data; - args = args->next; - if (args) { - arg = args->data; - param_subtype = arg->data; - } - - return common_has_content_part (task, param_type, param_subtype, 0, 0); -} - -gboolean -rspamd_has_content_part_len (struct worker_task * task, GList * args, void *unused) -{ - gchar *param_type = NULL, *param_subtype = NULL; - gint min = 0, max = 0; - struct expression_argument *arg; - - if (args == NULL) { - msg_warn ("no parameters to function"); - return FALSE; - } - - arg = get_function_arg (args->data, task, TRUE); - param_type = arg->data; - args = args->next; - if (args) { - arg = get_function_arg (args->data, task, TRUE); - param_subtype = arg->data; - args = args->next; - if (args) { - arg = get_function_arg (args->data, task, TRUE); - errno = 0; - min = strtoul (arg->data, NULL, 10); - if (errno != 0) { - msg_warn ("invalid numeric value '%s': %s", (gchar *)arg->data, strerror (errno)); - return FALSE; - } - args = args->next; - if (args) { - arg = get_function_arg (args->data, task, TRUE); - max = strtoul (arg->data, NULL, 10); - if (errno != 0) { - msg_warn ("invalid numeric value '%s': %s", (gchar *)arg->data, strerror (errno)); - return FALSE; - } - } - } - } - - return common_has_content_part (task, param_type, param_subtype, min, max); -} - gboolean rspamd_compare_transfer_encoding (struct worker_task * task, GList * args, void *unused) { diff --git a/src/plugins/regexp.c b/src/plugins/regexp.c index 35be00bd7..5b1eefe42 100644 --- a/src/plugins/regexp.c +++ b/src/plugins/regexp.c @@ -87,12 +87,19 @@ static struct regexp_ctx *regexp_module_ctx = NULL; static GMutex *workers_mtx = NULL; static gint regexp_common_filter (struct worker_task *task); -static void process_regexp_item_threaded (gpointer data, gpointer user_data); +static void process_regexp_item_threaded (gpointer data, gpointer user_data); static gboolean rspamd_regexp_match_number (struct worker_task *task, GList * args, void *unused); static gboolean rspamd_raw_header_exists (struct worker_task *task, GList * args, void *unused); static gboolean rspamd_check_smtp_data (struct worker_task *task, GList * args, void *unused); static gboolean rspamd_regexp_occurs_number (struct worker_task *task, GList * args, void *unused); -static void process_regexp_item (struct worker_task *task, void *user_data); +static gboolean rspamd_content_type_is_type (struct worker_task * task, GList * args, void *unused); +static gboolean rspamd_content_type_is_subtype (struct worker_task *task, GList * args, void *unused); +static gboolean rspamd_content_type_has_param (struct worker_task * task, GList * args, void *unused); +static gboolean rspamd_content_type_compare_param (struct worker_task * task, GList * args, void *unused); +static gboolean rspamd_has_content_part (struct worker_task *task, GList * args, void *unused); +static gboolean rspamd_has_content_part_len (struct worker_task *task, GList * args, void *unused); +static void process_regexp_item (struct worker_task *task, void *user_data); + /* Initialization */ gint regexp_module_init (struct config_file *cfg, struct module_ctx **ctx); @@ -515,6 +522,12 @@ regexp_module_init (struct config_file *cfg, struct module_ctx **ctx) register_expression_function ("regexp_occurs_number", rspamd_regexp_occurs_number, NULL); register_expression_function ("raw_header_exists", rspamd_raw_header_exists, NULL); register_expression_function ("check_smtp_data", rspamd_check_smtp_data, NULL); + register_expression_function ("content_type_is_type", rspamd_content_type_is_type, NULL); + register_expression_function ("content_type_is_subtype", rspamd_content_type_is_subtype, NULL); + register_expression_function ("content_type_has_param", rspamd_content_type_has_param, NULL); + register_expression_function ("content_type_compare_param", rspamd_content_type_compare_param, NULL); + register_expression_function ("has_content_part", rspamd_has_content_part, NULL); + register_expression_function ("has_content_part_len", rspamd_has_content_part_len, NULL); (void)luaopen_regexp (cfg->lua_state); register_module_opt ("regexp", "dynamic_rules", MODULE_OPT_TYPE_STRING); @@ -1643,3 +1656,582 @@ lua_regexp_match (lua_State *L) return 1; } + +static gboolean +rspamd_content_type_compare_param (struct worker_task * task, GList * args, void *unused) +{ + gchar *param_name, *param_pattern; + const gchar *param_data; + struct rspamd_regexp *re; + struct expression_argument *arg, *arg1; + GMimeObject *part; + GMimeContentType *ct; + gint r; + gboolean recursive = FALSE, result = FALSE; + GList *cur = NULL; + struct mime_part *cur_part; + + if (args == NULL) { + msg_warn ("no parameters to function"); + return FALSE; + } + arg = get_function_arg (args->data, task, TRUE); + param_name = arg->data; + args = g_list_next (args); + if (args == NULL) { + msg_warn ("too few params to function"); + return FALSE; + } + arg = get_function_arg (args->data, task, TRUE); + param_pattern = arg->data; + + + part = g_mime_message_get_mime_part (task->message); + if (part) { + ct = (GMimeContentType *)g_mime_object_get_content_type (part); + if (args->next) { + args = g_list_next (args); + arg1 = get_function_arg (args->data, task, TRUE); + if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { + recursive = TRUE; + } + } + else { + /* + * If user did not specify argument, let's assume that he wants + * recursive search if mime part is multipart/mixed + */ + if (g_mime_content_type_is_type (ct, "multipart", "*")) { + recursive = TRUE; + } + } + + if (recursive) { + cur = task->parts; + } + +#ifndef GMIME24 + g_object_unref (part); +#endif + for (;;) { + if ((param_data = g_mime_content_type_get_parameter ((GMimeContentType *)ct, param_name)) == NULL) { + result = FALSE; + } + else { + if (*param_pattern == '/') { + /* This is regexp, so compile and create g_regexp object */ + if ((re = re_cache_check (param_pattern, task->cfg->cfg_pool)) == NULL) { + re = parse_regexp (task->cfg->cfg_pool, param_pattern, task->cfg->raw_mode); + if (re == NULL) { + msg_warn ("cannot compile regexp for function"); + return FALSE; + } + re_cache_add (param_pattern, re, task->cfg->cfg_pool); + } + if ((r = task_cache_check (task, re)) == -1) { + if (g_regex_match (re->regexp, param_data, 0, NULL) == TRUE) { + task_cache_add (task, re, 1); + return TRUE; + } + task_cache_add (task, re, 0); + } + else { + + } + } + else { + /* Just do strcasecmp */ + if (g_ascii_strcasecmp (param_data, param_pattern) == 0) { + return TRUE; + } + } + } + /* Get next part */ + if (! recursive) { + return result; + } + else if (cur != NULL) { + cur_part = cur->data; + if (cur_part->type != NULL) { + ct = cur_part->type; + } + cur = g_list_next (cur); + } + else { + /* All is done */ + return result; + } + } + + } + + return FALSE; +} + +static gboolean +rspamd_content_type_has_param (struct worker_task * task, GList * args, void *unused) +{ + gchar *param_name; + const gchar *param_data; + struct expression_argument *arg, *arg1; + GMimeObject *part; + GMimeContentType *ct; + gboolean recursive = FALSE, result = FALSE; + GList *cur = NULL; + struct mime_part *cur_part; + + if (args == NULL) { + msg_warn ("no parameters to function"); + return FALSE; + } + arg = get_function_arg (args->data, task, TRUE); + param_name = arg->data; + + part = g_mime_message_get_mime_part (task->message); + if (part) { + ct = (GMimeContentType *)g_mime_object_get_content_type (part); + if (args->next) { + args = g_list_next (args); + arg1 = get_function_arg (args->data, task, TRUE); + if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { + recursive = TRUE; + } + } + else { + /* + * If user did not specify argument, let's assume that he wants + * recursive search if mime part is multipart/mixed + */ + if (g_mime_content_type_is_type (ct, "multipart", "*")) { + recursive = TRUE; + } + } + + if (recursive) { + cur = task->parts; + } + +#ifndef GMIME24 + g_object_unref (part); +#endif + for (;;) { + if ((param_data = g_mime_content_type_get_parameter ((GMimeContentType *)ct, param_name)) != NULL) { + return TRUE; + } + /* Get next part */ + if (! recursive) { + return result; + } + else if (cur != NULL) { + cur_part = cur->data; + if (cur_part->type != NULL) { + ct = cur_part->type; + } + cur = g_list_next (cur); + } + else { + /* All is done */ + return result; + } + } + + } + + return TRUE; +} + +static gboolean +rspamd_content_type_is_subtype (struct worker_task *task, GList * args, void *unused) +{ + gchar *param_pattern; + struct rspamd_regexp *re; + struct expression_argument *arg, *arg1; + GMimeObject *part; + GMimeContentType *ct; + gint r; + gboolean recursive = FALSE, result = FALSE; + GList *cur = NULL; + struct mime_part *cur_part; + + if (args == NULL) { + msg_warn ("no parameters to function"); + return FALSE; + } + arg = get_function_arg (args->data, task, TRUE); + param_pattern = arg->data; + + part = g_mime_message_get_mime_part (task->message); + if (part) { + ct = (GMimeContentType *)g_mime_object_get_content_type (part); + if (args->next) { + args = g_list_next (args); + arg1 = get_function_arg (args->data, task, TRUE); + if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { + recursive = TRUE; + } + } + else { + /* + * If user did not specify argument, let's assume that he wants + * recursive search if mime part is multipart/mixed + */ + if (g_mime_content_type_is_type (ct, "multipart", "*")) { + recursive = TRUE; + } + } + + if (recursive) { + cur = task->parts; + } + +#ifndef GMIME24 + g_object_unref (part); +#endif + for (;;) { + if (*param_pattern == '/') { + /* This is regexp, so compile and create g_regexp object */ + if ((re = re_cache_check (param_pattern, task->cfg->cfg_pool)) == NULL) { + re = parse_regexp (task->cfg->cfg_pool, param_pattern, task->cfg->raw_mode); + if (re == NULL) { + msg_warn ("cannot compile regexp for function"); + return FALSE; + } + re_cache_add (param_pattern, re, task->cfg->cfg_pool); + } + if ((r = task_cache_check (task, re)) == -1) { + if (g_regex_match (re->regexp, ct->subtype, 0, NULL) == TRUE) { + task_cache_add (task, re, 1); + return TRUE; + } + task_cache_add (task, re, 0); + } + else { + + } + } + else { + /* Just do strcasecmp */ + if (g_ascii_strcasecmp (ct->subtype, param_pattern) == 0) { + return TRUE; + } + } + /* Get next part */ + if (! recursive) { + return result; + } + else if (cur != NULL) { + cur_part = cur->data; + if (cur_part->type != NULL) { + ct = cur_part->type; + } + cur = g_list_next (cur); + } + else { + /* All is done */ + return result; + } + } + + } + + return FALSE; +} + +static gboolean +rspamd_content_type_is_type (struct worker_task * task, GList * args, void *unused) +{ + gchar *param_pattern; + struct rspamd_regexp *re; + struct expression_argument *arg, *arg1; + GMimeObject *part; + GMimeContentType *ct; + gint r; + gboolean recursive = FALSE, result = FALSE; + GList *cur = NULL; + struct mime_part *cur_part; + + if (args == NULL) { + msg_warn ("no parameters to function"); + return FALSE; + } + arg = get_function_arg (args->data, task, TRUE); + param_pattern = arg->data; + + + part = g_mime_message_get_mime_part (task->message); + if (part) { + ct = (GMimeContentType *)g_mime_object_get_content_type (part); + if (args->next) { + args = g_list_next (args); + arg1 = get_function_arg (args->data, task, TRUE); + if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { + recursive = TRUE; + } + } + else { + /* + * If user did not specify argument, let's assume that he wants + * recursive search if mime part is multipart/mixed + */ + if (g_mime_content_type_is_type (ct, "multipart", "*")) { + recursive = TRUE; + } + } + + if (recursive) { + cur = task->parts; + } + +#ifndef GMIME24 + g_object_unref (part); +#endif + for (;;) { + if (*param_pattern == '/') { + /* This is regexp, so compile and create g_regexp object */ + if ((re = re_cache_check (param_pattern, task->cfg->cfg_pool)) == NULL) { + re = parse_regexp (task->cfg->cfg_pool, param_pattern, task->cfg->raw_mode); + if (re == NULL) { + msg_warn ("cannot compile regexp for function"); + return FALSE; + } + re_cache_add (param_pattern, re, task->cfg->cfg_pool); + } + if ((r = task_cache_check (task, re)) == -1) { + if (g_regex_match (re->regexp, ct->type, 0, NULL) == TRUE) { + task_cache_add (task, re, 1); + return TRUE; + } + task_cache_add (task, re, 0); + } + else { + + } + } + else { + /* Just do strcasecmp */ + if (g_ascii_strcasecmp (ct->type, param_pattern) == 0) { + return TRUE; + } + } + /* Get next part */ + if (! recursive) { + return result; + } + else if (cur != NULL) { + cur_part = cur->data; + if (cur_part->type != NULL) { + ct = cur_part->type; + } + cur = g_list_next (cur); + } + else { + /* All is done */ + return result; + } + } + + } + + return FALSE; +} + +static gboolean +compare_subtype (struct worker_task *task, GMimeContentType * ct, gchar *subtype) +{ + struct rspamd_regexp *re; + gint r; + + if (*subtype == '/') { + /* This is regexp, so compile and create g_regexp object */ + if ((re = re_cache_check (subtype, task->cfg->cfg_pool)) == NULL) { + re = parse_regexp (task->cfg->cfg_pool, subtype, task->cfg->raw_mode); + if (re == NULL) { + msg_warn ("cannot compile regexp for function"); + return FALSE; + } + re_cache_add (subtype, re, task->cfg->cfg_pool); + } + if ((r = task_cache_check (task, re)) == -1) { + if (g_regex_match (re->regexp, subtype, 0, NULL) == TRUE) { + task_cache_add (task, re, 1); + return TRUE; + } + task_cache_add (task, re, 0); + } + else { + return r == 1; + } + } + else { + /* Just do strcasecmp */ + if (ct->subtype && g_ascii_strcasecmp (ct->subtype, subtype) == 0) { + return TRUE; + } + } + + return FALSE; +} + +static gboolean +compare_len (struct mime_part *part, guint min, guint max) +{ + if (min == 0 && max == 0) { + return TRUE; + } + + if (min == 0) { + return part->content->len <= max; + } + else if (max == 0) { + return part->content->len >= min; + } + else { + return part->content->len >= min && part->content->len <= max; + } +} + +static gboolean +common_has_content_part (struct worker_task * task, gchar *param_type, gchar *param_subtype, gint min_len, gint max_len) +{ + struct rspamd_regexp *re; + struct mime_part *part; + GList *cur; + GMimeContentType *ct; + gint r; + + cur = g_list_first (task->parts); + while (cur) { + part = cur->data; + ct = part->type; + if (ct == NULL) { + cur = g_list_next (cur); + continue; + } + + if (*param_type == '/') { + /* This is regexp, so compile and create g_regexp object */ + if ((re = re_cache_check (param_type, task->cfg->cfg_pool)) == NULL) { + re = parse_regexp (task->cfg->cfg_pool, param_type, task->cfg->raw_mode); + if (re == NULL) { + msg_warn ("cannot compile regexp for function"); + cur = g_list_next (cur); + continue; + } + re_cache_add (param_type, re, task->cfg->cfg_pool); + } + if ((r = task_cache_check (task, re)) == -1) { + if (ct->type && g_regex_match (re->regexp, ct->type, 0, NULL) == TRUE) { + if (param_subtype) { + if (compare_subtype (task, ct, param_subtype)) { + if (compare_len (part, min_len, max_len)) { + return TRUE; + } + } + } + else { + if (compare_len (part, min_len, max_len)) { + return TRUE; + } + } + task_cache_add (task, re, 1); + } + else { + task_cache_add (task, re, 0); + } + } + else { + if (r == 1) { + if (compare_subtype (task, ct, param_subtype)) { + if (compare_len (part, min_len, max_len)) { + return TRUE; + } + } + } + } + } + else { + /* Just do strcasecmp */ + if (ct->type && g_ascii_strcasecmp (ct->type, param_type) == 0) { + if (param_subtype) { + if (compare_subtype (task, ct, param_subtype)) { + if (compare_len (part, min_len, max_len)) { + return TRUE; + } + } + } + else { + if (compare_len (part, min_len, max_len)) { + return TRUE; + } + } + } + } + cur = g_list_next (cur); + } + + return FALSE; +} + +static gboolean +rspamd_has_content_part (struct worker_task * task, GList * args, void *unused) +{ + gchar *param_type = NULL, *param_subtype = NULL; + struct expression_argument *arg; + + if (args == NULL) { + msg_warn ("no parameters to function"); + return FALSE; + } + + arg = get_function_arg (args->data, task, TRUE); + param_type = arg->data; + args = args->next; + if (args) { + arg = args->data; + param_subtype = arg->data; + } + + return common_has_content_part (task, param_type, param_subtype, 0, 0); +} + +static gboolean +rspamd_has_content_part_len (struct worker_task * task, GList * args, void *unused) +{ + gchar *param_type = NULL, *param_subtype = NULL; + gint min = 0, max = 0; + struct expression_argument *arg; + + if (args == NULL) { + msg_warn ("no parameters to function"); + return FALSE; + } + + arg = get_function_arg (args->data, task, TRUE); + param_type = arg->data; + args = args->next; + if (args) { + arg = get_function_arg (args->data, task, TRUE); + param_subtype = arg->data; + args = args->next; + if (args) { + arg = get_function_arg (args->data, task, TRUE); + errno = 0; + min = strtoul (arg->data, NULL, 10); + if (errno != 0) { + msg_warn ("invalid numeric value '%s': %s", (gchar *)arg->data, strerror (errno)); + return FALSE; + } + args = args->next; + if (args) { + arg = get_function_arg (args->data, task, TRUE); + max = strtoul (arg->data, NULL, 10); + if (errno != 0) { + msg_warn ("invalid numeric value '%s': %s", (gchar *)arg->data, strerror (errno)); + return FALSE; + } + } + } + } + + return common_has_content_part (task, param_type, param_subtype, min, max); +} diff --git a/src/util.c b/src/util.c index 5fcf0858b..e7fe474ad 100644 --- a/src/util.c +++ b/src/util.c @@ -1335,8 +1335,8 @@ rspamd_strtoul (const gchar *s, gsize len, gulong *value) gint rspamd_fallocate (gint fd, off_t offset, off_t len) { -#if defined(HAVE_FALLOCATE) && defined(FALLOC_FL_KEEP_SIZE) - return fallocate (fd, FALLOC_FL_KEEP_SIZE, offset, len); +#if defined(HAVE_FALLOCATE) + return fallocate (fd, 0, offset, len); #elif defined(HAVE_POSIX_FALLOCATE) return posix_fallocate (fd, offset, len); #else diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c6011d2a8..c15f77b75 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -15,6 +15,10 @@ TARGET_LINK_LIBRARIES(rspamd-test rspamdserver) TARGET_LINK_LIBRARIES(rspamd-test event) TARGET_LINK_LIBRARIES(rspamd-test ${GLIB2_LIBRARIES}) TARGET_LINK_LIBRARIES(rspamd-test ${CMAKE_REQUIRED_LIBRARIES}) +IF(HAVE_LIBEVENT2) + TARGET_LINK_LIBRARIES(rspamd-test event_pthreads) +ENDIF(HAVE_LIBEVENT2) +INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/src") IF(GMIME2_FOUND) TARGET_LINK_LIBRARIES(rspamd-test ${GMIME2_LIBRARIES}) ELSE(GMIME2_FOUND) diff --git a/test/rspamd_dns_test.c b/test/rspamd_dns_test.c index c0b48080e..839c00a79 100644 --- a/test/rspamd_dns_test.c +++ b/test/rspamd_dns_test.c @@ -8,6 +8,7 @@ #include "../src/cfg_file.h" static guint requests = 0; +extern struct event_base *base; static void test_dns_cb (struct rspamd_dns_reply *reply, gpointer arg) @@ -49,7 +50,7 @@ test_dns_cb (struct rspamd_dns_reply *reply, gpointer arg) } } -void +gboolean session_fin (gpointer unused) { struct timeval tv; @@ -57,6 +58,8 @@ session_fin (gpointer unused) tv.tv_sec = 0; tv.tv_usec = 0; event_loopexit (&tv); + + return TRUE; } void @@ -76,9 +79,9 @@ rspamd_dns_test_func () pool = memory_pool_new (memory_pool_get_size ()); event_init (); - s = new_async_session (pool, session_fin, NULL); + s = new_async_session (pool, session_fin, NULL, NULL, NULL); - resolver = dns_resolver_init (cfg); + resolver = dns_resolver_init (base, cfg); requests ++; g_assert (make_dns_request (resolver, s, pool, test_dns_cb, NULL, DNS_REQUEST_A, "google.com")); diff --git a/test/rspamd_fuzzy_test.c b/test/rspamd_fuzzy_test.c index 004ebf3c0..7805e4f42 100644 --- a/test/rspamd_fuzzy_test.c +++ b/test/rspamd_fuzzy_test.c @@ -39,7 +39,7 @@ rspamd_fuzzy_test_func () memory_pool_t *pool; fuzzy_hash_t *h1, *h2, *h3, *h4, *h5; f_str_t f1, f2, f3, f4, f5; - int diff1, diff2; + int diff2; pool = memory_pool_new (1024); f1.begin = s1; @@ -59,7 +59,6 @@ rspamd_fuzzy_test_func () h4 = fuzzy_init (&f4, pool); h5 = fuzzy_init (&f5, pool); - diff1 = fuzzy_compare_hashes (h3, h4) + fuzzy_compare_hashes (h2, h4); diff2 = fuzzy_compare_hashes (h2, h5); msg_debug ("rspamd_fuzzy_test_func: s1, s2 difference between strings is %d", fuzzy_compare_hashes (h1, h2)); msg_debug ("rspamd_fuzzy_test_func: s1, s3 difference between strings is %d", fuzzy_compare_hashes (h1, h3)); diff --git a/test/rspamd_test_suite.c b/test/rspamd_test_suite.c index 423086506..f035fcb81 100644 --- a/test/rspamd_test_suite.c +++ b/test/rspamd_test_suite.c @@ -5,6 +5,8 @@ static gboolean do_debug; struct rspamd_main *rspamd_main = NULL; +struct event_base *base = NULL; +worker_t *workers[] = { NULL }; static GOptionEntry entries[] = { @@ -15,7 +17,7 @@ static GOptionEntry entries[] = int main (int argc, char **argv) { - struct config_file *cfg; + struct config_file *cfg; GError *error = NULL; GOptionContext *context; @@ -39,6 +41,8 @@ main (int argc, char **argv) bzero (cfg, sizeof (struct config_file)); cfg->cfg_pool = memory_pool_new (memory_pool_get_size ()); + base = event_init (); + if (do_debug) { cfg->log_level = G_LOG_LEVEL_DEBUG; } @@ -46,11 +50,13 @@ main (int argc, char **argv) cfg->log_level = G_LOG_LEVEL_INFO; } /* First set logger to console logger */ - rspamd_set_logger (RSPAMD_LOG_CONSOLE, TYPE_MAIN, rspamd_main); + rspamd_set_logger (RSPAMD_LOG_CONSOLE, g_quark_from_static_string("rspamd-test"), rspamd_main); (void)open_log (rspamd_main->logger); g_log_set_default_handler (rspamd_glib_log_function, rspamd_main->logger); +#if 0 g_test_add_func ("/rspamd/memcached", rspamd_memcached_test_func); +#endif g_test_add_func ("/rspamd/mem_pool", rspamd_mem_pool_test_func); g_test_add_func ("/rspamd/fuzzy", rspamd_fuzzy_test_func); g_test_add_func ("/rspamd/url", rspamd_url_test_func); -- 2.39.5