summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS9
-rw-r--r--macros/neon.m46
-rw-r--r--src/ne_auth.c4
-rw-r--r--src/ne_basic.c12
-rw-r--r--src/ne_compress.c30
-rw-r--r--src/ne_openssl.c2
-rw-r--r--src/ne_private.h3
-rw-r--r--src/ne_request.c16
-rw-r--r--src/ne_xml.c2
-rw-r--r--test/compress.c60
10 files changed, 119 insertions, 25 deletions
diff --git a/NEWS b/NEWS
index 5463aab..572d5d3 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,12 @@
+Changes in release 0.25.1:
+* ne_get_content_type(): fix cases where the charset field was not set
+ to NULL after successful return (Johannes Schneider)
+* Compressed response handling fixes:
+ - fix double invocation of reader callback with len=0
+ - fix cases where the reader callback return value was ignored
+* Cache the new SSL session if the old one was expired (Robert Eiglmaier)
+* Win32: fix build issues.
+
Changes in release 0.25.0:
* New interfaces:
- ne_get_response_header() replaces ne_add_response_header_handler
diff --git a/macros/neon.m4 b/macros/neon.m4
index a19c1e7..aae2ea0 100644
--- a/macros/neon.m4
+++ b/macros/neon.m4
@@ -136,9 +136,9 @@ AC_DEFUN([NE_VERSIONS_BUNDLED], [
# Define the current versions.
NE_VERSION_MAJOR=0
-NE_VERSION_MINOR=26
-NE_VERSION_PATCH=0
-NE_VERSION_TAG=-dev
+NE_VERSION_MINOR=25
+NE_VERSION_PATCH=1
+NE_VERSION_TAG=
# libtool library interface versioning. Release policy dictates that
# for neon 0.x.y, each x brings an incompatible interface change, and
diff --git a/src/ne_auth.c b/src/ne_auth.c
index ff2e280..480968c 100644
--- a/src/ne_auth.c
+++ b/src/ne_auth.c
@@ -1210,8 +1210,6 @@ static void ah_pre_send(ne_request *r, void *cookie, ne_buffer *request)
}
-#define SAFELY(x) ((x) != NULL?(x):"null")
-
static int ah_post_send(ne_request *req, void *cookie, const ne_status *status)
{
auth_session *sess = cookie;
@@ -1242,7 +1240,7 @@ static int ah_post_send(ne_request *req, void *cookie, const ne_status *status)
NE_DEBUG(NE_DBG_HTTPAUTH,
"ah_post_send (#%d), code is %d (want %d), %s is %s\n",
sess->attempt, status->code, sess->spec->status_code,
- sess->spec->resp_hdr, auth_hdr);
+ sess->spec->resp_hdr, auth_hdr ? auth_hdr : "(none)");
if (auth_info_hdr && sess->scheme == auth_scheme_digest) {
if (verify_digest_response(areq, sess, auth_info_hdr)) {
NE_DEBUG(NE_DBG_HTTPAUTH, "Response authentication invalid.\n");
diff --git a/src/ne_basic.c b/src/ne_basic.c
index de210e9..e50138c 100644
--- a/src/ne_basic.c
+++ b/src/ne_basic.c
@@ -239,20 +239,18 @@ int ne_get_content_type(ne_request *req, ne_content_type *ct)
return -1;
}
- ct->value = ne_strdup(value);
-
- stype = strchr(ct->value, '/');
+ ct->type = ct->value = ne_strdup(value);
+ stype = strchr(ct->value, '/');
*stype++ = '\0';
- ct->type = ct->value;
ct->charset = NULL;
sep = strchr(stype, ';');
if (sep) {
char *tok;
- /* look for the charset parameter. TODO; probably better to
- * hand-carve a parser than use ne_token/strstr/shave here. */
+
+ /* Look for the charset parameter: */
*sep++ = '\0';
do {
tok = ne_qtoken(&sep, ';', "\"\'");
@@ -270,7 +268,7 @@ int ne_get_content_type(ne_request *req, ne_content_type *ct)
ct->subtype = ne_shave(stype, " \t");
if (ct->charset == NULL && strcasecmp(ct->type, "text") == 0) {
- /* 3280§3.1: text/xml without charset implies us-ascii. */
+ /* 3023§3.1: text/xml without charset implies us-ascii. */
if (strcasecmp(ct->subtype, "xml") == 0)
ct->charset = "us-ascii";
/* 2616§3.7.1: subtypes of text/ default to charset ISO-8859-1. */
diff --git a/src/ne_compress.c b/src/ne_compress.c
index b36d384..bd614ff 100644
--- a/src/ne_compress.c
+++ b/src/ne_compress.c
@@ -1,6 +1,6 @@
/*
Handling of compressed HTTP responses
- Copyright (C) 2001-2004, Joe Orton <joe@manyfish.co.uk>
+ Copyright (C) 2001-2005, Joe Orton <joe@manyfish.co.uk>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -33,6 +33,8 @@
#include "ne_utils.h"
#include "ne_i18n.h"
+#include "ne_private.h"
+
#ifdef NE_HAVE_ZLIB
#include <zlib.h>
@@ -152,8 +154,6 @@ static int process_footer(ne_decompress *ctx,
uLong crc = BUF2UINT(ctx->footer) & 0xFFFFFFFF;
if (crc == ctx->checksum) {
ctx->state = NE_Z_FINISHED;
- /* reader requires a size=0 call at end-of-response */
- ctx->reader(ctx->userdata, NULL, 0);
NE_DEBUG(NE_DBG_HTTP, "compress: End of response; checksum match.\n");
} else {
NE_DEBUG(NE_DBG_HTTP, "compress: End of response; checksum mismatch: "
@@ -218,7 +218,9 @@ static int do_inflate(ne_decompress *ctx, const char *buf, size_t len)
/* pass on the inflated data, if any */
if (ctx->zstr.total_out > 0) {
- ctx->reader(ctx->userdata, ctx->outbuf, ctx->zstr.total_out);
+ int rret = ctx->reader(ctx->userdata, ctx->outbuf,
+ ctx->zstr.total_out);
+ if (rret) return rret;
}
} while (ret == Z_OK && ctx->zstr.avail_in > 0);
@@ -372,6 +374,21 @@ static int gz_reader(void *ud, const char *buf, size_t len)
return 0;
}
+/* Prepare for a compressed response */
+static void gz_pre_send(ne_request *r, void *ud, ne_buffer *req)
+{
+ ne_decompress *ctx = ud;
+
+ NE_DEBUG(NE_DBG_HTTP, "compress: Initialization.\n");
+
+ /* (Re-)Initialize the context */
+ ctx->state = NE_Z_BEFORE_DATA;
+ if (ctx->zstrinit) inflateEnd(&ctx->zstr);
+ ctx->zstrinit = 0;
+ ctx->hdrcount = ctx->footcount = 0;
+ ctx->checksum = crc32(0L, Z_NULL, 0);
+}
+
void ne_decompress_destroy(ne_decompress *ctx)
{
if (ctx->zstrinit)
@@ -398,15 +415,14 @@ ne_decompress *ne_decompress_reader(ne_request *req, ne_accept_response acpt,
ne_add_response_body_reader(req, gz_acceptor, gz_reader, ctx);
- ctx->state = NE_Z_BEFORE_DATA;
ctx->reader = rdr;
ctx->userdata = userdata;
ctx->session = ne_get_session(req);
ctx->request = req;
- /* initialize the checksum. */
- ctx->checksum = crc32(0L, Z_NULL, 0);
ctx->acceptor = acpt;
+ ne__reqhook_pre_send(req, gz_pre_send, ctx);
+
return ctx;
}
diff --git a/src/ne_openssl.c b/src/ne_openssl.c
index 984626b..f997ef9 100644
--- a/src/ne_openssl.c
+++ b/src/ne_openssl.c
@@ -302,7 +302,7 @@ static int check_identity(const char *hostname, X509 *cert, char **identity)
} while (idx >= 0);
if (lastidx < 0) {
- /* no commonName attributes at all. */
+ /* no commonNmae attributes at all. */
ne_buffer_destroy(cname);
return -1;
}
diff --git a/src/ne_private.h b/src/ne_private.h
index a0c4eb0..f5ef345 100644
--- a/src/ne_private.h
+++ b/src/ne_private.h
@@ -114,4 +114,7 @@ typedef int (*ne_push_fn)(void *userdata, const char *buf, size_t count);
/* Do the SSL negotiation. */
int ne__negotiate_ssl(ne_request *req);
+/* Hack to fix ne_compress layer problems */
+void ne__reqhook_pre_send(ne_request *sess, ne_pre_send_fn fn, void *userdata);
+
#endif /* HTTP_PRIVATE_H */
diff --git a/src/ne_request.c b/src/ne_request.c
index b98a53b..01f4fa2 100644
--- a/src/ne_request.c
+++ b/src/ne_request.c
@@ -171,7 +171,7 @@ struct ne_request_s {
ne_off_t progress; /* number of bytes read of response */
} resp;
- struct hook *private;
+ struct hook *private, *pre_send_hooks;
/* response header fields */
struct field *response_headers[HH_HASHSIZE];
@@ -322,6 +322,12 @@ void ne_hook_destroy_session(ne_session *sess,
ADD_HOOK(sess->destroy_sess_hooks, fn, userdata);
}
+/* Hack to fix ne_compress layer problems */
+void ne__reqhook_pre_send(ne_request *req, ne_pre_send_fn fn, void *userdata)
+{
+ ADD_HOOK(req->pre_send_hooks, fn, userdata);
+}
+
void ne_set_session_private(ne_session *sess, const char *id, void *userdata)
{
add_hook(&sess->private, id, NULL, userdata);
@@ -734,6 +740,10 @@ void ne_request_destroy(ne_request *req)
next_hk = hk->next;
ne_free(hk);
}
+ for (hk = req->pre_send_hooks; hk; hk = next_hk) {
+ next_hk = hk->next;
+ ne_free(hk);
+ }
if (req->status.reason_phrase)
ne_free(req->status.reason_phrase);
@@ -887,6 +897,10 @@ static ne_buffer *build_request(ne_request *req)
ne_pre_send_fn fn = (ne_pre_send_fn)hk->fn;
fn(req, hk->userdata, buf);
}
+ for (hk = req->pre_send_hooks; hk!=NULL; hk = hk->next) {
+ ne_pre_send_fn fn = (ne_pre_send_fn)hk->fn;
+ fn(req, hk->userdata, buf);
+ }
ne_buffer_append(buf, "\r\n", 2);
return buf;
diff --git a/src/ne_xml.c b/src/ne_xml.c
index 16c8480..cf6b1ab 100644
--- a/src/ne_xml.c
+++ b/src/ne_xml.c
@@ -393,7 +393,7 @@ static void end_element(void *userdata, const ne_xml_char *name)
}
}
- NE_DEBUG(NE_DBG_XMLPARSE, "XML: end-element (%d, {%s, %s})\n",
+ NE_DEBUG(NE_DBG_XML, "XML: end-element (%d, {%s, %s})\n",
elm->state, elm->nspace, elm->name);
/* move back up the tree */
diff --git a/test/compress.c b/test/compress.c
index f40db15..8eadf23 100644
--- a/test/compress.c
+++ b/test/compress.c
@@ -1,6 +1,6 @@
/*
tests for compressed response handling.
- Copyright (C) 2001-2004, Joe Orton <joe@manyfish.co.uk>
+ Copyright (C) 2001-2005, Joe Orton <joe@manyfish.co.uk>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -58,6 +58,14 @@ static int reader(void *ud, const char *block, size_t len)
if (failed == f_mismatch) return -1;
+ /* catch multiple len == 0 call as issued by 0.25.0 only: */
+ if (failed == f_complete) {
+ NE_DEBUG(NE_DBG_HTTP, "reader: called after complete, len=%d\n",
+ (int)len);
+ failed = f_mismatch;
+ return -1;
+ }
+
if (failed == f_partial && len == 0) {
if (b->len != 0) {
NE_DEBUG(NE_DBG_HTTP, "reader: got length %d at EOF\n",
@@ -357,6 +365,7 @@ static int retry_accept(void *ud, ne_request *req, const ne_status *st)
}
expect->len = 5;
+ failed = f_partial; /* reset the state */
return 1;
}
@@ -369,6 +378,52 @@ static int retry_compress(void)
return retry_compress_helper(retry_accept, &resp, &expect);
}
+#define READER_ABORT_ERR "reader_abort error string"
+
+static int reader_abort(void *ud, const char *buf, size_t len)
+{
+ ne_session *sess = ud;
+ ne_set_error(sess, READER_ABORT_ERR);
+ return len;
+}
+
+/* check that a callback abort does abort the response */
+static int compress_abort(void)
+{
+ ne_session *sess;
+ ne_request *req;
+ struct serve_file_args sfargs;
+ ne_decompress *dc;
+ int ret;
+
+ sfargs.fname = "file1.gz";
+ sfargs.headers = "Content-Encoding: gzip\r\n";
+ sfargs.chunks = 0;
+
+ CALL(make_session(&sess, serve_file, &sfargs));
+
+ req = ne_request_create(sess, "GET", "/abort");
+
+ dc = ne_decompress_reader(req, ne_accept_2xx, reader_abort, sess);
+
+ ret = ne_request_dispatch(req);
+
+ reap_server();
+
+ ONN("request was not aborted", ret != NE_ERROR);
+ ONV(strcmp(ne_get_error(sess), READER_ABORT_ERR),
+ ("session error was %s not %s",
+ ne_get_error(sess), READER_ABORT_ERR));
+
+ reap_server();
+ ne_decompress_destroy(dc);
+ ne_request_destroy(req);
+ ne_session_destroy(sess);
+
+ return OK;
+
+}
+
ne_test tests[] = {
T_LEAKY(init),
T(not_compressed),
@@ -389,6 +444,7 @@ ne_test tests[] = {
T(chunked_10b),
T(chunked_10b_wn),
T(retry_notcompress),
- T_XFAIL(retry_compress),
+ T(retry_compress),
+ T(compress_abort),
T(NULL)
};