]> spindle.queued.net Git - midori/commitdiff
Support IDN by decoding domain names in magic_uri
authorChristian Dywan <christian@twotoasts.de>
Mon, 16 Feb 2009 23:16:14 +0000 (00:16 +0100)
committerChristian Dywan <christian@twotoasts.de>
Mon, 16 Feb 2009 23:16:14 +0000 (00:16 +0100)
midori/sokoke.c
midori/wscript_build
tests/magic-uri.c
wscript

index 8b409f244144629561fd76aa8fc1e21d4e53a844..8a756e6e16024d2ffb1862a0660129cbe1315757 100644 (file)
@@ -1,5 +1,5 @@
 /*
- Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
+ Copyright (C) 2007-2009 Christian Dywan <christian@twotoasts.de>
 
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
 #if HAVE_UNISTD_H
     #include <unistd.h>
 #endif
+#include <stdlib.h>
 #include <string.h>
 
 #include <gdk/gdkkeysyms.h>
 #include <glib/gi18n.h>
 #include <glib/gprintf.h>
 
+#if HAVE_LIBIDN
+    #include <stringprep.h>
+    #include <punycode.h>
+    #include <idna.h>
+#endif
+
 static gchar*
 sokoke_js_string_utf8 (JSStringRef js_string)
 {
@@ -120,6 +127,46 @@ sokoke_spawn_program (const gchar* command,
     return TRUE;
 }
 
+static gchar*
+sokoke_idn_to_punycode (gchar* uri)
+{
+    #if HAVE_LIBIDN
+    gchar* hostname;
+    char *s;
+    uint32_t *q;
+    int rc;
+    gchar *result;
+
+    if (g_str_has_prefix (uri, "http://"))
+        hostname = &uri[7];
+    else if (g_str_has_prefix (uri, "https://"))
+        hostname = &uri[8];
+    else
+        hostname = uri;
+
+    if (!(q = stringprep_utf8_to_ucs4 (hostname, -1, NULL)))
+        return uri;
+
+    rc = idna_to_ascii_4z (q, &s, IDNA_ALLOW_UNASSIGNED);
+    free (q);
+    if (rc != IDNA_SUCCESS)
+        return uri;
+
+    if (g_str_has_prefix (uri, "http://"))
+        result = g_strdup_printf ("http://%s", s);
+    else if (g_str_has_prefix (uri, "https://"))
+        result = g_strdup_printf ("https://%s", s);
+    else
+        result = g_strdup (s);
+    g_free (uri);
+    free (s);
+
+    return result;
+    #else
+    return uri;
+    #endif
+}
+
 gchar*
 sokoke_magic_uri (const gchar* uri,
                   KatzeArray*  search_engines)
@@ -158,7 +205,7 @@ sokoke_magic_uri (const gchar* uri,
         if (search && search[0] &&
             !g_ascii_isalpha (search[1]) && search[1] != ' ')
             if (!strchr (search, '.'))
-                return g_strconcat ("http://", uri, NULL);
+                return sokoke_idn_to_punycode (g_strconcat ("http://", uri, NULL));
         if (!strcmp (uri, "localhost") || g_str_has_prefix (uri, "localhost/"))
             return g_strconcat ("http://", uri, NULL);
         parts = g_strsplit (uri, ".", 0);
@@ -170,7 +217,7 @@ sokoke_magic_uri (const gchar* uri,
                     search = g_strconcat ("http://", uri, NULL);
             g_free (parts);
             if (search)
-                return search;
+                return sokoke_idn_to_punycode (search);
         }
         /* We don't want to search? So return early. */
         if (!search_engines)
@@ -195,7 +242,7 @@ sokoke_magic_uri (const gchar* uri,
         }
         return search;
     }
-    return g_strdup (uri);
+    return sokoke_idn_to_punycode (g_strdup (uri));
 }
 
 void
