From 533e7fc62b4b540ae1913a51085d655ac3fcac70 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Mon, 2 Jun 2008 10:41:55 +0300 Subject: [PATCH] 1008: replace post_length() with open_http_post() --- src/protocol/file/cgi.c | 3 ++- src/protocol/http/http.c | 41 +++--------------------------- src/protocol/http/post.c | 54 ++++++++++++++++++++++++++++++++++++++++ src/protocol/http/post.h | 3 +++ 4 files changed, 62 insertions(+), 39 deletions(-) diff --git a/src/protocol/file/cgi.c b/src/protocol/file/cgi.c index df82e089..5b0e06f8 100644 --- a/src/protocol/file/cgi.c +++ b/src/protocol/file/cgi.c @@ -111,11 +111,12 @@ send_post_data(struct connection *conn) struct http_connection_info *http = conn->info; unsigned char *post = conn->uri->post; unsigned char *postend; + unsigned int files; postend = strchr(post, '\n'); if (postend) post = postend + 1; + open_http_post(&http->post, post, &files); - http->post.post_data = post; send_more_post_data(conn->data_socket); } diff --git a/src/protocol/http/http.c b/src/protocol/http/http.c index 1028882e..9f080a78 100644 --- a/src/protocol/http/http.c +++ b/src/protocol/http/http.c @@ -8,7 +8,6 @@ #include #include #include -#include #ifdef HAVE_LIMITS_H #include #endif @@ -593,37 +592,6 @@ accept_encoding_header(struct string *header) #endif } -/* This sets the Content-Length of POST data and counts files. */ -static off_t -post_length(unsigned char *post_data, unsigned int *count) -{ - off_t size = 0; - size_t length = strlen(post_data); - unsigned char *end = post_data; - - *count = 0; - while (1) { - struct stat sb; - unsigned char *begin; - int res; - - begin = strchr(end, FILE_CHAR); - if (!begin) break; - end = strchr(begin + 1, FILE_CHAR); - if (!end) break; - *end = '\0'; - res = stat(begin + 1, &sb); - *end = FILE_CHAR; - if (res) break; - (*count)++; - size += sb.st_size; - length -= (end - begin + 1); - end++; - } - size += (length / 2); - return size; -} - #define POST_BUFFER_SIZE 4096 #define BIG_READ 655360 @@ -1003,7 +971,6 @@ http_send_header(struct socket *socket) * as set by get_form_uri(). This '\n' is dropped if any * and replaced by correct '\r\n' termination here. */ unsigned char *postend = strchr(uri->post, '\n'); - off_t size; if (postend) { add_to_string(&header, "Content-Type: "); @@ -1012,11 +979,11 @@ http_send_header(struct socket *socket) } post_data = postend ? postend + 1 : uri->post; - size = post_length(post_data, &files); - http->post.total_upload_length = size; + open_http_post(&http->post, post_data, &files); add_format_to_string(&header, "Content-Length: " "%" OFF_PRINT_FORMAT "\x0D\x0A", - (off_print_T) size); + (off_print_T) + http->post.total_upload_length); } #ifdef CONFIG_COOKIES @@ -1040,9 +1007,7 @@ http_send_header(struct socket *socket) * in that case. Verified with an assertion below. */ if (post_data) { assert(!use_connect); /* see comment above */ - assert(http->post.post_fd == -1); - http->post.post_data = post_data; socket->state = SOCKET_END_ONCLOSE; if (!conn->upload_progress && files) conn->upload_progress = init_progress(0); diff --git a/src/protocol/http/post.c b/src/protocol/http/post.c index cdaffd5f..84fc7dde 100644 --- a/src/protocol/http/post.c +++ b/src/protocol/http/post.c @@ -7,6 +7,7 @@ #include #include +#include #ifdef HAVE_UNISTD_H #include #endif @@ -50,6 +51,59 @@ done_http_post(struct http_post *http_post) } } +/** Prepare to read POST data from a URI and possibly to upload files. + * + * @param http_post + * Must have been initialized with init_http_post(). + * @param[in] post_data + * The body of the POST request as formatted by get_form_uri(). + * However, unlike uri.post, @a post_data must not contain any + * Content-Type. The caller must ensure that the @a post_data + * pointer remains valid until done_http_post(). + * @param[out] files + * The number of files going to be uploaded. + * + * This function does not parse the Content-Type from uri.post; the + * caller must do that. This is because in local CGI, the child + * process handles the Content-Type (saving it to an environment + * variable before exec) but the parent process handles the body of + * the request (feeding it to the child process via a pipe). + * + * @relates http_post */ +void +open_http_post(struct http_post *http_post, unsigned char *post_data, + unsigned int *files) +{ + off_t size = 0; + size_t length = strlen(post_data); + unsigned char *end = post_data; + + done_http_post(http_post); + http_post->post_data = end; + + *files = 0; + while (1) { + struct stat sb; + unsigned char *begin; + int res; + + begin = strchr(end, FILE_CHAR); + if (!begin) break; + end = strchr(begin + 1, FILE_CHAR); + if (!end) break; + *end = '\0'; + res = stat(begin + 1, &sb); + *end = FILE_CHAR; + if (res) break; + (*files)++; + size += sb.st_size; + length -= (end - begin + 1); + end++; + } + size += (length / 2); + http_post->total_upload_length = size; +} + /** @relates http_post */ static int read_http_post_inline(struct http_post *http_post, diff --git a/src/protocol/http/post.h b/src/protocol/http/post.h index 27c1c589..562bba30 100644 --- a/src/protocol/http/post.h +++ b/src/protocol/http/post.h @@ -26,6 +26,9 @@ struct http_post { void init_http_post(struct http_post *http_post); void done_http_post(struct http_post *http_post); +void open_http_post(struct http_post *http_post, + unsigned char *post_data, + unsigned int *files); int read_http_post(struct http_post *http_post, unsigned char buffer[], int max);