Gitweb:
https://git.exim.org/exim.git/commitdiff/48b30ae1141cbce9fe6f1153f368dd63a4505775
Commit: 48b30ae1141cbce9fe6f1153f368dd63a4505775
Parent: 0b4dfe7aa1f12214abdfa1037497d6c49a471612
Author: Jeremy Harris <jgh146exb@???>
AuthorDate: Mon Apr 6 16:20:35 2020 +0100
Committer: Jeremy Harris <jgh146exb@???>
CommitDate: Mon Apr 6 16:20:35 2020 +0100
Expansion item ${listquote }. Bug 1066
---
doc/doc-txt/NewStuff | 2 ++
src/src/expand.c | 55 ++++++++++++++++++++++++++++++--------------
test/scripts/0000-Basic/0002 | 8 +++++++
test/stdout/0002 | 8 +++++++
4 files changed, 56 insertions(+), 17 deletions(-)
diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff
index 80d3525..f922f2c 100644
--- a/doc/doc-txt/NewStuff
+++ b/doc/doc-txt/NewStuff
@@ -54,6 +54,8 @@ Version 4.94
14. Options on pgsql and mysql lookups, to specify server separate from the
lookup string.
+15. Expansion item ${listquote {<char} {<item>}}
+
Version 4.93
diff --git a/src/src/expand.c b/src/src/expand.c
index 789f099..6d9a169 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -117,6 +117,7 @@ static uschar *item_table[] = {
#endif
US"length",
US"listextract",
+ US"listquote",
US"lookup",
US"map",
US"nhash",
@@ -151,6 +152,7 @@ enum {
#endif
EITEM_LENGTH,
EITEM_LISTEXTRACT,
+ EITEM_LISTQUOTE,
EITEM_LOOKUP,
EITEM_MAP,
EITEM_NHASH,
@@ -2744,7 +2746,7 @@ switch(cond_type = identify_operator(&s, &opname))
if (*s++ != '{') goto COND_FAILED_CURLY_START; /*}*/
switch(read_subs(sub, nelem(sub), 1,
- &s, yield == NULL, TRUE, US"acl", resetok))
+ &s, yield == NULL, TRUE, name, resetok))
{
case 1: expand_string_message = US"too few arguments or bracketing "
"error for acl";
@@ -2795,7 +2797,7 @@ switch(cond_type = identify_operator(&s, &opname))
uschar *sub[4];
while (isspace(*s)) s++;
if (*s++ != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
- switch(read_subs(sub, nelem(sub), 2, &s, yield == NULL, TRUE, US"saslauthd",
+ switch(read_subs(sub, nelem(sub), 2, &s, yield == NULL, TRUE, name,
resetok))
{
case 1: expand_string_message = US"too few arguments or bracketing "
@@ -3457,7 +3459,7 @@ switch(cond_type = identify_operator(&s, &opname))
uschar cksum[4];
BOOL boolvalue = FALSE;
- switch(read_subs(sub, 2, 2, CUSS &s, yield == NULL, FALSE, US"inbound_srs", resetok))
+ switch(read_subs(sub, 2, 2, CUSS &s, yield == NULL, FALSE, name, resetok))
{
case 1: expand_string_message = US"too few arguments or bracketing "
"error for inbound_srs";
@@ -4599,7 +4601,7 @@ while (*s != 0)
uschar *user_msg;
int rc;
- switch(read_subs(sub, nelem(sub), 1, &s, skipping, TRUE, US"acl",
+ switch(read_subs(sub, nelem(sub), 1, &s, skipping, TRUE, name,
&resetok))
{
case 1: goto EXPAND_FAILED_CURLY;
@@ -4980,7 +4982,7 @@ while (*s != 0)
}
switch(read_subs(sub_arg, EXIM_PERL_MAX_ARGS + 1, 1, &s, skipping, TRUE,
- US"perl", &resetok))
+ name, &resetok))
{
case 1: goto EXPAND_FAILED_CURLY;
case 2:
@@ -5051,7 +5053,7 @@ while (*s != 0)
uschar *sub_arg[3];
uschar *p,*domain;
- switch(read_subs(sub_arg, 3, 2, &s, skipping, TRUE, US"prvs", &resetok))
+ switch(read_subs(sub_arg, 3, 2, &s, skipping, TRUE, name, &resetok))
{
case 1: goto EXPAND_FAILED_CURLY;
case 2:
@@ -5125,7 +5127,7 @@ while (*s != 0)
prvscheck_address = NULL;
prvscheck_keynum = NULL;
- switch(read_subs(sub_arg, 1, 1, &s, skipping, FALSE, US"prvs", &resetok))
+ switch(read_subs(sub_arg, 1, 1, &s, skipping, FALSE, name, &resetok))
{
case 1: goto EXPAND_FAILED_CURLY;
case 2:
@@ -5157,7 +5159,7 @@ while (*s != 0)
prvscheck_keynum = string_copy(key_num);
/* Now expand the second argument */
- switch(read_subs(sub_arg, 1, 1, &s, skipping, FALSE, US"prvs", &resetok))
+ switch(read_subs(sub_arg, 1, 1, &s, skipping, FALSE, name, &resetok))
{
case 1: goto EXPAND_FAILED_CURLY;
case 2:
@@ -5211,7 +5213,7 @@ while (*s != 0)
/* Now expand the final argument. We leave this till now so that
it can include $prvscheck_result. */
- switch(read_subs(sub_arg, 1, 0, &s, skipping, TRUE, US"prvs", &resetok))
+ switch(read_subs(sub_arg, 1, 0, &s, skipping, TRUE, name, &resetok))
{
case 1: goto EXPAND_FAILED_CURLY;
case 2:
@@ -5232,7 +5234,7 @@ while (*s != 0)
We need to make sure all subs are expanded first, so as to skip over
the entire item. */
- switch(read_subs(sub_arg, 2, 1, &s, skipping, TRUE, US"prvs", &resetok))
+ switch(read_subs(sub_arg, 2, 1, &s, skipping, TRUE, name, &resetok))
{
case 1: goto EXPAND_FAILED_CURLY;
case 2:
@@ -5255,7 +5257,7 @@ while (*s != 0)
goto EXPAND_FAILED;
}
- switch(read_subs(sub_arg, 2, 1, &s, skipping, TRUE, US"readfile", &resetok))
+ switch(read_subs(sub_arg, 2, 1, &s, skipping, TRUE, name, &resetok))
{
case 1: goto EXPAND_FAILED_CURLY;
case 2:
@@ -5305,7 +5307,7 @@ while (*s != 0)
/* Read up to 4 arguments, but don't do the end of item check afterwards,
because there may be a string for expansion on failure. */
- switch(read_subs(sub_arg, 4, 2, &s, skipping, FALSE, US"readsocket", &resetok))
+ switch(read_subs(sub_arg, 4, 2, &s, skipping, FALSE, name, &resetok))
{
case 1: goto EXPAND_FAILED_CURLY;
case 2: /* Won't occur: no end check */
@@ -5692,7 +5694,7 @@ while (*s != 0)
int o2m;
uschar *sub[3];
- switch(read_subs(sub, 3, 3, &s, skipping, TRUE, US"tr", &resetok))
+ switch(read_subs(sub, 3, 3, &s, skipping, TRUE, name, &resetok))
{
case 1: goto EXPAND_FAILED_CURLY;
case 2:
@@ -5904,7 +5906,7 @@ while (*s != 0)
int save_expand_nmax =
save_expand_strings(save_expand_nstring, save_expand_nlength);
- switch(read_subs(sub, 3, 3, &s, skipping, TRUE, US"sg", &resetok))
+ switch(read_subs(sub, 3, 3, &s, skipping, TRUE, name, &resetok))
{
case 1: goto EXPAND_FAILED_CURLY;
case 2:
@@ -6253,7 +6255,7 @@ while (*s != 0)
for (int i = 0; i < 2; i++)
{
- while (isspace(*s)) s++;
+ skip_whitespace(&s);
if (*s != '{') /*'}'*/
{
expand_string_message = string_sprintf(
@@ -6338,6 +6340,23 @@ while (*s != 0)
continue;
}
+ case EITEM_LISTQUOTE:
+ {
+ uschar * sub[2];
+ switch(read_subs(sub, 2, 2, &s, skipping, TRUE, name, &resetok))
+ {
+ case 1: goto EXPAND_FAILED_CURLY;
+ case 2:
+ case 3: goto EXPAND_FAILED;
+ }
+ for (uschar sep = *sub[0], c; c = *sub[1]; sub[1]++)
+ {
+ if (c == sep) yield = string_catn(yield, sub[1], 1);
+ yield = string_catn(yield, sub[1], 1);
+ }
+ continue;
+ }
+
#ifndef DISABLE_TLS
case EITEM_CERTEXTRACT:
{
@@ -6347,7 +6366,7 @@ while (*s != 0)
save_expand_strings(save_expand_nstring, save_expand_nlength);
/* Read the field argument */
- while (isspace(*s)) s++;
+ skip_whitespace(&s);
if (*s != '{') /*}*/
{
expand_string_message = US"missing '{' for field arg of certextract";
@@ -6825,7 +6844,7 @@ while (*s != 0)
}
switch(read_subs(argv, EXPAND_DLFUNC_MAX_ARGS + 2, 2, &s, skipping,
- TRUE, US"dlfunc", &resetok))
+ TRUE, name, &resetok))
{
case 1: goto EXPAND_FAILED_CURLY;
case 2:
@@ -7445,6 +7464,8 @@ while (*s != 0)
continue;
}
+ /* quote a list-item for the given list-separator */
+
/* 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/scripts/0000-Basic/0002 b/test/scripts/0000-Basic/0002
index 2bf8f16..db8d709 100644
--- a/test/scripts/0000-Basic/0002
+++ b/test/scripts/0000-Basic/0002
@@ -126,6 +126,14 @@ listextract: ${listextract{-5}{a:b:c:d}}
listextract: ${listextract{ 5}{a:b:c:d}{}{fail}}
listextract: ${listextract{ 5}{a:b:c:d}{}fail}
+listquote: ${listquote{:}{abcd}}
+listquote: ${listquote{:}{ab:cd}}
+listquote: ${listquote{:}{:a:b:c:d:}}
+listquote: ${listquote{:}{ab::cd}}
+listquote: ${listquote{;}{ab:cd}}
+listquote: ${listquote{;}{ab;cd}}
+listquote: ${listquote{ }{ ab cd}}
+
sort: ${sort{3:2:1:4}{<}{$item}}
sort: ${sort {<, 3,2,1,4}{>}{$item}}
sort: ${sort{c:B:a:aa}{lti}{$item}}
diff --git a/test/stdout/0002 b/test/stdout/0002
index 01e96fe..4345a09 100644
--- a/test/stdout/0002
+++ b/test/stdout/0002
@@ -115,6 +115,14 @@
> listextract: fail
> Failed: "listextract" failed and "fail" requested
>
+> listquote: abcd
+> listquote: ab::cd
+> listquote: ::a::b::c::d::
+> listquote: ab::::cd
+> listquote: ab:cd
+> listquote: ab;;cd
+> listquote: ab cd
+>
> sort: 1:2:3:4
> sort: 4,3,2,1
> sort: a:aa:B:c