From: Pietro Cerutti Date: Mon, 29 Apr 2019 11:26:36 +0000 (+0000) Subject: Do not rely on idn2 to provide an idn1 compat layer X-Git-Tag: 2019-10-25~235 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c6e4b7039cddb8f32c25f5a32928a3e32e030897;p=neomutt Do not rely on idn2 to provide an idn1 compat layer Do not rely on idn2 to provide a compat layer to idn1, as Ubuntu doesn't provide it. Instead, really code address/idna.c to use the different APIs provided by the two versions of libidn. Systems with an old version of idn2 which does not provide the needed functionality will fail at configure time now, and users of such systems will see an error message with instructions how to build with libidn1. While at it, polish a bit the auto.def sections for idn and idn2. --- diff --git a/address/idna.c b/address/idna.c index ef7861e8d..b6b06d7f4 100644 --- a/address/idna.c +++ b/address/idna.c @@ -37,8 +37,8 @@ #elif defined(HAVE_IDN_STRINGPREP_H) #include #endif +#define IDN2_SKIP_LIBIDN_COMPAT #ifdef HAVE_IDN2_H -#include #include #elif defined(HAVE_IDN_IDN2_H) #include @@ -48,6 +48,12 @@ #include #endif +#if defined(HAVE_IDN2_H) || defined(HAVE_IDN_IDN2_H) +#define IDN_VERSION 2 +#elif defined(HAVE_IDNA_H) || defined(HAVE_IDN_IDNA_H) +#define IDN_VERSION 1 +#endif + /* These Config Variables are only used in mutt/idna.c */ #ifdef HAVE_LIBIDN bool C_IdnDecode; ///< Config: (idn) Decode international domain names @@ -110,7 +116,11 @@ int mutt_idna_to_ascii_lz(const char *input, char **output, int flags) if (!input || !output) return 1; +#if IDN_VERSION == 2 + return idn2_to_ascii_8z(input, output, flags | IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL); +#else return idna_to_ascii_lz(input, output, flags); +#endif } #endif /* HAVE_LIBIDN */ @@ -145,8 +155,14 @@ char *mutt_idna_intl_to_local(const char *user, const char *domain, int flags) bool is_idn_encoded = check_idn(local_domain); if (is_idn_encoded && C_IdnDecode) { +#if IDN_VERSION == 2 + if (idn2_to_unicode_8z8z(local_domain, &tmp, IDN2_ALLOW_UNASSIGNED) != IDN2_OK) +#else if (idna_to_unicode_8z8z(local_domain, &tmp, IDNA_ALLOW_UNASSIGNED) != IDNA_SUCCESS) +#endif + { goto cleanup; + } mutt_str_replace(&local_domain, tmp); FREE(&tmp); } @@ -194,7 +210,12 @@ char *mutt_idna_intl_to_local(const char *user, const char *domain, int flags) * idna_to_ascii_8z() if the original domain was IDNA encoded. */ if (is_idn_encoded && C_IdnDecode) { +#if IDN_VERSION == 2 + if (idn2_to_ascii_8z(reversed_domain, &tmp, + IDN2_ALLOW_UNASSIGNED | IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL) != IDN2_OK) +#else if (idna_to_ascii_8z(reversed_domain, &tmp, IDNA_ALLOW_UNASSIGNED) != IDNA_SUCCESS) +#endif { mutt_debug(LL_DEBUG1, "Not reversible. idna_to_ascii_8z failed for domain = '%s'\n", reversed_domain); @@ -257,8 +278,15 @@ char *mutt_idna_local_to_intl(const char *user, const char *domain) #ifdef HAVE_LIBIDN if (C_IdnEncode) { +#if IDN_VERSION == 2 + if (idn2_to_ascii_8z(intl_domain, &tmp, + IDN2_ALLOW_UNASSIGNED | IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL) != IDN2_OK) +#else if (idna_to_ascii_8z(intl_domain, &tmp, IDNA_ALLOW_UNASSIGNED) != IDNA_SUCCESS) +#endif + { goto cleanup; + } mutt_str_replace(&intl_domain, tmp); } #endif /* HAVE_LIBIDN */ @@ -284,13 +312,15 @@ const char *mutt_idna_print_version(void) { static char vstring[256]; -#ifdef HAVE_IDN2_H +#ifdef HAVE_LIBIDN +#if IDN_VERSION == 2 snprintf(vstring, sizeof(vstring), "libidn2: %s (compiled with %s)", idn2_check_version(NULL), IDN2_VERSION); -#elif defined(HAVE_LIBIDN) +#elif IDN_VERSION == 1 snprintf(vstring, sizeof(vstring), "libidn: %s (compiled with %s)", stringprep_check_version(NULL), STRINGPREP_VERSION); #endif +#endif /* HAVE_LIBIDN */ return vstring; } diff --git a/auto.def b/auto.def index 54f432cb6..f54b05f2c 100644 --- a/auto.def +++ b/auto.def @@ -697,12 +697,9 @@ if {[get-define want-idn]} { set sprep 0 set idna 0 cc-with [list -cflags -I$idn_prefix/include -libs -L$idn_prefix/lib] { - incr sprep [cc-check-includes stringprep.h] - incr sprep [cc-check-includes idn/stringprep.h] - incr idna [cc-check-includes idna.h] - incr idna [cc-check-includes idn/idna.h] - set sprcv [cc-check-function-in-lib stringprep_check_version idn] - if {$sprep == 0 || $idna == 0 || $sprcv == 0} { + if {!([cc-check-includes stringprep.h] || [cc-check-includes idn/stringprep.h]) || + !([cc-check-includes idna.h] || [cc-check-includes idn/idna.h]) || + ![cc-check-function-in-lib stringprep_check_version idn]} { user-error "Unable to find GNU libidn" } define-feature libidn @@ -715,21 +712,19 @@ if {[get-define want-idn]} { } elseif {[get-define want-idn2]} { set idn_prefix [opt-val with-idn2 $prefix] cc-with [list -cflags -I$idn_prefix/include -libs -L$idn_prefix/lib] { - set idn2 [cc-check-includes idn2.h] - incr idn2 [cc-check-includes idn/idn2.h] - set sprcv [cc-check-function-in-lib stringprep_check_version idn] - set lu8 [cc-check-function-in-lib idn2_lookup_u8 idn2] - if {$idn2 == 0 || $lu8 == 0} { + if {!([cc-check-includes idn2.h] || [cc-check-includes idn/idn2.h])} { user-error "Unable to find GNU libidn2" } + if {![cc-check-function-in-lib idn2_to_ascii_8z idn2] || + ![cc-check-function-in-lib idn2_to_unicode_8z8z idn2] || + ![cc-check-function-in-lib idn2_check_version idn2]} { + user-error "Unable to find required functions in GNU libidn2.\ + Please consider using idn1 with './configure --idn'." + } + define-feature libidn define-append CFLAGS -I$idn_prefix/include define-append LDFLAGS -L$idn_prefix/lib - cc-with {-includes "idn2.h idn/idn2.h"} { - cc-check-defines idna_to_unicode_utf8_from_utf8 idna_to_unicode_8z8z - cc-check-defines idna_to_ascii_from_utf8 idna_to_ascii_8z - cc-check-defines idna_to_ascii_lz idna_to_ascii_from_locale - } } }