Browse Source

[Feature] Keep track of headers in milter interface

It is now possible to remove not first but also last or even all headers
with the specific name by using `milter` control block in Rspamd.
tags/1.6.0
Vsevolod Stakhov 7 years ago
parent
commit
684b75db25
2 changed files with 67 additions and 10 deletions
  1. 66
    10
      src/libserver/milter.c
  2. 1
    0
      src/libserver/milter_internal.h

+ 66
- 10
src/libserver/milter.c View File

@@ -133,6 +133,10 @@ rspamd_milter_session_reset (struct rspamd_milter_session *session,
if (session->hostname) {
session->hostname->len = 0;
}

if (priv->headers) {
g_hash_table_remove_all (priv->headers);
}
}

if (how & RSPAMD_MILTER_RESET_ADDR) {
@@ -180,6 +184,10 @@ rspamd_milter_session_dtor (struct rspamd_milter_session *session)
rspamd_fstring_free (session->hostname);
}

if (priv->headers) {
g_hash_table_destroy (priv->headers);
}

g_free (priv);
g_free (session);
}
@@ -501,6 +509,26 @@ rspamd_milter_process_command (struct rspamd_milter_session *session,
}
else {
if (end > zero && *(end - 1) == '\0') {
gpointer res;
gint num;

res = g_hash_table_lookup (priv->headers, pos);
if (res) {
num = GPOINTER_TO_INT (res);
num ++;
/*
* No need to copy, as insert does not call
* destroy function for a key
*/
g_hash_table_insert (priv->headers, (gpointer)pos,
GINT_TO_POINTER (num));
}
else {
num = 1;
g_hash_table_insert (priv->headers, g_strdup (pos),
GINT_TO_POINTER (num));
}

rspamd_printf_fstring (&session->message, "%*s: %*s\r\n",
(int)(zero - pos), pos,
(int)(end - zero - 2), zero + 1);
@@ -983,6 +1011,8 @@ rspamd_milter_handle_socket (gint fd, const struct timeval *tv,
priv->ev_base = ev_base;
priv->state = RSPAMD_MILTER_READ_MORE;
priv->pool = pool;
priv->headers = g_hash_table_new_full (rspamd_strcase_hash,
rspamd_strcase_equal, g_free, NULL);

if (tv) {
memcpy (&priv->tv, tv, sizeof (*tv));
@@ -1292,8 +1322,10 @@ rspamd_milter_process_milter_block (struct rspamd_milter_session *session,
{
const ucl_object_t *elt, *cur, *cur_elt;
ucl_object_iter_t it;
struct rspamd_milter_private *priv = session->priv;
GString *hname, *hvalue;
gint nhdr;
gint nhdr, saved_nhdr, i;
gpointer found;

if (obj && ucl_object_type (obj) == UCL_OBJECT) {
elt = ucl_object_lookup (obj, "remove_headers");
@@ -1307,17 +1339,41 @@ rspamd_milter_process_milter_block (struct rspamd_milter_session *session,
while ((cur = ucl_object_iterate (elt, &it, true)) != NULL) {
if (ucl_object_type (cur) == UCL_INT) {
nhdr = ucl_object_toint (cur);
hname = g_string_new (ucl_object_key (cur));
hvalue = g_string_new ("");

if (nhdr >= 1) {
rspamd_milter_send_action (session,
RSPAMD_MILTER_CHGHEADER,
nhdr, hname, hvalue);
}
found = g_hash_table_lookup (priv->headers,
ucl_object_key (cur));

g_string_free (hname, TRUE);
g_string_free (hvalue, TRUE);
if (found) {
saved_nhdr = GPOINTER_TO_INT (found);

hname = g_string_new (ucl_object_key (cur));
hvalue = g_string_new ("");

if (nhdr >= 1) {
rspamd_milter_send_action (session,
RSPAMD_MILTER_CHGHEADER,
nhdr, hname, hvalue);
}
else if (nhdr == 0) {
/* We need to clear all headers */
for (i = 1; i <= saved_nhdr; i ++) {
rspamd_milter_send_action (session,
RSPAMD_MILTER_CHGHEADER,
i, hname, hvalue);
}
}
else {
/* Remove from the end */
if (nhdr >= -saved_nhdr) {
rspamd_milter_send_action (session,
RSPAMD_MILTER_CHGHEADER,
saved_nhdr + nhdr + 1, hname, hvalue);
}
}

g_string_free (hname, TRUE);
g_string_free (hvalue, TRUE);
}
}
}
}

+ 1
- 0
src/libserver/milter_internal.h View File

@@ -59,6 +59,7 @@ struct rspamd_milter_private {
struct timeval *ptv;
struct event_base *ev_base;
rspamd_mempool_t *pool;
GHashTable *headers;
rspamd_milter_finish fin_cb;
rspamd_milter_error err_cb;
void *ud;

Loading…
Cancel
Save