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 /src | |
parent | d7148a072a5fee80ffa8d1aeebf9bc05d0e903b4 (diff) | |
parent | a64a3dfa73b829669d838c8d129b0974360b95a5 (diff) |
Merge branch 'lists'
Diffstat (limited to 'src')
-rw-r--r-- | src/src/expand.c | 105 |
1 files changed, 105 insertions, 0 deletions
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. */ |