libsoup r1134 - in trunk: . libsoup
- From: danw svn gnome org
- To: svn-commits-list gnome org
- Subject: libsoup r1134 - in trunk: . libsoup
- Date: Tue, 8 Apr 2008 23:13:03 +0100 (BST)
Author: danw
Date: Tue Apr 8 23:13:03 2008
New Revision: 1134
URL: http://svn.gnome.org/viewvc/libsoup?rev=1134&view=rev
Log:
* 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)
Modified:
trunk/ChangeLog
trunk/libsoup/soup-auth-manager-ntlm.c
trunk/libsoup/soup-auth-manager-ntlm.h
trunk/libsoup/soup-auth-manager.c
trunk/libsoup/soup-auth-manager.h
trunk/libsoup/soup-session-private.h
trunk/libsoup/soup-session.c
Modified: trunk/libsoup/soup-auth-manager-ntlm.c
==============================================================================
--- trunk/libsoup/soup-auth-manager-ntlm.c (original)
+++ trunk/libsoup/soup-auth-manager-ntlm.c Tue Apr 8 23:13:03 2008
@@ -19,9 +19,32 @@
#include "soup-message-private.h"
#include "soup-misc.h"
#include "soup-session.h"
-#include "soup-session-private.h"
+#include "soup-session-feature.h"
#include "soup-uri.h"
+static void soup_auth_manager_ntlm_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data);
+static SoupSessionFeatureInterface *soup_auth_manager_parent_feature_interface;
+
+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);
+
+G_DEFINE_TYPE_WITH_CODE (SoupAuthManagerNTLM, soup_auth_manager_ntlm, SOUP_TYPE_AUTH_MANAGER,
+ G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE,
+ soup_auth_manager_ntlm_session_feature_init));
+
+enum {
+ PROP_0,
+
+ PROP_USE_NTLM,
+
+ LAST_PROP
+};
+
typedef enum {
SOUP_NTLM_NEW,
SOUP_NTLM_SENT_REQUEST,
@@ -39,18 +62,14 @@
SoupAuth *auth;
} SoupNTLMConnection;
-struct SoupAuthManagerNTLM {
+typedef struct {
+ gboolean use_ntlm;
+
SoupSession *session;
GHashTable *connections_by_msg;
GHashTable *connections_by_id;
-};
-
-static void ntlm_request_queued (SoupSession *session, SoupMessage *msg,
- gpointer ntlm);
-static void ntlm_request_started (SoupSession *session, SoupMessage *msg,
- SoupSocket *socket, gpointer ntlm);
-static void ntlm_request_unqueued (SoupSession *session, SoupMessage *msg,
- gpointer ntlm);
+} SoupAuthManagerNTLMPrivate;
+#define SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_AUTH_MANAGER_NTLM, SoupAuthManagerNTLMPrivate))
static char *soup_ntlm_request (void);
static gboolean soup_ntlm_parse_challenge (const char *challenge,
@@ -62,22 +81,19 @@
const char *host,
const char *domain);
-SoupAuthManagerNTLM *
-soup_auth_manager_ntlm_new (SoupSession *session)
+static void set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec);
+static void get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec);
+
+static void
+soup_auth_manager_ntlm_init (SoupAuthManagerNTLM *ntlm)
{
- SoupAuthManagerNTLM *ntlm;
+ SoupAuthManagerNTLMPrivate *priv =
+ SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (ntlm);
- ntlm = g_slice_new (SoupAuthManagerNTLM);
- ntlm->session = session;
- ntlm->connections_by_id = g_hash_table_new (NULL, NULL);
- ntlm->connections_by_msg = g_hash_table_new (NULL, NULL);
- g_signal_connect (session, "request_queued",
- G_CALLBACK (ntlm_request_queued), ntlm);
- g_signal_connect (session, "request_started",
- G_CALLBACK (ntlm_request_started), ntlm);
- g_signal_connect (session, "request_unqueued",
- G_CALLBACK (ntlm_request_unqueued), ntlm);
- return ntlm;
+ priv->connections_by_id = g_hash_table_new (NULL, NULL);
+ priv->connections_by_msg = g_hash_table_new (NULL, NULL);
}
static void
@@ -97,96 +113,180 @@
free_ntlm_connection (value);
}
-void
-soup_auth_manager_ntlm_free (SoupAuthManagerNTLM *ntlm)
+static void
+finalize (GObject *object)
{
- g_hash_table_foreach (ntlm->connections_by_id,
+ SoupAuthManagerNTLMPrivate *priv =
+ SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (object);
+
+ g_hash_table_foreach (priv->connections_by_id,
free_ntlm_connection_foreach, NULL);
- g_hash_table_destroy (ntlm->connections_by_id);
- g_hash_table_destroy (ntlm->connections_by_msg);
- g_signal_handlers_disconnect_by_func (ntlm->session,
- ntlm_request_queued, ntlm);
- g_signal_handlers_disconnect_by_func (ntlm->session,
- ntlm_request_started, ntlm);
- g_signal_handlers_disconnect_by_func (ntlm->session,
- ntlm_request_unqueued, ntlm);
+ g_hash_table_destroy (priv->connections_by_id);
+ g_hash_table_destroy (priv->connections_by_msg);
- g_slice_free (SoupAuthManagerNTLM, ntlm);
+ G_OBJECT_CLASS (soup_auth_manager_ntlm_parent_class)->finalize (object);
+}
+
+static void
+soup_auth_manager_ntlm_class_init (SoupAuthManagerNTLMClass *auth_manager_ntlm_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (auth_manager_ntlm_class);
+
+ g_type_class_add_private (auth_manager_ntlm_class, sizeof (SoupAuthManagerNTLMPrivate));
+
+ object_class->finalize = finalize;
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+
+ g_object_class_install_property (
+ object_class, PROP_USE_NTLM,
+ g_param_spec_boolean (SOUP_AUTH_MANAGER_NTLM_USE_NTLM,
+ "Use NTLM",
+ "Whether or not to use NTLM authentication",
+ FALSE,
+ G_PARAM_READWRITE));
+}
+
+static void
+soup_auth_manager_ntlm_session_feature_init (SoupSessionFeatureInterface *feature_interface,
+ gpointer interface_data)
+{
+ soup_auth_manager_parent_feature_interface =
+ g_type_interface_peek_parent (feature_interface);
+
+ feature_interface->attach = attach;
+ feature_interface->request_queued = request_queued;
+ feature_interface->request_started = request_started;
+ feature_interface->request_unqueued = request_unqueued;
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ SoupAuthManagerNTLMPrivate *priv =
+ SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_USE_NTLM:
+ priv->use_ntlm = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ SoupAuthManagerNTLMPrivate *priv =
+ SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_USE_NTLM:
+ g_value_set_boolean (value, priv->use_ntlm);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+attach (SoupSessionFeature *manager, SoupSession *session)
+{
+ SoupAuthManagerNTLMPrivate *priv =
+ SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (manager);
+
+ /* FIXME: should support multiple sessions */
+ priv->session = session;
+
+ soup_auth_manager_parent_feature_interface->attach (manager, session);
}
static void
delete_conn (SoupSocket *socket, gpointer user_data)
{
- SoupAuthManagerNTLM *ntlm = user_data;
+ SoupAuthManagerNTLMPrivate *priv = user_data;
SoupNTLMConnection *conn;
- conn = g_hash_table_lookup (ntlm->connections_by_id, socket);
+ conn = g_hash_table_lookup (priv->connections_by_id, socket);
if (conn)
free_ntlm_connection (conn);
- g_hash_table_remove (ntlm->connections_by_id, socket);
- g_signal_handlers_disconnect_by_func (socket, delete_conn, ntlm);
+ g_hash_table_remove (priv->connections_by_id, socket);
+ g_signal_handlers_disconnect_by_func (socket, delete_conn, priv);
}
static SoupNTLMConnection *
-get_connection (SoupAuthManagerNTLM *ntlm, SoupSocket *socket)
+get_connection (SoupAuthManagerNTLMPrivate *priv, SoupSocket *socket)
{
SoupNTLMConnection *conn;
- conn = g_hash_table_lookup (ntlm->connections_by_id, socket);
+ conn = g_hash_table_lookup (priv->connections_by_id, socket);
if (conn)
return conn;
conn = g_slice_new0 (SoupNTLMConnection);
conn->socket = socket;
conn->state = SOUP_NTLM_NEW;
- g_hash_table_insert (ntlm->connections_by_id, socket, conn);
+ g_hash_table_insert (priv->connections_by_id, socket, conn);
g_signal_connect (socket, "disconnected",
- G_CALLBACK (delete_conn), ntlm);
+ G_CALLBACK (delete_conn), priv);
return conn;
}
static void
unset_conn (SoupMessage *msg, gpointer user_data)
{
- SoupAuthManagerNTLM *ntlm = user_data;
+ SoupAuthManagerNTLMPrivate *priv = user_data;
- g_hash_table_remove (ntlm->connections_by_msg, msg);
- g_signal_handlers_disconnect_by_func (msg, unset_conn, ntlm);
+ g_hash_table_remove (priv->connections_by_msg, msg);
+ g_signal_handlers_disconnect_by_func (msg, unset_conn, priv);
}
static SoupNTLMConnection *
-set_connection_for_msg (SoupAuthManagerNTLM *ntlm, SoupMessage *msg,
+set_connection_for_msg (SoupAuthManagerNTLMPrivate *priv, SoupMessage *msg,
SoupNTLMConnection *conn)
{
- if (!g_hash_table_lookup (ntlm->connections_by_msg, msg)) {
+ if (!g_hash_table_lookup (priv->connections_by_msg, msg)) {
g_signal_connect (msg, "finished",
- G_CALLBACK (unset_conn), ntlm);
+ G_CALLBACK (unset_conn), priv);
g_signal_connect (msg, "restarted",
- G_CALLBACK (unset_conn), ntlm);
+ G_CALLBACK (unset_conn), priv);
}
- g_hash_table_insert (ntlm->connections_by_msg, msg, conn);
+ g_hash_table_insert (priv->connections_by_msg, msg, conn);
return conn;
}
static SoupNTLMConnection *
-get_connection_for_msg (SoupAuthManagerNTLM *ntlm, SoupMessage *msg)
+get_connection_for_msg (SoupAuthManagerNTLMPrivate *priv, SoupMessage *msg)
{
- return g_hash_table_lookup (ntlm->connections_by_msg, msg);
+ return g_hash_table_lookup (priv->connections_by_msg, msg);
}
static void
-ntlm_authorize_pre (SoupMessage *msg, gpointer user_data)
+ntlm_authorize_pre (SoupMessage *msg, gpointer ntlm)
{
- SoupAuthManagerNTLM *ntlm = user_data;
+ SoupAuthManagerNTLMPrivate *priv =
+ SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (ntlm);
SoupNTLMConnection *conn;
const char *val;
- conn = get_connection_for_msg (ntlm, msg);
+ conn = get_connection_for_msg (priv, msg);
if (!conn)
return;
+ val = soup_message_headers_get (msg->response_headers,
+ "WWW-Authenticate");
+ if (val)
+ val = strstr (val, "NTLM ");
+ if (!val)
+ return;
+
if (conn->state > SOUP_NTLM_SENT_REQUEST) {
/* We already authenticated, but then got another 401.
* That means "permission denied", so don't try to
@@ -196,15 +296,6 @@
goto done;
}
- val = soup_message_headers_get (msg->response_headers,
- "WWW-Authenticate");
- if (val)
- val = strstr (val, "NTLM ");
- if (!val) {
- conn->state = SOUP_NTLM_FAILED;
- goto done;
- }
-
if (!soup_ntlm_parse_challenge (val, &conn->nonce, &conn->domain)) {
conn->state = SOUP_NTLM_FAILED;
goto done;
@@ -213,7 +304,8 @@
conn->state = SOUP_NTLM_RECEIVED_CHALLENGE;
conn->auth = soup_auth_ntlm_new (conn->domain,
soup_message_get_uri (msg)->host);
- soup_session_emit_authenticate (ntlm->session, msg, conn->auth, FALSE);
+ soup_auth_manager_emit_authenticate (SOUP_AUTH_MANAGER (ntlm), msg,
+ conn->auth, FALSE);
done:
/* Remove the WWW-Authenticate headers so the session won't try
@@ -223,14 +315,15 @@
}
static void
-ntlm_authorize_post (SoupMessage *msg, gpointer user_data)
+ntlm_authorize_post (SoupMessage *msg, gpointer ntlm)
{
- SoupAuthManagerNTLM *ntlm = user_data;
+ SoupAuthManagerNTLMPrivate *priv =
+ SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (ntlm);
SoupNTLMConnection *conn;
const char *username = NULL, *password = NULL;
char *slash, *domain = NULL;
- conn = get_connection_for_msg (ntlm, msg);
+ conn = get_connection_for_msg (priv, msg);
if (!conn || !conn->auth)
return;
@@ -251,7 +344,7 @@
conn->response_header = soup_ntlm_response (conn->nonce,
username, password,
NULL, domain);
- soup_session_requeue_message (ntlm->session, msg);
+ soup_session_requeue_message (priv->session, msg);
done:
if (domain != conn->domain)
@@ -265,28 +358,37 @@
}
static void
-ntlm_request_queued (SoupSession *session, SoupMessage *msg, gpointer ntlm)
+request_queued (SoupSessionFeature *ntlm, SoupSession *session, SoupMessage *msg)
{
- soup_message_add_status_code_handler (msg, "got_headers",
- SOUP_STATUS_UNAUTHORIZED,
- G_CALLBACK (ntlm_authorize_pre),
- ntlm);
- soup_message_add_status_code_handler (msg, "got_body",
- SOUP_STATUS_UNAUTHORIZED,
- G_CALLBACK (ntlm_authorize_post),
- ntlm);
+ SoupAuthManagerNTLMPrivate *priv =
+ SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (ntlm);
+
+ if (priv->use_ntlm) {
+ soup_message_add_status_code_handler (
+ msg, "got_headers", SOUP_STATUS_UNAUTHORIZED,
+ G_CALLBACK (ntlm_authorize_pre), ntlm);
+ soup_message_add_status_code_handler (
+ msg, "got_body", SOUP_STATUS_UNAUTHORIZED,
+ G_CALLBACK (ntlm_authorize_post), ntlm);
+ }
+
+ soup_auth_manager_parent_feature_interface->request_queued (ntlm, session, msg);
}
static void
-ntlm_request_started (SoupSession *session, SoupMessage *msg,
- SoupSocket *socket, gpointer user_data)
+request_started (SoupSessionFeature *ntlm, SoupSession *session,
+ SoupMessage *msg, SoupSocket *socket)
{
- SoupAuthManagerNTLM *ntlm = user_data;
+ SoupAuthManagerNTLMPrivate *priv =
+ SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (ntlm);
SoupNTLMConnection *conn;
char *header = NULL;
- conn = get_connection (ntlm, socket);
- set_connection_for_msg (ntlm, msg, conn);
+ if (!priv->use_ntlm)
+ goto super;
+
+ conn = get_connection (priv, socket);
+ set_connection_for_msg (priv, msg, conn);
switch (conn->state) {
case SOUP_NTLM_NEW:
@@ -307,14 +409,19 @@
"Authorization", header);
g_free (header);
}
+
+super:
+ soup_auth_manager_parent_feature_interface->request_started (ntlm, session, msg, socket);
}
static void
-ntlm_request_unqueued (SoupSession *session, SoupMessage *msg,
- gpointer ntlm)
+request_unqueued (SoupSessionFeature *ntlm, SoupSession *session,
+ SoupMessage *msg)
{
g_signal_handlers_disconnect_by_func (msg, ntlm_authorize_pre, ntlm);
g_signal_handlers_disconnect_by_func (msg, ntlm_authorize_post, ntlm);
+
+ soup_auth_manager_parent_feature_interface->request_unqueued (ntlm, session, msg);
}
Modified: trunk/libsoup/soup-auth-manager-ntlm.h
==============================================================================
--- trunk/libsoup/soup-auth-manager-ntlm.h (original)
+++ trunk/libsoup/soup-auth-manager-ntlm.h Tue Apr 8 23:13:03 2008
@@ -6,15 +6,29 @@
#ifndef SOUP_AUTH_MANAGER_NTLM_H
#define SOUP_AUTH_MANAGER_NTLM_H 1
-#include "soup-types.h"
+#include "soup-auth-manager.h"
G_BEGIN_DECLS
-typedef struct SoupAuthManagerNTLM SoupAuthManagerNTLM;
+#define SOUP_TYPE_AUTH_MANAGER_NTLM (soup_auth_manager_ntlm_get_type ())
+#define SOUP_AUTH_MANAGER_NTLM(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_AUTH_MANAGER_NTLM, SoupAuthManagerNTLM))
+#define SOUP_AUTH_MANAGER_NTLM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_AUTH_MANAGER_NTLM, SoupAuthManagerNTLMClass))
+#define SOUP_IS_AUTH_MANAGER_NTLM(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_AUTH_MANAGER_NTLM))
+#define SOUP_IS_AUTH_MANAGER_NTLM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_AUTH_MANAGER_NTLM))
+#define SOUP_AUTH_MANAGER_NTLM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_AUTH_MANAGER_NTLM, SoupAuthManagerNTLMClass))
-SoupAuthManagerNTLM *soup_auth_manager_ntlm_new (SoupSession *session);
-void soup_auth_manager_ntlm_free (SoupAuthManagerNTLM *manager);
+typedef struct {
+ SoupAuthManager parent;
+
+} SoupAuthManagerNTLM;
+
+typedef struct {
+ SoupAuthManagerClass parent_class;
+
+} SoupAuthManagerNTLMClass;
+
+GType soup_auth_manager_ntlm_get_type (void);
G_END_DECLS
-#endif /* SOUP_AUTH_MANAGER_NTLM_H */
+#endif /* SOUP_AUTH_MANAGER_NTLM_NTLM_H */
Modified: trunk/libsoup/soup-auth-manager.c
==============================================================================
--- trunk/libsoup/soup-auth-manager.c (original)
+++ trunk/libsoup/soup-auth-manager.c Tue Apr 8 23:13:03 2008
@@ -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 @@
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;
+ SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (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;
+ 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 @@
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 < manager->auth_types->len; i++)
- g_type_class_unref (manager->auth_types->pdata[i]);
- g_ptr_array_free (manager->auth_types, TRUE);
+ 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);
+
+ 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 @@
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 @@
}
static SoupAuth *
-create_auth (SoupAuthManager *manager, SoupMessage *msg)
+create_auth (SoupAuthManagerPrivate *priv, SoupMessage *msg)
{
const char *header;
SoupAuthClass *auth_class;
@@ -231,8 +285,8 @@
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 @@
}
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 @@
}
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 @@
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 @@
}
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 @@
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 @@
}
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 @@
}
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);
}
Modified: trunk/libsoup/soup-auth-manager.h
==============================================================================
--- trunk/libsoup/soup-auth-manager.h (original)
+++ trunk/libsoup/soup-auth-manager.h Tue Apr 8 23:13:03 2008
@@ -11,16 +11,38 @@
G_BEGIN_DECLS
-typedef struct SoupAuthManager SoupAuthManager;
-
-SoupAuthManager *soup_auth_manager_new (SoupSession *session);
-
-void soup_auth_manager_add_type (SoupAuthManager *manager,
- GType type);
-void soup_auth_manager_remove_type (SoupAuthManager *manager,
- GType type);
-
-void soup_auth_manager_free (SoupAuthManager *manager);
+#define SOUP_TYPE_AUTH_MANAGER (soup_auth_manager_get_type ())
+#define SOUP_AUTH_MANAGER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_AUTH_MANAGER, SoupAuthManager))
+#define SOUP_AUTH_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_AUTH_MANAGER, SoupAuthManagerClass))
+#define SOUP_IS_AUTH_MANAGER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_AUTH_MANAGER))
+#define SOUP_IS_AUTH_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_AUTH_MANAGER))
+#define SOUP_AUTH_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_AUTH_MANAGER, SoupAuthManagerClass))
+
+typedef struct {
+ GObject parent;
+
+} SoupAuthManager;
+
+typedef struct {
+ GObjectClass parent_class;
+
+ void (*authenticate) (SoupAuthManager *manager, SoupMessage *msg,
+ SoupAuth *auth, gboolean retrying);
+} SoupAuthManagerClass;
+
+#define SOUP_AUTH_MANAGER_NTLM_USE_NTLM "use-ntlm"
+
+GType soup_auth_manager_get_type (void);
+
+void soup_auth_manager_add_type (SoupAuthManager *manager,
+ GType type);
+void soup_auth_manager_remove_type (SoupAuthManager *manager,
+ GType type);
+
+void soup_auth_manager_emit_authenticate (SoupAuthManager *manager,
+ SoupMessage *msg,
+ SoupAuth *auth,
+ gboolean retrying);
G_END_DECLS
Modified: trunk/libsoup/soup-session-private.h
==============================================================================
--- trunk/libsoup/soup-session-private.h (original)
+++ trunk/libsoup/soup-session-private.h Tue Apr 8 23:13:03 2008
@@ -12,12 +12,6 @@
G_BEGIN_DECLS
-/* internal methods */
-void soup_session_emit_authenticate (SoupSession *session,
- SoupMessage *msg,
- SoupAuth *auth,
- gboolean retrying);
-
/* "protected" methods for subclasses */
SoupMessageQueue *soup_session_get_queue (SoupSession *session);
Modified: trunk/libsoup/soup-session.c
==============================================================================
--- trunk/libsoup/soup-session.c (original)
+++ trunk/libsoup/soup-session.c Tue Apr 8 23:13:03 2008
@@ -16,7 +16,6 @@
#include "soup-auth.h"
#include "soup-auth-basic.h"
#include "soup-auth-digest.h"
-#include "soup-auth-manager.h"
#include "soup-auth-manager-ntlm.h"
#include "soup-connection.h"
#include "soup-marshal.h"
@@ -78,7 +77,6 @@
GSList *features;
SoupAuthManager *auth_manager;
- SoupAuthManagerNTLM *ntlm_manager;
GHashTable *hosts; /* SoupURI -> SoupSessionHost */
GHashTable *conns; /* SoupConnection -> SoupSessionHost */
@@ -104,6 +102,10 @@
static void cancel_message (SoupSession *session, SoupMessage *msg,
guint status_code);
+static void auth_manager_authenticate (SoupAuthManager *manager,
+ SoupMessage *msg, SoupAuth *auth,
+ gboolean retrying, gpointer user_data);
+
/* temporary until we fix this to index hosts by SoupAddress */
extern guint soup_uri_host_hash (gconstpointer key);
extern gboolean soup_uri_host_equal (gconstpointer v1,
@@ -166,9 +168,14 @@
priv->max_conns = SOUP_SESSION_MAX_CONNS_DEFAULT;
priv->max_conns_per_host = SOUP_SESSION_MAX_CONNS_PER_HOST_DEFAULT;
- priv->auth_manager = soup_auth_manager_new (session);
+ priv->auth_manager = g_object_new (SOUP_TYPE_AUTH_MANAGER_NTLM,
+ SOUP_AUTH_MANAGER_NTLM_USE_NTLM, FALSE,
+ NULL);
+ g_signal_connect (priv->auth_manager, "authenticate",
+ G_CALLBACK (auth_manager_authenticate), session);
soup_auth_manager_add_type (priv->auth_manager, SOUP_TYPE_AUTH_BASIC);
soup_auth_manager_add_type (priv->auth_manager, SOUP_TYPE_AUTH_DIGEST);
+ soup_session_add_feature (session, SOUP_SESSION_FEATURE (priv->auth_manager));
}
static gboolean
@@ -222,9 +229,8 @@
g_free (priv->user_agent);
- soup_auth_manager_free (priv->auth_manager);
- if (priv->ntlm_manager)
- soup_auth_manager_ntlm_free (priv->ntlm_manager);
+ if (priv->auth_manager)
+ g_object_unref (priv->auth_manager);
if (priv->proxy_uri)
soup_uri_free (priv->proxy_uri);
@@ -564,15 +570,9 @@
priv->max_conns_per_host = g_value_get_int (value);
break;
case PROP_USE_NTLM:
- if (g_value_get_boolean (value)) {
- if (!priv->ntlm_manager)
- priv->ntlm_manager = soup_auth_manager_ntlm_new (session);
- } else {
- if (priv->ntlm_manager) {
- soup_auth_manager_ntlm_free (priv->ntlm_manager);
- priv->ntlm_manager = NULL;
- }
- }
+ g_object_set_property (G_OBJECT (priv->auth_manager),
+ SOUP_AUTH_MANAGER_NTLM_USE_NTLM,
+ value);
break;
case PROP_SSL_CA_FILE:
new_ca_file = g_value_get_string (value);
@@ -652,7 +652,9 @@
g_value_set_int (value, priv->max_conns_per_host);
break;
case PROP_USE_NTLM:
- g_value_set_boolean (value, priv->ntlm_manager != NULL);
+ g_object_get_property (G_OBJECT (priv->auth_manager),
+ SOUP_AUTH_MANAGER_NTLM_USE_NTLM,
+ value);
break;
case PROP_SSL_CA_FILE:
g_value_set_string (value, priv->ssl_ca_file);
@@ -752,9 +754,10 @@
g_slice_free (SoupSessionHost, host);
}
-void
-soup_session_emit_authenticate (SoupSession *session, SoupMessage *msg,
- SoupAuth *auth, gboolean retrying)
+static void
+auth_manager_authenticate (SoupAuthManager *manager, SoupMessage *msg,
+ SoupAuth *auth, gboolean retrying,
+ gpointer session)
{
g_signal_emit (session, signals[AUTHENTICATE], 0, msg, auth, retrying);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]