]> git.sesse.net Git - vlc/commitdiff
vlc_UrlParse: support for Internationalized Domain Names (fixes #7343)
authorRémi Denis-Courmont <remi@remlab.net>
Mon, 20 Aug 2012 20:24:08 +0000 (23:24 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Mon, 20 Aug 2012 20:24:08 +0000 (23:24 +0300)
src/Makefile.am
src/text/url.c

index 4b12e6e3a22a05563cf75ab13656912bf180098e..da40d004edddc80533199b7d6141212742568995 100644 (file)
@@ -164,7 +164,7 @@ EXTRA_DIST += libvlc_win32_rc.rc.in
 
 lib_LTLIBRARIES = libvlccore.la
 
-AM_CPPFLAGS = $(INCICONV) \
+AM_CPPFLAGS = $(INCICONV) $(IDN_CFLAGS) \
        -DMODULE_STRING=\"main\" \
        -DLOCALEDIR=\"$(localedir)\" \
        -DSYSCONFDIR=\"$(sysconfdir)\" \
@@ -182,7 +182,7 @@ libvlccore_la_LDFLAGS = \
 libvlccore_la_LIBADD = $(LIBS_libvlccore) \
        ../compat/libcompat.la \
        $(LTLIBINTL) $(LTLIBICONV) \
-       $(SOCKET_LIBS) $(LIBDL) $(LIBM)
+       $(IDN_LIBS) $(SOCKET_LIBS) $(LIBDL) $(LIBM)
 libvlccore_la_DEPENDENCIES = libvlccore.sym
 if HAVE_WIN32
 libvlccore_la_DEPENDENCIES += libvlc_win32_rc.$(OBJEXT)
index fa9d86bcd688caa3c7a7945d7382c768285b8647..021613f59ef935a436ffc452d99f179b2e96d2fe 100644 (file)
@@ -370,6 +370,8 @@ out:
     return ret; /* unknown scheme */
 }
 
+static char *vlc_idna_to_ascii (const char *);
+
 /**
  * Splits an URL into parts.
  * \param url structure of URL parts [OUT]
@@ -459,7 +461,7 @@ void vlc_UrlParse (vlc_url_t *restrict url, const char *str, unsigned char opt)
     }
     else
     {
-        url->psz_host = strdup (cur);
+        url->psz_host = vlc_idna_to_ascii (cur);
         next = strchr (cur, ':');
     }
 
@@ -482,3 +484,62 @@ void vlc_UrlClean (vlc_url_t *restrict url)
     free (url->psz_host);
     free (url->psz_buffer);
 }
+
+#if defined (HAVE_IDN)
+# include <idna.h>
+#elif defined (WIN32)
+# include <windows.h>
+# include <vlc_charset.h>
+#endif
+
+/**
+ * Converts a UTF-8 nul-terminated IDN to nul-terminated ASCII domain name.
+ * \param idn UTF-8 Internationalized Domain Name to convert
+ * \return a heap-allocated string or NULL on error.
+ */
+static char *vlc_idna_to_ascii (const char *idn)
+{
+#if defined (HAVE_IDN)
+    char *adn;
+
+    if (idna_to_ascii_8z (idn, &adn, IDNA_ALLOW_UNASSIGNED) != IDNA_SUCCESS)
+        return NULL;
+    return adn;
+
+#elif defined (WIN32) && (_WIN32_WINNT >= 0x0601)
+    char *ret = NULL;
+
+    wchar_t *wide = ToWide (idn);
+    if (wide == NULL)
+        return NULL;
+
+    int len = IdnToAscii (IDN_ALLOW_UNASSIGNED, wide, -1, NULL, 0);
+    if (len == 0)
+        goto error;
+
+    wchar_t *buf = malloc (sizeof (*buf) * len);
+    if (unlikely(buf == NULL))
+        goto error;
+    if (!IdnToAscii (IDN_ALLOW_UNASSIGNED, wide, -1, buf, len))
+    {
+        free (buf);
+        goto error;
+    }
+    free (wide);
+
+    ret = FromWide (buf);
+    free (buf);
+error:
+    free (wide);
+    return ret;
+
+#else
+    /* No IDN support, filter out non-ASCII domain names */
+    for (const char *p = idn; *p; p++)
+        if (((unsigned char)*p) >= 0x80)
+            return NULL;
+
+    return strdup (idn);
+
+#endif
+}