[Spice-devel] [spice-gtk 11/13] Make SpiceURI a public API

Marc-André Lureau marcandre.lureau at gmail.com
Mon Feb 3 10:02:42 PST 2014


From: Marc-André Lureau <marcandre.lureau at redhat.com>

Generalize a little bit SpiceProxy to allow easy URI manipulation by
clients.
---
 doc/reference/Makefile.am            |   1 +
 doc/reference/spice-gtk-docs.xml     |   1 +
 doc/reference/spice-gtk-sections.txt |  26 ++
 gtk/Makefile.am                      |   5 +-
 gtk/map-file                         |  12 +
 gtk/spice-client.h                   |   1 +
 gtk/spice-glib-sym-file              |  12 +
 gtk/spice-proxy.c                    | 357 --------------------------
 gtk/spice-proxy.h                    |  64 -----
 gtk/spice-session-priv.h             |   3 +-
 gtk/spice-session.c                  |  28 +--
 gtk/spice-session.h                  |   1 +
 gtk/spice-uri-priv.h                 |  30 +++
 gtk/spice-uri.c                      | 473 +++++++++++++++++++++++++++++++++++
 gtk/spice-uri.h                      |  52 ++++
 15 files changed, 627 insertions(+), 439 deletions(-)
 delete mode 100644 gtk/spice-proxy.c
 delete mode 100644 gtk/spice-proxy.h
 create mode 100644 gtk/spice-uri-priv.h
 create mode 100644 gtk/spice-uri.c
 create mode 100644 gtk/spice-uri.h

diff --git a/doc/reference/Makefile.am b/doc/reference/Makefile.am
index a0a856c..76c7d34 100644
--- a/doc/reference/Makefile.am
+++ b/doc/reference/Makefile.am
@@ -44,6 +44,7 @@ IGNORE_HFILES=					\
 	spice-marshal.h				\
 	spice-pulse.h				\
 	spice-session-priv.h			\
+	spice-uri-priv.h			\
 	spice-util-priv.h			\
 	spice-widget-priv.h			\
 	usb-acl-helper.h			\
diff --git a/doc/reference/spice-gtk-docs.xml b/doc/reference/spice-gtk-docs.xml
index 4a9a3cf..d2c1a2b 100644
--- a/doc/reference/spice-gtk-docs.xml
+++ b/doc/reference/spice-gtk-docs.xml
@@ -52,6 +52,7 @@
       <xi:include href="xml/smartcard-manager.xml"/>
       <xi:include href="xml/usb-device-manager.xml"/>
       <xi:include href="xml/spice-util.xml"/>
+      <xi:include href="xml/spice-uri.xml"/>
     </chapter>
 
   </part>
diff --git a/doc/reference/spice-gtk-sections.txt b/doc/reference/spice-gtk-sections.txt
index 8d61aa9..411ca0e 100644
--- a/doc/reference/spice-gtk-sections.txt
+++ b/doc/reference/spice-gtk-sections.txt
@@ -429,3 +429,29 @@ SPICE_PORT_CHANNEL_GET_CLASS
 SpicePortChannelPrivate
 </SECTION>
 
+<SECTION>
+<FILE>spice-uri</FILE>
+spice_uri_get_scheme
+spice_uri_set_scheme
+spice_uri_get_hostname
+spice_uri_set_hostname
+spice_uri_get_port
+spice_uri_set_port
+spice_uri_get_user
+spice_uri_set_user
+spice_uri_get_password
+spice_uri_set_password
+spice_uri_to_string
+SpiceURIClass
+SpiceURI
+<SUBSECTION Standard>
+SPICE_IS_URI
+SPICE_IS_URI_CLASS
+SPICE_TYPE_URI
+SPICE_URI
+SPICE_URI_CLASS
+SPICE_URI_GET_CLASS
+spice_uri_get_type
+<SUBSECTION Private>
+SpiceURIPrivate
+</SECTION>
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 840d129..45d6796 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -248,8 +248,8 @@ libspice_client_glib_2_0_la_SOURCES =			\
 	channel-usbredir-priv.h				\
 	smartcard-manager.c				\
 	smartcard-manager-priv.h			\
-	spice-proxy.c					\
-	spice-proxy.h					\
+	spice-uri.c					\
+	spice-uri-priv.h				\
 	usb-device-manager.c				\
 	usb-device-manager-priv.h			\
 	usbutil.c					\
@@ -282,6 +282,7 @@ libspice_client_glibincludedir = $(includedir)/spice-client-glib-2.0
 libspice_client_glibinclude_HEADERS =	\
 	spice-audio.h			\
 	spice-client.h			\
+	spice-uri.h			\
 	spice-types.h			\
 	spice-session.h			\
 	spice-channel.h			\
diff --git a/gtk/map-file b/gtk/map-file
index 368b44f..cf65db0 100644
--- a/gtk/map-file
+++ b/gtk/map-file
@@ -118,6 +118,18 @@ spice_util_get_debug;
 spice_util_get_version_string;
 spice_util_set_debug;
 spice_uuid_to_string;
+spice_uri_get_hostname;
+spice_uri_get_password;
+spice_uri_get_port;
+spice_uri_get_scheme;
+spice_uri_get_type;
+spice_uri_get_user;
+spice_uri_set_hostname;
+spice_uri_set_password;
+spice_uri_set_port;
+spice_uri_set_scheme;
+spice_uri_set_user;
+spice_uri_to_string;
 local:
 *;
 };
