diff --git a/examples/embedded_c/embedded_c.c b/examples/embedded_c/embedded_c.c index e78ddb63..3ad8be92 100644 --- a/examples/embedded_c/embedded_c.c +++ b/examples/embedded_c/embedded_c.c @@ -155,12 +155,26 @@ FileHandler(struct mg_connection *conn, void *cbdata) } +enum { + FORM_DISPOSITION_SKIP = 0x0, + FORM_DISPOSITION_GET = 0x1, + FORM_DISPOSITION_STORE = 0x2, + FORM_DISPOSITION_READ = 0x4, + FORM_DISPOSITION_ABORT = 0x10 +}; + + struct mg_form_data_handler { int (*field_found)(const char *key, size_t keylen, const char *filename, - int *disposition, void *user_data); + int (*field_get)(const char *key, + size_t keylen, + const char *filename, + const char *value, + size_t valuelen, + void *user_data); void *user_data; }; @@ -169,16 +183,30 @@ int field_found(const char *key, size_t keylen, const char *filename, - int *disposition, void *user_data) { struct mg_connection *conn = (struct mg_connection *)user_data; + mg_write(conn, key, keylen); + mg_printf(conn, ":\r\n"); + return FORM_DISPOSITION_GET; +} + + +int +field_get(const char *key, + size_t keylen, + const char *filename, + const char *value, + size_t valuelen, + void *user_data) +{ + struct mg_connection *conn = (struct mg_connection *)user_data; + mg_write(conn, key, keylen); mg_printf(conn, " = "); - // mg_write(conn, value, vallen); - // TODO: disposition = skip/store/read/abort - mg_printf(conn, "\r\n"); + mg_write(conn, value, valuelen); + mg_printf(conn, "\r\n\r\n"); return 0; } @@ -190,7 +218,7 @@ FormHandler(struct mg_connection *conn, void *cbdata) /* Handler may access the request info using mg_get_request_info */ const struct mg_request_info *req_info = mg_get_request_info(conn); int ret; - struct mg_form_data_handler fdh = {field_found, 0}; + struct mg_form_data_handler fdh = {field_found, field_get, 0}; /* TODO: Checks before calling handle_form_data ? */ (void)req_info; diff --git a/src/handle_form.inl b/src/handle_form.inl index d3e2fe3f..8499ffaa 100644 --- a/src/handle_form.inl +++ b/src/handle_form.inl @@ -51,8 +51,13 @@ struct mg_form_data_handler { int (*field_found)(const char *key, size_t keylen, const char *filename, - int *disposition, void *user_data); + int (*field_get)(const char *key, + size_t keylen, + const char *filename, + const char *value, + size_t valuelen, + void *user_data); void *user_data; }; @@ -61,7 +66,6 @@ static int url_encoded_field_found(const char *key, size_t keylen, const char *filename, - int *disposition, struct mg_form_data_handler *fdh) { /* Call callback */ @@ -69,14 +73,13 @@ url_encoded_field_found(const char *key, int ret = mg_url_decode(key, (size_t)keylen, key_dec, (int)sizeof(key_dec), 1); if ((ret < sizeof(key_dec)) && (ret >= 0)) { - return fdh->field_found( - key, keylen, filename, disposition, fdh->user_data); + return fdh->field_found(key, keylen, filename, fdh->user_data); } return FORM_DISPOSITION_SKIP; } -void +int url_encoded_field_get(const char *key, size_t keylen, const char *filename, @@ -88,16 +91,14 @@ url_encoded_field_get(const char *key, char *value_dec = mg_malloc(valuelen + 1); if (!value_dec) { /* TODO: oom */ - return; + return FORM_DISPOSITION_ABORT; } mg_url_decode(key, (size_t)keylen, key_dec, (int)sizeof(key_dec), 1); mg_url_decode(value, (size_t)valuelen, value_dec, (int)valuelen + 1, 1); - - /* TODO: Form decode */ - fdh->field_get( - key, keylen, filename, value, strlen(value_dec), fdh->user_data); + return fdh->field_get( + key, keylen, filename, value_dec, strlen(value_dec), fdh->user_data); } @@ -106,8 +107,9 @@ mg_handle_form_data(struct mg_connection *conn, struct mg_form_data_handler *fdh) { const char *content_type; - const char *boundary; + char buf[1024]; int disposition; + int buf_fill = 0; int has_body_data = (conn->request_info.content_length > 0) || (conn->is_chunked); @@ -150,8 +152,8 @@ mg_handle_form_data(struct mg_connection *conn, } keylen = val - data; - url_encoded_field_found( - data, (size_t)keylen, NULL, &disposition, fdh); + disposition = + url_encoded_field_found(data, (size_t)keylen, NULL, fdh); val++; next = strchr(val, '&'); @@ -166,7 +168,7 @@ mg_handle_form_data(struct mg_connection *conn, if (disposition == FORM_DISPOSITION_GET) { /* Call callback */ url_encoded_field_get( - data, (size_t)keylen, val, (size_t)vallen, fdh); + data, (size_t)keylen, NULL, val, (size_t)vallen, fdh); } /* Proceed to next entry */ @@ -186,9 +188,6 @@ mg_handle_form_data(struct mg_connection *conn, /* Read body data and split it in a=1&b&c=3&c=4 ... */ /* The encoding is like in the "GET" case above, but here we read data * on the fly */ - char buf[1024]; - int buf_fill = 0; - for (;;) { /* TODO(high): Handle (text) fields with data > sizeof(buf). */ const char *val; @@ -229,8 +228,8 @@ mg_handle_form_data(struct mg_connection *conn, } /* Call callback */ - fdh->field_found( - buf, (size_t)keylen, NULL, &disposition, fdh->user_data); + disposition = + fdh->field_found(buf, (size_t)keylen, NULL, fdh->user_data); /* Proceed to next entry */ used = next - buf; @@ -241,14 +240,45 @@ mg_handle_form_data(struct mg_connection *conn, return 0; } - mirror_body___dev_helper(conn); + // mirror_body___dev_helper(conn); if (!mg_strncasecmp(content_type, "MULTIPART/FORM-DATA;", 20)) { /* The form data is in the request body data, encoded as multipart * content. */ + const char *boundary; + size_t bl; + int r; /* There has to be a BOUNDARY definition in the Content-Type header */ - if (!mg_strncasecmp(content_type + 20, "BOUNDARY=", 9)) { + if (mg_strncasecmp(content_type + 21, "BOUNDARY=", 9)) { + /* Malformed request */ + return 0; + } + + boundary = content_type + 30; + bl = strlen(boundary); + + r = mg_read(conn, buf + buf_fill, sizeof(buf) - 1 - buf_fill); + if (r < 0) { + /* read error */ + return 0; + } + buf_fill += r; + buf[buf_fill] = 0; + if (buf_fill < 1) { + /* No data */ + return 0; + } + + if (buf[0] != '-' || buf[1] != '-') { + /* Malformed request */ + return 0; + } + if (strncmp(buf + 2, boundary, bl)) { + /* Malformed request */ + return 0; + } + if (buf[bl + 2] != '\r' || buf[bl + 3] != '\n') { /* Malformed request */ return 0; }