diff options
Diffstat (limited to 'src/daemon/postprocessor.c')
-rw-r--r-- | src/daemon/postprocessor.c | 745 |
1 files changed, 364 insertions, 381 deletions
diff --git a/src/daemon/postprocessor.c b/src/daemon/postprocessor.c index 5b8f01a2..8be3ee89 100644 --- a/src/daemon/postprocessor.c +++ b/src/daemon/postprocessor.c | |||
@@ -40,13 +40,13 @@ enum PP_State | |||
40 | PP_Done, | 40 | PP_Done, |
41 | PP_Init, | 41 | PP_Init, |
42 | 42 | ||
43 | /* url encoding-states*/ | 43 | /* url encoding-states */ |
44 | PP_ProcessValue, | 44 | PP_ProcessValue, |
45 | PP_ExpectNewLine, | 45 | PP_ExpectNewLine, |
46 | 46 | ||
47 | /* post encoding-states */ | 47 | /* post encoding-states */ |
48 | PP_ProcessEntryHeaders, | 48 | PP_ProcessEntryHeaders, |
49 | PP_PerformCheckMultipart, | 49 | PP_PerformCheckMultipart, |
50 | PP_ProcessValueToBoundary, | 50 | PP_ProcessValueToBoundary, |
51 | PP_PerformCleanup, | 51 | PP_PerformCleanup, |
52 | 52 | ||
@@ -56,7 +56,7 @@ enum PP_State | |||
56 | PP_Nested_ProcessEntryHeaders, | 56 | PP_Nested_ProcessEntryHeaders, |
57 | PP_Nested_ProcessValueToBoundary, | 57 | PP_Nested_ProcessValueToBoundary, |
58 | PP_Nested_PerformCleanup, | 58 | PP_Nested_PerformCleanup, |
59 | 59 | ||
60 | }; | 60 | }; |
61 | 61 | ||
62 | enum RN_State | 62 | enum RN_State |
@@ -76,11 +76,11 @@ enum RN_State | |||
76 | * Expect '\r\n' (and only '\r\n'). As always, we also | 76 | * Expect '\r\n' (and only '\r\n'). As always, we also |
77 | * expect only '\r' or only '\n'. | 77 | * expect only '\r' or only '\n'. |
78 | */ | 78 | */ |
79 | RN_Full = 2, | 79 | RN_Full = 2, |
80 | 80 | ||
81 | /** | 81 | /** |
82 | * Expect either '\r\n' or '--\r\n'. If '--\r\n', transition into dash-state | 82 | * Expect either '\r\n' or '--\r\n'. If '--\r\n', transition into dash-state |
83 | * for the main state machine | 83 | * for the main state machine |
84 | */ | 84 | */ |
85 | RN_Dash = 3, | 85 | RN_Dash = 3, |
86 | 86 | ||
@@ -94,8 +94,8 @@ enum RN_State | |||
94 | * Bits for the globally known fields that | 94 | * Bits for the globally known fields that |
95 | * should not be deleted when we exit the | 95 | * should not be deleted when we exit the |
96 | * nested state. | 96 | * nested state. |
97 | */ | 97 | */ |
98 | enum NE_State | 98 | enum NE_State |
99 | { | 99 | { |
100 | NE_none = 0, | 100 | NE_none = 0, |
101 | NE_content_name = 1, | 101 | NE_content_name = 1, |
@@ -136,12 +136,12 @@ struct MHD_PostProcessor | |||
136 | /** | 136 | /** |
137 | * Primary boundary (points into encoding string) | 137 | * Primary boundary (points into encoding string) |
138 | */ | 138 | */ |
139 | const char * boundary; | 139 | const char *boundary; |
140 | 140 | ||
141 | /** | 141 | /** |
142 | * Nested boundary (if we have multipart/mixed encoding). | 142 | * Nested boundary (if we have multipart/mixed encoding). |
143 | */ | 143 | */ |
144 | char * nested_boundary; | 144 | char *nested_boundary; |
145 | 145 | ||
146 | /** | 146 | /** |
147 | * Pointer to the name given in disposition. | 147 | * Pointer to the name given in disposition. |
@@ -263,23 +263,22 @@ MHD_create_post_processor (struct MHD_Connection *connection, | |||
263 | if (encoding == NULL) | 263 | if (encoding == NULL) |
264 | return NULL; | 264 | return NULL; |
265 | boundary = NULL; | 265 | boundary = NULL; |
266 | if (0 != strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, | 266 | if (0 != strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, encoding)) |
267 | encoding)) | ||
268 | { | 267 | { |
269 | if (0 != strncasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, encoding, | 268 | if (0 != |
270 | strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA))) | 269 | strncasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, encoding, |
271 | return NULL; | 270 | strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA))) |
271 | return NULL; | ||
272 | boundary = | 272 | boundary = |
273 | &encoding[strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)]; | 273 | &encoding[strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)]; |
274 | /* Q: should this be "strcasestr"? */ | 274 | /* Q: should this be "strcasestr"? */ |
275 | if (NULL != strstr (boundary, "boundary=")) | 275 | if (NULL != strstr (boundary, "boundary=")) |
276 | boundary = strstr (boundary, "boundary=") + strlen ("boundary="); | 276 | boundary = strstr (boundary, "boundary=") + strlen ("boundary="); |
277 | else | 277 | else |
278 | return NULL; /* failed to determine boundary */ | 278 | return NULL; /* failed to determine boundary */ |
279 | blen = strlen (boundary); | 279 | blen = strlen (boundary); |
280 | if ( (blen == 0) || | 280 | if ((blen == 0) || (blen * 2 + 2 > buffer_size)) |
281 | (blen * 2 + 2 > buffer_size) ) | 281 | return NULL; /* (will be) out of memory or invalid boundary */ |
282 | return NULL; /* (will be) out of memory or invalid boundary */ | ||
283 | } | 282 | } |
284 | else | 283 | else |
285 | blen = 0; | 284 | blen = 0; |
@@ -322,10 +321,10 @@ post_process_urlencoded (struct MHD_PostProcessor *pp, | |||
322 | { | 321 | { |
323 | case PP_Error: | 322 | case PP_Error: |
324 | return MHD_NO; | 323 | return MHD_NO; |
325 | case PP_Done: | 324 | case PP_Done: |
326 | /* did not expect to receive more data */ | 325 | /* did not expect to receive more data */ |
327 | pp->state = PP_Error; | 326 | pp->state = PP_Error; |
328 | return MHD_NO; | 327 | return MHD_NO; |
329 | case PP_Init: | 328 | case PP_Init: |
330 | equals = 0; | 329 | equals = 0; |
331 | while ((equals + poff < post_data_len) && | 330 | while ((equals + poff < post_data_len) && |
@@ -444,39 +443,37 @@ try_match_header (const char *prefix, char *line, char **suffix) | |||
444 | { | 443 | { |
445 | if (NULL != *suffix) | 444 | if (NULL != *suffix) |
446 | return MHD_NO; | 445 | return MHD_NO; |
447 | while(*line != 0) | 446 | while (*line != 0) |
448 | { | 447 | { |
449 | if (0 == strncasecmp (prefix, line, strlen (prefix))) | 448 | if (0 == strncasecmp (prefix, line, strlen (prefix))) |
450 | { | 449 | { |
451 | *suffix = strdup (&line[strlen (prefix)]); | 450 | *suffix = strdup (&line[strlen (prefix)]); |
452 | return MHD_YES; | 451 | return MHD_YES; |
453 | } | 452 | } |
454 | ++line; | 453 | ++line; |
455 | } | 454 | } |
456 | return MHD_NO; | 455 | return MHD_NO; |
457 | } | 456 | } |
458 | 457 | ||
459 | static int | 458 | static int |
460 | find_boundary(struct MHD_PostProcessor * pp, | 459 | find_boundary (struct MHD_PostProcessor *pp, |
461 | const char * boundary, | 460 | const char *boundary, |
462 | size_t blen, | 461 | size_t blen, |
463 | unsigned int * ioffptr, | 462 | unsigned int *ioffptr, |
464 | enum PP_State next_state, | 463 | enum PP_State next_state, enum PP_State next_dash_state) |
465 | enum PP_State next_dash_state) | ||
466 | { | 464 | { |
467 | char * buf = (char*) &pp[1]; | 465 | char *buf = (char *) &pp[1]; |
468 | 466 | ||
469 | if (pp->buffer_pos < 2 + blen) | 467 | if (pp->buffer_pos < 2 + blen) |
470 | { | 468 | { |
471 | if (pp->buffer_pos == pp->buffer_size) | 469 | if (pp->buffer_pos == pp->buffer_size) |
472 | pp->state = PP_Error; /* out of memory */ | 470 | pp->state = PP_Error; /* out of memory */ |
473 | return MHD_NO; /* not enough data */ | 471 | return MHD_NO; /* not enough data */ |
474 | } | 472 | } |
475 | if ( (0 != memcmp ("--", buf, 2)) || | 473 | if ((0 != memcmp ("--", buf, 2)) || (0 != memcmp (&buf[2], boundary, blen))) |
476 | (0 != memcmp (&buf[2], boundary, blen))) | ||
477 | { | 474 | { |
478 | pp->state = PP_Error; | 475 | pp->state = PP_Error; |
479 | return MHD_NO; /* expected boundary */ | 476 | return MHD_NO; /* expected boundary */ |
480 | } | 477 | } |
481 | /* remove boundary from buffer */ | 478 | /* remove boundary from buffer */ |
482 | (*ioffptr) += 2 + blen; | 479 | (*ioffptr) += 2 + blen; |
@@ -491,49 +488,43 @@ find_boundary(struct MHD_PostProcessor * pp, | |||
491 | * In buf, there maybe an expression | 488 | * In buf, there maybe an expression |
492 | * '$key="$value"'. If that is the case, | 489 | * '$key="$value"'. If that is the case, |
493 | * copy a copy of $value to destination. | 490 | * copy a copy of $value to destination. |
494 | * | 491 | * |
495 | * If destination is already non-NULL, | 492 | * If destination is already non-NULL, |
496 | * do nothing. | 493 | * do nothing. |
497 | */ | 494 | */ |
498 | static void | 495 | static void |
499 | try_get_value(const char * buf, | 496 | try_get_value (const char *buf, const char *key, char **destination) |
500 | const char * key, | ||
501 | char ** destination) | ||
502 | { | 497 | { |
503 | const char * spos; | 498 | const char *spos; |
504 | const char * bpos; | 499 | const char *bpos; |
505 | const char * endv; | 500 | const char *endv; |
506 | size_t klen; | 501 | size_t klen; |
507 | size_t vlen; | 502 | size_t vlen; |
508 | 503 | ||
509 | if (NULL != *destination) | 504 | if (NULL != *destination) |
510 | return; | 505 | return; |
511 | bpos = buf; | 506 | bpos = buf; |
512 | klen = strlen(key); | 507 | klen = strlen (key); |
513 | while (NULL != (spos = strstr(bpos, key))) | 508 | while (NULL != (spos = strstr (bpos, key))) |
514 | { | 509 | { |
515 | if ( (spos[klen] != '=') || | 510 | if ((spos[klen] != '=') || ((spos != buf) && (spos[-1] != ' '))) |
516 | ( (spos != buf) && | 511 | { |
517 | (spos[-1] != ' ') ) ) | 512 | /* no match */ |
518 | { | 513 | bpos = spos + 1; |
519 | /* no match */ | 514 | continue; |
520 | bpos = spos + 1; | 515 | } |
521 | continue; | ||
522 | } | ||
523 | if (spos[klen + 1] != '"') | 516 | if (spos[klen + 1] != '"') |
524 | return; /* not quoted */ | 517 | return; /* not quoted */ |
525 | if (NULL == (endv = strstr(&spos[klen+2], "\""))) | 518 | if (NULL == (endv = strstr (&spos[klen + 2], "\""))) |
526 | return; /* no end-quote */ | 519 | return; /* no end-quote */ |
527 | vlen = endv - spos - klen - 1; | 520 | vlen = endv - spos - klen - 1; |
528 | *destination = malloc(vlen); | 521 | *destination = malloc (vlen); |
529 | if (NULL == *destination) | 522 | if (NULL == *destination) |
530 | return; /* out of memory */ | 523 | return; /* out of memory */ |
531 | (*destination)[vlen - 1] = '\0'; | 524 | (*destination)[vlen - 1] = '\0'; |
532 | memcpy(*destination, | 525 | memcpy (*destination, &spos[klen + 2], vlen - 1); |
533 | &spos[klen + 2], | 526 | return; /* success */ |
534 | vlen - 1); | 527 | } |
535 | return; /* success */ | ||
536 | } | ||
537 | } | 528 | } |
538 | 529 | ||
539 | /** | 530 | /** |
@@ -541,37 +532,35 @@ try_get_value(const char * buf, | |||
541 | * the fields in "pp" according to what we find. | 532 | * the fields in "pp" according to what we find. |
542 | * If we are at the end of the headers (as indicated | 533 | * If we are at the end of the headers (as indicated |
543 | * by an empty line), transition into next_state. | 534 | * by an empty line), transition into next_state. |
544 | * | 535 | * |
545 | * @param ioffptr set to how many bytes have been | 536 | * @param ioffptr set to how many bytes have been |
546 | * processed | 537 | * processed |
547 | * @return MHD_YES if we can continue processing, | 538 | * @return MHD_YES if we can continue processing, |
548 | * MHD_NO on error or if we do not have | 539 | * MHD_NO on error or if we do not have |
549 | * enough data yet | 540 | * enough data yet |
550 | */ | 541 | */ |
551 | static int | 542 | static int |
552 | process_multipart_headers(struct MHD_PostProcessor * pp, | 543 | process_multipart_headers (struct MHD_PostProcessor *pp, |
553 | unsigned int * ioffptr, | 544 | unsigned int *ioffptr, enum PP_State next_state) |
554 | enum PP_State next_state) | ||
555 | { | 545 | { |
556 | char * buf = (char*) &pp[1]; | 546 | char *buf = (char *) &pp[1]; |
557 | unsigned int newline; | 547 | unsigned int newline; |
558 | 548 | ||
559 | newline = 0; | 549 | newline = 0; |
560 | while ((newline < pp->buffer_pos) && | 550 | while ((newline < pp->buffer_pos) && |
561 | (buf[newline] != '\r') && | 551 | (buf[newline] != '\r') && (buf[newline] != '\n')) |
562 | (buf[newline] != '\n')) | ||
563 | newline++; | 552 | newline++; |
564 | if (newline == pp->buffer_size) | 553 | if (newline == pp->buffer_size) |
565 | { | 554 | { |
566 | pp->state = PP_Error; | 555 | pp->state = PP_Error; |
567 | return MHD_NO; /* out of memory */ | 556 | return MHD_NO; /* out of memory */ |
568 | } | 557 | } |
569 | if (newline == pp->buffer_pos) | 558 | if (newline == pp->buffer_pos) |
570 | return MHD_NO; /* will need more data */ | 559 | return MHD_NO; /* will need more data */ |
571 | if (newline == 0) | 560 | if (newline == 0) |
572 | { | 561 | { |
573 | /* empty line - end of headers */ | 562 | /* empty line - end of headers */ |
574 | pp->skip_rn = RN_Full; | 563 | pp->skip_rn = RN_Full; |
575 | pp->state = next_state; | 564 | pp->state = next_state; |
576 | return MHD_YES; | 565 | return MHD_YES; |
577 | } | 566 | } |
@@ -579,24 +568,21 @@ process_multipart_headers(struct MHD_PostProcessor * pp, | |||
579 | if (buf[newline] == '\r') | 568 | if (buf[newline] == '\r') |
580 | pp->skip_rn = RN_OptN; | 569 | pp->skip_rn = RN_OptN; |
581 | buf[newline] = '\0'; | 570 | buf[newline] = '\0'; |
582 | if (0 == strncasecmp("Content-disposition: ", | 571 | if (0 == strncasecmp ("Content-disposition: ", |
583 | buf, | 572 | buf, strlen ("Content-disposition: "))) |
584 | strlen("Content-disposition: "))) | 573 | { |
585 | { | 574 | try_get_value (&buf[strlen ("Content-disposition: ")], |
586 | try_get_value(&buf[strlen("Content-disposition: ")], | 575 | "name", &pp->content_name); |
587 | "name", | 576 | try_get_value (&buf[strlen ("Content-disposition: ")], |
588 | &pp->content_name); | 577 | "filename", &pp->content_filename); |
589 | try_get_value(&buf[strlen("Content-disposition: ")], | ||
590 | "filename", | ||
591 | &pp->content_filename); | ||
592 | } | 578 | } |
593 | else | 579 | else |
594 | { | 580 | { |
595 | try_match_header ("Content-type: ", buf, &pp->content_type); | 581 | try_match_header ("Content-type: ", buf, &pp->content_type); |
596 | try_match_header ("Content-Transfer-Encoding: ", | 582 | try_match_header ("Content-Transfer-Encoding: ", |
597 | buf, &pp->content_transfer_encoding); | 583 | buf, &pp->content_transfer_encoding); |
598 | } | 584 | } |
599 | (*ioffptr) += newline + 1; | 585 | (*ioffptr) += newline + 1; |
600 | return MHD_YES; | 586 | return MHD_YES; |
601 | } | 587 | } |
602 | 588 | ||
@@ -615,14 +601,14 @@ process_multipart_headers(struct MHD_PostProcessor * pp, | |||
615 | * enough data yet | 601 | * enough data yet |
616 | */ | 602 | */ |
617 | static int | 603 | static int |
618 | process_value_to_boundary(struct MHD_PostProcessor * pp, | 604 | process_value_to_boundary (struct MHD_PostProcessor *pp, |
619 | unsigned int * ioffptr, | 605 | unsigned int *ioffptr, |
620 | const char * boundary, | 606 | const char *boundary, |
621 | size_t blen, | 607 | size_t blen, |
622 | enum PP_State next_state, | 608 | enum PP_State next_state, |
623 | enum PP_State next_dash_state) | 609 | enum PP_State next_dash_state) |
624 | { | 610 | { |
625 | char * buf = (char*) &pp[1]; | 611 | char *buf = (char *) &pp[1]; |
626 | unsigned int newline; | 612 | unsigned int newline; |
627 | 613 | ||
628 | /* all data in buf until the boundary | 614 | /* all data in buf until the boundary |
@@ -631,53 +617,51 @@ process_value_to_boundary(struct MHD_PostProcessor * pp, | |||
631 | while (1) | 617 | while (1) |
632 | { | 618 | { |
633 | while ((newline + 4 < pp->buffer_pos) && | 619 | while ((newline + 4 < pp->buffer_pos) && |
634 | (0 != memcmp ("\r\n--", &buf[newline], 4))) | 620 | (0 != memcmp ("\r\n--", &buf[newline], 4))) |
635 | newline++; | 621 | newline++; |
636 | if (newline + pp->blen + 4 <= pp->buffer_pos) | 622 | if (newline + pp->blen + 4 <= pp->buffer_pos) |
637 | { | 623 | { |
638 | /* can check boundary */ | 624 | /* can check boundary */ |
639 | if (0 != memcmp (&buf[newline + 4], boundary, pp->blen)) | 625 | if (0 != memcmp (&buf[newline + 4], boundary, pp->blen)) |
640 | { | 626 | { |
641 | /* no boundary, "\r\n--" is part of content, skip */ | 627 | /* no boundary, "\r\n--" is part of content, skip */ |
642 | newline += 4; | 628 | newline += 4; |
643 | continue; | 629 | continue; |
644 | } | 630 | } |
645 | else | 631 | else |
646 | { | 632 | { |
647 | /* boundary found, process until newline then | 633 | /* boundary found, process until newline then |
648 | skip boundary and go back to init */ | 634 | skip boundary and go back to init */ |
649 | pp->skip_rn = RN_Dash; | 635 | pp->skip_rn = RN_Dash; |
650 | pp->state = next_state; | 636 | pp->state = next_state; |
651 | pp->dash_state = next_dash_state; | 637 | pp->dash_state = next_dash_state; |
652 | (*ioffptr) += pp->blen + 4; /* skip boundary as well */ | 638 | (*ioffptr) += pp->blen + 4; /* skip boundary as well */ |
653 | break; | 639 | break; |
654 | } | 640 | } |
655 | } | 641 | } |
656 | else | 642 | else |
657 | { | 643 | { |
658 | /* cannot check for boundary, process content that | 644 | /* cannot check for boundary, process content that |
659 | we have and check again later; except, if we have | 645 | we have and check again later; except, if we have |
660 | no content, abort (out of memory) */ | 646 | no content, abort (out of memory) */ |
661 | if ( (newline == 0) && | 647 | if ((newline == 0) && (pp->buffer_pos == pp->buffer_size)) |
662 | (pp->buffer_pos == pp->buffer_size) ) | 648 | { |
663 | { | 649 | pp->state = PP_Error; |
664 | pp->state = PP_Error; | 650 | return MHD_NO; |
665 | return MHD_NO; | 651 | } |
666 | } | 652 | break; |
667 | return MHD_NO; | 653 | } |
668 | } | ||
669 | } | 654 | } |
670 | /* newline is either at beginning of boundary or | 655 | /* newline is either at beginning of boundary or |
671 | at least at the last character that we are sure | 656 | at least at the last character that we are sure |
672 | is not part of the boundary */ | 657 | is not part of the boundary */ |
673 | if (MHD_NO == pp->ikvi (pp->cls, | 658 | if (MHD_NO == pp->ikvi (pp->cls, |
674 | MHD_POSTDATA_KIND, | 659 | MHD_POSTDATA_KIND, |
675 | pp->content_name, | 660 | pp->content_name, |
676 | pp->content_filename, | 661 | pp->content_filename, |
677 | pp->content_type, | 662 | pp->content_type, |
678 | pp->content_transfer_encoding, | 663 | pp->content_transfer_encoding, |
679 | buf, | 664 | buf, pp->value_offset, newline)) |
680 | pp->value_offset, newline)) | ||
681 | { | 665 | { |
682 | pp->state = PP_Error; | 666 | pp->state = PP_Error; |
683 | return MHD_NO; | 667 | return MHD_NO; |
@@ -688,30 +672,28 @@ process_value_to_boundary(struct MHD_PostProcessor * pp, | |||
688 | } | 672 | } |
689 | 673 | ||
690 | static void | 674 | static void |
691 | free_unmarked(struct MHD_PostProcessor * pp) | 675 | free_unmarked (struct MHD_PostProcessor *pp) |
692 | { | 676 | { |
693 | if ( (pp->content_name != NULL) && | 677 | if ((pp->content_name != NULL) && (0 == (pp->have & NE_content_name))) |
694 | (0 == (pp->have & NE_content_name)) ) | ||
695 | { | 678 | { |
696 | free(pp->content_name); | 679 | free (pp->content_name); |
697 | pp->content_name = NULL; | 680 | pp->content_name = NULL; |
698 | } | 681 | } |
699 | if ( (pp->content_type != NULL) && | 682 | if ((pp->content_type != NULL) && (0 == (pp->have & NE_content_type))) |
700 | (0 == (pp->have & NE_content_type)) ) | ||
701 | { | 683 | { |
702 | free(pp->content_type); | 684 | free (pp->content_type); |
703 | pp->content_type = NULL; | 685 | pp->content_type = NULL; |
704 | } | 686 | } |
705 | if ( (pp->content_filename != NULL) && | 687 | if ((pp->content_filename != NULL) && |
706 | (0 == (pp->have & NE_content_filename)) ) | 688 | (0 == (pp->have & NE_content_filename))) |
707 | { | 689 | { |
708 | free(pp->content_filename); | 690 | free (pp->content_filename); |
709 | pp->content_filename = NULL; | 691 | pp->content_filename = NULL; |
710 | } | 692 | } |
711 | if ( (pp->content_transfer_encoding != NULL) && | 693 | if ((pp->content_transfer_encoding != NULL) && |
712 | (0 == (pp->have & NE_content_transfer_encoding)) ) | 694 | (0 == (pp->have & NE_content_transfer_encoding))) |
713 | { | 695 | { |
714 | free(pp->content_transfer_encoding); | 696 | free (pp->content_transfer_encoding); |
715 | pp->content_transfer_encoding = NULL; | 697 | pp->content_transfer_encoding = NULL; |
716 | } | 698 | } |
717 | } | 699 | } |
@@ -727,251 +709,252 @@ post_process_multipart (struct MHD_PostProcessor *pp, | |||
727 | unsigned int max; | 709 | unsigned int max; |
728 | unsigned int ioff; | 710 | unsigned int ioff; |
729 | unsigned int poff; | 711 | unsigned int poff; |
712 | int state_changed; | ||
730 | 713 | ||
731 | buf = (char *) &pp[1]; | 714 | buf = (char *) &pp[1]; |
732 | ioff = 0; | 715 | ioff = 0; |
733 | poff = 0; | 716 | poff = 0; |
734 | max = 1; | 717 | state_changed = 1; |
735 | while ( (poff < post_data_len) || | 718 | while ((poff < post_data_len) || |
736 | ( (pp->buffer_pos > 0) && | 719 | ((pp->buffer_pos > 0) && (state_changed != 0))) |
737 | (max != 0) ) ) | ||
738 | { | 720 | { |
739 | /* first, move as much input data | 721 | /* first, move as much input data |
740 | as possible to our internal buffer */ | 722 | as possible to our internal buffer */ |
741 | max = pp->buffer_size - pp->buffer_pos; | 723 | max = pp->buffer_size - pp->buffer_pos; |
742 | if (max > post_data_len - poff) | 724 | if (max > post_data_len - poff) |
743 | max = post_data_len - poff; | 725 | max = post_data_len - poff; |
744 | memcpy (&buf[pp->buffer_pos], &post_data[poff], max); | 726 | memcpy (&buf[pp->buffer_pos], &post_data[poff], max); |
745 | poff += max; | 727 | poff += max; |
746 | pp->buffer_pos += max; | 728 | pp->buffer_pos += max; |
747 | if ( (max == 0) && | 729 | if ((max == 0) && (state_changed == 0) && (poff < post_data_len)) |
748 | (poff < post_data_len) ) | 730 | { |
749 | { | 731 | pp->state = PP_Error; |
750 | pp->state = PP_Error; | 732 | return MHD_NO; /* out of memory */ |
751 | return MHD_NO; /* out of memory */ | 733 | } |
752 | } | 734 | state_changed = 0; |
753 | 735 | ||
754 | /* first state machine for '\r'-'\n' and '--' handling */ | 736 | /* first state machine for '\r'-'\n' and '--' handling */ |
755 | switch (pp->skip_rn) | 737 | switch (pp->skip_rn) |
756 | { | 738 | { |
757 | case RN_Inactive: | 739 | case RN_Inactive: |
758 | break; | 740 | break; |
759 | case RN_OptN: | 741 | case RN_OptN: |
760 | if (buf[0] == '\n') | 742 | if (buf[0] == '\n') |
761 | { | 743 | { |
762 | ioff++; | 744 | ioff++; |
763 | pp->skip_rn = RN_Inactive; | 745 | pp->skip_rn = RN_Inactive; |
764 | goto AGAIN; | 746 | goto AGAIN; |
765 | } | 747 | } |
766 | case RN_Dash: | 748 | case RN_Dash: |
767 | if (buf[0] == '-') | 749 | if (buf[0] == '-') |
768 | { | 750 | { |
769 | ioff++; | 751 | ioff++; |
770 | pp->skip_rn = RN_Dash2; | 752 | pp->skip_rn = RN_Dash2; |
771 | goto AGAIN; | 753 | goto AGAIN; |
772 | } | 754 | } |
773 | pp->skip_rn = RN_Full; | 755 | pp->skip_rn = RN_Full; |
774 | /* fall-through! */ | 756 | /* fall-through! */ |
775 | case RN_Full: | 757 | case RN_Full: |
776 | if (buf[0] == '\r') | 758 | if (buf[0] == '\r') |
777 | { | 759 | { |
778 | if ( (pp->buffer_pos > 1) && | 760 | if ((pp->buffer_pos > 1) && (buf[1] == '\n')) |
779 | (buf[1] == '\n') ) | 761 | { |
780 | { | 762 | pp->skip_rn = RN_Inactive; |
781 | pp->skip_rn = RN_Inactive; | 763 | ioff += 2; |
782 | ioff += 2; | 764 | } |
783 | } | 765 | else |
784 | else | 766 | { |
785 | { | 767 | pp->skip_rn = RN_OptN; |
786 | pp->skip_rn = RN_OptN; | 768 | ioff++; |
787 | ioff++; | 769 | } |
788 | } | 770 | goto AGAIN; |
789 | goto AGAIN; | 771 | } |
790 | } | 772 | if (buf[0] == '\n') |
791 | if (buf[0] == '\n') | 773 | { |
792 | { | 774 | ioff++; |
793 | ioff++; | 775 | pp->skip_rn = RN_Inactive; |
794 | pp->skip_rn = RN_Inactive; | 776 | goto AGAIN; |
795 | goto AGAIN; | 777 | } |
796 | } | 778 | pp->skip_rn = RN_Inactive; |
797 | pp->skip_rn = RN_Inactive; | 779 | pp->state = PP_Error; |
798 | pp->state = PP_Error; | 780 | return MHD_NO; /* no '\r\n' */ |
799 | return MHD_NO; /* no '\r\n' */ | 781 | case RN_Dash2: |
800 | case RN_Dash2: | 782 | if (buf[0] == '-') |
801 | if (buf[0] == '-') | 783 | { |
802 | { | 784 | ioff++; |
803 | ioff++; | 785 | pp->skip_rn = RN_Full; |
804 | pp->skip_rn = RN_Full; | 786 | pp->state = pp->dash_state; |
805 | pp->state = pp->dash_state; | 787 | goto AGAIN; |
806 | goto AGAIN; | 788 | } |
807 | } | 789 | pp->state = PP_Error; |
808 | pp->state = PP_Error; | 790 | break; |
809 | break; | 791 | } |
810 | } | ||
811 | 792 | ||
812 | /* main state engine */ | 793 | /* main state engine */ |
813 | switch (pp->state) | 794 | switch (pp->state) |
814 | { | 795 | { |
815 | case PP_Error: | 796 | case PP_Error: |
816 | return MHD_NO; | 797 | return MHD_NO; |
817 | case PP_Done: | 798 | case PP_Done: |
818 | /* did not expect to receive more data */ | 799 | /* did not expect to receive more data */ |
819 | pp->state = PP_Error; | 800 | pp->state = PP_Error; |
820 | return MHD_NO; | 801 | return MHD_NO; |
821 | case PP_Init: | 802 | case PP_Init: |
822 | if (MHD_NO == find_boundary(pp, | 803 | if (MHD_NO == find_boundary (pp, |
823 | pp->boundary, | 804 | pp->boundary, |
824 | pp->blen, | 805 | pp->blen, |
825 | &ioff, | 806 | &ioff, |
826 | PP_ProcessEntryHeaders, | 807 | PP_ProcessEntryHeaders, PP_Done)) |
827 | PP_Done)) | 808 | { |
828 | { | 809 | if (pp->state == PP_Error) |
829 | if (pp->state == PP_Error) | 810 | return MHD_NO; |
830 | return MHD_NO; | 811 | goto END; |
831 | goto END; | 812 | } |
832 | } | 813 | break; |
833 | break; | 814 | case PP_ProcessEntryHeaders: |
834 | case PP_ProcessEntryHeaders: | 815 | if (MHD_NO == |
835 | if (MHD_NO == process_multipart_headers(pp, &ioff, PP_PerformCheckMultipart)) | 816 | process_multipart_headers (pp, &ioff, PP_PerformCheckMultipart)) |
836 | { | 817 | { |
837 | if (pp->state == PP_Error) | 818 | if (pp->state == PP_Error) |
838 | return MHD_NO; | 819 | return MHD_NO; |
839 | else | 820 | else |
840 | goto END; | 821 | goto END; |
841 | } | 822 | } |
842 | max = 1; | 823 | state_changed = 1; |
843 | break; | 824 | break; |
844 | case PP_PerformCheckMultipart: | 825 | case PP_PerformCheckMultipart: |
845 | if ( (pp->content_type != NULL) && | 826 | if ((pp->content_type != NULL) && |
846 | (0 == strncasecmp(pp->content_type, | 827 | (0 == strncasecmp (pp->content_type, |
847 | "multipart/mixed", | 828 | "multipart/mixed", |
848 | strlen("multipart/mixed")) ) ) | 829 | strlen ("multipart/mixed")))) |
849 | { | 830 | { |
850 | pp->nested_boundary = strstr(pp->content_type, | 831 | pp->nested_boundary = strstr (pp->content_type, "boundary="); |
851 | "boundary="); | 832 | if (pp->nested_boundary == NULL) |
852 | if (pp->nested_boundary == NULL) | 833 | { |
853 | { | 834 | pp->state = PP_Error; |
854 | pp->state = PP_Error; | 835 | return MHD_NO; |
855 | return MHD_NO; | 836 | } |
856 | } | 837 | pp->nested_boundary = |
857 | pp->nested_boundary = strdup(&pp->nested_boundary[strlen("boundary=")]); | 838 | strdup (&pp->nested_boundary[strlen ("boundary=")]); |
858 | if (pp->nested_boundary == NULL) | 839 | if (pp->nested_boundary == NULL) |
859 | { | 840 | { |
860 | /* out of memory */ | 841 | /* out of memory */ |
861 | pp->state = PP_Error; | 842 | pp->state = PP_Error; |
862 | return MHD_NO; | 843 | return MHD_NO; |
863 | } | 844 | } |
864 | /* free old content type, we will need that field | 845 | /* free old content type, we will need that field |
865 | for the content type of the nested elements */ | 846 | for the content type of the nested elements */ |
866 | free(pp->content_type); | 847 | free (pp->content_type); |
867 | pp->content_type = NULL; | 848 | pp->content_type = NULL; |
868 | pp->nlen = strlen(pp->nested_boundary); | 849 | pp->nlen = strlen (pp->nested_boundary); |
869 | pp->state = PP_Nested_Init; | 850 | pp->state = PP_Nested_Init; |
870 | max = 1; | 851 | state_changed = 1; |
871 | break; | 852 | break; |
872 | } | 853 | } |
873 | pp->state = PP_ProcessValueToBoundary; | 854 | pp->state = PP_ProcessValueToBoundary; |
874 | pp->value_offset = 0; | 855 | pp->value_offset = 0; |
875 | max = 1; | 856 | state_changed = 1; |
876 | break; | 857 | break; |
877 | case PP_ProcessValueToBoundary: | 858 | case PP_ProcessValueToBoundary: |
878 | if (MHD_NO == process_value_to_boundary(pp, | 859 | if (MHD_NO == process_value_to_boundary (pp, |
879 | &ioff, | 860 | &ioff, |
880 | pp->boundary, | 861 | pp->boundary, |
881 | pp->blen, | 862 | pp->blen, |
882 | PP_PerformCleanup, | 863 | PP_PerformCleanup, |
883 | PP_Done)) | 864 | PP_Done)) |
884 | { | 865 | { |
885 | if (pp->state == PP_Error) | 866 | if (pp->state == PP_Error) |
886 | return MHD_NO; | 867 | return MHD_NO; |
887 | break; | 868 | break; |
888 | } | 869 | } |
889 | break; | 870 | break; |
890 | case PP_PerformCleanup: | 871 | case PP_PerformCleanup: |
891 | /* clean up state of one multipart form-data element! */ | 872 | /* clean up state of one multipart form-data element! */ |
892 | pp->have = NE_none; | 873 | pp->have = NE_none; |
893 | free_unmarked(pp); | 874 | free_unmarked (pp); |
894 | if (pp->nested_boundary != NULL) | 875 | if (pp->nested_boundary != NULL) |
895 | { | 876 | { |
896 | free (pp->nested_boundary); | 877 | free (pp->nested_boundary); |
897 | pp->nested_boundary = NULL; | 878 | pp->nested_boundary = NULL; |
898 | } | 879 | } |
899 | pp->state = PP_ProcessEntryHeaders; | 880 | pp->state = PP_ProcessEntryHeaders; |
900 | max = 1; | 881 | state_changed = 1; |
901 | break; | 882 | break; |
902 | case PP_Nested_Init: | 883 | case PP_Nested_Init: |
903 | if (pp->nested_boundary == NULL) | 884 | if (pp->nested_boundary == NULL) |
904 | { | 885 | { |
905 | pp->state = PP_Error; | 886 | pp->state = PP_Error; |
906 | return MHD_NO; | 887 | return MHD_NO; |
907 | } | 888 | } |
908 | if (MHD_NO == find_boundary(pp, | 889 | if (MHD_NO == find_boundary (pp, |
909 | pp->nested_boundary, | 890 | pp->nested_boundary, |
910 | pp->nlen, | 891 | pp->nlen, |
911 | &ioff, | 892 | &ioff, |
912 | PP_Nested_PerformMarking, | 893 | PP_Nested_PerformMarking, |
913 | PP_Init /* or PP_Error? */)) | 894 | PP_Init /* or PP_Error? */ )) |
914 | { | 895 | { |
915 | if (pp->state == PP_Error) | 896 | if (pp->state == PP_Error) |
916 | return MHD_NO; | 897 | return MHD_NO; |
917 | goto END; | 898 | goto END; |
918 | } | 899 | } |
919 | break; | 900 | break; |
920 | case PP_Nested_PerformMarking: | 901 | case PP_Nested_PerformMarking: |
921 | /* remember what headers were given | 902 | /* remember what headers were given |
922 | globally */ | 903 | globally */ |
923 | pp->have = NE_none; | 904 | pp->have = NE_none; |
924 | if (pp->content_name != NULL) | 905 | if (pp->content_name != NULL) |
925 | pp->have |= NE_content_name; | 906 | pp->have |= NE_content_name; |
926 | if (pp->content_type != NULL) | 907 | if (pp->content_type != NULL) |
927 | pp->have |= NE_content_type; | 908 | pp->have |= NE_content_type; |
928 | if (pp->content_filename != NULL) | 909 | if (pp->content_filename != NULL) |
929 | pp->have |= NE_content_filename; | 910 | pp->have |= NE_content_filename; |
930 | if (pp->content_transfer_encoding != NULL) | 911 | if (pp->content_transfer_encoding != NULL) |
931 | pp->have |= NE_content_transfer_encoding; | 912 | pp->have |= NE_content_transfer_encoding; |
932 | pp->state = PP_Nested_ProcessEntryHeaders; | 913 | pp->state = PP_Nested_ProcessEntryHeaders; |
933 | max = 1; | 914 | state_changed = 1; |
934 | break; | 915 | break; |
935 | case PP_Nested_ProcessEntryHeaders: | 916 | case PP_Nested_ProcessEntryHeaders: |
936 | pp->value_offset = 0; | 917 | pp->value_offset = 0; |
937 | if (MHD_NO == process_multipart_headers(pp, &ioff, PP_Nested_ProcessValueToBoundary)) | 918 | if (MHD_NO == |
938 | { | 919 | process_multipart_headers (pp, &ioff, |
939 | if (pp->state == PP_Error) | 920 | PP_Nested_ProcessValueToBoundary)) |
940 | return MHD_NO; | 921 | { |
941 | else | 922 | if (pp->state == PP_Error) |
942 | goto END; | 923 | return MHD_NO; |
943 | } | 924 | else |
944 | max = 1; | 925 | goto END; |
926 | } | ||
927 | state_changed = 1; | ||
928 | break; | ||
929 | case PP_Nested_ProcessValueToBoundary: | ||
930 | if (MHD_NO == process_value_to_boundary (pp, | ||
931 | &ioff, | ||
932 | pp->nested_boundary, | ||
933 | pp->nlen, | ||
934 | PP_Nested_PerformCleanup, | ||
935 | PP_Init)) | ||
936 | { | ||
937 | if (pp->state == PP_Error) | ||
938 | return MHD_NO; | ||
939 | break; | ||
940 | } | ||
941 | break; | ||
942 | case PP_Nested_PerformCleanup: | ||
943 | free_unmarked (pp); | ||
944 | pp->state = PP_Nested_ProcessEntryHeaders; | ||
945 | state_changed = 1; | ||
945 | break; | 946 | break; |
946 | case PP_Nested_ProcessValueToBoundary: | ||
947 | if (MHD_NO == process_value_to_boundary(pp, | ||
948 | &ioff, | ||
949 | pp->nested_boundary, | ||
950 | pp->nlen, | ||
951 | PP_Nested_PerformCleanup, | ||
952 | PP_Init)) | ||
953 | { | ||
954 | if (pp->state == PP_Error) | ||
955 | return MHD_NO; | ||
956 | break; | ||
957 | } | ||
958 | break; | ||
959 | case PP_Nested_PerformCleanup: | ||
960 | free_unmarked(pp); | ||
961 | pp->state = PP_Nested_ProcessEntryHeaders; | ||
962 | max = 1; | ||
963 | break; | ||
964 | default: | 947 | default: |
965 | abort (); /* should never happen! */ | 948 | abort (); /* should never happen! */ |
966 | } | 949 | } |
967 | AGAIN: | 950 | AGAIN: |
968 | if (ioff > 0) | 951 | if (ioff > 0) |
969 | { | 952 | { |
970 | memmove (buf, &buf[ioff], pp->buffer_pos - ioff); | 953 | memmove (buf, &buf[ioff], pp->buffer_pos - ioff); |
971 | pp->buffer_pos -= ioff; | 954 | pp->buffer_pos -= ioff; |
972 | ioff = 0; | 955 | ioff = 0; |
973 | max = 1; | 956 | state_changed = 1; |
974 | } | 957 | } |
975 | } | 958 | } |
976 | END: | 959 | END: |
977 | if (ioff != 0) | 960 | if (ioff != 0) |
@@ -979,10 +962,10 @@ END: | |||
979 | memmove (buf, &buf[ioff], pp->buffer_pos - ioff); | 962 | memmove (buf, &buf[ioff], pp->buffer_pos - ioff); |
980 | pp->buffer_pos -= ioff; | 963 | pp->buffer_pos -= ioff; |
981 | } | 964 | } |
982 | if (poff < post_data_len) | 965 | if (poff < post_data_len) |
983 | { | 966 | { |
984 | pp->state = PP_Error; | 967 | pp->state = PP_Error; |
985 | return MHD_NO; /* serious error */ | 968 | return MHD_NO; /* serious error */ |
986 | } | 969 | } |
987 | return MHD_YES; | 970 | return MHD_YES; |
988 | } | 971 | } |
@@ -1027,9 +1010,9 @@ MHD_destroy_post_processor (struct MHD_PostProcessor *pp) | |||
1027 | the post-processing may have been interrupted | 1010 | the post-processing may have been interrupted |
1028 | at any stage */ | 1011 | at any stage */ |
1029 | pp->have = NE_none; | 1012 | pp->have = NE_none; |
1030 | free_unmarked(pp); | 1013 | free_unmarked (pp); |
1031 | if (pp->nested_boundary != NULL) | 1014 | if (pp->nested_boundary != NULL) |
1032 | free(pp->nested_boundary); | 1015 | free (pp->nested_boundary); |
1033 | free (pp); | 1016 | free (pp); |
1034 | } | 1017 | } |
1035 | 1018 | ||