summaryrefslogtreecommitdiff
path: root/libsoup
diff options
context:
space:
mode:
authorDan Winship <danw@src.gnome.org>2002-11-05 19:45:46 +0000
committerDan Winship <danw@src.gnome.org>2002-11-05 19:45:46 +0000
commitd4629510fb547f3ed2cce829ea1ec0c73bc5647c (patch)
tree19ee5b614bf12a0aa2ebd29d8a9fd2535dea8386 /libsoup
parent6314c214c92e43c84be54754013580ecb475b486 (diff)
downloadlibsoup-d4629510fb547f3ed2cce829ea1ec0c73bc5647c.tar.gz
Split libsoup out of soup. ChangeLog.old contains the original soup
* Split libsoup out of soup. ChangeLog.old contains the original soup ChangeLog. * Makefile.am, etc: Fix things up to work with the new directory layout. Disable docs until we fix them. * autogen.sh: Use gnome-autogen.sh * configure.in: Require autoconf 2.53. Remove stuff that was only needed for httpd or wsdl code. Remove glib1 support. Bump version to 2.0. * libsoup/Makefile.am: Rename library to libsoup-2.0, put includes in ${includedir}/soup-2.0 * libsoup/*: Merge soup-0-7 back onto the trunk. Remove SOAP-specific stuff, Windows support, and other things that weren't being maintained. * soup-config.in, soupConf.sh: Kill these. We only support pkg-config now.
Diffstat (limited to 'libsoup')
-rw-r--r--libsoup/.cvsignore1
-rw-r--r--libsoup/Makefile.am50
-rw-r--r--libsoup/soup-auth.c155
-rw-r--r--libsoup/soup-auth.h24
-rw-r--r--libsoup/soup-context.c72
-rw-r--r--libsoup/soup-context.h2
-rw-r--r--libsoup/soup-headers.c4
-rw-r--r--libsoup/soup-headers.h2
-rw-r--r--libsoup/soup-message.c727
-rw-r--r--libsoup/soup-message.h134
-rw-r--r--libsoup/soup-misc.c70
-rw-r--r--libsoup/soup-misc.h13
-rw-r--r--libsoup/soup-nss.c9
-rw-r--r--libsoup/soup-nss.h5
-rw-r--r--libsoup/soup-ntlm.c394
-rw-r--r--libsoup/soup-ntlm.h25
-rw-r--r--libsoup/soup-openssl.c329
-rw-r--r--libsoup/soup-openssl.h2
-rw-r--r--libsoup/soup-private.h40
-rw-r--r--libsoup/soup-queue.c29
-rw-r--r--libsoup/soup-queue.h2
-rw-r--r--libsoup/soup-server.c259
-rw-r--r--libsoup/soup-server.h9
-rw-r--r--libsoup/soup-socket-unix.c10
-rw-r--r--libsoup/soup-socket.c140
-rw-r--r--libsoup/soup-socket.h2
-rw-r--r--libsoup/soup-socks.c2
-rw-r--r--libsoup/soup-socks.h2
-rw-r--r--libsoup/soup-ssl-proxy.c32
-rw-r--r--libsoup/soup-ssl.c73
-rw-r--r--libsoup/soup-ssl.h8
-rw-r--r--libsoup/soup-transfer.c132
-rw-r--r--libsoup/soup-transfer.h2
-rw-r--r--libsoup/soup-uri.c6
-rw-r--r--libsoup/soup-uri.h3
-rw-r--r--libsoup/soup.h8
36 files changed, 1497 insertions, 1280 deletions
diff --git a/libsoup/.cvsignore b/libsoup/.cvsignore
index 69fb0bd8..0be24a01 100644
--- a/libsoup/.cvsignore
+++ b/libsoup/.cvsignore
@@ -4,3 +4,4 @@
.libs
Makefile
Makefile.in
+libsoup-ssl-proxy
diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am
index e47c5752..8e6f1697 100644
--- a/libsoup/Makefile.am
+++ b/libsoup/Makefile.am
@@ -1,71 +1,57 @@
## Process this file with automake to produce Makefile.in
-@SET_MAKE@
-
INCLUDES = \
-DG_LOG_DOMAIN=\"SOUP\" \
-DSYSCONFDIR=\"$(sysconfdir)\" \
-DBINDIR=\"$(bindir)\" \
- -I$(top_srcdir)/src \
+ -I$(top_srcdir) \
$(SOUP_DEBUG_FLAGS) \
$(GLIB_CFLAGS) \
- $(XML_CFLAGS) \
- $(NSS_CFLAGS)
+ $(NSS_CFLAGS) \
+ $(OPENSSL_CFLAGS)
-libsoupincludedir = $(includedir)/soup/libsoup
+libsoupincludedir = $(includedir)/soup-2.0/libsoup
libsoupinclude_HEADERS = \
soup.h \
soup-context.h \
- soup-dav.h \
- soup-dav-server.h \
- soup-env.h \
soup-error.h \
- soup-fault.h \
soup-headers.h \
soup-message.h \
soup-method.h \
soup-misc.h \
- soup-parser.h \
- soup-serializer.h \
+ soup-ntlm.h \
soup-server-auth.h \
soup-server.h \
soup-socket.h \
soup-uri.h
-lib_LTLIBRARIES = libsoup.la
+lib_LTLIBRARIES = libsoup-2.0.la
-libsoup_la_LDFLAGS = -version-info $(SOUP_CURRENT):$(SOUP_REVISION):$(SOUP_AGE)
+libsoup_2_0_la_LDFLAGS = \
+ -version-info $(SOUP_CURRENT):$(SOUP_REVISION):$(SOUP_AGE)
-libsoup_la_LIBADD = \
+libsoup_2_0_la_LIBADD = \
$(GLIB_LIBS) \
- $(XML_LIBS) \
$(NSS_LIBS)
-libsoup_la_SOURCES = \
+libsoup_2_0_la_SOURCES = \
md5-utils.h \
md5-utils.c \
soup-auth.h \
soup-auth.c \
soup-context.c \
- soup-dav.c \
- soup-dav-server.c \
- soup-env.c \
soup-error.c \
- soup-fault.c \
soup-headers.c \
soup-message.c \
soup-method.c \
soup-misc.c \
soup-nss.h \
soup-nss.c \
- soup-ntlm.h \
soup-ntlm.c \
- soup-parser.c \
soup-private.h \
soup-queue.h \
soup-queue.c \
- soup-serializer.c \
soup-server.c \
soup-server-auth.c \
soup-socket.c \
@@ -78,5 +64,19 @@ libsoup_la_SOURCES = \
soup-transfer.c \
soup-uri.c
-EXTRA_DIST =
+noinst_PROGRAMS = libsoup-ssl-proxy
+
+libsoup_ssl_proxy_LDADD = \
+ $(LINK_STATIC) \
+ $(OPENSSL_LIBS) \
+ $(GLIB_LIBS) \
+ $(LINK_DYNAMIC)
+
+libsoup_ssl_proxy_SOURCES = \
+ soup-openssl.h \
+ soup-openssl.c \
+ soup-ssl-proxy.c
+install-exec-hook:
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ $(INSTALL_PROGRAM) libsoup-ssl-proxy $(DESTDIR)$(bindir)/$(SSL_PROXY_NAME)
diff --git a/libsoup/soup-auth.c b/libsoup/soup-auth.c
index dd282925..2b3b22d4 100644
--- a/libsoup/soup-auth.c
+++ b/libsoup/soup-auth.c
@@ -14,14 +14,7 @@
#include <config.h>
#endif
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
-
-#ifdef SOUP_WIN32
-#include <process.h>
-#endif
-
#include <string.h>
#include <stdlib.h>
#include <glib.h>
@@ -46,12 +39,6 @@ typedef struct {
gchar *token;
} SoupAuthBasic;
-static gboolean
-basic_compare_func (SoupAuth *a, SoupAuth *b)
-{
- return FALSE;
-}
-
static char *
basic_auth_func (SoupAuth *auth, SoupMessage *message)
{
@@ -105,7 +92,6 @@ soup_auth_new_basic (void)
auth = (SoupAuth *) basic;
auth->type = SOUP_AUTH_TYPE_BASIC;
- auth->compare_func = basic_compare_func;
auth->parse_func = basic_parse_func;
auth->init_func = basic_init_func;
auth->auth_func = basic_auth_func;
@@ -140,7 +126,6 @@ typedef struct {
char *nonce;
QOPType qop_options;
AlgorithmType algorithm;
- gboolean stale;
/* These are generated by the client */
char *cnonce;
@@ -148,12 +133,6 @@ typedef struct {
QOPType qop;
} SoupAuthDigest;
-static gboolean
-digest_compare_func (SoupAuth *a, SoupAuth *b)
-{
- return ((SoupAuthDigest *) a)->stale;
-}
-
static void
digest_hex (guchar *digest, guchar hex[33])
{
@@ -285,6 +264,7 @@ digest_auth_func (SoupAuth *auth, SoupMessage *message)
url,
response);
+ g_free (response);
g_free (url);
g_free (nc);
@@ -369,15 +349,6 @@ digest_parse_func (SoupAuth *auth, const char *header)
g_free (tmp);
- tmp = soup_header_param_copy_token (tokens, "stale");
-
- if (tmp && g_strcasecmp (tmp, "true") == 0)
- digest->stale = TRUE;
- else
- digest->stale = FALSE;
-
- g_free (tmp);
-
tmp = soup_header_param_copy_token (tokens, "algorithm");
digest->algorithm = decode_algorithm (tmp);
g_free (tmp);
@@ -447,7 +418,6 @@ soup_auth_new_digest (void)
auth = (SoupAuth *) digest;
auth->type = SOUP_AUTH_TYPE_DIGEST;
- auth->compare_func = digest_compare_func;
auth->parse_func = digest_parse_func;
auth->init_func = digest_init_func;
auth->auth_func = digest_auth_func;
@@ -462,6 +432,8 @@ soup_auth_new_digest (void)
/* We're just going to do qop=auth for now */
digest->qop = QOP_AUTH;
+ g_free (bgen);
+
return auth;
}
@@ -474,15 +446,8 @@ typedef struct {
SoupAuth auth;
gchar *response;
gchar *header;
- gboolean completed;
} SoupAuthNTLM;
-static gboolean
-ntlm_compare_func (SoupAuth *a, SoupAuth *b)
-{
- return !((SoupAuthNTLM *)b)->completed;
-}
-
/*
* SoupAuthNTLMs are one time use. Just return the response, and set our
* reference to NULL so future requests do not include this header.
@@ -530,41 +495,42 @@ ntlm_parse (SoupAuth *sa, const char *header)
g_strstrip (auth->header);
}
-/*
- * FIXME: Because NTLM is a two step process, we parse the host and domain out
- * of the context's uri twice. This is because there is no way to reparse
- * a new header with an existing SoupAuth, so a new one is created for
- * each negotiation step.
- */
static void
ntlm_init (SoupAuth *sa, const SoupUri *uri)
{
SoupAuthNTLM *auth = (SoupAuthNTLM *) sa;
- gchar *host, *domain;
-
- host = ntlm_get_authmech_token (uri, "host=");
- domain = ntlm_get_authmech_token (uri, "domain=");
if (strlen (auth->header) < sizeof ("NTLM"))
auth->response = soup_ntlm_request ();
else {
- gchar lm_hash [21], nt_hash [21];
-
- soup_ntlm_lanmanager_hash (uri->passwd, lm_hash);
- soup_ntlm_nt_hash (uri->passwd, nt_hash);
-
- auth->response =
- soup_ntlm_response (auth->header,
- uri->user,
- (gchar *) &lm_hash,
- (gchar *) &nt_hash,
- host,
- domain);
- auth->completed = TRUE;
- }
+ gchar *host, *domain, *nonce;
+
+ host = ntlm_get_authmech_token (uri, "host=");
+ domain = ntlm_get_authmech_token (uri, "domain=");
+
+ if (!soup_ntlm_parse_challenge (auth->header,
+ &nonce,
+ domain ? NULL : &domain))
+ auth->response = NULL;
+ else {
+ auth->response =
+ soup_ntlm_response (nonce,
+ uri->user,
+ uri->passwd,
+ host,
+ domain);
+ g_free (nonce);
+ }
- g_free (host);
- g_free (domain);
+ g_free (host);
+ g_free (domain);
+
+ /* Set this now so that if the server returns 401,
+ * soup will fail instead of looping (since that
+ * probably means the password was incorrect).
+ */
+ sa->status = SOUP_AUTH_STATUS_SUCCESSFUL;
+ }
g_free (auth->header);
auth->header = NULL;
@@ -587,7 +553,6 @@ ntlm_new (void)
auth = g_new0 (SoupAuthNTLM, 1);
auth->auth.type = SOUP_AUTH_TYPE_NTLM;
- auth->auth.compare_func = ntlm_compare_func;
auth->auth.parse_func = ntlm_parse;
auth->auth.init_func = ntlm_init;
auth->auth.auth_func = ntlm_auth;
@@ -626,6 +591,33 @@ soup_auth_lookup (SoupContext *ctx)
}
void
+soup_auth_invalidate (SoupAuth *auth, SoupContext *ctx)
+{
+ SoupHost *server;
+ const SoupUri *uri;
+ SoupAuth *old_auth;
+ char *old_path;
+
+ g_return_if_fail (ctx != NULL);
+ g_return_if_fail (auth != NULL);
+
+ server = ctx->server;
+
+ if (!server->valid_auths)
+ return;
+
+ uri = soup_context_get_uri (ctx);
+ if (g_hash_table_lookup_extended (server->valid_auths,
+ uri->path,
+ (gpointer *) &old_path,
+ (gpointer *) &old_auth)) {
+ g_hash_table_remove (server->valid_auths, old_path);
+ g_free (old_path);
+ soup_auth_free (old_auth);
+ }
+}
+
+void
soup_auth_set_context (SoupAuth *auth, SoupContext *ctx)
{
SoupHost *server;
@@ -647,6 +639,9 @@ soup_auth_set_context (SoupAuth *auth, SoupContext *ctx)
uri->path,
(gpointer *) &old_path,
(gpointer *) &old_auth)) {
+ if (auth == old_auth)
+ return;
+
g_hash_table_remove (server->valid_auths, old_path);
g_free (old_path);
soup_auth_free (old_auth);
@@ -673,7 +668,8 @@ static AuthScheme known_auth_schemes [] = {
};
SoupAuth *
-soup_auth_new_from_header_list (const GSList *vals)
+soup_auth_new_from_header_list (const SoupUri *uri,
+ const GSList *vals)
{
gchar *header = NULL;
AuthScheme *scheme = NULL, *iter;
@@ -682,9 +678,14 @@ soup_auth_new_from_header_list (const GSList *vals)
g_return_val_if_fail (vals != NULL, NULL);
while (vals) {
- for (iter = known_auth_schemes; iter->scheme; iter++) {
- gchar *tryheader = vals->data;
+ gchar *tryheader = vals->data;
+ for (iter = known_auth_schemes; iter->scheme; iter++) {
+ if (uri->authmech &&
+ g_strncasecmp (uri->authmech,
+ iter->scheme,
+ strlen (iter->scheme)) != 0)
+ continue;
if (!g_strncasecmp (tryheader,
iter->scheme,
strlen (iter->scheme))) {
@@ -706,8 +707,7 @@ soup_auth_new_from_header_list (const GSList *vals)
auth = scheme->ctor ();
if (!auth) return NULL;
- if (!auth->compare_func ||
- !auth->parse_func ||
+ if (!auth->parse_func ||
!auth->init_func ||
!auth->auth_func ||
!auth->free_func)
@@ -744,18 +744,3 @@ soup_auth_free (SoupAuth *auth)
g_free (auth->realm);
auth->free_func (auth);
}
-
-gboolean
-soup_auth_invalidates_prior (SoupAuth *new_auth, SoupAuth *old_auth)
-{
- g_return_val_if_fail (new_auth != NULL, FALSE);
- g_return_val_if_fail (old_auth != NULL, TRUE);
-
- if (new_auth == old_auth)
- return FALSE;
-
- if (new_auth->type != old_auth->type)
- return TRUE;
-
- return new_auth->compare_func (new_auth, old_auth);
-}
diff --git a/libsoup/soup-auth.h b/libsoup/soup-auth.h
index 75a49459..f1634539 100644
--- a/libsoup/soup-auth.h
+++ b/libsoup/soup-auth.h
@@ -15,13 +15,22 @@
#include <libsoup/soup-message.h>
#include <libsoup/soup-misc.h>
-typedef struct _SoupAuth SoupAuth;
+typedef enum _SoupAuthStatus SoupAuthStatus;
+typedef struct _SoupAuth SoupAuth;
+
+enum _SoupAuthStatus {
+ SOUP_AUTH_STATUS_INVALID = 0,
+ SOUP_AUTH_STATUS_PENDING,
+ SOUP_AUTH_STATUS_FAILED,
+ SOUP_AUTH_STATUS_SUCCESSFUL
+};
+
struct _SoupAuth {
SoupAuthType type;
gchar *realm;
- gboolean (*compare_func) (SoupAuth *a,
- SoupAuth *b);
+ SoupAuthStatus status;
+ SoupMessage *controlling_msg;
void (*parse_func) (SoupAuth *auth,
const gchar *header);
@@ -40,7 +49,11 @@ SoupAuth *soup_auth_lookup (SoupContext *ctx);
void soup_auth_set_context (SoupAuth *auth,
SoupContext *ctx);
-SoupAuth *soup_auth_new_from_header_list (const GSList *header);
+void soup_auth_invalidate (SoupAuth *auth,
+ SoupContext *ctx);
+
+SoupAuth *soup_auth_new_from_header_list (const SoupUri *uri,
+ const GSList *header);
void soup_auth_initialize (SoupAuth *auth,
const SoupUri *uri);
@@ -50,7 +63,4 @@ void soup_auth_free (SoupAuth *auth);
gchar *soup_auth_authorize (SoupAuth *auth,
SoupMessage *msg);
-gboolean soup_auth_invalidates_prior (SoupAuth *new_auth,
- SoupAuth *old_auth);
-
#endif /* SOUP_AUTH_H */
diff --git a/libsoup/soup-context.c b/libsoup/soup-context.c
index 28d2c5f3..bd21d69d 100644
--- a/libsoup/soup-context.c
+++ b/libsoup/soup-context.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-context.c: Asyncronous Callback-based SOAP Request Queue.
+ * soup-context.c: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@helixcode.com)
@@ -12,10 +12,7 @@
#include <config.h>
#endif
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
-
#include <string.h>
#include <stdlib.h>
#include <glib.h>
@@ -23,16 +20,9 @@
#include <fcntl.h>
#include <sys/types.h>
-#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
-#endif
-
-#ifdef HAVE_NETINET_TCP_H
#include <netinet/tcp.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
-#endif
#include "soup-auth.h"
#include "soup-context.h"
@@ -85,17 +75,31 @@ static guint
soup_context_uri_hash (gconstpointer key)
{
const SoupUri *uri = key;
- guint ret = 0;
-
- ret += uri->protocol;
- ret += g_str_hash (uri->path ? uri->path : "");
- ret += g_str_hash (uri->querystring ? uri->querystring : "");
- ret += g_str_hash (uri->user ? uri->user : "");
- ret += g_str_hash (uri->passwd ? uri->passwd : "");
+ guint ret;
+
+ ret = uri->protocol;
+ if (uri->path)
+ ret += g_str_hash (uri->path);
+ if (uri->querystring)
+ ret += g_str_hash (uri->querystring);
+ if (uri->user)
+ ret += g_str_hash (uri->user);
+ if (uri->passwd)
+ ret += g_str_hash (uri->passwd);
return ret;
}
+static inline gboolean
+parts_equal (const char *one, const char *two)
+{
+ if (!one && !two)
+ return TRUE;
+ if (!one || !two)
+ return FALSE;
+ return !strcmp (one, two);
+}
+
/**
* soup_context_uri_equal:
* @v1: a %SoupUri
@@ -110,18 +114,18 @@ soup_context_uri_equal (gconstpointer v1, gconstpointer v2)
const SoupUri *one = v1;
const SoupUri *two = v2;
- if (one->protocol == two->protocol &&
- !strcmp (one->path ? one->path : "",
- two->path ? two->path : "") &&
- !strcmp (one->querystring ? one->querystring : "",
- two->querystring ? two->querystring : "") &&
- !strcmp (one->user ? one->user : "",
- two->user ? two->user : "") &&
- !strcmp (one->passwd ? one->passwd : "",
- two->passwd ? two->passwd : ""))
- return TRUE;
+ if (one->protocol != two->protocol)
+ return FALSE;
+ if (!parts_equal (one->path, two->path))
+ return FALSE;
+ if (!parts_equal (one->user, two->user))
+ return FALSE;
+ if (!parts_equal (one->passwd, two->passwd))
+ return FALSE;
+ if (!parts_equal (one->querystring, two->querystring))
+ return FALSE;
- return FALSE;
+ return TRUE;
}
/**
@@ -545,8 +549,10 @@ soup_context_cancel_connect (SoupConnectId tag)
if (data->timeout_tag)
g_source_remove (data->timeout_tag);
- else if (data->connect_tag)
+ else if (data->connect_tag) {
+ connection_count--;
soup_socket_connect_cancel (data->connect_tag);
+ }
g_free (data);
}
@@ -590,14 +596,12 @@ soup_connection_release (SoupConnection *conn)
static void
soup_connection_setup_socket (GIOChannel *channel)
{
-#if TCP_NODELAY && !SOUP_WIN32
int yes = 1, flags = 0, fd = g_io_channel_unix_get_fd (channel);
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes));
flags = fcntl(fd, F_GETFL, 0);
fcntl (fd, F_SETFL, flags | O_NONBLOCK);
-#endif
}
/**
@@ -628,7 +632,7 @@ soup_connection_get_iochannel (SoupConnection *conn)
}
/**
- * soup_connection_set_keepalive:
+ * soup_connection_set_keep_alive:
* @conn: a %SoupConnection.
* @keep_alive: boolean keep-alive value.
*
@@ -642,7 +646,7 @@ soup_connection_set_keep_alive (SoupConnection *conn, gboolean keep_alive)
}
/**
- * soup_connection_set_keepalive:
+ * soup_connection_is_keep_alive:
* @conn: a %SoupConnection.
*
* Returns the keep-alive flag for the %SoupConnection pointed to by
diff --git a/libsoup/soup-context.h b/libsoup/soup-context.h
index c10fe217..e0b008aa 100644
--- a/libsoup/soup-context.h
+++ b/libsoup/soup-context.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-context.h: Asyncronous Callback-based SOAP Request Queue.
+ * soup-context.h: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@helixcode.com)
diff --git a/libsoup/soup-headers.c b/libsoup/soup-headers.c
index 99cf232f..6924f392 100644
--- a/libsoup/soup-headers.c
+++ b/libsoup/soup-headers.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-headers.c: Asyncronous Callback-based SOAP Request Queue.
+ * soup-headers.c: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@ximian.com)
@@ -121,7 +121,7 @@ soup_headers_parse_request (gchar *str,
guint http_major, http_minor;
gchar method[16], path[1024];
- if (!str || !*str || len < sizeof ("GET / HTTP/0.0\r\n\r\n"))
+ if (!str || !*str || len < sizeof ("GET / HTTP/0.0\r\n\r\n") - 1)
goto THROW_MALFORMED_HEADER;
if (sscanf (str,
diff --git a/libsoup/soup-headers.h b/libsoup/soup-headers.h
index 5f33480c..70aaa7ba 100644
--- a/libsoup/soup-headers.h
+++ b/libsoup/soup-headers.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-headers.h: Asyncronous Callback-based SOAP Request Queue.
+ * soup-headers.h: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@ximian.com)
diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c
index 654ee19c..16e87fce 100644
--- a/libsoup/soup-message.c
+++ b/libsoup/soup-message.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-message.c: Asyncronous Callback-based SOAP Request Queue.
+ * soup-message.c: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@helixcode.com)
@@ -17,18 +17,6 @@
#include "soup-queue.h"
#include "soup-transfer.h"
-typedef struct {
- SoupHandlerEvent type;
- gchar *name;
- SoupHandlerWhen order;
- SoupHandlerFilter filter;
- SoupHandlerFn handler_cb;
- gpointer user_data;
-
- SoupMessage *msg;
- guint timeout_tag;
-} SoupHandlerData;
-
/**
* soup_message_new:
* @context: a %SoupContext for the destination endpoint.
@@ -193,6 +181,11 @@ soup_message_cleanup (SoupMessage *req)
req->connection);
req->priv->read_tag = 0;
req->connection = NULL;
+ /*
+ * The buffer doesn't belong to us until the message is
+ * finished.
+ */
+ req->response.owner = SOUP_BUFFER_STATIC;
}
if (req->priv->read_tag) {
@@ -219,22 +212,6 @@ soup_message_cleanup (SoupMessage *req)
}
static void
-handler_free (SoupHandlerData *data)
-{
- if (data->filter.type == SOUP_FILTER_HEADER)
- g_free ((gchar *) data->filter.data.header);
-
- if (data->timeout_tag)
- g_source_remove (data->timeout_tag);
-
- data->msg->priv->content_handlers =
- g_slist_remove (data->msg->priv->content_handlers, data);
-
- g_free (data->name);
- g_free (data);
-}
-
-static void
finalize_message (SoupMessage *req)
{
if (req->context)
@@ -251,10 +228,8 @@ finalize_message (SoupMessage *req)
soup_message_clear_headers (req->response_headers);
g_hash_table_destroy (req->response_headers);
- while (req->priv->content_handlers) {
- SoupHandlerData *data = req->priv->content_handlers->data;
- handler_free (data);
- }
+ g_slist_foreach (req->priv->content_handlers, (GFunc) g_free, NULL);
+ g_slist_free (req->priv->content_handlers);
g_free ((gchar *) req->errorphrase);
g_free (req->priv);
@@ -322,6 +297,11 @@ void
soup_message_cancel (SoupMessage *msg)
{
soup_message_set_error (msg, SOUP_ERROR_CANCELLED);
+
+ /* Kill the connection as a safety measure */
+ if (msg->connection)
+ soup_connection_set_keep_alive (msg->connection, FALSE);
+
soup_message_issue_callback (msg);
}
@@ -513,6 +493,122 @@ soup_message_foreach_remove_header (GHashTable *hash,
}
/**
+ * soup_message_set_request_header:
+ * @req: a %SoupMessage.
+ * @name: header name.
+ * @value: header value.
+ *
+ * ** DEPRECATED **
+ *
+ * Adds a new transport header to be sent on an outgoing request. Passing a NULL
+ * @value will remove all headers with a name equal to @name.
+ */
+void
+soup_message_set_request_header (SoupMessage *req,
+ const gchar *name,
+ const gchar *value)
+{
+ g_return_if_fail (req != NULL);
+ g_return_if_fail (name != NULL || name [0] != '\0');
+
+ g_warning ("soup_message_set_request_header is DEPRECATED. Use "
+ "soup_message_add_header, with msg->request_headers as "
+ "the first argument.\n");
+
+ soup_message_add_header (req->request_headers, name, value);
+}
+
+/**
+ * soup_message_get_request_header:
+ * @req: a %SoupMessage.
+ * @name: header name.
+ *
+ * ** DEPRECATED **
+ *
+ * Lookup the first transport request header with a key equal to @name.
+ *
+ * Return value: the header's value or NULL if not found.
+ */
+const gchar *
+soup_message_get_request_header (SoupMessage *req,
+ const gchar *name)
+{
+ GSList *vals;
+ g_return_val_if_fail (req != NULL, NULL);
+ g_return_val_if_fail (name != NULL || name [0] != '\0', NULL);
+
+ g_warning ("soup_message_get_request_header is DEPRECATED. Use "
+ "soup_message_get_header, with msg->request_headers as "
+ "the first argument.\n");
+
+ if (req->request_headers) {
+ vals = g_hash_table_lookup (req->request_headers, name);
+ if (vals)
+ return vals->data;
+ }
+
+ return NULL;
+}
+
+/**
+ * soup_message_set_response_header:
+ * @req: a %SoupMessage.
+ * @name: header name.
+ * @value: header value.
+ *
+ * ** DEPRECATED **
+ *
+ * Adds a new transport header to be sent on an outgoing response. Passing a
+ * NULL @value will remove all headers with a name equal to @name.
+ */
+void
+soup_message_set_response_header (SoupMessage *req,
+ const gchar *name,
+ const gchar *value)
+{
+ g_return_if_fail (req != NULL);
+ g_return_if_fail (name != NULL || name [0] != '\0');
+
+ g_warning ("soup_message_set_response_header is DEPRECATED. Use "
+ "soup_message_add_header, with msg->response_headers as "
+ "the first argument.\n");
+
+ soup_message_add_header (req->response_headers, name, value);
+}
+
+/**
+ * soup_message_get_response_header:
+ * @req: a %SoupMessage.
+ * @name: header name.
+ *
+ * ** DEPRECATED **
+ *
+ * Lookup the transport response header with a key equal to @name.
+ *
+ * Return value: the header's value or NULL if not found.
+ */
+const gchar *
+soup_message_get_response_header (SoupMessage *req,
+ const gchar *name)
+{
+ GSList *vals;
+ g_return_val_if_fail (req != NULL, NULL);
+ g_return_val_if_fail (name != NULL || name [0] != '\0', NULL);
+
+ g_warning ("soup_message_get_response_header is DEPRECATED. Use "
+ "soup_message_get_header, with msg->response_headers as "
+ "the first argument.\n");
+
+ if (req->response_headers) {
+ vals = g_hash_table_lookup (req->response_headers, name);
+ if (vals)
+ return vals->data;
+ }
+
+ return NULL;
+}
+
+/**
* soup_message_queue:
* @req: a %SoupMessage.
* @callback: a %SoupCallbackFn which will be called after the message completes
@@ -604,6 +700,7 @@ requeue_read_finished (const SoupDataBuffer *buf,
if (!soup_connection_is_keep_alive (msg->connection))
requeue_read_error (FALSE, data);
else {
+ g_free (data);
msg->connection = NULL;
soup_queue_message (msg,
@@ -677,15 +774,56 @@ soup_message_send (SoupMessage *msg)
return msg->errorclass;
}
-static SoupHandlerResult
-authorize_handler (SoupMessage *msg, gpointer user_data)
+static void
+maybe_validate_auth (SoupMessage *msg, gpointer user_data)
{
gboolean proxy = GPOINTER_TO_INT (user_data);
+ int auth_failure;
+ SoupContext *ctx;
+ SoupAuth *auth;
+
+ if (proxy) {
+ ctx = soup_get_proxy ();
+ auth_failure = SOUP_ERROR_PROXY_UNAUTHORIZED; /* 407 */
+ }
+ else {
+ ctx = msg->context;
+ auth_failure = SOUP_ERROR_UNAUTHORIZED; /* 401 */
+ }
+
+ auth = soup_auth_lookup (ctx);
+ if (!auth)
+ return;
+
+ if (msg->errorcode == auth_failure) {
+ /* Pass through */
+ }
+ else if (msg->errorclass == SOUP_ERROR_CLASS_SERVER_ERROR) {
+ /*
+ * We have no way of knowing whether our auth is any good
+ * anymore, so just invalidate it and start from the
+ * beginning next time.
+ */
+ soup_auth_invalidate (auth, ctx);
+ }
+ else {
+ auth->status = SOUP_AUTH_STATUS_SUCCESSFUL;
+ auth->controlling_msg = NULL;
+ }
+} /* maybe_validate_auth */
+
+static void
+authorize_handler (SoupMessage *msg, gboolean proxy)
+{
const GSList *vals;
- SoupAuth *auth, *old_auth;
+ SoupAuth *auth;
SoupContext *ctx;
const SoupUri *uri;
+ if (msg->connection->auth &&
+ msg->connection->auth->status == SOUP_AUTH_STATUS_SUCCESSFUL)
+ goto THROW_CANT_AUTHENTICATE;
+
ctx = proxy ? soup_get_proxy () : msg->context;
uri = soup_context_get_uri (ctx);
@@ -695,18 +833,59 @@ authorize_handler (SoupMessage *msg, gpointer user_data)
"WWW-Authenticate");
if (!vals) goto THROW_CANT_AUTHENTICATE;
- auth = soup_auth_new_from_header_list (vals);
+ auth = soup_auth_lookup (ctx);
+ if (auth) {
+ g_assert (auth->status != SOUP_AUTH_STATUS_INVALID);
+
+ if (auth->status == SOUP_AUTH_STATUS_PENDING) {
+ if (auth->controlling_msg == msg) {
+ auth->status = SOUP_AUTH_STATUS_FAILED;
+ goto THROW_CANT_AUTHENTICATE;
+ }
+ else {
+ soup_message_requeue (msg);
+ return;
+ }
+ }
+ else if (auth->status == SOUP_AUTH_STATUS_FAILED ||
+ auth->status == SOUP_AUTH_STATUS_SUCCESSFUL) {
+ /*
+ * We've failed previously, but we'll give it
+ * another go, or we've been successful
+ * previously, but it's not working anymore.
+ *
+ * Invalidate the auth, so it's removed from the
+ * hash and try it again as if we never had it
+ * in the first place.
+ */
+ soup_auth_invalidate (auth, ctx);
+ soup_message_requeue (msg);
+ return;
+ }
+ }
+
if (!auth) {
- soup_message_set_error_full (
- msg,
- proxy ?
- SOUP_ERROR_CANT_AUTHENTICATE_PROXY :
- SOUP_ERROR_CANT_AUTHENTICATE,
- proxy ?
- "Unknown authentication scheme required by "
- "proxy" :
- "Unknown authentication scheme required");
- return SOUP_HANDLER_RESTART;
+ auth = soup_auth_new_from_header_list (uri, vals);
+
+ if (!auth) {
+ soup_message_set_error_full (
+ msg,
+ proxy ?
+ SOUP_ERROR_CANT_AUTHENTICATE_PROXY :
+ SOUP_ERROR_CANT_AUTHENTICATE,
+ proxy ?
+ "Unknown authentication scheme "
+ "required by proxy" :
+ "Unknown authentication scheme "
+ "required");
+ return;
+ }
+
+ auth->status = SOUP_AUTH_STATUS_PENDING;
+ auth->controlling_msg = msg;
+ soup_message_add_handler (msg, SOUP_HANDLER_PRE_BODY,
+ maybe_validate_auth,
+ GINT_TO_POINTER (proxy));
}
/*
@@ -724,47 +903,38 @@ authorize_handler (SoupMessage *msg, gpointer user_data)
}
/*
- * Initialize with auth data (possibly returned from auth callback).
+ * Initialize with auth data (possibly returned from
+ * auth callback).
*/
soup_auth_initialize (auth, uri);
- if (auth->type == SOUP_AUTH_TYPE_NTLM)
- old_auth = msg->connection->auth;
- else
- old_auth = soup_auth_lookup (ctx);
-
- if (old_auth) {
- if (!soup_auth_invalidates_prior (auth, old_auth)) {
- soup_auth_free (auth);
- goto THROW_CANT_AUTHENTICATE;
- }
- }
-
if (auth->type == SOUP_AUTH_TYPE_NTLM) {
- if (old_auth)
+ SoupAuth *old_auth = msg->connection->auth;
+
+ if (old_auth)
soup_auth_free (old_auth);
msg->connection->auth = auth;
} else
soup_auth_set_context (auth, ctx);
- return SOUP_HANDLER_RESEND;
+ soup_message_requeue (msg);
+
+ return;
THROW_CANT_AUTHENTICATE:
soup_message_set_error (msg,
proxy ?
SOUP_ERROR_CANT_AUTHENTICATE_PROXY :
SOUP_ERROR_CANT_AUTHENTICATE);
- return SOUP_HANDLER_RESTART;
}
-static SoupHandlerResult
+static void
redirect_handler (SoupMessage *msg, gpointer user_data)
{
const gchar *new_loc;
if (msg->errorclass != SOUP_ERROR_CLASS_REDIRECT ||
- msg->priv->msg_flags & SOUP_MESSAGE_NO_REDIRECT)
- return SOUP_HANDLER_CONTINUE;
+ msg->priv->msg_flags & SOUP_MESSAGE_NO_REDIRECT) return;
new_loc = soup_message_get_header (msg->response_headers, "Location");
@@ -798,141 +968,96 @@ redirect_handler (SoupMessage *msg, gpointer user_data)
soup_message_set_context (msg, new_ctx);
soup_context_unref (new_ctx);
- return SOUP_HANDLER_RESEND;
+ soup_message_requeue (msg);
}
- return SOUP_HANDLER_CONTINUE;
+ return;
INVALID_REDIRECT:
soup_message_set_error_full (msg,
SOUP_ERROR_MALFORMED,
"Invalid Redirect URL");
- return SOUP_HANDLER_RESTART;
}
+typedef enum {
+ RESPONSE_HEADER_HANDLER = 1,
+ RESPONSE_ERROR_CODE_HANDLER,
+ RESPONSE_ERROR_CLASS_HANDLER
+} SoupHandlerKind;
+
+typedef struct {
+ SoupHandlerType type;
+ SoupCallbackFn handler_cb;
+ gpointer user_data;
+
+ SoupHandlerKind kind;
+ union {
+ guint errorcode;
+ SoupErrorClass errorclass;
+ const gchar *header;
+ } data;
+} SoupHandlerData;
+
static SoupHandlerData global_handlers [] = {
/*
* Handle redirect response codes 300, 301, 302, 303, and 305.
*/
{
- SOUP_HANDLER_HEADERS,
- "redirect",
- 0,
- {
- SOUP_FILTER_HEADER,
- {
- (guint) "Location"
- },
- },
+ SOUP_HANDLER_PRE_BODY,
redirect_handler,
NULL,
+ RESPONSE_HEADER_HANDLER,
+ { (guint) "Location" }
},
/*
* Handle authorization.
*/
{
- SOUP_HANDLER_HEADERS,
- "authenticate",
- 0,
- {
- SOUP_FILTER_ERROR_CODE,
- {
- 401
- },
- },
- authorize_handler,
+ SOUP_HANDLER_PRE_BODY,
+ (SoupCallbackFn) authorize_handler,
GINT_TO_POINTER (FALSE),
+ RESPONSE_ERROR_CODE_HANDLER,
+ { 401 }
},
/*
* Handle proxy authorization.
*/
{
- SOUP_HANDLER_HEADERS,
- "proxy-authenticate",
- 0,
- {
- SOUP_FILTER_ERROR_CODE,
- {
- 407
- },
- },
- authorize_handler,
+ SOUP_HANDLER_PRE_BODY,
+ (SoupCallbackFn) authorize_handler,
GINT_TO_POINTER (TRUE),
+ RESPONSE_ERROR_CODE_HANDLER,
+ { 407 }
},
{ 0 }
};
-static inline SoupHandlerResult
-run_handler (SoupMessage *msg,
- SoupHandlerEvent invoke_type,
- SoupHandlerEvent when,
- SoupHandlerData *data)
+static inline void
+run_handler (SoupMessage *msg,
+ SoupHandlerType invoke_type,
+ SoupHandlerData *data)
{
- SoupHandlerResult result;
+ if (data->type != invoke_type) return;
- if (data->type != invoke_type || data->order != when)
- return SOUP_HANDLER_CONTINUE;
-
- switch (data->filter.type) {
- case SOUP_FILTER_HEADER:
+ switch (data->kind) {
+ case RESPONSE_HEADER_HANDLER:
if (!soup_message_get_header (msg->response_headers,
- data->filter.data.header))
- return SOUP_HANDLER_CONTINUE;
- break;
- case SOUP_FILTER_ERROR_CODE:
- if (msg->errorcode != data->filter.data.errorcode)
- return SOUP_HANDLER_CONTINUE;
- break;
- case SOUP_FILTER_ERROR_CLASS:
- if (msg->errorclass != data->filter.data.errorclass)
- return SOUP_HANDLER_CONTINUE;
- break;
- case SOUP_FILTER_TIMEOUT:
- return SOUP_HANDLER_CONTINUE;
- default:
- break;
- }
-
- result = (*data->handler_cb) (msg, data->user_data);
-
- switch (result) {
- case SOUP_HANDLER_STOP:
- if (invoke_type == SOUP_HANDLER_FINISHED &&
- msg->errorclass != SOUP_ERROR_CLASS_INFORMATIONAL)
- soup_message_issue_callback (msg);
+ data->data.header))
+ return;
break;
- case SOUP_HANDLER_KILL:
- soup_message_issue_callback (msg);
+ case RESPONSE_ERROR_CODE_HANDLER:
+ if (msg->errorcode != data->data.errorcode) return;
break;
- case SOUP_HANDLER_RESEND:
- if (msg->status != SOUP_STATUS_QUEUED)
- soup_message_queue (msg,
- msg->priv->callback,
- msg->priv->user_data);
+ case RESPONSE_ERROR_CLASS_HANDLER:
+ if (msg->errorclass != data->data.errorclass) return;
break;
default:
- if (msg->status == SOUP_STATUS_QUEUED)
- result = SOUP_HANDLER_RESEND;
break;
}
- return result;
+ (*data->handler_cb) (msg, data->user_data);
}
-#define PROCESS_HANDLER_RESULT(result) ({ \
- switch (result) { \
- case SOUP_HANDLER_STOP: \
- return FALSE; \
- case SOUP_HANDLER_KILL: \
- case SOUP_HANDLER_RESEND: \
- return TRUE; \
- case SOUP_HANDLER_RESTART: \
- goto RESTART; \
- default: \
- break; \
- } \
-})
-
/*
* Run each handler with matching criteria (first per-message then global
* handlers). If a handler requeues a message, we stop processing and terminate
@@ -945,55 +1070,34 @@ run_handler (SoupMessage *msg,
* processing.
*/
gboolean
-soup_message_run_handlers (SoupMessage *msg, SoupHandlerEvent invoke_type)
+soup_message_run_handlers (SoupMessage *msg, SoupHandlerType invoke_type)
{
GSList *list;
SoupHandlerData *data;
- SoupHandlerResult result;
g_return_val_if_fail (msg != NULL, FALSE);
- RESTART:
- /*
- * Pre-Global handlers
- */
for (list = msg->priv->content_handlers; list; list = list->next) {
data = list->data;
- result = run_handler (msg,
- invoke_type,
- SOUP_HANDLER_FIRST,
- data);
- PROCESS_HANDLER_RESULT (result);
+
+ run_handler (msg, invoke_type, data);
+
+ if (msg->status == SOUP_STATUS_QUEUED ||
+ msg->status == SOUP_STATUS_CONNECTING) return TRUE;
}
- /*
- * Global handlers
- */
for (data = global_handlers; data->type; data++) {
- result = run_handler (msg,
- invoke_type,
- 0,
- data);
- PROCESS_HANDLER_RESULT (result);
- }
+ run_handler (msg, invoke_type, data);
- /*
- * Post-Global handlers
- */
- for (list = msg->priv->content_handlers; list; list = list->next) {
- data = list->data;
- result = run_handler (msg,
- invoke_type,
- SOUP_HANDLER_LAST,
- data);
- PROCESS_HANDLER_RESULT (result);
+ if (msg->status == SOUP_STATUS_QUEUED ||
+ msg->status == SOUP_STATUS_CONNECTING) return TRUE;
}
/*
- * Issue final callback if the invoke_type is FINISHED and the error
+ * Issue final callback if the invoke_type is POST_BODY and the error
* class is not INFORMATIONAL.
*/
- if (invoke_type == SOUP_HANDLER_FINISHED &&
+ if (invoke_type == SOUP_HANDLER_POST_BODY &&
msg->errorclass != SOUP_ERROR_CLASS_INFORMATIONAL) {
soup_message_issue_callback (msg);
return TRUE;
@@ -1002,201 +1106,146 @@ soup_message_run_handlers (SoupMessage *msg, SoupHandlerEvent invoke_type)
return FALSE;
}
-static gboolean
-timeout_handler (gpointer user_data)
+static void
+add_handler (SoupMessage *msg,
+ SoupHandlerType type,
+ SoupCallbackFn handler_cb,
+ gpointer user_data,
+ SoupHandlerKind kind,
+ const gchar *header,
+ guint errorcode,
+ guint errorclass)
{
- SoupHandlerData *data = user_data;
- SoupMessage *msg = data->msg;
- SoupHandlerResult result;
-
- switch (data->type) {
- case SOUP_HANDLER_PREPARE:
- if (msg->status >= SOUP_STATUS_SENDING_REQUEST)
- goto REMOVE_SOURCE;
- case SOUP_HANDLER_HEADERS:
- case SOUP_HANDLER_DATA:
- if (msg->status >= SOUP_STATUS_READING_RESPONSE &&
- g_hash_table_size (msg->response_headers) > 0)
- goto REMOVE_SOURCE;
- case SOUP_HANDLER_FINISHED:
- if (msg->status == SOUP_STATUS_FINISHED)
- goto REMOVE_SOURCE;
- }
+ SoupHandlerData *data;
- result = (*data->handler_cb) (msg, data->user_data);
+ data = g_new0 (SoupHandlerData, 1);
+ data->type = type;
+ data->handler_cb = handler_cb;
+ data->user_data = user_data;
+ data->kind = kind;
- switch (result) {
- case SOUP_HANDLER_KILL:
- soup_message_cancel (msg);
+ switch (kind) {
+ case RESPONSE_HEADER_HANDLER:
+ data->data.header = header;
break;
- case SOUP_HANDLER_RESEND:
- soup_message_queue (msg,
- msg->priv->callback,
- msg->priv->user_data);
+ case RESPONSE_ERROR_CODE_HANDLER:
+ data->data.errorcode = errorcode;
+ break;
+ case RESPONSE_ERROR_CLASS_HANDLER:
+ data->data.errorclass = errorclass;
break;
default:
break;
}
- REMOVE_SOURCE:
- data->timeout_tag = 0;
- return FALSE;
+ msg->priv->content_handlers =
+ g_slist_append (msg->priv->content_handlers, data);
}
void
-soup_message_add_handler_full (SoupMessage *msg,
- const gchar *name,
- SoupHandlerEvent type,
- SoupHandlerWhen order,
- SoupHandlerFilter *filter,
- SoupHandlerFn handler_cb,
- gpointer user_data)
+soup_message_add_header_handler (SoupMessage *msg,
+ const gchar *header,
+ SoupHandlerType type,
+ SoupCallbackFn handler_cb,
+ gpointer user_data)
{
- SoupHandlerData *data;
-
g_return_if_fail (msg != NULL);
- g_return_if_fail (type != 0);
- g_return_if_fail (order != 0);
+ g_return_if_fail (header != NULL);
g_return_if_fail (handler_cb != NULL);
- data = g_new0 (SoupHandlerData, 1);
- data->type = type;
- data->handler_cb = handler_cb;
- data->user_data = user_data;
- data->name = g_strdup (name);
- data->order = order;
- data->msg = msg;
-
- if (filter) {
- data->filter.type = filter->type;
-
- switch (filter->type) {
- case SOUP_FILTER_HEADER:
- data->filter.data.header =
- g_strdup (filter->data.header);
- break;
- case SOUP_FILTER_ERROR_CODE:
- data->filter.data.errorcode = filter->data.errorcode;
- break;
- case SOUP_FILTER_ERROR_CLASS:
- data->filter.data.errorclass = filter->data.errorclass;
- break;
- case SOUP_FILTER_TIMEOUT:
- data->filter.data.timeout = filter->data.timeout;
- data->timeout_tag =
- g_timeout_add (filter->data.timeout * 1000,
- timeout_handler,
- data);
- break;
- default:
- break;
- }
- }
-
- msg->priv->content_handlers =
- g_slist_append (msg->priv->content_handlers, data);
+ add_handler (msg,
+ type,
+ handler_cb,
+ user_data,
+ RESPONSE_HEADER_HANDLER,
+ header,
+ 0,
+ 0);
}
void
-soup_message_add_handler (SoupMessage *msg,
- SoupHandlerEvent type,
- SoupHandlerFilter *filter,
- SoupHandlerFn handler_cb,
- gpointer user_data)
+soup_message_add_error_code_handler (SoupMessage *msg,
+ guint errorcode,
+ SoupHandlerType type,
+ SoupCallbackFn handler_cb,
+ gpointer user_data)
{
g_return_if_fail (msg != NULL);
- g_return_if_fail (type != 0);
+ g_return_if_fail (errorcode != 0);
g_return_if_fail (handler_cb != NULL);
- soup_message_add_handler_full (msg,
- NULL,
- type,
- SOUP_HANDLER_LAST,
- filter,
- handler_cb,
- user_data);
-}
-
-GSList *
-soup_message_list_handlers (SoupMessage *msg)
-{
- GSList *ret = NULL, *list;
-
- g_return_val_if_fail (msg != NULL, NULL);
-
- for (list = msg->priv->content_handlers; list; list = list->next) {
- SoupHandlerData *data = list->data;
- if (data->name)
- ret = g_slist_append (ret, data->name);
- }
-
- return ret;
+ add_handler (msg,
+ type,
+ handler_cb,
+ user_data,
+ RESPONSE_ERROR_CODE_HANDLER,
+ NULL,
+ errorcode,
+ 0);
}
void
-soup_message_remove_handler (SoupMessage *msg,
- gchar *name)
+soup_message_add_error_class_handler (SoupMessage *msg,
+ SoupErrorClass errorclass,
+ SoupHandlerType type,
+ SoupCallbackFn handler_cb,
+ gpointer user_data)
{
- GSList *iter;
-
g_return_if_fail (msg != NULL);
- g_return_if_fail (name != NULL);
-
- iter = msg->priv->content_handlers;
- while (iter) {
- SoupHandlerData *data = iter->data;
-
- if (data->name && !g_strcasecmp (data->name, name)) {
- handler_free (data);
- break;
- }
+ g_return_if_fail (errorclass != 0);
+ g_return_if_fail (handler_cb != NULL);
- iter = iter->next;
- }
+ add_handler (msg,
+ type,
+ handler_cb,
+ user_data,
+ RESPONSE_ERROR_CLASS_HANDLER,
+ NULL,
+ 0,
+ errorclass);
}
void
-soup_message_remove_handler_by_func (SoupMessage *msg,
- SoupHandlerFn handler_cb)
+soup_message_add_handler (SoupMessage *msg,
+ SoupHandlerType type,
+ SoupCallbackFn handler_cb,
+ gpointer user_data)
{
- GSList *iter;
-
g_return_if_fail (msg != NULL);
g_return_if_fail (handler_cb != NULL);
- iter = msg->priv->content_handlers;
- while (iter) {
- SoupHandlerData *data = iter->data;
-
- if (data->handler_cb == handler_cb) {
- handler_free (data);
- break;
- }
-
- iter = iter->next;
- }
+ add_handler (msg,
+ type,
+ handler_cb,
+ user_data,
+ 0,
+ NULL,
+ 0,
+ 0);
}
-void
-soup_message_remove_handler_by_func_and_data (SoupMessage *msg,
- SoupHandlerFn handler_cb,
- gpointer user_data)
+void
+soup_message_remove_handler (SoupMessage *msg,
+ SoupHandlerType type,
+ SoupCallbackFn handler_cb,
+ gpointer user_data)
{
- GSList *iter;
-
- g_return_if_fail (msg != NULL);
- g_return_if_fail (handler_cb != NULL);
+ GSList *iter = msg->priv->content_handlers;
- iter = msg->priv->content_handlers;
while (iter) {
SoupHandlerData *data = iter->data;
- if (data->handler_cb == handler_cb &&
- data->user_data == user_data) {
- handler_free (data);
+ if (data->handler_cb == handler_cb &&
+ data->user_data == user_data &&
+ data->type == type) {
+ msg->priv->content_handlers =
+ g_slist_remove_link (
+ msg->priv->content_handlers,
+ iter);
+ g_free (data);
break;
}
-
+
iter = iter->next;
}
}
diff --git a/libsoup/soup-message.h b/libsoup/soup-message.h
index 631da19d..c46c6e94 100644
--- a/libsoup/soup-message.h
+++ b/libsoup/soup-message.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-message.h: Asyncronous Callback-based SOAP Request Queue.
+ * soup-message.h: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@ximian.com)
@@ -173,103 +173,39 @@ guint soup_message_get_flags (SoupMessage *msg);
* Handler Registration
*/
typedef enum {
- SOUP_HANDLER_PREPARE = 0,
- SOUP_HANDLER_HEADERS,
- SOUP_HANDLER_DATA,
- SOUP_HANDLER_FINISHED,
-} SoupHandlerEvent;
-
-typedef enum {
- SOUP_FILTER_HEADER = (1 << 0),
- SOUP_FILTER_ERROR_CODE = (1 << 1),
- SOUP_FILTER_ERROR_CLASS = (1 << 2),
- SOUP_FILTER_TIMEOUT = (1 << 3),
-} SoupHandlerFilterType;
-
-typedef struct {
- gint type;
-
- union {
- guint errorcode;
- SoupErrorClass errorclass;
- const gchar *header;
- guint timeout;
- } data;
-} SoupHandlerFilter;
-
-typedef enum {
- /*
- * Continue processing as normal.
- */
- SOUP_HANDLER_CONTINUE,
-
- /*
- * Do not process further handlers. Continue receiving data.
- */
- SOUP_HANDLER_STOP,
-
- /*
- * do not process further handlers. Stop receiving data and
- * issue final callback.
- */
- SOUP_HANDLER_KILL,
-
- /*
- * Restart handler processing. This should be returned if a
- * handler changes the message's errorcode.
- */
- SOUP_HANDLER_RESTART,
-
- /*
- * Requeue the request immediately. Stop processing handlers
- * and do not issue final callback.
- */
- SOUP_HANDLER_RESEND
-} SoupHandlerResult;
-
-typedef SoupHandlerResult (*SoupHandlerFn) (SoupMessage *req,
- gpointer user_data);
+ SOUP_HANDLER_PRE_BODY = 1,
+ SOUP_HANDLER_BODY_CHUNK,
+ SOUP_HANDLER_POST_BODY
+} SoupHandlerType;
void soup_message_add_handler (SoupMessage *msg,
- SoupHandlerEvent type,
- SoupHandlerFilter *filter,
- SoupHandlerFn handler_cb,
+ SoupHandlerType type,
+ SoupCallbackFn handler_cb,
gpointer user_data);
-typedef enum {
- /*
- * Run before global handlers and previously registered message
- * handlers.
- */
- SOUP_HANDLER_FIRST,
-
- /*
- * Run after global handlers and previously registered message
- * handlers.
- */
- SOUP_HANDLER_LAST
-} SoupHandlerWhen;
+void soup_message_add_header_handler (SoupMessage *msg,
+ const gchar *header,
+ SoupHandlerType type,
+ SoupCallbackFn handler_cb,
+ gpointer user_data);
-void soup_message_add_handler_full (SoupMessage *msg,
- const gchar *name,
- SoupHandlerEvent type,
- SoupHandlerWhen order,
- SoupHandlerFilter *filter,
- SoupHandlerFn handler_cb,
+void soup_message_add_error_code_handler (
+ SoupMessage *msg,
+ guint errorcode,
+ SoupHandlerType type,
+ SoupCallbackFn handler_cb,
gpointer user_data);
-GSList *soup_message_list_handlers (SoupMessage *msg);
+void soup_message_add_error_class_handler (
+ SoupMessage *msg,
+ SoupErrorClass errorclass,
+ SoupHandlerType type,
+ SoupCallbackFn handler_cb,
+ gpointer user_data);
void soup_message_remove_handler (SoupMessage *msg,
- gchar *name);
-
-void soup_message_remove_handler_by_func (
- SoupMessage *msg,
- SoupHandlerFn handler_cb);
-
-void soup_message_remove_handler_by_func_and_data (
- SoupMessage *msg,
- SoupHandlerFn handler_cb,
+ SoupHandlerType type,
+ SoupCallbackFn handler_cb,
gpointer user_data);
/*
@@ -286,4 +222,24 @@ void soup_message_set_handler_error (SoupMessage *msg,
guint errcode,
const gchar *errphrase);
+/** DEPRECATED API **/
+
+/** DEPRECATED **/
+void soup_message_set_request_header (SoupMessage *req,
+ const gchar *name,
+ const gchar *value);
+
+/** DEPRECATED **/
+const gchar *soup_message_get_request_header (SoupMessage *req,
+ const gchar *name);
+
+/** DEPRECATED **/
+void soup_message_set_response_header (SoupMessage *req,
+ const gchar *name,
+ const gchar *value);
+
+/** DEPRECATED **/
+const gchar *soup_message_get_response_header (SoupMessage *req,
+ const gchar *name);
+
#endif /*SOUP_MESSAGE_H*/
diff --git a/libsoup/soup-misc.c b/libsoup/soup-misc.c
index 1310fe5c..aa7765c4 100644
--- a/libsoup/soup-misc.c
+++ b/libsoup/soup-misc.c
@@ -687,6 +687,11 @@ soup_shutdown ()
soup_queue_shutdown ();
}
+static char *ssl_ca_file = NULL;
+static char *ssl_ca_dir = NULL;
+static char *ssl_cert_file = NULL;
+static char *ssl_key_file = NULL;
+
/**
* soup_set_ca_file:
* @ca_file: the path to a CA file
@@ -695,9 +700,11 @@ soup_shutdown ()
* peers.
*/
void
-soup_set_ssl_ca_file (gchar *ca_file)
+soup_set_ssl_ca_file (const gchar *ca_file)
{
- putenv (g_strdup_printf ("HTTPS_CA_FILE=%s", ca_file));
+ g_free (ssl_ca_file);
+
+ ssl_ca_file = g_strdup (ca_file);
}
/**
@@ -708,9 +715,11 @@ soup_set_ssl_ca_file (gchar *ca_file)
* peers.
*/
void
-soup_set_ssl_ca_dir (gchar *ca_dir)
+soup_set_ssl_ca_dir (const gchar *ca_dir)
{
- putenv (g_strdup_printf ("HTTPS_CA_DIR=%s", ca_dir));
+ g_free (ssl_ca_dir);
+
+ ssl_ca_dir = g_strdup (ca_dir);
}
/**
@@ -719,13 +728,58 @@ soup_set_ssl_ca_dir (gchar *ca_dir)
* @key_file: the file containing the SSL private key
*
* Specify a SSL client certificate to be used for client
- * authentication with the SOAP server
+ * authentication with the HTTP server
*/
void
-soup_set_ssl_cert_files (gchar *cert_file, gchar *key_file)
+soup_set_ssl_cert_files (const gchar *cert_file, const gchar *key_file)
{
- putenv (g_strdup_printf ("HTTPS_CERT_FILE=%s", cert_file));
- putenv (g_strdup_printf ("HTTPS_KEY_FILE=%s", key_file));
+ g_free (ssl_cert_file);
+ g_free (ssl_key_file);
+
+ ssl_cert_file = g_strdup (cert_file);
+ ssl_key_file = g_strdup (key_file);
+}
+
+/**
+ * soup_get_ca_file:
+ *
+ * Return value: A file containing CA certificates to be used to verify
+ * peers.
+ */
+const char *
+soup_get_ssl_ca_file (void)
+{
+ return ssl_ca_file;
+}
+
+/**
+ * soup_get_ca_dir
+ *
+ * Return value: A directory containing CA certificates to be used to verify
+ * peers.
+ */
+const char *
+soup_get_ssl_ca_dir (void)
+{
+ return ssl_ca_dir;
+}
+
+/**
+ * soup_get_ssl_cert_files
+ * @cert_file: the file containing the SSL client certificate
+ * @key_file: the file containing the SSL private key
+ *
+ * Specify a SSL client certificate to be used for client
+ * authentication with the HTTP server
+ */
+void
+soup_get_ssl_cert_files (const gchar **cert_file, const gchar **key_file)
+{
+ if (cert_file)
+ *cert_file = ssl_cert_file;
+
+ if (key_file)
+ *key_file = ssl_key_file;
}
SoupAuthorizeFn soup_auth_fn = NULL;
diff --git a/libsoup/soup-misc.h b/libsoup/soup-misc.h
index be80993b..ba3aa8c5 100644
--- a/libsoup/soup-misc.h
+++ b/libsoup/soup-misc.h
@@ -42,12 +42,17 @@ SoupSecurityPolicy soup_get_security_policy (void);
/* SSL setup routines */
-void soup_set_ssl_ca_file (gchar *ca_file);
+void soup_set_ssl_ca_file (const gchar *ca_file);
-void soup_set_ssl_ca_dir (gchar *ca_dir);
+void soup_set_ssl_ca_dir (const gchar *ca_dir);
-void soup_set_ssl_cert_files (gchar *cert_file,
- gchar *key_file);
+void soup_set_ssl_cert_files (const gchar *cert_file,
+ const gchar *key_file);
+
+const char *soup_get_ssl_ca_file (void);
+const char *soup_get_ssl_ca_dir (void);
+void soup_get_ssl_cert_files (const gchar **cert_file,
+ const gchar **key_file);
/* Authentication callback */
diff --git a/libsoup/soup-nss.c b/libsoup/soup-nss.c
index edadbd93..a9517528 100644
--- a/libsoup/soup-nss.c
+++ b/libsoup/soup-nss.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-nss.c: Asyncronous Callback-based SOAP Request Queue.
+ * soup-nss.c: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@ximian.com)
@@ -295,7 +295,7 @@ soup_nss_bad_cert (void *data, PRFileDesc *fd)
}
GIOChannel *
-soup_nss_get_iochannel (GIOChannel *sock)
+soup_nss_get_iochannel (GIOChannel *sock, SoupSSLType type)
{
SoupNSSChannel *chan;
GIOChannel *gchan;
@@ -322,7 +322,10 @@ soup_nss_get_iochannel (GIOChannel *sock)
}
SSL_OptionSet (fdesc, SSL_SECURITY, PR_TRUE);
- SSL_OptionSet (fdesc, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
+ if (type == SOUP_SSL_TYPE_CLIENT)
+ SSL_OptionSet (fdesc, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
+ else
+ SSL_OptionSet (fdesc, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
SSL_BadCertHook (fdesc, soup_nss_bad_cert, NULL);
if (SSL_ResetHandshake (fdesc, PR_FALSE) == PR_FAILURE) {
diff --git a/libsoup/soup-nss.h b/libsoup/soup-nss.h
index 1aaa0a45..99ac3fe6 100644
--- a/libsoup/soup-nss.h
+++ b/libsoup/soup-nss.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-nss.h: Asyncronous Callback-based SOAP Request Queue.
+ * soup-nss.h: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@ximian.com)
@@ -13,8 +13,9 @@
#include <glib.h>
#include <libsoup/soup-misc.h>
+#include <libsoup/soup-ssl.h>
-GIOChannel *soup_nss_get_iochannel (GIOChannel *sock);
+GIOChannel *soup_nss_get_iochannel (GIOChannel *sock, SoupSSLType type);
void soup_nss_set_security_policy (SoupSecurityPolicy policy);
diff --git a/libsoup/soup-ntlm.c b/libsoup/soup-ntlm.c
index 64f809fe..734c7eec 100644
--- a/libsoup/soup-ntlm.c
+++ b/libsoup/soup-ntlm.c
@@ -44,7 +44,7 @@ static void calc_response (const guchar *key,
"\x00\x00\x00\x00\x00"
void
-soup_ntlm_lanmanager_hash (const char *password, char hash[21])
+soup_ntlm_lanmanager_hash (const char *password, guchar hash[21])
{
guchar lm_password [15];
DES_KS ks;
@@ -66,7 +66,7 @@ soup_ntlm_lanmanager_hash (const char *password, char hash[21])
}
void
-soup_ntlm_nt_hash (const char *password, char hash[21])
+soup_ntlm_nt_hash (const char *password, guchar hash[21])
{
unsigned char *buf, *p;
@@ -90,13 +90,12 @@ typedef struct {
guchar zero_pad[2];
} NTLMString;
-#define NTLM_CHALLENGE_NONCE_OFFSET 24
-#define NTLM_CHALLENGE_NONCE_LENGTH 8
-#define NTLM_CHALLENGE_DOMAIN_OFFSET 48
-#define NTLM_CHALLENGE_DOMAIN_LEN_OFFSET 44
+#define NTLM_CHALLENGE_NONCE_OFFSET 24
+#define NTLM_CHALLENGE_NONCE_LENGTH 8
+#define NTLM_CHALLENGE_DOMAIN_STRING_OFFSET 12
#define NTLM_RESPONSE_HEADER "NTLMSSP\x00\x03\x00\x00\x00"
-#define NTLM_RESPONSE_FLAGS "\x82\x01"
+#define NTLM_RESPONSE_FLAGS 0x8202
typedef struct {
guchar header[12];
@@ -106,25 +105,16 @@ typedef struct {
NTLMString domain;
NTLMString user;
NTLMString host;
+ NTLMString session_key;
- guint16 msg_len;
- guchar zero_pad[2];
-
- guchar flags[2];
- guchar zero_pad2[2];
+ guint32 flags;
} NTLMResponse;
-#if G_BYTE_ORDER == G_BIG_ENDIAN
-#define LE16(x) (((x & 0xFF) << 8) | ((x >> 8) & 0xFF))
-#else
-#define LE16(x) x
-#endif
-
static void
ntlm_set_string (NTLMString *string, int *offset, int len)
{
- string->offset = LE16 (*offset);
- string->length = string->length2 = LE16 (len);
+ string->offset = GUINT16_TO_LE (*offset);
+ string->length = string->length2 = GUINT16_TO_LE (len);
*offset += len;
}
@@ -134,53 +124,82 @@ soup_ntlm_request (void)
return g_strdup ("NTLM TlRMTVNTUAABAAAABoIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAA");
}
-char *
-soup_ntlm_response (const char *challenge,
- const char *user,
- const char *lm_hash,
- const char *nt_hash,
- const char *host,
- const char *domain)
+gboolean
+soup_ntlm_parse_challenge (const char *challenge,
+ char **nonce,
+ char **default_domain)
{
- int hlen, dlen, ulen, offset, decodelen;
- guchar lm_resp[24], nt_resp[24], *nonce;
- NTLMResponse resp;
+ int clen, decodelen;
+ NTLMString domain;
char *chall;
- unsigned char *out, *p;
int state, save;
if (strncmp (challenge, "NTLM ", 5) != 0)
- return NULL;
+ return FALSE;
decodelen = strlen (challenge) - 5;
chall = g_malloc (decodelen);
state = save = 0;
- soup_base64_decode_step ((guchar *) challenge + 5,
- decodelen,
- chall,
- &state,
- &save);
+ clen = soup_base64_decode_step ((guchar *) challenge + 5,
+ decodelen,
+ chall,
+ &state,
+ &save);
+
+ if (clen < NTLM_CHALLENGE_DOMAIN_STRING_OFFSET ||
+ clen < NTLM_CHALLENGE_NONCE_OFFSET + NTLM_CHALLENGE_NONCE_LENGTH) {
+ g_free (chall);
+ return FALSE;
+ }
+
+ if (default_domain) {
+ memcpy (&domain, chall + NTLM_CHALLENGE_DOMAIN_STRING_OFFSET, sizeof (domain));
+ domain.length = GUINT16_FROM_LE (domain.length);
+ domain.offset = GUINT16_FROM_LE (domain.offset);
+
+ if (clen < domain.length + domain.offset) {
+ g_free (chall);
+ return FALSE;
+ }
+
+ *default_domain = g_strndup (chall + domain.offset, domain.length);
+ }
+
+ if (nonce) {
+ *nonce = g_memdup (chall + NTLM_CHALLENGE_NONCE_OFFSET,
+ NTLM_CHALLENGE_NONCE_LENGTH);
+ }
- nonce = chall + NTLM_CHALLENGE_NONCE_OFFSET;
- nonce [NTLM_CHALLENGE_NONCE_LENGTH] = '\0';
+ g_free (chall);
+ return TRUE;
+}
- calc_response (lm_hash, nonce, lm_resp);
- calc_response (nt_hash, nonce, nt_resp);
+char *
+soup_ntlm_response (const char *nonce,
+ const char *user,
+ const char *password,
+ const char *host,
+ const char *domain)
+{
+ int hlen, dlen, ulen, offset;
+ guchar hash[21], lm_resp[24], nt_resp[24];
+ NTLMResponse resp;
+ unsigned char *out, *p;
+ int state, save;
+
+ soup_ntlm_lanmanager_hash (password, hash);
+ calc_response (hash, nonce, lm_resp);
+ soup_ntlm_nt_hash (password, hash);
+ calc_response (hash, nonce, nt_resp);
memset (&resp, 0, sizeof (resp));
memcpy (resp.header, NTLM_RESPONSE_HEADER, sizeof (resp.header));
- memcpy (resp.flags, NTLM_RESPONSE_FLAGS, sizeof (resp.flags));
+ resp.flags = GUINT32_TO_LE (NTLM_RESPONSE_FLAGS);
offset = sizeof (resp);
- if (domain)
- dlen = strlen (domain);
- else {
- /* Grab the default domain from the challenge */
- domain = chall + NTLM_CHALLENGE_DOMAIN_OFFSET;
- dlen = atoi (chall + NTLM_CHALLENGE_DOMAIN_LEN_OFFSET);
- }
+ dlen = strlen (domain);
ntlm_set_string (&resp.domain, &offset, dlen);
ulen = strlen (user);
ntlm_set_string (&resp.user, &offset, ulen);
@@ -235,14 +254,10 @@ soup_ntlm_response (const char *challenge,
&state,
&save);
*p = '\0';
- g_free (chall);
return out;
}
-#define KEYBITS(k,s) \
- (((k[(s)/8] << ((s)%8)) & 0xFF) | (k[(s)/8+1] >> (8-(s)%8)))
-
/* DES utils */
/* Set up a key schedule based on a 56bit key */
static void
@@ -251,15 +266,22 @@ setup_schedule (const guchar *key_56, DES_KS ks)
guchar key[8];
int i, c, bit;
- for (i = 0; i < 8; i++) {
- key [i] = KEYBITS (key_56, i * 7);
+ key[0] = (key_56[0]) ;
+ key[1] = (key_56[1] >> 1) | ((key_56[0] << 7) & 0xFF);
+ key[2] = (key_56[2] >> 2) | ((key_56[1] << 6) & 0xFF);
+ key[3] = (key_56[3] >> 3) | ((key_56[2] << 5) & 0xFF);
+ key[4] = (key_56[4] >> 4) | ((key_56[3] << 4) & 0xFF);
+ key[5] = (key_56[5] >> 5) | ((key_56[4] << 3) & 0xFF);
+ key[6] = (key_56[6] >> 6) | ((key_56[5] << 2) & 0xFF);
+ key[7] = ((key_56[6] << 1) & 0xFF);
- /* Fix parity */
+ /* Fix parity */
+ for (i = 0; i < 8; i++) {
for (c = bit = 0; bit < 8; bit++)
- if (key [i] & (1 << bit))
+ if (key[i] & (1 << bit))
c++;
if (!(c & 1))
- key [i] ^= 0x01;
+ key[i] ^= 0x01;
}
deskey (ks, key, 0);
@@ -410,134 +432,134 @@ md4sum (const unsigned char *in, int nbytes, unsigned char digest[16])
/* Public domain DES implementation from Phil Karn */
static unsigned long Spbox[8][64] = {
- 0x01010400,0x00000000,0x00010000,0x01010404,
- 0x01010004,0x00010404,0x00000004,0x00010000,
- 0x00000400,0x01010400,0x01010404,0x00000400,
- 0x01000404,0x01010004,0x01000000,0x00000004,
- 0x00000404,0x01000400,0x01000400,0x00010400,
- 0x00010400,0x01010000,0x01010000,0x01000404,
- 0x00010004,0x01000004,0x01000004,0x00010004,
- 0x00000000,0x00000404,0x00010404,0x01000000,
- 0x00010000,0x01010404,0x00000004,0x01010000,
- 0x01010400,0x01000000,0x01000000,0x00000400,
- 0x01010004,0x00010000,0x00010400,0x01000004,
- 0x00000400,0x00000004,0x01000404,0x00010404,
- 0x01010404,0x00010004,0x01010000,0x01000404,
- 0x01000004,0x00000404,0x00010404,0x01010400,
- 0x00000404,0x01000400,0x01000400,0x00000000,
- 0x00010004,0x00010400,0x00000000,0x01010004,
- 0x80108020,0x80008000,0x00008000,0x00108020,
- 0x00100000,0x00000020,0x80100020,0x80008020,
- 0x80000020,0x80108020,0x80108000,0x80000000,
- 0x80008000,0x00100000,0x00000020,0x80100020,
- 0x00108000,0x00100020,0x80008020,0x00000000,
- 0x80000000,0x00008000,0x00108020,0x80100000,
- 0x00100020,0x80000020,0x00000000,0x00108000,
- 0x00008020,0x80108000,0x80100000,0x00008020,
- 0x00000000,0x00108020,0x80100020,0x00100000,
- 0x80008020,0x80100000,0x80108000,0x00008000,
- 0x80100000,0x80008000,0x00000020,0x80108020,
- 0x00108020,0x00000020,0x00008000,0x80000000,
- 0x00008020,0x80108000,0x00100000,0x80000020,
- 0x00100020,0x80008020,0x80000020,0x00100020,
- 0x00108000,0x00000000,0x80008000,0x00008020,
- 0x80000000,0x80100020,0x80108020,0x00108000,
- 0x00000208,0x08020200,0x00000000,0x08020008,
- 0x08000200,0x00000000,0x00020208,0x08000200,
- 0x00020008,0x08000008,0x08000008,0x00020000,
- 0x08020208,0x00020008,0x08020000,0x00000208,
- 0x08000000,0x00000008,0x08020200,0x00000200,
- 0x00020200,0x08020000,0x08020008,0x00020208,
- 0x08000208,0x00020200,0x00020000,0x08000208,
- 0x00000008,0x08020208,0x00000200,0x08000000,
- 0x08020200,0x08000000,0x00020008,0x00000208,
- 0x00020000,0x08020200,0x08000200,0x00000000,
- 0x00000200,0x00020008,0x08020208,0x08000200,
- 0x08000008,0x00000200,0x00000000,0x08020008,
- 0x08000208,0x00020000,0x08000000,0x08020208,
- 0x00000008,0x00020208,0x00020200,0x08000008,
- 0x08020000,0x08000208,0x00000208,0x08020000,
- 0x00020208,0x00000008,0x08020008,0x00020200,
- 0x00802001,0x00002081,0x00002081,0x00000080,
- 0x00802080,0x00800081,0x00800001,0x00002001,
- 0x00000000,0x00802000,0x00802000,0x00802081,
- 0x00000081,0x00000000,0x00800080,0x00800001,
- 0x00000001,0x00002000,0x00800000,0x00802001,
- 0x00000080,0x00800000,0x00002001,0x00002080,
- 0x00800081,0x00000001,0x00002080,0x00800080,
- 0x00002000,0x00802080,0x00802081,0x00000081,
- 0x00800080,0x00800001,0x00802000,0x00802081,
- 0x00000081,0x00000000,0x00000000,0x00802000,
- 0x00002080,0x00800080,0x00800081,0x00000001,
- 0x00802001,0x00002081,0x00002081,0x00000080,
- 0x00802081,0x00000081,0x00000001,0x00002000,
- 0x00800001,0x00002001,0x00802080,0x00800081,
- 0x00002001,0x00002080,0x00800000,0x00802001,
- 0x00000080,0x00800000,0x00002000,0x00802080,
- 0x00000100,0x02080100,0x02080000,0x42000100,
- 0x00080000,0x00000100,0x40000000,0x02080000,
- 0x40080100,0x00080000,0x02000100,0x40080100,
- 0x42000100,0x42080000,0x00080100,0x40000000,
- 0x02000000,0x40080000,0x40080000,0x00000000,
- 0x40000100,0x42080100,0x42080100,0x02000100,
- 0x42080000,0x40000100,0x00000000,0x42000000,
- 0x02080100,0x02000000,0x42000000,0x00080100,
- 0x00080000,0x42000100,0x00000100,0x02000000,
- 0x40000000,0x02080000,0x42000100,0x40080100,
- 0x02000100,0x40000000,0x42080000,0x02080100,
- 0x40080100,0x00000100,0x02000000,0x42080000,
- 0x42080100,0x00080100,0x42000000,0x42080100,
- 0x02080000,0x00000000,0x40080000,0x42000000,
- 0x00080100,0x02000100,0x40000100,0x00080000,
- 0x00000000,0x40080000,0x02080100,0x40000100,
- 0x20000010,0x20400000,0x00004000,0x20404010,
- 0x20400000,0x00000010,0x20404010,0x00400000,
- 0x20004000,0x00404010,0x00400000,0x20000010,
- 0x00400010,0x20004000,0x20000000,0x00004010,
- 0x00000000,0x00400010,0x20004010,0x00004000,
- 0x00404000,0x20004010,0x00000010,0x20400010,
- 0x20400010,0x00000000,0x00404010,0x20404000,
- 0x00004010,0x00404000,0x20404000,0x20000000,
- 0x20004000,0x00000010,0x20400010,0x00404000,
- 0x20404010,0x00400000,0x00004010,0x20000010,
- 0x00400000,0x20004000,0x20000000,0x00004010,
- 0x20000010,0x20404010,0x00404000,0x20400000,
- 0x00404010,0x20404000,0x00000000,0x20400010,
- 0x00000010,0x00004000,0x20400000,0x00404010,
- 0x00004000,0x00400010,0x20004010,0x00000000,
- 0x20404000,0x20000000,0x00400010,0x20004010,
- 0x00200000,0x04200002,0x04000802,0x00000000,
- 0x00000800,0x04000802,0x00200802,0x04200800,
- 0x04200802,0x00200000,0x00000000,0x04000002,
- 0x00000002,0x04000000,0x04200002,0x00000802,
- 0x04000800,0x00200802,0x00200002,0x04000800,
- 0x04000002,0x04200000,0x04200800,0x00200002,
- 0x04200000,0x00000800,0x00000802,0x04200802,
- 0x00200800,0x00000002,0x04000000,0x00200800,
- 0x04000000,0x00200800,0x00200000,0x04000802,
- 0x04000802,0x04200002,0x04200002,0x00000002,
- 0x00200002,0x04000000,0x04000800,0x00200000,
- 0x04200800,0x00000802,0x00200802,0x04200800,
- 0x00000802,0x04000002,0x04200802,0x04200000,
- 0x00200800,0x00000000,0x00000002,0x04200802,
- 0x00000000,0x00200802,0x04200000,0x00000800,
- 0x04000002,0x04000800,0x00000800,0x00200002,
- 0x10001040,0x00001000,0x00040000,0x10041040,
- 0x10000000,0x10001040,0x00000040,0x10000000,
- 0x00040040,0x10040000,0x10041040,0x00041000,
- 0x10041000,0x00041040,0x00001000,0x00000040,
- 0x10040000,0x10000040,0x10001000,0x00001040,
- 0x00041000,0x00040040,0x10040040,0x10041000,
- 0x00001040,0x00000000,0x00000000,0x10040040,
- 0x10000040,0x10001000,0x00041040,0x00040000,
- 0x00041040,0x00040000,0x10041000,0x00001000,
- 0x00000040,0x10040040,0x00001000,0x00041040,
- 0x10001000,0x00000040,0x10000040,0x10040000,
- 0x10040040,0x10000000,0x00040000,0x10001040,
- 0x00000000,0x10041040,0x00040040,0x10000040,
- 0x10040000,0x10001000,0x10001040,0x00000000,
- 0x10041040,0x00041000,0x00041000,0x00001040,
- 0x00001040,0x00040040,0x10000000,0x10041000,
+ { 0x01010400,0x00000000,0x00010000,0x01010404,
+ 0x01010004,0x00010404,0x00000004,0x00010000,
+ 0x00000400,0x01010400,0x01010404,0x00000400,
+ 0x01000404,0x01010004,0x01000000,0x00000004,
+ 0x00000404,0x01000400,0x01000400,0x00010400,
+ 0x00010400,0x01010000,0x01010000,0x01000404,
+ 0x00010004,0x01000004,0x01000004,0x00010004,
+ 0x00000000,0x00000404,0x00010404,0x01000000,
+ 0x00010000,0x01010404,0x00000004,0x01010000,
+ 0x01010400,0x01000000,0x01000000,0x00000400,
+ 0x01010004,0x00010000,0x00010400,0x01000004,
+ 0x00000400,0x00000004,0x01000404,0x00010404,
+ 0x01010404,0x00010004,0x01010000,0x01000404,
+ 0x01000004,0x00000404,0x00010404,0x01010400,
+ 0x00000404,0x01000400,0x01000400,0x00000000,
+ 0x00010004,0x00010400,0x00000000,0x01010004 },
+ { 0x80108020,0x80008000,0x00008000,0x00108020,
+ 0x00100000,0x00000020,0x80100020,0x80008020,
+ 0x80000020,0x80108020,0x80108000,0x80000000,
+ 0x80008000,0x00100000,0x00000020,0x80100020,
+ 0x00108000,0x00100020,0x80008020,0x00000000,
+ 0x80000000,0x00008000,0x00108020,0x80100000,
+ 0x00100020,0x80000020,0x00000000,0x00108000,
+ 0x00008020,0x80108000,0x80100000,0x00008020,
+ 0x00000000,0x00108020,0x80100020,0x00100000,
+ 0x80008020,0x80100000,0x80108000,0x00008000,
+ 0x80100000,0x80008000,0x00000020,0x80108020,
+ 0x00108020,0x00000020,0x00008000,0x80000000,
+ 0x00008020,0x80108000,0x00100000,0x80000020,
+ 0x00100020,0x80008020,0x80000020,0x00100020,
+ 0x00108000,0x00000000,0x80008000,0x00008020,
+ 0x80000000,0x80100020,0x80108020,0x00108000 },
+ { 0x00000208,0x08020200,0x00000000,0x08020008,
+ 0x08000200,0x00000000,0x00020208,0x08000200,
+ 0x00020008,0x08000008,0x08000008,0x00020000,
+ 0x08020208,0x00020008,0x08020000,0x00000208,
+ 0x08000000,0x00000008,0x08020200,0x00000200,
+ 0x00020200,0x08020000,0x08020008,0x00020208,
+ 0x08000208,0x00020200,0x00020000,0x08000208,
+ 0x00000008,0x08020208,0x00000200,0x08000000,
+ 0x08020200,0x08000000,0x00020008,0x00000208,
+ 0x00020000,0x08020200,0x08000200,0x00000000,
+ 0x00000200,0x00020008,0x08020208,0x08000200,
+ 0x08000008,0x00000200,0x00000000,0x08020008,
+ 0x08000208,0x00020000,0x08000000,0x08020208,
+ 0x00000008,0x00020208,0x00020200,0x08000008,
+ 0x08020000,0x08000208,0x00000208,0x08020000,
+ 0x00020208,0x00000008,0x08020008,0x00020200 },
+ { 0x00802001,0x00002081,0x00002081,0x00000080,
+ 0x00802080,0x00800081,0x00800001,0x00002001,
+ 0x00000000,0x00802000,0x00802000,0x00802081,
+ 0x00000081,0x00000000,0x00800080,0x00800001,
+ 0x00000001,0x00002000,0x00800000,0x00802001,
+ 0x00000080,0x00800000,0x00002001,0x00002080,
+ 0x00800081,0x00000001,0x00002080,0x00800080,
+ 0x00002000,0x00802080,0x00802081,0x00000081,
+ 0x00800080,0x00800001,0x00802000,0x00802081,
+ 0x00000081,0x00000000,0x00000000,0x00802000,
+ 0x00002080,0x00800080,0x00800081,0x00000001,
+ 0x00802001,0x00002081,0x00002081,0x00000080,
+ 0x00802081,0x00000081,0x00000001,0x00002000,
+ 0x00800001,0x00002001,0x00802080,0x00800081,
+ 0x00002001,0x00002080,0x00800000,0x00802001,
+ 0x00000080,0x00800000,0x00002000,0x00802080 },
+ { 0x00000100,0x02080100,0x02080000,0x42000100,
+ 0x00080000,0x00000100,0x40000000,0x02080000,
+ 0x40080100,0x00080000,0x02000100,0x40080100,
+ 0x42000100,0x42080000,0x00080100,0x40000000,
+ 0x02000000,0x40080000,0x40080000,0x00000000,
+ 0x40000100,0x42080100,0x42080100,0x02000100,
+ 0x42080000,0x40000100,0x00000000,0x42000000,
+ 0x02080100,0x02000000,0x42000000,0x00080100,
+ 0x00080000,0x42000100,0x00000100,0x02000000,
+ 0x40000000,0x02080000,0x42000100,0x40080100,
+ 0x02000100,0x40000000,0x42080000,0x02080100,
+ 0x40080100,0x00000100,0x02000000,0x42080000,
+ 0x42080100,0x00080100,0x42000000,0x42080100,
+ 0x02080000,0x00000000,0x40080000,0x42000000,
+ 0x00080100,0x02000100,0x40000100,0x00080000,
+ 0x00000000,0x40080000,0x02080100,0x40000100 },
+ { 0x20000010,0x20400000,0x00004000,0x20404010,
+ 0x20400000,0x00000010,0x20404010,0x00400000,
+ 0x20004000,0x00404010,0x00400000,0x20000010,
+ 0x00400010,0x20004000,0x20000000,0x00004010,
+ 0x00000000,0x00400010,0x20004010,0x00004000,
+ 0x00404000,0x20004010,0x00000010,0x20400010,
+ 0x20400010,0x00000000,0x00404010,0x20404000,
+ 0x00004010,0x00404000,0x20404000,0x20000000,
+ 0x20004000,0x00000010,0x20400010,0x00404000,
+ 0x20404010,0x00400000,0x00004010,0x20000010,
+ 0x00400000,0x20004000,0x20000000,0x00004010,
+ 0x20000010,0x20404010,0x00404000,0x20400000,
+ 0x00404010,0x20404000,0x00000000,0x20400010,
+ 0x00000010,0x00004000,0x20400000,0x00404010,
+ 0x00004000,0x00400010,0x20004010,0x00000000,
+ 0x20404000,0x20000000,0x00400010,0x20004010 },
+ { 0x00200000,0x04200002,0x04000802,0x00000000,
+ 0x00000800,0x04000802,0x00200802,0x04200800,
+ 0x04200802,0x00200000,0x00000000,0x04000002,
+ 0x00000002,0x04000000,0x04200002,0x00000802,
+ 0x04000800,0x00200802,0x00200002,0x04000800,
+ 0x04000002,0x04200000,0x04200800,0x00200002,
+ 0x04200000,0x00000800,0x00000802,0x04200802,
+ 0x00200800,0x00000002,0x04000000,0x00200800,
+ 0x04000000,0x00200800,0x00200000,0x04000802,
+ 0x04000802,0x04200002,0x04200002,0x00000002,
+ 0x00200002,0x04000000,0x04000800,0x00200000,
+ 0x04200800,0x00000802,0x00200802,0x04200800,
+ 0x00000802,0x04000002,0x04200802,0x04200000,
+ 0x00200800,0x00000000,0x00000002,0x04200802,
+ 0x00000000,0x00200802,0x04200000,0x00000800,
+ 0x04000002,0x04000800,0x00000800,0x00200002 },
+ { 0x10001040,0x00001000,0x00040000,0x10041040,
+ 0x10000000,0x10001040,0x00000040,0x10000000,
+ 0x00040040,0x10040000,0x10041040,0x00041000,
+ 0x10041000,0x00041040,0x00001000,0x00000040,
+ 0x10040000,0x10000040,0x10001000,0x00001040,
+ 0x00041000,0x00040040,0x10040040,0x10041000,
+ 0x00001040,0x00000000,0x00000000,0x10040040,
+ 0x10000040,0x10001000,0x00041040,0x00040000,
+ 0x00041040,0x00040000,0x10041000,0x00001000,
+ 0x00000040,0x10040040,0x00001000,0x00041040,
+ 0x10001000,0x00000040,0x10000040,0x10040000,
+ 0x10040040,0x10000000,0x00040000,0x10001040,
+ 0x00000000,0x10041040,0x00040040,0x10000040,
+ 0x10040000,0x10001000,0x10001040,0x00000000,
+ 0x10041040,0x00041000,0x00041000,0x00001040,
+ 0x00001040,0x00040040,0x10000000,0x10041000 }
};
#undef F
diff --git a/libsoup/soup-ntlm.h b/libsoup/soup-ntlm.h
index 3149805a..5b35f429 100644
--- a/libsoup/soup-ntlm.h
+++ b/libsoup/soup-ntlm.h
@@ -13,19 +13,22 @@
#include <glib.h>
-void soup_ntlm_lanmanager_hash (const char *password,
- char hash[21]);
+void soup_ntlm_lanmanager_hash (const char *password,
+ guchar hash[21]);
-void soup_ntlm_nt_hash (const char *password,
- char hash[21]);
+void soup_ntlm_nt_hash (const char *password,
+ guchar hash[21]);
-char *soup_ntlm_request (void);
+char *soup_ntlm_request (void);
-char *soup_ntlm_response (const char *challenge,
- const char *user,
- const char *lm_hash,
- const char *nt_hash,
- const char *host,
- const char *domain);
+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);
#endif /* NTLM_H */
diff --git a/libsoup/soup-openssl.c b/libsoup/soup-openssl.c
index d8c8eac9..015cbf50 100644
--- a/libsoup/soup-openssl.c
+++ b/libsoup/soup-openssl.c
@@ -14,10 +14,7 @@
#ifdef HAVE_OPENSSL_SSL_H
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
-
#include <glib.h>
#include <sys/time.h>
@@ -27,6 +24,8 @@
#include "soup-openssl.h"
+static gboolean server_mode = FALSE;
+
typedef struct {
GIOChannel channel;
gint fd;
@@ -34,11 +33,21 @@ typedef struct {
SSL *ssl;
} SoupOpenSSLChannel;
-static GIOError
+static void
+soup_openssl_free (GIOChannel *channel)
+{
+ SoupOpenSSLChannel *chan = (SoupOpenSSLChannel *) channel;
+ g_io_channel_unref (chan->real_sock);
+ SSL_free (chan->ssl);
+ g_free (chan);
+}
+
+static GIOStatus
soup_openssl_read (GIOChannel *channel,
gchar *buf,
guint count,
- guint *bytes_read)
+ guint *bytes_read,
+ GError **err)
{
SoupOpenSSLChannel *chan = (SoupOpenSSLChannel *) channel;
gint result;
@@ -49,27 +58,32 @@ soup_openssl_read (GIOChannel *channel,
/* This occurs when a re-handshake is required */
*bytes_read = 0;
if (SSL_get_error (chan->ssl, result) == SSL_ERROR_WANT_READ)
- return G_IO_ERROR_AGAIN;
+ return G_IO_STATUS_AGAIN;
switch (errno) {
case EINVAL:
+#if 0
return G_IO_ERROR_INVAL;
+#else
+ return G_IO_STATUS_ERROR;
+#endif
case EAGAIN:
case EINTR:
- return G_IO_ERROR_AGAIN;
+ return G_IO_STATUS_AGAIN;
default:
- return G_IO_ERROR_UNKNOWN;
+ return G_IO_STATUS_ERROR;
}
} else {
*bytes_read = result;
- return G_IO_ERROR_NONE;
+ return G_IO_STATUS_NORMAL;
}
}
-static GIOError
+static GIOStatus
soup_openssl_write (GIOChannel *channel,
- gchar *buf,
- guint count,
- guint *bytes_written)
+ const gchar *buf,
+ gsize count,
+ gsize *bytes_written,
+ GError **err)
{
SoupOpenSSLChannel *chan = (SoupOpenSSLChannel *) channel;
gint result;
@@ -78,119 +92,183 @@ soup_openssl_write (GIOChannel *channel,
if (result < 0) {
*bytes_written = 0;
- if (SSL_get_error (chan->ssl, result) == SSL_ERROR_WANT_READ)
- return G_IO_ERROR_AGAIN;
+ if (SSL_get_error (chan->ssl, result) == SSL_ERROR_WANT_WRITE)
+ return G_IO_STATUS_AGAIN;
switch (errno) {
case EINVAL:
+#if 0
return G_IO_ERROR_INVAL;
+#else
+ return G_IO_STATUS_ERROR;
+#endif
case EAGAIN:
case EINTR:
- return G_IO_ERROR_AGAIN;
+ return G_IO_STATUS_AGAIN;
default:
- return G_IO_ERROR_UNKNOWN;
+ return G_IO_STATUS_ERROR;
}
} else {
*bytes_written = result;
- return G_IO_ERROR_NONE;
+
+ return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
}
}
-static GIOError
-soup_openssl_seek (GIOChannel *channel, gint offset, GSeekType type)
+static GIOStatus
+soup_openssl_seek (GIOChannel *channel,
+ gint64 offset,
+ GSeekType type,
+ GError **err)
{
SoupOpenSSLChannel *chan = (SoupOpenSSLChannel *) channel;
- return g_io_channel_seek (chan->real_sock, offset, type);
+ GIOError e;
+
+ e = g_io_channel_seek (chan->real_sock, offset, type);
+
+ if (e != G_IO_ERROR_NONE)
+ return G_IO_STATUS_ERROR;
+ else
+ return G_IO_STATUS_NORMAL;
}
-static void
-soup_openssl_close (GIOChannel *channel)
+static GIOStatus
+soup_openssl_close (GIOChannel *channel,
+ GError **err)
{
SoupOpenSSLChannel *chan = (SoupOpenSSLChannel *) channel;
g_io_channel_close (chan->real_sock);
+
+ return G_IO_STATUS_NORMAL;
}
-static void
-soup_openssl_free (GIOChannel *channel)
+typedef struct {
+ GSource source;
+ GPollFD pollfd;
+ GIOChannel *channel;
+ GIOCondition condition;
+} SoupOpenSSLWatch;
+
+static gboolean
+soup_openssl_prepare (GSource *source,
+ gint *timeout)
{
- SoupOpenSSLChannel *chan = (SoupOpenSSLChannel *) channel;
- g_io_channel_unref (chan->real_sock);
- SSL_free (chan->ssl);
- g_free (chan);
+ SoupOpenSSLWatch *watch = (SoupOpenSSLWatch *) source;
+ GIOCondition buffer_condition = g_io_channel_get_buffer_condition (
+ watch->channel);
+
+ *timeout = -1;
+
+ /* Only return TRUE here if _all_ bits in watch->condition will be set
+ */
+ return ((watch->condition & buffer_condition) == watch->condition);
}
-#if 0
+static gboolean
+soup_openssl_check (GSource *source)
+{
+ SoupOpenSSLWatch *watch = (SoupOpenSSLWatch *) source;
+ GIOCondition buffer_condition = g_io_channel_get_buffer_condition (
+ watch->channel);
+ GIOCondition poll_condition = watch->pollfd.revents;
-/* Commented out until we can figure out why SSL_pending always fails */
+ return ((poll_condition | buffer_condition) & watch->condition);
+}
-typedef struct {
- GIOFunc func;
- gpointer user_data;
-} SoupOpenSSLReadData;
-
-static gboolean
-soup_openssl_read_cb (GIOChannel *channel,
- GIOCondition condition,
- gpointer user_data)
+static gboolean
+soup_openssl_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
{
- SoupOpenSSLChannel *chan = (SoupOpenSSLChannel *) channel;
- SoupOpenSSLReadData *data = user_data;
+ GIOFunc func = (GIOFunc) callback;
+ SoupOpenSSLWatch *watch = (SoupOpenSSLWatch *) source;
+ SoupOpenSSLChannel *chan = (SoupOpenSSLChannel *) watch->channel;
+ GIOCondition buffer_condition = g_io_channel_get_buffer_condition (
+ watch->channel);
+ GIOCondition cond;
+
+ if (!func) {
+ g_warning ("IO watch dispatched without callback\n"
+ "You must call g_source_connect().");
+ return FALSE;
+ }
+
+ cond = (watch->pollfd.revents | buffer_condition) & watch->condition;
- if (condition & G_IO_IN) {
- if (SSL_pending (chan->ssl) &&
- !(*data->func) (channel, condition, data->user_data)) {
- g_free (data);
+ if (cond & G_IO_IN) {
+ do {
+ if (!(*func) (watch->channel, cond, user_data))
return FALSE;
- }
+ } while (SSL_pending (chan->ssl));
+
return TRUE;
- } else return (*data->func) (channel, condition, data->user_data);
+ } else
+ return (*func) (watch->channel, cond, user_data);
+}
+
+static void
+soup_openssl_finalize (GSource *source)
+{
+ SoupOpenSSLWatch *watch = (SoupOpenSSLWatch *) source;
+
+ g_io_channel_unref (watch->channel);
}
-static guint
-soup_openssl_add_watch (GIOChannel *channel,
- gint priority,
- GIOCondition condition,
- GIOFunc func,
- gpointer user_data,
- GDestroyNotify notify)
+/* All of these functions were basically cut-and-pasted from glib */
+GSourceFuncs soup_openssl_watch_funcs = {
+ soup_openssl_prepare,
+ soup_openssl_check,
+ soup_openssl_dispatch,
+ soup_openssl_finalize
+};
+
+static GSource *
+soup_openssl_create_watch (GIOChannel *channel,
+ GIOCondition condition)
{
SoupOpenSSLChannel *chan = (SoupOpenSSLChannel *) channel;
if (condition & G_IO_IN) {
- SoupOpenSSLReadData *data = g_new0 (SoupOpenSSLReadData, 1);
- data->func = func;
- data->user_data = user_data;
-
- return chan->real_sock->funcs->io_add_watch (channel,
- priority,
- condition,
- soup_openssl_read_cb,
- data,
- notify);
- } else return chan->real_sock->funcs->io_add_watch (channel,
- priority,
- condition,
- func,
- user_data,
- notify);
+ GSource *source;
+ SoupOpenSSLWatch *watch;
+
+ source = g_source_new (&soup_openssl_watch_funcs,
+ sizeof (SoupOpenSSLWatch));
+ watch = (SoupOpenSSLWatch *) source;
+
+ watch->channel = channel;
+ g_io_channel_ref (channel);
+
+ watch->condition = condition;
+
+ watch->pollfd.fd = chan->fd;
+ watch->pollfd.events = condition;
+
+ g_source_add_poll (source, &watch->pollfd);
+
+ return source;
+ }
+ else {
+ return chan->real_sock->funcs->io_create_watch (channel,
+ condition);
+ }
}
-#endif /* 0 */
+static GIOStatus
+soup_openssl_set_flags (GIOChannel *channel,
+ GIOFlags flags,
+ GError **err)
+{
+ SoupOpenSSLChannel *chan = (SoupOpenSSLChannel *) channel;
-static guint
-soup_openssl_add_watch (GIOChannel *channel,
- gint priority,
- GIOCondition condition,
- GIOFunc func,
- gpointer user_data,
- GDestroyNotify notify)
+ return chan->real_sock->funcs->io_set_flags (channel, flags, err);
+}
+
+static GIOFlags
+soup_openssl_get_flags (GIOChannel *channel)
{
SoupOpenSSLChannel *chan = (SoupOpenSSLChannel *) channel;
- return chan->real_sock->funcs->io_add_watch (channel,
- priority,
- condition,
- func,
- user_data,
- notify);
+
+ return chan->real_sock->funcs->io_get_flags (channel);
}
GIOFuncs soup_openssl_channel_funcs = {
@@ -198,8 +276,10 @@ GIOFuncs soup_openssl_channel_funcs = {
soup_openssl_write,
soup_openssl_seek,
soup_openssl_close,
- soup_openssl_add_watch,
+ soup_openssl_create_watch,
soup_openssl_free,
+ soup_openssl_set_flags,
+ soup_openssl_get_flags
};
static SSL_CTX *ssl_context = NULL;
@@ -258,7 +338,7 @@ soup_openssl_get_iochannel (GIOChannel *sock)
g_return_val_if_fail (sock != NULL, NULL);
- if (!ssl_context && !soup_openssl_init ())
+ if (!ssl_context && !soup_openssl_init (server_mode))
goto THROW_CREATE_ERROR;
if (!soup_openssl_seed ())
@@ -283,12 +363,13 @@ soup_openssl_get_iochannel (GIOChannel *sock)
goto THROW_CREATE_ERROR;
}
- if (!SSL_use_RSAPrivateKey_file (ssl, ckey_file, 1)) {
+ if (!SSL_use_RSAPrivateKey_file (ssl, ckey_file, SSL_FILETYPE_PEM)) {
g_warning ("Unable to use private key file.");
+ ERR_print_errors_fp(stderr);
goto THROW_CREATE_ERROR;
}
- if (!SSL_use_certificate_file (ssl, ccert_file, 1)) {
+ if (!SSL_use_certificate_file (ssl, ccert_file, SSL_FILETYPE_PEM)) {
g_warning ("Unable to use certificate file.");
goto THROW_CREATE_ERROR;
}
@@ -307,25 +388,31 @@ soup_openssl_get_iochannel (GIOChannel *sock)
goto THROW_CREATE_ERROR;
}
- while (1) {
- err = SSL_connect (ssl);
- switch (SSL_get_error (ssl, err)) {
- case SSL_ERROR_NONE:
- break;
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
- {
- fd_set readfds;
- FD_ZERO (&readfds);
- FD_SET (sockfd, &readfds);
- select (1, &readfds, NULL, NULL, NULL);
- continue;
+ do {
+ fd_set ssl_fdset;
+
+ if (server_mode)
+ err = SSL_accept (ssl);
+ else
+ err = SSL_connect (ssl);
+
+ err = SSL_get_error (ssl, err);
+
+ if (err == SSL_ERROR_WANT_READ) {
+ FD_ZERO (&ssl_fdset);
+ FD_SET (sockfd, &ssl_fdset);
+ select (sockfd + 1, &ssl_fdset, NULL, NULL, NULL);
}
- default:
+ else if (err == SSL_ERROR_WANT_WRITE) {
+ FD_ZERO (&ssl_fdset);
+ FD_SET (sockfd, &ssl_fdset);
+ select (sockfd + 1, NULL, &ssl_fdset, NULL, NULL);
+ }
+ else if (err != SSL_ERROR_NONE) {
g_warning ("Could not establish secure connection.");
goto THROW_CREATE_ERROR;
}
- }
+ } while (err != SSL_ERROR_NONE);
bits = SSL_get_cipher_bits (ssl, &alg_bits);
if (bits == 0) {
@@ -333,12 +420,15 @@ soup_openssl_get_iochannel (GIOChannel *sock)
goto THROW_CREATE_ERROR;
}
- cert = SSL_get_peer_certificate (ssl);
- if (!cert) {
- g_warning ("Server certificate unavailable");
- goto THROW_CREATE_ERROR;
+ if (!server_mode) {
+ cert = SSL_get_peer_certificate (ssl);
+ if (!cert) {
+ g_warning ("Server certificate unavailable");
+ goto THROW_CREATE_ERROR;
+ }
+ else
+ X509_free (cert);
}
- X509_free (cert);
chan = g_new0 (SoupOpenSSLChannel, 1);
chan->fd = sockfd;
@@ -356,8 +446,17 @@ soup_openssl_get_iochannel (GIOChannel *sock)
return NULL;
}
+static int
+verify_cb (int verified, X509_STORE_CTX *x509_ctx)
+{
+ if (!verified)
+ g_warning ("Unable to verify server's CA");
+
+ return verified;
+}
+
gboolean
-soup_openssl_init (void)
+soup_openssl_init (gboolean server)
{
static gchar *ssl_ca_file = NULL;
static gchar *ssl_ca_dir = NULL;
@@ -365,7 +464,13 @@ soup_openssl_init (void)
SSL_library_init ();
SSL_load_error_strings ();
- ssl_context = SSL_CTX_new (SSLv23_client_method ());
+ server_mode = server;
+
+ if (server_mode)
+ ssl_context = SSL_CTX_new (SSLv23_server_method ());
+ else
+ ssl_context = SSL_CTX_new (SSLv23_client_method ());
+
if (!ssl_context) {
g_warning ("Unable to initialize OpenSSL library");
return FALSE;
@@ -380,7 +485,7 @@ soup_openssl_init (void)
SSL_CTX_load_verify_locations (ssl_context,
ssl_ca_file,
ssl_ca_dir);
- SSL_CTX_set_verify (ssl_context, SSL_VERIFY_PEER, NULL);
+ SSL_CTX_set_verify (ssl_context, SSL_VERIFY_PEER, verify_cb);
}
return TRUE;
diff --git a/libsoup/soup-openssl.h b/libsoup/soup-openssl.h
index 2a00983b..dbcd25a7 100644
--- a/libsoup/soup-openssl.h
+++ b/libsoup/soup-openssl.h
@@ -18,6 +18,6 @@ GIOChannel *soup_openssl_get_iochannel (GIOChannel *sock);
void soup_openssl_set_security_policy (SoupSecurityPolicy policy);
-gboolean soup_openssl_init (void);
+gboolean soup_openssl_init (gboolean server_mode);
#endif /* SOUP_OPENSSL_H */
diff --git a/libsoup/soup-private.h b/libsoup/soup-private.h
index 55005081..f31e979c 100644
--- a/libsoup/soup-private.h
+++ b/libsoup/soup-private.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-private.h: Asyncronous Callback-based SOAP Request Queue.
+ * soup-private.h: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@helixcode.com)
@@ -13,46 +13,16 @@
* extraneous circumstances.
*/
-#ifndef SOAP_PRIVATE_H
-#define SOAP_PRIVATE_H 1
+#ifndef SOUP_PRIVATE_H
+#define SOUP_PRIVATE_H 1
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
-#ifdef SOUP_WIN32
-# include <malloc.h>
-# define alloca _alloca
-#else
-# ifdef HAVE_ALLOCA_H
-# include <alloca.h>
-# else
-# ifdef _AIX
-# pragma alloca
-# else
-# ifndef alloca /* predefined by HP cc +Olibcalls */
- char *alloca ();
-# endif
-# endif
-# endif
-#endif
-
#include <sys/types.h>
-
-#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
-#endif
-
-#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
-#endif
-
-#ifdef SOUP_WIN32
-#define VERSION "Win/0.7.99"
-#include <windows.h>
-#include <winbase.h>
-#include <winuser.h>
-#endif
#include <libsoup/soup-auth.h>
#include <libsoup/soup-context.h>
@@ -137,6 +107,8 @@ struct _SoupMessagePrivate {
guint write_tag;
guint timeout_tag;
+ guint retries;
+
SoupCallbackFn callback;
gpointer user_data;
@@ -156,7 +128,7 @@ struct _SoupMessagePrivate {
void soup_message_issue_callback (SoupMessage *req);
gboolean soup_message_run_handlers (SoupMessage *msg,
- SoupHandlerEvent invoke_type);
+ SoupHandlerType invoke_type);
void soup_message_cleanup (SoupMessage *req);
diff --git a/libsoup/soup-queue.c b/libsoup/soup-queue.c
index 365a582a..e0153657 100644
--- a/libsoup/soup-queue.c
+++ b/libsoup/soup-queue.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-queue.c: Asyncronous Callback-based SOAP Request Queue.
+ * soup-queue.c: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@helixcode.com)
@@ -79,9 +79,19 @@ soup_queue_error_cb (gboolean body_started, gpointer user_data)
case SOUP_STATUS_SENDING_REQUEST:
if (!body_started) {
/*
- * FIXME: Use exponential backoff here
+ * This can easily happen if we are using the OpenSSL
+ * out-of-process proxy and we couldn't establish an
+ * SSL connection.
*/
- soup_message_requeue (req);
+ if (req->priv->retries >= 3) {
+ soup_message_set_error (
+ req,
+ SOUP_ERROR_CANT_CONNECT);
+ soup_message_issue_callback (req);
+ } else {
+ req->priv->retries++;
+ soup_message_requeue (req);
+ }
} else {
soup_message_set_error (req, SOUP_ERROR_IO);
soup_message_issue_callback (req);
@@ -198,7 +208,7 @@ soup_queue_read_headers_cb (const GString *headers,
}
SUCCESS_CONTINUE:
- soup_message_run_handlers (req, SOUP_HANDLER_HEADERS);
+ soup_message_run_handlers (req, SOUP_HANDLER_PRE_BODY);
return SOUP_TRANSFER_CONTINUE;
THROW_MALFORMED_HEADER:
@@ -217,7 +227,7 @@ soup_queue_read_chunk_cb (const SoupDataBuffer *data,
req->response.length = data->length;
req->response.body = data->body;
- soup_message_run_handlers (req, SOUP_HANDLER_DATA);
+ soup_message_run_handlers (req, SOUP_HANDLER_BODY_CHUNK);
return SOUP_TRANSFER_CONTINUE;
}
@@ -255,7 +265,7 @@ soup_queue_read_done_cb (const SoupDataBuffer *data,
req->priv->read_tag = 0;
}
- soup_message_run_handlers (req, SOUP_HANDLER_FINISHED);
+ soup_message_run_handlers (req, SOUP_HANDLER_POST_BODY);
}
static void
@@ -497,7 +507,7 @@ start_request (SoupContext *ctx, SoupMessage *req)
req->status = SOUP_STATUS_SENDING_REQUEST;
}
-static SoupHandlerResult
+static void
proxy_https_connect_cb (SoupMessage *msg, gpointer user_data)
{
gboolean *ret = user_data;
@@ -516,8 +526,6 @@ proxy_https_connect_cb (SoupMessage *msg, gpointer user_data)
*ret = TRUE;
}
-
- return SOUP_HANDLER_CONTINUE;
}
static gboolean
@@ -538,8 +546,7 @@ proxy_https_connect (SoupContext *proxy,
connect_msg = soup_message_new (dest_ctx, SOUP_METHOD_CONNECT);
connect_msg->connection = conn;
soup_message_add_handler (connect_msg,
- SOUP_HANDLER_FINISHED,
- NULL,
+ SOUP_HANDLER_POST_BODY,
proxy_https_connect_cb,
&ret);
soup_message_send (connect_msg);
diff --git a/libsoup/soup-queue.h b/libsoup/soup-queue.h
index 30ba5d3f..0def1f44 100644
--- a/libsoup/soup-queue.h
+++ b/libsoup/soup-queue.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-queue.h: Asyncronous Callback-based SOAP Request Queue.
+ * soup-queue.h: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@ximian.com)
diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c
index 82c4179a..fe689ad0 100644
--- a/libsoup/soup-server.c
+++ b/libsoup/soup-server.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-server.c: Asyncronous Callback-based SOAP Request Queue.
+ * soup-server.c: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@ximian.com)
@@ -16,9 +16,7 @@
#include <config.h>
#endif
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
#ifdef HAVE_SYS_FILIO_H
#include <sys/filio.h>
@@ -28,12 +26,6 @@
#include <sys/ioctl.h>
#endif
-#ifdef SOUP_WIN32
-#define ioctl ioctlsocket
-#define STDIN_FILENO 0
-#define STDOUT_FILENO 1
-#endif
-
extern char **environ;
#include <string.h>
@@ -200,6 +192,33 @@ static gboolean start_another_request (GIOChannel *serv_chan,
GIOCondition condition,
gpointer user_data);
+static gboolean
+check_close_connection (SoupMessage *msg)
+{
+ const char *connection_hdr;
+ gboolean close_connection;
+
+ connection_hdr = soup_message_get_header (msg->request_headers,
+ "Connection");
+
+ if (msg->priv->http_version == SOUP_HTTP_1_0) {
+ if (connection_hdr && g_strcasecmp (connection_hdr,
+ "keep-alive") == 0)
+ close_connection = FALSE;
+ else
+ close_connection = TRUE;
+ }
+ else {
+ if (connection_hdr && g_strcasecmp (connection_hdr,
+ "close") == 0)
+ close_connection = TRUE;
+ else
+ close_connection = FALSE;
+ }
+
+ return close_connection;
+} /* check_close_connection */
+
static void
destroy_message (SoupMessage *msg)
{
@@ -208,18 +227,24 @@ destroy_message (SoupMessage *msg)
SoupServerMessage *server_msg = msg->priv->server_msg;
if (server_sock) {
- if (server_msg && msg->priv->http_version == SOUP_HTTP_1_0)
- /*
- * Close the socket if we are using HTTP/1.0 and
- * did not specify a Content-Length response header.
- */
+ GIOChannel *chan;
+
+ chan = soup_socket_get_iochannel (server_sock);
+
+ /*
+ * Close the socket if we're using HTTP/1.0 and
+ * "Connection: keep-alive" isn't specified, or if we're
+ * using HTTP/1.1 and "Connection: close" was specified.
+ */
+ if (check_close_connection (msg)) {
+ g_io_channel_close (chan);
soup_socket_unref (server_sock);
+ }
else {
/*
* Listen for another request on this connection
*/
ServerConnectData *data;
- GIOChannel *chan;
data = g_new0 (ServerConnectData, 1);
data->server = msg->priv->server;
@@ -413,6 +438,85 @@ get_server_sockname (gint fd)
return host;
}
+static void
+write_header (gchar *key, gchar *value, GString *ret)
+{
+ g_string_sprintfa (ret, "%s: %s\r\n", key, value);
+}
+
+static GString *
+get_response_header (SoupMessage *req,
+ gboolean status_line,
+ SoupTransferEncoding encoding)
+{
+ GString *ret = g_string_new (NULL);
+
+ if (status_line)
+ g_string_sprintfa (ret,
+ "HTTP/1.1 %d %s\r\n",
+ req->errorcode,
+ req->errorphrase);
+ else
+ g_string_sprintfa (ret,
+ "Status: %d %s\r\n",
+ req->errorcode,
+ req->errorphrase);
+
+ if (encoding == SOUP_TRANSFER_CONTENT_LENGTH)
+ g_string_sprintfa (ret,
+ "Content-Length: %d\r\n",
+ req->response.length);
+ else if (encoding == SOUP_TRANSFER_CHUNKED)
+ g_string_append (ret, "Transfer-Encoding: chunked\r\n");
+
+ soup_message_foreach_header (req->response_headers,
+ (GHFunc) write_header,
+ ret);
+
+ g_string_append (ret, "\r\n");
+
+ return ret;
+}
+
+static inline void
+set_response_error (SoupMessage *req,
+ guint code,
+ gchar *phrase,
+ gchar *body)
+{
+ if (phrase)
+ soup_message_set_error_full (req, code, phrase);
+ else
+ soup_message_set_error (req, code);
+
+ req->response.owner = SOUP_BUFFER_STATIC;
+ req->response.body = body;
+ req->response.length = body ? strlen (req->response.body) : 0;
+}
+
+static void
+issue_bad_request (SoupMessage *msg)
+{
+ GString *header;
+ GIOChannel *channel;
+
+ set_response_error (msg, SOUP_ERROR_BAD_REQUEST, NULL, NULL);
+
+ header = get_response_header (msg,
+ FALSE,
+ SOUP_TRANSFER_CONTENT_LENGTH);
+
+ channel = soup_socket_get_iochannel (msg->priv->server_sock);
+
+ msg->priv->write_tag =
+ soup_transfer_write_simple (channel,
+ header,
+ &msg->response,
+ write_done_cb,
+ error_cb,
+ msg);
+} /* issue_bad_request */
+
static SoupTransferDone
read_headers_cb (const GString *headers,
SoupTransferEncoding *encoding,
@@ -473,17 +577,7 @@ read_headers_cb (const GString *headers,
req_host = soup_message_get_header (msg->request_headers,
"Host");
- if (req_host) {
- url =
- g_strdup_printf (
- "%s%s:%d%s",
- server->proto == SOUP_PROTOCOL_HTTPS ?
- "https://" :
- "http://",
- req_host,
- server->port,
- req_path);
- } else if (*req_path != '/') {
+ if (*req_path != '/') {
/*
* Check for absolute URI
*/
@@ -495,6 +589,16 @@ read_headers_cb (const GString *headers,
soup_uri_free (absolute);
} else
goto THROW_MALFORMED_HEADER;
+ } else if (req_host) {
+ url =
+ g_strdup_printf (
+ "%s%s:%d%s",
+ server->proto == SOUP_PROTOCOL_HTTPS ?
+ "https://" :
+ "http://",
+ req_host,
+ server->port,
+ req_path);
} else {
/*
* No Host header, no AbsoluteUri
@@ -531,65 +635,9 @@ read_headers_cb (const GString *headers,
THROW_MALFORMED_HEADER:
g_free (req_path);
- destroy_message (msg);
-
- return SOUP_TRANSFER_END;
-}
-
-static void
-write_header (gchar *key, gchar *value, GString *ret)
-{
- g_string_sprintfa (ret, "%s: %s\r\n", key, value);
-}
-
-static GString *
-get_response_header (SoupMessage *req,
- gboolean status_line,
- SoupTransferEncoding encoding)
-{
- GString *ret = g_string_new (NULL);
-
- if (status_line)
- g_string_sprintfa (ret,
- "HTTP/1.1 %d %s\r\n",
- req->errorcode,
- req->errorphrase);
- else
- g_string_sprintfa (ret,
- "Status: %d %s\r\n",
- req->errorcode,
- req->errorphrase);
+ issue_bad_request(msg);
- if (encoding == SOUP_TRANSFER_CONTENT_LENGTH)
- g_string_sprintfa (ret,
- "Content-Length: %d\r\n",
- req->response.length);
- else if (encoding == SOUP_TRANSFER_CHUNKED)
- g_string_append (ret, "Transfer-Encoding: chunked\r\n");
-
- soup_message_foreach_header (req->response_headers,
- (GHFunc) write_header,
- ret);
-
- g_string_append (ret, "\r\n");
-
- return ret;
-}
-
-static inline void
-set_response_error (SoupMessage *req,
- guint code,
- gchar *phrase,
- gchar *body)
-{
- if (phrase)
- soup_message_set_error_full (req, code, phrase);
- else
- soup_message_set_error (req, code);
-
- req->response.owner = SOUP_BUFFER_STATIC;
- req->response.body = body;
- req->response.length = body ? strlen (req->response.body) : 0;
+ return SOUP_TRANSFER_CONTINUE;
}
static void
@@ -792,19 +840,6 @@ read_done_cb (const SoupDataBuffer *data,
req->priv->read_tag = 0;
- /* FIXME: Do this in soap handler
- action = soup_message_get_header (req->request_headers, "SOAPAction");
- if (!action) {
- g_print ("No SOAPAction found in request.\n");
- set_response_error (
- req,
- 403,
- "Missing SOAPAction",
- "The required SOAPAction header was not supplied.");
- goto START_WRITE;
- }
- */
-
call_handler (req, data, soup_context_get_uri (req->context)->path);
channel = soup_socket_get_iochannel (server_sock);
@@ -860,6 +895,7 @@ message_new (SoupServer *server)
*/
msg = soup_message_new (NULL, NULL);
if (msg) {
+ msg->method = NULL;
msg->priv->server = server;
soup_server_ref (server);
}
@@ -926,7 +962,7 @@ conn_accept (GIOChannel *serv_chan,
chan = soup_socket_get_iochannel (sock);
if (server->proto == SOUP_PROTOCOL_HTTPS) {
- chan = soup_ssl_get_iochannel (chan);
+ chan = soup_ssl_get_server_iochannel (chan);
g_io_channel_unref (sock->iochannel);
g_io_channel_ref (chan);
sock->iochannel = chan;
@@ -1156,6 +1192,33 @@ soup_server_get_handler (SoupServer *server, const gchar *path)
return server->default_handler;
}
+SoupAddress *
+soup_server_context_get_client_address (SoupServerContext *context)
+{
+ SoupSocket *socket;
+ SoupAddress *address;
+
+ g_return_val_if_fail (context != NULL, NULL);
+
+ socket = context->msg->priv->server_sock;
+ address = soup_socket_get_address (socket);
+
+ return address;
+}
+
+gchar *
+soup_server_context_get_client_host (SoupServerContext *context)
+{
+ gchar *host;
+ SoupAddress *address;
+
+ address = soup_server_context_get_client_address (context);
+ host = g_strdup (soup_address_get_canonical_name (address));
+ soup_address_unref (address);
+
+ return host;
+}
+
static SoupServerAuthContext *
auth_context_copy (SoupServerAuthContext *auth_ctx)
{
diff --git a/libsoup/soup-server.h b/libsoup/soup-server.h
index 9245381a..c4bb6285 100644
--- a/libsoup/soup-server.h
+++ b/libsoup/soup-server.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-server.h: Asyncronous Callback-based SOAP Request Queue.
+ * soup-server.h: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@helixcode.com)
@@ -15,6 +15,7 @@
#include <libsoup/soup-message.h>
#include <libsoup/soup-method.h>
#include <libsoup/soup-misc.h>
+#include <libsoup/soup-socket.h>
#include <libsoup/soup-uri.h>
#include <libsoup/soup-server-auth.h>
@@ -82,6 +83,12 @@ SoupServerHandler *soup_server_get_handler (SoupServer *serv,
GSList *soup_server_list_handlers (SoupServer *serv);
+/* Functions for accessing information about the specific connection */
+
+SoupAddress *soup_server_context_get_client_address (SoupServerContext *context);
+
+gchar *soup_server_context_get_client_host (SoupServerContext *context);
+
/*
* Apache/soup-httpd module initializtion
* Implement soup_server_init() in your shared library.
diff --git a/libsoup/soup-socket-unix.c b/libsoup/soup-socket-unix.c
index a46fecc8..c5dd86ba 100644
--- a/libsoup/soup-socket-unix.c
+++ b/libsoup/soup-socket-unix.c
@@ -36,7 +36,6 @@
#include "soup-socket.h"
#include <netdb.h>
-#include <resolv.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
@@ -69,6 +68,11 @@
# endif
#endif
+/* this generally causes problems, so remove from build atm */
+#ifdef SOUP_PTRACE_ATTACH
+#undef SOUP_PTRACE_ATTACH
+#endif
+
#ifndef socklen_t
#define socklen_t size_t
#endif
@@ -192,7 +196,7 @@ soup_gethostbyname(const char* hostname,
g_free(buf);
}
#else
-#ifdef HAVE_GET_HOSTBYNAME_R_SOLARIS
+#ifdef HAVE_GETHOSTBYNAME_R_SOLARIS
{
struct hostent result;
size_t len;
@@ -348,7 +352,7 @@ soup_gethostbyaddr (const char* addr, size_t length, int type)
g_free(buf);
}
#else
-#ifdef HAVE_GET_HOSTBYNAME_R_SOLARIS
+#ifdef HAVE_GETHOSTBYNAME_R_SOLARIS
{
struct hostent result;
size_t len;
diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c
index 4b733205..0b51ce30 100644
--- a/libsoup/soup-socket.c
+++ b/libsoup/soup-socket.c
@@ -22,17 +22,9 @@
#include "soup-private.h"
#include "soup-socket.h"
-#ifdef SOUP_WIN32
-# define socklen_t gint32
-# define SOUP_CLOSE_SOCKET(fd) closesocket(fd)
-# define SOUP_SOCKET_IOCHANNEL_NEW(fd) g_io_channel_win32_new_socket(fd)
-#else
-# include <unistd.h>
-# ifndef socklen_t
-# define socklen_t size_t
-# endif
-# define SOUP_CLOSE_SOCKET(fd) close(fd)
-# define SOUP_SOCKET_IOCHANNEL_NEW(fd) g_io_channel_unix_new(fd)
+#include <unistd.h>
+#ifndef socklen_t
+# define socklen_t size_t
#endif
#ifndef INET_ADDRSTRLEN
@@ -315,8 +307,6 @@ soup_socket_connect_tcp_cb (SoupSocket* socket,
SoupSocketConnectFn func = state->func;
gpointer user_data = state->data;
- g_free (state);
-
if (status == SOUP_SOCKET_NEW_STATUS_OK)
(*func) (socket,
SOUP_SOCKET_CONNECT_ERROR_NONE,
@@ -325,6 +315,9 @@ soup_socket_connect_tcp_cb (SoupSocket* socket,
(*func) (NULL,
SOUP_SOCKET_CONNECT_ERROR_NETWORK,
user_data);
+
+ if (state->tcp_id)
+ g_free (state);
}
static void
@@ -335,31 +328,23 @@ soup_socket_connect_inetaddr_cb (SoupAddress* inetaddr,
SoupSocketConnectState* state = (SoupSocketConnectState*) data;
if (status == SOUP_ADDRESS_STATUS_OK) {
- gpointer tcp_id;
-
- state->inetaddr_id = NULL;
-
- tcp_id = soup_socket_new (inetaddr,
- soup_socket_connect_tcp_cb,
- state);
- /*
- * NOTE: soup_socket_new can fail immediately and call our
- * callback which will delete the state.
- */
- if (tcp_id)
- state->tcp_id = tcp_id;
-
+ state->tcp_id = soup_socket_new (inetaddr,
+ soup_socket_connect_tcp_cb,
+ state);
soup_address_unref (inetaddr);
} else {
SoupSocketConnectFn func = state->func;
gpointer user_data = state->data;
- g_free (state);
-
(*func) (NULL,
SOUP_SOCKET_CONNECT_ERROR_ADDR_RESOLVE,
user_data);
}
+
+ if (state->inetaddr_id && !state->tcp_id)
+ g_free (state);
+ else
+ state->inetaddr_id = NULL;
}
/**
@@ -377,8 +362,8 @@ soup_socket_connect_inetaddr_cb (SoupAddress* inetaddr,
* returns. It will call the callback if there is a failure.
*
* Returns: ID of the connection which can be used with
- * soup_socket_connect_cancel() to cancel it; NULL on
- * failure.
+ * soup_socket_connect_cancel() to cancel it; NULL if it succeeds
+ * or fails immediately.
**/
SoupSocketConnectId
soup_socket_connect (const gchar* hostname,
@@ -388,7 +373,6 @@ soup_socket_connect (const gchar* hostname,
{
SoupSocketConnectState* state;
SoupAddress *cached_addr;
- gpointer addr_id, tcp_id;
g_return_val_if_fail (hostname != NULL, NULL);
g_return_val_if_fail (func != NULL, NULL);
@@ -400,35 +384,26 @@ soup_socket_connect (const gchar* hostname,
/* Check if a cached version of the address already exists */
cached_addr = soup_address_lookup_in_cache (hostname, port);
if (cached_addr) {
- tcp_id = soup_socket_new (cached_addr,
- soup_socket_connect_tcp_cb,
- state);
+ state->tcp_id = soup_socket_new (cached_addr,
+ soup_socket_connect_tcp_cb,
+ state);
soup_address_unref (cached_addr);
-
- /*
- * NOTE: soup_socket_new can fail immediately and call our
- * callback which will delete the state.
- */
- if (tcp_id) {
- state->tcp_id = tcp_id;
- return state;
- } else
- return NULL;
} else {
- addr_id = soup_address_new (hostname,
- port,
- soup_socket_connect_inetaddr_cb,
- state);
-
- /*
- * NOTE: soup_address_new can fail immediately and call our
- * callback which will delete the state.
+ state->inetaddr_id = soup_address_new (hostname,
+ port,
+ soup_socket_connect_inetaddr_cb,
+ state);
+ /* NOTE: soup_address_new could succeed immediately
+ * and call our callback, in which case state->inetaddr_id
+ * will be NULL but state->tcp_id may be set.
*/
- if (addr_id) {
- state->inetaddr_id = addr_id;
- return state;
- } else
- return NULL;
+ }
+
+ if (state->tcp_id || state->inetaddr_id)
+ return state;
+ else {
+ g_free (state);
+ return NULL;
}
}
@@ -532,7 +507,7 @@ soup_socket_unref (SoupSocket* s)
--s->ref_count;
if (s->ref_count == 0) {
- SOUP_CLOSE_SOCKET (s->sockfd);
+ close (s->sockfd);
if (s->addr) soup_address_unref (s->addr);
if (s->iochannel) g_io_channel_unref (s->iochannel);
@@ -567,7 +542,7 @@ soup_socket_get_iochannel (SoupSocket* socket)
g_return_val_if_fail (socket != NULL, NULL);
if (socket->iochannel == NULL)
- socket->iochannel = SOUP_SOCKET_IOCHANNEL_NEW (socket->sockfd);
+ socket->iochannel = g_io_channel_unix_new (socket->sockfd);
g_io_channel_ref (socket->iochannel);
@@ -631,6 +606,8 @@ soup_socket_server_new (const gint port)
SoupSocket* s;
struct sockaddr_in* sa_in;
socklen_t socklen;
+ const int on = 1;
+ gint flags;
/* Create socket */
s = g_new0 (SoupSocket, 1);
@@ -650,32 +627,21 @@ soup_socket_server_new (const gint port)
sa_in->sin_addr.s_addr = g_htonl (INADDR_ANY);
sa_in->sin_port = g_htons (port);
- /*
- * For Unix, set REUSEADDR and NONBLOCK.
- * For Windows, set NONBLOCK during accept.
- */
-#ifndef SOUP_WIN32
- {
- const int on = 1;
- gint flags;
-
- /* Set REUSEADDR so we can reuse the port */
- if (setsockopt (s->sockfd,
- SOL_SOCKET,
- SO_REUSEADDR,
- &on,
- sizeof (on)) != 0)
- g_warning("Can't set reuse on tcp socket\n");
-
- /* Get the flags (should all be 0?) */
- flags = fcntl (s->sockfd, F_GETFL, 0);
- if (flags == -1) goto SETUP_ERROR;
-
- /* Make the socket non-blocking */
- if (fcntl (s->sockfd, F_SETFL, flags | O_NONBLOCK) == -1)
- goto SETUP_ERROR;
- }
-#endif
+ /* Set REUSEADDR so we can reuse the port */
+ if (setsockopt (s->sockfd,
+ SOL_SOCKET,
+ SO_REUSEADDR,
+ &on,
+ sizeof (on)) != 0)
+ g_warning("Can't set reuse on tcp socket\n");
+
+ /* Get the flags (should all be 0?) */
+ flags = fcntl (s->sockfd, F_GETFL, 0);
+ if (flags == -1) goto SETUP_ERROR;
+
+ /* Make the socket non-blocking */
+ if (fcntl (s->sockfd, F_SETFL, flags | O_NONBLOCK) == -1)
+ goto SETUP_ERROR;
/* Bind */
if (bind (s->sockfd, &s->addr->sa, sizeof (s->addr->sa)) != 0)
@@ -691,7 +657,7 @@ soup_socket_server_new (const gint port)
return s;
SETUP_ERROR:
- SOUP_CLOSE_SOCKET (s->sockfd);
+ close (s->sockfd);
g_free (s->addr);
g_free (s);
return NULL;
diff --git a/libsoup/soup-socket.h b/libsoup/soup-socket.h
index a190ecfb..e9d942c5 100644
--- a/libsoup/soup-socket.h
+++ b/libsoup/soup-socket.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-socket.c: ronous Callback-based SOAP Request Queue.
+ * soup-socket.c: ronous Callback-based HTTP Request Queue.
*
* Authors:
* David Helder (dhelder@umich.edu)
diff --git a/libsoup/soup-socks.c b/libsoup/soup-socks.c
index 623be186..22948590 100644
--- a/libsoup/soup-socks.c
+++ b/libsoup/soup-socks.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-queue.c: Asyncronous Callback-based SOAP Request Queue.
+ * soup-queue.c: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@helixcode.com)
diff --git a/libsoup/soup-socks.h b/libsoup/soup-socks.h
index a1d84616..e602cfa0 100644
--- a/libsoup/soup-socks.h
+++ b/libsoup/soup-socks.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-socks.h: Asyncronous Callback-based SOAP Request Queue.
+ * soup-socks.h: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@helixcode.com)
diff --git a/libsoup/soup-ssl-proxy.c b/libsoup/soup-ssl-proxy.c
index 5d94066a..e161acce 100644
--- a/libsoup/soup-ssl-proxy.c
+++ b/libsoup/soup-ssl-proxy.c
@@ -12,10 +12,7 @@
#include <config.h>
#endif
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
-
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
@@ -33,6 +30,8 @@ static gint ssl_library = 0; /* -1 = fail,
1 = openssl */
static SoupSecurityPolicy ssl_security_level = SOUP_SECURITY_DOMESTIC;
+static gboolean server_mode = FALSE;
+
static GMainLoop *loop;
static void
@@ -58,7 +57,8 @@ soup_ssl_proxy_init (void)
ssl_library = -1;
#ifdef HAVE_OPENSSL_SSL_H
- if (ssl_library == -1) ssl_library = soup_openssl_init () ? 1 : -1;
+ if (ssl_library == -1)
+ ssl_library = soup_openssl_init (server_mode) ? 1 : -1;
#endif
if (ssl_library == -1) return;
@@ -115,7 +115,8 @@ soup_ssl_proxy_readwrite (GIOChannel *iochannel,
write_total += bytes_written;
}
- if (condition & (G_IO_HUP | G_IO_ERR)) goto FINISH;
+ if (condition & G_IO_ERR)
+ goto FINISH;
return TRUE;
@@ -131,6 +132,11 @@ main (int argc, char** argv)
GIOChannel *read_chan, *write_chan, *sock_chan;
int sockfd, secpol, flags;
+ if (getenv ("SOUP_PROXY_DELAY")) {
+ g_warning ("Proxy delay set: sleeping for 20 seconds");
+ sleep (20);
+ }
+
loop = g_main_new (FALSE);
env = getenv ("SOCKFD");
@@ -148,6 +154,10 @@ main (int argc, char** argv)
secpol = atoi (env);
soup_ssl_proxy_set_security_policy (secpol);
+ env = getenv ("IS_SERVER");
+ if (env)
+ server_mode = TRUE;
+
read_chan = g_io_channel_unix_new (STDIN_FILENO);
if (!read_chan)
g_error ("Unable to open STDIN");
@@ -156,13 +166,13 @@ main (int argc, char** argv)
if (!write_chan)
g_error ("Unable to open STDOUT");
- /* Block on socket write */
+ /* We use select. All fds should block. */
flags = fcntl(sockfd, F_GETFL, 0);
fcntl (sockfd, F_SETFL, flags & ~O_NONBLOCK);
-
- /* Don't block on STDIN read */
flags = fcntl(STDIN_FILENO, F_GETFL, 0);
- fcntl (STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
+ fcntl (STDIN_FILENO, F_SETFL, flags & ~O_NONBLOCK);
+ flags = fcntl(STDOUT_FILENO, F_GETFL, 0);
+ fcntl (STDOUT_FILENO, F_SETFL, flags & ~O_NONBLOCK);
sock_chan = g_io_channel_unix_new (sockfd);
sock_chan = soup_ssl_proxy_get_iochannel (sock_chan);
@@ -170,12 +180,12 @@ main (int argc, char** argv)
g_error ("Unable to establish SSL connection");
g_io_add_watch (read_chan,
- G_IO_IN | G_IO_HUP | G_IO_ERR,
+ G_IO_IN | G_IO_PRI | G_IO_ERR,
(GIOFunc) soup_ssl_proxy_readwrite,
sock_chan);
g_io_add_watch (sock_chan,
- G_IO_IN | G_IO_HUP | G_IO_ERR,
+ G_IO_IN | G_IO_PRI | G_IO_ERR,
(GIOFunc) soup_ssl_proxy_readwrite,
write_chan);
diff --git a/libsoup/soup-ssl.c b/libsoup/soup-ssl.c
index 05302cad..63adb338 100644
--- a/libsoup/soup-ssl.c
+++ b/libsoup/soup-ssl.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-queue.c: Asyncronous Callback-based SOAP Request Queue.
+ * soup-queue.c: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@ximian.com)
@@ -12,21 +12,12 @@
#include <config.h>
#endif
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
-
-#ifdef HAVE_SYS_WAIT_H
+#include <sys/types.h>
#include <sys/wait.h>
-#endif
-
-#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
-#endif
-
#include <stdlib.h>
#include <stdio.h>
-#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
@@ -34,23 +25,14 @@
#include "soup-nss.h"
#include "soup-misc.h"
-#ifdef SOUP_WIN32
-
-GIOChannel *
-soup_ssl_get_iochannel (GIOChannel *sock)
-{
- return NULL;
-}
-
-#else /* SOUP_WIN32 */
#ifdef HAVE_NSS
GIOChannel *
-soup_ssl_get_iochannel (GIOChannel *sock)
+soup_ssl_get_iochannel_real (GIOChannel *sock, SoupSSLType type)
{
g_return_val_if_fail (sock != NULL, NULL);
- return soup_nss_get_iochannel (sock);
+ return soup_nss_get_iochannel (sock, type);
}
#else /* HAVE_NSS */
@@ -63,13 +45,14 @@ soup_ssl_hup_waitpid (GIOChannel *source, GIOCondition condition, gpointer ppid)
return FALSE;
}
-GIOChannel *
-soup_ssl_get_iochannel (GIOChannel *sock)
+static GIOChannel *
+soup_ssl_get_iochannel_real (GIOChannel *sock, SoupSSLType type)
{
GIOChannel *new_chan;
int sock_fd;
int pid;
int pair[2], flags;
+ const char *cert_file, *key_file;
g_return_val_if_fail (sock != NULL, NULL);
@@ -101,6 +84,31 @@ soup_ssl_get_iochannel (GIOChannel *sock)
putenv (g_strdup_printf ("SECURITY_POLICY=%d",
soup_get_security_policy ()));
+ if (type == SOUP_SSL_TYPE_SERVER)
+ putenv ("IS_SERVER=1");
+
+ if (soup_get_ssl_ca_file ()) {
+ putenv (g_strdup_printf ("HTTPS_CA_FILE=%s",
+ soup_get_ssl_ca_file ()));
+ }
+
+ if (soup_get_ssl_ca_dir ()) {
+ putenv (g_strdup_printf ("HTTPS_CA_DIR=%s",
+ soup_get_ssl_ca_dir ()));
+ }
+
+ soup_get_ssl_cert_files (&cert_file, &key_file);
+
+ if (cert_file) {
+ putenv (g_strdup_printf ("HTTPS_CERT_FILE=%s",
+ cert_file));
+ }
+
+ if (key_file) {
+ putenv (g_strdup_printf ("HTTPS_KEY_FILE=%s",
+ key_file));
+ }
+
execl (BINDIR G_DIR_SEPARATOR_S SSL_PROXY_NAME,
BINDIR G_DIR_SEPARATOR_S SSL_PROXY_NAME,
NULL);
@@ -116,11 +124,9 @@ soup_ssl_get_iochannel (GIOChannel *sock)
fcntl (pair [1], F_SETFL, flags | O_NONBLOCK);
new_chan = g_io_channel_unix_new (pair [1]);
- g_io_add_watch (new_chan, G_IO_HUP,
+ g_io_add_watch (new_chan, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
soup_ssl_hup_waitpid, GINT_TO_POINTER (pid));
- /* FIXME: Why is this needed?? */
- g_io_channel_ref (new_chan);
return new_chan;
ERROR:
@@ -132,4 +138,15 @@ soup_ssl_get_iochannel (GIOChannel *sock)
}
#endif /* HAVE_NSS */
-#endif /* SOUP_WIN32 */
+
+GIOChannel *
+soup_ssl_get_iochannel (GIOChannel *sock)
+{
+ return soup_ssl_get_iochannel_real (sock, SOUP_SSL_TYPE_CLIENT);
+}
+
+GIOChannel *
+soup_ssl_get_server_iochannel (GIOChannel *sock)
+{
+ return soup_ssl_get_iochannel_real (sock, SOUP_SSL_TYPE_SERVER);
+}
diff --git a/libsoup/soup-ssl.h b/libsoup/soup-ssl.h
index 0cfd438b..9e398e48 100644
--- a/libsoup/soup-ssl.h
+++ b/libsoup/soup-ssl.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-queue.c: Asyncronous Callback-based SOAP Request Queue.
+ * soup-queue.c: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@helixcode.com)
@@ -13,6 +13,12 @@
#include <glib.h>
+typedef enum {
+ SOUP_SSL_TYPE_CLIENT = 0,
+ SOUP_SSL_TYPE_SERVER
+} SoupSSLType;
+
GIOChannel *soup_ssl_get_iochannel (GIOChannel *sock);
+GIOChannel *soup_ssl_get_server_iochannel (GIOChannel *sock);
#endif /* SOUP_SSL_H */
diff --git a/libsoup/soup-transfer.c b/libsoup/soup-transfer.c
index 332cd7c0..fdbc4562 100644
--- a/libsoup/soup-transfer.c
+++ b/libsoup/soup-transfer.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-queue.c: Asyncronous Callback-based SOAP Request Queue.
+ * soup-queue.c: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@helixcode.com)
@@ -50,7 +50,7 @@ DUMP_WRITE (guchar *data, gint bytes_written)
typedef struct {
/*
- * Length remaining to be downloaded of the current chunk data.
+ * Length of the current chunk data.
*/
guint len;
@@ -219,34 +219,6 @@ remove_block_at_index (GByteArray *arr, gint offset, gint length)
g_byte_array_set_size (arr, arr->len - length);
}
-/*
- * Count number of hex digits, and convert to decimal. Store number of hex
- * digits read in @width.
- */
-static gint
-decode_hex (const gchar *src, gint *width)
-{
- gint new_len = 0, j;
-
- *width = 0;
-
- while (isxdigit (*src)) {
- (*width)++;
- src++;
- }
- src -= *width;
-
- for (j = *width - 1; j + 1; j--) {
- if (isdigit (*src))
- new_len += (*src - 0x30) << (4*j);
- else
- new_len += (tolower (*src) - 0x57) << (4*j);
- src++;
- }
-
- return new_len;
-}
-
static gboolean
decode_chunk (SoupTransferChunkState *s,
GByteArray *arr,
@@ -259,73 +231,68 @@ decode_chunk (SoupTransferChunkState *s,
while (TRUE) {
gint new_len = 0;
gint len = 0;
- gchar *i = &arr->data [s->idx + s->len];
-
- /*
- * Not enough data to finish the chunk (and the smallest
- * possible next chunk header), break
- */
- if (s->idx + s->len + 5 > arr->len)
- break;
- /*
- * Check for end of chunk header, otherwise break. Avoid
- * trailing \r\n from previous chunk body if this is not the
- * opening chunk.
- */
if (s->len) {
- if (soup_substring_index (
- i + 2,
- arr->len - s->idx - s->len - 2,
- "\r\n") <= 0)
- break;
- } else if (soup_substring_index (arr->data,
- arr->len,
- "\r\n") <= 0)
+ /* We're in the middle of a chunk. If we don't
+ * have the entire chunk and the trailing CRLF
+ * yet, read more.
+ */
+ if (s->idx + s->len + 2 > arr->len)
break;
- /*
- * Remove trailing \r\n after previous chunk body
+ /*
+ * Increment datalen and s->idx, and remove
+ * the trailing CRLF.
+ */
+ s->idx += s->len;
+ *datalen += s->len;
+ remove_block_at_index (arr, s->idx, 2);
+
+ /*
+ * Ready for the next chunk.
+ */
+ s->len = 0;
+ }
+
+ /*
+ * We're at the start of a new chunk. If we don't have
+ * the complete chunk header, wait for more.
*/
- if (s->len)
- remove_block_at_index (arr, s->idx + s->len, 2);
+ len = soup_substring_index (&arr->data [s->idx],
+ arr->len - s->idx,
+ "\r\n");
+ if (len < 0)
+ break;
+ len += 2;
- new_len = decode_hex (i, &len);
+ new_len = strtol (&arr->data [s->idx], NULL, 16);
g_assert (new_len >= 0);
- /*
- * Previous chunk is now processed, add its length to index and
- * datalen.
+ /*
+ * If this is the final (zero-length) chunk, we need
+ * to have all of the trailing entity headers as well.
*/
- s->idx += s->len;
- *datalen += s->len;
+ if (new_len == 0) {
+ len = soup_substring_index (&arr->data [s->idx],
+ arr->len - s->idx,
+ "\r\n\r\n");
+ if (len < 0)
+ break;
- /*
- * Update length for next chunk's size
- */
- s->len = new_len;
-
- /*
- * FIXME: Add entity headers we find here to
- * req->response_headers.
- */
- len += soup_substring_index (&arr->data [s->idx + len],
- arr->len - s->idx - len,
- "\r\n");
+ /*
+ * FIXME: Add entity headers we find here to
+ * req->response_headers.
+ */
- /*
- * Zero-length chunk closes transfer. Include final \r\n after
- * empty chunk.
- */
- if (s->len == 0) {
- len += 2;
+ len += 4;
ret = TRUE;
}
/*
- * Remove hexified length, entity headers, and trailing \r\n
+ * Remove chunk header and get ready for chunk data.
*/
- remove_block_at_index (arr, s->idx, len + 2);
+ remove_block_at_index (arr, s->idx, len);
+ s->len = new_len;
}
return ret;
@@ -378,7 +345,8 @@ read_chunk (SoupReader *r, gboolean *cancelled)
if (*cancelled) goto CANCELLED;
/*
- * If overwrite, remove datalen worth of data from start of buffer
+ * If overwrite, remove already-processed data from start
+ * of buffer
*/
if (r->overwrite_chunks) {
remove_block_at_index (arr, 0, s->idx);
diff --git a/libsoup/soup-transfer.h b/libsoup/soup-transfer.h
index ba0d6af1..ab556b1d 100644
--- a/libsoup/soup-transfer.h
+++ b/libsoup/soup-transfer.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup-queue.c: Asyncronous Callback-based SOAP Request Queue.
+ * soup-queue.c: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@helixcode.com)
diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c
index 970e2b4f..8d11f467 100644
--- a/libsoup/soup-uri.c
+++ b/libsoup/soup-uri.c
@@ -58,6 +58,7 @@ SoupKnownProtocols known_protocols [] = {
{ SOUP_PROTOCOL_SMTP, "mailto:", 25 },
{ SOUP_PROTOCOL_SOCKS4, "socks4://", -1 },
{ SOUP_PROTOCOL_SOCKS5, "socks5://", -1 },
+ { SOUP_PROTOCOL_FILE, "file://", -1 },
{ 0 }
};
@@ -325,7 +326,10 @@ soup_uri_new (const gchar* uri_string)
}
/* Must have a protocol */
- if (!g_uri->protocol) return NULL;
+ if (!g_uri->protocol) {
+ g_free (g_uri);
+ return NULL;
+ }
/* If there is an @ sign, look for user, authmech, and
* password before it.
diff --git a/libsoup/soup-uri.h b/libsoup/soup-uri.h
index f7d297a4..c83952bf 100644
--- a/libsoup/soup-uri.h
+++ b/libsoup/soup-uri.h
@@ -34,7 +34,8 @@ typedef enum {
SOUP_PROTOCOL_HTTPS,
SOUP_PROTOCOL_SMTP,
SOUP_PROTOCOL_SOCKS4,
- SOUP_PROTOCOL_SOCKS5
+ SOUP_PROTOCOL_SOCKS5,
+ SOUP_PROTOCOL_FILE
} SoupProtocol;
typedef struct {
diff --git a/libsoup/soup.h b/libsoup/soup.h
index bda95f1f..f5fc25e0 100644
--- a/libsoup/soup.h
+++ b/libsoup/soup.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * soup.h: Asyncronous Callback-based SOAP Request Queue.
+ * soup.h: Asyncronous Callback-based HTTP Request Queue.
*
* Authors:
* Alex Graveley (alex@helixcode.com)
@@ -16,14 +16,8 @@ extern "C" {
#endif
#include <libsoup/soup-context.h>
-#include <libsoup/soup-dav.h>
-#include <libsoup/soup-dav-server.h>
#include <libsoup/soup-message.h>
#include <libsoup/soup-misc.h>
-#include <libsoup/soup-fault.h>
-#include <libsoup/soup-env.h>
-#include <libsoup/soup-parser.h>
-#include <libsoup/soup-serializer.h>
#include <libsoup/soup-socket.h>
#include <libsoup/soup-uri.h>