From 17a938b2aeffb3448c8d61f3d8dd7d012eb910cc Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Tue, 15 Feb 2011 18:26:27 +0300 Subject: [PATCH] * Add ability to specify 'S' flag to regexp that means that headers checks must be case sensitive * Add lua function message:get_header_strong --- src/cfg_file.h | 1 + src/controller.c | 2 +- src/expressions.c | 7 ++++- src/filter.c | 2 +- src/lua/lua_message.c | 17 ++++++++-- src/message.c | 72 +++++++++++++++++++++++++++++-------------- src/message.h | 2 +- src/plugins/regexp.c | 2 +- src/spf.c | 2 +- 9 files changed, 76 insertions(+), 31 deletions(-) diff --git a/src/cfg_file.h b/src/cfg_file.h index e33b1585a..09eea3976 100644 --- a/src/cfg_file.h +++ b/src/cfg_file.h @@ -93,6 +93,7 @@ struct rspamd_regexp { gchar *header; /**< header name for header regexps */ gboolean is_test; /**< true if this expression must be tested */ gboolean is_raw; /**< true if this regexp is done by raw matching */ + gboolean is_strong; /**< true if headers search must be case sensitive */ }; /** diff --git a/src/controller.c b/src/controller.c index e4dea60f7..162217828 100644 --- a/src/controller.c +++ b/src/controller.c @@ -800,7 +800,7 @@ controller_read_socket (f_str_t * in, void *arg) return FALSE; } if ((s = g_hash_table_lookup (session->learn_classifier->opts, "header")) != NULL) { - cur = message_get_header (task->task_pool, task->message, s); + cur = message_get_header (task->task_pool, task->message, s, FALSE); if (cur) { memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_list_free, cur); } diff --git a/src/expressions.c b/src/expressions.c index c3b45ef7c..87ce59337 100644 --- a/src/expressions.c +++ b/src/expressions.c @@ -245,6 +245,7 @@ is_regexp_flag (gchar a) case 'U': case 'X': case 'T': + case 'S': return TRUE; default: return FALSE; @@ -680,6 +681,10 @@ parse_regexp (memory_pool_t * pool, gchar *line, gboolean raw_mode) result->is_test = TRUE; p ++; break; + case 'S': + result->is_strong = TRUE; + p ++; + break; /* Stop flags parsing */ default: p = NULL; @@ -913,7 +918,7 @@ rspamd_header_exists (struct worker_task * task, GList * args, void *unused) } debug_task ("try to get header %s", (gchar *)arg->data); - headerlist = message_get_header (task->task_pool, task->message, (gchar *)arg->data); + headerlist = message_get_header (task->task_pool, task->message, (gchar *)arg->data, FALSE); if (headerlist) { g_list_free (headerlist); return TRUE; diff --git a/src/filter.c b/src/filter.c index 1091de0ca..91b0196d4 100644 --- a/src/filter.c +++ b/src/filter.c @@ -493,7 +493,7 @@ classifiers_callback (gpointer value, void *arg) gchar *header = NULL; if ((header = g_hash_table_lookup (cl->opts, "header")) != NULL) { - cur = message_get_header (task->task_pool, task->message, header); + cur = message_get_header (task->task_pool, task->message, header, FALSE); if (cur) { memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_list_free, cur); } diff --git a/src/lua/lua_message.c b/src/lua/lua_message.c index 04adec24a..2848e082f 100644 --- a/src/lua/lua_message.c +++ b/src/lua/lua_message.c @@ -66,6 +66,7 @@ LUA_FUNCTION_DEF (message, set_sender); LUA_FUNCTION_DEF (message, get_reply_to); LUA_FUNCTION_DEF (message, set_reply_to); LUA_FUNCTION_DEF (message, get_header); +LUA_FUNCTION_DEF (message, get_header_strong); LUA_FUNCTION_DEF (message, set_header); static const struct luaL_reg msglib_m[] = { @@ -78,6 +79,7 @@ static const struct luaL_reg msglib_m[] = { LUA_INTERFACE_DEF (message, get_reply_to), LUA_INTERFACE_DEF (message, set_reply_to), LUA_INTERFACE_DEF (message, get_header), + LUA_INTERFACE_DEF (message, get_header_strong), LUA_INTERFACE_DEF (message, set_header), {"__tostring", lua_class_tostring}, {NULL, NULL} @@ -106,7 +108,7 @@ LUA_GMIME_BRIDGE_GET (message, get_reply_to, Message) LUA_GMIME_BRIDGE_SET (message, set_reply_to, Message) static gint -lua_message_get_header (lua_State * L) +lua_message_get_header_common (lua_State * L, gboolean strong) { const gchar *headern; GMimeMessage *obj = lua_check_message (L); @@ -116,7 +118,7 @@ lua_message_get_header (lua_State * L) if (obj != NULL) { headern = luaL_checkstring (L, 2); if (headern) { - res = message_get_header (NULL, obj, headern); + res = message_get_header (NULL, obj, headern, strong); if (res) { cur = res; lua_newtable (L); @@ -143,6 +145,17 @@ lua_message_get_header (lua_State * L) return 1; } +static gint +lua_message_get_header (lua_State * L) +{ + return lua_message_get_header_common (L, FALSE); +} + +static gint +lua_message_get_header_strong (lua_State * L) +{ + return lua_message_get_header_common (L, TRUE); +} static gint lua_message_set_header (lua_State * L) diff --git a/src/message.c b/src/message.c index 83ce3b91d..323dd33a0 100644 --- a/src/message.c +++ b/src/message.c @@ -816,7 +816,7 @@ process_message (struct worker_task *task) #endif /* Parse received headers */ - first = message_get_header (task->task_pool, message, "Received"); + first = message_get_header (task->task_pool, message, "Received", FALSE); cur = first; while (cur) { recv = memory_pool_alloc0 (task->task_pool, sizeof (struct received_header)); @@ -927,15 +927,27 @@ enum { #ifndef GMIME24 static void -header_iterate (memory_pool_t * pool, struct raw_header *h, GList ** ret, const gchar *field) +header_iterate (memory_pool_t * pool, struct raw_header *h, GList ** ret, const gchar *field, gboolean strong) { while (h) { - if (h->value && !g_strncasecmp (field, h->name, strlen (field))) { - if (pool != NULL) { - *ret = g_list_prepend (*ret, memory_pool_strdup (pool, h->value)); + if (G_LIKELY (!strong)) { + if (h->value && !g_strncasecmp (field, h->name, strlen (field))) { + if (pool != NULL) { + *ret = g_list_prepend (*ret, memory_pool_strdup (pool, h->value)); + } + else { + *ret = g_list_prepend (*ret, g_strdup (h->value)); + } } - else { - *ret = g_list_prepend (*ret, g_strdup (h->value)); + } + else { + if (h->value && !strncmp (field, h->name, strlen (field))) { + if (pool != NULL) { + *ret = g_list_prepend (*ret, memory_pool_strdup (pool, h->value)); + } + else { + *ret = g_list_prepend (*ret, g_strdup (h->value)); + } } } h = h->next; @@ -943,7 +955,7 @@ header_iterate (memory_pool_t * pool, struct raw_header *h, GList ** ret, const } #else static void -header_iterate (memory_pool_t * pool, GMimeHeaderList * ls, GList ** ret, const gchar *field) +header_iterate (memory_pool_t * pool, GMimeHeaderList * ls, GList ** ret, const gchar *field, gboolean strong) { GMimeHeaderIter *iter; const gchar *name; @@ -957,12 +969,24 @@ header_iterate (memory_pool_t * pool, GMimeHeaderList * ls, GList ** ret, const if (g_mime_header_list_get_iter (ls, iter) && g_mime_header_iter_first (iter)) { while (g_mime_header_iter_is_valid (iter)) { name = g_mime_header_iter_get_name (iter); - if (!g_strncasecmp (field, name, strlen (name))) { - if (pool != NULL) { - *ret = g_list_prepend (*ret, memory_pool_strdup (pool, g_mime_header_iter_get_value (iter))); + if (G_LIKELY (!strong)) { + if (!g_strncasecmp (field, name, strlen (name))) { + if (pool != NULL) { + *ret = g_list_prepend (*ret, memory_pool_strdup (pool, g_mime_header_iter_get_value (iter))); + } + else { + *ret = g_list_prepend (*ret, g_strdup (g_mime_header_iter_get_value (iter))); + } } - else { - *ret = g_list_prepend (*ret, g_strdup (g_mime_header_iter_get_value (iter))); + } + else { + if (!strncmp (field, name, strlen (name))) { + if (pool != NULL) { + *ret = g_list_prepend (*ret, memory_pool_strdup (pool, g_mime_header_iter_get_value (iter))); + } + else { + *ret = g_list_prepend (*ret, g_strdup (g_mime_header_iter_get_value (iter))); + } } } if (!g_mime_header_iter_next (iter)) { @@ -980,6 +1004,7 @@ struct multipart_cb_data { memory_pool_t *pool; const gchar *field; gboolean try_search; + gboolean strong; gint rec; }; @@ -1003,10 +1028,10 @@ multipart_iterate (GMimeObject * part, gpointer user_data) GMimeHeaderList *ls; ls = g_mime_object_get_header_list (GMIME_OBJECT (part)); - header_iterate (data->pool, ls, &l, data->field); + header_iterate (data->pool, ls, &l, data->field, data->strong); #else h = part->headers->headers; - header_iterate (data->pool, h, &l, data->field); + header_iterate (data->pool, h, &l, data->field, data->strong); #endif if (l == NULL) { /* Header not found, abandon search results */ @@ -1031,7 +1056,7 @@ multipart_iterate (GMimeObject * part, gpointer user_data) } static GList * -local_message_get_header (memory_pool_t * pool, GMimeMessage * message, const gchar *field) +local_message_get_header (memory_pool_t * pool, GMimeMessage * message, const gchar *field, gboolean strong) { GList *gret = NULL; GMimeObject *part; @@ -1042,6 +1067,7 @@ local_message_get_header (memory_pool_t * pool, GMimeMessage * message, const gc }; cb.pool = pool; cb.field = field; + cb.strong = strong; #ifndef GMIME24 struct raw_header *h; @@ -1052,7 +1078,7 @@ local_message_get_header (memory_pool_t * pool, GMimeMessage * message, const gc msg_debug ("iterate over headers to find header %s", field); h = GMIME_OBJECT (message)->headers->headers; - header_iterate (pool, h, &gret, field); + header_iterate (pool, h, &gret, field, strong); if (gret == NULL) { /* Try to iterate with mime part headers */ @@ -1060,7 +1086,7 @@ local_message_get_header (memory_pool_t * pool, GMimeMessage * message, const gc part = g_mime_message_get_mime_part (message); if (part) { h = part->headers->headers; - header_iterate (pool, h, &gret, field); + header_iterate (pool, h, &gret, field, strong); if (gret == NULL && GMIME_IS_MULTIPART (part)) { msg_debug ("iterate over headers of each multipart's subparts %s", field); g_mime_multipart_foreach (GMIME_MULTIPART (part), multipart_iterate, &cb); @@ -1079,13 +1105,13 @@ local_message_get_header (memory_pool_t * pool, GMimeMessage * message, const gc GMimeHeaderList *ls; ls = g_mime_object_get_header_list (GMIME_OBJECT (message)); - header_iterate (pool, ls, &gret, field); + header_iterate (pool, ls, &gret, field, strong); if (gret == NULL) { /* Try to iterate with mime part headers */ part = g_mime_message_get_mime_part (message); if (part) { ls = g_mime_object_get_header_list (GMIME_OBJECT (part)); - header_iterate (pool, ls, &gret, field); + header_iterate (pool, ls, &gret, field, strong); if (gret == NULL && GMIME_IS_MULTIPART (part)) { g_mime_multipart_foreach (GMIME_MULTIPART (part), multipart_iterate, &cb); if (cb.ret != NULL) { @@ -1202,7 +1228,7 @@ local_message_get_recipients_##type (GMimeMessage *message, const gchar *unused) /* different declarations for different types of set and get functions */ typedef const gchar *(*GetFunc) (GMimeMessage * message); typedef InternetAddressList *(*GetRcptFunc) (GMimeMessage * message, const gchar *type); - typedef GList *(*GetListFunc) (memory_pool_t * pool, GMimeMessage * message, const gchar *type); + typedef GList *(*GetListFunc) (memory_pool_t * pool, GMimeMessage * message, const gchar *type, gboolean strong); typedef void (*SetFunc) (GMimeMessage * message, const gchar *value); typedef void (*SetListFunc) (GMimeMessage * message, const gchar *field, const gchar *value); @@ -1306,7 +1332,7 @@ message_set_header (GMimeMessage * message, const gchar *field, const gchar *val * You should free the GList list by yourself. **/ GList * -message_get_header (memory_pool_t * pool, GMimeMessage * message, const gchar *field) +message_get_header (memory_pool_t * pool, GMimeMessage * message, const gchar *field, gboolean strong) { gint i; gchar *ret = NULL, *ia_string; @@ -1347,7 +1373,7 @@ message_get_header (memory_pool_t * pool, GMimeMessage * message, const gchar *f #endif break; case FUNC_LIST: - gret = (*(fieldfunc[i].getlistfunc)) (pool, message, field); + gret = (*(fieldfunc[i].getlistfunc)) (pool, message, field, strong); break; } break; diff --git a/src/message.h b/src/message.h index d8be944e3..a57571987 100644 --- a/src/message.h +++ b/src/message.h @@ -54,6 +54,6 @@ struct received_header { gint process_message (struct worker_task *task); void message_set_header (GMimeMessage *message, const gchar *field, const gchar *value); -GList* message_get_header (memory_pool_t *pool, GMimeMessage *message, const gchar *field); +GList* message_get_header (memory_pool_t *pool, GMimeMessage *message, const gchar *field, gboolean strong); #endif diff --git a/src/plugins/regexp.c b/src/plugins/regexp.c index 4ae056bee..68c91f976 100644 --- a/src/plugins/regexp.c +++ b/src/plugins/regexp.c @@ -661,7 +661,7 @@ process_regexp (struct rspamd_regexp *re, struct worker_task *task, const gchar } debug_task ("checking header regexp: %s = %s", re->header, re->regexp_text); - headerlist = message_get_header (task->task_pool, task->message, re->header); + headerlist = message_get_header (task->task_pool, task->message, re->header, re->is_strong); if (headerlist == NULL) { if (G_UNLIKELY (re->is_test)) { msg_info ("process test regexp %s for header %s returned FALSE: no header found", re->regexp_text, re->header); diff --git a/src/spf.c b/src/spf.c index 63a3fed99..8e60604ac 100644 --- a/src/spf.c +++ b/src/spf.c @@ -1152,7 +1152,7 @@ resolve_spf (struct worker_task *task, spf_cb_t callback) } } else { - domains = message_get_header (task->task_pool, task->message, "From"); + domains = message_get_header (task->task_pool, task->message, "From", FALSE); if (domains != NULL) { rec->cur_domain = memory_pool_strdup (task->task_pool, domains->data); -- 2.39.5