diff --git a/midori/sokoke.c b/midori/sokoke.c index 8b409f24..8a756e6e 100644 --- a/midori/sokoke.c +++ b/midori/sokoke.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2007-2008 Christian Dywan + Copyright (C) 2007-2009 Christian Dywan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -18,12 +18,19 @@ #if HAVE_UNISTD_H #include #endif +#include #include #include #include #include +#if HAVE_LIBIDN + #include + #include + #include +#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 diff --git a/midori/wscript_build b/midori/wscript_build index cae4674f..91f53026 100644 --- a/midori/wscript_build +++ b/midori/wscript_build @@ -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 diff --git a/tests/magic-uri.c b/tests/magic-uri.c index 3fd83367..38046f73 100644 --- a/tests/magic-uri.c +++ b/tests/magic-uri.c @@ -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 c8518dda..9107e96f 100644 --- 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)