diff --git a/gtk/spice-client.h b/gtk/spice-client.h
index 730d11a..975259a 100644
--- a/gtk/spice-client.h
+++ b/gtk/spice-client.h
@@ -31,6 +31,7 @@
 #include "spice-session.h"
 #include "spice-channel.h"
 #include "spice-option.h"
+#include "spice-uri.h"
 
 #include "channel-main.h"
 #include "channel-display.h"
diff --git a/gtk/spice-glib-sym-file b/gtk/spice-glib-sym-file
index 4fc8643..ac7e871 100644
--- a/gtk/spice-glib-sym-file
+++ b/gtk/spice-glib-sym-file
@@ -92,3 +92,15 @@ spice_util_get_debug
 spice_util_get_version_string
 spice_util_set_debug
 spice_uuid_to_string
+spice_uri_get_hostname
+spice_uri_get_password
+spice_uri_get_port
+spice_uri_get_scheme
+spice_uri_get_type
+spice_uri_get_user
+spice_uri_set_hostname
+spice_uri_set_password
+spice_uri_set_port
+spice_uri_set_scheme
+spice_uri_set_user
+spice_uri_to_string
diff --git a/gtk/spice-proxy.c b/gtk/spice-proxy.c
deleted file mode 100644
index ecf7e54..0000000
--- a/gtk/spice-proxy.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
-   Copyright (C) 2012 Red Hat, Inc.
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   This library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "glib-compat.h"
-#include "spice-client.h"
-#include "spice-proxy.h"
-
-struct _SpiceProxyPrivate {
-    gchar *protocol;
-    gchar *hostname;
-    guint port;
-    gchar *user;
-    gchar *password;
-};
-
-#define SPICE_PROXY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), SPICE_TYPE_PROXY, SpiceProxyPrivate))
-
-G_DEFINE_TYPE(SpiceProxy, spice_proxy, G_TYPE_OBJECT);
-
-enum  {
-    SPICE_PROXY_DUMMY_PROPERTY,
-    SPICE_PROXY_PROTOCOL,
-    SPICE_PROXY_USER,
-    SPICE_PROXY_PASSWORD,
-    SPICE_PROXY_HOSTNAME,
-    SPICE_PROXY_PORT
-};
-
-G_GNUC_INTERNAL
-SpiceProxy* spice_proxy_new(void)
-{
-    SpiceProxy * self = NULL;
-    self = (SpiceProxy*)g_object_new(SPICE_TYPE_PROXY, NULL);
-    return self;
-}
-
-G_GNUC_INTERNAL
-gboolean spice_proxy_parse(SpiceProxy *self, const gchar *proxyuri, GError **error)
-{
-    gchar *dup, *uri;
-    gboolean success = FALSE;
-    size_t len;
-
-    g_return_val_if_fail(self != NULL, FALSE);
-    g_return_val_if_fail(proxyuri != NULL, FALSE);
-
-    uri = dup = g_strdup(proxyuri);
-    /* FIXME: use GUri when it is ready... only support http atm */
-    /* the code is voluntarily not parsing thoroughly the uri */
-    if (g_ascii_strncasecmp("http://", uri, 7) == 0) {
-        uri += 7;
-        spice_proxy_set_protocol(self, "http");
-        spice_proxy_set_port(self, 3128);
-    } else if (g_ascii_strncasecmp("https://", uri, 8) == 0) {
-        uri += 8;
-        spice_proxy_set_protocol(self, "https");
-        spice_proxy_set_port(self, 3129);
-    } else {
-        return FALSE;
-    }
-    /* remove trailing slash */
-    len = strlen(uri);
-    for (; len > 0; len--)
-        if (uri[len-1] == '/')
-            uri[len-1] = '\0';
-        else
-            break;
-
-
-    gchar *saveptr, *auth = strtok_r(uri, "@", &saveptr);
-    if (saveptr && *saveptr) {
-        gchar *saveptr2;
-        const gchar *user = strtok_r(auth, ":", &saveptr2);
-        const gchar *pass = strtok_r(NULL, ":", &saveptr2);
-        spice_proxy_set_user(self, user);
-        spice_proxy_set_password(self, pass);
-        uri = saveptr;
-    }
-
-    gchar **proxyv = g_strsplit(uri, ":", 2);
-    const gchar *proxy_port = NULL;
-
-    if (proxyv[0] == NULL || strlen(proxyv[0]) == 0) {
-        g_set_error(error, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
-                    "Invalid hostname in proxy address");
-        goto end;
-    }
-
-    spice_proxy_set_hostname(self, proxyv[0]);
-    if (proxyv[0] != NULL)
-        proxy_port = proxyv[1];
-
-    if (proxy_port != NULL) {
-        char *endptr;
-        guint port = strtoul(proxy_port, &endptr, 10);
-        if (*endptr != '\0') {
-            g_set_error(error, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
-                        "Invalid proxy port: %s", proxy_port);
-            goto end;
-        }
-        spice_proxy_set_port(self, port);
-    }
-
-    success = TRUE;
-
-end:
-    g_free(dup);
-    g_strfreev(proxyv);
-    return success;
-}
-
-G_GNUC_INTERNAL
-const gchar* spice_proxy_get_protocol(SpiceProxy *self)
-{
-    g_return_val_if_fail(SPICE_IS_PROXY(self), NULL);
-    return self->priv->protocol;
-}
-
-G_GNUC_INTERNAL
-void spice_proxy_set_protocol(SpiceProxy *self, const gchar *value)
-{
-    g_return_if_fail(SPICE_IS_PROXY(self));
-
-    g_free(self->priv->protocol);
-    self->priv->protocol = g_strdup(value);
-    g_object_notify((GObject *)self, "protocol");
-}
-
-G_GNUC_INTERNAL
-const gchar* spice_proxy_get_hostname(SpiceProxy *self)
-{
-    g_return_val_if_fail(SPICE_IS_PROXY(self), NULL);
-    return self->priv->hostname;
-}
-
-
-G_GNUC_INTERNAL
-void spice_proxy_set_hostname(SpiceProxy *self, const gchar *value)
-{
-    g_return_if_fail(SPICE_IS_PROXY(self));
-
-    g_free(self->priv->hostname);
-    self->priv->hostname = g_strdup(value);
-    g_object_notify((GObject *)self, "hostname");
-}
-
-G_GNUC_INTERNAL
-guint spice_proxy_get_port(SpiceProxy *self)
-{
-    g_return_val_if_fail(SPICE_IS_PROXY(self), 0);
-    return self->priv->port;
-}
-
-G_GNUC_INTERNAL
-void spice_proxy_set_port(SpiceProxy *self, guint port)
-{
-    g_return_if_fail(SPICE_IS_PROXY(self));
-    self->priv->port = port;
-    g_object_notify((GObject *)self, "port");
-}
-
-static void spice_proxy_get_property(GObject *object, guint property_id,
-                                     GValue *value, GParamSpec *pspec)
-{
-    SpiceProxy *self;
-    self = G_TYPE_CHECK_INSTANCE_CAST(object, SPICE_TYPE_PROXY, SpiceProxy);
-
-    switch (property_id) {
-    case SPICE_PROXY_PROTOCOL:
-        g_value_set_string(value, spice_proxy_get_protocol(self));
-        break;
-    case SPICE_PROXY_HOSTNAME:
-        g_value_set_string(value, spice_proxy_get_hostname(self));
-        break;
-    case SPICE_PROXY_PORT:
-        g_value_set_uint(value, spice_proxy_get_port(self));
-        break;
-    case SPICE_PROXY_USER:
-        g_value_set_string(value, spice_proxy_get_user(self));
-        break;
-    case SPICE_PROXY_PASSWORD:
-        g_value_set_string(value, spice_proxy_get_password(self));
-        break;
-    default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
-        break;
-    }
-}
-
-
-static void spice_proxy_set_property(GObject *object, guint property_id,
-                                     const GValue *value, GParamSpec *pspec)
-{
-    SpiceProxy * self;
-    self = G_TYPE_CHECK_INSTANCE_CAST(object, SPICE_TYPE_PROXY, SpiceProxy);
-
-    switch (property_id) {
-    case SPICE_PROXY_PROTOCOL:
-        spice_proxy_set_protocol(self, g_value_get_string(value));
-        break;
-    case SPICE_PROXY_HOSTNAME:
-        spice_proxy_set_hostname(self, g_value_get_string(value));
-        break;
-    case SPICE_PROXY_USER:
-        spice_proxy_set_user(self, g_value_get_string(value));
-        break;
-    case SPICE_PROXY_PASSWORD:
-        spice_proxy_set_password(self, g_value_get_string(value));
-        break;
-    case SPICE_PROXY_PORT:
-        spice_proxy_set_port(self, g_value_get_uint(value));
-        break;
-    default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
-        break;
-    }
-}
-
-static void spice_proxy_finalize(GObject* obj)
-{
-    SpiceProxy *self;
-
-    self = G_TYPE_CHECK_INSTANCE_CAST(obj, SPICE_TYPE_PROXY, SpiceProxy);
-    g_free(self->priv->protocol);
-    g_free(self->priv->hostname);
-
-    G_OBJECT_CLASS (spice_proxy_parent_class)->finalize (obj);
-}
-
-static void spice_proxy_init (SpiceProxy *self)
-{
-    self->priv = SPICE_PROXY_GET_PRIVATE(self);
-}
-
-
-static void spice_proxy_class_init(SpiceProxyClass *klass)
-{
-    spice_proxy_parent_class = g_type_class_peek_parent (klass);
-    g_type_class_add_private(klass, sizeof(SpiceProxyPrivate));
-
-    G_OBJECT_CLASS (klass)->get_property = spice_proxy_get_property;
-    G_OBJECT_CLASS (klass)->set_property = spice_proxy_set_property;
-    G_OBJECT_CLASS (klass)->finalize = spice_proxy_finalize;
-
-    g_object_class_install_property(G_OBJECT_CLASS (klass),
-                                    SPICE_PROXY_PROTOCOL,
-                                    g_param_spec_string ("protocol",
-                                                         "protocol",
-                                                         "protocol",
-                                                         NULL,
-                                                         G_PARAM_STATIC_STRINGS |
-                                                         G_PARAM_READWRITE));
-
-    g_object_class_install_property(G_OBJECT_CLASS (klass),
-                                    SPICE_PROXY_HOSTNAME,
-                                    g_param_spec_string ("hostname",
-                                                         "hostname",
-                                                         "hostname",
-                                                         NULL,
-                                                         G_PARAM_STATIC_STRINGS |
-                                                         G_PARAM_READWRITE));
-
-    g_object_class_install_property(G_OBJECT_CLASS (klass),
-                                    SPICE_PROXY_PORT,
-                                    g_param_spec_uint ("port",
-                                                       "port",
-                                                       "port",
-                                                       0, G_MAXUINT, 0,
-                                                       G_PARAM_STATIC_STRINGS |
-                                                       G_PARAM_READWRITE));
-
-    g_object_class_install_property(G_OBJECT_CLASS (klass),
-                                    SPICE_PROXY_USER,
-                                    g_param_spec_string ("user",
-                                                         "user",
-                                                         "user",
-                                                         NULL,
-                                                         G_PARAM_STATIC_STRINGS |
-                                                         G_PARAM_READWRITE));
-
-    g_object_class_install_property(G_OBJECT_CLASS (klass),
-                                    SPICE_PROXY_PASSWORD,
-                                    g_param_spec_string ("password",
-                                                         "password",
-                                                         "password",
-                                                         NULL,
-                                                         G_PARAM_STATIC_STRINGS |
-                                                         G_PARAM_READWRITE));
-}
-
-G_GNUC_INTERNAL
-gchar* spice_proxy_to_string(SpiceProxy* self)
-{
-    SpiceProxyPrivate *p;
-
-    g_return_val_if_fail(SPICE_IS_PROXY(self), NULL);
-    p = self->priv;
-
-    if (p->protocol == NULL || p->hostname == NULL)
-        return NULL;
-
-    return g_strdup_printf("%s://%s:%u", p->protocol, p->hostname, p->port);
-}
-
-G_GNUC_INTERNAL
-const gchar* spice_proxy_get_user(SpiceProxy *self)
-{
-    g_return_val_if_fail(SPICE_IS_PROXY(self), NULL);
-    return self->priv->user;
-}
-
-
-G_GNUC_INTERNAL
-void spice_proxy_set_user(SpiceProxy *self, const gchar *value)
-{
-    g_return_if_fail(SPICE_IS_PROXY(self));
-
-    g_free(self->priv->user);
-    self->priv->user = g_strdup(value);
-    g_object_notify((GObject *)self, "user");
-}
-
-G_GNUC_INTERNAL
-const gchar* spice_proxy_get_password(SpiceProxy *self)
-{
-    g_return_val_if_fail(SPICE_IS_PROXY(self), NULL);
-    return self->priv->password;
-}
-
-
-G_GNUC_INTERNAL
-void spice_proxy_set_password(SpiceProxy *self, const gchar *value)
-{
-    g_return_if_fail(SPICE_IS_PROXY(self));
-
-    g_free(self->priv->password);
-    self->priv->password = g_strdup(value);
-    g_object_notify((GObject *)self, "password");
-}
diff --git a/gtk/spice-proxy.h b/gtk/spice-proxy.h
deleted file mode 100644
index e74053b..0000000
--- a/gtk/spice-proxy.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
-   Copyright (C) 2012 Red Hat, Inc.
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   This library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef __SPICE_PROXY_H__
-#define __SPICE_PROXY_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-#define SPICE_TYPE_PROXY (spice_proxy_get_type ())
-#define SPICE_PROXY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_TYPE_PROXY, SpiceProxy))
-#define SPICE_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_TYPE_PROXY, SpiceProxyClass))
-#define SPICE_IS_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_TYPE_PROXY))
-#define SPICE_IS_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_TYPE_PROXY))
-#define SPICE_PROXY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_TYPE_PROXY, SpiceProxyClass))
-
-typedef struct _SpiceProxy SpiceProxy;
-typedef struct _SpiceProxyClass SpiceProxyClass;
-typedef struct _SpiceProxyPrivate SpiceProxyPrivate;
-
-struct _SpiceProxy {
-    GObject parent_instance;
-    SpiceProxyPrivate * priv;
-};
-
-struct _SpiceProxyClass {
-    GObjectClass parent_class;
-};
-
-
-GType spice_proxy_get_type(void) G_GNUC_CONST;
-
-SpiceProxy* spice_proxy_new(void);
-gboolean spice_proxy_parse(SpiceProxy* self, const gchar* uri, GError** error);
-const gchar* spice_proxy_get_protocol(SpiceProxy* self);
-void spice_proxy_set_protocol(SpiceProxy* self, const gchar* value);
-const gchar* spice_proxy_get_hostname(SpiceProxy* self);
-void spice_proxy_set_hostname(SpiceProxy* self, const gchar* value);
-guint spice_proxy_get_port(SpiceProxy* self);
-void spice_proxy_set_port(SpiceProxy* self, guint port);
-gchar *spice_proxy_to_string(SpiceProxy* self);
-const gchar* spice_proxy_get_user(SpiceProxy* self);
-void spice_proxy_set_user(SpiceProxy* self, const gchar* value);
-const gchar* spice_proxy_get_password(SpiceProxy* self);
-void spice_proxy_set_password(SpiceProxy* self, const gchar* value);
-
-G_END_DECLS
-
-#endif /* __SPICE_PROXY_H__ */
diff --git a/gtk/spice-session-priv.h b/gtk/spice-session-priv.h
index 55fee47..0dc2bfb 100644
--- a/gtk/spice-session-priv.h
+++ b/gtk/spice-session-priv.h
@@ -22,7 +22,6 @@
 #include <gio/gio.h>
 #include "desktop-integration.h"
 #include "spice-session.h"
