libsoup r1134 - in trunk: . libsoup



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]