From: Philip Hazel Date: Mon, 26 Feb 2007 14:07:04 +0000 (+0000) Subject: MH's patch for allowing control characters as list separators. X-Git-Tag: exim-4_67~27 X-Git-Url: https://git.exim.org/users/jgh/exim.git/commitdiff_plain/ec95d1a6a6c015844e412572b6e5a185b072e01e MH's patch for allowing control characters as list separators. --- diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 6e61fa9b6..3202cc9c1 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -1,4 +1,4 @@ -$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.484 2007/02/20 15:58:02 ph10 Exp $ +$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.485 2007/02/26 14:07:04 ph10 Exp $ Change log file for Exim from version 4.21 ------------------------------------------- @@ -131,6 +131,8 @@ PH/29 SMTP synchronization checks are implemented when a command is read - HELO/EHLO and after the predata ACL, and likewise for MAIL and RCPT when pipelining has not been advertised. +PH/30 MH's patch to allow iscntrl() characters to be list separators. + Exim version 4.66 ----------------- diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index 677ab21aa..d39c6d3e2 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -1,4 +1,4 @@ -$Cambridge: exim/doc/doc-txt/NewStuff,v 1.142 2007/02/14 15:33:40 ph10 Exp $ +$Cambridge: exim/doc/doc-txt/NewStuff,v 1.143 2007/02/26 14:07:04 ph10 Exp $ New Features in Exim -------------------- @@ -375,6 +375,22 @@ Version 4.67 continue = condition = ${if eq{0}{}{true}{true}} +18. It is now possible to use newline and other control characters (those with + values less than 32, plus DEL) as separators in lists. Such separators must + be provided literally at the time the list is processed, but the string + expansion that happens first means that you can write them using normal + escape sequences. For example, if a new-line separated list of domains is + generated by a lookup, you can now process it directly by a line such as + this: + + domains = <\n ${lookup mysql{.....}} + + This avoids having to change the list separator in such data. Unlike + printing character separators, which can be included in list items by + doubling, it is not possible to include a control character as data when it + is set as the separator. Two such characters in succession are interpreted + as enclosing an empty list item. + Version 4.66 ------------ diff --git a/src/src/string.c b/src/src/string.c index b52d4ab95..20bd1d1f3 100644 --- a/src/src/string.c +++ b/src/src/string.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/string.c,v 1.12 2007/02/07 11:24:56 ph10 Exp $ */ +/* $Cambridge: exim/src/src/string.c,v 1.13 2007/02/26 14:07:04 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -764,19 +764,26 @@ return NULL; /* Leading and trailing space is removed from each item. The separator in the list is controlled by the int pointed to by the separator argument as follows: - If its value is > 0 it is used as the delimiter. - (If its value is actually > UCHAR_MAX there is only one item in the list. + If the value is > 0 it is used as the separator. This is typically used for + sublists such as slash-separated options. The value is always a printing + character. + + (If the value is actually > UCHAR_MAX there is only one item in the list. This is used for some cases when called via functions that sometimes plough through lists, and sometimes are given single items.) - If its value is <= 0, the string is inspected for a leading 0 && isspace(buffer[p-1])) p--; @@ -834,31 +856,37 @@ if (buffer != NULL) else { + int size = 0; + int ptr = 0; + uschar *ss; + /* We know that *s != 0 at this point. However, it might be pointing to a - separator, which could indicate an empty string, or could be doubled to - indicate a separator character as data at the start of a string. */ + separator, which could indicate an empty string, or (if an ispunct() + character) could be doubled to indicate a separator character as data at the + start of a string. Avoid getting working memory for an empty item. */ if (*s == sep) { s++; - if (*s != sep) buffer = string_copy(US""); + if (*s != sep || sep_is_special) + { + *listptr = s; + return string_copy(US""); + } } - if (buffer == NULL) + /* Not an empty string; the first character is guaranteed to be a data + character. */ + + for (;;) { - int size = 0; - int ptr = 0; - uschar *ss; - for (;;) - { - for (ss = s + 1; *ss != 0 && *ss != sep; ss++); - buffer = string_cat(buffer, &size, &ptr, s, ss-s); - s = ss; - if (*s == 0 || *(++s) != sep) break; - } - while (ptr > 0 && isspace(buffer[ptr-1])) ptr--; - buffer[ptr] = 0; + for (ss = s + 1; *ss != 0 && *ss != sep; ss++); + buffer = string_cat(buffer, &size, &ptr, s, ss-s); + s = ss; + if (*s == 0 || *(++s) != sep || sep_is_special) break; } + while (ptr > 0 && isspace(buffer[ptr-1])) ptr--; + buffer[ptr] = 0; } /* Update the current pointer and return the new string */ diff --git a/test/confs/0002 b/test/confs/0002 index 8662e54d0..af680500c 100644 --- a/test/confs/0002 +++ b/test/confs/0002 @@ -33,7 +33,7 @@ connect0: accept connect1: - deny hosts = partial-lsearch;DIR/aux-fixed/0002.lsearch + deny hosts = <\n partial-lsearch;DIR/aux-fixed/0002.lsearch \n 1.2.3.4 connect2: deny hosts = net-lsearch;DIR/aux-fixed/0002.lsearch diff --git a/test/scripts/0000-Basic/0002 b/test/scripts/0000-Basic/0002 index 870359eb2..fd332afa4 100644 --- a/test/scripts/0000-Basic/0002 +++ b/test/scripts/0000-Basic/0002 @@ -59,6 +59,15 @@ reduce: ${reduce{a:b:c}{+}{$value$item}} reduce: ${reduce {<, 1,2,3}{0}{${eval:$value+$item}}} reduce: ${reduce {3:0:9:4:6}{0}{${if >{$item}{$value}{$item}{$value}}}} +# Tests with iscntrl() and illegal separators + +map: ${map{<\n a\n\nb\nc}{'$item'}} + +reduce: ${reduce {> 550 Administrative prohibition LOG: MAIN REJECT diff --git a/test/stdout/0002 b/test/stdout/0002 index d985a9c1e..f76f07f51 100644 --- a/test/stdout/0002 +++ b/test/stdout/0002 @@ -49,6 +49,18 @@ > reduce: 6 > reduce: 9 > +> # Tests with iscntrl() and illegal separators +> +> map: 'a' +'' +'b' +'c' +> +> Failed: error in expression evaluation: expecting number or opening parenthesis (after processing "0+") inside "reduce" item +> reduce: 6 +> reduce: 6 +> reduce: 6 +> > # Operators > > addrss: local-part@dom.ain