diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/src/functions.h | 1 | ||||
-rw-r--r-- | src/src/readconf.c | 24 | ||||
-rw-r--r-- | src/src/routers/rf_get_munge_headers.c | 99 | ||||
-rw-r--r-- | src/src/string.c | 44 | ||||
-rw-r--r-- | src/src/transport.c | 76 |
5 files changed, 147 insertions, 97 deletions
diff --git a/src/src/functions.h b/src/src/functions.h index 395961530..35500a165 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -350,6 +350,7 @@ extern int stdin_feof(void); extern int stdin_ferror(void); extern int stdin_ungetc(int); extern uschar *string_append(uschar *, int *, int *, int, ...); +extern uschar *string_append_listele(uschar *, uschar, const uschar *); extern uschar *string_base62(unsigned long int); extern uschar *string_cat(uschar *, int *, int *, const uschar *, int); extern uschar *string_copy_dnsdomain(uschar *); diff --git a/src/src/readconf.c b/src/src/readconf.c index b41d22d2a..81e3bc267 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -1562,15 +1562,21 @@ switch (type) Because we only do this once, near process start-up, I'm prepared to let this slide for the time being, even though it rankles. */ } - else if (*str_target && (ol->type & opt_rep_str)) - { + else if (ol->type & opt_rep_str) + { uschar sep = Ustrncmp(name, "headers_add", 11)==0 ? '\n' : ':'; - saved_condition = *str_target; - strtemp = saved_condition + Ustrlen(saved_condition)-1; - if (*strtemp == sep) *strtemp = 0; /* eliminate trailing list-sep */ - strtemp = string_sprintf("%s%c%s", saved_condition, sep, sptr); - *str_target = string_copy_malloc(strtemp); - } + uschar * cp; + + /* Strip trailing whitespace and seperators */ + for (cp = sptr + Ustrlen(sptr) - 1; + cp >= sptr && (*cp == '\n' || *cp == '\t' || *cp == ' ' || *cp == sep); + cp--) *cp = '\0'; + + if (cp >= sptr) + *str_target = string_copy_malloc( + *str_target ? string_sprintf("%s%c%s", *str_target, sep, sptr) + : sptr); + } else { *str_target = sptr; @@ -4131,4 +4137,6 @@ while(next_section[0] != 0) (void)fclose(config_file); } +/* vi: aw ai sw=2 +*/ /* End of readconf.c */ diff --git a/src/src/routers/rf_get_munge_headers.c b/src/src/routers/rf_get_munge_headers.c index 76e87e9c7..c44ba70b8 100644 --- a/src/src/routers/rf_get_munge_headers.c +++ b/src/src/routers/rf_get_munge_headers.c @@ -13,7 +13,7 @@ * Get additional headers for a router * *************************************************/ -/* This function is called by both routers to sort out the additional headers +/* This function is called by routers to sort out the additional headers and header remove list for a particular address. Arguments: @@ -32,83 +32,78 @@ 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->p.extra_headers; -if (rblock->extra_headers != NULL) +if (rblock->extra_headers) { - header_line *h; - uschar *s = expand_string(rblock->extra_headers); + uschar * list = rblock->extra_headers; + int sep = '\n'; + uschar * s; + int slen; - if (s == NULL) - { - if (!expand_string_forcedfail) + while ((s = string_nextinlist(&list, &sep, NULL, 0))) + if (!(s = expand_string(s))) { - addr->message = string_sprintf("%s router failed to expand \"%s\": %s", - rblock->name, rblock->extra_headers, expand_string_message); - return DEFER; + if (!expand_string_forcedfail) + { + addr->message = string_sprintf("%s router failed to expand \"%s\": %s", + rblock->name, rblock->extra_headers, expand_string_message); + return DEFER; + } } - } - - /* Expand succeeded. Put extra header 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. */ - - else - { - int slen = Ustrlen(s); - if (slen > 0) + else if ((slen = Ustrlen(s)) > 0) { - h = store_get(sizeof(header_line)); + /* 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)); /* 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; - } + h->text = s; else - { - h->text = store_get(slen+2); - memcpy(h->text, s, slen); - h->text[slen++] = '\n'; - h->text[slen] = 0; - } - - h->next = addr->p.extra_headers; + { + h->text = store_get(slen+2); + 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->p.remove_headers; -if (rblock->remove_headers != NULL) +/* Expand items from colon-sep list separately, then build new list */ +if (rblock->remove_headers) { - uschar *s = expand_string(rblock->remove_headers); - if (s == NULL) - { - if (!expand_string_forcedfail) + uschar * list = rblock->remove_headers; + int sep = ':'; + uschar * s; + uschar buffer[128]; + + while ((s = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))) + if (!(s = expand_string(s))) { - addr->message = string_sprintf("%s router failed to expand \"%s\": %s", - rblock->name, rblock->remove_headers, expand_string_message); - return DEFER; + if (!expand_string_forcedfail) + { + addr->message = string_sprintf("%s router failed to expand \"%s\": %s", + rblock->name, rblock->remove_headers, expand_string_message); + return DEFER; + } } - } - else if (*s != 0) - { - if (addr->p.remove_headers == NULL) - *remove_headers = s; - else - *remove_headers = string_sprintf("%s : %s", addr->p.remove_headers, s); - } + else if (*s) + *remove_headers = string_append_listele(*remove_headers, ':', s); } return OK; diff --git a/src/src/string.c b/src/src/string.c index 6f54cc624..eb73fae3e 100644 --- a/src/src/string.c +++ b/src/src/string.c @@ -966,6 +966,50 @@ return buffer; #endif /* COMPILE_UTILITY */ +#ifndef COMPILE_UTILITY +/************************************************ +* Add element to seperated list * +************************************************/ +/* This function is used to build a list, returning +an allocated null-terminated growable string. The +given element has any embedded seperator characters +doubled. + +Arguments: + list points to the start of the list that is being built, or NULL + if this is a new list that has no contents yet + sep list seperator charactoer + ele new lement to be appended to the list + +Returns: pointer to the start of the list, changed if copied for expansion. +*/ + +uschar * +string_append_listele(uschar * list, uschar sep, const uschar * ele) +{ +uschar * new = NULL; +int sz = 0, off = 0; +uschar * sp; + +if (list) + { + new = string_cat(new, &sz, &off, list, Ustrlen(list)); + new = string_cat(new, &sz, &off, &sep, 1); + } + +while (sp = Ustrchr(ele, sep)) + { + new = string_cat(new, &sz, &off, ele, sp-ele+1); + new = string_cat(new, &sz, &off, &sep, 1); + ele = sp+1; + } +new = string_cat(new, &sz, &off, ele, Ustrlen(ele)); +new[off] = '\0'; +return new; +} +#endif /* COMPILE_UTILITY */ + + #ifndef COMPILE_UTILITY /************************************************* diff --git a/src/src/transport.c b/src/src/transport.c index 549da4694..d4495393b 100644 --- a/src/src/transport.c +++ b/src/src/transport.c @@ -626,19 +626,9 @@ header_line *h; /* Then the message's headers. Don't write any that are flagged as "old"; that means they were rewritten, or are a record of envelope rewriting, or were removed (e.g. Bcc). If remove_headers is not null, skip any headers that -match any entries therein. Then check addr->p.remove_headers too, provided that -addr is not NULL. */ - -if (remove_headers) - { - uschar *s = expand_string(remove_headers); - if (!s && !expand_string_forcedfail) - { - errno = ERRNO_CHHEADER_FAIL; - return FALSE; - } - remove_headers = s; - } +match any entries therein. It is a colon-sep list; expand the items +separately and squash any empty ones. +Then check addr->p.remove_headers too, provided that addr is not NULL. */ for (h = header_list; h != NULL; h = h->next) if (h->type != htype_old) { @@ -656,7 +646,15 @@ for (h = header_list; h != NULL; h = h->next) if (h->type != htype_old) uschar buffer[128]; while ((s = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))) { - int len = Ustrlen(s); + int len; + + if (i == 0) + if (!(s = expand_string(s)) && !expand_string_forcedfail) + { + errno = ERRNO_CHHEADER_FAIL; + return FALSE; + } + len = Ustrlen(s); if (strncmpic(h->text, s, len) != 0) continue; ss = h->text + len; while (*ss == ' ' || *ss == '\t') ss++; @@ -731,36 +729,40 @@ if (addr) } } -/* If a string containing additional headers exists, expand it and write -out the result. This is done last so that if it (deliberately or accidentally) -isn't in header format, it won't mess up any other headers. An empty string -or a forced expansion failure are noops. An added header string from a -transport may not end with a newline; add one if it does not. */ +/* If a string containing additional headers exists it is a newline-sep +list. Expand each item and write out the result. This is done last so that +if it (deliberately or accidentally) isn't in header format, it won't mess +up any other headers. An empty string or a forced expansion failure are +noops. An added header string from a transport may not end with a newline; +add one if it does not. */ if (add_headers) { - uschar *s = expand_string(add_headers); - if (s == NULL) - { - if (!expand_string_forcedfail) - { errno = ERRNO_CHHEADER_FAIL; return FALSE; } - } - else - { - int len = Ustrlen(s); - if (len > 0) + int sep = '\n'; + uschar * s; + + while ((s = string_nextinlist(&add_headers, &sep, NULL, 0))) + if (!(s = expand_string(s))) { - if (!sendfn(fd, s, len, use_crlf)) return FALSE; - if (s[len-1] != '\n' && !sendfn(fd, US"\n", 1, use_crlf)) - return FALSE; - DEBUG(D_transport) + if (!expand_string_forcedfail) + { errno = ERRNO_CHHEADER_FAIL; return FALSE; } + } + else + { + int len = Ustrlen(s); + if (len > 0) { - debug_printf("added header line(s):\n%s", s); - if (s[len-1] != '\n') debug_printf("\n"); - debug_printf("---\n"); + if (!sendfn(fd, s, len, use_crlf)) return FALSE; + if (s[len-1] != '\n' && !sendfn(fd, US"\n", 1, use_crlf)) + return FALSE; + DEBUG(D_transport) + { + debug_printf("added header line:\n%s", s); + if (s[len-1] != '\n') debug_printf("\n"); + debug_printf("---\n"); + } } } - } } /* Separate headers from body with a blank line */ |