[exim-cvs] A-label transform functions

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List
Date:  
To: exim-cvs
Subject: [exim-cvs] A-label transform functions
Gitweb: http://git.exim.org/exim.git/commitdiff/0d7911ea3aa8124490bd9272474aeba8b4a6313e
Commit:     0d7911ea3aa8124490bd9272474aeba8b4a6313e
Parent:     d1a13eea59347e185a8f28764115c30dfae44136
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Sun Mar 29 11:40:35 2015 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Sun Apr 12 19:15:20 2015 +0100


    A-label transform functions
---
 TODO                              |   28 +++++++-
 doc/doc-txt/experimental-spec.txt |    1 +
 src/OS/Makefile-Base              |    3 +-
 src/scripts/MakeLinks             |    1 +
 src/src/EDITME                    |    5 ++
 src/src/functions.h               |    9 +++
 src/src/utf8.c                    |  125 +++++++++++++++++++++++++++++++++++++
 7 files changed, 167 insertions(+), 5 deletions(-)


diff --git a/TODO b/TODO
index 44aa80e..d2d31ef 100644
--- a/TODO
+++ b/TODO
@@ -14,14 +14,34 @@ destination supports the SMTPUTF8 extension

======================

-An "international" flag on the message?
-An is-international expansion condition?
+to-Alabel convert of helo name

-helo-time option handling
-dsn handling
+++ An "international" flag on the message?
+++ An is-international expansion condition?
+
+++ helo-time option handling
+conversion of utf-8 domains on input    rfc5890
+- deconversion on forwarding
+- deconversion for trace headers
+dsn handling                rfc6533
 logging
 - international msg
 - presentation of local-part in log
+-- a log option?
 encoding of local_part
 encoding transform string-expansions
 Recieved-by header tracking info
+- WITH protocol types get UTF8 prefix
+
+forwarding checks            rfc6530 7.1 -3-
+- rcpt-time rejects get 533 mailbox name not allowed
+- mail-time rejects get 550 mailbox unavailable
+- bounces (see dsn handling)
+
+
+expansions for to- and from-Alabel ?    bug1567
+
+enhanced status codes?            rfc5248++
+
+VRFY
+EXPN
diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt
index ce4edeb..0eeb939 100644
--- a/doc/doc-txt/experimental-spec.txt
+++ b/doc/doc-txt/experimental-spec.txt
@@ -1276,6 +1276,7 @@ SMTPUTF8
 Internationalised mail name handling.
 RFCs 6530, 6533, 5890


+Compile with libidn.


--------------------------------------------------------------
diff --git a/src/OS/Makefile-Base b/src/OS/Makefile-Base
index 38d7198..63646e2 100644
--- a/src/OS/Makefile-Base
+++ b/src/OS/Makefile-Base
@@ -295,7 +295,7 @@ convert4r4: Makefile ../src/convert4r4.src

OBJ_WITH_CONTENT_SCAN = malware.o mime.o regex.o spam.o spool_mbox.o
OBJ_WITH_OLD_DEMIME = demime.o
-OBJ_EXPERIMENTAL = bmi_spam.o spf.o srs.o dcc.o dmarc.o dane.o
+OBJ_EXPERIMENTAL = bmi_spam.o spf.o srs.o dcc.o dmarc.o dane.o utf8.o

 # Targets for final binaries; the main one has a build number which is
 # updated each time. We don't bother with that for the auxiliaries.
@@ -604,6 +604,7 @@ dcc.o:           $(HDRS) dcc.h dcc.c
 dmarc.o:         $(HDRS) dmarc.h dmarc.c
 spf.o:           $(HDRS) spf.h spf.c
 srs.o:           $(HDRS) srs.h srs.c
+utf8.o:         $(HDRS) utf8.c


 # The module containing tables of available lookups, routers, auths, and
 # transports must be rebuilt if any of them are. However, because the makefiles
diff --git a/src/scripts/MakeLinks b/src/scripts/MakeLinks
index f68fd6f..f9cc27c 100755
--- a/src/scripts/MakeLinks
+++ b/src/scripts/MakeLinks
@@ -276,6 +276,7 @@ ln -s ../src/dane.c            dane.c
 ln -s ../src/dane-gnu.c        dane-gnu.c
 ln -s ../src/dane-openssl.c    dane-openssl.c
 ln -s ../src/danessl.h         danessl.h
+ln -s ../src/utf8.c            utf8.c



# End of MakeLinks
diff --git a/src/src/EDITME b/src/src/EDITME
index d48f268..4260335 100644
--- a/src/src/EDITME
+++ b/src/src/EDITME
@@ -497,6 +497,11 @@ EXIM_MONITOR=eximon.bin
# Uncomment the following line to add SOCKS support
# EXPERIMENTAL_SOCKS=yes

+# Uncomment the following to add Internationalisation features. You need to
+# have the IDN library installed.
+EXPERIMENTAL_INTERNATIONAL=yes
+LDFLAGS += -lidn
+
 ###############################################################################
 #                 THESE ARE THINGS YOU MIGHT WANT TO SPECIFY                  #
 ###############################################################################
