diff options
author | Vsevolod Stakhov <vsevolod@rambler-co.ru> | 2010-10-20 22:26:34 +0400 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@rambler-co.ru> | 2010-10-20 22:26:34 +0400 |
commit | 7a09c641f8caaefa697013540166f0a7f3857321 (patch) | |
tree | ece6ade382dd4acb53f275a34fe47c590e8ff617 /src/expressions.c | |
parent | 2f23fd64a793f818300bb645beb16f1a01528d31 (diff) | |
download | rspamd-7a09c641f8caaefa697013540166f0a7f3857321.tar.gz rspamd-7a09c641f8caaefa697013540166f0a7f3857321.zip |
* Add ability to recursive scan over multipart's parts for functions:
- content_type_is_type
- content_type_is_subtype
- content_type_compare_param
- content_type_has_param
* Add ability to specify any of actions in user's settings, not only reject.
Diffstat (limited to 'src/expressions.c')
-rw-r--r-- | src/expressions.c | 327 |
1 files changed, 241 insertions, 86 deletions
diff --git a/src/expressions.c b/src/expressions.c index 9d17a146c..c4fa738b5 100644 --- a/src/expressions.c +++ b/src/expressions.c @@ -1003,10 +1003,13 @@ rspamd_content_type_compare_param (struct worker_task * task, GList * args, void gchar *param_name, *param_pattern; const gchar *param_data; struct rspamd_regexp *re; - struct expression_argument *arg; + struct expression_argument *arg, *arg1; GMimeObject *part; - const GMimeContentType *ct; + GMimeContentType *ct; gint r; + gboolean recursive = FALSE, result = FALSE; + GList *cur; + struct mime_part *cur_part; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1022,45 +1025,83 @@ rspamd_content_type_compare_param (struct worker_task * task, GList * args, void arg = get_function_arg (args->data, task, TRUE); param_pattern = arg->data; + part = g_mime_message_get_mime_part (task->message); if (part) { - ct = g_mime_object_get_content_type (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; + } + 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 { - if ((param_data = g_mime_content_type_get_parameter ((GMimeContentType *)ct, param_name)) == NULL) { - return FALSE; - } - 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); + else { + /* Just do strcasecmp */ + if (g_ascii_strcasecmp (param_data, param_pattern) == 0) { return TRUE; } - task_cache_add (task, re, 0); } - else { - return r == 1; + /* Get next part */ + if (! recursive) { + return result; } - } - else { - /* Just do strcasecmp */ - if (g_ascii_strcasecmp (param_data, param_pattern) == 0) { - return TRUE; + 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; } @@ -1070,9 +1111,12 @@ rspamd_content_type_has_param (struct worker_task * task, GList * args, void *un { gchar *param_name; const gchar *param_data; - struct expression_argument *arg; + struct expression_argument *arg, *arg1; GMimeObject *part; - const GMimeContentType *ct; + GMimeContentType *ct; + gboolean recursive = FALSE, result = FALSE; + GList *cur; + struct mime_part *cur_part; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1080,18 +1124,55 @@ rspamd_content_type_has_param (struct worker_task * task, GList * args, void *un } arg = get_function_arg (args->data, task, TRUE); param_name = arg->data; + part = g_mime_message_get_mime_part (task->message); if (part) { - ct = g_mime_object_get_content_type (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 - - debug_task ("checking %s param", param_name); - param_data = g_mime_content_type_get_parameter ((GMimeContentType *)ct, param_name); - if (param_data == NULL) { - return FALSE; + 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; @@ -1100,58 +1181,95 @@ rspamd_content_type_has_param (struct worker_task * task, GList * args, void *un gboolean rspamd_content_type_is_subtype (struct worker_task *task, GList * args, void *unused) { - gchar *param_pattern; + gchar *param_pattern; struct rspamd_regexp *re; - struct expression_argument *arg; + struct expression_argument *arg, *arg1; GMimeObject *part; GMimeContentType *ct; gint r; + gboolean recursive = FALSE, result = FALSE; + GList *cur; + 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 { - if (ct == NULL ) { - return FALSE; - } - - 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); + else { + /* Just do strcasecmp */ + if (g_ascii_strcasecmp (ct->subtype, param_pattern) == 0) { return TRUE; } - task_cache_add (task, re, 0); } - else { - return r == 1; + /* Get next part */ + if (! recursive) { + return result; } - } - else { - /* Just do strcasecmp */ - if (ct->subtype && g_ascii_strcasecmp (ct->subtype, param_pattern) == 0) { - return TRUE; + 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; @@ -1160,59 +1278,96 @@ rspamd_content_type_is_subtype (struct worker_task *task, GList * args, void *un gboolean rspamd_content_type_is_type (struct worker_task * task, GList * args, void *unused) { - gchar *param_pattern; + gchar *param_pattern; struct rspamd_regexp *re; + struct expression_argument *arg, *arg1; GMimeObject *part; GMimeContentType *ct; - struct expression_argument *arg; gint r; + gboolean recursive = FALSE, result = FALSE; + GList *cur; + 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 { - if (ct == NULL) { - return FALSE; - } - - 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); + else { + /* Just do strcasecmp */ + if (g_ascii_strcasecmp (ct->type, param_pattern) == 0) { return TRUE; } - task_cache_add (task, re, 0); } - else { - return r == 1; + /* Get next part */ + if (! recursive) { + return result; } - } - else { - /* Just do strcasecmp */ - if (ct->type && g_ascii_strcasecmp (ct->type, param_pattern) == 0) { - return TRUE; + 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; |