summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2015-04-03 19:13:27 +0100
committerJeremy Harris <jgh146exb@wizmail.org>2015-04-12 19:15:31 +0100
commit4e08fd50ebe820edb008a96b892a2749bbe8e72b (patch)
tree8ee90c68bac009aada01a438fe5bdc601197dcb1 /src
parent0d7911ea3aa8124490bd9272474aeba8b4a6313e (diff)
A-label expansion operators
Diffstat (limited to 'src')
-rw-r--r--src/src/expand.c88
-rw-r--r--src/src/utf8.c19
2 files changed, 97 insertions, 10 deletions
diff --git a/src/src/expand.c b/src/src/expand.c
index b613ef2b4..ad97f6fef 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -168,7 +168,14 @@ static uschar *op_table_underscore[] = {
US"quote_local_part",
US"reverse_ip",
US"time_eval",
- US"time_interval"};
+ US"time_interval"
+#ifdef EXPERIMENTAL_INTERNATIONAL
+ ,US"utf8_domain_from_alabel",
+ US"utf8_domain_to_alabel",
+ US"utf8_localpart_from_alabel",
+ US"utf8_localpart_to_alabel"
+#endif
+ };
enum {
EOP_FROM_UTF8,
@@ -176,7 +183,14 @@ enum {
EOP_QUOTE_LOCAL_PART,
EOP_REVERSE_IP,
EOP_TIME_EVAL,
- EOP_TIME_INTERVAL };
+ EOP_TIME_INTERVAL
+#ifdef EXPERIMENTAL_INTERNATIONAL
+ ,EOP_UTF8_DOMAIN_FROM_ALABEL,
+ EOP_UTF8_DOMAIN_TO_ALABEL,
+ EOP_UTF8_LOCALPART_FROM_ALABEL,
+ EOP_UTF8_LOCALPART_TO_ALABEL
+#endif
+ };
static uschar *op_table_main[] = {
US"address",
@@ -6555,16 +6569,13 @@ while (*s != 0)
if (bytes_left)
{
if ((c & 0xc0) != 0x80)
- {
/* wrong continuation byte; invalidate all bytes */
complete = 1; /* error */
- }
else
{
codepoint = (codepoint << 6) | (c & 0x3f);
seq_buff[index++] = c;
if (--bytes_left == 0) /* codepoint complete */
- {
if(codepoint > 0x10FFFF) /* is it too large? */
complete = -1; /* error (RFC3629 limit) */
else
@@ -6572,7 +6583,6 @@ while (*s != 0)
yield = string_cat(yield, &size, &ptr, seq_buff, seq_len);
index = 0;
}
- }
}
}
else /* no bytes left: new sequence */
@@ -6615,13 +6625,75 @@ while (*s != 0)
yield = string_cat(yield, &size, &ptr, UTF8_REPLACEMENT_CHAR, 1);
}
if ((complete == 1) && ((c & 0x80) == 0))
- { /* ASCII character follows incomplete sequence */
+ /* ASCII character follows incomplete sequence */
yield = string_cat(yield, &size, &ptr, &c, 1);
- }
}
continue;
}
+#ifdef EXPERIMENTAL_INTERNATIONAL
+ case EOP_UTF8_DOMAIN_TO_ALABEL:
+ {
+ uschar * error = NULL;
+ uschar * s = string_domain_utf8_to_alabel(sub, &error);
+ if (error)
+ {
+ expand_string_message = string_sprintf(
+ "error converting utf8 (%s) to alabel: %s",
+ string_printing(sub), error);
+ goto EXPAND_FAILED;
+ }
+ yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
+ continue;
+ }
+
+ case EOP_UTF8_DOMAIN_FROM_ALABEL:
+ {
+ uschar * error = NULL;
+ uschar * s = string_domain_alabel_to_utf8(sub, &error);
+ if (error)
+ {
+ expand_string_message = string_sprintf(
+ "error converting alabel (%s) to utf8: %s",
+ string_printing(sub), error);
+ goto EXPAND_FAILED;
+ }
+ yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
+ continue;
+ }
+
+ case EOP_UTF8_LOCALPART_TO_ALABEL:
+ {
+ uschar * error = NULL;
+ uschar * s = string_localpart_utf8_to_alabel(sub, &error);
+ if (error)
+ {
+ expand_string_message = string_sprintf(
+ "error converting utf8 (%s) to alabel: %s",
+ string_printing(sub), error);
+ goto EXPAND_FAILED;
+ }
+ yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
+ DEBUG(D_expand) debug_printf("yield: '%s'\n", yield);
+ continue;
+ }
+
+ case EOP_UTF8_LOCALPART_FROM_ALABEL:
+ {
+ uschar * error = NULL;
+ uschar * s = string_localpart_alabel_to_utf8(sub, &error);
+ if (error)
+ {
+ expand_string_message = string_sprintf(
+ "error converting alabel (%s) to utf8: %s",
+ string_printing(sub), error);
+ goto EXPAND_FAILED;
+ }
+ yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
+ continue;
+ }
+#endif /* EXPERIMENTAL_INTERNATIONAL */
+
/* escape turns all non-printing characters into escape sequences. */
case EOP_ESCAPE:
diff --git a/src/src/utf8.c b/src/src/utf8.c
index 2f8173dc1..9a2b8656e 100644
--- a/src/src/utf8.c
+++ b/src/src/utf8.c
@@ -78,14 +78,22 @@ size_t p_len = ucs4_len*4; /* this multiplier is pure guesswork */
uschar * res = store_get(p_len+5);
int rc;
+DEBUG(D_expand) debug_printf("l_u2a: ulen %d plen %d\n", ucs4_len, p_len);
+DEBUG(D_expand) for (rc = 0; rc < ucs4_len; rc++) debug_printf("%08x ", p[rc]);
+
res[0] = 'x'; res[1] = 'n'; res[2] = res[3] = '-';
if ((rc = punycode_encode(ucs4_len, p, NULL, &p_len, res+4)) != PUNYCODE_SUCCESS)
{
+ DEBUG(D_expand) debug_printf("l_u2a: bad '%s'\n", punycode_strerror(rc));
free(p);
if (err) *err = US punycode_strerror(rc);
return NULL;
}
+DEBUG(D_expand) debug_printf("l_u2a: plen %d\n", p_len);
+p_len += 4;
+DEBUG(D_expand) for (rc = 0; rc < p_len; rc++) debug_printf("%02x ", res[rc]);
+DEBUG(D_expand) debug_printf("\n");
free(p);
res[p_len] = '\0';
return res;
@@ -97,6 +105,8 @@ string_localpart_alabel_to_utf8(const uschar * alabel, uschar ** err)
{
size_t p_len = strlen(alabel);
punycode_uint * p;
+uschar * s;
+uschar * res;
int rc;
if (alabel[0] != 'x' || alabel[1] != 'n' || alabel[2] != '-' || alabel[3] != '-')
@@ -105,6 +115,7 @@ if (alabel[0] != 'x' || alabel[1] != 'n' || alabel[2] != '-' || alabel[3] != '-'
return NULL;
}
p_len -= 4;
+DEBUG(D_expand) debug_printf("l_a2u: plen %d\n", p_len);
p = (punycode_uint *) store_get((p_len+1) * sizeof(*p));
@@ -113,8 +124,12 @@ if ((rc = punycode_decode(p_len, CCS alabel+4, &p_len, p, NULL)) != PUNYCODE_SUC
if (err) *err = US punycode_strerror(rc);
return NULL;
}
-p[p_len] = 0;
-return US p;
+DEBUG(D_expand) debug_printf("l_a2u: dlen %d\n", p_len);
+
+s = stringprep_ucs4_to_utf8(p, p_len, NULL, &p_len);
+res = string_copyn(s, p_len);
+free(s);
+return res;
}