]> source.dussan.org Git - rspamd.git/commitdiff
[Project] Further rework of mime headers processing
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 11 Jul 2019 12:04:28 +0000 (13:04 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 12 Jul 2019 14:18:17 +0000 (15:18 +0100)
contrib/uthash/utlist.h
src/libmime/email_addr.h
src/libmime/message.c
src/libmime/message.h
src/libmime/mime_headers.c
src/libmime/mime_headers.h
src/libmime/smtp_parsers.h
src/lua/lua_task.c

index c82dd916e2eddfbd8f4d57f2e554b07a7240b125..e4d9a4c23d7bc14163730250293a9f8423f20f39 100644 (file)
@@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <assert.h>
 
-/* 
+/*
  * This file contains macros to manipulate singly and doubly-linked lists.
  *
  * 1. LL_ macros:  singly-linked lists.
@@ -38,7 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  * To use singly-linked lists, your structure must have a "next" pointer.
  * To use doubly-linked lists, your structure must "prev" and "next" pointers.
  * Either way, the pointer to the head of the list must be initialized to NULL.
- * 
+ *
  * ----------------.EXAMPLE -------------------------
  * struct item {
  *      int id;
@@ -88,7 +88,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define _PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
 #define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
 #define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
-#else 
+#else
 #define _SV(elt,list)
 #define _NEXT(elt,list,next) ((elt)->next)
 #define _NEXTASGN(elt,list,to,next) ((elt)->next)=(to)
@@ -312,7 +312,7 @@ do {
 #define LL_PREPEND2(head,add,next)                                                             \
 do {                                                                                           \
   (add)->next = head;                                                                          \
-  head = add;                                                                                  \
+  (head) = (add);                                                                                  \
 } while (0)
 
 #define LL_CONCAT(head1,head2)                                                                 \
@@ -445,7 +445,7 @@ do {
     LL_FOREACH2(head,out,next) {                                                               \
       if ((out)->field == (val)) break;                                                        \
     }                                                                                          \
-} while(0) 
+} while(0)
 
 #define LL_SEARCH(head,out,elt,cmp)                                                            \
     LL_SEARCH2(head,out,elt,cmp,next)
@@ -455,7 +455,7 @@ do {
     LL_FOREACH2(head,out,next) {                                                               \
       if ((cmp(out,elt))==0) break;                                                            \
     }                                                                                          \
-} while(0) 
+} while(0)
 
 #define LL_REPLACE_ELEM(head, el, add)                                                         \
 do {                                                                                           \
@@ -531,7 +531,7 @@ do {
       (head)->prev = (head);                                                                   \
       (head)->next = NULL;                                                                     \
   }                                                                                            \
-} while (0) 
+} while (0)
 
 #define DL_CONCAT(head1,head2)                                                                 \
     DL_CONCAT2(head1,head2,prev,next)
@@ -549,7 +549,7 @@ do {
         (head1)=(head2);                                                                       \
     }                                                                                          \
   }                                                                                            \
-} while (0) 
+} while (0)
 
 #define DL_DELETE(head,del)                                                                    \
     DL_DELETE2(head,del,prev,next)
@@ -570,7 +570,7 @@ do {
           (head)->prev = (del)->prev;                                                          \
       }                                                                                        \
   }                                                                                            \
-} while (0) 
+} while (0)
 
 #define DL_COUNT(head,el,counter)                                                              \
     DL_COUNT2(head,el,counter,next)                                                            \
@@ -674,7 +674,7 @@ do {
      (del)->prev->next = (del)->next;                                                          \
      if ((del) == (head)) (head)=(del)->next;                                                  \
   }                                                                                            \
-} while (0) 
+} while (0)
 
 #define CDL_COUNT(head,el,counter)                                                             \
     CDL_COUNT2(head,el,counter,next)                                                           \
@@ -689,7 +689,7 @@ do {
     CDL_FOREACH2(head,el,next)
 
 #define CDL_FOREACH2(head,el,next)                                                             \
-    for(el=head;el;el=((el)->next==head ? 0L : (el)->next)) 
+    for(el=head;el;el=((el)->next==head ? 0L : (el)->next))
 
 #define CDL_FOREACH_SAFE(head,el,tmp1,tmp2)                                                    \
     CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)
@@ -707,7 +707,7 @@ do {
     CDL_FOREACH2(head,out,next) {                                                              \
       if ((out)->field == (val)) break;                                                        \
     }                                                                                          \
-} while(0) 
+} while(0)
 
 #define CDL_SEARCH(head,out,elt,cmp)                                                           \
     CDL_SEARCH2(head,out,elt,cmp,next)
@@ -717,7 +717,7 @@ do {
     CDL_FOREACH2(head,out,next) {                                                              \
       if ((cmp(out,elt))==0) break;                                                            \
     }                                                                                          \
-} while(0) 
+} while(0)
 
 #define CDL_REPLACE_ELEM(head, el, add)                                                        \
 do {                                                                                           \
index 69aa2aa00f6418aba2503701f78b2728e9327960..13e94f7ccb5556a582cc346243320a0caf2dfc10 100644 (file)
@@ -58,7 +58,7 @@ struct rspamd_email_address {
        guint flags;
 };
 
-struct received_header;
+struct rspamd_received_header;
 struct rspamd_task;
 
 /**
index 1d9da26f21a55bd6fe4772bdd8fe144daafb4985..500590e0204fafa226ef22c065275bee69545bc1 100644 (file)
@@ -1110,7 +1110,7 @@ rspamd_message_new (struct rspamd_task *task)
 gboolean
 rspamd_message_parse (struct rspamd_task *task)
 {
-       struct received_header *recv, *trecv;
+       struct rspamd_received_header *recv, *trecv;
        const gchar *p;
        gsize len;
        guint i;
@@ -1247,7 +1247,7 @@ rspamd_message_parse (struct rspamd_task *task)
                                        " not ours, prepend it with fake one");
 
                        trecv = rspamd_mempool_alloc0 (task->task_pool,
-                                       sizeof (struct received_header));
+                                       sizeof (struct rspamd_received_header));
                        trecv->flags |= RSPAMD_RECEIVED_FLAG_ARTIFICIAL;
 
                        if (task->flags & RSPAMD_TASK_FLAG_SSL) {
@@ -1515,101 +1515,6 @@ rspamd_message_process (struct rspamd_task *task)
 }
 
 
-GPtrArray *
-rspamd_message_get_header_from_hash (GHashTable *htb,
-               rspamd_mempool_t *pool,
-               const gchar *field,
-               gboolean strong)
-{
-       GPtrArray *ret, *ar;
-       struct rspamd_mime_header *cur;
-       guint i;
-
-       ar = g_hash_table_lookup (htb, field);
-
-       if (ar == NULL) {
-               return NULL;
-       }
-
-       if (strong && pool != NULL) {
-               /* Need to filter what we have */
-               ret = g_ptr_array_sized_new (ar->len);
-
-               PTR_ARRAY_FOREACH (ar, i, cur) {
-                       if (strcmp (cur->name, field) != 0) {
-                               continue;
-                       }
-
-                       g_ptr_array_add (ret, cur);
-               }
-
-               rspamd_mempool_add_destructor (pool,
-                               (rspamd_mempool_destruct_t)rspamd_ptr_array_free_hard, ret);
-       }
-       else {
-               ret = ar;
-       }
-
-       return ret;
-}
-
-GPtrArray *
-rspamd_message_get_header_array (struct rspamd_task *task,
-               const gchar *field,
-               gboolean strong)
-{
-       return rspamd_message_get_header_from_hash (task->raw_headers,
-                       task->task_pool, field, strong);
-}
-
-GPtrArray *
-rspamd_message_get_mime_header_array (struct rspamd_task *task,
-               const gchar *field,
-               gboolean strong)
-{
-       GPtrArray *ret, *ar;
-       struct rspamd_mime_header *cur;
-       guint nelems = 0, i, j;
-       struct rspamd_mime_part *mp;
-
-       for (i = 0; i < task->parts->len; i ++) {
-               mp = g_ptr_array_index (task->parts, i);
-               ar = g_hash_table_lookup (mp->raw_headers, field);
-
-               if (ar == NULL) {
-                       continue;
-               }
-
-               nelems += ar->len;
-       }
-
-       if (nelems == 0) {
-               return NULL;
-       }
-
-       ret = g_ptr_array_sized_new (nelems);
-
-       for (i = 0; i < task->parts->len; i ++) {
-               mp = g_ptr_array_index (task->parts, i);
-               ar = g_hash_table_lookup (mp->raw_headers, field);
-
-               PTR_ARRAY_FOREACH (ar, j, cur) {
-                       if (strong) {
-                               if (strcmp (cur->name, field) != 0) {
-                                       continue;
-                               }
-                       }
-
-                       g_ptr_array_add (ret, cur);
-               }
-       }
-
-       rspamd_mempool_add_destructor (task->task_pool,
-               (rspamd_mempool_destruct_t)rspamd_ptr_array_free_hard, ret);
-
-       return ret;
-}
-
 struct rspamd_message *
 rspamd_message_ref (struct rspamd_message *msg)
 {
@@ -1618,5 +1523,5 @@ rspamd_message_ref (struct rspamd_message *msg)
 
 void rspamd_message_unref (struct rspamd_message *msg)
 {
-       REF_RELEASE (msg);s
+       REF_RELEASE (msg);
 }
index 7d58fa88f95805f1ab6fccf0a593b23e9042fcca..880645c0a79bb682c8e9f2e55a9d81b316fc8b7f 100644 (file)
@@ -7,11 +7,12 @@
 #define RSPAMD_MESSAGE_H
 
 #include "config.h"
-#include "email_addr.h"
-#include "addr.h"
-#include "cryptobox.h"
-#include "mime_headers.h"
-#include "content_type.h"
+
+#include "libmime/email_addr.h"
+#include "libutil/addr.h"
+#include "libcryptobox/cryptobox.h"
+#include "libmime/mime_headers.h"
+#include "libmime/content_type.h"
 #include "libutil/ref.h"
 #include "libutil/str_util.h"
 
@@ -60,8 +61,8 @@ struct rspamd_mime_part {
        rspamd_ftok_t parsed_data;
        struct rspamd_mime_part *parent_part;
 
-       GQueue *headers_order;
-       GHashTable *raw_headers;
+       struct rspamd_mime_header *headers_order;
+       khash_t(rspamd_mime_headers_htb) *raw_headers;
 
        gchar *raw_headers_str;
        gsize raw_headers_len;
@@ -141,24 +142,25 @@ struct rspamd_message {
                const gchar *begin;
                gsize len;
                const gchar *body_start;
-       } raw_headers_content;                  /**< list of raw headers                                                        */
-       GPtrArray *received;                    /**< list of received headers                                           */
-       GHashTable *urls;                               /**< list of parsed urls                                                        */
-       GHashTable *emails;                             /**< list of parsed emails                                                      */
-       GHashTable *raw_headers;                /**< list of raw headers                                                        */
-       GQueue *headers_order;                  /**< order of raw headers                                                       */
+       } raw_headers_content;                                          /**< list of raw headers                                                        */
+       struct rspamd_received_header *received;        /**< list of received headers                                           */
+       GHashTable *urls;                                                       /**< list of parsed urls                                                        */
+       GHashTable *emails;                                                     /**< list of parsed emails                                                      */
+       khash_t(rspamd_mime_headers_htb) *raw_headers;  /**< list of raw headers                                                        */
+       struct rspamd_mime_header *headers_order;       /**< inversed order of raw headers                                                      */
        GPtrArray *rcpt_mime;
        GPtrArray *from_mime;
-       enum rspamd_newlines_type nlines_type; /**< type of newlines (detected on most of headers       */
+       enum rspamd_newlines_type nlines_type;          /**< type of newlines (detected on most of headers      */
        ref_entry_t ref;
 };
 
 #ifndef FULL_DEBUG
