diff options
author | Dan Winship <danw@src.gnome.org> | 2008-04-08 22:13:03 +0000 |
---|---|---|
committer | Dan Winship <danw@src.gnome.org> | 2008-04-08 22:13:03 +0000 |
commit | e1c6bf7690fc035e0a0560ebc6f3030eee6b3a8d (patch) | |
tree | dad9aeeb321a20266681530452f6a51efbcbc803 /libsoup/soup-auth-manager.c | |
parent | 700b6a340c5142255b2189fb78580ca2dc96a1ae (diff) | |
download | libsoup-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.c | 242 |
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); } |