summaryrefslogtreecommitdiff
path: root/libsoup/soup-auth-manager.c
diff options
context:
space:
mode:
authorDan Winship <danw@src.gnome.org>2008-04-08 22:13:03 +0000
committerDan Winship <danw@src.gnome.org>2008-04-08 22:13:03 +0000
commite1c6bf7690fc035e0a0560ebc6f3030eee6b3a8d (patch)
treedad9aeeb321a20266681530452f6a51efbcbc803 /libsoup/soup-auth-manager.c
parent700b6a340c5142255b2189fb78580ca2dc96a1ae (diff)
downloadlibsoup-e1c6bf7690fc035e0a0560ebc6f3030eee6b3a8d.tar.gz
Make this a GObject and specifically a SoupSessionFeature. Add an
* libsoup/soup-auth-manager.c: Make this a GObject and specifically a SoupSessionFeature. Add an "authenticate" signal, and emit that rather than explicitly calling into the SoupSession and telling it when to emit its own authenticate signal. * libsoup/soup-auth-manager-ntlm.c: Make this a subclass of SoupAuthManager, with NTLM support controllable via a property. * libsoup/soup-session.c (soup_session_init): create an auth_manager of type SOUP_TYPE_AUTH_MANAGER_NTLM, but defaulting to USE_NTLM=FALSE. Connect to its "authenticate" signal, and call soup_session_add_feature() on it. (set_property, get_property): proxy the USE_NTLM property to the auth manager. (auth_manager_authenticate): signal handler for SoupAuthManager "authenticate" signal. (Replaces soup_session_emit_authenticate(), which is no longer needed) svn path=/trunk/; revision=1134
Diffstat (limited to 'libsoup/soup-auth-manager.c')
-rw-r--r--libsoup/soup-auth-manager.c242
1 files changed, 147 insertions, 95 deletions
diff --git a/libsoup/soup-auth-manager.c b/libsoup/soup-auth-manager.c
index 55402b41..4b2a5dee 100644
--- a/libsoup/soup-auth-manager.c
+++ b/libsoup/soup-auth-manager.c
@@ -13,26 +13,43 @@
#include "soup-auth-manager.h"
#include "soup-headers.h"
+#include "soup-marshal.h"
#include "soup-message-private.h"
#include "soup-path-map.h"
#include "soup-session.h"
-#include "soup-session-private.h"
+#include "soup-session-feature.h"
#include "soup-uri.h"
-static void session_request_queued (SoupSession *session, SoupMessage *msg,
- gpointer data);
-static void session_request_started (SoupSession *session, SoupMessage *msg,
- SoupSocket *socket, gpointer data);
-static void session_request_unqueued (SoupSession *session, SoupMessage *msg,
- gpointer data);
+static void soup_auth_manager_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data);
+static SoupSessionFeatureInterface *soup_session_feature_default_interface;
-struct SoupAuthManager {
+static void attach (SoupSessionFeature *feature, SoupSession *session);
+static void request_queued (SoupSessionFeature *feature, SoupSession *session,
+ SoupMessage *msg);
+static void request_started (SoupSessionFeature *feature, SoupSession *session,
+ SoupMessage *msg, SoupSocket *socket);
+static void request_unqueued (SoupSessionFeature *feature,
+ SoupSession *session, SoupMessage *msg);
+
+enum {
+ AUTHENTICATE,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE_WITH_CODE (SoupAuthManager, soup_auth_manager, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE,
+ soup_auth_manager_session_feature_init));
+
+typedef struct {
SoupSession *session;
GPtrArray *auth_types;
SoupAuth *proxy_auth;
GHashTable *auth_hosts;
-};
+} SoupAuthManagerPrivate;
+#define SOUP_AUTH_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_AUTH_MANAGER, SoupAuthManagerPrivate))
typedef struct {
SoupURI *root_uri;
@@ -46,24 +63,14 @@ extern gboolean soup_uri_host_equal (gconstpointer v1,
gconstpointer v2);
extern SoupURI *soup_uri_copy_root (SoupURI *uri);
-SoupAuthManager *
-soup_auth_manager_new (SoupSession *session)
+static void
+soup_auth_manager_init (SoupAuthManager *manager)
{
- SoupAuthManager *manager;
-
- manager = g_slice_new0 (SoupAuthManager);
- manager->session = session;
- manager->auth_types = g_ptr_array_new ();
- manager->auth_hosts = g_hash_table_new (soup_uri_host_hash,
- soup_uri_host_equal);
-
- g_signal_connect (session, "request_queued",
- G_CALLBACK (session_request_queued), manager);
- g_signal_connect (session, "request_started",
- G_CALLBACK (session_request_started), manager);
- g_signal_connect (session, "request_unqueued",
- G_CALLBACK (session_request_unqueued), manager);
- return manager;
+ SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager);
+
+ priv->auth_types = g_ptr_array_new ();
+ priv->auth_hosts = g_hash_table_new (soup_uri_host_hash,
+ soup_uri_host_equal);
}
static gboolean
@@ -82,32 +89,59 @@ foreach_free_host (gpointer key, gpointer value, gpointer data)
return TRUE;
}
-void
-soup_auth_manager_free (SoupAuthManager *manager)
+static void
+finalize (GObject *object)
{
+ SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (object);
int i;
- g_signal_handlers_disconnect_by_func (
- manager->session,
- G_CALLBACK (session_request_queued), manager);
- g_signal_handlers_disconnect_by_func (
- manager->session,
- G_CALLBACK (session_request_started), manager);
- g_signal_handlers_disconnect_by_func (
- manager->session,
- G_CALLBACK (session_request_unqueued), manager);
+ for (i = 0; i < priv->auth_types->len; i++)
+ g_type_class_unref (priv->auth_types->pdata[i]);
+ g_ptr_array_free (priv->auth_types, TRUE);
+
+ g_hash_table_foreach_remove (priv->auth_hosts, foreach_free_host, NULL);
+ g_hash_table_destroy (priv->auth_hosts);
+
+ if (priv->proxy_auth)
+ g_object_unref (priv->proxy_auth);
+
+ G_OBJECT_CLASS (soup_auth_manager_parent_class)->finalize (object);
+}
+
+static void
+soup_auth_manager_class_init (SoupAuthManagerClass *auth_manager_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (auth_manager_class);
- for (i = 0; i < manager->auth_types->len; i++)
- g_type_class_unref (manager->auth_types->pdata[i]);
- g_ptr_array_free (manager->auth_types, TRUE);
+ g_type_class_add_private (auth_manager_class, sizeof (SoupAuthManagerPrivate));
- g_hash_table_foreach_remove (manager->auth_hosts, foreach_free_host, NULL);
- g_hash_table_destroy (manager->auth_hosts);
+ object_class->finalize = finalize;
- if (manager->proxy_auth)
- g_object_unref (manager->proxy_auth);
+ signals[AUTHENTICATE] =
+ g_signal_new ("authenticate",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (SoupAuthManagerClass, authenticate),
+ NULL, NULL,
+ soup_marshal_NONE__OBJECT_OBJECT_BOOLEAN,
+ G_TYPE_NONE, 3,
+ SOUP_TYPE_MESSAGE,
+ SOUP_TYPE_AUTH,
+ G_TYPE_BOOLEAN);
- g_slice_free (SoupAuthManager, manager);
+}
+
+static void
+soup_auth_manager_session_feature_init (SoupSessionFeatureInterface *feature_interface,
+ gpointer interface_data)
+{
+ soup_session_feature_default_interface =
+ g_type_default_interface_peek (SOUP_TYPE_SESSION_FEATURE);
+
+ feature_interface->attach = attach;
+ feature_interface->request_queued = request_queued;
+ feature_interface->request_started = request_started;
+ feature_interface->request_unqueued = request_unqueued;
}
static int
@@ -122,33 +156,53 @@ auth_type_compare_func (gconstpointer a, gconstpointer b)
void
soup_auth_manager_add_type (SoupAuthManager *manager, GType type)
{
+ SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager);
SoupAuthClass *auth_class;
g_return_if_fail (g_type_is_a (type, SOUP_TYPE_AUTH));
auth_class = g_type_class_ref (type);
- g_ptr_array_add (manager->auth_types, auth_class);
- g_ptr_array_sort (manager->auth_types, auth_type_compare_func);
+ g_ptr_array_add (priv->auth_types, auth_class);
+ g_ptr_array_sort (priv->auth_types, auth_type_compare_func);
}
void
soup_auth_manager_remove_type (SoupAuthManager *manager, GType type)
{
+ SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager);
SoupAuthClass *auth_class;
int i;
g_return_if_fail (g_type_is_a (type, SOUP_TYPE_AUTH));
auth_class = g_type_class_peek (type);
- for (i = 0; i < manager->auth_types->len; i++) {
- if (manager->auth_types->pdata[i] == (gpointer)auth_class) {
- g_ptr_array_remove_index (manager->auth_types, i);
+ for (i = 0; i < priv->auth_types->len; i++) {
+ if (priv->auth_types->pdata[i] == (gpointer)auth_class) {
+ g_ptr_array_remove_index (priv->auth_types, i);
g_type_class_unref (auth_class);
return;
}
}
}
+void
+soup_auth_manager_emit_authenticate (SoupAuthManager *manager, SoupMessage *msg,
+ SoupAuth *auth, gboolean retrying)
+{
+ g_signal_emit (manager, signals[AUTHENTICATE], 0, msg, auth, retrying);
+}
+
+static void
+attach (SoupSessionFeature *manager, SoupSession *session)
+{
+ SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager);
+
+ /* FIXME: should support multiple sessions */
+ priv->session = session;
+
+ soup_session_feature_default_interface->attach (manager, session);
+}
+
static inline const char *
auth_header_for_message (SoupMessage *msg)
{
@@ -219,7 +273,7 @@ extract_challenge (const char *challenges, const char *scheme)
}
static SoupAuth *
-create_auth (SoupAuthManager *manager, SoupMessage *msg)
+create_auth (SoupAuthManagerPrivate *priv, SoupMessage *msg)
{
const char *header;
SoupAuthClass *auth_class;
@@ -231,8 +285,8 @@ create_auth (SoupAuthManager *manager, SoupMessage *msg)
if (!header)
return NULL;
- for (i = manager->auth_types->len - 1; i >= 0; i--) {
- auth_class = manager->auth_types->pdata[i];
+ for (i = priv->auth_types->len - 1; i >= 0; i--) {
+ auth_class = priv->auth_types->pdata[i];
challenge = extract_challenge (header, auth_class->scheme_name);
if (challenge)
break;
@@ -246,7 +300,7 @@ create_auth (SoupAuthManager *manager, SoupMessage *msg)
}
static gboolean
-check_auth (SoupAuthManager *manager, SoupMessage *msg, SoupAuth *auth)
+check_auth (SoupMessage *msg, SoupAuth *auth)
{
const char *header;
char *challenge;
@@ -266,29 +320,29 @@ check_auth (SoupAuthManager *manager, SoupMessage *msg, SoupAuth *auth)
}
static SoupAuthHost *
-get_auth_host_for_message (SoupAuthManager *manager, SoupMessage *msg)
+get_auth_host_for_message (SoupAuthManagerPrivate *priv, SoupMessage *msg)
{
SoupAuthHost *host;
SoupURI *source = soup_message_get_uri (msg);
- host = g_hash_table_lookup (manager->auth_hosts, source);
+ host = g_hash_table_lookup (priv->auth_hosts, source);
if (host)
return host;
host = g_slice_new0 (SoupAuthHost);
host->root_uri = soup_uri_copy_root (source);
- g_hash_table_insert (manager->auth_hosts, host->root_uri, host);
+ g_hash_table_insert (priv->auth_hosts, host->root_uri, host);
return host;
}
static SoupAuth *
-lookup_auth (SoupAuthManager *manager, SoupMessage *msg)
+lookup_auth (SoupAuthManagerPrivate *priv, SoupMessage *msg)
{
SoupAuthHost *host;
const char *path, *realm;
- host = get_auth_host_for_message (manager, msg);
+ host = get_auth_host_for_message (priv, msg);
if (!host->auth_realms)
return NULL;
@@ -307,13 +361,14 @@ authenticate_auth (SoupAuthManager *manager, SoupAuth *auth,
SoupMessage *msg, gboolean prior_auth_failed,
gboolean proxy)
{
+ SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager);
SoupURI *uri;
if (soup_auth_is_authenticated (auth))
return TRUE;
if (proxy) {
- g_object_get (G_OBJECT (manager->session),
+ g_object_get (G_OBJECT (priv->session),
SOUP_SESSION_PROXY_URI, &uri,
NULL);
} else
@@ -326,15 +381,15 @@ authenticate_auth (SoupAuthManager *manager, SoupAuth *auth,
}
soup_uri_free (uri);
- soup_session_emit_authenticate (manager->session,
- msg, auth, prior_auth_failed);
+ soup_auth_manager_emit_authenticate (manager, msg, auth,
+ prior_auth_failed);
return soup_auth_is_authenticated (auth);
}
static void
-update_auth (SoupMessage *msg, gpointer user_data)
+update_auth (SoupMessage *msg, gpointer manager)
{
- SoupAuthManager *manager = user_data;
+ SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager);
SoupAuthHost *host;
SoupAuth *auth, *prior_auth, *old_auth;
const char *path;
@@ -342,16 +397,16 @@ update_auth (SoupMessage *msg, gpointer user_data)
GSList *pspace, *p;
gboolean prior_auth_failed = FALSE;
- host = get_auth_host_for_message (manager, msg);
+ host = get_auth_host_for_message (priv, msg);
/* See if we used auth last time */
prior_auth = soup_message_get_auth (msg);
- if (prior_auth && check_auth (manager, msg, prior_auth)) {
+ if (prior_auth && check_auth (msg, prior_auth)) {
auth = prior_auth;
if (!soup_auth_is_authenticated (auth))
prior_auth_failed = TRUE;
} else {
- auth = create_auth (manager, msg);
+ auth = create_auth (priv, msg);
if (!auth)
return;
}
@@ -400,56 +455,54 @@ update_auth (SoupMessage *msg, gpointer user_data)
}
static void
-requeue_if_authenticated (SoupMessage *msg, gpointer user_data)
+requeue_if_authenticated (SoupMessage *msg, gpointer manager)
{
- SoupAuthManager *manager = user_data;
- SoupAuth *auth = lookup_auth (manager, msg);
+ SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager);
+ SoupAuth *auth = lookup_auth (priv, msg);
if (auth && soup_auth_is_authenticated (auth))
- soup_session_requeue_message (manager->session, msg);
+ soup_session_requeue_message (priv->session, msg);
}
static void
-update_proxy_auth (SoupMessage *msg, gpointer user_data)
+update_proxy_auth (SoupMessage *msg, gpointer manager)
{
- SoupAuthManager *manager = user_data;
+ SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager);
SoupAuth *prior_auth;
gboolean prior_auth_failed = FALSE;
/* See if we used auth last time */
prior_auth = soup_message_get_proxy_auth (msg);
- if (prior_auth && check_auth (manager, msg, prior_auth)) {
+ if (prior_auth && check_auth (msg, prior_auth)) {
if (!soup_auth_is_authenticated (prior_auth))
prior_auth_failed = TRUE;
}
- if (!manager->proxy_auth) {
- manager->proxy_auth = create_auth (manager, msg);
- if (!manager->proxy_auth)
+ if (!priv->proxy_auth) {
+ priv->proxy_auth = create_auth (priv, msg);
+ if (!priv->proxy_auth)
return;
}
/* If we need to authenticate, try to do it. */
- authenticate_auth (manager, manager->proxy_auth, msg,
+ authenticate_auth (manager, priv->proxy_auth, msg,
prior_auth_failed, TRUE);
}
static void
-requeue_if_proxy_authenticated (SoupMessage *msg, gpointer user_data)
+requeue_if_proxy_authenticated (SoupMessage *msg, gpointer manager)
{
- SoupAuthManager *manager = user_data;
- SoupAuth *auth = manager->proxy_auth;
+ SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager);
+ SoupAuth *auth = priv->proxy_auth;
if (auth && soup_auth_is_authenticated (auth))
- soup_session_requeue_message (manager->session, msg);
+ soup_session_requeue_message (priv->session, msg);
}
static void
-session_request_queued (SoupSession *session, SoupMessage *msg,
- gpointer data)
+request_queued (SoupSessionFeature *manager, SoupSession *session,
+ SoupMessage *msg)
{
- SoupAuthManager *manager = data;
-
soup_message_add_status_code_handler (
msg, "got_headers", SOUP_STATUS_UNAUTHORIZED,
G_CALLBACK (update_auth), manager);
@@ -466,29 +519,28 @@ session_request_queued (SoupSession *session, SoupMessage *msg,
}
static void
-session_request_started (SoupSession *session, SoupMessage *msg,
- SoupSocket *socket, gpointer data)
+request_started (SoupSessionFeature *feature, SoupSession *session,
+ SoupMessage *msg, SoupSocket *socket)
{
- SoupAuthManager *manager = data;
+ SoupAuthManager *manager = SOUP_AUTH_MANAGER (feature);
+ SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager);
SoupAuth *auth;
- auth = lookup_auth (manager, msg);
+ auth = lookup_auth (priv, msg);
if (!auth || !authenticate_auth (manager, auth, msg, FALSE, FALSE))
auth = NULL;
soup_message_set_auth (msg, auth);
- auth = manager->proxy_auth;
+ auth = priv->proxy_auth;
if (!auth || !authenticate_auth (manager, auth, msg, FALSE, TRUE))
auth = NULL;
soup_message_set_proxy_auth (msg, auth);
}
static void
-session_request_unqueued (SoupSession *session, SoupMessage *msg,
- gpointer data)
+request_unqueued (SoupSessionFeature *manager, SoupSession *session,
+ SoupMessage *msg)
{
- SoupAuthManager *manager = data;
-
g_signal_handlers_disconnect_matched (msg, G_SIGNAL_MATCH_DATA,
0, 0, NULL, NULL, manager);
}