-#define MESSAGE_FIELD(task, field) ((task)->message->(field))
+#define MESSAGE_FIELD(task, field) ((task)->message->field)
 #else
-#define MESSAGE_FIELD(task, field) do { \
-       if (!task->message) {msg_err_task("no message when getting field %s", #field); g_assert(0);} \
-       } while(0), ((task)->message->(field))
+#define MESSAGE_FIELD(task, field)
+       ((!(task)->message) ? \
+       (msg_err_task("no message when getting field %s", #field), g_assert(0)) : \
+       ((task)->message->field))
 #endif
 
 /**
@@ -174,40 +176,6 @@ gboolean rspamd_message_parse (struct rspamd_task *task);
  */
 void rspamd_message_process (struct rspamd_task *task);
 
-/**
- * Get an array of header's values with specified header's name using raw headers
- * @param task worker task structure
- * @param field header's name
- * @param strong if this flag is TRUE header's name is case sensitive, otherwise it is not
- * @return An array of header's values or NULL. It is NOT permitted to free array or values.
- */
-GPtrArray *rspamd_message_get_header_array (struct rspamd_task *task,
-                                                                                       const gchar *field,
-                                                                                       gboolean strong);
-
-/**
- * Get an array of mime parts header's values with specified header's name using raw headers
- * @param task worker task structure
- * @param field header's name
- * @param strong if this flag is TRUE header's name is case sensitive, otherwise it is not
- * @return An array of header's values or NULL. It is NOT permitted to free array or values.
- */
-GPtrArray *rspamd_message_get_mime_header_array (struct rspamd_task *task,
-                                                                                                const gchar *field,
-                                                                                                gboolean strong);
-
-/**
- * Get an array of header's values with specified header's name using raw headers
- * @param htb hash table indexed by header name (caseless) with ptr arrays as elements
- * @param field header's name
- * @param strong if this flag is TRUE header's name is case sensitive, otherwise it is not
- * @return An array of header's values or NULL. It is NOT permitted to free array or values.
- */
-GPtrArray *rspamd_message_get_header_from_hash (GHashTable *htb,
-                                                                                               rspamd_mempool_t *pool,
-                                                                                               const gchar *field,
-                                                                                               gboolean strong);
-
 
 /**
  * Converts string to cte
index 952a163b974508162d26c5c5ce14b7ab2222e3d2..7ffa5453c7c9f5231c8a14983c28a106d2f73e52 100644 (file)
 #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
index 60fd7b6973a3d9607017e5328d3b582835360403..7c17b8dddade3591e519a7a998571726622374dd 100644 (file)
@@ -19,6 +19,7 @@
 #include "config.h"
 #include "libutil/mem_pool.h"
 #include "libutil/addr.h"
+#include "khash.h"
 
 #ifdef  __cplusplus
 extern "C" {
@@ -50,7 +51,7 @@ enum rspamd_mime_header_flags {
 };
 
 struct rspamd_mime_header {
-       gchar *name;
+       gchar *name; /* Also used for key */
        gchar *value;
        const gchar *raw_value; /* As it is in the message (unfolded and unparsed) */
        gsize raw_len;
@@ -59,9 +60,12 @@ struct rspamd_mime_header {
        gchar *separator;
        gchar *decoded;
        struct rspamd_mime_header *prev, *next; /* Headers with the same name */
-       struct rspamd_mime_header *ord_prev, *ord_next; /* Overall order of headers */
+       struct rspamd_mime_header *ord_next; /* Overall order of headers, slist */
 };
 
+/* Define hash type */
+__KHASH_TYPE (rspamd_mime_headers_htb, gchar *, struct rspamd_mime_header *)
+
 enum rspamd_received_type {
        RSPAMD_RECEIVED_SMTP = 0,
        RSPAMD_RECEIVED_ESMTP = 1u << 0u,
@@ -79,7 +83,7 @@ enum rspamd_received_type {
        RSPAMD_RECEIVED_FLAG_AUTHENTICATED =  (1u << 12u),
 };
 
-struct received_header {
+struct rspamd_received_header {
        const gchar *from_hostname;
        const gchar *from_ip;
        const gchar *real_hostname;
@@ -90,7 +94,7 @@ struct received_header {
        struct rspamd_mime_header *hdr;
        time_t timestamp;
        gint flags; /* See enum rspamd_received_type */
-       struct received_header *prev, *next;
+       struct rspamd_received_header *prev, *next;
 };
 
 /**
@@ -102,7 +106,7 @@ struct received_header {
  * @param check_newlines
  */
 void rspamd_mime_headers_process (struct rspamd_task *task,
-                                                                 GHashTable *target,
+                                                                 khash_t(rspamd_mime_headers_htb) *target,
                                                                  struct rspamd_mime_header **order_ptr,
                                                                  const gchar *in, gsize len,
                                                                  gboolean check_newlines);
@@ -132,6 +136,26 @@ gchar *rspamd_mime_header_encode (const gchar *in, gsize len);
  */
 gchar *rspamd_mime_message_id_generate (const gchar *fqdn);
 
+/**
+ * Get an array of header's values with specified header's name using raw headers
+ * @param task worker task structure
+ * @param field header's name
+ * @return An array of header's values or NULL. It is NOT permitted to free array or values.
+ */
+struct rspamd_mime_header *
+rspamd_message_get_header_array (struct rspamd_task *task,
+                                                                const gchar *field);
+
+/**
+ * Get an array of header's values with specified header's name using raw headers
+ * @param htb hash table indexed by header name (caseless) with ptr arrays as elements
+ * @param field header's name
+ * @return An array of header's values or NULL. It is NOT permitted to free array or values.
+ */
+struct rspamd_mime_header *
+rspamd_message_get_header_from_hash (khash_t(rspamd_mime_headers_htb) *htb,
+                                                                        const gchar *field);
+
 #ifdef  __cplusplus
 }
 #endif
index b4fb825b4932422bd350a1b02af0a0e2fdc0f896..3a52f1dd6950729dc7e452ecc730d2d7c85f1626 100644 (file)
@@ -29,7 +29,7 @@ extern "C" {
 
 int rspamd_smtp_received_parse (struct rspamd_task *task,
                                                                const char *data, size_t len,
-                                                               struct received_header *rh);
+                                                               struct rspamd_received_header *rh);
 
 int rspamd_smtp_addr_parse (const char *data, size_t len,
                                                        struct rspamd_email_address *addr);
index 99faa4b3e4952af38d8984dd313a50ccee490258..3f69adfccf61bbf49405dfb5c31b06fc10dfbb9d 100644 (file)
@@ -2514,7 +2514,7 @@ lua_task_get_received_headers (lua_State * L)
 {
        LUA_TRACE_POINT;
        struct rspamd_task *task = lua_check_task (L, 1);
-       struct received_header *rh;
+       struct rspamd_received_header *rh;
        const gchar *proto;
        guint i, k = 1;