index cae4674f65d9c51bffe624eda79cbf92a4d3ff26..91f53026d0d4849d35689d7a52e34cb5a7afdb0a 100644 (file)
@@ -10,7 +10,7 @@ obj.target = 'midori'
 obj.includes = '. ..'
 obj.find_sources_in_dirs ('.', excludes=['main.c'])
 obj.add_marshal_file ('marshal.list', 'midori_cclosure_marshal')
-obj.uselib = 'UNIQUE LIBSOUP GIO GTK SQLITE WEBKIT LIBXML HILDON'
+obj.uselib = 'UNIQUE LIBSOUP LIBIDN GIO GTK SQLITE WEBKIT LIBXML HILDON'
 obj.uselib_local = 'katze'
 obj.install_path = None
 
index 3fd833679cf163bb5d00332619070df1369d9ee0..38046f731be4ea46d44081042573faa6e16a61cb 100644 (file)
@@ -94,6 +94,21 @@ main (int    argc,
     test_input ("javascript:alert(1)", "javascript:alert(1)");
     test_input ("sm warning: configure /dev/net: virtual",
                 SM "warning: configure /dev/net: virtual");
+    #if HAVE_LIBIDN
+    test_input ("http://www.münchhausen.at", "http://www.xn--mnchhausen-9db.at");
+    test_input ("http://www.خداوند.com/", "http://www.xn--mgbndb8il.com/");
+    test_input ("айкидо.com", "http://xn--80aildf0a.com");
+    test_input ("http://東京理科大学.jp", "http://xn--1lq68wkwbj6ugkpigi.jp");
+    test_input ("https://青のネコ",  "https://xn--u9jthzcs263c");
+    #else
+    test_input ("http://www.münchhausen.at", "http://www.münchhausen.at");
+    test_input ("http://www.خداوند.com/", "http://www.خداوند.com/");
+    test_input ("айкидо.com", "http://айкидо.com");
+    test_input ("http://東京理科大学.jp", "http://東京理科大学.jp");
+    test_input ("https://青のネコ.co.jp",  "https://青のネコ.co.jp");
+    #endif
+    test_input ("sm Küchenzubehör", SM "Küchenzubehör");
+    test_input ("sm 東京理科大学", SM "東京理科大学");
 
     return 0;
 }
diff --git a/wscript b/wscript
index c8518ddad08e9cec38fdd57c68a905f21db8b309..9107e96f85b653f3e9f62f1c6582cd78be236b52 100644 (file)
--- a/wscript
+++ b/wscript
@@ -134,6 +134,14 @@ def configure (conf):
     conf.define ('HAVE_LIBSOUP', [0,1][libsoup == 'yes'])
     conf.define ('HAVE_LIBSOUP_2_25_2', [0,1][libsoup_25_2 == 'yes'])
 
+    if option_enabled ('libidn'):
+        check_pkg ('libidn', '1.0', False)
+        libidn = ['N/A','yes'][conf.env['HAVE_LIBIDN'] == 1]
+    else:
+        option_checkfatal ('libidn', 'international domain names')
+        libidn = 'no '
+    conf.define ('HAVE_LIBIDN', [0,1][libidn == 'yes'])
+
     if option_enabled ('sqlite'):
         check_pkg ('sqlite3', '3.0', False, var='SQLITE')
         sqlite = ['N/A','yes'][conf.env['HAVE_SQLITE'] == 1]
@@ -238,6 +246,7 @@ def configure (conf):
                 Utils.pprint ('RED', 'WebKit was NOT built with libsoup')
     except:
         pass
+    print "IDN support:         " + libidn + " (libidn)"
     print "Persistent history:  " + sqlite + " (sqlite3)"
     print "Maemo integration:   " + hildon + " (hildon)"
 
@@ -277,6 +286,7 @@ def set_options (opt):
     group = opt.add_option_group ('Optional features', '')
     add_enable_option ('unique', 'single instance support', group)
     add_enable_option ('libsoup', 'icon and view source support', group)
+    add_enable_option ('libidn', 'international domain name support', group)
     add_enable_option ('sqlite', 'history database support', group)
     add_enable_option ('addons', 'building of extensions', group)
     add_enable_option ('hildon', 'Maemo integration', group)