From 13a2f6144c51c0451b20056bf92cbd0b2f338f1e Mon Sep 17 00:00:00 2001 From: Matej Muzila Date: Mon, 9 Apr 2018 13:46:42 +0200 Subject: [PATCH] Add libidn2 support --- configure.ac | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ doc/makedoc-defs.h | 3 +++ init.h | 4 ++-- main.c | 13 ++++++++++++- mutt.h | 2 +- mutt_idna.c | 20 ++++++++++---------- mutt_idna.h | 8 ++++++-- mutt_socket.c | 8 ++++---- mutt_ssl.c | 2 +- 9 files changed, 94 insertions(+), 21 deletions(-) diff --git a/configure.ac b/configure.ac index c46f72b0..5c6de33c 100644 --- a/configure.ac +++ b/configure.ac @@ -1293,6 +1293,25 @@ AC_ARG_WITH(idn, AS_HELP_STRING([--with-idn=@<:@PFX@:>@],[Use GNU libidn for int ], [with_idn=auto]) +AC_ARG_WITH(idn2, AS_HELP_STRING([--with-idn2=@<:@PFX@:>@],[Use GNU libidn2 for internationalized domain names]), + [ + if test "$with_idn2" != "no" ; then + if test "$with_idn" = "auto"; then + with_idn="no" + fi + + if test "$with_idn" != "no"; then + AC_MSG_ERROR([Cannot enable IDN and IDN2 support at the same time]) + fi + + if test "$with_idn2" != "yes" ; then + CPPFLAGS="$CPPFLAGS -I$with_idn2/include" + LDFLAGS="$LDFLAGS -L$with_idn2/lib" + fi + fi + ], + [with_idn2=no]) + if test "x$with_idn" != "xno"; then if test "$am_cv_func_iconv" != "yes"; then if test "$with_idn" != "auto"; then @@ -1332,6 +1351,42 @@ if test "x$with_idn" != "xno"; then fi fi +dnl idna2 +if test "x$with_idn2" != "xno"; then + if test "$am_cv_func_iconv" != "yes"; then + if test "$with_idn2" != "auto"; then + AC_MSG_ERROR([IDN2 requested but iconv is disabled or unavailable]) + fi + else + dnl Solaris 11 has /usr/include/idn + have_idn2_h=no + AC_CHECK_HEADERS([idn2.h idn/idn2.h], [ + have_idn2_h=yes + break]) + + mutt_save_LIBS="$LIBS" + LIBS= + + AC_SEARCH_LIBS([idn2_check_version], [idn2], [ + AC_DEFINE([HAVE_LIBIDN2], 1, [Define to 1 if you have the GNU idn2 library]) + MUTTLIBS="$MUTTLIBS $LIBS" + + LIBS="$LIBS $LIBICONV" + AC_DEFINE([HAVE_IDNA_TO_UNICODE_8Z8Z]) + AC_DEFINE([HAVE_IDNA_TO_ASCII_8Z]) + AC_DEFINE([HAVE_IDNA_TO_ASCII_LZ]) + ]) + + LIBS="$mutt_save_LIBS" + + if test "$with_idn2" != "no"; then + if test "$have_idn2_h" = "no" || test "$ac_cv_search_idn2_check_version" = "no"; then + AC_MSG_ERROR([IDN2 was requested, but libidn2 was not usable on this system]) + fi + fi + fi +fi + dnl -- locales -- AC_CHECK_HEADERS(wchar.h) diff --git a/doc/makedoc-defs.h b/doc/makedoc-defs.h index 2da29f48..78a4ebc0 100644 --- a/doc/makedoc-defs.h +++ b/doc/makedoc-defs.h @@ -52,6 +52,9 @@ # ifndef HAVE_LIBIDN # define HAVE_LIBIDN # endif +# ifndef HAVE_LIBIDN2 +# define HAVE_LIBIDN2 +# endif # ifndef HAVE_GETADDRINFO # define HAVE_GETADDRINFO # endif diff --git a/init.h b/init.h index bdd22543..5e79786c 100644 --- a/init.h +++ b/init.h @@ -1177,7 +1177,7 @@ struct option_t MuttVars[] = { ** .pp ** Also see $$use_domain and $$hidden_host. */ -#ifdef HAVE_LIBIDN +#if defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) { "idn_decode", DT_BOOL, R_MENU, OPTIDNDECODE, 1}, /* ** .pp @@ -1192,7 +1192,7 @@ struct option_t MuttVars[] = { ** IDN. Unset this if your SMTP server can handle newer (RFC 6531) ** UTF-8 encoded domains. (IDN only) */ -#endif /* HAVE_LIBIDN */ +#endif /* defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) */ { "ignore_linear_white_space", DT_BOOL, R_NONE, OPTIGNORELWS, 0 }, /* ** .pp diff --git a/main.c b/main.c index b189c860..0d2dbac4 100644 --- a/main.c +++ b/main.c @@ -218,6 +218,11 @@ static void show_version (void) STRINGPREP_VERSION); #endif +#ifdef HAVE_LIBIDN2 + printf ("\nlibidn2: %s (compiled with %s)", idn2_check_version (NULL), + IDN2_VERSION); +#endif + #ifdef USE_HCACHE printf ("\nhcache backend: %s", mutt_hcache_backend ()); #endif @@ -485,7 +490,13 @@ static void show_version (void) #else "-HAVE_LIBIDN " #endif - + +#if HAVE_LIBIDN2 + "+HAVE_LIBIDN2 " +#else + "-HAVE_LIBIDN2 " +#endif + #if HAVE_GETSID "+HAVE_GETSID " #else diff --git a/mutt.h b/mutt.h index 4fe7ce49..7372a510 100644 --- a/mutt.h +++ b/mutt.h @@ -492,7 +492,7 @@ enum OPTUSEDOMAIN, OPTUSEFROM, OPTUSEGPGAGENT, -#ifdef HAVE_LIBIDN +#if defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) OPTIDNDECODE, OPTIDNENCODE, #endif diff --git a/mutt_idna.c b/mutt_idna.c index a059e867..cb231b5a 100644 --- a/mutt_idna.c +++ b/mutt_idna.c @@ -24,7 +24,7 @@ #include "charset.h" #include "mutt_idna.h" -#ifdef HAVE_LIBIDN +#if defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) static int check_idn (char *domain) { if (! domain) @@ -41,7 +41,7 @@ static int check_idn (char *domain) return 0; } -#endif /* HAVE_LIBIDN */ +#endif /* defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) */ static int mbox_to_udomain (const char *mbx, char **user, char **domain) { @@ -90,14 +90,14 @@ static char *intl_to_local (char *orig_user, char *orig_domain, int flags) char *local_user = NULL, *local_domain = NULL, *mailbox = NULL; char *reversed_user = NULL, *reversed_domain = NULL; char *tmp = NULL; -#ifdef HAVE_LIBIDN +#if defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) int is_idn_encoded = 0; -#endif /* HAVE_LIBIDN */ +#endif /* defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) */ local_user = safe_strdup (orig_user); local_domain = safe_strdup (orig_domain); -#ifdef HAVE_LIBIDN +#if defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) is_idn_encoded = check_idn (local_domain); if (is_idn_encoded && option (OPTIDNDECODE)) { @@ -106,7 +106,7 @@ static char *intl_to_local (char *orig_user, char *orig_domain, int flags) mutt_str_replace (&local_domain, tmp); FREE (&tmp); } -#endif /* HAVE_LIBIDN */ +#endif /* defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) */ /* we don't want charset-hook effects, so we set flags to 0 */ if (mutt_convert_string (&local_user, "utf-8", Charset, 0) == -1) @@ -148,7 +148,7 @@ static char *intl_to_local (char *orig_user, char *orig_domain, int flags) goto cleanup; } -#ifdef HAVE_LIBIDN +#if defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) /* If the original domain was UTF-8, idna encoding here could * produce a non-matching domain! Thus we only want to do the * idna_to_ascii_8z() if the original domain was IDNA encoded. @@ -164,7 +164,7 @@ static char *intl_to_local (char *orig_user, char *orig_domain, int flags) } mutt_str_replace (&reversed_domain, tmp); } -#endif /* HAVE_LIBIDN */ +#endif /* defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) */ if (ascii_strcasecmp (orig_domain, reversed_domain)) { @@ -203,14 +203,14 @@ static char *local_to_intl (char *user, char *domain) if (mutt_convert_string (&intl_domain, Charset, "utf-8", 0) == -1) goto cleanup; -#ifdef HAVE_LIBIDN +#if defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) if (option (OPTIDNENCODE)) { if (idna_to_ascii_8z (intl_domain, &tmp, IDNA_ALLOW_UNASSIGNED) != IDNA_SUCCESS) goto cleanup; mutt_str_replace (&intl_domain, tmp); } -#endif /* HAVE_LIBIDN */ +#endif /* defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) */ mailbox = safe_malloc (mutt_strlen (intl_user) + mutt_strlen (intl_domain) + 2); sprintf (mailbox, "%s@%s", NONULL(intl_user), NONULL(intl_domain)); /* __SPRINTF_CHECKED__ */ diff --git a/mutt_idna.h b/mutt_idna.h index 192e08db..62e6e301 100644 --- a/mutt_idna.h +++ b/mutt_idna.h @@ -26,13 +26,17 @@ #include #elif defined(HAVE_IDN_IDNA_H) #include +#elif defined(HAVE_IDN2_H) +#include +#elif defined(HAVE_IDN_IDN2_H) +#include #endif #define MI_MAY_BE_IRREVERSIBLE (1 << 0) /* Work around incompatibilities in the libidn API */ -#ifdef HAVE_LIBIDN +#if defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) # if (!defined(HAVE_IDNA_TO_ASCII_8Z) && defined(HAVE_IDNA_TO_ASCII_FROM_UTF8)) # define idna_to_ascii_8z(a,b,c) idna_to_ascii_from_utf8(a,b,(c)&1,((c)&2)?1:0) # endif @@ -42,7 +46,7 @@ # if (!defined(HAVE_IDNA_TO_UNICODE_8Z8Z) && defined(HAVE_IDNA_TO_UNICODE_UTF8_FROM_UTF8)) # define idna_to_unicode_8z8z(a,b,c) idna_to_unicode_utf8_from_utf8(a,b,(c)&1,((c)&2)?1:0) # endif -#endif /* HAVE_LIBIDN */ +#endif /* defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) */ #ifdef HAVE_ICONV diff --git a/mutt_socket.c b/mutt_socket.c index 16e52dce..dc845865 100644 --- a/mutt_socket.c +++ b/mutt_socket.c @@ -499,7 +499,7 @@ int raw_socket_open (CONNECTION* conn) snprintf (port, sizeof (port), "%d", conn->account.port); -# ifdef HAVE_LIBIDN +# if defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) if (idna_to_ascii_lz (conn->account.host, &host_idna, 1) != IDNA_SUCCESS) { mutt_error (_("Bad IDN \"%s\"."), conn->account.host); @@ -514,7 +514,7 @@ int raw_socket_open (CONNECTION* conn) rc = getaddrinfo (host_idna, port, &hints, &res); -# ifdef HAVE_LIBIDN +# if defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) FREE (&host_idna); # endif @@ -558,7 +558,7 @@ int raw_socket_open (CONNECTION* conn) sin.sin_port = htons (conn->account.port); sin.sin_family = AF_INET; -# ifdef HAVE_LIBIDN +# if defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) if (idna_to_ascii_lz (conn->account.host, &host_idna, 1) != IDNA_SUCCESS) { mutt_error (_("Bad IDN \"%s\"."), conn->account.host); @@ -573,7 +573,7 @@ int raw_socket_open (CONNECTION* conn) he = gethostbyname (host_idna); -# ifdef HAVE_LIBIDN +# if defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) FREE (&host_idna); # endif diff --git a/mutt_ssl.c b/mutt_ssl.c index eacd1556..3467b618 100644 --- a/mutt_ssl.c +++ b/mutt_ssl.c @@ -935,7 +935,7 @@ static int check_host (X509 *x509cert, const char *hostname, char *err, size_t e /* Check if 'hostname' matches the one of the subjectAltName extensions of * type DNS or the Common Name (CN). */ -#ifdef HAVE_LIBIDN +#if defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) if (idna_to_ascii_lz(hostname, &hostname_ascii, 0) != IDNA_SUCCESS) { hostname_ascii = safe_strdup(hostname); -- 2.13.6