Fix matching of long addresses. Bug 2677
[exim.git] / src / src / rewrite.c
index 6b194ca91c740c2e613dba469a9dbf2a329ac5dd..d003c6ce05974178aab33ac02626c9c390056fc4 100644 (file)
@@ -109,11 +109,11 @@ int yield_start = 0, yield_end = 0;
 
 if (whole) *whole = FALSE;
 
-/* Scan the rewriting rules */
+/* Scan the rewriting rules, ignoring any without matching flag */
 
 for (rewrite_rule * rule = rewrite_rules;
      rule && !done;
-     rule_number++, rule = rule->next)
+     rule_number++, rule = rule->next) if (rule->flags & flag)
   {
   int start, end, pdomain;
   int count = 0;
@@ -121,10 +121,6 @@ for (rewrite_rule * rule = rewrite_rules;
   const uschar *save_domain;
   uschar *error, *new, *newparsed;
 
-  /* Ensure that the flag matches the flags in the rule. */
-
-  if (!(rule->flags & flag)) continue;
-
   /* Come back here for a repeat after a successful rewrite. We do this
   only so many times. */
 
@@ -292,16 +288,11 @@ for (rewrite_rule * rule = rewrite_rules;
         uschar *p1 = new + start - 1;
         uschar *p2 = new + end + 1;
         const uschar *pf1, *pf2;
-        uschar buff1[256], buff2[256];
 
         while (p1 > new && p1[-1] == ' ') p1--;
-        pf1 = parse_fix_phrase(new, p1 - new, buff1, sizeof(buff1));
+        pf1 = parse_fix_phrase(new, p1 - new);
         while (*p2 == ' ') p2++;
-        pf2 = parse_fix_phrase(p2, Ustrlen(p2), buff2, sizeof(buff2));
-
-        /* Note that pf1 and pf2 are NOT necessarily buff1 and buff2. For
-        a non-RFC 2047 phrase that does not need to be RFC 2822 quoted, they
-        will be buff1+1 and buff2+1. */
+        pf2 = parse_fix_phrase(p2, Ustrlen(p2));
 
         start = Ustrlen(pf1) + start + new - p1;
         end = start + Ustrlen(newparsed);
@@ -454,8 +445,9 @@ rewrite_one_header(header_line *h, int flag,
 {
 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)
@@ -475,7 +467,7 @@ 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;
@@ -485,10 +477,10 @@ while (*s)
   the next address, saving the start of the old one. */
 
   *ss = 0;
-  recipient = parse_extract_address(s,&errmess,&start,&end,&domain,FALSE);
+  recipient = parse_extract_address(s, &errmess, &start, &end, &domain, FALSE);
   *ss = terminator;
   sprev = s;
-  s = ss + (terminator? 1:0);
+  s = ss + (terminator ? 1 :0);
   while (isspace(*s)) s++;
 
   /* There isn't much we can do for syntactic disasters at this stage.
@@ -496,7 +488,7 @@ while (*s)
 
   if (!recipient)
     {
-    store_reset(loop_reset_point);
+    loop_reset_point = store_reset(loop_reset_point);
     continue;
     }
 
@@ -510,7 +502,7 @@ while (*s)
   as abc@xyz, which the DNS lookup turns into abc@xyz.foo.com). However, if no
   change is made here, don't bother carrying on. */
 
-  if (routed_old != NULL)
+  if (routed_old)
     {
     if (domain <= 0 || strcmpic(recipient+domain, routed_old) != 0) continue;
     recipient[domain-1] = 0;
@@ -543,7 +535,7 @@ while (*s)
     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;
       }
     }
@@ -554,7 +546,7 @@ while (*s)
   "whole" flag set, adjust the pointers so that the whole address gets
   replaced, except possibly a final \n. */
 
-  if ((existflags & flag) != 0)
+  if (existflags & flag)
     {
     BOOL whole;
     new = rewrite_one(recipient, flag, &whole, FALSE, NULL, rewrite_rules);
@@ -575,7 +567,7 @@ while (*s)
   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
@@ -592,9 +584,9 @@ while (*s)
     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;
@@ -633,7 +625,7 @@ while (*s)
       if (*p != '\n')
         {
         lastnewline = newt - newtstart;
-        Ustrcat(newt, "\n\t");
+        Ustrcat(newt, US"\n\t");
         slen += 2;
         }
       }
@@ -656,16 +648,16 @@ while (*s)
     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 */
 
     s = newh->text + remlen;
-    DEBUG(D_rewrite) debug_printf("remainder: %s", (*s == 0)? US"\n" : s);
+    DEBUG(D_rewrite) debug_printf("remainder: %s", *s ? s : US"\n");
     }
   }
 
@@ -675,10 +667,10 @@ 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. */
 
-if (newh != NULL && replace)
+if (newh && replace)
   {
   newh->next = h->next;
-  if (newh->next == NULL) header_last = newh;
+  if (!newh->next) header_last = newh;
   h->type = htype_old;
   h->next = newh;
   }
@@ -721,34 +713,19 @@ 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);
 }