-#include "spice-proxy.h"
 #include "spice-gtk-session.h"
 #include "spice-channel-cache.h"
 #include "decode.h"
@@ -45,7 +44,7 @@ struct _SpiceSessionPrivate {
     char              *cert_subject;
     guint             verify;
     gboolean          read_only;
-    SpiceProxy        *proxy;
+    SpiceURI          *proxy;
 
     /* whether to enable audio */
     gboolean          audio;
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 29c84e8..e229c64 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -28,7 +28,7 @@
 #include "gio-coroutine.h"
 #include "glib-compat.h"
 #include "wocky-http-proxy.h"
-#include "spice-proxy.h"
+#include "spice-uri-priv.h"
 #include "channel-playback-priv.h"
 
 struct channel {
@@ -139,7 +139,7 @@ static void do_emit_main_context(GObject *object, int signum, gpointer params)
 static void update_proxy(SpiceSession *self, const gchar *str)
 {
     SpiceSessionPrivate *s = self->priv;
-    SpiceProxy *proxy = NULL;
+    SpiceURI *proxy = NULL;
     GError *error = NULL;
 
     if (str == NULL)
@@ -149,8 +149,8 @@ static void update_proxy(SpiceSession *self, const gchar *str)
         return;
     }
 
-    proxy = spice_proxy_new();
-    if (!spice_proxy_parse(proxy, str, &error))
+    proxy = spice_uri_new();
+    if (!spice_uri_parse(proxy, str, &error))
         g_clear_object(&proxy);
     if (error) {
         g_warning("%s", error->message);
@@ -269,7 +269,7 @@ static int spice_uri_create(SpiceSession *session, char *dest, int len)
     return pos;
 }
 
-static int spice_uri_parse(SpiceSession *session, const char *original_uri)
+static int spice_parse_uri(SpiceSession *session, const char *original_uri)
 {
     SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(session);
     gchar *host = NULL, *port = NULL, *tls_port = NULL, *uri = NULL, *password = NULL;
@@ -499,7 +499,7 @@ static void spice_session_get_property(GObject    *gobject,
         g_value_set_pointer(value, s->uuid);
 	break;
     case PROP_PROXY:
-        g_value_take_string(value, spice_proxy_to_string(s->proxy));
+        g_value_take_string(value, spice_uri_to_string(s->proxy));
 	break;
     default:
 	G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec);
@@ -547,7 +547,7 @@ static void spice_session_set_property(GObject      *gobject,
     case PROP_URI:
         str = g_value_get_string(value);
         if (str != NULL)
-            spice_uri_parse(session, str);
+            spice_parse_uri(session, str);
         break;
     case PROP_CLIENT_SOCKETS:
         s->client_provided_sockets = g_value_get_boolean(value);
@@ -1664,7 +1664,7 @@ struct spice_open_host {
     struct coroutine *from;
     SpiceSession *session;
     SpiceChannel *channel;
-    SpiceProxy *proxy;
+    SpiceURI *proxy;
     int port;
     GCancellable *cancellable;
     GError *error;
@@ -1723,11 +1723,11 @@ static void proxy_lookup_ready(GObject *source_object, GAsyncResult *result,
 
     for (it = addresses; it != NULL; it = it->next) {
         address = g_proxy_address_new(G_INET_ADDRESS(it->data),
-                                      spice_proxy_get_port(open_host->proxy),
-                                      spice_proxy_get_protocol(open_host->proxy),
+                                      spice_uri_get_port(open_host->proxy),
+                                      spice_uri_get_scheme(open_host->proxy),
                                       s->host, open_host->port,
-                                      spice_proxy_get_user(open_host->proxy),
-                                      spice_proxy_get_password(open_host->proxy));
+                                      spice_uri_get_user(open_host->proxy),
+                                      spice_uri_get_password(open_host->proxy));
         if (address != NULL)
             break;
     }
@@ -1755,7 +1755,7 @@ static gboolean open_host_idle_cb(gpointer data)
 
     if (open_host->proxy)
         g_resolver_lookup_by_name_async(g_resolver_get_default(),
-                                        spice_proxy_get_hostname(open_host->proxy),
+                                        spice_uri_get_hostname(open_host->proxy),
                                         open_host->cancellable,
                                         proxy_lookup_ready, open_host);
     else
@@ -1770,7 +1770,7 @@ static gboolean open_host_idle_cb(gpointer data)
 
     SPICE_DEBUG("open host %s:%d", s->host, open_host->port);
     if (open_host->proxy != NULL) {
-        gchar *str = spice_proxy_to_string(open_host->proxy);
+        gchar *str = spice_uri_to_string(open_host->proxy);
         SPICE_DEBUG("(with proxy %s)", str);
         g_free(str);
     }
diff --git a/gtk/spice-session.h b/gtk/spice-session.h
index b07f525..4ea645e 100644
--- a/gtk/spice-session.h
+++ b/gtk/spice-session.h
@@ -20,6 +20,7 @@
 
 #include <glib-object.h>
 #include "spice-types.h"
+#include "spice-uri.h"
 #include "spice-glib-enums.h"
 #include "spice-util.h"
 
diff --git a/gtk/spice-uri-priv.h b/gtk/spice-uri-priv.h
new file mode 100644
index 0000000..54351de
--- /dev/null
+++ b/gtk/spice-uri-priv.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+  Copyright (C) 2012 Red Hat, Inc.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef __SPICE_URI_PRIV_H__
+#define __SPICE_URI_PRIV_H__
+
+#include "spice-uri.h"
+
+G_BEGIN_DECLS
+
+SpiceURI* spice_uri_new(void);
+gboolean spice_uri_parse(SpiceURI* self, const gchar* uri, GError** error);
+
+G_END_DECLS
+
+#endif /* __SPICE_URI_PRIV_H__ */
diff --git a/gtk/spice-uri.c b/gtk/spice-uri.c
new file mode 100644
index 0000000..8a51208
--- /dev/null
+++ b/gtk/spice-uri.c
@@ -0,0 +1,473 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2012 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "glib-compat.h"
+#include "spice-client.h"
+#include "spice-uri.h"
+
+/**
+ * SECTION:spice-uri
+ * @short_description: URIs handling
+ * @title: SpiceURI
+ * @section_id:
+ * @stability: Stable
+ * @include: spice-uri.h
+ *
+ * A SpiceURI represents a (parsed) URI.
+ * Since: 0.23
+ */
+
+struct _SpiceURI {
+    GObject parent_instance;
+    SpiceURIPrivate * priv;
+};
+
+struct _SpiceURIClass {
+    GObjectClass parent_class;
+};
+
+struct _SpiceURIPrivate {
+    gchar *scheme;
+    gchar *hostname;
+    guint port;
+    gchar *user;
+    gchar *password;
+};
+
+#define SPICE_URI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), SPICE_TYPE_URI, SpiceURIPrivate))
+
+G_DEFINE_TYPE(SpiceURI, spice_uri, G_TYPE_OBJECT);
+
+enum  {
+    SPICE_URI_DUMMY_PROPERTY,
+    SPICE_URI_SCHEME,
+    SPICE_URI_USER,
+    SPICE_URI_PASSWORD,
+    SPICE_URI_HOSTNAME,
+    SPICE_URI_PORT
+};
+
+G_GNUC_INTERNAL
+SpiceURI* spice_uri_new(void)
+{
+    SpiceURI * self = NULL;
+    self = (SpiceURI*)g_object_new(SPICE_TYPE_URI, NULL);
+    return self;
+}
+
+G_GNUC_INTERNAL
+gboolean spice_uri_parse(SpiceURI *self, const gchar *_uri, GError **error)
+{
+    gchar *dup, *uri;
+    gboolean success = FALSE;
+    size_t len;
+
+    g_return_val_if_fail(self != NULL, FALSE);
+    g_return_val_if_fail(_uri != NULL, FALSE);
+
+    uri = dup = g_strdup(_uri);
+    /* FIXME: use GURI when it is ready... only support http atm */
+    /* the code is voluntarily not parsing thoroughly the uri */
+    if (g_ascii_strncasecmp("http://", uri, 7) == 0) {
+        uri += 7;
+        spice_uri_set_scheme(self, "http");
+        spice_uri_set_port(self, 3128);
+    } else if (g_ascii_strncasecmp("https://", uri, 8) == 0) {
+        uri += 8;
+        spice_uri_set_scheme(self, "https");
+        spice_uri_set_port(self, 3129);
+    } else {
+        return FALSE;
+    }
+    /* remove trailing slash */
+    len = strlen(uri);
+    for (; len > 0; len--)
+        if (uri[len-1] == '/')
+            uri[len-1] = '\0';
+        else
+            break;
+
+
+    gchar *saveptr, *auth = strtok_r(uri, "@", &saveptr);
+    if (saveptr && *saveptr) {
+        gchar *saveptr2;
+        const gchar *user = strtok_r(auth, ":", &saveptr2);
+        const gchar *pass = strtok_r(NULL, ":", &saveptr2);
+        spice_uri_set_user(self, user);
+        spice_uri_set_password(self, pass);
+        uri = saveptr;
+    }
+
+    gchar **uriv = g_strsplit(uri, ":", 2);
+    const gchar *uri_port = NULL;
+
+    if (uriv[0] == NULL || strlen(uriv[0]) == 0) {
+        g_set_error(error, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
+                    "Invalid hostname in uri address");
+        goto end;
+    }
+
+    spice_uri_set_hostname(self, uriv[0]);
+    if (uriv[0] != NULL)
+        uri_port = uriv[1];
+
+    if (uri_port != NULL) {
+        char *endptr;
+        guint port = strtoul(uri_port, &endptr, 10);
+        if (*endptr != '\0') {
+            g_set_error(error, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
+                        "Invalid uri port: %s", uri_port);
+            goto end;
+        }
+        spice_uri_set_port(self, port);
+    }
+
+    success = TRUE;
+
+end:
+    g_free(dup);
+    g_strfreev(uriv);
+    return success;
+}
+
+/**
+ * spice_uri_get_scheme:
+ * @uri: a #SpiceURI
+ *
+ * Gets @uri's scheme.
+ *
+ * Returns: @uri's scheme.
+ * Since: 0.23
+ **/
+const gchar* spice_uri_get_scheme(SpiceURI *self)
+{
+    g_return_val_if_fail(SPICE_IS_URI(self), NULL);
+
+    return self->priv->scheme;
+}
+
+/**
+ * spice_uri_set_scheme:
+ * @uri: a #SpiceURI
+ * @scheme: the scheme
+ *
+ * Sets @uri's scheme to @scheme.
+ * Since: 0.23
+ **/
+void spice_uri_set_scheme(SpiceURI *self, const gchar *value)
+{
+    g_return_if_fail(SPICE_IS_URI(self));
+
+    g_free(self->priv->scheme);
+    self->priv->scheme = g_strdup(value);
+    g_object_notify((GObject *)self, "scheme");
+}
+
+/**
+ * spice_uri_get_hostname:
+ * @uri: a #SpiceURI
+ *
+ * Gets @uri's hostname.
+ *
+ * Returns: @uri's hostname.
+ * Since: 0.23
+ **/
+const gchar* spice_uri_get_hostname(SpiceURI *self)
+{
+    g_return_val_if_fail(SPICE_IS_URI(self), NULL);
+
+    return self->priv->hostname;
+}
+
+
+/**
+ * spice_uri_set_hostname:
+ * @uri: a #SpiceURI
+ * @hostname: the hostname
+ *
+ * Sets @uri's hostname to @hostname.
+ * Since: 0.23
+ **/
+void spice_uri_set_hostname(SpiceURI *self, const gchar *hostname)
+{
+    g_return_if_fail(SPICE_IS_URI(self));
+
+    g_free(self->priv->hostname);
+    self->priv->hostname = g_strdup(hostname);
+    g_object_notify((GObject *)self, "hostname");
+}
+
+/**
+ * spice_uri_get_port:
+ * @uri: a #SpiceURI
+ *
+ * Gets @uri's port.
+ *
+ * Returns: @uri's port.
+ * Since: 0.23
+ **/
+guint spice_uri_get_port(SpiceURI *self)
+{
+    g_return_val_if_fail(SPICE_IS_URI(self), 0);
+
+    return self->priv->port;
+}
+
+/**
+ * spice_uri_set_port:
+ * @uri: a #SpiceURI
+ * @port: the port
+ *
+ * Sets @uri's port to @port.
+ * Since: 0.23
+ **/
+void spice_uri_set_port(SpiceURI *self, guint port)
+{
+    g_return_if_fail(SPICE_IS_URI(self));
+
+    self->priv->port = port;
+    g_object_notify((GObject *)self, "port");
+}
+
+static void spice_uri_get_property(GObject *object, guint property_id,
+                                   GValue *value, GParamSpec *pspec)
+{
+    SpiceURI *self;
+    self = G_TYPE_CHECK_INSTANCE_CAST(object, SPICE_TYPE_URI, SpiceURI);
+
+    switch (property_id) {
+    case SPICE_URI_SCHEME:
+        g_value_set_string(value, spice_uri_get_scheme(self));
+        break;
+    case SPICE_URI_HOSTNAME:
+        g_value_set_string(value, spice_uri_get_hostname(self));
+        break;
+    case SPICE_URI_PORT:
+        g_value_set_uint(value, spice_uri_get_port(self));
+        break;
+    case SPICE_URI_USER:
+        g_value_set_string(value, spice_uri_get_user(self));
+        break;
+    case SPICE_URI_PASSWORD:
+        g_value_set_string(value, spice_uri_get_password(self));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+        break;
+    }
+}
+
+
+static void spice_uri_set_property(GObject *object, guint property_id,
+                                   const GValue *value, GParamSpec *pspec)
+{
+    SpiceURI * self;
+    self = G_TYPE_CHECK_INSTANCE_CAST(object, SPICE_TYPE_URI, SpiceURI);
+
+    switch (property_id) {
+    case SPICE_URI_SCHEME:
+        spice_uri_set_scheme(self, g_value_get_string(value));
+        break;
+    case SPICE_URI_HOSTNAME:
+        spice_uri_set_hostname(self, g_value_get_string(value));
+        break;
+    case SPICE_URI_USER:
+        spice_uri_set_user(self, g_value_get_string(value));
+        break;
+    case SPICE_URI_PASSWORD:
+        spice_uri_set_password(self, g_value_get_string(value));
+        break;
+    case SPICE_URI_PORT:
+        spice_uri_set_port(self, g_value_get_uint(value));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+        break;
+    }
+}
+
+static void spice_uri_finalize(GObject* obj)
+{
+    SpiceURI *self;
+
+    self = G_TYPE_CHECK_INSTANCE_CAST(obj, SPICE_TYPE_URI, SpiceURI);
+    g_free(self->priv->scheme);
+    g_free(self->priv->hostname);
+
+    G_OBJECT_CLASS (spice_uri_parent_class)->finalize (obj);
+}
+
+static void spice_uri_init (SpiceURI *self)
+{
+    self->priv = SPICE_URI_GET_PRIVATE(self);
+}
+
+
+static void spice_uri_class_init(SpiceURIClass *klass)
+{
+    spice_uri_parent_class = g_type_class_peek_parent (klass);
+    g_type_class_add_private(klass, sizeof(SpiceURIPrivate));
+
+    G_OBJECT_CLASS (klass)->get_property = spice_uri_get_property;
+    G_OBJECT_CLASS (klass)->set_property = spice_uri_set_property;
+    G_OBJECT_CLASS (klass)->finalize = spice_uri_finalize;
+
+    g_object_class_install_property(G_OBJECT_CLASS (klass),
+                                    SPICE_URI_SCHEME,
+                                    g_param_spec_string ("scheme",
+                                                         "scheme",
+                                                         "scheme",
+                                                         NULL,
+                                                         G_PARAM_STATIC_STRINGS |
+                                                         G_PARAM_READWRITE));
+
+    g_object_class_install_property(G_OBJECT_CLASS (klass),
+                                    SPICE_URI_HOSTNAME,
+                                    g_param_spec_string ("hostname",
+                                                         "hostname",
+                                                         "hostname",
+                                                         NULL,
+                                                         G_PARAM_STATIC_STRINGS |
+                                                         G_PARAM_READWRITE));
+
+    g_object_class_install_property(G_OBJECT_CLASS (klass),
+                                    SPICE_URI_PORT,
+                                    g_param_spec_uint ("port",
+                                                       "port",
+                                                       "port",
+                                                       0, G_MAXUINT, 0,
+                                                       G_PARAM_STATIC_STRINGS |
+                                                       G_PARAM_READWRITE));
+
+    g_object_class_install_property(G_OBJECT_CLASS (klass),
+                                    SPICE_URI_USER,
+                                    g_param_spec_string ("user",
+                                                         "user",
+                                                         "user",
+                                                         NULL,
+                                                         G_PARAM_STATIC_STRINGS |
+                                                         G_PARAM_READWRITE));
+
+    g_object_class_install_property(G_OBJECT_CLASS (klass),
+                                    SPICE_URI_PASSWORD,
+                                    g_param_spec_string ("password",
+                                                         "password",
+                                                         "password",
+                                                         NULL,
+                                                         G_PARAM_STATIC_STRINGS |
+                                                         G_PARAM_READWRITE));
+}
+
+/**
+ * spice_uri_to_string:
+ * @uri: a #SpiceURI
+ *
+ * Returns a string representing @uri.
+ *
+ * Returns: a string representing @uri, which the caller must free.
+ * Since: 0.23
+ **/
+gchar* spice_uri_to_string(SpiceURI* self)
+{
+    SpiceURIPrivate *p;
+
+    g_return_val_if_fail(SPICE_IS_URI(self), NULL);
+    p = self->priv;
+
+    if (p->scheme == NULL || p->hostname == NULL)
+        return NULL;
+
+    if (p->user || p->password) {
+        return g_strdup_printf("%s://%s:%s@%s:%u",
+                               p->scheme,
+                               p->user ?: "", p->password ?: "",
+                               p->hostname, p->port);
+    } else {
+        return g_strdup_printf("%s://%s:%u", p->scheme, p->hostname, p->port);
+    }
+}
+
+/**
+ * spice_uri_get_user:
+ * @uri: a #SpiceURI
+ *
+ * Gets @uri's user.
+ *
+ * Returns: @uri's user.
+ * Since: 0.23
+ **/
+const gchar* spice_uri_get_user(SpiceURI *self)
+{
+    g_return_val_if_fail(SPICE_IS_URI(self), NULL);
+
+    return self->priv->user;
+}
+
+
+/**
+ * spice_uri_set_user:
+ * @uri: a #SpiceURI
+ * @password: the user, or %NULL.
+ *
+ * Sets @uri's user to @password.
+ * Since: 0.23
+ **/
+void spice_uri_set_user(SpiceURI *self, const gchar *user)
+{
+    g_return_if_fail(SPICE_IS_URI(self));
+
+    g_free(self->priv->user);
+    self->priv->user = g_strdup(user);
+    g_object_notify((GObject *)self, "user");
+}
+
+/**
+ * spice_uri_get_password:
+ * @uri: a #SpiceURI
+ *
+ * Gets @uri's password.
+ *
+ * Returns: @uri's password.
+ * Since: 0.23
+ **/
+const gchar* spice_uri_get_password(SpiceURI *self)
+{
+    g_return_val_if_fail(SPICE_IS_URI(self), NULL);
+
+    return self->priv->password;
+}
+
+/**
+ * spice_uri_set_password:
+ * @uri: a #SpiceURI
+ * @password: the password, or %NULL.
+ *
+ * Sets @uri's password to @password.
+ * Since: 0.23
+ **/
+void spice_uri_set_password(SpiceURI *self, const gchar *password)
+{
+    g_return_if_fail(SPICE_IS_URI(self));
+
+    g_free(self->priv->password);
+    self->priv->password = g_strdup(password);
+    g_object_notify((GObject *)self, "password");
+}
diff --git a/gtk/spice-uri.h b/gtk/spice-uri.h
new file mode 100644
index 0000000..9e8d590
--- /dev/null
+++ b/gtk/spice-uri.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2012 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef __SPICE_URI_H__
+#define __SPICE_URI_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define SPICE_TYPE_URI (spice_uri_get_type ())
+#define SPICE_URI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_TYPE_URI, SpiceURI))
+#define SPICE_URI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_TYPE_URI, SpiceURIClass))
+#define SPICE_IS_URI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_TYPE_URI))
+#define SPICE_IS_URI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_TYPE_URI))
+#define SPICE_URI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_TYPE_URI, SpiceURIClass))
+
+typedef struct _SpiceURI SpiceURI;
+typedef struct _SpiceURIClass SpiceURIClass;
+typedef struct _SpiceURIPrivate SpiceURIPrivate;
+
+GType spice_uri_get_type(void) G_GNUC_CONST;
+
+const gchar* spice_uri_get_scheme(SpiceURI* uri);
+void spice_uri_set_scheme(SpiceURI* uri, const gchar* scheme);
+const gchar* spice_uri_get_hostname(SpiceURI* uri);
+void spice_uri_set_hostname(SpiceURI* uri, const gchar* hostname);
+guint spice_uri_get_port(SpiceURI* uri);
+void spice_uri_set_port(SpiceURI* uri, guint port);
+gchar *spice_uri_to_string(SpiceURI* uri);
+const gchar* spice_uri_get_user(SpiceURI* uri);
+void spice_uri_set_user(SpiceURI* uri, const gchar* user);
+const gchar* spice_uri_get_password(SpiceURI* uri);
+void spice_uri_set_password(SpiceURI* uri, const gchar* password);
+
+G_END_DECLS
+
+#endif /* __SPICE_URI_H__ */
-- 
1.8.4.2



More information about the Spice-devel mailing list