diff options
Diffstat (limited to 'src/libmime/mime_headers.c')
-rw-r--r-- | src/libmime/mime_headers.c | 136 |
1 files changed, 86 insertions, 50 deletions
diff --git a/src/libmime/mime_headers.c b/src/libmime/mime_headers.c index 952a163b9..7ffa5453c 100644 --- a/src/libmime/mime_headers.c +++ b/src/libmime/mime_headers.c @@ -20,14 +20,18 @@ #include "contrib/uthash/utlist.h" #include "libserver/mempool_vars_internal.h" #include "libserver/url.h" +#include "libutil/util.h" #include <unicode/utf8.h> +__KHASH_IMPL (rspamd_mime_headers_htb, static inline, gchar *, + struct rspamd_mime_header *, 1, rspamd_strcase_hash, rspamd_strcase_equal); + static void rspamd_mime_header_check_special (struct rspamd_task *task, struct rspamd_mime_header *rh) { guint64 h; - struct received_header *recv; + struct rspamd_received_header *recv; const gchar *p, *end; gchar *id; @@ -36,35 +40,39 @@ rspamd_mime_header_check_special (struct rspamd_task *task, switch (h) { case 0x88705DC4D9D61ABULL: /* received */ recv = rspamd_mempool_alloc0 (task->task_pool, - sizeof (struct received_header)); + sizeof (struct rspamd_received_header)); recv->hdr = rh; if (rspamd_smtp_received_parse (task, rh->decoded, strlen (rh->decoded), recv) != -1) { - g_ptr_array_add (task->received, recv); + DL_APPEND (MESSAGE_FIELD (task, received), recv); } - rh->flags = RSPAMD_HEADER_RECEIVED; + rh->flags |= RSPAMD_HEADER_RECEIVED; break; case 0x76F31A09F4352521ULL: /* to */ - task->rcpt_mime = rspamd_email_address_from_mime (task->task_pool, - rh->decoded, strlen (rh->decoded), task->rcpt_mime); - rh->flags = RSPAMD_HEADER_TO|RSPAMD_HEADER_RCPT|RSPAMD_HEADER_UNIQUE; + MESSAGE_FIELD (task, rcpt_mime) = rspamd_email_address_from_mime (task->task_pool, + rh->decoded, strlen (rh->decoded), + MESSAGE_FIELD (task, rcpt_mime)); + rh->flags |= RSPAMD_HEADER_TO|RSPAMD_HEADER_RCPT|RSPAMD_HEADER_UNIQUE; break; case 0x7EB117C1480B76ULL: /* cc */ - task->rcpt_mime = rspamd_email_address_from_mime (task->task_pool, - rh->decoded, strlen (rh->decoded), task->rcpt_mime); - rh->flags = RSPAMD_HEADER_CC|RSPAMD_HEADER_RCPT|RSPAMD_HEADER_UNIQUE; + MESSAGE_FIELD (task, rcpt_mime) = rspamd_email_address_from_mime (task->task_pool, + rh->decoded, strlen (rh->decoded), + MESSAGE_FIELD (task, rcpt_mime)); + rh->flags |= RSPAMD_HEADER_CC|RSPAMD_HEADER_RCPT|RSPAMD_HEADER_UNIQUE; break; case 0xE4923E11C4989C8DULL: /* bcc */ - task->rcpt_mime = rspamd_email_address_from_mime (task->task_pool, - rh->decoded, strlen (rh->decoded), task->rcpt_mime); - rh->flags = RSPAMD_HEADER_BCC|RSPAMD_HEADER_RCPT|RSPAMD_HEADER_UNIQUE; + MESSAGE_FIELD (task, rcpt_mime) = rspamd_email_address_from_mime (task->task_pool, + rh->decoded, strlen (rh->decoded), + MESSAGE_FIELD (task, rcpt_mime)); + rh->flags |= RSPAMD_HEADER_BCC|RSPAMD_HEADER_RCPT|RSPAMD_HEADER_UNIQUE; break; case 0x41E1985EDC1CBDE4ULL: /* from */ - task->from_mime = rspamd_email_address_from_mime (task->task_pool, - rh->decoded, strlen (rh->decoded), task->from_mime); - rh->flags = RSPAMD_HEADER_FROM|RSPAMD_HEADER_SENDER|RSPAMD_HEADER_UNIQUE; + MESSAGE_FIELD (task, from_mime) = rspamd_email_address_from_mime (task->task_pool, + rh->decoded, strlen (rh->decoded), + MESSAGE_FIELD (task, from_mime)); + rh->flags |= RSPAMD_HEADER_FROM|RSPAMD_HEADER_SENDER|RSPAMD_HEADER_UNIQUE; break; case 0x43A558FC7C240226ULL: /* message-id */ { @@ -98,14 +106,14 @@ rspamd_mime_header_check_special (struct rspamd_task *task, *d = '\0'; - task->message_id = id; + MESSAGE_FIELD (task, message_id) = id; } break; } case 0xB91D3910358E8212ULL: /* subject */ - if (task->subject == NULL) { - task->subject = rh->decoded; + if (MESSAGE_FIELD (task, subject) == NULL) { + MESSAGE_FIELD (task, subject) = rh->decoded; } rh->flags = RSPAMD_HEADER_SUBJECT|RSPAMD_HEADER_UNIQUE; break; @@ -135,24 +143,28 @@ rspamd_mime_header_check_special (struct rspamd_task *task, static void rspamd_mime_header_add (struct rspamd_task *task, - GHashTable *target, GQueue *order, - struct rspamd_mime_header *rh, - gboolean check_special) + khash_t(rspamd_mime_headers_htb) *target, + struct rspamd_mime_header **order_ptr, + struct rspamd_mime_header *rh, + gboolean check_special) { - GPtrArray *ar; + khiter_t k; + struct rspamd_mime_header *ex; + int res; + + k = kh_put (rspamd_mime_headers_htb, target, rh->name, &res); - if ((ar = g_hash_table_lookup (target, rh->name)) != NULL) { - g_ptr_array_add (ar, rh); + if (res == 0) { + ex = kh_value (target, k); + DL_APPEND (ex, rh); msg_debug_task ("append raw header %s: %s", rh->name, rh->value); } else { - ar = g_ptr_array_sized_new (2); - g_ptr_array_add (ar, rh); - g_hash_table_insert (target, rh->name, ar); + kh_value (target, k) = rh; msg_debug_task ("add new raw header %s: %s", rh->name, rh->value); } - g_queue_push_tail (order, rh); + LL_PREPEND2 (*order_ptr, rh, ord_next); if (check_special) { rspamd_mime_header_check_special (task, rh); @@ -162,8 +174,9 @@ rspamd_mime_header_add (struct rspamd_task *task, /* Convert raw headers to a list of struct raw_header * */ void -rspamd_mime_headers_process (struct rspamd_task *task, GHashTable *target, - GQueue *order, +rspamd_mime_headers_process (struct rspamd_task *task, + khash_t(rspamd_mime_headers_htb) *target, + struct rspamd_mime_header **order_ptr, const gchar *in, gsize len, gboolean check_newlines) { @@ -205,7 +218,7 @@ rspamd_mime_headers_process (struct rspamd_task *task, GHashTable *target, tmp = rspamd_mempool_alloc (task->task_pool, l + 1); rspamd_null_safe_copy (c, l, tmp, l + 1); nh->name = tmp; - nh->empty_separator = TRUE; + nh->flags |= RSPAMD_HEADER_EMPTY_SEPARATOR; nh->raw_value = c; nh->raw_len = p - c; /* Including trailing ':' */ p++; @@ -225,12 +238,12 @@ rspamd_mime_headers_process (struct rspamd_task *task, GHashTable *target, case 2: /* We got header's name, so skip any \t or spaces */ if (*p == '\t') { - nh->tab_separated = TRUE; - nh->empty_separator = FALSE; + nh->flags &= ~RSPAMD_HEADER_EMPTY_SEPARATOR; + nh->flags |= RSPAMD_HEADER_TAB_SEPARATED; p++; } else if (*p == ' ') { - nh->empty_separator = FALSE; + nh->flags &= ~RSPAMD_HEADER_EMPTY_SEPARATOR; p++; } else if (*p == '\n' || *p == '\r') { @@ -464,7 +477,7 @@ rspamd_mime_headers_process (struct rspamd_task *task, GHashTable *target, } } - task->nlines_type = sel; + MESSAGE_FIELD (task, nlines_type) = sel; cur = order->head; rspamd_cryptobox_hash_init (&hs, NULL, 0); @@ -1287,7 +1300,7 @@ rspamd_smtp_received_process_rdns (struct rspamd_task *task, static gboolean rspamd_smtp_received_process_host_tcpinfo (struct rspamd_task *task, - struct received_header *rh, + struct rspamd_received_header *rh, const gchar *data, gsize len) { @@ -1373,7 +1386,7 @@ rspamd_smtp_received_process_host_tcpinfo (struct rspamd_task *task, static void rspamd_smtp_received_process_from (struct rspamd_task *task, struct rspamd_received_part *rpart, - struct received_header *rh) + struct rspamd_received_header *rh) { if (rpart->dlen > 0) { /* We have seen multiple cases: @@ -1457,7 +1470,7 @@ int rspamd_smtp_received_parse (struct rspamd_task *task, const char *data, size_t len, - struct received_header *rh) + struct rspamd_received_header *rh) { goffset date_pos = -1; struct rspamd_received_part *head, *cur; @@ -1469,7 +1482,7 @@ rspamd_smtp_received_parse (struct rspamd_task *task, return -1; } - rh->type = RSPAMD_RECEIVED_UNKNOWN; + rh->flags = RSPAMD_RECEIVED_UNKNOWN; DL_FOREACH (head, cur) { switch (cur->type) { @@ -1490,7 +1503,7 @@ rspamd_smtp_received_parse (struct rspamd_task *task, RSPAMD_FTOK_ASSIGN (&t2, "smtp"); if (rspamd_ftok_cmp (&t1, &t2) == 0) { - rh->type = RSPAMD_RECEIVED_SMTP; + rh->flags = RSPAMD_RECEIVED_SMTP; } RSPAMD_FTOK_ASSIGN (&t2, "esmtp"); @@ -1501,11 +1514,11 @@ rspamd_smtp_received_parse (struct rspamd_task *task, */ if (t1.len == t2.len + 1) { if (t1.begin[t2.len] == 'a') { - rh->type = RSPAMD_RECEIVED_ESMTPA; + rh->flags = RSPAMD_RECEIVED_ESMTPA; rh->flags |= RSPAMD_RECEIVED_FLAG_AUTHENTICATED; } else if (t1.begin[t2.len] == 's') { - rh->type = RSPAMD_RECEIVED_ESMTPS; + rh->flags = RSPAMD_RECEIVED_ESMTPS; rh->flags |= RSPAMD_RECEIVED_FLAG_SSL; } continue; @@ -1513,14 +1526,14 @@ rspamd_smtp_received_parse (struct rspamd_task *task, else if (t1.len == t2.len + 2) { if (t1.begin[t2.len] == 's' && t1.begin[t2.len + 1] == 'a') { - rh->type = RSPAMD_RECEIVED_ESMTPSA; + rh->flags = RSPAMD_RECEIVED_ESMTPSA; rh->flags |= RSPAMD_RECEIVED_FLAG_AUTHENTICATED; rh->flags |= RSPAMD_RECEIVED_FLAG_SSL; } continue; } else if (t1.len == t2.len) { - rh->type = RSPAMD_RECEIVED_ESMTP; + rh->flags = RSPAMD_RECEIVED_ESMTP; continue; } } @@ -1528,21 +1541,21 @@ rspamd_smtp_received_parse (struct rspamd_task *task, RSPAMD_FTOK_ASSIGN (&t2, "lmtp"); if (rspamd_ftok_cmp (&t1, &t2) == 0) { - rh->type = RSPAMD_RECEIVED_LMTP; + rh->flags = RSPAMD_RECEIVED_LMTP; continue; } RSPAMD_FTOK_ASSIGN (&t2, "imap"); if (rspamd_ftok_cmp (&t1, &t2) == 0) { - rh->type = RSPAMD_RECEIVED_IMAP; + rh->flags = RSPAMD_RECEIVED_IMAP; continue; } RSPAMD_FTOK_ASSIGN (&t2, "local"); if (rspamd_ftok_cmp (&t1, &t2) == 0) { - rh->type = RSPAMD_RECEIVED_LOCAL; + rh->flags = RSPAMD_RECEIVED_LOCAL; continue; } @@ -1551,12 +1564,12 @@ rspamd_smtp_received_parse (struct rspamd_task *task, if (rspamd_ftok_starts_with (&t1, &t2)) { if (t1.len == t2.len + 1) { if (t1.begin[t2.len] == 's') { - rh->type = RSPAMD_RECEIVED_HTTP; + rh->flags = RSPAMD_RECEIVED_HTTP; rh->flags |= RSPAMD_RECEIVED_FLAG_SSL; } } else if (t1.len == t2.len) { - rh->type = RSPAMD_RECEIVED_HTTP; + rh->flags = RSPAMD_RECEIVED_HTTP; } continue; @@ -1584,4 +1597,27 @@ rspamd_smtp_received_parse (struct rspamd_task *task, } return 0; +} + +struct rspamd_mime_header * +rspamd_message_get_header_from_hash (khash_t(rspamd_mime_headers_htb) *htb, + const gchar *field) +{ + khiter_t k; + + k = kh_get (rspamd_mime_headers_htb, htb, (gchar *)field); + + if (k == kh_end (htb)) { + return NULL; + } + + return kh_value (htb, k); +} + +struct rspamd_mime_header * +rspamd_message_get_header_array (struct rspamd_task *task, + const gchar *field) +{ + return rspamd_message_get_header_from_hash (MESSAGE_FIELD (task, raw_headers), + field); }
\ No newline at end of file |