@@ -1277,11 +1277,11 @@ rspamc_stat_output (FILE *out, ucl_object_t *obj) | |||
static void | |||
rspamc_output_headers (FILE *out, struct rspamd_http_message *msg) | |||
{ | |||
struct rspamd_http_header *h, *htmp; | |||
struct rspamd_http_header *h; | |||
HASH_ITER (hh, msg->headers, h, htmp) { | |||
kh_foreach_value (msg->headers, h, { | |||
rspamd_fprintf (out, "%T: %T\n", &h->name, &h->value); | |||
} | |||
}); | |||
rspamd_fprintf (out, "\n"); | |||
} |
@@ -450,10 +450,10 @@ rspamd_protocol_handle_headers (struct rspamd_task *task, | |||
{ | |||
rspamd_ftok_t *hn_tok, *hv_tok, srch; | |||
gboolean has_ip = FALSE, seen_settings_header = FALSE; | |||
struct rspamd_http_header *header, *h, *htmp; | |||
struct rspamd_http_header *header, *h; | |||
gchar *ntok; | |||
HASH_ITER (hh, msg->headers, header, htmp) { | |||
kh_foreach_value (msg->headers, header, { | |||
DL_FOREACH (header, h) { | |||
ntok = rspamd_mempool_ftokdup (task->task_pool, &h->name); | |||
hn_tok = rspamd_mempool_alloc (task->task_pool, sizeof (*hn_tok)); | |||
@@ -702,7 +702,7 @@ rspamd_protocol_handle_headers (struct rspamd_task *task, | |||
rspamd_task_add_request_header (task, hn_tok, hv_tok); | |||
} | |||
} | |||
}); /* End of kh_foreach_value */ | |||
if (seen_settings_header && task->settings_elt) { | |||
msg_warn_task ("ignore settings id %s as settings header is also presented", |
@@ -243,6 +243,8 @@ rspamd_http_finish_header (struct rspamd_http_connection *conn, | |||
struct rspamd_http_connection_private *priv) | |||
{ | |||
struct rspamd_http_header *hdr; | |||
khiter_t k; | |||
gint r; | |||
priv->header->combined = rspamd_fstring_append (priv->header->combined, | |||
"\r\n", 2); | |||
@@ -252,12 +254,15 @@ rspamd_http_finish_header (struct rspamd_http_connection *conn, | |||
priv->header->name.len + 2; | |||
priv->header->name.begin = priv->header->combined->str; | |||
HASH_FIND (hh, priv->msg->headers, priv->header->name.begin, | |||
priv->header->name.len, hdr); | |||
k = kh_put (rspamd_http_headers_hash, priv->msg->headers, &priv->header->name, | |||
&r); | |||
if (hdr == NULL) { | |||
HASH_ADD_KEYPTR (hh, priv->msg->headers, priv->header->name.begin, | |||
priv->header->name.len, priv->header); | |||
if (r != 0) { | |||
kh_value (priv->msg->headers, k) = priv->header; | |||
hdr = NULL; | |||
} | |||
else { | |||
hdr = kh_value (priv->msg->headers, k); | |||
} | |||
DL_APPEND (hdr, priv->header); | |||
@@ -565,7 +570,7 @@ rspamd_http_decrypt_message (struct rspamd_http_connection *conn, | |||
const guchar *nm; | |||
gsize dec_len; | |||
struct rspamd_http_message *msg = priv->msg; | |||
struct rspamd_http_header *hdr, *hdrtmp, *hcur, *hcurtmp; | |||
struct rspamd_http_header *hdr, *hcur, *hcurtmp; | |||
struct http_parser decrypted_parser; | |||
struct http_parser_settings decrypted_cb; | |||
enum rspamd_cryptobox_mode mode; | |||
@@ -589,16 +594,15 @@ rspamd_http_decrypt_message (struct rspamd_http_connection *conn, | |||
} | |||
/* Cleanup message */ | |||
HASH_ITER (hh, msg->headers, hdr, hdrtmp) { | |||
HASH_DELETE (hh, msg->headers, hdr); | |||
kh_foreach_value (msg->headers, hdr, { | |||
DL_FOREACH_SAFE (hdr, hcur, hcurtmp) { | |||
rspamd_fstring_free (hcur->combined); | |||
g_free (hcur); | |||
} | |||
} | |||
}); | |||
msg->headers = NULL; | |||
kh_destroy (rspamd_http_headers_hash, msg->headers); | |||
msg->headers = kh_init (rspamd_http_headers_hash); | |||
if (msg->url != NULL) { | |||
msg->url = rspamd_fstring_assign (msg->url, "", 0); | |||
@@ -1325,7 +1329,7 @@ struct rspamd_http_message * | |||
rspamd_http_connection_copy_msg (struct rspamd_http_message *msg, GError **err) | |||
{ | |||
struct rspamd_http_message *new_msg; | |||
struct rspamd_http_header *hdr, *nhdr, *nhdrs, *thdr, *hcur; | |||
struct rspamd_http_header *hdr, *nhdr, *nhdrs, *hcur; | |||
const gchar *old_body; | |||
gsize old_len; | |||
struct stat st; | |||
@@ -1420,7 +1424,7 @@ rspamd_http_connection_copy_msg (struct rspamd_http_message *msg, GError **err) | |||
new_msg->date = msg->date; | |||
new_msg->last_modified = msg->last_modified; | |||
HASH_ITER (hh, msg->headers, hdr, thdr) { | |||
kh_foreach_value (msg->headers, hdr, { | |||
nhdrs = NULL; | |||
DL_FOREACH (hdr, hcur) { | |||
@@ -1429,17 +1433,25 @@ rspamd_http_connection_copy_msg (struct rspamd_http_message *msg, GError **err) | |||
nhdr->combined = rspamd_fstring_new_init (hcur->combined->str, | |||
hcur->combined->len); | |||
nhdr->name.begin = nhdr->combined->str + | |||
(hcur->name.begin - hcur->combined->str); | |||
(hcur->name.begin - hcur->combined->str); | |||
nhdr->name.len = hcur->name.len; | |||
nhdr->value.begin = nhdr->combined->str + | |||
(hcur->value.begin - hcur->combined->str); | |||
(hcur->value.begin - hcur->combined->str); | |||
nhdr->value.len = hcur->value.len; | |||
DL_APPEND (nhdrs, nhdr); | |||
} | |||
HASH_ADD_KEYPTR (hh, new_msg->headers, nhdrs->name.begin, | |||
nhdrs->name.len, nhdrs); | |||
} | |||
gint r; | |||
khiter_t k = kh_put (rspamd_http_headers_hash, new_msg->headers, | |||
&nhdrs->name,&r); | |||
if (r != 0) { | |||
kh_value (new_msg->headers, k) = nhdrs; | |||
} | |||
else { | |||
DL_CONCAT (kh_value (new_msg->headers, k), nhdrs); | |||
} | |||
}); | |||
return new_msg; | |||
} | |||
@@ -1550,7 +1562,7 @@ rspamd_http_connection_encrypt_message ( | |||
const guchar *nm; | |||
gint i, cnt; | |||
guint outlen; | |||
struct rspamd_http_header *hdr, *htmp, *hcur; | |||
struct rspamd_http_header *hdr, *hcur; | |||
enum rspamd_cryptobox_mode mode; | |||
mode = rspamd_keypair_alg (priv->local_key); | |||
@@ -1585,12 +1597,12 @@ rspamd_http_connection_encrypt_message ( | |||
} | |||
HASH_ITER (hh, msg->headers, hdr, htmp) { | |||
kh_foreach_value (msg->headers, hdr, { | |||
DL_FOREACH (hdr, hcur) { | |||
segments[i].data = hcur->combined->str; | |||
segments[i++].len = hcur->combined->len; | |||
} | |||
} | |||
}); | |||
/* crlfp should point now at the second crlf */ | |||
segments[i].data = crlfp; | |||
@@ -1915,7 +1927,7 @@ rspamd_http_connection_write_message_common (struct rspamd_http_connection *conn | |||
gboolean allow_shared) | |||
{ | |||
struct rspamd_http_connection_private *priv = conn->priv; | |||
struct rspamd_http_header *hdr, *htmp, *hcur; | |||
struct rspamd_http_header *hdr, *hcur; | |||
gchar repbuf[512], *pbody; | |||
gint i, hdrcount, meth_len = 0, preludelen = 0; | |||
gsize bodylen, enclen = 0; | |||
@@ -1988,14 +2000,29 @@ rspamd_http_connection_write_message_common (struct rspamd_http_connection *conn | |||
} | |||
if (priv->ctx->config.user_agent && conn->type == RSPAMD_HTTP_CLIENT) { | |||
struct rspamd_http_header *found = NULL; | |||
rspamd_ftok_t srch; | |||
khiter_t k; | |||
gint r; | |||
RSPAMD_FTOK_ASSIGN (&srch, "User-Agent"); | |||
HASH_FIND (hh, msg->headers, "User-Agent", | |||
sizeof ("User-Agent") - 1, found); | |||
k = kh_put (rspamd_http_headers_hash, msg->headers, &srch,&r); | |||
if (!found) { | |||
rspamd_http_message_add_header (msg, "User-Agent", | |||
if (r != 0) { | |||
hdr = g_malloc0 (sizeof (struct rspamd_http_header)); | |||
guint vlen = strlen (priv->ctx->config.user_agent); | |||
hdr->combined = rspamd_fstring_sized_new (srch.len + vlen + 4); | |||
rspamd_printf_fstring (&hdr->combined, "%T: %*s\r\n", &srch, vlen, | |||
priv->ctx->config.user_agent); | |||
hdr->name.begin = hdr->combined->str; | |||
hdr->name.len = srch.len; | |||
hdr->value.begin = hdr->combined->str + srch.len + 2; | |||
hdr->value.len = vlen; | |||
hdr->prev = hdr; /* for utlists */ | |||
kh_value (msg->headers, k) = hdr; | |||
/* as we searched using static buffer */ | |||
kh_key (msg->headers, k) = &hdr->name; | |||
} | |||
} | |||
@@ -2117,7 +2144,7 @@ rspamd_http_connection_write_message_common (struct rspamd_http_connection *conn | |||
hdrcount = 0; | |||
if (msg->method < HTTP_SYMBOLS) { | |||
HASH_ITER (hh, msg->headers, hdr, htmp) { | |||
kh_foreach_value (msg->headers, hdr, { | |||
DL_FOREACH (hdr, hcur) { | |||
/* <name: value\r\n> */ | |||
priv->wr_total += hcur->combined->len; | |||
@@ -2125,7 +2152,7 @@ rspamd_http_connection_write_message_common (struct rspamd_http_connection *conn | |||
priv->outlen ++; | |||
hdrcount ++; | |||
} | |||
} | |||
}); | |||
} | |||
/* Allocate iov */ | |||
@@ -2195,12 +2222,12 @@ rspamd_http_connection_write_message_common (struct rspamd_http_connection *conn | |||
else { | |||
i = 1; | |||
if (msg->method < HTTP_SYMBOLS) { | |||
HASH_ITER (hh, msg->headers, hdr, htmp) { | |||
kh_foreach_value (msg->headers, hdr, { | |||
DL_FOREACH (hdr, hcur) { | |||
priv->out[i].iov_base = hcur->combined->str; | |||
priv->out[i++].iov_len = hcur->combined->len; | |||
} | |||
} | |||
}); | |||
priv->out[i].iov_base = "\r\n"; | |||
priv->out[i++].iov_len = 2; |
@@ -39,6 +39,7 @@ rspamd_http_new_message (enum rspamd_http_message_type type) | |||
new->port = 80; | |||
new->type = type; | |||
new->method = HTTP_INVALID; | |||
new->headers = kh_init (rspamd_http_headers_hash); | |||
REF_INIT_RETAIN (new, rspamd_http_message_free); | |||
@@ -468,18 +469,16 @@ rspamd_http_message_storage_cleanup (struct rspamd_http_message *msg) | |||
void | |||
rspamd_http_message_free (struct rspamd_http_message *msg) | |||
{ | |||
struct rspamd_http_header *hdr, *htmp, *hcur, *hcurtmp; | |||
HASH_ITER (hh, msg->headers, hdr, htmp) { | |||
HASH_DEL (msg->headers, hdr); | |||
struct rspamd_http_header *hdr, *hcur, *hcurtmp; | |||
kh_foreach_value (msg->headers, hdr, { | |||
DL_FOREACH_SAFE (hdr, hcur, hcurtmp) { | |||
rspamd_fstring_free (hcur->combined); | |||
g_free (hcur); | |||
} | |||
} | |||
}); | |||
kh_destroy (rspamd_http_headers_hash, msg->headers); | |||
rspamd_http_message_storage_cleanup (msg); | |||
if (msg->url != NULL) { | |||
@@ -520,8 +519,10 @@ rspamd_http_message_add_header_len (struct rspamd_http_message *msg, | |||
const gchar *value, | |||
gsize len) | |||
{ | |||
struct rspamd_http_header *hdr, *found = NULL; | |||
struct rspamd_http_header *hdr, *found; | |||
guint nlen, vlen; | |||
khiter_t k; | |||
gint r; | |||
if (msg != NULL && name != NULL && value != NULL) { | |||
hdr = g_malloc0 (sizeof (struct rspamd_http_header)); | |||
@@ -535,12 +536,15 @@ rspamd_http_message_add_header_len (struct rspamd_http_message *msg, | |||
hdr->value.begin = hdr->combined->str + nlen + 2; | |||
hdr->value.len = vlen; | |||
HASH_FIND (hh, msg->headers, hdr->name.begin, | |||
hdr->name.len, found); | |||
k = kh_put (rspamd_http_headers_hash, msg->headers, &hdr->name, | |||
&r); | |||
if (found == NULL) { | |||
HASH_ADD_KEYPTR (hh, msg->headers, hdr->name.begin, | |||
hdr->name.len, hdr); | |||
if (r != 0) { | |||
kh_value (msg->headers, k) = hdr; | |||
found = NULL; | |||
} | |||
else { | |||
found = kh_value (msg->headers, k); | |||
} | |||
DL_APPEND (found, hdr); | |||
@@ -564,6 +568,8 @@ rspamd_http_message_add_header_fstr (struct rspamd_http_message *msg, | |||
{ | |||
struct rspamd_http_header *hdr, *found = NULL; | |||
guint nlen, vlen; | |||
khiter_t k; | |||
gint r; | |||
if (msg != NULL && name != NULL && value != NULL) { | |||
hdr = g_malloc0 (sizeof (struct rspamd_http_header)); | |||
@@ -576,12 +582,15 @@ rspamd_http_message_add_header_fstr (struct rspamd_http_message *msg, | |||
hdr->value.begin = hdr->combined->str + nlen + 2; | |||
hdr->value.len = vlen; | |||
HASH_FIND (hh, msg->headers, hdr->name.begin, | |||
hdr->name.len, found); | |||
k = kh_put (rspamd_http_headers_hash, msg->headers, &hdr->name, | |||
&r); | |||
if (found == NULL) { | |||
HASH_ADD_KEYPTR (hh, msg->headers, hdr->name.begin, | |||
hdr->name.len, hdr); | |||
if (r != 0) { | |||
kh_value (msg->headers, k) = hdr; | |||
found = NULL; | |||
} | |||
else { | |||
found = kh_value (msg->headers, k); | |||
} | |||
DL_APPEND (found, hdr); | |||
@@ -592,15 +601,19 @@ const rspamd_ftok_t * | |||
rspamd_http_message_find_header (struct rspamd_http_message *msg, | |||
const gchar *name) | |||
{ | |||
struct rspamd_http_header *hdr; | |||
const rspamd_ftok_t *res = NULL; | |||
rspamd_ftok_t srch; | |||
guint slen = strlen (name); | |||
khiter_t k; | |||
if (msg != NULL) { | |||
HASH_FIND (hh, msg->headers, name, slen, hdr); | |||
srch.begin = name; | |||
srch.len = slen; | |||
k = kh_get (rspamd_http_headers_hash, msg->headers, &srch); | |||
if (hdr) { | |||
res = &hdr->value; | |||
if (k != kh_end (msg->headers)) { | |||
res = &(kh_value (msg->headers, k)->value); | |||
} | |||
} | |||
@@ -614,14 +627,23 @@ rspamd_http_message_find_header_multiple ( | |||
{ | |||
GPtrArray *res = NULL; | |||
struct rspamd_http_header *hdr, *cur; | |||
rspamd_ftok_t srch; | |||
khiter_t k; | |||
guint cnt = 0; | |||
guint slen = strlen (name); | |||
if (msg != NULL) { | |||
HASH_FIND (hh, msg->headers, name, slen, hdr); | |||
srch.begin = name; | |||
srch.len = slen; | |||
if (hdr) { | |||
res = g_ptr_array_sized_new (4); | |||
k = kh_get (rspamd_http_headers_hash, msg->headers, &srch); | |||
if (k != kh_end (msg->headers)) { | |||
hdr = kh_value (msg->headers, k); | |||
LL_COUNT (hdr, cur, cnt); | |||
res = g_ptr_array_sized_new (cnt); | |||
LL_FOREACH (hdr, cur) { | |||
g_ptr_array_add (res, &cur->value); | |||
@@ -641,12 +663,18 @@ rspamd_http_message_remove_header (struct rspamd_http_message *msg, | |||
struct rspamd_http_header *hdr, *hcur, *hcurtmp; | |||
gboolean res = FALSE; | |||
guint slen = strlen (name); | |||
rspamd_ftok_t srch; | |||
khiter_t k; | |||
if (msg != NULL) { | |||
HASH_FIND (hh, msg->headers, name, slen, hdr); | |||
srch.begin = name; | |||
srch.len = slen; | |||
k = kh_get (rspamd_http_headers_hash, msg->headers, &srch); | |||
if (hdr) { | |||
HASH_DEL (msg->headers, hdr); | |||
if (k != kh_end (msg->headers)) { | |||
hdr = kh_value (msg->headers, k); | |||
kh_del (rspamd_http_headers_hash, msg->headers, k); | |||
res = TRUE; | |||
DL_FOREACH_SAFE (hdr, hcur, hcurtmp) { |
@@ -24,8 +24,6 @@ | |||
#include "ref.h" | |||
#include "upstream.h" | |||
#include "khash.h" | |||
#define HASH_CASELESS | |||
#include "uthash_strcase.h" | |||
#ifdef __cplusplus | |||
extern "C" { | |||
@@ -38,10 +36,13 @@ struct rspamd_http_header { | |||
rspamd_fstring_t *combined; | |||
rspamd_ftok_t name; | |||
rspamd_ftok_t value; | |||
UT_hash_handle hh; | |||
struct rspamd_http_header *prev, *next; | |||
}; | |||
KHASH_INIT (rspamd_http_headers_hash, rspamd_ftok_t *, | |||
struct rspamd_http_header *, 1, | |||
rspamd_ftok_icase_hash, rspamd_ftok_icase_equal); | |||
/** | |||
* HTTP message structure, used for requests and replies | |||
*/ | |||
@@ -49,7 +50,7 @@ struct rspamd_http_message { | |||
rspamd_fstring_t *url; | |||
GString *host; | |||
rspamd_fstring_t *status; | |||
struct rspamd_http_header *headers; | |||
khash_t (rspamd_http_headers_hash) *headers; | |||
struct _rspamd_body_buf_s { | |||
/* Data start */ |
@@ -221,7 +221,7 @@ lua_http_finish_handler (struct rspamd_http_connection *conn, | |||
struct rspamd_http_message *msg) | |||
{ | |||
struct lua_http_cbdata *cbd = (struct lua_http_cbdata *)conn->ud; | |||
struct rspamd_http_header *h, *htmp; | |||
struct rspamd_http_header *h; | |||
const gchar *body; | |||
gsize body_len; | |||
@@ -275,7 +275,7 @@ lua_http_finish_handler (struct rspamd_http_connection *conn, | |||
/* Headers */ | |||
lua_newtable (L); | |||
HASH_ITER (hh, msg->headers, h, htmp) { | |||
kh_foreach_value (msg->headers, h, { | |||
/* | |||
* Lowercase header name, as Lua cannot search in caseless matter | |||
*/ | |||
@@ -283,7 +283,7 @@ lua_http_finish_handler (struct rspamd_http_connection *conn, | |||
lua_pushlstring (L, h->name.begin, h->name.len); | |||
lua_pushlstring (L, h->value.begin, h->value.len); | |||
lua_settable (L, -3); | |||
} | |||
}); | |||
if (cbd->item) { | |||
/* Replace watcher to deal with nested calls */ | |||
@@ -313,7 +313,7 @@ lua_http_resume_handler (struct rspamd_http_connection *conn, | |||
lua_State *L = cbd->thread->lua_state; | |||
const gchar *body; | |||
gsize body_len; | |||
struct rspamd_http_header *h, *htmp; | |||
struct rspamd_http_header *h; | |||
if (err) { | |||
lua_pushstring (L, err); | |||
@@ -363,7 +363,7 @@ lua_http_resume_handler (struct rspamd_http_connection *conn, | |||
lua_pushliteral (L, "headers"); | |||
lua_newtable (L); | |||
HASH_ITER (hh, msg->headers, h, htmp) { | |||
kh_foreach_value (msg->headers, h, { | |||
/* | |||
* Lowercase header name, as Lua cannot search in caseless matter | |||
*/ | |||
@@ -371,7 +371,7 @@ lua_http_resume_handler (struct rspamd_http_connection *conn, | |||
lua_pushlstring (L, h->name.begin, h->name.len); | |||
lua_pushlstring (L, h->value.begin, h->value.len); | |||
lua_settable (L, -3); | |||
} | |||
}); | |||
lua_settable (L, -3); | |||
} |