Refactor IDN handling and related unit tests

Most code is shared despite different available libraries now and
can more effeciently be tested.
This commit is contained in:
Christian Dywan 2009-10-10 11:09:10 +02:00
parent 94db485293
commit b9d4266d27
4 changed files with 92 additions and 79 deletions

View file

@ -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);

View file

@ -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.
* If no IDN support is available at compile time,
* the URI will be returned unaltered.
*
* The called function owns the passed string.
*
* 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);
gchar* path;
gchar* hostname = sokoke_hostname_from_uri (uri, &path);
gchar* encoded = sokoke_hostname_to_ascii (hostname);
if (!(q = stringprep_utf8_to_ucs4 (hostname, -1, NULL)))
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);
}
rc = idna_to_ascii_4z (q, &s, IDNA_ALLOW_UNASSIGNED);
free (q);
if (rc != IDNA_SUCCESS)
{
g_free (proto);
g_free (hostname);
return 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;

View file

@ -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,

View file

@ -86,27 +86,46 @@ magic_uri_uri (void)
static void
magic_uri_idn (void)
{
#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");
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
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");
{ "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 ("айкидо.com", "http://xn--80aildf0a.com");
#else
test_input ("айкидо.com", "http://айкидо.com");
#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