Router variables: change list-separator to semicolon
authorJeremy Harris <jgh146exb@wizmail.org>
Mon, 15 Jul 2019 11:51:42 +0000 (12:51 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Mon, 15 Jul 2019 13:14:36 +0000 (14:14 +0100)
doc/doc-docbook/spec.xfpt
src/src/readconf.c
src/src/route.c
test/confs/0620
test/mail/0620.b
test/scripts/0000-Basic/0620

index 37ada7514fb783d15f9c219176f624210b20adfe..dd0439644dbb7b5484ebfae00c6ec3cfb2f2ac6c 100644 (file)
@@ -19011,13 +19011,12 @@ matters.
 .cindex router variables
 This option may be used multiple times on a router;
 because of this the list aspect is mostly irrelevant.
-The list separator is a colon but can be changed in the
+The list separator is a semicolon but can be changed in the
 usual way.
 
 Each list-element given must be of the form $"name = value"$
 and the names used must start with the string &"r_"&.
-Values containing colons should either have them doubled, or
-the entire list should be prefixed with a list-separator change.
+Values containing a list-separator should have them doubled.
 When a router runs, the strings are evaluated in order,
 to create variables which are added to the set associated with
 the address.
index b9d193554160bc62bcfef743c3c96299d26445f1..a7cf03dd353171409166f4778136282d2cb4b50b 100644 (file)
@@ -1770,7 +1770,10 @@ switch (type)
       }
     else if (ol->type & opt_rep_str)
       {
-      uschar sep_o = Ustrncmp(name, "headers_add", 11)==0 ? '\n' : ':';
+      uschar sep_o =
+       Ustrncmp(name, "headers_add", 11) == 0  ? '\n'
+       : Ustrncmp(name, "set", 3) == 0         ? ';'
+       : ':';
       int    sep_i = -(int)sep_o;
       const uschar * list = sptr;
       uschar * s;
index 416effd41deb8c62997fd5cd93a6eac818e1ed0b..b6930493f6899a7d85fdc087129a620590735e53 100644 (file)
@@ -1416,7 +1416,7 @@ set_router_vars(address_item * addr, const router_instance * r)
 {
 const uschar * varlist = r->set;
 tree_node ** root = (tree_node **) &addr->prop.variables;
-int sep = 0;
+int sep = ';';
 
 if (!varlist) return OK;
 
@@ -1433,7 +1433,11 @@ for (uschar * ele; (ele = string_nextinlist(&varlist, &sep, NULL, 0)); )
   /* Variable name must exist and start "r_". */
 
   if (!name || name[0] != 'r' || name[1] != '_' || !name[2])
+    {
+    log_write(0, LOG_MAIN|LOG_PANIC,
+       "bad router variable name '%s' in router '%s'\n", name, r->name);
     return FAIL;
+    }
   name += 2;
 
   while (isspace(*assignment)) assignment++;
@@ -1690,54 +1694,12 @@ for (r = addr->start_router ? addr->start_router : routers; r; r = nextr)
   router traversal.  On the addr string they are held as a variable tree, so
   as to maintain the post-expansion taints separate. */
 
-  if ((yield = set_router_vars(addr, r)) != OK)
-    if (yield == PASS)
-      continue;                /* with next router */
-    else
-      goto ROUTE_EXIT;
-
-#ifdef notdef
-  if (r->set)
+  switch (set_router_vars(addr, r))
     {
-    const uschar * list = r->set;
-    int sep = 0;
-    for (uschar * ele; (ele = string_nextinlist(&list, &sep, NULL, 0)); )
-      {
-      uschar * ee;
-      if (!(ee = expand_string(ele)))
-       if (f.expand_string_forcedfail)
-         {
-         DEBUG(D_route) debug_printf("forced failure in expansion of \"%s\" "
-             "(router variable): decline action taken\n", ele);
-
-         /* Expand "more" if necessary; DEFER => an expansion failed */
-
-         yield = exp_bool(addr, US"router", r->name, D_route,
-                         US"more", r->more, r->expand_more, &more);
-         if (yield != OK) goto ROUTE_EXIT;
-
-         if (!more)
-           {
-           DEBUG(D_route)
-             debug_printf("\"more\"=false: skipping remaining routers\n");
-           router_name = NULL;
-           r = NULL;
-           break;
-           }
-         else continue;    /* With next router */
-         }
-       else
-         {
-         addr->message = string_sprintf("expansion of \"%s\" failed "
-           "in %s router: %s", ele, r->name, expand_string_message);
-         yield = DEFER;
-         goto ROUTE_EXIT;
-         }
-
-      addr->prop.set = string_append_listele(addr->prop.set, ':', ee);
-      }
+    case OK:   break;
+    case PASS: continue;               /* with next router */
+    default:    goto ROUTE_EXIT;
     }
-#endif
 
   /* Finally, expand the address_data field in the router. Forced failure
   behaves as if the router declined. Any other failure is more serious. On
index 15e31f1c505f022fd8ad6008b775e45f5767153f..7f1b694158a0e8e254c62aeed9ddf7cd43a313d1 100644 (file)
@@ -13,25 +13,43 @@ acl_not_smtp = not_smtp
 begin acl
 
 not_smtp:
-  accept log_message = rcpt <$recipients> l <$local_part>
+  accept log_message = rcpts <$recipients> local_part <$local_part>
 
 # ----- Routers -----
 
 begin routers
 
+hide_verifies:
+  driver =     accept
+  verify_only
+
 alias:
   driver =     redirect
   debug_print = DEBUG: $r_r1 $r_r2
   data =       b
-  set =        <;      r_r1 = <$local_part> aaa:bbb bar=baz
+               # r_r1 checks that a variable with tainted data is ok
+               #       that the default list-sep ":" is not used for this list
+               #       that an '=' on the RHS is ok
+  set =                r_r1 = <$local_part> aaa:bbb bar=baz
+               # r_local checks that a variable is immediately usable
   set =                r_local = check
   errors_to =  bad_$r_local
 
 user:
   driver =     accept
   debug_print = DEBUG: $r_r1 $r_r2
+               # r_r1 vs. r_r2 checks we can have multiple "set" options
   set =                r_r1 = $local_part
-  set =        <;      r_r2 = $local_part 2a00:1940:100::ff:0:1 foo=bar
+  set =                r_r2 = $local_part \
+                       2a00:1940:100::ff:0:1 \
+                       foo=bar \
+                       # check we can get a newline into content
+                       newline=initial\n\tcont \
+                       # check we can get a list-sep into content (by doubling)
+                       semicolon=initial;;cont \
+               ; \
+               # r_r3 checks we can have a list as arg for a "set" option
+               r_r3 = bletch
   transport =  local_delivery
 
 
@@ -44,8 +62,7 @@ local_delivery:
   envelope_to_add
   file = DIR/test-mail/$local_part
   user = CALLER
-  debug_print = DEBUG: $r_r1 $r_r2
-  headers_add =        X-r1: <$r_r1>\nX-r2: <$r_r2>
+  headers_add =        X-r1: <$r_r1>\nX-r2: <$r_r2>\nX-r3: <$r_r3>
 
 
 # End
index 5840bc90a798e594711c25dc2082d888120f0a1c..ef81a0910d883769325561150f33fe2fe8436374 100644 (file)
@@ -4,10 +4,14 @@ Received: from CALLER by the.local.host.name with local (Exim x.yz)
        (envelope-from <CALLER@test.ex>)
        id 10HmaX-0005vi-00
        for a@test.ex; Tue, 2 Mar 1999 09:44:33 +0000
+Subject: foo
 Message-Id: <E10HmaX-0005vi-00@the.local.host.name>
 From: CALLER_NAME <CALLER@test.ex>
 Date: Tue, 2 Mar 1999 09:44:33 +0000
 X-r1: <b>
-X-r2: <b 2a00:1940:100::ff:0:1 foo=bar>
+X-r2: <b 2a00:1940:100::ff:0:1 foo=bar newline=initial
+       cont semicolon=initial;cont>
+X-r3: <bletch>
 
+body
 
index 0f662f1531930b925ee1ae3b608662e825d01cd8..96d598834dab457036583759abf77e0a9018167a 100644 (file)
@@ -1,2 +1,6 @@
 # router variables
 exim -odi a
+Subject: foo
+
+body
+****