From: Christian Dywan Date: Sat, 10 Oct 2009 09:09:10 +0000 (+0200) Subject: Refactor IDN handling and related unit tests X-Git-Url: https://spindle.queued.net/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b9d4266d27914c36681a25ca2835bd6546fa81f2;p=midori Refactor IDN handling and related unit tests Most code is shared despite different available libraries now and can more effeciently be tested. --- diff --git a/midori/main.c b/midori/main.c index a8400f39..86cfd012 100644 --- a/midori/main.c +++ b/midori/main.c @@ -1776,22 +1776,8 @@ main (int argc, i = 0; while (uris[i] != NULL) { - #ifdef HAVE_LIBSOUP_2_27_90 - gchar* path; - gchar* hostname = sokoke_hostname_from_uri (uris[i], &path); - gchar* encoded = g_hostname_to_ascii (hostname); - - if (encoded) - { - gchar* res = g_strconcat ("http://", encoded, path, NULL); - g_free (uris[i]); - g_free (encoded); - uris[i] = res; - } - g_free (hostname); - #else - uris[i] = sokoke_idn_to_punycode (uris[i]); - #endif + gchar* new_uri = sokoke_uri_to_ascii (uris[i]); + katze_assign (uris[i], new_uri); i++; } result = midori_app_instance_send_uris (app, uris); diff --git a/midori/sokoke.c b/midori/sokoke.c index 1b986ca2..b2f4b59a 100644 --- a/midori/sokoke.c +++ b/midori/sokoke.c @@ -185,7 +185,6 @@ sokoke_spawn_program (const gchar* command, return TRUE; } -#if defined (HAVE_LIBSOUP_2_27_90) || HAVE_LIBIDN /** * sokoke_hostname_from_uri: * @uri: an URI string @@ -222,79 +221,88 @@ sokoke_hostname_from_uri (const gchar* uri, hostname = g_strdup (uri); return hostname; } -#endif /** - * sokoke_idn_to_punycode: + * sokoke_hostname_to_ascii: + * @uri: an URI string + * + * The specified hostname is encoded if it is not ASCII. + * + * If no IDN support is available at compile time, + * the hostname will be returned unaltered. + * + * Return value: a newly allocated hostname + **/ +static gchar* +sokoke_hostname_to_ascii (const gchar* hostname) +{ + #ifdef HAVE_LIBSOUP_2_27_90 + return g_hostname_to_ascii (hostname); + #elif HAVE_LIBIDN + uint32_t* q; + char* encoded; + int rc; + + if ((q = stringprep_utf8_to_ucs4 (hostname, -1, NULL))) + { + rc = idna_to_ascii_4z (q, &encoded, IDNA_ALLOW_UNASSIGNED); + free (q); + if (rc == IDNA_SUCCESS) + return encoded; + } + #endif + return g_strdup (hostname); +} + +/** + * sokoke_uri_to_ascii: * @uri: an URI string * * The specified URI is parsed and the hostname * part of it is encoded if it is not ASCII. * - * If libIDN is not available at compile time, - * this code will pass the string unaltered. - * - * The called function owns the passed string. + * If no IDN support is available at compile time, + * the URI will be returned unaltered. * - * Return value: a newly allocated ASCII URI + * Return value: a newly allocated URI **/ gchar* -sokoke_idn_to_punycode (gchar* uri) +sokoke_uri_to_ascii (const gchar* uri) { - #if HAVE_LIBIDN gchar* proto; - gchar* hostname; - gchar* path; - char *s; - uint32_t *q; - int rc; - gchar *result; if ((proto = g_utf8_strchr (uri, -1, ':'))) { gulong offset; gchar* buffer; - /* 'file' URIs don't have a hostname */ - if (!strcmp (proto, "file")) - return uri; - offset = g_utf8_pointer_to_offset (uri, proto); buffer = g_malloc0 (offset + 1); g_utf8_strncpy (buffer, uri, offset); proto = buffer; } - hostname = sokoke_hostname_from_uri (uri, &path); - - if (!(q = stringprep_utf8_to_ucs4 (hostname, -1, NULL))) - { - g_free (proto); - g_free (hostname); - return uri; - } + gchar* path; + gchar* hostname = sokoke_hostname_from_uri (uri, &path); + gchar* encoded = sokoke_hostname_to_ascii (hostname); - rc = idna_to_ascii_4z (q, &s, IDNA_ALLOW_UNASSIGNED); - free (q); - if (rc != IDNA_SUCCESS) + if (encoded) { - g_free (proto); - g_free (hostname); - return uri; + gchar* res = g_strconcat (proto ? proto : "", proto ? "://" : "", + encoded, path, NULL); + g_free (encoded); + return res; } + g_free (hostname); + return g_strdup (uri); +} - if (proto) - { - result = g_strconcat (proto, "://", s, path ? path : "", NULL); - g_free (proto); - if (path) - g_free (hostname); - } - else - result = g_strdup (s); +static gchar* +sokoke_idn_to_punycode (gchar* uri) +{ + #if HAVE_LIBIDN + gchar* result = sokoke_uri_to_ascii (uri); g_free (uri); - free (s); - return result; #else return uri; diff --git a/midori/sokoke.h b/midori/sokoke.h index 854b0c33..f01de6cc 100644 --- a/midori/sokoke.h +++ b/midori/sokoke.h @@ -46,7 +46,7 @@ sokoke_hostname_from_uri (const gchar* uri, gchar** path); gchar* -sokoke_idn_to_punycode (gchar* uri); +sokoke_uri_to_ascii (const gchar* uri); gchar* sokoke_magic_uri (const gchar* uri, diff --git a/tests/magic-uri.c b/tests/magic-uri.c index bf5bcb7e..826ae896 100644 --- a/tests/magic-uri.c +++ b/tests/magic-uri.c @@ -86,27 +86,46 @@ magic_uri_uri (void) static void magic_uri_idn (void) { + typedef struct + { + const gchar* before; + const gchar* after; + } URIItem; + + static const URIItem items[] = { + #if HAVE_LIBIDN || defined (HAVE_LIBSOUP_2_27_90) + { "http://www.münchhausen.at", "http://www.xn--mnchhausen-9db.at" }, + { "http://www.خداوند.com/", "http://www.xn--mgbndb8il.com/" }, + { "айкидо.com", "xn--80aildf0a.com" }, + { "http://東京理科大学.jp", "http://xn--1lq68wkwbj6ugkpigi.jp" }, + { "https://青のネコ", "https://xn--u9jthzcs263c" }, + #else + { "http://www.münchhausen.at", NULL }, + { "http://www.خداوند.com/", NULL }, + { "айкидо.com", NULL }, + { "http://東京理科大学.jp", NULL }, + { "https://青のネコ.co.jp", NULL }, + #endif + { "http://en.wikipedia.org/wiki/Kölsch_language", NULL }, + { "file:///home/mark/frühstück", NULL }, + }; + guint i; + + for (i = 0; i < G_N_ELEMENTS (items); i++) + { + gchar* result = sokoke_uri_to_ascii (items[i].before); + const gchar* after = items[i].after ? items[i].after : items[i].before; + sokoke_assert_str_equal (items[i].before, result, after); + g_free (result); + } + #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 ("http://en.wikipedia.org/wiki/Kölsch_language", - "http://en.wikipedia.org/wiki/Kölsch_language"); - test_input ("en.wikipedia.org/wiki/Kölsch_language", - "http://en.wikipedia.org/wiki/Kölsch_language"); test_input ("sm Küchenzubehör", SM "Küchenzubehör"); test_input ("sm 東京理科大学", SM "東京理科大学"); - test_input ("file:///home/mark/frühstück", - "file:///home/mark/frühstück"); } static void