#include <assert.h>
-/*
+/*
* This file contains macros to manipulate singly and doubly-linked lists.
*
* 1. LL_ macros: singly-linked lists.
* 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;
#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)
#define LL_PREPEND2(head,add,next) \
do { \
(add)->next = head; \
- head = add; \
+ (head) = (add); \
} while (0)
#define LL_CONCAT(head1,head2) \
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)
LL_FOREACH2(head,out,next) { \
if ((cmp(out,elt))==0) break; \
} \
-} while(0)
+} while(0)
#define LL_REPLACE_ELEM(head, el, add) \
do { \
(head)->prev = (head); \
(head)->next = NULL; \
} \
-} while (0)
+} while (0)
#define DL_CONCAT(head1,head2) \
DL_CONCAT2(head1,head2,prev,next)
(head1)=(head2); \
} \
} \
-} while (0)
+} while (0)
#define DL_DELETE(head,del) \
DL_DELETE2(head,del,prev,next)
(head)->prev = (del)->prev; \
} \
} \
-} while (0)
+} while (0)
#define DL_COUNT(head,el,counter) \
DL_COUNT2(head,el,counter,next) \
(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) \
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)
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)
CDL_FOREACH2(head,out,next) { \
if ((cmp(out,elt))==0) break; \
} \
-} while(0)
+} while(0)
#define CDL_REPLACE_ELEM(head, el, add) \
do { \
guint flags;
};
-struct received_header;
+struct rspamd_received_header;
struct rspamd_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;
" 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) {
}
-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)
{
void rspamd_message_unref (struct rspamd_message *msg)
{
- REF_RELEASE (msg);s
+ REF_RELEASE (msg);
}
#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"
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;
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
/**
*/
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
#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;
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 */ {
*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;
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);
/* 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)
{
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++;
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') {
}
}
- task->nlines_type = sel;
+ MESSAGE_FIELD (task, nlines_type) = sel;
cur = order->head;
rspamd_cryptobox_hash_init (&hs, NULL, 0);
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)
{
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:
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;
return -1;
}
- rh->type = RSPAMD_RECEIVED_UNKNOWN;
+ rh->flags = RSPAMD_RECEIVED_UNKNOWN;
DL_FOREACH (head, cur) {
switch (cur->type) {
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");
*/
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;
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;
}
}
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;
}
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;
}
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
#include "config.h"
#include "libutil/mem_pool.h"
#include "libutil/addr.h"
+#include "khash.h"
#ifdef __cplusplus
extern "C" {
};
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;
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,
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;
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;
};
/**
* @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);
*/
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
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);
{
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;