4282467c0a44bfd6c368d5b0743d728d2b2e5ad7
[users/jgh/exim.git] / src / src / routers / rf_get_munge_headers.c
1 /* $Cambridge: exim/src/src/routers/rf_get_munge_headers.c,v 1.5 2009/11/16 19:50:38 nm4 Exp $ */
2
3 /*************************************************
4 *     Exim - an Internet mail transport agent    *
5 *************************************************/
6
7 /* Copyright (c) University of Cambridge 1995 - 2009 */
8 /* See the file NOTICE for conditions of use and distribution. */
9
10 #include "../exim.h"
11 #include "rf_functions.h"
12
13
14 /*************************************************
15 *      Get additional headers for a router       *
16 *************************************************/
17
18 /* This function is called by both routers to sort out the additional headers
19 and header remove list for a particular address.
20
21 Arguments:
22   addr           the input address
23   rblock         the router instance
24   extra_headers  points to where to hang the header chain
25   remove_headers points to where to hang the remove list
26
27 Returns:         OK if no problem
28                  DEFER if expanding a string caused a deferment
29                    or a big disaster (e.g. expansion failure)
30 */
31
32 int
33 rf_get_munge_headers(address_item *addr, router_instance *rblock,
34   header_line **extra_headers, uschar **remove_headers)
35 {
36 /* Default is to retain existing headers */
37
38 *extra_headers = addr->p.extra_headers;
39
40 if (rblock->extra_headers != NULL)
41   {
42   header_line *h;
43   uschar *s = expand_string(rblock->extra_headers);
44
45   if (s == NULL)
46     {
47     if (!expand_string_forcedfail)
48       {
49       addr->message = string_sprintf("%s router failed to expand \"%s\": %s",
50         rblock->name, rblock->extra_headers, expand_string_message);
51       return DEFER;
52       }
53     }
54
55   /* Expand succeeded. Put extra header at the start of the chain because
56   further down it may point to headers from other routers, which may be
57   shared with other addresses. The output function outputs them in reverse
58   order. */
59
60   else
61     {
62     int slen = Ustrlen(s);
63     if (slen > 0)
64       {
65       h = store_get(sizeof(header_line));
66
67       /* We used to use string_sprintf() to add the newline if needed, but that
68       causes problems if the header line is exceedingly long (e.g. adding
69       something to a pathologically long line). So avoid it. */
70
71       if (s[slen-1] == '\n')
72         {
73         h->text = s;
74         }
75       else
76         {
77         h->text = store_get(slen+2);
78         memcpy(h->text, s, slen);
79         h->text[slen++] = '\n';
80         h->text[slen] = 0;
81         }
82
83       h->next = addr->p.extra_headers;
84       h->type = htype_other;
85       h->slen = slen;
86       *extra_headers = h;
87       }
88     }
89   }
90
91 /* Default is to retain existing removes */
92
93 *remove_headers = addr->p.remove_headers;
94
95 if (rblock->remove_headers != NULL)
96   {
97   uschar *s = expand_string(rblock->remove_headers);
98   if (s == NULL)
99     {
100     if (!expand_string_forcedfail)
101       {
102       addr->message = string_sprintf("%s router failed to expand \"%s\": %s",
103         rblock->name, rblock->remove_headers, expand_string_message);
104       return DEFER;
105       }
106     }
107   else if (*s != 0)
108     {
109     if (addr->p.remove_headers == NULL)
110       *remove_headers = s;
111     else
112       *remove_headers = string_sprintf("%s : %s", addr->p.remove_headers, s);
113     }
114   }
115
116 return OK;
117 }
118
119 /* End of rf_get_munge_headers.c */