diff --git a/src/protocol/file/cgi.c b/src/protocol/file/cgi.c index 5b0e06f8..42e841ea 100644 --- a/src/protocol/file/cgi.c +++ b/src/protocol/file/cgi.c @@ -112,12 +112,15 @@ send_post_data(struct connection *conn) unsigned char *post = conn->uri->post; unsigned char *postend; unsigned int files; + enum connection_state error; postend = strchr(post, '\n'); if (postend) post = postend + 1; - open_http_post(&http->post, post, &files); - send_more_post_data(conn->data_socket); + if (!open_http_post(&http->post, post, &files, &error)) + abort_connection(conn, error); + else + send_more_post_data(conn->data_socket); } static void diff --git a/src/protocol/http/http.c b/src/protocol/http/http.c index 9f080a78..e301ad80 100644 --- a/src/protocol/http/http.c +++ b/src/protocol/http/http.c @@ -971,6 +971,7 @@ 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'); + enum connection_state error; if (postend) { add_to_string(&header, "Content-Type: "); @@ -979,7 +980,11 @@ http_send_header(struct socket *socket) } post_data = postend ? postend + 1 : uri->post; - open_http_post(&http->post, post_data, &files); + if (!open_http_post(&http->post, post_data, &files, &error)) { + http_end_request(conn, error, 0); + done_string(&header); + return; + } add_format_to_string(&header, "Content-Length: " "%" OFF_PRINT_FORMAT "\x0D\x0A", (off_print_T) diff --git a/src/protocol/http/post.c b/src/protocol/http/post.c index 84fc7dde..c8d6cb8f 100644 --- a/src/protocol/http/post.c +++ b/src/protocol/http/post.c @@ -62,6 +62,10 @@ done_http_post(struct http_post *http_post) * pointer remains valid until done_http_post(). * @param[out] files * The number of files going to be uploaded. + * @param[out] error + * If the function fails, it writes the error state here so that + * the caller can pass that on to abort_connection(). If the + * function succeeds, the value of *@a error is undefined. * * This function does not parse the Content-Type from uri.post; the * caller must do that. This is because in local CGI, the child @@ -69,10 +73,12 @@ done_http_post(struct http_post *http_post) * variable before exec) but the parent process handles the body of * the request (feeding it to the child process via a pipe). * + * @return nonzero on success, zero on error. + * * @relates http_post */ -void +int open_http_post(struct http_post *http_post, unsigned char *post_data, - unsigned int *files) + unsigned int *files, enum connection_state *error) { off_t size = 0; size_t length = strlen(post_data); @@ -102,6 +108,8 @@ open_http_post(struct http_post *http_post, unsigned char *post_data, } size += (length / 2); http_post->total_upload_length = size; + + return 1; } /** @relates http_post */ diff --git a/src/protocol/http/post.h b/src/protocol/http/post.h index 562bba30..d0455f82 100644 --- a/src/protocol/http/post.h +++ b/src/protocol/http/post.h @@ -4,6 +4,8 @@ #ifndef EL__PROTOCOL_HTTP_POST_H #define EL__PROTOCOL_HTTP_POST_H +#include "network/state.h" + /** State of reading POST data from connection.uri->post and related * files. */ struct http_post { @@ -26,9 +28,8 @@ 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 open_http_post(struct http_post *http_post, unsigned char *post_data, + unsigned int *files, enum connection_state *error); int read_http_post(struct http_post *http_post, unsigned char buffer[], int max);