* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions concerned with rewriting headers */
rewrite_one(uschar *s, int flag, BOOL *whole, BOOL add_header, uschar *name,
rewrite_rule *rewrite_rules)
{
-rewrite_rule *rule;
uschar *yield = s;
uschar *subject = s;
uschar *domain = NULL;
int rule_number = 1;
int yield_start = 0, yield_end = 0;
-if (whole != NULL) *whole = FALSE;
+if (whole) *whole = FALSE;
/* Scan the rewriting rules */
-for (rule = rewrite_rules;
- rule != NULL && !done;
+for (rewrite_rule * rule = rewrite_rules;
+ rule && !done;
rule_number++, rule = rule->next)
{
int start, end, pdomain;
int count = 0;
- uschar *save_localpart, *save_domain;
+ uschar *save_localpart;
+ const uschar *save_domain;
uschar *error, *new, *newparsed;
/* Ensure that the flag matches the flags in the rule. */
- if ((rule->flags & flag) == 0) continue;
+ if (!(rule->flags & flag)) continue;
/* Come back here for a repeat after a successful rewrite. We do this
only so many times. */
with the other kinds of rewrite, where expansion happens inside
match_address_list(). */
- if ((flag & rewrite_smtp) != 0)
+ if (flag & rewrite_smtp)
{
uschar *key = expand_string(rule->key);
- if (key == NULL)
+ if (!key)
{
- if (!expand_string_forcedfail)
+ if (!f.expand_string_forcedfail)
log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand \"%s\" while "
"checking for SMTP rewriting: %s", rule->key, expand_string_message);
continue;
else
{
- if (domain == NULL) domain = Ustrrchr(subject, '@') + 1;
+ if (!domain) domain = Ustrrchr(subject, '@') + 1;
/* Use the general function for matching an address against a list (here
just one item, so use the "impossible value" separator UCHAR_MAX+1). */
- if (match_address_list(subject, FALSE, TRUE, &(rule->key), NULL, 0,
+ if (match_address_list(subject, FALSE, TRUE, CUSS &(rule->key), NULL, 0,
UCHAR_MAX + 1, NULL) != OK)
continue;
give up altogether. For other expansion failures we have a configuration
error. */
- if (new == NULL)
+ if (!new)
{
- if (expand_string_forcedfail)
- { if ((rule->flags & rewrite_quit) != 0) break; else continue; }
+ if (f.expand_string_forcedfail)
+ { if (rule->flags & rewrite_quit) break; else continue; }
+
+ expand_string_message = expand_hide_passwords(expand_string_message);
+
log_write(0, LOG_MAIN|LOG_PANIC, "Expansion of %s failed while rewriting: "
"%s", rule->replacement, expand_string_message);
break;
newparsed = parse_extract_address(new, &error, &start, &end, &pdomain,
flag == rewrite_envfrom || flag == (rewrite_smtp|rewrite_smtp_sender));
- if (newparsed == NULL)
+ if (!newparsed)
{
log_write(0, LOG_MAIN|LOG_PANIC, "Rewrite of %s yielded unparseable "
"address: %s in address %s", subject, error, new);
if (pdomain == 0 && (*newparsed != 0 ||
(flag != rewrite_envfrom && flag != (rewrite_smtp|rewrite_smtp_sender))))
{
- if ((rule->flags & rewrite_qualify) != 0)
+ if (rule->flags & rewrite_qualify)
{
newparsed = rewrite_address_qualify(newparsed, TRUE);
new = string_sprintf("%.*s%s%.*s", start, new, newparsed,
/* We have a validly rewritten address */
- if ((log_write_selector & L_address_rewrite) != 0 ||
- (debug_selector & D_rewrite) != 0)
+ if (LOGGING(address_rewrite) || (debug_selector & D_rewrite) != 0)
{
- int i;
const uschar *where = CUS"?";
- for (i = 0; i < where_list_size; i++)
- {
+ for (int i = 0; i < where_list_size; i++)
if (flag == where_list[i].bit)
{
where = where_list[i].string;
break;
}
- }
log_write(L_address_rewrite,
LOG_MAIN, "\"%s\" from %s rewritten as \"%s\" by rule %d",
yield, where, new, rule_number);
flag set and so we must preserve the non-active portion of the current
subject unless the current rule also has the w flag set. */
- if (whole != NULL && (flag & rewrite_all_headers) != 0)
+ if (whole && (flag & rewrite_all_headers))
{
/* Current rule has the w flag set. We must ensure the phrase parts
are syntactically valid if they are present. */
- if ((rule->flags & rewrite_whole) != 0)
+ if (rule->flags & rewrite_whole)
{
if (start > 0 && new[start-1] == '<')
{
uschar *p1 = new + start - 1;
uschar *p2 = new + end + 1;
- uschar *pf1, *pf2;
+ const uschar *pf1, *pf2;
uschar buff1[256], buff2[256];
while (p1 > new && p1[-1] == ' ') p1--;
start = Ustrlen(pf1) + start + new - p1;
end = start + Ustrlen(newparsed);
- new = string_sprintf("%s%.*s%s", pf1, p2 - p1, p1, pf2);
+ new = string_sprintf("%s%.*s%s", pf1, (int)(p2 - p1), p1, pf2);
}
/* Now accept the whole thing */
/* If no further rewrites are to be done, set the done flag. This allows
repeats of the current rule if configured before breaking the loop. */
- if ((rule->flags & rewrite_quit) != 0) done = TRUE;
+ if (rule->flags & rewrite_quit) done = TRUE;
/* Allow the current rule to be applied up to 10 times if
requested. */
- if ((rule->flags & rewrite_repeat) != 0)
+ if (rule->flags & rewrite_repeat)
{
if (count++ < 10) goto REPEAT_RULE;
log_write(0, LOG_MAIN|LOG_PANIC, "rewrite rule repeat ignored after 10 "
*/
static header_line *
-rewrite_one_header(header_line *h, int flag, uschar *routed_old,
- uschar *routed_new, rewrite_rule *rewrite_rules, int existflags, BOOL replace)
+rewrite_one_header(header_line *h, int flag,
+ const uschar *routed_old, const uschar *routed_new,
+ rewrite_rule *rewrite_rules, int existflags, BOOL replace)
{
int lastnewline = 0;
header_line *newh = NULL;
-void *function_reset_point = store_get(0);
+rmark function_reset_point = store_mark();
uschar *s = Ustrchr(h->text, ':') + 1;
while (isspace(*s)) s++;
DEBUG(D_rewrite)
debug_printf("rewrite_one_header: type=%c:\n %s", h->type, h->text);
-parse_allow_group = TRUE; /* Allow group syntax */
+f.parse_allow_group = TRUE; /* Allow group syntax */
/* Loop for multiple addresses in the header. We have to go through them all
in case any need qualifying, even if there's no rewriting. Pathological headers
_are_ rewritten so as to avoid runaway store usage for these kinds of header.
We want to avoid keeping store for any intermediate versions. */
-while (*s != 0)
+while (*s)
{
uschar *sprev;
uschar *ss = parse_find_address_end(s, FALSE);
uschar *recipient, *new, *errmess;
- void *loop_reset_point = store_get(0);
+ rmark loop_reset_point = store_mark();
BOOL changed = FALSE;
int terminator = *ss;
int start, end, domain;
/* There isn't much we can do for syntactic disasters at this stage.
Pro tem (possibly for ever) ignore them. */
- if (recipient == NULL)
+ if (!recipient)
{
- store_reset(loop_reset_point);
+ loop_reset_point = store_reset(loop_reset_point);
continue;
}
/* Can only qualify if permitted; if not, no rewrite. */
- if (changed && ((is_recipient && !allow_unqualified_recipient) ||
- (!is_recipient && !allow_unqualified_sender)))
+ if (changed && ((is_recipient && !f.allow_unqualified_recipient) ||
+ (!is_recipient && !f.allow_unqualified_sender)))
{
- store_reset(loop_reset_point);
+ loop_reset_point = store_reset(loop_reset_point);
continue;
}
}
point, because we may have a rewritten line from a previous time round the
loop. */
- if (!changed) store_reset(loop_reset_point);
+ if (!changed) loop_reset_point = store_reset(loop_reset_point);
/* If the address has changed, create a new header containing the
rewritten address. We do not need to set the chain pointers at this
int newlen = Ustrlen(new);
int oldlen = end - start;
- header_line *prev = (newh == NULL)? h : newh;
- uschar *newt = store_malloc(prev->slen - oldlen + newlen + 4);
- uschar *newtstart = newt;
+ header_line * prev = newh ? newh : h;
+ uschar * newt = store_get_perm(prev->slen - oldlen + newlen + 4, TRUE);
+ uschar * newtstart = newt;
int type = prev->type;
int slen = prev->slen - oldlen + newlen;
if (*p != '\n')
{
lastnewline = newt - newtstart;
- Ustrcat(newt, "\n\t");
+ Ustrcat(newt, US"\n\t");
slen += 2;
}
}
rewritten copy from a previous time round this loop. */
store_reset(function_reset_point);
- newh = store_get(sizeof(header_line));
+ function_reset_point = store_mark();
+ newh = store_get(sizeof(header_line), FALSE);
newh->type = type;
newh->slen = slen;
newh->text = string_copyn(newtstart, slen);
- store_free(newtstart);
/* Set up for scanning the rest of the header */
}
}
-parse_allow_group = FALSE; /* Reset group flags */
-parse_found_group = FALSE;
+f.parse_allow_group = FALSE; /* Reset group flags */
+f.parse_found_group = FALSE;
/* If a rewrite happened and "replace" is true, put the new header into the
chain following the old one, and mark the old one as replaced. */
*/
header_line *
-rewrite_header(header_line *h, uschar *routed_old, uschar *routed_new,
+rewrite_header(header_line *h,
+ const uschar *routed_old, const uschar *routed_new,
rewrite_rule *rewrite_rules, int existflags, BOOL replace)
{
+int flag;
switch (h->type)
{
- case htype_sender:
- return rewrite_one_header(h, rewrite_sender, routed_old, routed_new,
- rewrite_rules, existflags, replace);
-
- case htype_from:
- return rewrite_one_header(h, rewrite_from, routed_old, routed_new,
- rewrite_rules, existflags, replace);
-
- case htype_to:
- return rewrite_one_header(h, rewrite_to, routed_old, routed_new,
- rewrite_rules, existflags, replace);
-
- case htype_cc:
- return rewrite_one_header(h, rewrite_cc, routed_old, routed_new,
- rewrite_rules, existflags, replace);
-
- case htype_bcc:
- return rewrite_one_header(h, rewrite_bcc, routed_old, routed_new,
- rewrite_rules, existflags, replace);
-
- case htype_reply_to:
- return rewrite_one_header(h, rewrite_replyto, routed_old, routed_new,
- rewrite_rules, existflags, replace);
+ case htype_sender: flag = rewrite_sender; break;
+ case htype_from: flag = rewrite_from; break;
+ case htype_to: flag = rewrite_to; break;
+ case htype_cc: flag = rewrite_cc; break;
+ case htype_bcc: flag = rewrite_bcc; break;
+ case htype_reply_to: flag = rewrite_replyto; break;
+ default: return NULL;
}
-
-return NULL;
+return rewrite_one_header(h, flag, routed_old, routed_new,
+ rewrite_rules, existflags, replace);
}
void rewrite_test(uschar *s)
{
uschar *recipient, *error;
-int i, start, end, domain;
+int start, end, domain;
BOOL done_smtp = FALSE;
if (rewrite_existflags == 0)
recipient = parse_extract_address(s, &error, &start, &end, &domain, FALSE);
-if (recipient == NULL)
+if (!recipient)
{
if (!done_smtp)
printf("Syntax error in %s\n%c%s\n", s, toupper(error[0]), error+1);
return;
}
-for (i = 0; i < 8; i++)
+for (int i = 0; i < 8; i++)
{
BOOL whole = FALSE;
int flag = 1 << i;