summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoe <joe@61a7d7f5-40b7-0310-9c16-bb0ea8cb1845>2010-09-22 19:33:36 +0000
committerjoe <joe@61a7d7f5-40b7-0310-9c16-bb0ea8cb1845>2010-09-22 19:33:36 +0000
commit2e1d714cd8106eb397a4aa48866cbb34353b78f3 (patch)
treef3eb4464ce5a7114982ec5767950b158f4c832a1
parentda757cba8a2a74ea0d0f7ac325fa6bc75f01706e (diff)
downloadneon-2e1d714cd8106eb397a4aa48866cbb34353b78f3.tar.gz
Merge r1801 from trunk:
* src/ne_request.c (body_fd_send): Handle read() errors; thanks to Lou Montulli. * test/request.c (serve_mirror, send_length): Add test case. * test/Makefile.in (foobar.txt): Create test file. git-svn-id: http://svn.webdav.org/repos/projects/neon/branches/0.29.x@1807 61a7d7f5-40b7-0310-9c16-bb0ea8cb1845
-rw-r--r--src/ne_request.c25
-rw-r--r--test/Makefile.in5
-rw-r--r--test/request.c63
3 files changed, 89 insertions, 4 deletions
diff --git a/src/ne_request.c b/src/ne_request.c
index 8cab832..ea43f3a 100644
--- a/src/ne_request.c
+++ b/src/ne_request.c
@@ -1,6 +1,6 @@
/*
HTTP request/response handling
- Copyright (C) 1999-2009, Joe Orton <joe@manyfish.co.uk>
+ Copyright (C) 1999-2010, 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
@@ -284,6 +284,8 @@ static ssize_t body_fd_send(void *userdata, char *buffer, size_t count)
ne_request *req = userdata;
if (count) {
+ ssize_t ret;
+
if (req->body.file.remain == 0)
return 0;
@@ -292,7 +294,26 @@ static ssize_t body_fd_send(void *userdata, char *buffer, size_t count)
* and 64-bit off64_t: */
if ((ne_off_t)count > req->body.file.remain)
count = (size_t)req->body.file.remain;
- return read(req->body.file.fd, buffer, count);
+
+ ret = read(req->body.file.fd, buffer, count);
+ if (ret > 0) {
+ req->body.file.remain -= ret;
+ return ret;
+ }
+ else if (ret == 0) {
+ ne_set_error(req->session,
+ _("Premature EOF in request body file"));
+ }
+ else if (ret < 0) {
+ char err[200];
+ int errnum = errno;
+
+ ne_set_error(req->session,
+ _("Failed reading request body file: %s"),
+ ne_strerror(errnum, err, sizeof err));
+ }
+
+ return -1;
} else {
ne_off_t newoff;
diff --git a/test/Makefile.in b/test/Makefile.in
index 8617a3e..d94a02d 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -18,7 +18,7 @@ LIBS = $(LIBTEST)
CC = @CC@
OPENSSL = @OPENSSL@
-HELPERS = @HELPERS@
+HELPERS = @HELPERS@ foobar.txt
BASIC_TESTS = uri-tests util-tests string-tests socket \
session request auth basic stubs redirect
ZLIB_TESTS = compress
@@ -125,6 +125,9 @@ empty.gz:
random.txt: $(NEWS)
cat $(NEWS) > $@
+foobar.txt:
+ echo foobar > $@
+
# Dummy target to create the CA keys etc. makekeys stderr is redirected
# since it changes for every invocation; not helpful for regression
# testing.
diff --git a/test/request.c b/test/request.c
index 55f9c8d..0cb4c8b 100644
--- a/test/request.c
+++ b/test/request.c
@@ -1,6 +1,6 @@
/*
HTTP request handling tests
- Copyright (C) 2001-2009, Joe Orton <joe@manyfish.co.uk>
+ Copyright (C) 2001-2010, 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
@@ -31,6 +31,7 @@
#include <unistd.h>
#endif
#include <fcntl.h>
+#include <errno.h>
#include "ne_request.h"
#include "ne_socket.h"
@@ -2236,6 +2237,65 @@ static int socks_v4_proxy(void)
return await_server();
}
+/* Server function which serves the request body back as the response
+ * body. */
+static int serve_mirror(ne_socket *sock, void *userdata)
+{
+ char response[1024];
+
+ CALL(discard_request(sock));
+
+ ONV(clength == 0 || (size_t)clength > sizeof buffer,
+ ("C-L out of bounds: %d", clength));
+
+ ONV(ne_sock_fullread(sock, buffer, clength),
+ ("read failed: %s", ne_sock_error(sock)));
+
+ ne_snprintf(response, sizeof response,
+ "HTTP/1.0 200 OK\r\n"
+ "Content-Length: %d\r\n"
+ "\r\n", clength);
+
+ ONN("send response header failed",
+ server_send(sock, response, strlen(response)));
+
+ ONN("send response body failed",
+ server_send(sock, buffer, clength));
+
+ ONV(ne_sock_read(sock, buffer, 1) != NE_SOCK_CLOSED,
+ ("client sent data after request: %c", buffer[0]));
+
+ return OK;
+}
+
+/* Test for ne_set_request_body_fd() bug in <= 0.29.3. */
+static int send_length(void)
+{
+ ne_session *sess;
+ ne_request *req;
+ int fd;
+ ne_buffer *buf = ne_buffer_create();
+
+ fd = open("foobar.txt", O_RDONLY);
+ ONV(fd < 0, ("open random.txt failed: %s", strerror(errno)));
+
+ CALL(make_session(&sess, serve_mirror, NULL));
+
+ req = ne_request_create(sess, "GET", "/foo");
+
+ ne_set_request_body_fd(req, fd, 0, 3);
+ ne_add_response_body_reader(req, ne_accept_2xx, collector, buf);
+
+ ONREQ(ne_request_dispatch(req));
+
+ ONCMP("foo", buf->data, "response body", "match");
+
+ ne_request_destroy(req);
+ ne_session_destroy(sess);
+ close(fd);
+ return await_server();
+}
+
/* TODO: test that ne_set_notifier(, NULL, NULL) DTRT too. */
ne_test tests[] = {
@@ -2327,5 +2387,6 @@ ne_test tests[] = {
T(addrlist),
T(socks_proxy),
T(socks_v4_proxy),
+ T(send_length),
T(NULL)
};