From 59383c8bea00b8f4bf50cf82ae9f3e7ce1df1a03 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 10 Sep 2010 08:51:21 -0400 Subject: [PATCH] Fix IPv6 parsing in _g_uri_parse_authority, add _g_uri_from_authority Fixes connections to IPv6 address literals. https://bugzilla.gnome.org/show_bug.cgi?id=629259 --- gio/gnetworkaddress.c | 49 +++++++++++++++++++++++++++++++++++++++++++++--- gio/gnetworkingprivate.h | 4 ++++ gio/gnetworkservice.c | 9 +++++---- gio/gsocketaddress.c | 2 +- 4 files changed, 56 insertions(+), 8 deletions(-) diff --git a/gio/gnetworkaddress.c b/gio/gnetworkaddress.c index 80a3e31..11bda8c 100644 --- a/gio/gnetworkaddress.c +++ b/gio/gnetworkaddress.c @@ -526,6 +526,8 @@ _g_uri_parse_authority (const char *uri, /* If IPv6 or IPvFuture */ if (*p == '[') { + start++; + p++; while (1) { c = *p++; @@ -625,6 +627,46 @@ error: return FALSE; } +gchar * +_g_uri_from_authority (const gchar *protocol, + const gchar *host, + guint port, + const gchar *userinfo) +{ + GString *uri; + + uri = g_string_new (protocol); + g_string_append (uri, "://"); + + if (userinfo) + { + g_string_append_uri_escaped (uri, userinfo, G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO, FALSE); + g_string_append_c (uri, '@'); + } + + if (g_hostname_is_non_ascii (host)) + { + gchar *ace_encoded = g_hostname_to_ascii (host); + + if (!ace_encoded) + { + g_string_free (uri, TRUE); + return NULL; + } + g_string_append (uri, ace_encoded); + g_free (ace_encoded); + } + else if (strchr (host, ':')) + g_string_append_printf (uri, "[%s]", host); + else + g_string_append (uri, host); + + if (port != 0) + g_string_append_printf (uri, ":%u", port); + + return g_string_free (uri, FALSE); +} + /** * g_network_address_parse_uri: * @uri: the hostname and optionally a port @@ -920,9 +962,10 @@ g_network_address_connectable_proxy_enumerate (GSocketConnectable *connectable) GSocketAddressEnumerator *proxy_enum; gchar *uri; - uri = g_strdup_printf ("%s://%s:%u", - self->priv->scheme ? self->priv->scheme : "none", - self->priv->hostname, self->priv->port); + uri = _g_uri_from_authority (self->priv->scheme ? self->priv->scheme : "none", + self->priv->hostname, + self->priv->port, + NULL); proxy_enum = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR, "connectable", connectable, diff --git a/gio/gnetworkingprivate.h b/gio/gnetworkingprivate.h index 9434adf..92d2645 100644 --- a/gio/gnetworkingprivate.h +++ b/gio/gnetworkingprivate.h @@ -124,6 +124,10 @@ gboolean _g_uri_parse_authority (const char *uri, char **host, guint16 *port, char **userinfo); +gchar * _g_uri_from_authority (const gchar *protocol, + const gchar *host, + guint port, + const gchar *userinfo); G_END_DECLS diff --git a/gio/gnetworkservice.c b/gio/gnetworkservice.c index e46126a..b1d934d 100644 --- a/gio/gnetworkservice.c +++ b/gio/gnetworkservice.c @@ -31,6 +31,7 @@ #include "ginetsocketaddress.h" #include "gioerror.h" #include "gnetworkaddress.h" +#include "gnetworkingprivate.h" #include "gresolver.h" #include "gsimpleasyncresult.h" #include "gsocketaddressenumerator.h" @@ -438,10 +439,10 @@ g_network_service_address_enumerator_next (GSocketAddressEnumerator *enumerator continue; } - uri = g_strdup_printf ("%s://%s:%u", - g_network_service_get_scheme (srv_enum->srv), - hostname, - g_srv_target_get_port (target)); + uri = _g_uri_from_authority (g_network_service_get_scheme (srv_enum->srv), + hostname, + g_srv_target_get_port (target), + NULL); g_free (hostname); addr = g_network_address_parse_uri (uri, diff --git a/gio/gsocketaddress.c b/gio/gsocketaddress.c index 49220b4..d4dcbb0 100644 --- a/gio/gsocketaddress.c +++ b/gio/gsocketaddress.c @@ -372,7 +372,7 @@ g_socket_address_connectable_proxy_enumerate (GSocketConnectable *connectable) g_object_get (connectable, "address", &addr, "port", &port, NULL); ip = g_inet_address_to_string (addr); - uri = g_strdup_printf ("none://%s:%u", ip, port); + uri = _g_uri_from_authority ("none", ip, port, NULL); addr_enum = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR, "connectable", connectable, -- 2.7.4