diff options
author | joe <joe@61a7d7f5-40b7-0310-9c16-bb0ea8cb1845> | 2004-12-30 11:55:13 +0000 |
---|---|---|
committer | joe <joe@61a7d7f5-40b7-0310-9c16-bb0ea8cb1845> | 2004-12-30 11:55:13 +0000 |
commit | 4bbd032fc525b0185c4bfe3f73395ab857e507e8 (patch) | |
tree | 9b0191b7f4e0b47888322184f0f9e4608d400ee2 /src/ne_basic.c | |
parent | 5313dc13b9ed83dc429edc0fcec68980254ac91b (diff) | |
download | neon-4bbd032fc525b0185c4bfe3f73395ab857e507e8.tar.gz |
Remove callback-based response header handling in favour of
ne_get_response_header interface:
* src/ne_request.h (ne_get_response_header): New function, replacing
ne_add_response_header_handler and ne_add_response_header_catcher.
* src/ne_request.c (struct header_handler): Remove.
(struct field): Add.
(struct ne_request_s): Store a hash of header fields rather than
a hash of callbacks.
(te_hdr_handler, connection_hdr_handler, clength_hdr_handler,
ne_add_response_header_catcher, ne_add_response_header_handler,
ne_duplicate_header, ne_handle_numeric_header):
Remove functions.
(get_response_header_hv, ne_get_response_header,
add_response_header, remove_response_header): New functions.
(ne_request_create): Don't register the callbacks.
(read_response_headers): Call add_response_header for each
field.
(ne_begin_request): Move handling of Connection, T-E and C-L headers
here. Comply with 2616/14.10 w.r.t. Connection header handling in
HTTP/1.0 responses.
(ne_request_dispatch): Use ne_discard_response (unrelated).
* src/ne_redirect.c (struct redirect): Remove location field.
(post_send): Adjust to retrieve location header here.
* src/ne_basic.h (ne_get_content_type): Replaces
ne_content_type_handler.
* src/ne_basic.c (dispatch_to_fd): New function.
(get_to_fd, get_lastmodified, clength_hdr_handler, accept_206,
content_range_hdr_handler): Remove functions.
(ne_getmodtime): Adjust to use ne_get_response_header.
(ne_get_range, ne_get, ne_post): Adjust to use dispatch_to_fd.
(ne_get_content_type): Adjust for new API, use ne_get_response_header.
(parse_dav_header, ne_options): Adjust to use ne_get_response_header.
* src/ne_compress.c (struct ne_decompress_s): Add ne_request * field,
remove enchdr field.
(gz_reader): Retrieve C-E header on demand, here.
(ne_decompress_reader, ne_decompress_destroy): Remove C-E response
header duplication.
* src/ne_auth.c (auth_request): Remove auth_hdr, auth_info_hdr
fields.
(ah_collect_header): Remove function.
(ah_create, ah_destroy): Remove response-header callback handling.
(ah_post_send): Retrieve -Authenticate header here; correctly handle
the broken proxy which sends a 401 in response to CONNECT.
* src/ne_locks.c (lk_startelm): Retrieve Lock-Token header here.
(get_ltoken_hdr): Remove function.
(ne_lock, ne_lock_refresh): Remove response-header handling.
* test/basic.c (content_type): Test new interface.
* test/request.c (expect_header_value): Adjust to accept NULL value,
use ne_get_response_header interface.
(multi_header): Test new ne_get_response_header multi-header handling.
(multi_header2, strip_http10_connhdr, strip_http10_connhdr2): New
tests.
git-svn-id: http://svn.webdav.org/repos/projects/neon/trunk@367 61a7d7f5-40b7-0310-9c16-bb0ea8cb1845
Diffstat (limited to 'src/ne_basic.c')
-rw-r--r-- | src/ne_basic.c | 226 |
1 files changed, 66 insertions, 160 deletions
diff --git a/src/ne_basic.c b/src/ne_basic.c index 0038778..f9cc348 100644 --- a/src/ne_basic.c +++ b/src/ne_basic.c @@ -50,27 +50,21 @@ #include "ne_dates.h" #include "ne_i18n.h" -/* Header parser to retrieve Last-Modified date */ -static void get_lastmodified(void *userdata, const char *value) { - time_t *modtime = userdata; - *modtime = ne_httpdate_parse(value); -} - int ne_getmodtime(ne_session *sess, const char *uri, time_t *modtime) { ne_request *req = ne_request_create(sess, "HEAD", uri); + const char *value; int ret; - ne_add_response_header_handler(req, "Last-Modified", get_lastmodified, - modtime); - - *modtime = -1; - ret = ne_request_dispatch(req); + value = ne_get_response_header(req, "Last-Modified"); + if (ret == NE_OK && ne_get_status(req)->klass != 2) { *modtime = -1; ret = NE_ERROR; + } else if (value) { + *modtime = ne_httpdate_parse(value); } ne_request_destroy(req); @@ -113,126 +107,70 @@ int ne_put(ne_session *sess, const char *uri, int fd) return ret; } -struct get_context { - int error; - ne_session *session; - off_t total; - int fd; /* used in get_to_fd */ - ne_content_range *range; -}; - -static int get_to_fd(void *userdata, const char *block, size_t length) +/* Dispatch a GET request REQ, writing the response body to FD fd. If + * RANGE is non-NULL, then it is the value of the Range request + * header, e.g. "bytes=1-5". Returns an NE_* error code. */ +static int dispatch_to_fd(ne_request *req, int fd, const char *range) { - struct get_context *ctx = userdata; - ssize_t ret; - - if (ctx->error) { - return -1; - } - - if (!ctx->error) { - while (length > 0) { - ret = write(ctx->fd, block, length); - if (ret < 0) { - char err[200]; - ne_strerror(errno, err, sizeof err); - ne_set_error(ctx->session, _("Could not write to file: %s"), - err); - return -1; - } else { - length -= ret; - block += ret; - } - } - } - - return 0; -} - -static int accept_206(void *ud, ne_request *req, const ne_status *st) -{ - return (st->code == 206); -} - -static void clength_hdr_handler(void *ud, const char *value) -{ - struct get_context *ctx = ud; - off_t len = strtol(value, NULL, 10); - - if (ctx->range->end == -1) { - ctx->range->end = ctx->range->start + len - 1; - ctx->range->total = len; - } - else if (len != ctx->total) { - NE_DEBUG(NE_DBG_HTTP, - "Expecting %" NE_FMT_OFF_T " bytes, " - "got entity of length %" NE_FMT_OFF_T "\n", - ctx->total, len); - ne_set_error(ctx->session, _("Response not of expected length")); - ctx->error = 1; - } -} - -static void content_range_hdr_handler(void *ud, const char *value) -{ - struct get_context *ctx = ud; + ne_session *const sess = ne_get_session(req); + const ne_status *const st = ne_get_status(req); + int ret; - if (strncmp(value, "bytes ", 6) != 0) { - ne_set_error(ctx->session, ("Response range using unrecognized unit")); - ctx->error = 1; - } + do { + const char *value; + + ret = ne_begin_request(req); + if (ret != NE_OK) break; + + value = ne_get_response_header(req, "Content-Range"); + + /* For a 206 response, check that a Content-Range header is + * given which matches the Range request header. */ + if (range && st->code == 206 + && (value == NULL || strncmp(value, "bytes ", 6) != 0 + || strcmp(range + 6, value + 6))) { + ne_set_error(sess, _("Response did not include requested range")); + return NE_ERROR; + } + + if ((range && st->code == 206) || (!range && st->klass == 2)) { + ret = ne_read_response_to_fd(req, fd); + } else { + ret = ne_discard_response(req); + } + + if (ret == NE_OK) ret = ne_end_request(req); + } while (ret == NE_RETRY); - /* TODO: verify against requested range. */ + return ret; } int ne_get_range(ne_session *sess, const char *uri, ne_content_range *range, int fd) { ne_request *req = ne_request_create(sess, "GET", uri); - struct get_context ctx; const ne_status *status; int ret; + char brange[64]; if (range->end == -1) { - ctx.total = -1; - } - else { - ctx.total = (range->end - range->start) + 1; - } - - NE_DEBUG(NE_DBG_HTTP, "Range total: %" NE_FMT_OFF_T "\n", ctx.total); - - ctx.fd = fd; - ctx.error = 0; - ctx.range = range; - ctx.session = sess; - - ne_add_response_header_handler(req, "Content-Length", - clength_hdr_handler, &ctx); - ne_add_response_header_handler(req, "Content-Range", - content_range_hdr_handler, - &ctx); - - ne_add_response_body_reader(req, accept_206, get_to_fd, &ctx); - - if (range->end == -1) { - ne_print_request_header(req, "Range", "bytes=%" NE_FMT_OFF_T "-", - range->start); + ne_snprintf(brange, sizeof brange, "bytes=%" NE_FMT_OFF_T "-", + range->start); } else { - ne_print_request_header(req, "Range", - "bytes=%" NE_FMT_OFF_T "-%" NE_FMT_OFF_T, - range->start, range->end); + ne_snprintf(brange, sizeof brange, + "bytes=%" NE_FMT_OFF_T "-%" NE_FMT_OFF_T, + range->start, range->end); } + + ne_add_request_header(req, "Range", brange); ne_add_request_header(req, "Accept-Ranges", "bytes"); - ret = ne_request_dispatch(req); + ret = dispatch_to_fd(req, fd, brange); status = ne_get_status(req); - if (ctx.error) { - ret = NE_ERROR; - } else if (status && status->code == 416) { + if (ret == NE_OK && status->code == 416) { /* connection is terminated too early with Apache/1.3, so we check * this even if ret == NE_ERROR... */ ne_set_error(sess, _("Range is not satisfiable")); @@ -258,26 +196,11 @@ int ne_get_range(ne_session *sess, const char *uri, int ne_get(ne_session *sess, const char *uri, int fd) { ne_request *req = ne_request_create(sess, "GET", uri); - struct get_context ctx; int ret; - ctx.total = -1; - ctx.fd = fd; - ctx.error = 0; - ctx.session = sess; - - /* Read the value of the Content-Length header into ctx.total */ - ne_add_response_header_handler(req, "Content-Length", - ne_handle_numeric_header, - &ctx.total); - - ne_add_response_body_reader(req, ne_accept_2xx, get_to_fd, &ctx); - - ret = ne_request_dispatch(req); + ret = dispatch_to_fd(req, fd, NULL); - if (ctx.error) { - ret = NE_ERROR; - } else if (ret == NE_OK && ne_get_status(req)->klass != 2) { + if (ret == NE_OK && ne_get_status(req)->klass != 2) { ret = NE_ERROR; } @@ -291,28 +214,13 @@ int ne_get(ne_session *sess, const char *uri, int fd) int ne_post(ne_session *sess, const char *uri, int fd, const char *buffer) { ne_request *req = ne_request_create(sess, "POST", uri); - struct get_context ctx; int ret; - ctx.total = -1; - ctx.fd = fd; - ctx.error = 0; - ctx.session = sess; - - /* Read the value of the Content-Length header into ctx.total */ - ne_add_response_header_handler(req, "Content-Length", - ne_handle_numeric_header, &ctx.total); - - ne_add_response_body_reader(req, ne_accept_2xx, get_to_fd, &ctx); - ne_set_request_body_buffer(req, buffer, strlen(buffer)); - ret = ne_request_dispatch(req); + ret = dispatch_to_fd(req, fd, NULL); - if (ctx.error) { - ret = NE_ERROR; - } - else if (ret == NE_OK && ne_get_status(req)->klass != 2) { + if (ret == NE_OK && ne_get_status(req)->klass != 2) { ret = NE_ERROR; } @@ -321,18 +229,19 @@ int ne_post(ne_session *sess, const char *uri, int fd, const char *buffer) return ret; } -void ne_content_type_handler(void *userdata, const char *value) +int ne_get_content_type(ne_request *req, ne_content_type *ct) { - ne_content_type *ct = userdata; + const char *value; char *sep, *stype; + value = ne_get_response_header(req, "Content-Type"); + if (value == NULL || strchr(value, '/') == NULL) { + return -1; + } + ct->value = ne_strdup(value); stype = strchr(ct->value, '/'); - if (!stype) { - NE_FREE(ct->value); - return; - } *stype++ = '\0'; ct->type = ct->value; @@ -367,12 +276,13 @@ void ne_content_type_handler(void *userdata, const char *value) else ct->charset = "ISO-8859-1"; } + + return 0; } -static void dav_hdr_handler(void *userdata, const char *value) +static void parse_dav_header(const char *value, ne_server_capabilities *caps) { char *tokens = ne_strdup(value), *pnt = tokens; - ne_server_capabilities *caps = userdata; do { char *tok = ne_qtoken(&pnt, ',', "\"'"); @@ -390,19 +300,15 @@ static void dav_hdr_handler(void *userdata, const char *value) } while (pnt != NULL); ne_free(tokens); - } -int ne_options(ne_session *sess, const char *uri, - ne_server_capabilities *caps) +int ne_options(ne_session *sess, const char *uri, ne_server_capabilities *caps) { ne_request *req = ne_request_create(sess, "OPTIONS", uri); + int ret = ne_request_dispatch(req); + const char *header = ne_get_response_header(req, "DAV"); - int ret; - - ne_add_response_header_handler(req, "DAV", dav_hdr_handler, caps); - - ret = ne_request_dispatch(req); + if (header) parse_dav_header(header, caps); if (ret == NE_OK && ne_get_status(req)->klass != 2) { ret = NE_ERROR; |