[vlc-commits] vlc_UrlParse: support for Internationalized Domain Names (fixes #7343)

Rémi Denis-Courmont git at videolan.org
Mon Aug 20 22:24:59 CEST 2012


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Mon Aug 20 23:24:08 2012 +0300| [6ae9dc2d0d59ac332e170f228ecd908e5b5e106b] | committer: Rémi Denis-Courmont

vlc_UrlParse: support for Internationalized Domain Names (fixes #7343)

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=6ae9dc2d0d59ac332e170f228ecd908e5b5e106b
---

 src/Makefile.am |    4 ++--
 src/text/url.c  |   63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index 4b12e6e..da40d00 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -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)
diff --git a/src/text/url.c b/src/text/url.c
index fa9d86b..021613f 100644
--- a/src/text/url.c
+++ b/src/text/url.c
@@ -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
+}



More information about the vlc-commits mailing list