diff options
author | Vsevolod Stakhov <vsevolod@rambler-co.ru> | 2009-03-30 19:35:57 +0400 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@rambler-co.ru> | 2009-03-30 19:35:57 +0400 |
commit | f579fed1dee306a5cf58360589d29ae1514d25b4 (patch) | |
tree | f5d5e288553d30fc617d06bf9e48ae919092f876 /src/expressions.c | |
parent | dd2fbb7a5b7e1c0d844900147486ad7ffd98c1e4 (diff) | |
download | rspamd-f579fed1dee306a5cf58360589d29ae1514d25b4.tar.gz rspamd-f579fed1dee306a5cf58360589d29ae1514d25b4.zip |
* Add 3 functions:
- is_recipients_sorted
- has_only_html_part
- compare_recipients_distance
* Update documentation
* Fix build
Diffstat (limited to 'src/expressions.c')
-rw-r--r-- | src/expressions.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/src/expressions.c b/src/expressions.c index 957c43c5c..3fff36fbd 100644 --- a/src/expressions.c +++ b/src/expressions.c @@ -37,6 +37,9 @@ gboolean rspamd_content_type_has_param (struct worker_task *task, GList *args); gboolean rspamd_content_type_is_subtype (struct worker_task *task, GList *args); gboolean rspamd_content_type_is_type (struct worker_task *task, GList *args); gboolean rspamd_parts_distance (struct worker_task *task, GList *args); +gboolean rspamd_recipients_distance (struct worker_task *task, GList *args); +gboolean rspamd_has_only_html_part (struct worker_task *task, GList *args); +gboolean rspamd_is_recipients_sorted (struct worker_task *task, GList *args); /* * List of internal functions of rspamd @@ -48,11 +51,14 @@ static struct _fl { } rspamd_functions_list[] = { { "compare_encoding", rspamd_compare_encoding }, { "compare_parts_distance", rspamd_parts_distance }, + { "compare_recipients_distance", rspamd_recipients_distance }, { "content_type_compare_param", rspamd_content_type_compare_param }, { "content_type_has_param", rspamd_content_type_has_param }, { "content_type_is_subtype", rspamd_content_type_is_subtype }, { "content_type_is_type", rspamd_content_type_is_type }, + { "has_only_html_part", rspamd_has_only_html_part }, { "header_exists", rspamd_header_exists }, + { "is_recipients_sorted", rspamd_is_recipients_sorted }, }; static struct _fl *list_ptr = &rspamd_functions_list[0]; @@ -916,6 +922,144 @@ rspamd_content_type_is_type (struct worker_task *task, GList *args) return FALSE; } +struct addr_list { + const char *name; + const char *addr; +}; + +#define COMPARE_RCPT_LEN 3 +#define MIN_RCPT_TO_COMPARE 5 + +gboolean +rspamd_recipients_distance (struct worker_task *task, GList *args) +{ + struct expression_argument *arg; + InternetAddressList *cur; + InternetAddress *addr; + double threshold; + struct addr_list *ar; + int num, i, j, hits = 0, total = 0; + + if (args == NULL) { + msg_warn ("rspamd_content_type_compare_param: no parameters to function"); + return FALSE; + } + + arg = args->data; + threshold = strtod ((char *)arg->data, NULL); + + num = internet_address_list_length (task->rcpts); + if (num < MIN_RCPT_TO_COMPARE) { + return FALSE; + } + ar = memory_pool_alloc (task->task_pool, num * sizeof (struct addr_list)); + + /* Fill array */ + cur = task->rcpts; + i = 0; + while (cur) { + addr = internet_address_list_get_address (cur); + ar[i].name = internet_address_get_name (addr); + ar[i].addr = internet_address_get_addr (addr); + cur = internet_address_list_next (cur); + } + + /* Cycle all elements in array */ + for (i = 0; i < num; i ++) { + for (j = i + 1; j < num; j ++) { + if (g_ascii_strncasecmp (ar[i].name, ar[j].name, COMPARE_RCPT_LEN) == 0) { + hits ++; + } + if (g_ascii_strcasecmp (ar[i].addr, ar[j].addr) == 0) { + hits ++; + } + total ++; + } + } + + if ((double)total / (double)hits >= threshold) { + return TRUE; + } + + return FALSE; +} + +gboolean +rspamd_has_only_html_part (struct worker_task *task, GList *args) +{ + struct mime_text_part *p; + GList *cur; + gboolean res = FALSE; + + cur = g_list_first (task->text_parts); + while (cur) { + p = cur->data; + if (p->is_html) { + res = TRUE; + } + else { + res = FALSE; + break; + } + cur = g_list_next (cur); + } + + return res; +} + +static gboolean +is_recipient_list_sorted (const InternetAddressList *ia) +{ + const InternetAddressList *cur; + InternetAddress *addr; + gboolean res = TRUE; + struct addr_list current = {NULL, NULL}, previous = {NULL, NULL}; + + /* Do not check to short address lists */ + if (internet_address_list_length (ia) < MIN_RCPT_TO_COMPARE) { + return FALSE; + } + + cur = ia; + while (cur) { + addr = internet_address_list_get_address (cur); + current.name = internet_address_get_name (addr); + current.addr = internet_address_get_addr (addr); + if (previous.name != NULL) { + if (g_ascii_strcasecmp (current.name, previous.name) < 0) { + res = FALSE; + break; + } + if (g_ascii_strcasecmp (current.addr, previous.addr) < 0) { + res = FALSE; + break; + } + } + previous.name = current.name; + previous.addr = current.addr; + cur = internet_address_list_next (cur); + } + + return res; +} + +gboolean +rspamd_is_recipients_sorted (struct worker_task *task, GList *args) +{ + /* Check all types of addresses */ + if (is_recipient_list_sorted (g_mime_message_get_recipients (task->message, GMIME_RECIPIENT_TYPE_TO)) == TRUE) { + return TRUE; + } + if (is_recipient_list_sorted (g_mime_message_get_recipients (task->message, GMIME_RECIPIENT_TYPE_BCC)) == TRUE) { + return TRUE; + } + if (is_recipient_list_sorted (g_mime_message_get_recipients (task->message, GMIME_RECIPIENT_TYPE_CC)) == TRUE) { + return TRUE; + } + + return FALSE; +} + /* * vi:ts=4 */ |