diff options
author | Jeremy Harris <jgh146exb@wizmail.org> | 2015-04-03 19:13:27 +0100 |
---|---|---|
committer | Jeremy Harris <jgh146exb@wizmail.org> | 2015-04-12 19:15:31 +0100 |
commit | 4e08fd50ebe820edb008a96b892a2749bbe8e72b (patch) | |
tree | 8ee90c68bac009aada01a438fe5bdc601197dcb1 /src | |
parent | 0d7911ea3aa8124490bd9272474aeba8b4a6313e (diff) |
A-label expansion operators
Diffstat (limited to 'src')
-rw-r--r-- | src/src/expand.c | 88 | ||||
-rw-r--r-- | src/src/utf8.c | 19 |
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; } |