summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/doc-docbook/spec.xfpt15
-rw-r--r--doc/doc-txt/NewStuff2
-rw-r--r--src/src/expand.c48
-rw-r--r--test/scripts/0000-Basic/000214
-rw-r--r--test/stdout/000214
5 files changed, 93 insertions, 0 deletions
diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index d3307eacd..d08a7a040 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -10090,6 +10090,21 @@ Last:user@example.com
user@example.com
.endd
+.new
+.vitem &*${base32:*&<&'digits'&>&*}*&
+.cindex "&%base32%& expansion item"
+.cindex "expansion" "conversion to base 32"
+The string must consist entirely of decimal digits. The number is converted to
+base 32 and output as a (empty, for zero) string of characters.
+Only lowercase letters are used.
+
+.vitem &*${base32d:*&<&'base-32&~digits'&>&*}*&
+.cindex "&%base32d%& expansion item"
+.cindex "expansion" "conversion to base 32"
+The string must consist entirely of base-32 digits.
+The number is converted to decimal and output as a string.
+.wen
+
.vitem &*${base62:*&<&'digits'&>&*}*&
.cindex "&%base62%& expansion item"
.cindex "expansion" "conversion to base 62"
diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff
index 2a776b730..587dc6508 100644
--- a/doc/doc-txt/NewStuff
+++ b/doc/doc-txt/NewStuff
@@ -26,6 +26,8 @@ Version 4.88
the queue to be used for a message. A $queue_name variable gives
visibility.
+ 6. New expansion operators base32/base32d.
+
Version 4.87
------------
diff --git a/src/src/expand.c b/src/src/expand.c
index 2c23f13e4..10874add3 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -199,6 +199,8 @@ enum {
static uschar *op_table_main[] = {
US"address",
US"addresses",
+ US"base32",
+ US"base32d",
US"base62",
US"base62d",
US"base64",
@@ -242,6 +244,8 @@ static uschar *op_table_main[] = {
enum {
EOP_ADDRESS = nelem(op_table_underscore),
EOP_ADDRESSES,
+ EOP_BASE32,
+ EOP_BASE32D,
EOP_BASE62,
EOP_BASE62D,
EOP_BASE64,
@@ -838,6 +842,9 @@ static int utf8_table2[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
}
+
+static uschar * base32_chars = US"abcdefghijklmnopqrstuvwxyz234567";
+
/*************************************************
* Binary chop search on a table *
*************************************************/
@@ -6257,6 +6264,47 @@ while (*s != 0)
switch(c)
{
+ case EOP_BASE32:
+ {
+ uschar *t;
+ unsigned long int n = Ustrtoul(sub, &t, 10);
+ uschar * s = NULL;
+ int sz = 0, i = 0;
+
+ if (*t != 0)
+ {
+ expand_string_message = string_sprintf("argument for base32 "
+ "operator is \"%s\", which is not a decimal number", sub);
+ goto EXPAND_FAILED;
+ }
+ for ( ; n; n >>= 5)
+ s = string_catn(s, &sz, &i, &base32_chars[n & 0x1f], 1);
+
+ while (i > 0) yield = string_catn(yield, &size, &ptr, &s[--i], 1);
+ continue;
+ }
+
+ case EOP_BASE32D:
+ {
+ uschar *tt = sub;
+ unsigned long int n = 0;
+ uschar * s;
+ while (*tt)
+ {
+ uschar * t = Ustrchr(base32_chars, *tt++);
+ if (t == NULL)
+ {
+ expand_string_message = string_sprintf("argument for base32d "
+ "operator is \"%s\", which is not a base 32 number", sub);
+ goto EXPAND_FAILED;
+ }
+ n = n * 32 + (t - base32_chars);
+ }
+ s = string_sprintf("%ld", n);
+ yield = string_cat(yield, &size, &ptr, s);
+ continue;
+ }
+
case EOP_BASE62:
{
uschar *t;
diff --git a/test/scripts/0000-Basic/0002 b/test/scripts/0000-Basic/0002
index 278a38660..dafcba7f0 100644
--- a/test/scripts/0000-Basic/0002
+++ b/test/scripts/0000-Basic/0002
@@ -179,6 +179,20 @@ hex2b64:${hex2b64:1a2b3c4d5e6g}
hex2b64:${hex2b64:${md5:the quick brown fox}}
hex2b64:${hex2b64:${sha1:the quick brown fox}}
+base32: 0 <${base32:0}>
+base32: 1 <${base32:1}>
+base32: 31 <${base32:31}>
+base32: 32 <${base32:32}>
+base32: 42 <${base32:42}>
+base32 error: 0x1 ${base32:0x1}
+
+base32d: 0 ${base32d:${base32:0}}
+base32d: 1 ${base32d:${base32:1}}
+base32d: 31 ${base32d:${base32:31}}
+base32d: 32 ${base32d:${base32:32}}
+base32d: 42 ${base32d:${base32:42}}
+base32d error: ABC ${base32d:ABC}
+
The base62 operator is actually a base36 operator in the Darwin and Cygwin
environments. Write cunning tests that produce the same output in both cases,
while doing a reasonable check.
diff --git a/test/stdout/0002 b/test/stdout/0002
index 0bbd4c754..a19cc526c 100644
--- a/test/stdout/0002
+++ b/test/stdout/0002
@@ -169,6 +169,20 @@
> hex2b64:MPPJPkZDbetYunCBao7BJA==
> hex2b64:ztcfpyNSMb7Tg/rP3EHE3cwi7PE=
>
+> base32: 0 <>
+> base32: 1 <b>
+> base32: 31 <7>
+> base32: 32 <ba>
+> base32: 42 <bk>
+> Failed: argument for base32 operator is "0x1", which is not a decimal number
+>
+> base32d: 0 0
+> base32d: 1 1
+> base32d: 31 31
+> base32d: 32 32
+> base32d: 42 42
+> Failed: argument for base32d operator is "ABC", which is not a base 32 number
+>
> The base62 operator is actually a base36 operator in the Darwin and Cygwin
> environments. Write cunning tests that produce the same output in both cases,
> while doing a reasonable check.