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:
parent
94db485293
commit
b9d4266d27
4 changed files with 92 additions and 79 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue