diff options
author | Jeremy Harris <jgh146exb@wizmail.org> | 2012-06-12 21:43:58 +0100 |
---|---|---|
committer | Jeremy Harris <jgh146exb@wizmail.org> | 2012-06-12 21:43:58 +0100 |
commit | 585121e2682545b7afa599e039a7a1e2b1804570 (patch) | |
tree | b4074602a1cc3b876fee896d6d5446e4548d51a6 | |
parent | d7148a072a5fee80ffa8d1aeebf9bc05d0e903b4 (diff) | |
parent | a64a3dfa73b829669d838c8d129b0974360b95a5 (diff) |
Merge branch 'lists'
-rw-r--r-- | doc/doc-docbook/spec.xfpt | 20 | ||||
-rw-r--r-- | doc/doc-txt/ChangeLog | 2 | ||||
-rw-r--r-- | doc/doc-txt/NewStuff | 4 | ||||
-rw-r--r-- | src/src/expand.c | 105 | ||||
-rw-r--r-- | test/confs/0002 | 2 | ||||
-rw-r--r-- | test/scripts/0000-Basic/0002 | 15 | ||||
-rw-r--r-- | test/stdout/0002 | 15 |
7 files changed, 162 insertions, 1 deletions
diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index 0cdc98657..dcf6b6cfb 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -9567,6 +9567,7 @@ environments where Exim uses base 36 instead of base 62 for its message identifiers, base-36 digits. The number is converted to decimal and output as a string. + .vitem &*${domain:*&<&'string'&>&*}*& .cindex "domain" "extraction" .cindex "expansion" "domain extraction" @@ -9726,6 +9727,25 @@ See the description of the general &%length%& item above for details. Note that when &%length%& is used as an operator. +.vitem &*${listcount:*&<&'string'&>&*}*& +.cindex "expansion" "list item count" +.cindex "list" "item count" +.cindex "list" "count of items" +.cindex "&%listcount%& expansion item" +The string is interpreted as a list and the number of items is returned. + + +.vitem &*${listnamed:*&<&'name'&>&*}*&&~and&~&*${list_*&<&'type'&>&*name'&>&*}*& +.cindex "expansion" "named list" +.cindex "&%listnamed%& expansion item" +The name is interpreted as a named list and the content of the list is returned, +expanding any referenced lists, re-quoting as needed for colon-separation. +If the optional type if given it must be one of "a", "d", "h" or "l" +and selects address-, domain-, host- or localpart- lists to search among respectively. +Otherwise all types are searched in an undefined order and the first +matching list is returned. + + .vitem &*${local_part:*&<&'string'&>&*}*& .cindex "expansion" "local part extraction" .cindex "&%local_part%& expansion item" diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index bd0628637..34521098e 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -42,6 +42,8 @@ PP/08 Handle smtp transport tls_sni option forced-fail for OpenSSL. NM/01 Bugzilla 1197 - Spec typo Bugzilla 1196 - Spec examples corrections +JH/03 Add expansion operators ${listnamed:name} and ${listcount:string} + Exim version 4.80 ----------------- diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index aae58c631..6d64faa00 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -70,7 +70,7 @@ Version 4.81 system not your own. The Recieved-by: header on items delivered by cutthrough is generated - early in of reception rather than at the end; this will affect any timestamp + early in reception rather than at the end; this will affect any timestamp included. The log line showing delivery is recorded before that showing reception; it uses a new ">>" tag instead of "=>". @@ -84,6 +84,8 @@ Version 4.81 Not yet supported: IGNOREQUOTA, SIZE, PIPELINING, AUTH. + 8. New expansion operators ${listnamed:name} to get the content of a named list + and ${listcount:string} to count the items in a list. Version 4.80 ------------ diff --git a/src/src/expand.c b/src/src/expand.c index 05361a3ef..965842611 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -182,6 +182,8 @@ static uschar *op_table_main[] = { US"l", US"lc", US"length", + US"listcount", + US"listnamed", US"mask", US"md5", US"nh", @@ -215,6 +217,8 @@ enum { EOP_L, EOP_LC, EOP_LENGTH, + EOP_LISTCOUNT, + EOP_LISTNAMED, EOP_MASK, EOP_MD5, EOP_NH, @@ -5470,6 +5474,107 @@ while (*s != 0) continue; } + /* count the number of list elements */ + + case EOP_LISTCOUNT: + { + int cnt = 0; + int sep = 0; + uschar * cp; + uschar buffer[256]; + + while (string_nextinlist(&sub, &sep, buffer, sizeof(buffer)) != NULL) cnt++; + cp = string_sprintf("%d", cnt); + yield = string_cat(yield, &size, &ptr, cp, Ustrlen(cp)); + continue; + } + + /* expand a named list given the name */ + /* handles nested named lists; requotes as colon-sep list */ + + case EOP_LISTNAMED: + { + tree_node *t = NULL; + uschar * list; + int sep = 0; + uschar * item; + uschar * suffix = ""; + BOOL needsep = FALSE; + uschar buffer[256]; + + if (*sub == '+') sub++; + if (arg == NULL) /* no-argument version */ + { + if (!(t = tree_search(addresslist_anchor, sub)) && + !(t = tree_search(domainlist_anchor, sub)) && + !(t = tree_search(hostlist_anchor, sub))) + t = tree_search(localpartlist_anchor, sub); + } + else switch(*arg) /* specific list-type version */ + { + case 'a': t = tree_search(addresslist_anchor, sub); suffix = "_a"; break; + case 'd': t = tree_search(domainlist_anchor, sub); suffix = "_d"; break; + case 'h': t = tree_search(hostlist_anchor, sub); suffix = "_h"; break; + case 'l': t = tree_search(localpartlist_anchor, sub); suffix = "_l"; break; + default: + expand_string_message = string_sprintf("bad suffix on \"list\" operator"); + goto EXPAND_FAILED; + } + + if(!t) + { + expand_string_message = string_sprintf("\"%s\" is not a %snamed list", + sub, !arg?"" + : *arg=='a'?"address " + : *arg=='d'?"domain " + : *arg=='h'?"host " + : *arg=='l'?"localpart " + : 0); + goto EXPAND_FAILED; + } + + if (skipping) continue; + list = ((namedlist_block *)(t->data.ptr))->string; + + while ((item = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL) + { + uschar * buf = US" : "; + if (needsep) + yield = string_cat(yield, &size, &ptr, buf, 3); + else + needsep = TRUE; + + if (*item == '+') /* list item is itself a named list */ + { + uschar * sub = string_sprintf("${listnamed%s:%s}", suffix, item); + item = expand_string_internal(sub, FALSE, NULL, FALSE, TRUE); + } + else if (sep != ':') /* item from non-colon-sep list, re-quote for colon list-separator */ + { + char * cp; + char tok[3]; + tok[0] = sep; tok[1] = ':'; tok[2] = 0; + while ((cp= strpbrk((const char *)item, tok))) + { + yield = string_cat(yield, &size, &ptr, item, cp-(char *)item); + if (*cp++ == ':') /* colon in a non-colon-sep list item, needs doubling */ + { + yield = string_cat(yield, &size, &ptr, US"::", 2); + item = cp; + } + else /* sep in item; should already be doubled; emit once */ + { + yield = string_cat(yield, &size, &ptr, (uschar *)tok, 1); + if (*cp == sep) cp++; + item = cp; + } + } + } + yield = string_cat(yield, &size, &ptr, item, Ustrlen(item)); + } + continue; + } + /* mask applies a mask to an IP address; for example the result of ${mask:131.111.10.206/28} is 131.111.10.192/28. */ diff --git a/test/confs/0002 b/test/confs/0002 index af680500c..6983fd87f 100644 --- a/test/confs/0002 +++ b/test/confs/0002 @@ -15,6 +15,8 @@ gecos_name = CALLER_NAME # ----- Main settings ----- domainlist dlist = *.aa.bb : ^\Nxxx(.*) +domainlist elist = +dlist : ;; +domainlist flist = <; a ; b;;c ; +elist ; 2001:630:212:8:204::b664 ; hostlist hlist = V4NET.11.12.13 : iplsearch;DIR/aux-fixed/0002.iplsearch headers_charset = iso-8859-8 diff --git a/test/scripts/0000-Basic/0002 b/test/scripts/0000-Basic/0002 index 3b485ee97..652891615 100644 --- a/test/scripts/0000-Basic/0002 +++ b/test/scripts/0000-Basic/0002 @@ -60,6 +60,21 @@ 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}}}} +listnamed: ${listnamed:dlist} +listnamed: ${listnamed:+dlist} +listnamed: ${listnamed:hlist} +listnamed: ${listnamed:elist} +listnamed: ${listnamed:flist} +listnamed: ${listnamed:nolist} +listnamed: ${listnamed_d:dlist} +listnamed: ${listnamed_d:hlist} +listnamed: ${listnamed_z:dlist} + +listcount: ${listcount:a:b:c} +listcount: ${listcount:} +listcount: ${listcount:<;a;b;c} +listcount: ${listcount:${listnamed:dlist}} + # Tests with iscntrl() and illegal separators map: ${map{<\n a\n\nb\nc}{'$item'}} diff --git a/test/stdout/0002 b/test/stdout/0002 index 2acfb63ea..de67f99fc 100644 --- a/test/stdout/0002 +++ b/test/stdout/0002 @@ -49,6 +49,21 @@ > reduce: 6 > reduce: 9 > +> listnamed: *.aa.bb : ^\Nxxx(.*) +> listnamed: *.aa.bb : ^\Nxxx(.*) +> listnamed: V4NET.11.12.13 : iplsearch;TESTSUITE/aux-fixed/0002.iplsearch +> listnamed: *.aa.bb : ^\Nxxx(.*) : ;; +> listnamed: a : b;c : *.aa.bb : ^\Nxxx(.*) : ;; : 2001::630::212::8::204::::b664 +> Failed: "nolist" is not a named list +> listnamed: *.aa.bb : ^\Nxxx(.*) +> Failed: "hlist" is not a domain named list +> Failed: bad suffix on "list" operator +> +> listcount: 3 +> listcount: 0 +> listcount: 3 +> listcount: 2 +> > # Tests with iscntrl() and illegal separators > > map: 'a' |