diff options
author | Dan Winship <danw@src.gnome.org> | 2009-03-09 23:35:25 +0000 |
---|---|---|
committer | Dan Winship <danw@src.gnome.org> | 2009-03-09 23:35:25 +0000 |
commit | a9b0e0a071825ec0b29d9bc09cc9770c419b8481 (patch) | |
tree | a622da7030437c438c9e1b8f5673eb53c8d8044e | |
parent | 777915733e447d61afd05e80555d900bb74e6dd2 (diff) | |
download | libsoup-a9b0e0a071825ec0b29d9bc09cc9770c419b8481.tar.gz libsoup-a9b0e0a071825ec0b29d9bc09cc9770c419b8481.tar.bz2 libsoup-a9b0e0a071825ec0b29d9bc09cc9770c419b8481.zip |
Bug 571527 – gvfsd-http crashed with SIGSEGV in
g_hash_table_lookup().
As currently written, libproxy's gnome plugin causes intermittent
gvfsd-http crashes, and I didn't have time to come up with either
a fix or a workaround. So for 2.26.0 we will fall back to using
the GConf-based proxy resolver. Hopefully to be fixed for 2.26.1.
* configure.in: require both gconf and libproxy if building
--with-gnome
* libsoup/soup-proxy-resolver-gconf.c: bring this back.
* libsoup/soup-gnome-features.c
(soup_proxy_resolver_gnome_get_type): use gconf instead of
libproxy
* libsoup/Makefile.am: updates
svn path=/trunk/; revision=1247
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | configure.in | 19 | ||||
-rw-r--r-- | docs/reference/Makefile.am | 3 | ||||
-rw-r--r-- | libsoup/Makefile.am | 4 | ||||
-rw-r--r-- | libsoup/soup-gnome-features.c | 6 | ||||
-rw-r--r-- | libsoup/soup-proxy-resolver-gconf.c | 316 | ||||
-rw-r--r-- | libsoup/soup-proxy-resolver-gconf.h | 32 |
7 files changed, 393 insertions, 8 deletions
@@ -1,3 +1,24 @@ +2009-03-09 Dan Winship <danw@gnome.org> + + Bug 571527 – gvfsd-http crashed with SIGSEGV in + g_hash_table_lookup(). + + As currently written, libproxy's gnome plugin causes intermittent + gvfsd-http crashes, and I didn't have time to come up with either + a fix or a workaround. So for 2.26.0 we will fall back to using + the GConf-based proxy resolver. Hopefully to be fixed for 2.26.1. + + * configure.in: require both gconf and libproxy if building + --with-gnome + + * libsoup/soup-proxy-resolver-gconf.c: bring this back. + + * libsoup/soup-gnome-features.c + (soup_proxy_resolver_gnome_get_type): use gconf instead of + libproxy + + * libsoup/Makefile.am: updates + 2009-03-08 Dan Winship <danw@gnome.org> * libsoup/*.c: gtk-doc updates. In particular, document a bunch of diff --git a/configure.in b/configure.in index da9b1c77..57565d47 100644 --- a/configure.in +++ b/configure.in @@ -184,14 +184,23 @@ AM_CONDITIONAL(BUILD_LIBSOUP_GNOME, test $with_gnome != no) if test $with_gnome != no; then AC_DEFINE(HAVE_GNOME, 1, [Defined if GNOME support is enabled]) - PKG_CHECK_MODULES(LIBPROXY, libproxy-1.0, - :, [AC_MSG_ERROR(dnl + PKG_CHECK_MODULES(LIBPROXY, libproxy-1.0, :, [AC_MSG_ERROR(dnl [Could not find libproxy: $LIBPROXY_PKG_ERRORS -libproxy is now a dependency of GNOME, and is required for proxy -support in libsoup. +This is required for GNOME proxy support. + +Pass "--without-gnome" to configure if you want to build libsoup +without GNOME support.])]) + + PKG_CHECK_MODULES(GCONF, gconf-2.0, , [AC_MSG_ERROR(dnl +[Could not find GConf: + +$GCONF_PKG_ERRORS + +Due to bugs in libproxy as of the GNOME 2.26 freeze date, GConf is +*also* required for GNOME proxy support. Pass "--without-gnome" to configure if you want to build libsoup without GNOME support.])]) @@ -205,6 +214,8 @@ Pass "--without-gnome" to configure if you want to build libsoup without GNOME support.])]) fi AC_SUBST(HAVE_GNOME) +AC_SUBST(GCONF_CFLAGS) +AC_SUBST(GCONF_LIBS) AC_SUBST(LIBPROXY_CFLAGS) AC_SUBST(LIBPROXY_LIBS) AC_SUBST(SQLITE_CFLAGS) diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am index 0f22d4ae..cd067dc7 100644 --- a/docs/reference/Makefile.am +++ b/docs/reference/Makefile.am @@ -35,7 +35,8 @@ IGNORE_HFILES= soup.h soup-marshal.h soup-enum-types.h \ soup-connection.h soup-connection-ntlm.h \ soup-dns.h soup-auth-manager.h soup-auth-manager-ntlm.h \ soup-message-queue.h soup-path-map.h soup-ssl.h \ - soup-proxy-resolver-libproxy.h soup-proxy-resolver-static.h + soup-proxy-resolver-libproxy.h soup-proxy-resolver-gconf.h \ + soup-proxy-resolver-static.h # Images to copy into HTML directory. HTML_IMAGES = diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am index e68cbad3..11ca32be 100644 --- a/libsoup/Makefile.am +++ b/libsoup/Makefile.am @@ -11,6 +11,7 @@ INCLUDES = \ $(SOUP_MAINTAINER_FLAGS) \ $(GLIB_CFLAGS) \ $(XML_CFLAGS) \ + $(GCONF_CFLAGS) \ $(LIBPROXY_CFLAGS) \ $(SQLITE_CFLAGS) \ $(LIBGCRYPT_CFLAGS) \ @@ -174,12 +175,15 @@ libsoup_gnome_2_4_la_LDFLAGS = $(libsoup_2_4_la_LDFLAGS) libsoup_gnome_2_4_la_LIBADD = \ libsoup-2.4.la \ $(GLIB_LIBS) \ + $(GCONF_LIBS) \ $(LIBPROXY_LIBS) \ $(SQLITE_LIBS) libsoup_gnome_2_4_la_SOURCES = \ soup-cookie-jar-sqlite.c \ soup-gnome-features.c \ + soup-proxy-resolver-gconf.h \ + soup-proxy-resolver-gconf.c \ soup-proxy-resolver-libproxy.h \ soup-proxy-resolver-libproxy.c diff --git a/libsoup/soup-gnome-features.c b/libsoup/soup-gnome-features.c index 2a85e8c9..549af391 100644 --- a/libsoup/soup-gnome-features.c +++ b/libsoup/soup-gnome-features.c @@ -11,7 +11,7 @@ #include "soup-gnome-features.h" -#include "soup-proxy-resolver-libproxy.h" +#include "soup-proxy-resolver-gconf.h" /** * SOUP_TYPE_PROXY_RESOLVER_GNOME: @@ -19,7 +19,7 @@ * This returns the #GType of a #SoupProxyResolver that can be used to * resolve HTTP proxies for GNOME applications. You can add this to * a session using soup_session_add_feature_by_type() or by using the - * %SOUP_SESSION_ADD_FEATURE_BY_TIME construct-time property. + * %SOUP_SESSION_ADD_FEATURE_BY_TYPE construct-time property. * * This feature is included in %SOUP_TYPE_GNOME_FEATURES_2_26, so if * you are using that feature, you do not need to include this feature @@ -30,7 +30,7 @@ GType soup_proxy_resolver_gnome_get_type (void) { - return SOUP_TYPE_PROXY_RESOLVER_LIBPROXY; + return SOUP_TYPE_PROXY_RESOLVER_GCONF; } /** diff --git a/libsoup/soup-proxy-resolver-gconf.c b/libsoup/soup-proxy-resolver-gconf.c new file mode 100644 index 00000000..f3063b24 --- /dev/null +++ b/libsoup/soup-proxy-resolver-gconf.c @@ -0,0 +1,316 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-proxy-resolver-gconf.c: GConf-based proxy resolution + * + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> + +#include "soup-proxy-resolver-gconf.h" +#include "soup-address.h" +#include "soup-dns.h" +#include "soup-message.h" +#include "soup-misc.h" +#include "soup-session-feature.h" + +#include <gconf/gconf-client.h> + +typedef struct { + GMutex *lock; + GConfClient *gconf; + + SoupAddress *proxy_addr; + char *user, *password; + + GSList *ignore_hosts; +} SoupProxyResolverGConfPrivate; +#define SOUP_PROXY_RESOLVER_GCONF_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_PROXY_RESOLVER_GCONF, SoupProxyResolverGConfPrivate)) + +static void soup_proxy_resolver_gconf_interface_init (SoupProxyResolverInterface *proxy_resolver_interface); + +G_DEFINE_TYPE_EXTENDED (SoupProxyResolverGConf, soup_proxy_resolver_gconf, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, NULL) + G_IMPLEMENT_INTERFACE (SOUP_TYPE_PROXY_RESOLVER, soup_proxy_resolver_gconf_interface_init)) + +static void gconf_value_changed (GConfClient *client, const char *key, + GConfValue *value, gpointer user_data); +static void update_proxy_settings (SoupProxyResolverGConfPrivate *priv); +static void free_proxy_settings (SoupProxyResolverGConfPrivate *priv); + +static void get_proxy_async (SoupProxyResolver *proxy_resolver, + SoupMessage *msg, + GMainContext *async_context, + GCancellable *cancellable, + SoupProxyResolverCallback callback, + gpointer user_data); +static guint get_proxy_sync (SoupProxyResolver *proxy_resolver, + SoupMessage *msg, + GCancellable *cancellable, + SoupAddress **addr); + +static void +soup_proxy_resolver_gconf_init (SoupProxyResolverGConf *resolver_gconf) +{ + SoupProxyResolverGConfPrivate *priv = + SOUP_PROXY_RESOLVER_GCONF_GET_PRIVATE (resolver_gconf); + + priv->lock = g_mutex_new (); + priv->gconf = gconf_client_get_default (); + + gconf_client_add_dir (priv->gconf, "/system/http_proxy", + GCONF_CLIENT_PRELOAD_RECURSIVE, NULL); + g_signal_connect (priv->gconf, "value_changed", + G_CALLBACK (gconf_value_changed), + resolver_gconf); + update_proxy_settings (priv); +} + +static void +finalize (GObject *object) +{ + SoupProxyResolverGConfPrivate *priv = + SOUP_PROXY_RESOLVER_GCONF_GET_PRIVATE (object); + + g_signal_handlers_disconnect_by_func (priv->gconf, gconf_value_changed, + object); + free_proxy_settings (priv); + g_object_unref (priv->gconf); + g_mutex_free (priv->lock); + + G_OBJECT_CLASS (soup_proxy_resolver_gconf_parent_class)->finalize (object); +} + +static void +soup_proxy_resolver_gconf_class_init (SoupProxyResolverGConfClass *gconf_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (gconf_class); + + g_type_class_add_private (gconf_class, sizeof (SoupProxyResolverGConfPrivate)); + + object_class->finalize = finalize; +} + +static void +soup_proxy_resolver_gconf_interface_init (SoupProxyResolverInterface *proxy_resolver_interface) +{ + proxy_resolver_interface->get_proxy_async = get_proxy_async; + proxy_resolver_interface->get_proxy_sync = get_proxy_sync; +} + +SoupProxyResolver * +soup_proxy_resolver_gconf_new (void) +{ + return g_object_new (SOUP_TYPE_PROXY_RESOLVER_GCONF, NULL); +} + +static void +free_proxy_settings (SoupProxyResolverGConfPrivate *priv) +{ + GSList *l; + + if (priv->proxy_addr) { + g_object_unref (priv->proxy_addr); + priv->proxy_addr = NULL; + } + g_free (priv->user); + priv->user = NULL; + g_free (priv->password); + priv->password = NULL; + + for (l = priv->ignore_hosts; l; l = l->next) + g_free (l->data); + g_slist_free (priv->ignore_hosts); + priv->ignore_hosts = NULL; +} + +#define SOUP_GCONF_PROXY_ENABLED "/system/http_proxy/use_http_proxy" +#define SOUP_GCONF_PROXY_USE_AUTH "/system/http_proxy/use_authentication" +#define SOUP_GCONF_PROXY_HOST "/system/http_proxy/host" +#define SOUP_GCONF_PROXY_PORT "/system/http_proxy/port" +#define SOUP_GCONF_PROXY_USER "/system/http_proxy/authentication_user" +#define SOUP_GCONF_PROXY_PASSWORD "/system/http_proxy/authentication_password" +#define SOUP_GCONF_PROXY_IGNORE_HOSTS "/system/http_proxy/ignore_hosts" + +static void +update_proxy_settings (SoupProxyResolverGConfPrivate *priv) +{ + GSList *ignore_hosts, *i; + char *host; + guint port; + + if (!gconf_client_get_bool (priv->gconf, SOUP_GCONF_PROXY_ENABLED, NULL)) + return; + + host = gconf_client_get_string ( + priv->gconf, SOUP_GCONF_PROXY_HOST, NULL); + if (!host) + return; + port = gconf_client_get_int ( + priv->gconf, SOUP_GCONF_PROXY_PORT, NULL); + priv->proxy_addr = soup_address_new (host, port); + g_free (host); + + if (gconf_client_get_bool (priv->gconf, SOUP_GCONF_PROXY_USE_AUTH, NULL)) { + priv->user = gconf_client_get_string ( + priv->gconf, SOUP_GCONF_PROXY_USER, NULL); + priv->password = gconf_client_get_string ( + priv->gconf, SOUP_GCONF_PROXY_PASSWORD, NULL); + } + + ignore_hosts = gconf_client_get_list ( + priv->gconf, SOUP_GCONF_PROXY_IGNORE_HOSTS, + GCONF_VALUE_STRING, NULL); + for (i = ignore_hosts; i; i = i->next) { + host = i->data; + + /* FIXME: not right. Need to handle addresses, masks */ + priv->ignore_hosts = g_slist_prepend ( + priv->ignore_hosts, + g_ascii_strdown (host, -1)); + g_free (host); + } + g_slist_free (ignore_hosts); +} + +static void +gconf_value_changed (GConfClient *client, const char *key, + GConfValue *value, gpointer user_data) +{ + SoupProxyResolverGConf *resolver_gconf = user_data; + SoupProxyResolverGConfPrivate *priv = + SOUP_PROXY_RESOLVER_GCONF_GET_PRIVATE (resolver_gconf); + + free_proxy_settings (priv); + update_proxy_settings (priv); +} + +static gboolean +message_has_ignored_address (SoupProxyResolverGConfPrivate *priv, + SoupMessage *msg) +{ + SoupAddress *addr; + struct sockaddr *sockaddr; + const char *name, *ignore_name; + char *hostname; + GSList *l; + int len; + + if (!priv->ignore_hosts) + return FALSE; + + addr = soup_message_get_address (msg); + name = soup_address_get_name (addr); + sockaddr = soup_address_get_sockaddr (addr, &len); + g_return_val_if_fail (name != NULL && sockaddr != NULL, FALSE); + + hostname = g_ascii_strdown (name, -1); + for (l = priv->ignore_hosts; l; l = l->next) { + ignore_name = l->data; + + if (*ignore_name == '*') { + if (g_str_has_suffix (hostname, ignore_name + 1)) { + g_free (hostname); + return TRUE; + } + } else if (strcmp (hostname, ignore_name) == 0) { + g_free (hostname); + return TRUE; + } + } + g_free (hostname); + + return FALSE; +} + +static SoupAddress * +get_proxy_for_message (SoupProxyResolver *proxy_resolver, + SoupMessage *msg) +{ + SoupProxyResolverGConfPrivate *priv = + SOUP_PROXY_RESOLVER_GCONF_GET_PRIVATE (proxy_resolver); + SoupAddress *addr; + + g_mutex_lock (priv->lock); + + if (!priv->proxy_addr || message_has_ignored_address (priv, msg)) { + g_mutex_unlock (priv->lock); + return NULL; + } + + addr = g_object_ref (priv->proxy_addr); + g_mutex_unlock (priv->lock); + return addr; +} + +typedef struct { + SoupProxyResolver *proxy_resolver; + SoupMessage *msg; + SoupAddress *addr; + SoupProxyResolverCallback callback; + gpointer user_data; +} SoupGConfAsyncData; + +static void +resolved_address (SoupAddress *addr, guint status, gpointer data) +{ + SoupGConfAsyncData *sgad = data; + + sgad->callback (sgad->proxy_resolver, sgad->msg, + soup_status_proxify (status), addr, + sgad->user_data); + g_object_unref (sgad->proxy_resolver); + g_object_unref (sgad->msg); + if (addr) + g_object_unref (addr); + g_slice_free (SoupGConfAsyncData, sgad); +} + +static gboolean +resolved_no_address (gpointer data) +{ + resolved_address (NULL, SOUP_STATUS_OK, data); + return FALSE; +} + +static void +get_proxy_async (SoupProxyResolver *proxy_resolver, + SoupMessage *msg, + GMainContext *async_context, + GCancellable *cancellable, + SoupProxyResolverCallback callback, + gpointer user_data) +{ + SoupGConfAsyncData *sgad; + + sgad = g_slice_new0 (SoupGConfAsyncData); + sgad->proxy_resolver = g_object_ref (proxy_resolver); + sgad->msg = g_object_ref (msg); + sgad->callback = callback; + sgad->user_data = user_data; + sgad->addr = get_proxy_for_message (proxy_resolver, msg); + + if (sgad->addr) { + soup_address_resolve_async (sgad->addr, async_context, + cancellable, resolved_address, + sgad); + } else + soup_add_idle (async_context, resolved_no_address, sgad); +} + +static guint +get_proxy_sync (SoupProxyResolver *proxy_resolver, + SoupMessage *msg, + GCancellable *cancellable, + SoupAddress **addr) +{ + *addr = get_proxy_for_message (proxy_resolver, msg); + if (*addr) + return soup_status_proxify (soup_address_resolve_sync (*addr, cancellable)); + else + return SOUP_STATUS_OK; +} diff --git a/libsoup/soup-proxy-resolver-gconf.h b/libsoup/soup-proxy-resolver-gconf.h new file mode 100644 index 00000000..d14f7f33 --- /dev/null +++ b/libsoup/soup-proxy-resolver-gconf.h @@ -0,0 +1,32 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifndef SOUP_PROXY_RESOLVER_GCONF_H +#define SOUP_PROXY_RESOLVER_GCONF_H 1 + +#include <libsoup/soup-proxy-resolver.h> + +#define SOUP_TYPE_PROXY_RESOLVER_GCONF (soup_proxy_resolver_gconf_get_type ()) +#define SOUP_PROXY_RESOLVER_GCONF(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_PROXY_RESOLVER_GCONF, SoupProxyResolverGConf)) +#define SOUP_PROXY_RESOLVER_GCONF_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_PROXY_RESOLVER_GCONF, SoupProxyResolverGConfClass)) +#define SOUP_IS_PROXY_RESOLVER_GCONF(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_PROXY_RESOLVER_GCONF)) +#define SOUP_IS_PROXY_RESOLVER_GCONF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_PROXY_RESOLVER_GCONF)) +#define SOUP_PROXY_RESOLVER_GCONF_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_PROXY_RESOLVER_GCONF, SoupProxyResolverGConfClass)) + +typedef struct { + GObject parent; + +} SoupProxyResolverGConf; + +typedef struct { + GObjectClass parent_class; + +} SoupProxyResolverGConfClass; + +GType soup_proxy_resolver_gconf_get_type (void); + +SoupProxyResolver *soup_proxy_resolver_gconf_new (void); + +#endif /*SOUP_PROXY_RESOLVER_GCONF_H*/ |