diff --git a/src/src/functions.h b/src/src/functions.h
index 7195afa..ac93c16 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -412,12 +412,21 @@ extern BOOL    string_format(uschar *, int, const char *, ...) ALMOST_PRINTF(3,4
 extern uschar *string_format_size(int, uschar *);
 extern int     string_interpret_escape(const uschar **);
 extern int     string_is_ip_address(const uschar *, int *);
+#ifdef EXPERIMENTAL_INTERNATIONAL
+extern BOOL    string_is_utf8(const uschar *);
+#endif
 extern uschar *string_log_address(address_item *, BOOL, BOOL);
 extern uschar *string_nextinlist(const uschar **, int *, uschar *, int);
 extern uschar *string_open_failed(int, const char *, ...) PRINTF_FUNCTION(2,3);
 extern const uschar *string_printing2(const uschar *, BOOL);
 extern uschar *string_split_message(uschar *);
 extern uschar *string_unprinting(uschar *);
+#ifdef EXPERIMENTAL_INTERNATIONAL
+extern uschar *string_domain_alabel_to_utf8(const uschar *, uschar **);
+extern uschar *string_domain_utf8_to_alabel(const uschar *, uschar **);
+extern uschar *string_localpart_alabel_to_utf8(const uschar *, uschar **);
+extern uschar *string_localpart_utf8_to_alabel(const uschar *, uschar **);
+#endif
 extern BOOL    string_vformat(uschar *, int, const char *, va_list);
 extern int     strcmpic(const uschar *, const uschar *);
 extern int     strncmpic(const uschar *, const uschar *, int);
diff --git a/src/src/utf8.c b/src/src/utf8.c
new file mode 100644
index 0000000..2f8173d
--- /dev/null
+++ b/src/src/utf8.c
@@ -0,0 +1,125 @@
+/*************************************************
+*     Exim - an Internet mail transport agent    *
+*************************************************/
+
+/* Copyright (c) Jeremy Harris 2015 */
+/* See the file NOTICE for conditions of use and distribution. */
+
+
+#include "exim.h"
+
+#ifdef EXPERIMENTAL_INTERNATIONAL
+
+#include <idna.h>
+#include <punycode.h>
+#include <stringprep.h>
+
+BOOL
+string_is_utf8(const uschar * s)
+{
+uschar c;
+while ((c = *s++)) if (c & 0x80) return TRUE;
+return FALSE;
+}
+
+/**************************************************/
+/* Domain conversions */
+
+uschar *
+string_domain_utf8_to_alabel(const uschar * utf8, uschar ** err)
+{
+uschar * s1;
+uschar * s;
+int rc;
+
+s = US stringprep_utf8_nfkc_normalize(CCS utf8, -1);
+if (  (rc = idna_to_ascii_8z(CCS s, CSS &s1, IDNA_USE_STD3_ASCII_RULES))
+   != IDNA_SUCCESS)
+  {
+  free(s);
+  if (err) *err = US idna_strerror(rc);
+  return NULL;
+  }
+free(s);
+s = string_copy(s1);
+free(s1);
+return s;
+}
+
+
+
+uschar *
+string_domain_alabel_to_utf8(const uschar * alabel, uschar ** err)
+{
+uschar * s1;
+uschar * s;
+int rc;
+if (  (rc = idna_to_unicode_8z8z(CCS alabel, CSS &s1, IDNA_USE_STD3_ASCII_RULES))
+   != IDNA_SUCCESS)
+  {
+  if (err) *err = US idna_strerror(rc);
+  return NULL;
+  }
+s = string_copy(s1);
+free(s1);
+return s;
+}
+
+/**************************************************/
+/* localpart conversions */
+
+
+uschar *
+string_localpart_utf8_to_alabel(const uschar * utf8, uschar ** err)
+{
+size_t ucs4_len;
+punycode_uint * p = (punycode_uint *) stringprep_utf8_to_ucs4(CCS utf8, -1, &ucs4_len);
+size_t p_len = ucs4_len*4;    /* this multiplier is pure guesswork */
+uschar * res = store_get(p_len+5);
+int 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)
+  {
+  free(p);
+  if (err) *err = US punycode_strerror(rc);
+  return NULL;
+  }
+free(p);
+res[p_len] = '\0';
+return res;
+}
+
+
+uschar *
+string_localpart_alabel_to_utf8(const uschar * alabel, uschar ** err)
+{
+size_t p_len = strlen(alabel);
+punycode_uint * p;
+int rc;
+
+if (alabel[0] != 'x' || alabel[1] != 'n' || alabel[2] != '-' || alabel[3] != '-')
+  {
+  if (err) *err = US"bad alabel prefix";
+  return NULL;
+  }
+p_len -= 4;
+
+p = (punycode_uint *) store_get((p_len+1) * sizeof(*p));
+
+if ((rc = punycode_decode(p_len, CCS alabel+4, &p_len, p, NULL)) != PUNYCODE_SUCCESS)
+  {
+  if (err) *err = US punycode_strerror(rc);
+  return NULL;
+  }
+p[p_len] = 0;
+return US p;
+}
+
+
+#endif    /* whole file */
+
+/* vi: aw ai sw=2
+*/
+/* End of utf8.c */