|
@@ -383,7 +383,6 @@ mg_handle_form_data(struct mg_connection *conn,
|
|
fclose(fstore);
|
|
fclose(fstore);
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
/* Proceed to next entry */
|
|
/* Proceed to next entry */
|
|
used = next - buf;
|
|
used = next - buf;
|
|
memmove(buf, buf + (size_t)used, sizeof(buf) - (size_t)used);
|
|
memmove(buf, buf + (size_t)used, sizeof(buf) - (size_t)used);
|
|
@@ -400,9 +399,11 @@ mg_handle_form_data(struct mg_connection *conn,
|
|
const char *boundary;
|
|
const char *boundary;
|
|
size_t bl;
|
|
size_t bl;
|
|
int r;
|
|
int r;
|
|
|
|
+ ptrdiff_t used;
|
|
struct mg_request_info part_header;
|
|
struct mg_request_info part_header;
|
|
char *hbuf, *hend, *fbeg, *fend, *nbeg, *nend;
|
|
char *hbuf, *hend, *fbeg, *fend, *nbeg, *nend;
|
|
const char *content_disp;
|
|
const char *content_disp;
|
|
|
|
+ const char *next;
|
|
|
|
|
|
memset(&part_header, 0, sizeof(part_header));
|
|
memset(&part_header, 0, sizeof(part_header));
|
|
|
|
|
|
@@ -415,98 +416,100 @@ mg_handle_form_data(struct mg_connection *conn,
|
|
boundary = content_type + 30;
|
|
boundary = content_type + 30;
|
|
bl = strlen(boundary);
|
|
bl = strlen(boundary);
|
|
|
|
|
|
- r = mg_read(conn,
|
|
|
|
- buf + (size_t)buf_fill,
|
|
|
|
- sizeof(buf) - 1 - (size_t)buf_fill);
|
|
|
|
- if (r < 0) {
|
|
|
|
- /* read error */
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
- buf_fill += r;
|
|
|
|
- buf[buf_fill] = 0;
|
|
|
|
- if (buf_fill < 1) {
|
|
|
|
- /* No data */
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
|
|
+ do {
|
|
|
|
|
|
- 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;
|
|
|
|
- }
|
|
|
|
|
|
+ r = mg_read(conn,
|
|
|
|
+ buf + (size_t)buf_fill,
|
|
|
|
+ sizeof(buf) - 1 - (size_t)buf_fill);
|
|
|
|
+ if (r < 0) {
|
|
|
|
+ /* read error */
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ buf_fill += r;
|
|
|
|
+ buf[buf_fill] = 0;
|
|
|
|
+ if (buf_fill < 1) {
|
|
|
|
+ /* No data */
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
|
|
- /* Next, we need to get the part header: Read until \r\n\r\n */
|
|
|
|
- hbuf = buf + bl + 4;
|
|
|
|
- hend = strstr(hbuf, "\r\n\r\n");
|
|
|
|
- if (!hend) {
|
|
|
|
- /* Malformed request */
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
- parse_http_headers(&hbuf, &part_header);
|
|
|
|
- if ((hend + 2) != hbuf) {
|
|
|
|
- /* Malformed request */
|
|
|
|
- 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;
|
|
|
|
+ }
|
|
|
|
|
|
- /* According to the RFC, every part has to have a header field like:
|
|
|
|
- * Content-Disposition: form-data; name="..." */
|
|
|
|
- content_disp = get_header(&part_header, "Content-Disposition");
|
|
|
|
- if (!content_disp) {
|
|
|
|
- /* Malformed request */
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
|
|
+ /* Next, we need to get the part header: Read until \r\n\r\n */
|
|
|
|
+ hbuf = buf + bl + 4;
|
|
|
|
+ hend = strstr(hbuf, "\r\n\r\n");
|
|
|
|
+ if (!hend) {
|
|
|
|
+ /* Malformed request */
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ parse_http_headers(&hbuf, &part_header);
|
|
|
|
+ if ((hend + 2) != hbuf) {
|
|
|
|
+ /* Malformed request */
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
|
|
- /* Get the mandatory name="..." part of the Content-Disposition
|
|
|
|
- * header. */
|
|
|
|
- nbeg = strstr(content_disp, "name=\"");
|
|
|
|
- if (!nbeg) {
|
|
|
|
- /* Malformed request */
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
- nbeg += 6;
|
|
|
|
- nend = strchr(nbeg, '\"');
|
|
|
|
- if (!nend) {
|
|
|
|
- /* Malformed request */
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
|
|
+ /* According to the RFC, every part has to have a header field like:
|
|
|
|
+ * Content-Disposition: form-data; name="..." */
|
|
|
|
+ content_disp = get_header(&part_header, "Content-Disposition");
|
|
|
|
+ if (!content_disp) {
|
|
|
|
+ /* Malformed request */
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
|
|
- /* Get the optional filename="..." part of the Content-Disposition
|
|
|
|
- * header. */
|
|
|
|
- fbeg = strstr(content_disp, "filename=\"");
|
|
|
|
- if (fbeg) {
|
|
|
|
- fbeg += 10;
|
|
|
|
- fend = strchr(fbeg, '\"');
|
|
|
|
- if (!fend) {
|
|
|
|
- /* Malformed request (the filename field is optional, but if it
|
|
|
|
- * exists, it needs to be terminated correctly). */
|
|
|
|
|
|
+ /* Get the mandatory name="..." part of the Content-Disposition
|
|
|
|
+ * header. */
|
|
|
|
+ nbeg = strstr(content_disp, "name=\"");
|
|
|
|
+ if (!nbeg) {
|
|
|
|
+ /* Malformed request */
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ nbeg += 6;
|
|
|
|
+ nend = strchr(nbeg, '\"');
|
|
|
|
+ if (!nend) {
|
|
|
|
+ /* Malformed request */
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
- /* TODO: check Content-Type */
|
|
|
|
- /* Content-Type: application/octet-stream */
|
|
|
|
|
|
+ /* Get the optional filename="..." part of the Content-Disposition
|
|
|
|
+ * header. */
|
|
|
|
+ fbeg = strstr(content_disp, "filename=\"");
|
|
|
|
+ if (fbeg) {
|
|
|
|
+ fbeg += 10;
|
|
|
|
+ fend = strchr(fbeg, '\"');
|
|
|
|
+ if (!fend) {
|
|
|
|
+ /* Malformed request (the filename field is optional, but if
|
|
|
|
+ * it
|
|
|
|
+ * exists, it needs to be terminated correctly). */
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
|
|
- } else {
|
|
|
|
- fend = fbeg;
|
|
|
|
- }
|
|
|
|
|
|
+ /* TODO: check Content-Type */
|
|
|
|
+ /* Content-Type: application/octet-stream */
|
|
|
|
|
|
- memset(path, 0, sizeof(path));
|
|
|
|
- disposition = url_encoded_field_found(nbeg,
|
|
|
|
- (size_t)(nend - nbeg),
|
|
|
|
- fbeg,
|
|
|
|
- (size_t)(fend - fbeg),
|
|
|
|
- path,
|
|
|
|
- sizeof(path) - 1,
|
|
|
|
- fdh);
|
|
|
|
|
|
+ } else {
|
|
|
|
+ fend = fbeg;
|
|
|
|
+ }
|
|
|
|
|
|
- do {
|
|
|
|
- const char *next = strstr(hbuf, "--");
|
|
|
|
|
|
+ memset(path, 0, sizeof(path));
|
|
|
|
+ disposition = url_encoded_field_found(nbeg,
|
|
|
|
+ (size_t)(nend - nbeg),
|
|
|
|
+ fbeg,
|
|
|
|
+ (size_t)(fend - fbeg),
|
|
|
|
+ path,
|
|
|
|
+ sizeof(path) - 1,
|
|
|
|
+ fdh);
|
|
|
|
+
|
|
|
|
+ next = strstr(hbuf, "--");
|
|
while (next && (strncmp(next + 2, boundary, bl))) {
|
|
while (next && (strncmp(next + 2, boundary, bl))) {
|
|
/* found "--" not followed by boundary: look for next "--" */
|
|
/* found "--" not followed by boundary: look for next "--" */
|
|
next = strstr(next + 1, "--");
|
|
next = strstr(next + 1, "--");
|
|
@@ -528,6 +531,7 @@ mg_handle_form_data(struct mg_connection *conn,
|
|
(size_t)(next - hend),
|
|
(size_t)(next - hend),
|
|
fdh);
|
|
fdh);
|
|
}
|
|
}
|
|
|
|
+
|
|
if (disposition == FORM_DISPOSITION_STORE) {
|
|
if (disposition == FORM_DISPOSITION_STORE) {
|
|
/* Store the content to a file */
|
|
/* Store the content to a file */
|
|
FILE *f = fopen(path, "wb");
|
|
FILE *f = fopen(path, "wb");
|
|
@@ -544,7 +548,13 @@ mg_handle_form_data(struct mg_connection *conn,
|
|
/* Stop parsing the request */
|
|
/* Stop parsing the request */
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
- } while (0 /* TODO */);
|
|
|
|
|
|
+
|
|
|
|
+ /* Remove from the buffer */
|
|
|
|
+ used = next - buf;
|
|
|
|
+ memmove(buf, buf + (size_t)used, sizeof(buf) - (size_t)used);
|
|
|
|
+ buf_fill -= used;
|
|
|
|
+
|
|
|
|
+ } while (1 /* TODO */);
|
|
|
|
|
|
/* TODO: handle multipart request */
|
|
/* TODO: handle multipart request */
|
|
return 0;
|
|
return 0;
|