diff --git a/examples/embedded_c/embedded_c.c b/examples/embedded_c/embedded_c.c index 79c4a320..497e63f6 100644 --- a/examples/embedded_c/embedded_c.c +++ b/examples/embedded_c/embedded_c.c @@ -156,7 +156,8 @@ FileHandler(struct mg_connection *conn, void *cbdata) /**********************/ -/* proposed interface */ +/* proposed interface - will be moved to the header once it is ready for release + */ enum { FORM_FIELD_STORAGE_SKIP = 0x0, @@ -181,8 +182,8 @@ struct mg_form_data_handler { void *user_data; }; -int mg_handle_form_data(struct mg_connection *conn, - struct mg_form_data_handler *fdh); +extern int mg_handle_form_data(struct mg_connection *conn, + struct mg_form_data_handler *fdh); /* end of interface */ /********************/ diff --git a/src/handle_form.inl b/src/handle_form.inl index e907d642..222eb25b 100644 --- a/src/handle_form.inl +++ b/src/handle_form.inl @@ -99,8 +99,13 @@ enum { }; -int mg_handle_form_data(struct mg_connection *conn, - struct mg_form_data_handler *fdh); +/* Process form data. + * Returns the number of fields handled, or < 0 in case of an error. + * Note: It is possible that several fields are handled succesfully (e.g., + * stored in a file), before the request handling is stopped with an + * error. In this case a number < 0 is returned as well. */ +CIVETWEB_API int mg_handle_form_data(struct mg_connection *conn, + struct mg_form_data_handler *fdh); /* end of interface */ /********************/ @@ -239,6 +244,7 @@ mg_handle_form_data(struct mg_connection *conn, int buf_fill = 0; int r; FILE *fstore = NULL; + int field_count = 0; int has_body_data = (conn->request_info.content_length > 0) || (conn->is_chunked); @@ -260,7 +266,7 @@ mg_handle_form_data(struct mg_connection *conn, if (strcmp(conn->request_info.request_method, "GET")) { /* No body data, but not a GET request. * This is not a valid form request. */ - return 0; + return -1; } /* GET request: form data is in the query string. */ @@ -270,7 +276,7 @@ mg_handle_form_data(struct mg_connection *conn, data = conn->request_info.query_string; if (!data) { /* No query string. */ - return 0; + return -1; } /* Split data in a=1&b=xy&c=3&c=4 ... */ @@ -296,6 +302,7 @@ mg_handle_form_data(struct mg_connection *conn, * FORM_FIELD_STORAGE_ABORT (flag) ... stop parsing */ memset(path, 0, sizeof(path)); + field_count++; field_storage = url_encoded_field_found(conn, data, (size_t)keylen, @@ -378,7 +385,7 @@ mg_handle_form_data(struct mg_connection *conn, data = next; } - return 0; + return field_count; } content_type = mg_get_header(conn, "Content-Type"); @@ -393,7 +400,7 @@ mg_handle_form_data(struct mg_connection *conn, /* The encoding is like in the "GET" case above, but here we read data * on the fly */ for (;;) { - /* TODO(high): Handle (text) fields with data > sizeof(buf). */ + /* TODO(high): Handle (text) fields with data size > sizeof(buf). */ const char *val; const char *next; ptrdiff_t keylen, vallen; @@ -406,7 +413,7 @@ mg_handle_form_data(struct mg_connection *conn, r = mg_read(conn, buf + (size_t)buf_fill, to_read); if (r < 0) { /* read error */ - return 0; + return -1; } if (r != (int)to_read) { /* TODO: Create a function to get "all_data_read" from @@ -433,6 +440,7 @@ mg_handle_form_data(struct mg_connection *conn, /* Call callback */ memset(path, 0, sizeof(path)); + field_count++; field_storage = url_encoded_field_found(conn, buf, (size_t)keylen, @@ -485,7 +493,7 @@ mg_handle_form_data(struct mg_connection *conn, mg_cry(conn, "%s: Data too long for callback", __func__); - return 0; + return -1; } /* Call callback */ url_encoded_field_get( @@ -517,7 +525,7 @@ mg_handle_form_data(struct mg_connection *conn, buf_fill -= used; } - return 0; + return field_count; } if (!mg_strncasecmp(content_type, "MULTIPART/FORM-DATA;", 20)) { @@ -537,7 +545,7 @@ mg_handle_form_data(struct mg_connection *conn, /* There has to be a BOUNDARY definition in the Content-Type header */ if (mg_strncasecmp(content_type + 21, "BOUNDARY=", 9)) { /* Malformed request */ - return 0; + return -1; } boundary = content_type + 30; @@ -552,7 +560,7 @@ mg_handle_form_data(struct mg_connection *conn, * any reasonable request from every browser. If it is not * fulfilled, it might be a hand-made request, intended to * interfere with the algorithm. */ - return 0; + return -1; } for (;;) { @@ -562,22 +570,22 @@ mg_handle_form_data(struct mg_connection *conn, sizeof(buf) - 1 - (size_t)buf_fill); if (r < 0) { /* read error */ - return 0; + return -1; } buf_fill += r; buf[buf_fill] = 0; if (buf_fill < 1) { /* No data */ - return 0; + return -1; } if (buf[0] != '-' || buf[1] != '-') { /* Malformed request */ - return 0; + return -1; } if (strncmp(buf + 2, boundary, bl)) { /* Malformed request */ - return 0; + return -1; } if (buf[bl + 2] != '\r' || buf[bl + 3] != '\n') { /* Every part must end with \r\n, if there is another part. @@ -585,7 +593,7 @@ mg_handle_form_data(struct mg_connection *conn, if (((size_t)buf_fill != (size_t)(bl + 6)) || (strncmp(buf + bl + 2, "--\r\n", 4))) { /* Malformed request */ - return 0; + return -1; } /* End of the request */ break; @@ -596,13 +604,13 @@ mg_handle_form_data(struct mg_connection *conn, hend = strstr(hbuf, "\r\n\r\n"); if (!hend) { /* Malformed request */ - return 0; + return -1; } parse_http_headers(&hbuf, &part_header); if ((hend + 2) != hbuf) { /* Malformed request */ - return 0; + return -1; } /* Skip \r\n\r\n */ @@ -613,7 +621,7 @@ mg_handle_form_data(struct mg_connection *conn, content_disp = get_header(&part_header, "Content-Disposition"); if (!content_disp) { /* Malformed request */ - return 0; + return -1; } /* Get the mandatory name="..." part of the Content-Disposition @@ -621,13 +629,13 @@ mg_handle_form_data(struct mg_connection *conn, nbeg = strstr(content_disp, "name=\""); if (!nbeg) { /* Malformed request */ - return 0; + return -1; } nbeg += 6; nend = strchr(nbeg, '\"'); if (!nend) { /* Malformed request */ - return 0; + return -1; } /* Get the optional filename="..." part of the Content-Disposition @@ -639,7 +647,7 @@ mg_handle_form_data(struct mg_connection *conn, if (!fend) { /* Malformed request (the filename field is optional, but if * it exists, it needs to be terminated correctly). */ - return 0; + return -1; } /* TODO: check Content-Type */ @@ -650,6 +658,7 @@ mg_handle_form_data(struct mg_connection *conn, } memset(path, 0, sizeof(path)); + field_count++; field_storage = url_encoded_field_found(conn, nbeg, (size_t)(nend - nbeg), @@ -670,7 +679,7 @@ mg_handle_form_data(struct mg_connection *conn, if (!next) { /* TODO: check for an easy way to get longer data */ mg_cry(conn, "%s: Data too long for callback", __func__); - return 0; + return -1; } /* Call callback */ @@ -727,13 +736,13 @@ mg_handle_form_data(struct mg_connection *conn, sizeof(buf) - 1 - (size_t)buf_fill); if (r < 0) { /* read error */ - return 0; + return -1; } buf_fill += r; buf[buf_fill] = 0; if (buf_fill < 1) { /* No data */ - return 0; + return -1; } /* Find boundary */ @@ -774,7 +783,7 @@ mg_handle_form_data(struct mg_connection *conn, if ((field_storage & FORM_FIELD_STORAGE_ABORT) == FORM_FIELD_STORAGE_ABORT) { /* Stop parsing the request */ - return 0; + return -1; } /* Remove from the buffer */ @@ -784,9 +793,9 @@ mg_handle_form_data(struct mg_connection *conn, } /* All parts handled */ - return 0; + return field_count; } /* Unknown Content-Type */ - return 0; + return -1; }