diff options
Diffstat (limited to 'src/routers/rf_get_munge_headers.c')
-rw-r--r-- | src/routers/rf_get_munge_headers.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/src/routers/rf_get_munge_headers.c b/src/routers/rf_get_munge_headers.c new file mode 100644 index 0000000..d304d11 --- /dev/null +++ b/src/routers/rf_get_munge_headers.c @@ -0,0 +1,123 @@ +/************************************************* +* Exim - an Internet mail transport agent * +*************************************************/ + +/* Copyright (c) The Exim Maintainers 2021 - 2022 */ +/* Copyright (c) University of Cambridge 1995 - 2018 */ +/* See the file NOTICE for conditions of use and distribution. */ + +#include "../exim.h" +#include "rf_functions.h" + + +/************************************************* +* Get additional headers for a router * +*************************************************/ + +/* This function is called by routers to sort out the additional headers +and header remove list for a particular address. + +Arguments: + addr the input address + rblock the router instance + extra_headers points to where to hang the header chain + remove_headers points to where to hang the remove list + +Returns: OK if no problem + DEFER if expanding a string caused a deferment + or a big disaster (e.g. expansion failure) +*/ + +int +rf_get_munge_headers(address_item *addr, router_instance *rblock, + header_line **extra_headers, uschar **remove_headers) +{ +/* Default is to retain existing headers */ +*extra_headers = addr->prop.extra_headers; + +if (rblock->extra_headers) + { + const uschar * list = rblock->extra_headers; + int sep = '\n'; + uschar * s, * t; + int slen; + + while ((s = string_nextinlist(&list, &sep, NULL, 0))) + if (!(s = expand_string(t = s))) + { + if (!f.expand_string_forcedfail) + { + addr->message = string_sprintf( + "%s router failed to expand add_headers item \"%s\": %s", + rblock->name, t, expand_string_message); + return DEFER; + } + } + else if ((slen = Ustrlen(s)) > 0) + { + /* Expand succeeded. Put extra headers at the start of the chain because + further down it may point to headers from other routers, which may be + shared with other addresses. The output function outputs them in reverse + order. */ + + header_line * h = store_get(sizeof(header_line), GET_UNTAINTED); + + /* We used to use string_sprintf() to add the newline if needed, but that + causes problems if the header line is exceedingly long (e.g. adding + something to a pathologically long line). So avoid it. */ + + if (s[slen-1] == '\n') + h->text = s; + else + { + h->text = store_get(slen+2, s); + memcpy(h->text, s, slen); + h->text[slen++] = '\n'; + h->text[slen] = 0; + } + + h->next = *extra_headers; + h->type = htype_other; + h->slen = slen; + *extra_headers = h; + } + } + +/* Default is to retain existing removes */ +*remove_headers = addr->prop.remove_headers; + +/* Expand items from colon-sep list separately, then build new list */ +if (rblock->remove_headers) + { + const uschar * list = rblock->remove_headers; + int sep = ':'; + uschar * s, * t; + gstring * g = NULL; + + if (*remove_headers) + g = string_cat(NULL, *remove_headers); + + while ((s = string_nextinlist(&list, &sep, NULL, 0))) + if (!(s = expand_string(t = s))) + { + if (!f.expand_string_forcedfail) + { + addr->message = string_sprintf( + "%s router failed to expand remove_headers item \"%s\": %s", + rblock->name, t, expand_string_message); + return DEFER; + } + } + else if (*s) + g = string_append_listele(g, ':', s); + + if (g) + *remove_headers = g->s; + } + +return OK; +} + +/* vi: aw ai sw=2 +*/ +/* End of rf_get_munge_headers.c */ |