From 9f5d6b1e9dd9c275bd0ff4adb49ad2821a141c15 Mon Sep 17 00:00:00 2001 From: Tim Ruehsen Date: Thu, 19 Jun 2014 13:15:31 +0200 Subject: [PATCH] added idn2 punycode generation as fallback for missing libicu --- configure.ac | 7 ++++++- src/psl2c.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 0b0527d..ca49b20 100644 --- a/configure.ac +++ b/configure.ac @@ -81,7 +81,7 @@ AC_ARG_WITH(libicu, [[#include ]], [[u_strToUTF8(NULL, 0, NULL, NULL, 0, NULL);]])], [HAVE_LIBICU=yes; AC_MSG_RESULT([yes]) AC_DEFINE([WITH_LIBICU], [1], [generate PSL data with IDNA2008 UTS#46 punycode])], - [LIBS=$OLDLIBS; AC_MSG_WARN([no working ICU unicode library was found])]) + [LIBS=$OLDLIBS; AC_MSG_ERROR([no working ICU unicode library was found])]) # AC_SEARCH_LIBS(uidna_close, icuuc, # [HAVE_LIBICU=yes; AC_DEFINE([WITH_LIBICU], [1], [generate PSL data with IDNA2008 UTS#46 punycode])], @@ -99,6 +99,11 @@ AC_ARG_ENABLE(builtin, ], [ enable_builtin=yes AC_DEFINE([WITH_BUILTIN], [1], [compile PSL data into library]) + AS_IF([test $HAVE_LIBICU != yes], + [ + # Check for idn2 fallback to generate punycode + AC_CHECK_PROG(HAVE_IDN2, idn2, yes, AC_MSG_ERROR(Cannot find required tool 'idn2' as fallback.)) + ]) ]) AM_CONDITIONAL([WITH_BUILTIN], [test $enable_builtin = yes]) diff --git a/src/psl2c.c b/src/psl2c.c index a270307..8ec4a3c 100644 --- a/src/psl2c.c +++ b/src/psl2c.c @@ -65,7 +65,7 @@ static void _print_psl_entries(FILE *fpout, const _psl_vector_t *v, const char * } while (0); #else fprintf(fpout, "/* automatically generated by psl2c (without punycode support) */\n"); -#endif +#endif /* WITH_LIBICU */ fprintf(fpout, "static _psl_entry_t %s[] = {\n", varname); @@ -79,6 +79,48 @@ static void _print_psl_entries(FILE *fpout, const _psl_vector_t *v, const char * fprintf(fpout, "};\n"); } +#ifndef WITH_LIBICU +static int _str_needs_encoding(const char *s) +{ + while (*s > 0) s++; + + return !!*s; +} + +static void _add_punycode_if_needed(_psl_vector_t *v) +{ + int it, n; + + /* do not use 'it < v->cur' since v->cur is changed by _vector_add() ! */ + for (it = 0, n = v->cur; it < n; it++) { + _psl_entry_t *e = _vector_get(v, it); + + if (_str_needs_encoding(e->label_buf)) { + _psl_entry_t suffix, *suffixp; + char lookupname[64] = ""; + + /* this is much slower than the libidn2 API but should have no license issues */ + FILE *pp; + char cmd[16 + sizeof(e->label_buf)]; + snprintf(cmd, sizeof(cmd), "idn2 '%s'", e->label_buf); + if ((pp = popen(cmd, "r"))) { + if (fscanf(pp, "%63s", lookupname) >= 1 && strcmp(e->label_buf, lookupname)) { + /* fprintf(stderr, "idn2 '%s' -> '%s'\n", e->label_buf, lookupname); */ + _suffix_init(&suffix, lookupname, strlen(lookupname)); + suffix.wildcard = e->wildcard; + suffixp = _vector_get(v, _vector_add(v, &suffix)); + suffixp->label = suffixp->label_buf; /* set label to changed address */ + } + pclose(pp); + } else + fprintf(stderr, "Failed to call popen(%s, \"r\")\n", cmd); + } + } + + _vector_sort(v); +} +#endif /* ! WITH_LIBICU */ + #endif /* WITH_BUILTIN */ int main(int argc, const char **argv) @@ -106,6 +148,13 @@ int main(int argc, const char **argv) size_t cmdsize = 16 + strlen(argv[1]); char *cmd = alloca(cmdsize), checksum[64] = ""; +#ifndef WITH_LIBICU + /* If libicu is not configured, we still need to have punycode in our built-in data. */ + /* Else the test suite fails. */ + _add_punycode_if_needed(psl->suffixes); + _add_punycode_if_needed(psl->suffix_exceptions); +#endif + _print_psl_entries(fpout, psl->suffixes, "suffixes"); _print_psl_entries(fpout, psl->suffix_exceptions, "suffix_exceptions");