aboutsummaryrefslogtreecommitdiff
path: root/src/daemon/postprocessor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon/postprocessor.c')
-rw-r--r--src/daemon/postprocessor.c745
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
62enum RN_State 62enum 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 */
98enum NE_State 98enum 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
459static int 458static int
460find_boundary(struct MHD_PostProcessor * pp, 459find_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 */
498static void 495static void
499try_get_value(const char * buf, 496try_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 */
551static int 542static int
552process_multipart_headers(struct MHD_PostProcessor * pp, 543process_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 */
617static int 603static int
618process_value_to_boundary(struct MHD_PostProcessor * pp, 604process_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
690static void 674static void
691free_unmarked(struct MHD_PostProcessor * pp) 675free_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 }
967AGAIN: 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 }
976END: 959END:
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