summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@src.gnome.org>2009-03-09 23:35:25 +0000
committerDan Winship <danw@src.gnome.org>2009-03-09 23:35:25 +0000
commita9b0e0a071825ec0b29d9bc09cc9770c419b8481 (patch)
treea622da7030437c438c9e1b8f5673eb53c8d8044e
parent777915733e447d61afd05e80555d900bb74e6dd2 (diff)
downloadlibsoup-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--ChangeLog21
-rw-r--r--configure.in19
-rw-r--r--docs/reference/Makefile.am3
-rw-r--r--libsoup/Makefile.am4
-rw-r--r--libsoup/soup-gnome-features.c6
-rw-r--r--libsoup/soup-proxy-resolver-gconf.c316
-rw-r--r--libsoup/soup-proxy-resolver-gconf.h32
7 files changed, 393 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index 3c93ffe3..4c021e00 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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*/