From: Dan Winship Date: Sat, 11 Dec 2010 14:23:51 +0000 (+0100) Subject: Implement a GNOME proxy backend using GSettings X-Git-Tag: 2.28.4~11 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=00c639ccb953a36ae5be3dc2bcfe87a14b9592d1;p=platform%2Fupstream%2Fglib-networking.git Implement a GNOME proxy backend using GSettings Use the network proxy settings from gsettings-desktop-schemas and return proxies based on that. For Automatic proxy configuration, we use the D-Bus service provided by the libproxy plugin. https://bugzilla.gnome.org/show_bug.cgi?id=644211 --- diff --git a/Makefile.am b/Makefile.am index 6e030c1..2c34280 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,6 +9,10 @@ if HAVE_LIBPROXY SUBDIRS += proxy/libproxy endif +if HAVE_GNOME_PROXY +SUBDIRS += proxy/gnome +endif + if HAVE_GNUTLS SUBDIRS += tls/gnutls endif diff --git a/configure.ac b/configure.ac index 0218196..dac8721 100644 --- a/configure.ac +++ b/configure.ac @@ -43,9 +43,6 @@ AC_SUBST(GIO_MODULE_DIR) AC_PATH_PROG(GIO_QUERYMODULES, gio-querymodules) AC_SUBST(GIO_QUERYMODULES) -proxy_support=no -tls_support=no - dnl ***************************** dnl *** Checks for LibProxy *** dnl ***************************** @@ -64,6 +61,22 @@ AM_CONDITIONAL(HAVE_LIBPROXY, [test "x$with_libproxy" = "xyes"]) AC_SUBST(LIBPROXY_CFLAGS) AC_SUBST(LIBPROXY_LIBS) +dnl ************************************** +dnl *** Checks for GNOME proxy backend *** +dnl ************************************** +AC_ARG_WITH(gnome-proxy, + [AC_HELP_STRING([--with-gnome-proxy], + [support for GNOME proxy configuration @<:@default=check@:>@])] + [], + [with_gnome_proxy=check]) +AS_IF([test "x$with_gnome_proxy" != "xno"], + [PKG_CHECK_MODULES(GSETTINGS_DESKTOP_SCHEMAS, [gsettings-desktop-schemas], + [with_gnome_proxy=yes; proxy_support="gnome $proxy_support"], + [AS_IF([test "x$with_gnome_proxy" = "xyes"], + [AC_MSG_FAILURE("$GSETTINGS_DESKTOP_SCHEMAS_PKG_ERRORS")])])]) +AM_CONDITIONAL(HAVE_GNOME_PROXY, [test "x$with_gnome_proxy" = "xyes"]) +AC_SUBST(GSETTINGS_DESKTOP_SCHEMAS_CFLAGS) + dnl ***************************** dnl *** Checks for GNUTLS *** dnl ***************************** @@ -143,13 +156,14 @@ dnl ***************************** AC_CONFIG_FILES([Makefile po/Makefile.in po/Makefile proxy/libproxy/Makefile + proxy/gnome/Makefile tls/gnutls/Makefile ]) AC_OUTPUT echo "" -echo " Proxy support: $proxy_support" -echo " TLS support: $tls_support" +echo " Proxy support: ${proxy_support:-no}" +echo " TLS support: ${tls_support:-no}" if test "$tls_support" != "no"; then echo " TLS CA file: ${with_ca_certificates:-(none)}" if test -n "$with_ca_certificates"; then diff --git a/proxy/gnome/Makefile.am b/proxy/gnome/Makefile.am new file mode 100644 index 0000000..a59b436 --- /dev/null +++ b/proxy/gnome/Makefile.am @@ -0,0 +1,26 @@ +include $(top_srcdir)/Makefile.decl + +NULL = + +module_flags = -export_dynamic -avoid-version -module -no-undefined -export-symbols-regex '^g_io_module_(load|unload|query)' + +giomodule_LTLIBRARIES = libgiognomeproxy.la +giomoduledir = $(GIO_MODULE_DIR) + +libgiognomeproxy_la_SOURCES = \ + gproxyresolvergnome.c \ + gproxyresolvergnome.h \ + gnome-proxy-module.c \ + $(NULL) + +libgiognomeproxy_la_CFLAGS = \ + -DG_LOG_DOMAIN=\"GLib-Net\" \ + $(GLIB_CFLAGS) \ + $(GSETTINGS_DESKTOP_SCHEMAS_CFLAGS) \ + -DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\" \ + -DG_DISABLE_DEPRECATED + +libgiognomeproxy_la_LDFLAGS = $(module_flags) +libgiognomeproxy_la_LIBADD = \ + $(GLIB_LIBS) \ + $(NULL) diff --git a/proxy/gnome/gnome-proxy-module.c b/proxy/gnome/gnome-proxy-module.c new file mode 100644 index 0000000..03495ca --- /dev/null +++ b/proxy/gnome/gnome-proxy-module.c @@ -0,0 +1,45 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2010 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 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, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "gproxyresolvergnome.h" + + +void +g_io_module_load (GIOModule *module) +{ + g_proxy_resolver_gnome_register (module); +} + +void +g_io_module_unload (GIOModule *module) +{ +} + +gchar ** +g_io_module_query (void) +{ + gchar *eps[] = { + G_PROXY_RESOLVER_EXTENSION_POINT_NAME, + NULL + }; + return g_strdupv (eps); +} diff --git a/proxy/gnome/gproxyresolvergnome.c b/proxy/gnome/gproxyresolvergnome.c new file mode 100644 index 0000000..80fc806 --- /dev/null +++ b/proxy/gnome/gproxyresolvergnome.c @@ -0,0 +1,641 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2010 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 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, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include "gproxyresolvergnome.h" + +#include +#include + +#define GNOME_PROXY_SETTINGS_SCHEMA "org.gnome.system.proxy" +#define GNOME_PROXY_MODE_KEY "mode" +#define GNOME_PROXY_AUTOCONFIG_URL_KEY "autoconfig-url" +#define GNOME_PROXY_IGNORE_HOSTS_KEY "ignore-hosts" +#define GNOME_PROXY_USE_SAME_PROXY_KEY "use-same-proxy" + +#define GNOME_PROXY_HTTP_SETTINGS_SCHEMA "org.gnome.system.proxy.http" +#define GNOME_PROXY_HTTP_ENABLED_KEY "enabled" +#define GNOME_PROXY_HTTP_HOST_KEY "host" +#define GNOME_PROXY_HTTP_PORT_KEY "port" +#define GNOME_PROXY_HTTP_USE_AUTH_KEY "use-authentication" +#define GNOME_PROXY_HTTP_USER_KEY "authentication-user" +#define GNOME_PROXY_HTTP_PASSWORD_KEY "authentication-password" + +#define GNOME_PROXY_HTTPS_SETTINGS_SCHEMA "org.gnome.system.proxy.https" +#define GNOME_PROXY_HTTPS_HOST_KEY "host" +#define GNOME_PROXY_HTTPS_PORT_KEY "port" + +#define GNOME_PROXY_FTP_SETTINGS_SCHEMA "org.gnome.system.proxy.ftp" +#define GNOME_PROXY_FTP_HOST_KEY "host" +#define GNOME_PROXY_FTP_PORT_KEY "port" + +#define GNOME_PROXY_SOCKS_SETTINGS_SCHEMA "org.gnome.system.proxy.socks" +#define GNOME_PROXY_SOCKS_HOST_KEY "host" +#define GNOME_PROXY_SOCKS_PORT_KEY "port" + +typedef struct { + GSocketFamily family; + guint8 mask[16]; + gint length; +} GProxyResolverGnomeIPMask; + +struct _GProxyResolverGnome { + GObject parent_instance; + + GSettings *proxy_settings; + GSettings *http_settings; + GSettings *https_settings; + GSettings *ftp_settings; + GSettings *socks_settings; + gboolean need_update; + + GDesktopProxyMode mode; + gchar *autoconfig_url; + gboolean use_same_proxy; + gchar **ignore_hosts; + GProxyResolverGnomeIPMask *ignore_ips; + + gchar *http_proxy, *https_proxy; + gchar *ftp_proxy, *socks_authority; + + GDBusProxy *pacrunner; +}; + +static void g_proxy_resolver_gnome_iface_init (GProxyResolverInterface *iface); + +G_DEFINE_DYNAMIC_TYPE_EXTENDED (GProxyResolverGnome, + g_proxy_resolver_gnome, + G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_PROXY_RESOLVER, + g_proxy_resolver_gnome_iface_init)) + +static void +g_proxy_resolver_gnome_class_finalize (GProxyResolverGnomeClass *klass) +{ +} + +static void +free_settings (GProxyResolverGnome *resolver) +{ + g_free (resolver->autoconfig_url); + g_strfreev (resolver->ignore_hosts); + g_free (resolver->ignore_ips); + + g_free (resolver->http_proxy); + g_free (resolver->https_proxy); + g_free (resolver->ftp_proxy); + g_free (resolver->socks_authority); +} + +static void +gsettings_changed (GSettings *settings, + const gchar *key, + gpointer user_data) +{ + GProxyResolverGnome *resolver = user_data; + + resolver->need_update = TRUE; +} + +static void +g_proxy_resolver_gnome_finalize (GObject *object) +{ + GProxyResolverGnome *resolver = G_PROXY_RESOLVER_GNOME (object); + + if (resolver->proxy_settings) + { + g_signal_handlers_disconnect_by_func (resolver->proxy_settings, + (gpointer)gsettings_changed, + resolver); + g_object_unref (resolver->proxy_settings); + + g_signal_handlers_disconnect_by_func (resolver->http_settings, + (gpointer)gsettings_changed, + resolver); + g_object_unref (resolver->http_settings); + + g_signal_handlers_disconnect_by_func (resolver->https_settings, + (gpointer)gsettings_changed, + resolver); + g_object_unref (resolver->https_settings); + + g_signal_handlers_disconnect_by_func (resolver->ftp_settings, + (gpointer)gsettings_changed, + resolver); + g_object_unref (resolver->ftp_settings); + + g_signal_handlers_disconnect_by_func (resolver->socks_settings, + (gpointer)gsettings_changed, + resolver); + g_object_unref (resolver->socks_settings); + + free_settings (resolver); + } + + if (resolver->pacrunner) + g_object_unref (resolver->pacrunner); + + G_OBJECT_CLASS (g_proxy_resolver_gnome_parent_class)->finalize (object); +} + +static void +g_proxy_resolver_gnome_init (GProxyResolverGnome *resolver) +{ + resolver->proxy_settings = g_settings_new (GNOME_PROXY_SETTINGS_SCHEMA); + g_signal_connect (resolver->proxy_settings, "changed", + G_CALLBACK (gsettings_changed), resolver); + resolver->http_settings = g_settings_new (GNOME_PROXY_HTTP_SETTINGS_SCHEMA); + g_signal_connect (resolver->http_settings, "changed", + G_CALLBACK (gsettings_changed), resolver); + resolver->https_settings = g_settings_new (GNOME_PROXY_HTTPS_SETTINGS_SCHEMA); + g_signal_connect (resolver->https_settings, "changed", + G_CALLBACK (gsettings_changed), resolver); + resolver->ftp_settings = g_settings_new (GNOME_PROXY_FTP_SETTINGS_SCHEMA); + g_signal_connect (resolver->ftp_settings, "changed", + G_CALLBACK (gsettings_changed), resolver); + resolver->socks_settings = g_settings_new (GNOME_PROXY_SOCKS_SETTINGS_SCHEMA); + g_signal_connect (resolver->socks_settings, "changed", + G_CALLBACK (gsettings_changed), resolver); + + resolver->need_update = TRUE; +} + +static void +update_settings (GProxyResolverGnome *resolver) +{ + gchar *host; + guint port; + int i; + + resolver->need_update = FALSE; + + free_settings (resolver); + + resolver->mode = + g_settings_get_enum (resolver->proxy_settings, GNOME_PROXY_MODE_KEY); + resolver->autoconfig_url = + g_settings_get_string (resolver->proxy_settings, GNOME_PROXY_AUTOCONFIG_URL_KEY); + resolver->use_same_proxy = + g_settings_get_boolean (resolver->proxy_settings, GNOME_PROXY_USE_SAME_PROXY_KEY); + + resolver->ignore_hosts = + g_settings_get_strv (resolver->proxy_settings, GNOME_PROXY_IGNORE_HOSTS_KEY); + + if (resolver->ignore_hosts && resolver->ignore_hosts[0]) + { + GArray *ignore_ips; + gchar *slash; + GInetAddress *iaddr; + GProxyResolverGnomeIPMask mask; + + ignore_ips = g_array_new (TRUE, FALSE, sizeof (GProxyResolverGnomeIPMask)); + for (i = 0; resolver->ignore_hosts[i]; i++) + { + host = resolver->ignore_hosts[i]; + slash = strchr (host, '/'); + if (slash) + host = g_strndup (host, slash - host); + iaddr = g_inet_address_new_from_string (host); + if (iaddr) + { + int addrlen = g_inet_address_get_native_size (iaddr); + + memset (&mask, 0, sizeof (mask)); + mask.family = g_inet_address_get_family (iaddr); + memcpy (mask.mask, g_inet_address_to_bytes (iaddr), addrlen); + if (slash) + { + mask.length = atoi (slash + 1); + if (mask.length > addrlen * 8) + { + g_warning("ignore_host '%s' has invalid mask length", + resolver->ignore_hosts[i]); + mask.length = addrlen; + } + } + else + mask.length = 0; + + g_array_append_val (ignore_ips, mask); + + g_object_unref (iaddr); + } + if (slash) + g_free (host); + } + + if (ignore_ips->len) + resolver->ignore_ips = (GProxyResolverGnomeIPMask *)g_array_free (ignore_ips, FALSE); + else + { + g_array_free (ignore_ips, TRUE); + resolver->ignore_ips = NULL; + } + } + else + resolver->ignore_ips = NULL; + + host = g_settings_get_string (resolver->http_settings, GNOME_PROXY_HTTP_HOST_KEY); + port = g_settings_get_int (resolver->http_settings, GNOME_PROXY_HTTP_PORT_KEY); + + if (g_settings_get_boolean (resolver->http_settings, GNOME_PROXY_HTTP_USE_AUTH_KEY)) + { + gchar *user, *password; + gchar *enc_user, *enc_password; + + user = g_settings_get_string (resolver->http_settings, GNOME_PROXY_HTTP_USER_KEY); + enc_user = g_uri_escape_string (user, NULL, TRUE); + g_free (user); + password = g_settings_get_string (resolver->http_settings, GNOME_PROXY_HTTP_PASSWORD_KEY); + enc_password = g_uri_escape_string (password, NULL, TRUE); + g_free (password); + + resolver->http_proxy = g_strdup_printf ("http://%s:%s@%s:%u", + enc_user, enc_password, + host, port); + g_free (enc_user); + g_free (enc_password); + } + else + resolver->http_proxy = g_strdup_printf ("http://%s:%u", host, port); + g_free (host); + + host = g_settings_get_string (resolver->https_settings, GNOME_PROXY_HTTPS_HOST_KEY); + port = g_settings_get_int (resolver->https_settings, GNOME_PROXY_HTTPS_PORT_KEY); + if (host && *host) + resolver->https_proxy = g_strdup_printf ("http://%s:%u", host, port); + g_free (host); + + host = g_settings_get_string (resolver->ftp_settings, GNOME_PROXY_FTP_HOST_KEY); + port = g_settings_get_int (resolver->ftp_settings, GNOME_PROXY_FTP_PORT_KEY); + if (host && *host) + resolver->ftp_proxy = g_strdup_printf ("ftp://%s:%u", host, port); + g_free (host); + + host = g_settings_get_string (resolver->socks_settings, GNOME_PROXY_SOCKS_HOST_KEY); + port = g_settings_get_int (resolver->socks_settings, GNOME_PROXY_SOCKS_PORT_KEY); + if (host && *host) + resolver->socks_authority = g_strdup_printf ("%s:%u", host, port); + g_free (host); + + if (resolver->mode == G_DESKTOP_PROXY_MODE_AUTO && !resolver->pacrunner) + { + GError *error = NULL; + resolver->pacrunner = + g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.gtk.GLib.PACRunner", + "/org/gtk/GLib/PACRunner", + "org.gtk.GLib.PACRunner", + NULL, &error); + if (error) + { + g_warning ("Could not start proxy autoconfiguration helper:" + "\n %s\nProxy autoconfiguration will not work", + error->message); + } + } + else if (resolver->mode != G_DESKTOP_PROXY_MODE_AUTO && resolver->pacrunner) + { + g_object_unref (resolver->pacrunner); + resolver->pacrunner = NULL; + } +} + +static gboolean +g_proxy_resolver_gnome_is_supported (GProxyResolver *object) +{ + GProxyResolverGnome *resolver = G_PROXY_RESOLVER_GNOME (object); + + return resolver->proxy_settings != NULL; +} + +static gboolean +parse_uri (const gchar *uri, + gchar **scheme, + gchar **host) +{ + const gchar *authority, *hoststart, *hostend, *at, *colon, *slash; + + colon = strchr (uri, ':'); + if (!colon || strncmp (colon, "://", 3) != 0) + return FALSE; + + *scheme = g_strndup (uri, colon - uri); + + authority = colon + 3; + colon = strchr (authority, ':'); + slash = strchr (authority, '/'); + if (colon && (!slash || colon < slash)) + hostend = colon; + else if (slash) + hostend = slash; + else + hostend = authority + strlen (authority); + + at = strchr (authority, '@'); + if (at && at < hostend) + hoststart = at + 1; + else + hoststart = authority; + *host = g_strndup (hoststart, hostend - hoststart); + + return TRUE; +} + +static gboolean +masked_compare (const guint8 *mask, + const guint8 *addr, + int maskbits) +{ + int bytes, bits; + + if (maskbits == 0) + return TRUE; + + bytes = maskbits / 8; + if (bytes != 0 && memcmp (mask, addr, bytes) != 0) + return FALSE; + + bits = maskbits % 8; + return mask[bytes] == (addr[bytes] & (0xFF << (8 - bits))); +} + +static gboolean +ignore_host (GProxyResolverGnome *resolver, + const gchar *host) +{ + gboolean ignore = FALSE; + gint i; + + if (resolver->ignore_ips) + { + GInetAddress *iaddr; + + iaddr = g_inet_address_new_from_string (host); + if (iaddr) + { + GSocketFamily family = g_inet_address_get_family (iaddr); + const guint8 *addr = g_inet_address_to_bytes (iaddr); + + for (i = 0; resolver->ignore_ips[i].length; i++) + { + if (resolver->ignore_ips[i].family == family && + masked_compare (resolver->ignore_ips[i].mask, addr, + resolver->ignore_ips[i].length)) + { + ignore = TRUE; + break; + } + } + + g_object_unref (iaddr); + return ignore; + } + } + + if (resolver->ignore_hosts && resolver->ignore_hosts[0]) + { + gchar *ascii_host = NULL; + + if (g_hostname_is_non_ascii (host)) + host = ascii_host = g_hostname_to_ascii (host); + + for (i = 0; resolver->ignore_hosts[i]; i++) + { + if (!g_ascii_strcasecmp (host, resolver->ignore_hosts[i])) + { + ignore = TRUE; + break; + } + } + + g_free (ascii_host); + } + + return ignore; +} + +static gchar ** +g_proxy_resolver_gnome_lookup (GProxyResolver *proxy_resolver, + const gchar *uri, + GCancellable *cancellable, + GError **error) +{ + GProxyResolverGnome *resolver = G_PROXY_RESOLVER_GNOME (proxy_resolver); + gchar *scheme = NULL, *host = NULL; + const gchar *proxy = "direct://"; + gchar **proxies = NULL; + + if (resolver->need_update) + update_settings (resolver); + + if (resolver->mode == G_DESKTOP_PROXY_MODE_NONE) + goto done; + + /* FIXME: use guri when it lands... */ + if (!parse_uri (uri, &scheme, &host)) + goto done; + if (ignore_host (resolver, host)) + goto done; + + if (resolver->pacrunner) + { + GVariant *vproxies; + + vproxies = g_dbus_proxy_call_sync (resolver->pacrunner, + "Lookup", + g_variant_new ("(ss)", + resolver->autoconfig_url, + uri), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, error); + if (vproxies) + { + g_variant_get (vproxies, "(^as)", &proxies); + g_variant_unref (vproxies); + } + } + else if (resolver->ftp_proxy && + (!strcmp (scheme, "ftp") || !strcmp (scheme, "ftps"))) + { + proxy = resolver->ftp_proxy; + } + else if (resolver->https_proxy && !strcmp (scheme, "https")) + { + proxy = resolver->https_proxy; + } + else if (resolver->http_proxy && + (!strcmp (scheme, "http") || !strcmp (scheme, "https"))) + { + proxy = resolver->http_proxy; + } + else if (resolver->socks_authority) + { + proxies = g_new0 (gchar *, 4); + proxies[0] = g_strdup_printf ("socks5://%s", resolver->socks_authority); + proxies[1] = g_strdup_printf ("socks4a://%s", resolver->socks_authority); + proxies[2] = g_strdup_printf ("socks4://%s", resolver->socks_authority); + } + else if (resolver->use_same_proxy && resolver->http_proxy) + { + proxy = resolver->http_proxy; + } + +done: + g_free (scheme); + g_free (host); + + if (!proxies) + { + proxies = g_new0 (gchar *, 2); + proxies[0] = g_strdup (proxy); + } + return proxies; +} + +static void +got_autoconfig_proxies (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + GVariant *vproxies; + char **proxies; + GError *error = NULL; + + vproxies = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), + result, &error); + if (vproxies) + { + g_variant_get (vproxies, "(^as)", &proxies); + g_simple_async_result_set_op_res_gpointer (simple, proxies, + (GDestroyNotify)g_strfreev); + g_variant_unref (vproxies); + } + else + { + g_simple_async_result_set_from_error (simple, error); + g_error_free (error); + } + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +static void +g_proxy_resolver_gnome_lookup_async (GProxyResolver *proxy_resolver, + const gchar *uri, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GProxyResolverGnome *resolver = G_PROXY_RESOLVER_GNOME (proxy_resolver); + GSimpleAsyncResult *simple; + + simple = g_simple_async_result_new (G_OBJECT (resolver), + callback, user_data, + g_proxy_resolver_gnome_lookup_async); + + if (resolver->pacrunner) + { + g_dbus_proxy_call (resolver->pacrunner, + "Lookup", + g_variant_new ("(ss)", + resolver->autoconfig_url, + uri), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + got_autoconfig_proxies, + simple); + } + else + { + GError *error = NULL; + char **proxies; + + proxies = g_proxy_resolver_gnome_lookup (proxy_resolver, uri, + cancellable, &error); + if (proxies) + { + g_simple_async_result_set_op_res_gpointer (simple, proxies, + (GDestroyNotify)g_strfreev); + } + else + { + g_simple_async_result_set_from_error (simple, error); + g_error_free (error); + } + g_simple_async_result_complete_in_idle (simple); + g_object_unref (simple); + } +} + +static gchar ** +g_proxy_resolver_gnome_lookup_finish (GProxyResolver *resolver, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + gchar **proxies; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (resolver), g_proxy_resolver_gnome_lookup_async), NULL); + + simple = G_SIMPLE_ASYNC_RESULT (result); + + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + + proxies = g_simple_async_result_get_op_res_gpointer (simple); + return g_strdupv (proxies); +} + +static void +g_proxy_resolver_gnome_class_init (GProxyResolverGnomeClass *resolver_class) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (resolver_class); + object_class->finalize = g_proxy_resolver_gnome_finalize; +} + +static void +g_proxy_resolver_gnome_iface_init (GProxyResolverInterface *iface) +{ + iface->is_supported = g_proxy_resolver_gnome_is_supported; + iface->lookup = g_proxy_resolver_gnome_lookup; + iface->lookup_async = g_proxy_resolver_gnome_lookup_async; + iface->lookup_finish = g_proxy_resolver_gnome_lookup_finish; +} + +void +g_proxy_resolver_gnome_register (GIOModule *module) +{ + g_proxy_resolver_gnome_register_type (G_TYPE_MODULE (module)); + g_io_extension_point_implement (G_PROXY_RESOLVER_EXTENSION_POINT_NAME, + g_proxy_resolver_gnome_get_type(), + "gnome", + 80); +} diff --git a/proxy/gnome/gproxyresolvergnome.h b/proxy/gnome/gproxyresolvergnome.h new file mode 100644 index 0000000..be173a4 --- /dev/null +++ b/proxy/gnome/gproxyresolvergnome.h @@ -0,0 +1,48 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2010 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 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, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __G_PROXY_RESOLVER_GNOME_H__ +#define __G_PROXY_RESOLVER_GNOME_H__ + +#include +#include + +G_BEGIN_DECLS + +#define G_TYPE_PROXY_RESOLVER_GNOME (g_proxy_resolver_gnome_get_type ()) +#define G_PROXY_RESOLVER_GNOME(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_PROXY_RESOLVER_GNOME, GProxyResolverGnome)) +#define G_PROXY_RESOLVER_GNOME_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_PROXY_RESOLVER_GNOME, GProxyResolverGnomeClass)) +#define G_IS_PROXY_RESOLVER_GNOME(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_PROXY_RESOLVER_GNOME)) +#define G_IS_PROXY_RESOLVER_GNOME_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_PROXY_RESOLVER_GNOME)) +#define G_PROXY_RESOLVER_GNOME_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_PROXY_RESOLVER_GNOME, GProxyResolverGnomeClass)) + +typedef struct _GProxyResolverGnome GProxyResolverGnome; +typedef struct _GProxyResolverGnomeClass GProxyResolverGnomeClass; + +struct _GProxyResolverGnomeClass { + GObjectClass parent_class; +}; + +GType g_proxy_resolver_gnome_get_type (void); +void g_proxy_resolver_gnome_register (GIOModule *module); + +G_END_DECLS + +#endif /* __G_PROXY_RESOLVER_GNOME_H__ */