24 url_encoded_field_found(
const struct mg_connection *conn,
31 struct mg_form_data_handler *fdh)
34 char filename_dec[1024];
40 mg_url_decode(key, (
int)key_len, key_dec, (
int)
sizeof(key_dec), 1);
42 if (((
size_t)key_dec_len >= (
size_t)
sizeof(key_dec)) || (key_dec_len < 0)) {
43 return MG_FORM_FIELD_STORAGE_SKIP;
47 filename_dec_len = mg_url_decode(filename,
50 (
int)
sizeof(filename_dec),
53 if (((
size_t)filename_dec_len >= (
size_t)
sizeof(filename_dec))
54 || (filename_dec_len < 0)) {
56 mg_cry_internal(conn,
"%s: Cannot decode filename", __func__);
57 return MG_FORM_FIELD_STORAGE_SKIP;
64 fdh->field_found(key_dec, filename_dec, path, path_len, fdh->user_data);
66 if ((ret & 0xF) == MG_FORM_FIELD_STORAGE_GET) {
67 if (fdh->field_get == NULL) {
69 "%s: Function \"Get\" not available",
71 return MG_FORM_FIELD_STORAGE_SKIP;
74 if ((ret & 0xF) == MG_FORM_FIELD_STORAGE_STORE) {
75 if (fdh->field_store == NULL) {
77 "%s: Function \"Store\" not available",
79 return MG_FORM_FIELD_STORAGE_SKIP;
88 url_encoded_field_get(
const struct mg_connection *conn,
93 struct mg_form_data_handler *fdh)
97 char *value_dec = (
char *)mg_malloc_ctx(value_len + 1, conn->phys_ctx);
98 int value_dec_len, ret;
102 mg_cry_internal(conn,
103 "%s: Not enough memory (required: %lu)",
105 (
unsigned long)(value_len + 1));
106 return MG_FORM_FIELD_STORAGE_ABORT;
109 mg_url_decode(key, (
int)key_len, key_dec, (
int)
sizeof(key_dec), 1);
112 mg_url_decode(value, (
int)value_len, value_dec, (
int)value_len + 1, 1);
114 ret = fdh->field_get(key_dec,
116 (
size_t)value_dec_len,
126 unencoded_field_get(
const struct mg_connection *conn,
131 struct mg_form_data_handler *fdh)
136 mg_url_decode(key, (
int)key_len, key_dec, (
int)
sizeof(key_dec), 1);
138 return fdh->field_get(key_dec, value, value_len, fdh->user_data);
143 field_stored(
const struct mg_connection *conn,
146 struct mg_form_data_handler *fdh)
152 return fdh->field_store(path, file_size, fdh->user_data);
157 search_boundary(
const char *buf,
159 const char *boundary,
164 int clen = (int)buf_len - (
int)boundary_len - 4;
167 for (i = 0; i <= clen; i++) {
168 if (!memcmp(buf + i,
"\r\n--", 4)) {
169 if (!memcmp(buf + i + 4, boundary, boundary_len)) {
179 mg_handle_form_request(
struct mg_connection *conn,
180 struct mg_form_data_handler *fdh)
182 const char *content_type;
184 char buf[MG_BUF_LEN];
189 struct mg_file fstore = STRUCT_FILE_INITIALIZER;
190 int64_t file_size = 0;
194 (conn->request_info.content_length > 0) || (conn->is_chunked);
207 if (!has_body_data) {
210 if (0 != strcmp(conn->request_info.request_method,
"GET")) {
220 data = conn->request_info.query_string;
228 const char *val = strchr(data,
'=');
230 ptrdiff_t keylen, vallen;
250 memset(path, 0,
sizeof(path));
252 field_storage = url_encoded_field_found(conn,
262 next = strchr(val,
'&');
267 vallen = (ptrdiff_t)strlen(val);
271 if (field_storage == MG_FORM_FIELD_STORAGE_GET) {
273 r = url_encoded_field_get(
274 conn, data, (
size_t)keylen, val, (
size_t)vallen, fdh);
275 if (r == MG_FORM_FIELD_HANDLE_ABORT) {
279 if (r == MG_FORM_FIELD_HANDLE_NEXT) {
281 field_storage = MG_FORM_FIELD_STORAGE_SKIP;
284 if (field_storage == MG_FORM_FIELD_STORAGE_STORE) {
286 if (mg_fopen(conn, path, MG_FOPEN_MODE_WRITE, &fstore) == 0) {
287 fstore.access.fp = NULL;
290 if (fstore.access.fp != NULL) {
292 fwrite(val, 1, (
size_t)vallen, fstore.access.fp);
293 if ((n != (
size_t)vallen) || (ferror(fstore.access.fp))) {
294 mg_cry_internal(conn,
295 "%s: Cannot write file %s",
298 (void)mg_fclose(&fstore.access);
299 remove_bad_file(conn, path);
301 file_size += (int64_t)n;
303 if (fstore.access.fp) {
304 r = mg_fclose(&fstore.access);
307 r = field_stored(conn, path, file_size, fdh);
308 if (r == MG_FORM_FIELD_HANDLE_ABORT) {
314 mg_cry_internal(conn,
315 "%s: Error saving file %s",
318 remove_bad_file(conn, path);
320 fstore.access.fp = NULL;
324 mg_cry_internal(conn,
325 "%s: Cannot create file %s",
344 if ((field_storage & MG_FORM_FIELD_STORAGE_ABORT)
345 == MG_FORM_FIELD_STORAGE_ABORT) {
357 content_type = mg_get_header(conn,
"Content-Type");
360 || !mg_strncasecmp(content_type,
361 "APPLICATION/X-WWW-FORM-URLENCODED",
363 || !mg_strncasecmp(content_type,
364 "APPLICATION/WWW-FORM-URLENCODED",
368 int all_data_read = 0;
378 ptrdiff_t keylen, vallen;
380 int end_of_key_value_pair_found = 0;
383 if ((
size_t)buf_fill < (
sizeof(buf) - 1)) {
385 size_t to_read =
sizeof(buf) - 1 - (
size_t)buf_fill;
386 r = mg_read(conn, buf + (
size_t)buf_fill, to_read);
391 if (r != (
int)to_read) {
406 val = strchr(buf,
'=');
415 memset(path, 0,
sizeof(path));
417 field_storage = url_encoded_field_found(conn,
426 if ((field_storage & MG_FORM_FIELD_STORAGE_ABORT)
427 == MG_FORM_FIELD_STORAGE_ABORT) {
432 if (field_storage == MG_FORM_FIELD_STORAGE_STORE) {
433 if (mg_fopen(conn, path, MG_FOPEN_MODE_WRITE, &fstore) == 0) {
434 fstore.access.fp = NULL;
437 if (!fstore.access.fp) {
438 mg_cry_internal(conn,
439 "%s: Cannot create file %s",
448 next = strchr(val,
'&');
452 end_of_key_value_pair_found = 1;
454 vallen = (ptrdiff_t)strlen(val);
456 end_of_key_value_pair_found = all_data_read;
459 if (field_storage == MG_FORM_FIELD_STORAGE_GET) {
461 if (!end_of_key_value_pair_found && !all_data_read) {
467 r = url_encoded_field_get(conn,
468 ((get_block > 0) ? NULL : buf),
476 if (r == MG_FORM_FIELD_HANDLE_ABORT) {
480 if (r == MG_FORM_FIELD_HANDLE_NEXT) {
482 field_storage = MG_FORM_FIELD_STORAGE_SKIP;
485 if (fstore.access.fp) {
487 fwrite(val, 1, (
size_t)vallen, fstore.access.fp);
488 if ((n != (
size_t)vallen) || (ferror(fstore.access.fp))) {
489 mg_cry_internal(conn,
490 "%s: Cannot write file %s",
493 mg_fclose(&fstore.access);
494 remove_bad_file(conn, path);
496 file_size += (int64_t)n;
499 if (!end_of_key_value_pair_found) {
503 sizeof(buf) - (
size_t)used);
505 buf_fill -= (int)used;
506 if ((
size_t)buf_fill < (
sizeof(buf) - 1)) {
508 size_t to_read =
sizeof(buf) - 1 - (
size_t)buf_fill;
509 r = mg_read(conn, buf + (
size_t)buf_fill, to_read);
512 if (fstore.access.fp) {
513 mg_fclose(&fstore.access);
514 remove_bad_file(conn, path);
518 if (r != (
int)to_read) {
535 }
while (!end_of_key_value_pair_found);
537 if (fstore.access.fp) {
538 r = mg_fclose(&fstore.access);
541 r = field_stored(conn, path, file_size, fdh);
542 if (r == MG_FORM_FIELD_HANDLE_ABORT) {
547 mg_cry_internal(conn,
548 "%s: Error saving file %s",
551 remove_bad_file(conn, path);
553 fstore.access.fp = NULL;
556 if (all_data_read && (buf_fill == 0)) {
563 memmove(buf, buf + (
size_t)used,
sizeof(buf) - (
size_t)used);
564 buf_fill -= (int)used;
570 if (!mg_strncasecmp(content_type,
"MULTIPART/FORM-DATA;", 20)) {
577 struct mg_request_info part_header;
579 const char *content_disp, *hend, *fbeg, *fend, *nbeg, *nend;
583 memset(&part_header, 0,
sizeof(part_header));
587 while (content_type[bl] ==
' ') {
592 if (mg_strncasecmp(content_type + bl,
"BOUNDARY=", 9)) {
598 fbeg = content_type + bl + 9;
600 boundary = (
char *)mg_malloc(bl + 1);
603 mg_cry_internal(conn,
604 "%s: Cannot allocate memory for boundary [%lu]",
609 memcpy(boundary, fbeg, bl);
614 if (boundary[0] ==
'"') {
615 hbuf = strchr(boundary + 1,
'"');
616 if ((!hbuf) || (*hbuf !=
'"')) {
622 memmove(boundary, boundary + 1, bl);
623 bl = strlen(boundary);
649 for (part_no = 0;; part_no++) {
650 size_t towrite, fnlen, n;
654 buf + (
size_t)buf_fill,
655 sizeof(buf) - 1 - (
size_t)buf_fill);
671 while ((buf[d] !=
'-') && (d < buf_fill)) {
674 if ((d > 0) && (buf[d] ==
'-')) {
675 memmove(buf, buf + d, (
unsigned)buf_fill - (
unsigned)d);
681 if (buf[0] !=
'-' || buf[1] !=
'-') {
686 if (0 != strncmp(buf + 2, boundary, bl)) {
691 if (buf[bl + 2] !=
'\r' || buf[bl + 3] !=
'\n') {
694 if (((
size_t)buf_fill != (
size_t)(bl + 6))
695 || (strncmp(buf + bl + 2,
"--\r\n", 4))) {
706 hend = strstr(hbuf,
"\r\n\r\n");
713 part_header.num_headers =
714 parse_http_headers(&hbuf, part_header.http_headers);
715 if ((hend + 2) != hbuf) {
726 content_disp = get_header(part_header.http_headers,
727 part_header.num_headers,
728 "Content-Disposition");
737 nbeg = strstr(content_disp,
"name=\"");
738 while ((nbeg != NULL) && (strcspn(nbeg - 1,
":,; \t") != 0)) {
740 nbeg = strstr(nbeg + 1,
"name=\"");
752 nend = strchr(nbeg,
'\"');
760 nbeg = strstr(content_disp,
"name=");
761 while ((nbeg != NULL) && (strcspn(nbeg - 1,
":,; \t") != 0)) {
763 nbeg = strstr(nbeg + 1,
"name=");
779 nend = nbeg + strcspn(nbeg,
",; \t");
784 fbeg = strstr(content_disp,
"filename=\"");
785 while ((fbeg != NULL) && (strcspn(fbeg - 1,
":,; \t") != 0)) {
787 fbeg = strstr(fbeg + 1,
"filename=\"");
797 fend = strchr(fbeg,
'\"');
811 fbeg = strstr(content_disp,
"filename=");
812 while ((fbeg != NULL) && (strcspn(fbeg - 1,
":,; \t") != 0)) {
814 fbeg = strstr(fbeg + 1,
"filename=");
818 fend = fbeg + strcspn(fbeg,
",; \t");
822 if (!fbeg || !fend) {
827 fnlen = (size_t)(fend - fbeg);
833 if (!(((ptrdiff_t)fbeg > (ptrdiff_t)nend)
834 || ((ptrdiff_t)nbeg > (ptrdiff_t)fend))) {
840 memset(path, 0,
sizeof(path));
842 field_storage = url_encoded_field_found(conn,
844 (
size_t)(nend - nbeg),
845 ((fnlen > 0) ? fbeg : NULL),
853 next = search_boundary(hbuf,
854 (
size_t)((buf - hbuf) + buf_fill),
858 if (field_storage == MG_FORM_FIELD_STORAGE_STORE) {
860 if (mg_fopen(conn, path, MG_FOPEN_MODE_WRITE, &fstore) == 0) {
861 fstore.access.fp = NULL;
865 if (!fstore.access.fp) {
866 mg_cry_internal(conn,
867 "%s: Cannot create file %s",
877 towrite = (size_t)(buf - hend + buf_fill);
883 if (field_storage == MG_FORM_FIELD_STORAGE_GET) {
884 r = unencoded_field_get(conn,
885 ((get_block > 0) ? NULL : nbeg),
888 : (
size_t)(nend - nbeg)),
893 if (r == MG_FORM_FIELD_HANDLE_ABORT) {
897 if (r == MG_FORM_FIELD_HANDLE_NEXT) {
899 field_storage = MG_FORM_FIELD_STORAGE_SKIP;
903 if (field_storage == MG_FORM_FIELD_STORAGE_STORE) {
904 if (fstore.access.fp) {
907 n = (size_t)fwrite(hend, 1, towrite, fstore.access.fp);
908 if ((n != towrite) || (ferror(fstore.access.fp))) {
909 mg_cry_internal(conn,
910 "%s: Cannot write file %s",
913 mg_fclose(&fstore.access);
914 remove_bad_file(conn, path);
916 file_size += (int64_t)n;
920 memmove(buf, hend + towrite, bl + 4);
921 buf_fill = (int)(bl + 4);
926 buf + (
size_t)buf_fill,
927 sizeof(buf) - 1 - (
size_t)buf_fill);
930 if (fstore.access.fp) {
931 mg_fclose(&fstore.access);
932 remove_bad_file(conn, path);
942 next = search_boundary(buf, (
size_t)buf_fill, boundary, bl);
945 towrite = (size_t)(next - hend);
947 if (field_storage == MG_FORM_FIELD_STORAGE_GET) {
949 r = unencoded_field_get(conn,
950 ((get_block > 0) ? NULL : nbeg),
953 : (
size_t)(nend - nbeg)),
957 if (r == MG_FORM_FIELD_HANDLE_ABORT) {
961 if (r == MG_FORM_FIELD_HANDLE_NEXT) {
963 field_storage = MG_FORM_FIELD_STORAGE_SKIP;
967 if (field_storage == MG_FORM_FIELD_STORAGE_STORE) {
969 if (fstore.access.fp) {
970 n = (size_t)fwrite(hend, 1, towrite, fstore.access.fp);
971 if ((n != towrite) || (ferror(fstore.access.fp))) {
972 mg_cry_internal(conn,
973 "%s: Cannot write file %s",
976 mg_fclose(&fstore.access);
977 remove_bad_file(conn, path);
979 file_size += (int64_t)n;
980 r = mg_fclose(&fstore.access);
983 r = field_stored(conn, path, file_size, fdh);
984 if (r == MG_FORM_FIELD_HANDLE_ABORT) {
989 mg_cry_internal(conn,
990 "%s: Error saving file %s",
993 remove_bad_file(conn, path);
996 fstore.access.fp = NULL;
1000 if ((field_storage & MG_FORM_FIELD_STORAGE_ABORT)
1001 == MG_FORM_FIELD_STORAGE_ABORT) {
1007 used = next - buf + 2;
1008 memmove(buf, buf + (
size_t)used,
sizeof(buf) - (
size_t)used);
1009 buf_fill -= (int)used;