Replaces the three previous soup_connection_new* functions and uses
authorDan Winship <danw@src.gnome.org>
Wed, 17 Sep 2003 18:57:46 +0000 (18:57 +0000)
committerDan Winship <danw@src.gnome.org>
Wed, 17 Sep 2003 18:57:46 +0000 (18:57 +0000)
* libsoup/soup-connection.c (soup_connection_new): Replaces the
three previous soup_connection_new* functions and uses gobject
properties to set the destination and proxy uris.
(class_init): set up two more signals, authenticate and
reauthenticate.
(soup_connection_send_request): virtualize
(send_request): Default implementation

* libsoup/soup-connection-ntlm.c: New SoupConnection subclass that
also handles NTLM authentication. Includes all of the NTLM code
formerly in soup-auth-ntlm.c.

* libsoup/soup-auth-ntlm.[ch]: Gone.

* libsoup/soup-auth.c: Remove NTLM refs

* libsoup/soup-session.c (class_init): Add gobject properties for
proxy, max_conns, use_ntlm. Change the "authenticate" and
"reauthenticate" signal prototypes to not pass a SoupAuth (so they
can be used for authenticating SoupConnectionNTLM as well, which
doesn't use a SoupAuth).
(soup_session_new): Renamed from soup_session_new_default.
(soup_session_new_with_options): Replaces
soup_session_new_with_proxy and soup_session_new_full. Takes
gobject properties.
(run_queue): Create a new connection of type SoupConnection or
SoupConnectionNTLM depending on our "use_ntlm" property. Connect
to its authenticate and reauthenticate signals.
(connection_authenticate, connection_reauthenticate): proxy these
signals.

* libsoup/soup-address.c (update_address_from_entry): Fix a
crasher when failing to resolve the address.

* libsoup/soup-dns.c (check_hostent): Fix some "how was this
working before" bugs.

* libsoup/soup-message-client-io.c (soup_message_send_request):
call soup_message_prepare() to clean up the existing response
state.

* libsoup/soup-message-io.c (io_error): Set the read_state to DONE
when processing an OK EOF.

* libsoup/soup-status.h (SoupStatusClass): fix the numbering of
these so that SOUP_STATUS_CLASS_SUCCESS is 2, etc.

* tests/auth-test.c (authenticate, reauthenticate): Update for new
prototypes.
(main): Use soup_session_new.
* tests/get.c (main): Likewise.
* tests/simple-proxy.c (main): Likewise.

21 files changed:
ChangeLog
libsoup/Makefile.am
libsoup/soup-address.c
libsoup/soup-auth-ntlm.h [deleted file]
libsoup/soup-auth.c
libsoup/soup-connection-ntlm.c [moved from libsoup/soup-auth-ntlm.c with 85% similarity]
libsoup/soup-connection-ntlm.h [new file with mode: 0644]
libsoup/soup-connection.c
libsoup/soup-connection.h
libsoup/soup-dns.c
libsoup/soup-marshal.list
libsoup/soup-message-client-io.c
libsoup/soup-message-io.c
libsoup/soup-message-private.h
libsoup/soup-message.h
libsoup/soup-session.c
libsoup/soup-session.h
libsoup/soup-status.h
tests/auth-test.c
tests/get.c
tests/simple-proxy.c

index 09bc9c6..1307d92 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,58 @@
+2003-09-17  Dan Winship  <danw@ximian.com>
+
+       * libsoup/soup-connection.c (soup_connection_new): Replaces the
+       three previous soup_connection_new* functions and uses gobject
+       properties to set the destination and proxy uris.
+       (class_init): set up two more signals, authenticate and
+       reauthenticate.
+       (soup_connection_send_request): virtualize
+       (send_request): Default implementation
+
+       * libsoup/soup-connection-ntlm.c: New SoupConnection subclass that
+       also handles NTLM authentication. Includes all of the NTLM code
+       formerly in soup-auth-ntlm.c.
+
+       * libsoup/soup-auth-ntlm.[ch]: Gone.
+
+       * libsoup/soup-auth.c: Remove NTLM refs
+
+       * libsoup/soup-session.c (class_init): Add gobject properties for
+       proxy, max_conns, use_ntlm. Change the "authenticate" and
+       "reauthenticate" signal prototypes to not pass a SoupAuth (so they
+       can be used for authenticating SoupConnectionNTLM as well, which
+       doesn't use a SoupAuth).
+       (soup_session_new): Renamed from soup_session_new_default.
+       (soup_session_new_with_options): Replaces
+       soup_session_new_with_proxy and soup_session_new_full. Takes
+       gobject properties.
+       (run_queue): Create a new connection of type SoupConnection or
+       SoupConnectionNTLM depending on our "use_ntlm" property. Connect
+       to its authenticate and reauthenticate signals.
+       (connection_authenticate, connection_reauthenticate): proxy these
+       signals.
+
+       * libsoup/soup-address.c (update_address_from_entry): Fix a
+       crasher when failing to resolve the address.
+
+       * libsoup/soup-dns.c (check_hostent): Fix some "how was this
+       working before" bugs.
+
+       * libsoup/soup-message-client-io.c (soup_message_send_request):
+       call soup_message_prepare() to clean up the existing response
+       state.
+
+       * libsoup/soup-message-io.c (io_error): Set the read_state to DONE
+       when processing an OK EOF.
+
+       * libsoup/soup-status.h (SoupStatusClass): fix the numbering of
+       these so that SOUP_STATUS_CLASS_SUCCESS is 2, etc.
+
+       * tests/auth-test.c (authenticate, reauthenticate): Update for new
+       prototypes.
+       (main): Use soup_session_new.
+       * tests/get.c (main): Likewise.
+       * tests/simple-proxy.c (main): Likewise.
+
 2003-09-10  Dan Winship  <danw@ximian.com>
 
        * libsoup/soup-session.c: Add "authenticate" and "reauthenticate"
index e66857a..48e34ce 100644 (file)
@@ -62,9 +62,9 @@ libsoup_2_2_la_SOURCES =              \
        soup-auth-basic.c               \
        soup-auth-digest.h              \
        soup-auth-digest.c              \
-       soup-auth-ntlm.h                \
-       soup-auth-ntlm.c                \
        soup-connection.c               \
+       soup-connection-ntlm.h          \
+       soup-connection-ntlm.c          \
        soup-dns.h                      \
        soup-dns.c                      \
        soup-gnutls.h                   \
index a59a4c4..056ad47 100644 (file)
@@ -313,6 +313,8 @@ update_address_from_entry (SoupAddress *addr, SoupDNSEntry *entry)
        struct hostent *h;
 
        h = soup_dns_entry_get_hostent (addr->priv->lookup);
+       if (!h)
+               return SOUP_STATUS_CANT_RESOLVE;
 
        if (!addr->priv->name)
                addr->priv->name = g_strdup (h->h_name);
diff --git a/libsoup/soup-auth-ntlm.h b/libsoup/soup-auth-ntlm.h
deleted file mode 100644 (file)
index 6950bbf..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-ntlm-offset: 8 -*- */
-/*
- * Copyright (C) 2000-2003, Ximian, Inc.
- */
-
-#ifndef SOUP_AUTH_NTLM_H
-#define SOUP_AUTH_NTLM_H 1
-
-#include "soup-auth.h"
-
-#define SOUP_TYPE_AUTH_NTLM            (soup_auth_ntlm_get_type ())
-#define SOUP_AUTH_NTLM(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_AUTH_NTLM, SoupAuthNTLM))
-#define SOUP_AUTH_NTLM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_AUTH_NTLM, SoupAuthNTLMClass))
-#define SOUP_IS_AUTH_NTLM(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_AUTH_NTLM))
-#define SOUP_IS_AUTH_NTLM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_AUTH_NTLM))
-#define SOUP_AUTH_NTLM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_AUTH_NTLM, SoupAuthNTLMClass))
-
-typedef struct SoupAuthNTLMPrivate SoupAuthNTLMPrivate;
-
-typedef struct {
-       SoupAuth parent;
-
-       SoupAuthNTLMPrivate *priv;
-} SoupAuthNTLM;
-
-typedef struct {
-       SoupAuthClass  parent_class;
-
-} SoupAuthNTLMClass;
-
-GType     soup_auth_ntlm_get_type (void);
-
-SoupAuth *soup_auth_ntlm_new      (void);
-
-#endif /*SOUP_AUTH_NTLM_H*/
index 65ffd7c..1f308b0 100644 (file)
@@ -14,7 +14,6 @@
 #include "soup-auth.h"
 #include "soup-auth-basic.h"
 #include "soup-auth-digest.h"
-#include "soup-auth-ntlm.h"
 #include "soup-private.h"
 
 #define PARENT_TYPE G_TYPE_OBJECT
@@ -37,7 +36,6 @@ typedef struct {
 
 static AuthScheme known_auth_schemes [] = {
        { "Basic",  soup_auth_basic_get_type,  0 },
-       { "NTLM",   soup_auth_ntlm_get_type,   2 },
        { "Digest", soup_auth_digest_get_type, 3 },
        { NULL }
 };
similarity index 85%
rename from libsoup/soup-auth-ntlm.c
rename to libsoup/soup-connection-ntlm.c
index f5ed688..609e749 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-ntlm-offset: 8 -*- */
 /*
- * soup-auth-ntlm.c: HTTP NTLM Authentication
+ * soup-connection-ntlm.c: NTLM-using Connection
  *
  * Copyright (C) 2001-2003, Ximian, Inc.
  */
 #include <ctype.h>
 #include <string.h>
 
-#include "soup-auth-ntlm.h"
+#include "soup-connection-ntlm.h"
 #include "soup-private.h"
 #include "soup-uri.h"
 
-static void construct (SoupAuth *auth, const char *header);
-static GSList *get_protection_space (SoupAuth *auth, const SoupUri *source_uri);
-static const char *get_realm (SoupAuth *auth);
-static void authenticate (SoupAuth *auth, const char *username, const char *password);
-static gboolean is_authenticated (SoupAuth *auth);
-static char *get_authorization (SoupAuth *auth, SoupMessage *msg);
-
-char     *soup_ntlm_request         (void);
-gboolean  soup_ntlm_parse_challenge (const char  *challenge,
-                                    char       **nonce,
-                                    char       **default_domain);
-char     *soup_ntlm_response        (const char  *nonce, 
-                                    const char  *user,
-                                    const char  *password, 
-                                    const char  *host, 
-                                    const char  *domain);
-
-struct SoupAuthNTLMPrivate {
+void send_request (SoupConnection *conn, SoupMessage *req);
+
+struct SoupConnectionNTLMPrivate {
+       char *user;
+       guchar nt_hash[21], lm_hash[21];
        gboolean authenticated;
-       char *header;
-       char *response;
 };
 
-#define PARENT_TYPE SOUP_TYPE_AUTH
-static SoupAuthClass *parent_class;
+#define PARENT_TYPE SOUP_TYPE_CONNECTION
+static SoupConnectionClass *parent_class;
+
+static char     *soup_ntlm_request         (void);
+static gboolean  soup_ntlm_parse_challenge (const char  *challenge,
+                                           char       **nonce,
+                                           char       **default_domain);
+static char     *soup_ntlm_response        (const char  *nonce, 
+                                           const char  *user,
+                                           const char  *password,
+                                           const char  *host, 
+                                           const char  *domain);
 
 static void
 init (GObject *object)
 {
-       SoupAuthNTLM *ntlm = SOUP_AUTH_NTLM (object);
+       SoupConnectionNTLM *ntlm = SOUP_CONNECTION_NTLM (object);
 
-       ntlm->priv = g_new0 (SoupAuthNTLMPrivate, 1);
+       ntlm->priv = g_new0 (SoupConnectionNTLMPrivate, 1);
 }
 
 static void
 finalize (GObject *object)
 {
-       SoupAuthNTLM *ntlm = SOUP_AUTH_NTLM (object);
+       SoupConnectionNTLM *ntlm = SOUP_CONNECTION_NTLM (object);
+
+       g_free (ntlm->priv->user);
+       memset (ntlm->priv->nt_hash, 0, sizeof (ntlm->priv->nt_hash));
+       memset (ntlm->priv->lm_hash, 0, sizeof (ntlm->priv->lm_hash));
 
-       g_free (ntlm->priv->header);
-       g_free (ntlm->priv->response);
        g_free (ntlm->priv);
 
        G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -65,104 +62,121 @@ finalize (GObject *object)
 static void
 class_init (GObjectClass *object_class)
 {
-       SoupAuthClass *auth_class = SOUP_AUTH_CLASS (object_class);
+       SoupConnectionClass *connection_class =
+               SOUP_CONNECTION_CLASS (object_class);
 
        parent_class = g_type_class_ref (PARENT_TYPE);
 
-       auth_class->scheme_name = "NTLM";
-
-       auth_class->construct = construct;
-       auth_class->get_protection_space = get_protection_space;
-       auth_class->get_realm = get_realm;
-       auth_class->authenticate = authenticate;
-       auth_class->is_authenticated = is_authenticated;
-       auth_class->get_authorization = get_authorization;
-
+       connection_class->send_request = send_request;
        object_class->finalize = finalize;
 }
 
-SOUP_MAKE_TYPE (soup_auth_ntlm, SoupAuthNTLM, class_init, init, PARENT_TYPE)
-
+SOUP_MAKE_TYPE (soup_connection_ntlm, SoupConnectionNTLM, class_init, init, PARENT_TYPE)
 
-SoupAuth *
-soup_auth_ntlm_new (void)
-{
-       SoupAuth *auth;
-
-       auth = g_object_new (SOUP_TYPE_AUTH_NTLM, NULL);
-       construct (auth, "");
-       return auth;
-}
 
 static void
-construct (SoupAuth *auth, const char *header)
+ntlm_authorize_pre (SoupMessage *msg, gpointer user_data)
 {
-       SoupAuthNTLM *ntlm = SOUP_AUTH_NTLM (auth);
-
-       ntlm->priv->header = g_strdup (header);
-}
-
-static GSList *
-get_protection_space (SoupAuth *auth, const SoupUri *source_uri)
-{
-       /* The protection space is the whole server. */
-       return g_slist_prepend (NULL, g_strdup (""));
-}
-
-static const char *
-get_realm (SoupAuth *auth)
-{
-       return "";
-}
-
-static void
-authenticate (SoupAuth *auth, const char *username, const char *password)
-{
-       SoupAuthNTLM *ntlm = SOUP_AUTH_NTLM (auth);
-       char *domain, *nonce;
+       SoupConnectionNTLM *ntlm = user_data;
+       const GSList *headers;
+       const char *val;
+       char *nonce, *header;
+       char *username, *domain_username = NULL, *password = NULL;
+       char *slash, *domain;
+
+       if (ntlm->priv->authenticated) {
+               /* We already authenticated, but then got another 401.
+                * That means "permission denied", so don't try to
+                * authenticate again.
+                */
+               return;
+       }
 
-       if (!ntlm->priv->header || strlen (ntlm->priv->header) < sizeof ("NTLM"))
+       headers = soup_message_get_header_list (msg->response_headers,
+                                               "WWW-Authenticate");
+       while (headers) {
+               val = headers->data;
+               if (!strncmp (val, "NTLM ", 5))
+                       break;
+       }
+       if (!headers)
                return;
 
-       if (ntlm->priv->response)
-               g_free (ntlm->priv->response);
+       if (!soup_ntlm_parse_challenge (val, &nonce, &domain))
+               return;
 
-       if (soup_ntlm_parse_challenge (ntlm->priv->header, &nonce, &domain)) {
-               ntlm->priv->response =
-                       soup_ntlm_response (nonce, username, password,
-                                           NULL, domain);
+       soup_connection_authenticate (SOUP_CONNECTION (ntlm), msg,
+                                     "NTLM", domain,
+                                     &domain_username, &password);
+       if (!domain_username) {
                g_free (nonce);
                g_free (domain);
+               return;
+       }
+
+       slash = strpbrk (domain_username, "\\/");
+       if (slash) {
+               g_free (domain);
+               domain = g_strdup (domain_username);
+               username = slash + 1;
        } else
-               ntlm->priv->response = NULL;
+               username = domain_username;
 
-       g_free (ntlm->priv->header);
-       ntlm->priv->header = NULL;
+       header = soup_ntlm_response (nonce, username, password, NULL, domain);
+       g_free (domain_username);
+       g_free (password);
+       g_free (nonce);
 
+       soup_message_remove_header (msg->request_headers, "Authorization");
+       soup_message_add_header (msg->request_headers,
+                                "Authorization", header);
+       g_free (header);
        ntlm->priv->authenticated = TRUE;
+
+       /* Remove the WWW-Authenticate headers so the session won't try
+        * to do Basic auth too.
+        */
+       soup_message_remove_header (msg->response_headers, "WWW-Authenticate");
 }
 
-static gboolean
-is_authenticated (SoupAuth *auth)
+static void
+ntlm_authorize_post (SoupMessage *msg, gpointer conn)
 {
-       SoupAuthNTLM *ntlm = SOUP_AUTH_NTLM (auth);
+       SoupConnectionNTLM *ntlm = conn;
 
-       return ntlm->priv->authenticated;
+       if (ntlm->priv->authenticated &&
+           soup_message_get_header (msg->request_headers, "Authorization")) {
+               /* We just added the last Auth header, so restart it. */
+               soup_connection_send_request (conn, msg);
+       }
 }
 
-static char *
-get_authorization (SoupAuth *auth, SoupMessage *msg)
+void
+send_request (SoupConnection *conn, SoupMessage *req)
 {
-       SoupAuthNTLM *ntlm = SOUP_AUTH_NTLM (auth);
-       char *ret;
+       SoupConnectionNTLM *ntlm = SOUP_CONNECTION_NTLM (conn);
 
-       if (!ntlm->priv->authenticated)
-               return soup_ntlm_request ();
+       if (!ntlm->priv->authenticated) {
+               char *header = soup_ntlm_request ();
 
-       /* Otherwise, return the response; but only once */
-       ret = ntlm->priv->response;
-       ntlm->priv->response = NULL;
-       return ret;
+               soup_message_add_header (req->request_headers,
+                                        "Authorization", header);
+               g_free (header);
+       }
+
+       soup_message_remove_handler (req, SOUP_HANDLER_PRE_BODY,
+                                    ntlm_authorize_pre, conn);
+       soup_message_add_status_code_handler (req, SOUP_STATUS_UNAUTHORIZED,
+                                             SOUP_HANDLER_PRE_BODY,
+                                             ntlm_authorize_pre, conn);
+
+       soup_message_remove_handler (req, SOUP_HANDLER_POST_BODY,
+                                    ntlm_authorize_post, conn);
+       soup_message_add_status_code_handler (req, SOUP_STATUS_UNAUTHORIZED,
+                                             SOUP_HANDLER_POST_BODY,
+                                             ntlm_authorize_post, conn);
+
+       SOUP_CONNECTION_CLASS (parent_class)->send_request (conn, req);
 }
 
 
@@ -264,13 +278,13 @@ ntlm_set_string (NTLMString *string, int *offset, int len)
        *offset += len;
 }
 
-char *
+static char *
 soup_ntlm_request (void)
 {
        return g_strdup ("NTLM TlRMTVNTUAABAAAABoIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAA");
 }
 
-gboolean
+static gboolean
 soup_ntlm_parse_challenge (const char *challenge,
                           char      **nonce,
                           char      **default_domain)
@@ -321,10 +335,10 @@ soup_ntlm_parse_challenge (const char *challenge,
        return TRUE;
 }
 
-char *
+static char *
 soup_ntlm_response (const char *nonce, 
                    const char *user,
-                   const char *password, 
+                   const char *password,
                    const char *host, 
                    const char *domain)
 {
@@ -334,10 +348,10 @@ soup_ntlm_response (const char *nonce,
        unsigned char *out, *p;
        int state, save;
 
-       lanmanager_hash (password, hash);
-       calc_response (hash, nonce, lm_resp);
        nt_hash (password, hash);
        calc_response (hash, nonce, nt_resp);
+       lanmanager_hash (password, hash);
+       calc_response (hash, nonce, lm_resp);
 
        memset (&resp, 0, sizeof (resp));
        memcpy (resp.header, NTLM_RESPONSE_HEADER, sizeof (resp.header));
diff --git a/libsoup/soup-connection-ntlm.h b/libsoup/soup-connection-ntlm.h
new file mode 100644 (file)
index 0000000..8d0a242
--- /dev/null
@@ -0,0 +1,33 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-ntlm-offset: 8 -*- */
+/*
+ * Copyright (C) 2000-2003, Ximian, Inc.
+ */
+
+#ifndef SOUP_CONNECTION_NTLM_H
+#define SOUP_CONNECTION_NTLM_H 1
+
+#include "soup-connection.h"
+
+#define SOUP_TYPE_CONNECTION_NTLM            (soup_connection_ntlm_get_type ())
+#define SOUP_CONNECTION_NTLM(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_CONNECTION_NTLM, SoupConnectionNTLM))
+#define SOUP_CONNECTION_NTLM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_CONNECTION_NTLM, SoupConnectionNTLMClass))
+#define SOUP_IS_CONNECTION_NTLM(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_CONNECTION_NTLM))
+#define SOUP_IS_CONNECTION_NTLM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_CONNECTION_NTLM))
+#define SOUP_CONNECTION_NTLM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_CONNECTION_NTLM, SoupConnectionNTLMClass))
+
+typedef struct SoupConnectionNTLMPrivate SoupConnectionNTLMPrivate;
+
+typedef struct {
+       SoupConnection parent;
+
+       SoupConnectionNTLMPrivate *priv;
+} SoupConnectionNTLM;
+
+typedef struct {
+       SoupConnectionClass  parent_class;
+
+} SoupConnectionNTLMClass;
+
+GType soup_connection_ntlm_get_type (void);
+
+#endif /*SOUP_CONNECTION_NTLM_H*/
index d6fbd77..074fd7a 100644 (file)
@@ -42,12 +42,29 @@ static GObjectClass *parent_class;
 enum {
        CONNECT_RESULT,
        DISCONNECTED,
+       AUTHENTICATE,
+       REAUTHENTICATE,
        LAST_SIGNAL
 };
 
 static guint signals[LAST_SIGNAL] = { 0 };
 
+enum {
+  PROP_0,
+
+  PROP_DEST_URI,
+  PROP_PROXY_URI,
+
+  LAST_PROP
+};
+
+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 request_done (SoupMessage *req, gpointer user_data);
+static void send_request (SoupConnection *conn, SoupMessage *req);
 
 static void
 init (GObject *object)
@@ -87,11 +104,19 @@ dispose (GObject *object)
 static void
 class_init (GObjectClass *object_class)
 {
+       SoupConnectionClass *connection_class =
+               SOUP_CONNECTION_CLASS (object_class);
+
        parent_class = g_type_class_ref (PARENT_TYPE);
 
+       /* virtual method definition */
+       connection_class->send_request = send_request;
+
        /* virtual method override */
        object_class->dispose = dispose;
        object_class->finalize = finalize;
+       object_class->set_property = set_property;
+       object_class->get_property = get_property;
 
        /* signals */
        signals[CONNECT_RESULT] =
@@ -111,6 +136,46 @@ class_init (GObjectClass *object_class)
                              NULL, NULL,
                              soup_marshal_NONE__NONE,
                              G_TYPE_NONE, 0);
+       signals[AUTHENTICATE] =
+               g_signal_new ("authenticate",
+                             G_OBJECT_CLASS_TYPE (object_class),
+                             G_SIGNAL_RUN_FIRST,
+                             G_STRUCT_OFFSET (SoupConnectionClass, authenticate),
+                             NULL, NULL,
+                             soup_marshal_NONE__OBJECT_STRING_STRING_POINTER_POINTER,
+                             G_TYPE_NONE, 5,
+                             SOUP_TYPE_MESSAGE,
+                             G_TYPE_STRING,
+                             G_TYPE_STRING,
+                             G_TYPE_POINTER,
+                             G_TYPE_POINTER);
+       signals[REAUTHENTICATE] =
+               g_signal_new ("reauthenticate",
+                             G_OBJECT_CLASS_TYPE (object_class),
+                             G_SIGNAL_RUN_FIRST,
+                             G_STRUCT_OFFSET (SoupConnectionClass, reauthenticate),
+                             NULL, NULL,
+                             soup_marshal_NONE__OBJECT_STRING_STRING_POINTER_POINTER,
+                             G_TYPE_NONE, 5,
+                             SOUP_TYPE_MESSAGE,
+                             G_TYPE_STRING,
+                             G_TYPE_STRING,
+                             G_TYPE_POINTER,
+                             G_TYPE_POINTER);
+
+       /* properties */
+       g_object_class_install_property (
+               object_class, PROP_DEST_URI,
+               g_param_spec_pointer (SOUP_CONNECTION_DEST_URI,
+                                     "Destination URI",
+                                     "The HTTP destination server to use for this connection",
+                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+       g_object_class_install_property (
+               object_class, PROP_PROXY_URI,
+               g_param_spec_pointer (SOUP_CONNECTION_PROXY_URI,
+                                     "Proxy URI",
+                                     "The HTTP Proxy to use for this connection",
+                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 }
 
 SOUP_MAKE_TYPE (soup_connection, SoupConnection, class_init, init, PARENT_TYPE)
@@ -118,68 +183,76 @@ SOUP_MAKE_TYPE (soup_connection, SoupConnection, class_init, init, PARENT_TYPE)
 
 /**
  * soup_connection_new:
- * @uri: remote machine to connect to
+ * @propname1: name of first property to set
+ * @...:
+ *
+ * Creates an HTTP connection. You must set at least one of
+ * %SOUP_CONNECTION_DEST_URI or %SOUP_CONNECTION_PROXY_URI. If you set a
+ * destination URI but no proxy URI, this will be a direct connection. If
+ * you set a proxy URI and an https destination URI, this will be a tunnel.
+ * Otherwise it will be an http proxy connection.
  *
- * Creates a connection to @uri. You must call
- * soup_connection_connect_async() or soup_connection_connect_sync()
- * to connect it after creating it.
+ * You must call soup_connection_connect_async() or
+ * soup_connection_connect_sync() to connect it after creating it.
  *
  * Return value: the new connection (not yet ready for use).
  **/
 SoupConnection *
-soup_connection_new (const SoupUri *uri)
+soup_connection_new (const char *propname1, ...)
 {
        SoupConnection *conn;
+       va_list ap;
 
-       conn = g_object_new (SOUP_TYPE_CONNECTION, NULL);
-       conn->priv->dest_uri = soup_uri_copy_root (uri);
+       va_start (ap, propname1);
+       conn = (SoupConnection *)g_object_new_valist (SOUP_TYPE_CONNECTION,
+                                                     propname1, ap);
+       va_end (ap);
 
        return conn;
 }
 
-/**
- * soup_connection_new_proxy:
- * @proxy_uri: proxy to connect to
- *
- * Creates a connection to @proxy_uri. As with soup_connection_new(),
- * the returned object is not yet connected.
- *
- * Return value: the new connection (not yet ready for use).
- **/
-SoupConnection *
-soup_connection_new_proxy (const SoupUri *proxy_uri)
+static void
+set_property (GObject *object, guint prop_id,
+             const GValue *value, GParamSpec *pspec)
 {
-       SoupConnection *conn;
-
-       conn = g_object_new (SOUP_TYPE_CONNECTION, NULL);
-       conn->priv->proxy_uri = soup_uri_copy_root (proxy_uri);
-
-       return conn;
+       SoupConnection *conn = SOUP_CONNECTION (object);
+       gpointer pval;
+
+       switch (prop_id) {
+       case PROP_DEST_URI:
+               pval = g_value_get_pointer (value);
+               conn->priv->dest_uri = pval ? soup_uri_copy (pval) : NULL;
+               break;
+       case PROP_PROXY_URI:
+               pval = g_value_get_pointer (value);
+               conn->priv->proxy_uri = pval ? soup_uri_copy (pval) : NULL;
+               break;
+       default:
+               break;
+       }
 }
 
-/**
- * soup_connection_new_tunnel:
- * @proxy_uri: proxy to connect to
- * @dest_uri: remote machine to ask the proxy to connect to
- *
- * Creates a connection to @uri via @proxy_uri. As with
- * soup_connection_new(), the returned object is not yet connected.
- *
- * Return value: the new connection (not yet ready for use).
- **/
-SoupConnection *
-soup_connection_new_tunnel (const SoupUri *proxy_uri, const SoupUri *dest_uri)
+static void
+get_property (GObject *object, guint prop_id,
+             GValue *value, GParamSpec *pspec)
 {
-       SoupConnection *conn;
-
-       conn = g_object_new (SOUP_TYPE_CONNECTION, NULL);
-       conn->priv->dest_uri = soup_uri_copy_root (dest_uri);
-       conn->priv->proxy_uri = soup_uri_copy_root (proxy_uri);
+       SoupConnection *conn = SOUP_CONNECTION (object);
 
-       return conn;
+       switch (prop_id) {
+       case PROP_DEST_URI:
+               g_value_set_pointer (value, conn->priv->dest_uri ?
+                                    soup_uri_copy (conn->priv->dest_uri) :
+                                    NULL);
+               break;
+       case PROP_PROXY_URI:
+               g_value_set_pointer (value, conn->priv->proxy_uri ?
+                                    soup_uri_copy (conn->priv->proxy_uri) :
+                                    NULL);
+       default:
+               break;
+       }
 }
 
-
 static void
 socket_disconnected (SoupSocket *sock, gpointer conn)
 {
@@ -392,20 +465,48 @@ request_done (SoupMessage *req, gpointer user_data)
                soup_connection_disconnect (conn);
 }
 
+static void
+send_request (SoupConnection *conn, SoupMessage *req)
+{
+       if (req != conn->priv->cur_req) {
+               g_return_if_fail (conn->priv->cur_req == NULL);
+               conn->priv->cur_req = req;
+               g_object_add_weak_pointer (G_OBJECT (req),
+                                          (gpointer *)conn->priv->cur_req);
+
+               g_signal_connect (req, "finished",
+                                 G_CALLBACK (request_done), conn);
+       }
+
+       soup_message_io_cancel (req);
+       soup_message_send_request (req, conn->priv->socket,
+                                  conn->priv->proxy_uri != NULL);
+}
+
 void
 soup_connection_send_request (SoupConnection *conn, SoupMessage *req)
 {
        g_return_if_fail (SOUP_IS_CONNECTION (conn));
        g_return_if_fail (SOUP_IS_MESSAGE (req));
        g_return_if_fail (conn->priv->socket != NULL);
-       g_return_if_fail (conn->priv->cur_req == NULL);
 
-       conn->priv->cur_req = req;
-       g_object_add_weak_pointer (G_OBJECT (req),
-                                  (gpointer *)conn->priv->cur_req);
+       SOUP_CONNECTION_GET_CLASS (conn)->send_request (conn, req);
+}
 
-       g_signal_connect (req, "finished", G_CALLBACK (request_done), conn);
+void
+soup_connection_authenticate (SoupConnection *conn, SoupMessage *msg,
+                             const char *auth_type, const char *auth_realm,
+                             char **username, char **password)
+{
+       g_signal_emit (conn, signals[AUTHENTICATE], 0,
+                      msg, auth_type, auth_realm, username, password);
+}
 
-       soup_message_send_request (req, conn->priv->socket,
-                                  conn->priv->proxy_uri != NULL);
+void
+soup_connection_reauthenticate (SoupConnection *conn, SoupMessage *msg,
+                               const char *auth_type, const char *auth_realm,
+                               char **username, char **password)
+{
+       g_signal_emit (conn, signals[REAUTHENTICATE], 0,
+                      msg, auth_type, auth_realm, username, password);
 }
index 74628e1..f40287c 100644 (file)
@@ -30,21 +30,32 @@ typedef struct {
 
        /* signals */
        void (*connect_result) (SoupConnection *, guint);
-       void (*disconnected) (SoupConnection *);
+       void (*disconnected)   (SoupConnection *);
+
+       void (*authenticate)   (SoupConnection *, SoupMessage *,
+                               const char *auth_type, const char *auth_realm,
+                               char **username, char **password);
+       void (*reauthenticate) (SoupConnection *, SoupMessage *,
+                               const char *auth_type, const char *auth_realm,
+                               char **username, char **password);
+
+       /* methods */
+       void (*send_request) (SoupConnection *, SoupMessage *);
 } SoupConnectionClass;
 
 GType soup_connection_get_type (void);
 
 
+#define SOUP_CONNECTION_DEST_URI "dest-uri"
+#define SOUP_CONNECTION_PROXY_URI "proxy-uri"
+
+SoupConnection *soup_connection_new            (const char       *propname1,
+                                               ...);
+
 typedef void  (*SoupConnectionCallback)        (SoupConnection   *sock,
                                                guint             status,
                                                gpointer          data);
 
-SoupConnection *soup_connection_new            (const SoupUri    *uri);
-SoupConnection *soup_connection_new_proxy      (const SoupUri    *proxy_uri);
-SoupConnection *soup_connection_new_tunnel     (const SoupUri    *proxy_uri,
-                                               const SoupUri    *dest_uri);
-
 void            soup_connection_connect_async  (SoupConnection   *conn,
                                                SoupConnectionCallback,
                                                gpointer          user_data);
@@ -58,4 +69,19 @@ time_t          soup_connection_last_used      (SoupConnection   *conn);
 void            soup_connection_send_request   (SoupConnection   *conn,
                                                SoupMessage      *req);
 
+/* protected */
+void            soup_connection_authenticate   (SoupConnection   *conn,
+                                               SoupMessage      *msg,
+                                               const char       *auth_type,
+                                               const char       *auth_realm,
+                                               char            **username,
+                                               char            **password);
+void            soup_connection_reauthenticate (SoupConnection   *conn,
+                                               SoupMessage      *msg,
+                                               const char       *auth_type,
+                                               const char       *auth_realm,
+                                               char            **username,
+                                               char            **password);
+
+
 #endif /* SOUP_CONNECTION_H */
index 77d132d..1c24548 100644 (file)
@@ -605,9 +605,9 @@ static void
 check_hostent (SoupDNSEntry *entry, gboolean block)
 {
        char buf[256], *namelenp, *name, *typep, *addrlenp, *addr;
-       int nread;
+       int nread, status;
        fd_set readfds;
-       struct timeval tv = { 0, 0 };
+       struct timeval tv = { 0, 0 }, *tvp;
 
        soup_dns_lock ();
 
@@ -616,9 +616,18 @@ check_hostent (SoupDNSEntry *entry, gboolean block)
                return;
        }
 
-       FD_ZERO (&readfds);
-       FD_SET (entry->fd, &readfds);
-       if (select (entry->fd + 1, &readfds, NULL, NULL, &tv) != 0) {
+       if (block)
+               tvp = &tv;
+       else
+               tvp = NULL;
+
+       do {
+               FD_ZERO (&readfds);
+               FD_SET (entry->fd, &readfds);
+               status = select (entry->fd + 1, &readfds, NULL, NULL, tvp);
+       } while (status == -1 && errno == EINTR);
+
+       if (status == 0) {
                soup_dns_unlock ();
                return;
        }
@@ -660,7 +669,7 @@ soup_dns_entry_get_hostent (SoupDNSEntry *entry)
        struct hostent *h;
 
        check_hostent (entry, TRUE);
-       h = copy_hostent (entry->h);
+       h = entry->h ? copy_hostent (entry->h) : NULL;
        soup_dns_entry_unref (entry);
 
        return h;
index 2469e53..9f42926 100644 (file)
@@ -1,5 +1,4 @@
 NONE:NONE
 NONE:INT
 NONE:OBJECT
-NONE:POINTER
-NONE:POINTER,OBJECT
+NONE:OBJECT,STRING,STRING,POINTER,POINTER
index d3a1dc5..e42b96a 100644 (file)
@@ -154,6 +154,7 @@ void
 soup_message_send_request (SoupMessage *req, SoupSocket *sock,
                           gboolean is_via_proxy)
 {
+       soup_message_prepare (req);
        soup_message_io_client (req, sock,
                                get_request_headers,
                                parse_response_headers,
index 1345296..7fbc56e 100644 (file)
@@ -120,6 +120,7 @@ io_error (SoupSocket *sock, SoupMessage *msg)
        /* Closing the connection to signify EOF is sometimes ok */
        if (io->read_state == SOUP_MESSAGE_IO_STATE_BODY &&
            io->read_encoding == SOUP_TRANSFER_UNKNOWN) {
+               io->read_state = SOUP_MESSAGE_IO_STATE_DONE;
                soup_message_io_finished (msg);
                return;
        }
index 6782acb..3da643f 100644 (file)
@@ -52,6 +52,4 @@ void soup_message_io_server  (SoupMessage               *msg,
                              SoupMessageParseHeadersFn  parse_headers_cb,
                              gpointer                   user_data);
 
-void soup_message_io_cancel  (SoupMessage *msg);
-
 #endif /* SOUP_MESSAGE_PRIVATE_H */
index 08f60be..cc9ea00 100644 (file)
@@ -250,6 +250,7 @@ void           soup_message_send_request        (SoupMessage       *req,
                                                 gboolean           via_proxy);
 void           soup_message_read_request        (SoupMessage       *req,
                                                 SoupSocket        *sock);
+void           soup_message_io_cancel           (SoupMessage       *msg);;
 void           soup_message_io_pause            (SoupMessage       *msg);
 void           soup_message_io_unpause          (SoupMessage       *msg);
 
index 570d89c..fade4d1 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "soup-session.h"
 #include "soup-connection.h"
+#include "soup-connection-ntlm.h"
 #include "soup-marshal.h"
 #include "soup-message-queue.h"
 #include "soup-private.h"
@@ -28,13 +29,12 @@ typedef struct {
 
        GHashTable *auth_realms;      /* path -> scheme:realm */
        GHashTable *auths;            /* scheme:realm -> SoupAuth */
-
-       GHashTable *ntlm_auths;       /* SoupConnection -> SoupAuth */
 } SoupSessionHost;
 
 struct SoupSessionPrivate {
        SoupUri *proxy_uri;
        guint max_conns, max_conns_per_host;
+       gboolean use_ntlm;
 
        SoupMessageQueue *queue;
 
@@ -64,6 +64,22 @@ enum {
 
 static guint signals[LAST_SIGNAL] = { 0 };
 
+enum {
+  PROP_0,
+
+  PROP_PROXY_URI,
+  PROP_MAX_CONNS,
+  PROP_MAX_CONNS_PER_HOST,
+  PROP_USE_NTLM,
+
+  LAST_PROP
+};
+
+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
 init (GObject *object)
 {
@@ -105,6 +121,8 @@ class_init (GObjectClass *object_class)
 
        /* virtual method override */
        object_class->finalize = finalize;
+       object_class->set_property = set_property;
+       object_class->get_property = get_property;
 
        /* signals */
        signals[AUTHENTICATE] =
@@ -113,53 +131,132 @@ class_init (GObjectClass *object_class)
                              G_SIGNAL_RUN_FIRST,
                              G_STRUCT_OFFSET (SoupSessionClass, authenticate),
                              NULL, NULL,
-                             soup_marshal_NONE__POINTER_OBJECT,
-                             G_TYPE_NONE, 2,
+                             soup_marshal_NONE__OBJECT_STRING_STRING_POINTER_POINTER,
+                             G_TYPE_NONE, 5,
+                             SOUP_TYPE_MESSAGE,
+                             G_TYPE_STRING,
+                             G_TYPE_STRING,
                              G_TYPE_POINTER,
-                             SOUP_TYPE_MESSAGE);
+                             G_TYPE_POINTER);
        signals[REAUTHENTICATE] =
                g_signal_new ("reauthenticate",
                              G_OBJECT_CLASS_TYPE (object_class),
                              G_SIGNAL_RUN_FIRST,
                              G_STRUCT_OFFSET (SoupSessionClass, reauthenticate),
                              NULL, NULL,
-                             soup_marshal_NONE__POINTER_OBJECT,
-                             G_TYPE_NONE, 2,
+                             soup_marshal_NONE__OBJECT_STRING_STRING_POINTER_POINTER,
+                             G_TYPE_NONE, 5,
+                             SOUP_TYPE_MESSAGE,
+                             G_TYPE_STRING,
+                             G_TYPE_STRING,
                              G_TYPE_POINTER,
-                             SOUP_TYPE_MESSAGE);
+                             G_TYPE_POINTER);
+
+       /* properties */
+       g_object_class_install_property (
+               object_class, PROP_PROXY_URI,
+               g_param_spec_pointer (SOUP_SESSION_PROXY_URI,
+                                     "Proxy URI",
+                                     "The HTTP Proxy to use for this session",
+                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+       g_object_class_install_property (
+               object_class, PROP_MAX_CONNS,
+               g_param_spec_int (SOUP_SESSION_MAX_CONNS,
+                                 "Max Connection Count",
+                                 "The maximum number of connections that the session can open at once",
+                                 1,
+                                 G_MAXINT,
+                                 10,
+                                 G_PARAM_READWRITE));
+       g_object_class_install_property (
+               object_class, PROP_MAX_CONNS_PER_HOST,
+               g_param_spec_int (SOUP_SESSION_MAX_CONNS_PER_HOST,
+                                 "Max Per-Host Connection Count",
+                                 "The maximum number of connections that the session can open at once to a given host",
+                                 1,
+                                 G_MAXINT,
+                                 4,
+                                 G_PARAM_READWRITE));
+       g_object_class_install_property (
+               object_class, PROP_USE_NTLM,
+               g_param_spec_boolean (SOUP_SESSION_USE_NTLM,
+                                     "Use NTLM",
+                                     "Whether or not to use NTLM authentication",
+                                     FALSE,
+                                     G_PARAM_READWRITE));
 }
 
 SOUP_MAKE_TYPE (soup_session, SoupSession, class_init, init, PARENT_TYPE)
 
 SoupSession *
-soup_session_new_default (void)
+soup_session_new (void)
 {
        return g_object_new (SOUP_TYPE_SESSION, NULL);
 }
 
 SoupSession *
-soup_session_new_with_proxy (const SoupUri *proxy_uri)
+soup_session_new_with_options (const char *optname1, ...)
 {
        SoupSession *session;
+       va_list ap;
 
-       session = soup_session_new_default ();
-       if (proxy_uri)
-               session->priv->proxy_uri = soup_uri_copy (proxy_uri);
+       va_start (ap, optname1);
+       session = (SoupSession *)g_object_new_valist (SOUP_TYPE_SESSION, optname1, ap);
+       va_end (ap);
 
        return session;
 }
 
-SoupSession *
-soup_session_new_full (const SoupUri *proxy_uri,
-                      guint max_conns, guint max_conns_per_host)
+static void
+set_property (GObject *object, guint prop_id,
+             const GValue *value, GParamSpec *pspec)
 {
-       SoupSession *session;
+       SoupSession *session = SOUP_SESSION (object);
+       gpointer pval;
+
+       switch (prop_id) {
+       case PROP_PROXY_URI:
+               pval = g_value_get_pointer (value);
+               session->priv->proxy_uri = pval ? soup_uri_copy (pval) : NULL;
+               break;
+       case PROP_MAX_CONNS:
+               session->priv->max_conns = g_value_get_int (value);
+               break;
+       case PROP_MAX_CONNS_PER_HOST:
+               session->priv->max_conns_per_host = g_value_get_int (value);
+               break;
+       case PROP_USE_NTLM:
+               session->priv->use_ntlm = g_value_get_boolean (value);
+               break;
+       default:
+               break;
+       }
+}
 
-       session = soup_session_new_with_proxy (proxy_uri);
-       session->priv->max_conns = max_conns;
-       session->priv->max_conns_per_host = max_conns_per_host;
+static void
+get_property (GObject *object, guint prop_id,
+             GValue *value, GParamSpec *pspec)
+{
+       SoupSession *session = SOUP_SESSION (object);
 
-       return session;
+       switch (prop_id) {
+       case PROP_PROXY_URI:
+               g_value_set_pointer (value, session->priv->proxy_uri ?
+                                    soup_uri_copy (session->priv->proxy_uri) :
+                                    NULL);
+               break;
+       case PROP_MAX_CONNS:
+               g_value_set_int (value, session->priv->max_conns);
+               break;
+       case PROP_MAX_CONNS_PER_HOST:
+               g_value_set_int (value, session->priv->max_conns_per_host);
+               break;
+       case PROP_USE_NTLM:
+               g_value_set_boolean (value, session->priv->use_ntlm);
+               break;
+       default:
+               break;
+       }
 }
 
 
@@ -268,13 +365,26 @@ authenticate_auth (SoupSession *session, SoupAuth *auth,
                   SoupMessage *msg, gboolean prior_auth_failed)
 {
        const SoupUri *uri = soup_message_get_uri (msg);
+       char *username = NULL, *password = NULL;
 
        if (uri->passwd && !prior_auth_failed) {
                soup_auth_authenticate (auth, uri->user, uri->passwd);
                return TRUE;
        }
 
-       g_signal_emit (session, signals[prior_auth_failed ? REAUTHENTICATE : AUTHENTICATE], 0, auth, msg);
+       g_signal_emit (session, signals[prior_auth_failed ? REAUTHENTICATE : AUTHENTICATE], 0,
+                      msg, soup_auth_get_scheme_name (auth),
+                      soup_auth_get_realm (auth),
+                      &username, &password);
+       if (username || password)
+               soup_auth_authenticate (auth, username, password);
+       if (username)
+               g_free (username);
+       if (password) {
+               memset (password, 0, strlen (password));
+               g_free (password);
+       }
+
        return soup_auth_is_authenticated (auth);
 }
 
@@ -372,6 +482,26 @@ update_auth_internal (SoupSession *session, SoupMessage *msg,
 }
 
 static void
+connection_authenticate (SoupConnection *conn, SoupMessage *msg,
+                        const char *auth_type, const char *auth_realm,
+                        char **username, char **password, gpointer session)
+{
+       g_signal_emit (session, signals[AUTHENTICATE], 0,
+                      msg, auth_type, auth_realm, username, password);
+}
+
+static void
+connection_reauthenticate (SoupConnection *conn, SoupMessage *msg,
+                          const char *auth_type, const char *auth_realm,
+                          char **username, char **password,
+                          gpointer user_data)
+{
+       g_signal_emit (conn, signals[REAUTHENTICATE], 0,
+                      msg, auth_type, auth_realm, username, password);
+}
+
+
+static void
 authorize_handler (SoupMessage *msg, gpointer user_data)
 {
        SoupSession *session = user_data;
@@ -387,6 +517,8 @@ authorize_handler (SoupMessage *msg, gpointer user_data)
                                                        "WWW-Authenticate");
                proxy = FALSE;
        }
+       if (!headers)
+               return;
 
        if (update_auth_internal (session, msg, headers, proxy, TRUE))
                soup_session_requeue_message (session, msg);
@@ -421,16 +553,17 @@ redirect_handler (SoupMessage *msg, gpointer user_data)
 static void
 request_finished (SoupMessage *req, gpointer user_data)
 {
-       SoupSession *session = user_data;
-
-       soup_message_queue_remove_message (session->priv->queue, req);
        req->status = SOUP_MESSAGE_STATUS_FINISHED;
 }
 
 static void
-final_finished (SoupMessage *req, gpointer session)
+final_finished (SoupMessage *req, gpointer user_data)
 {
+       SoupSession *session = user_data;
+
        if (!SOUP_MESSAGE_IS_STARTING (req)) {
+               soup_message_queue_remove_message (session->priv->queue, req);
+
                g_signal_handlers_disconnect_by_func (req, request_finished, session);
                g_signal_handlers_disconnect_by_func (req, final_finished, session);
                g_object_unref (req);
@@ -627,16 +760,18 @@ run_queue (SoupSession *session, gboolean try_pruning)
                }
 
                /* Otherwise, open a new connection */
-               if (session->priv->proxy_uri &&
-                   host->root_uri->protocol == SOUP_PROTOCOL_HTTPS) {
-                       conn = soup_connection_new_tunnel (
-                               session->priv->proxy_uri, host->root_uri);
-               } else if (session->priv->proxy_uri) {
-                       conn = soup_connection_new_proxy (
-                               session->priv->proxy_uri);
-               } else {
-                       conn = soup_connection_new (host->root_uri);
-               }
+               conn = g_object_new (
+                       (session->priv->use_ntlm ?
+                        SOUP_TYPE_CONNECTION_NTLM : SOUP_TYPE_CONNECTION),
+                       SOUP_CONNECTION_DEST_URI, host->root_uri,
+                       SOUP_CONNECTION_PROXY_URI, session->priv->proxy_uri,
+                       NULL);
+               g_signal_connect (conn, "authenticate",
+                                 G_CALLBACK (connection_authenticate),
+                                 session);
+               g_signal_connect (conn, "reauthenticate",
+                                 G_CALLBACK (connection_reauthenticate),
+                                 session);
 
                soup_connection_connect_async (conn, got_connection, session);
                g_signal_connect (conn, "disconnected",
@@ -675,8 +810,6 @@ run_queue (SoupSession *session, gboolean try_pruning)
 static void
 queue_message (SoupSession *session, SoupMessage *req, gboolean requeue)
 {
-       soup_message_prepare (req);
-
        req->status = SOUP_MESSAGE_STATUS_QUEUED;
        if (!requeue)
                soup_message_queue_append (session->priv->queue, req);
index 1871ec6..5ad03c2 100644 (file)
@@ -7,7 +7,6 @@
 #define SOUP_SESSION_H 1
 
 #include <libsoup/soup-types.h>
-#include <libsoup/soup-auth.h>
 #include <libsoup/soup-message.h>
 
 #define SOUP_TYPE_SESSION            (soup_session_get_type ())
@@ -29,28 +28,35 @@ typedef struct {
        GObjectClass parent_class;
 
        /* signals */
-       void (*authenticate)   (SoupSession *, SoupAuth *, SoupMessage *);
-       void (*reauthenticate) (SoupSession *, SoupAuth *, SoupMessage *);
+       void (*authenticate)   (SoupSession *, SoupMessage *,
+                               const char *auth_type, const char *auth_realm,
+                               char **username, char **password);
+       void (*reauthenticate) (SoupSession *, SoupMessage *,
+                               const char *auth_type, const char *auth_realm,
+                               char **username, char **password);
 
 } SoupSessionClass;
 
 GType soup_session_get_type (void);
 
-SoupSession    *soup_session_new_default     (void);
-SoupSession    *soup_session_new_with_proxy  (const SoupUri         *proxy_uri);
-SoupSession    *soup_session_new_full        (const SoupUri         *proxy_uri,
-                                             guint                  max_conns,
-                                             guint                  max_per_host);
-
-void            soup_session_queue_message   (SoupSession           *session,
-                                             SoupMessage           *req,
-                                             SoupMessageCallbackFn  callback,
-                                             gpointer               user_data);
-void            soup_session_requeue_message (SoupSession           *session,
-                                             SoupMessage           *req);
-
-guint           soup_session_send_message    (SoupSession           *session,
-                                             SoupMessage            *req);
+#define SOUP_SESSION_PROXY_URI          "proxy-uri"
+#define SOUP_SESSION_MAX_CONNS          "max-conns"
+#define SOUP_SESSION_MAX_CONNS_PER_HOST "max-conns-per-host"
+#define SOUP_SESSION_USE_NTLM           "use-ntlm"
+
+SoupSession    *soup_session_new              (void);
+SoupSession    *soup_session_new_with_options (const char            *optname1,
+                                              ...);
+
+void            soup_session_queue_message    (SoupSession           *session,
+                                              SoupMessage           *req,
+                                              SoupMessageCallbackFn  callback,
+                                              gpointer               user_data);
+void            soup_session_requeue_message  (SoupSession           *session,
+                                              SoupMessage           *req);
+
+guint           soup_session_send_message     (SoupSession           *session,
+                                              SoupMessage            *req);
 
 
 #endif /* SOUP_SESSION_H */
index c673104..a954bd5 100644 (file)
@@ -9,7 +9,7 @@
 #define SOUP_STATUS_H 1
 
 typedef enum {
-       SOUP_STATUS_CLASS_TRANSPORT = 1,
+       SOUP_STATUS_CLASS_TRANSPORT = 0,
        SOUP_STATUS_CLASS_INFORMATIONAL,
        SOUP_STATUS_CLASS_SUCCESS,
        SOUP_STATUS_CLASS_REDIRECT,
index a3bb480..9271b38 100644 (file)
@@ -250,28 +250,28 @@ handler (SoupMessage *msg, gpointer data)
 }
 
 static void
-authenticate (SoupSession *session, SoupAuth *auth, SoupMessage *msg, gpointer data)
+authenticate (SoupSession *session, SoupMessage *msg,
+             const char *auth_type, const char *auth_realm,
+             char **username, char **password, gpointer data)
 {
-       char user[6], password[7];
        int *i = data;
 
        if (tests[*i].provided[0]) {
-               sprintf (user, "user%c", tests[*i].provided[0]);
-               sprintf (password, "realm%c", tests[*i].provided[0]);
-               soup_auth_authenticate (auth, user, password);
+               *username = g_strdup_printf ("user%c", tests[*i].provided[0]);
+               *password = g_strdup_printf ("realm%c", tests[*i].provided[0]);
        }
 }
 
 static void
-reauthenticate (SoupSession *session, SoupAuth *auth, SoupMessage *msg, gpointer data)
+reauthenticate (SoupSession *session, SoupMessage *msg, 
+               const char *auth_type, const char *auth_realm,
+               char **username, char **password, gpointer data)
 {
-       char user[6], password[7];
        int *i = data;
 
        if (tests[*i].provided[0] && tests[*i].provided[1]) {
-               sprintf (user, "user%c", tests[*i].provided[1]);
-               sprintf (password, "realm%c", tests[*i].provided[1]);
-               soup_auth_authenticate (auth, user, password);
+               *username = g_strdup_printf ("user%c", tests[*i].provided[1]);
+               *password = g_strdup_printf ("realm%c", tests[*i].provided[1]);
        }
 }
 
@@ -285,7 +285,7 @@ main (int argc, char **argv)
 
        g_type_init ();
 
-       session = soup_session_new_default ();
+       session = soup_session_new ();
        g_signal_connect (session, "authenticate",
                          G_CALLBACK (authenticate), &i);
        g_signal_connect (session, "reauthenticate",
index ec1ee7b..efb9b9d 100644 (file)
@@ -207,7 +207,7 @@ main (int argc, char **argv)
        int opt;
 
        g_type_init ();
-       session = soup_session_new_default ();
+       session = soup_session_new ();
 
        while ((opt = getopt (argc, argv, "r")) != -1) {
                switch (opt) {
index b5b21a4..3af0a75 100644 (file)
@@ -159,7 +159,7 @@ main (int argc, char **argv)
                soup_server_get_port (server));
        soup_server_run_async (server);
 
-       session = soup_session_new_default ();
+       session = soup_session_new ();
 
        printf ("\nWaiting for requests...\n");