1/* 2 This file is part of libmicrohttpd 3 Copyright (C) 2007-2013 Daniel Pittman and Christian Grothoff 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18*/ 19 20/** 21 * @file postprocessor.c 22 * @brief Methods for parsing POST data 23 * @author Christian Grothoff 24 */ 25 26#include "internal.h" 27 28/** 29 * Size of on-stack buffer that we use for un-escaping of the value. 30 * We use a pretty small value to be nice to the stack on embedded 31 * systems. 32 */ 33#define XBUF_SIZE 512 34 35/** 36 * States in the PP parser's state machine. 37 */ 38enum PP_State 39{ 40 /* general states */ 41 PP_Error, 42 PP_Done, 43 PP_Init, 44 PP_NextBoundary, 45 46 /* url encoding-states */ 47 PP_ProcessValue, 48 PP_ExpectNewLine, 49 50 /* post encoding-states */ 51 PP_ProcessEntryHeaders, 52 PP_PerformCheckMultipart, 53 PP_ProcessValueToBoundary, 54 PP_PerformCleanup, 55 56 /* nested post-encoding states */ 57 PP_Nested_Init, 58 PP_Nested_PerformMarking, 59 PP_Nested_ProcessEntryHeaders, 60 PP_Nested_ProcessValueToBoundary, 61 PP_Nested_PerformCleanup 62 63}; 64 65 66enum RN_State 67{ 68 /** 69 * No RN-preprocessing in this state. 70 */ 71 RN_Inactive = 0, 72 73 /** 74 * If the next character is CR, skip it. Otherwise, 75 * just go inactive. 76 */ 77 RN_OptN = 1, 78 79 /** 80 * Expect LFCR (and only LFCR). As always, we also 81 * expect only LF or only CR. 82 */ 83 RN_Full = 2, 84 85 /** 86 * Expect either LFCR or '--'LFCR. If '--'LFCR, transition into dash-state 87 * for the main state machine 88 */ 89 RN_Dash = 3, 90 91 /** 92 * Got a single dash, expect second dash. 93 */ 94 RN_Dash2 = 4 95}; 96 97 98/** 99 * Bits for the globally known fields that 100 * should not be deleted when we exit the 101 * nested state. 102 */ 103enum NE_State 104{ 105 NE_none = 0, 106 NE_content_name = 1, 107 NE_content_type = 2, 108 NE_content_filename = 4, 109 NE_content_transfer_encoding = 8 110}; 111 112 113/** 114 * Internal state of the post-processor. Note that the fields 115 * are sorted by type to enable optimal packing by the compiler. 116 */ 117struct MHD_PostProcessor 118{ 119 120 /** 121 * The connection for which we are doing 122 * POST processing. 123 */ 124 struct MHD_Connection *connection; 125 126 /** 127 * Function to call with POST data. 128 */ 129 MHD_PostDataIterator ikvi; 130 131 /** 132 * Extra argument to ikvi. 133 */ 134 void *cls; 135 136 /** 137 * Encoding as given by the headers of the 138 * connection. 139 */ 140 const char *encoding; 141 142 /** 143 * Primary boundary (points into encoding string) 144 */ 145 const char *boundary; 146 147 /** 148 * Nested boundary (if we have multipart/mixed encoding). 149 */ 150 char *nested_boundary; 151 152 /** 153 * Pointer to the name given in disposition. 154 */ 155 char *content_name; 156 157 /** 158 * Pointer to the (current) content type. 159 */ 160 char *content_type; 161 162 /** 163 * Pointer to the (current) filename. 164 */ 165 char *content_filename; 166 167 /** 168 * Pointer to the (current) encoding. 169 */ 170 char *content_transfer_encoding; 171 172 /** 173 * Unprocessed value bytes due to escape 174 * sequences (URL-encoding only). 175 */ 176 char xbuf[8]; 177 178 /** 179 * Size of our buffer for the key. 180 */ 181 size_t buffer_size; 182 183 /** 184 * Current position in the key buffer. 185 */ 186 size_t buffer_pos; 187 188 /** 189 * Current position in xbuf. 190 */ 191 size_t xbuf_pos; 192 193 /** 194 * Current offset in the value being processed. 195 */ 196 uint64_t value_offset; 197 198 /** 199 * strlen(boundary) -- if boundary != NULL. 200 */ 201 size_t blen; 202 203 /** 204 * strlen(nested_boundary) -- if nested_boundary != NULL. 205 */ 206 size_t nlen; 207 208 /** 209 * Do we have to call the 'ikvi' callback when processing the 210 * multipart post body even if the size of the payload is zero? 211 * Set to #MHD_YES whenever we parse a new multiparty entry header, 212 * and to #MHD_NO the first time we call the 'ikvi' callback. 213 * Used to ensure that we do always call 'ikvi' even if the 214 * payload is empty (but not more than once). 215 */ 216 int must_ikvi; 217 218 /** 219 * State of the parser. 220 */ 221 enum PP_State state; 222 223 /** 224 * Side-state-machine: skip LRCR (or just LF). 225 * Set to 0 if we are not in skip mode. Set to 2 226 * if a LFCR is expected, set to 1 if a CR should 227 * be skipped if it is the next character. 228 */ 229 enum RN_State skip_rn; 230 231 /** 232 * If we are in skip_rn with "dash" mode and 233 * do find 2 dashes, what state do we go into? 234 */ 235 enum PP_State dash_state; 236 237 /** 238 * Which headers are global? (used to tell which 239 * headers were only valid for the nested multipart). 240 */ 241 enum NE_State have; 242 243}; 244 245 246/** 247 * Create a `struct MHD_PostProcessor`. 248 * 249 * A `struct MHD_PostProcessor` can be used to (incrementally) parse 250 * the data portion of a POST request. Note that some buggy browsers 251 * fail to set the encoding type. If you want to support those, you 252 * may have to call #MHD_set_connection_value with the proper encoding 253 * type before creating a post processor (if no supported encoding 254 * type is set, this function will fail). 255 * 256 * @param connection the connection on which the POST is 257 * happening (used to determine the POST format) 258 * @param buffer_size maximum number of bytes to use for 259 * internal buffering (used only for the parsing, 260 * specifically the parsing of the keys). A 261 * tiny value (256-1024) should be sufficient. 262 * Do NOT use a value smaller than 256. For good 263 * performance, use 32 or 64k (i.e. 65536). 264 * @param iter iterator to be called with the parsed data, 265 * Must NOT be NULL. 266 * @param iter_cls first argument to @a iter 267 * @return NULL on error (out of memory, unsupported encoding), 268 * otherwise a PP handle 269 * @ingroup request 270 */ 271struct MHD_PostProcessor * 272MHD_create_post_processor (struct MHD_Connection *connection, 273 size_t buffer_size, 274 MHD_PostDataIterator iter, void *iter_cls) 275{ 276 struct MHD_PostProcessor *ret; 277 const char *encoding; 278 const char *boundary; 279 size_t blen; 280 281 if ((buffer_size < 256) || (connection == NULL) || (iter == NULL)) 282 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); 283 encoding = MHD_lookup_connection_value (connection, 284 MHD_HEADER_KIND, 285 MHD_HTTP_HEADER_CONTENT_TYPE); 286 if (encoding == NULL) 287 return NULL; 288 boundary = NULL; 289 if (!MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, encoding, 290 strlen (MHD_HTTP_POST_ENCODING_FORM_URLENCODED))) 291 { 292 if (!MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, encoding, 293 strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA))) 294 return NULL; 295 boundary = 296 &encoding[strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)]; 297 /* Q: should this be "strcasestr"? */ 298 boundary = strstr (boundary, "boundary="); 299 if (NULL == boundary) 300 return NULL; /* failed to determine boundary */ 301 boundary += strlen ("boundary="); 302 blen = strlen (boundary); 303 if ((blen == 0) || (blen * 2 + 2 > buffer_size)) 304 return NULL; /* (will be) out of memory or invalid boundary */ 305 if ( (boundary[0] == '"') && (boundary[blen - 1] == '"') ) 306 { 307 /* remove enclosing quotes */ 308 ++boundary; 309 blen -= 2; 310 } 311 } 312 else 313 blen = 0; 314 buffer_size += 4; /* round up to get nice block sizes despite boundary search */ 315 316 /* add +1 to ensure we ALWAYS have a zero-termination at the end */ 317 if (NULL == (ret = malloc (sizeof (struct MHD_PostProcessor) + buffer_size + 1))) 318 return NULL; 319 memset (ret, 0, sizeof (struct MHD_PostProcessor) + buffer_size + 1); 320 ret->connection = connection; 321 ret->ikvi = iter; 322 ret->cls = iter_cls; 323 ret->encoding = encoding; 324 ret->buffer_size = buffer_size; 325 ret->state = PP_Init; 326 ret->blen = blen; 327 ret->boundary = boundary; 328 ret->skip_rn = RN_Inactive; 329 return ret; 330} 331 332 333/** 334 * Process url-encoded POST data. 335 * 336 * @param pp post processor context 337 * @param post_data upload data 338 * @param post_data_len number of bytes in @a post_data 339 * @return #MHD_YES on success, #MHD_NO if there was an error processing the data 340 */ 341static int 342post_process_urlencoded (struct MHD_PostProcessor *pp, 343 const char *post_data, 344 size_t post_data_len) 345{ 346 size_t equals; 347 size_t amper; 348 size_t poff; 349 size_t xoff; 350 size_t delta; 351 int end_of_value_found; 352 char *buf; 353 char xbuf[XBUF_SIZE + 1]; 354 355 buf = (char *) &pp[1]; 356 poff = 0; 357 while (poff < post_data_len) 358 { 359 switch (pp->state) 360 { 361 case PP_Error: 362 return MHD_NO; 363 case PP_Done: 364 /* did not expect to receive more data */ 365 pp->state = PP_Error; 366 return MHD_NO; 367 case PP_Init: 368 equals = 0; 369 while ((equals + poff < post_data_len) && 370 (post_data[equals + poff] != '=')) 371 equals++; 372 if (equals + pp->buffer_pos > pp->buffer_size) 373 { 374 pp->state = PP_Error; /* out of memory */ 375 return MHD_NO; 376 } 377 memcpy (&buf[pp->buffer_pos], &post_data[poff], equals); 378 pp->buffer_pos += equals; 379 if (equals + poff == post_data_len) 380 return MHD_YES; /* no '=' yet */ 381 buf[pp->buffer_pos] = '\0'; /* 0-terminate key */ 382 pp->buffer_pos = 0; /* reset for next key */ 383 MHD_unescape_plus (buf); 384 MHD_http_unescape (buf); 385 poff += equals + 1; 386 pp->state = PP_ProcessValue; 387 pp->value_offset = 0; 388 break; 389 case PP_ProcessValue: 390 /* obtain rest of value from previous iteration */ 391 memcpy (xbuf, pp->xbuf, pp->xbuf_pos); 392 xoff = pp->xbuf_pos; 393 pp->xbuf_pos = 0; 394 395 /* find last position in input buffer that is part of the value */ 396 amper = 0; 397 while ((amper + poff < post_data_len) && 398 (amper < XBUF_SIZE) && 399 (post_data[amper + poff] != '&') && 400 (post_data[amper + poff] != '\n') && 401 (post_data[amper + poff] != '\r')) 402 amper++; 403 end_of_value_found = ((amper + poff < post_data_len) && 404 ((post_data[amper + poff] == '&') || 405 (post_data[amper + poff] == '\n') || 406 (post_data[amper + poff] == '\r'))); 407 /* compute delta, the maximum number of bytes that we will be able to 408 process right now (either amper-limited of xbuf-size limited) */ 409 delta = amper; 410 if (delta > XBUF_SIZE - xoff) 411 delta = XBUF_SIZE - xoff; 412 413 /* move input into processing buffer */ 414 memcpy (&xbuf[xoff], &post_data[poff], delta); 415 xoff += delta; 416 poff += delta; 417 418 /* find if escape sequence is at the end of the processing buffer; 419 if so, exclude those from processing (reduce delta to point at 420 end of processed region) */ 421 delta = xoff; 422 if ((delta > 0) && (xbuf[delta - 1] == '%')) 423 delta--; 424 else if ((delta > 1) && (xbuf[delta - 2] == '%')) 425 delta -= 2; 426 427 /* if we have an incomplete escape sequence, save it to 428 pp->xbuf for later */ 429 if (delta < xoff) 430 { 431 memcpy (pp->xbuf, &xbuf[delta], xoff - delta); 432 pp->xbuf_pos = xoff - delta; 433 xoff = delta; 434 } 435 436 /* If we have nothing to do (delta == 0) and 437 not just because the value is empty (are 438 waiting for more data), go for next iteration */ 439 if ((xoff == 0) && (poff == post_data_len)) 440 continue; 441 442 /* unescape */ 443 xbuf[xoff] = '\0'; /* 0-terminate in preparation */ 444 MHD_unescape_plus (xbuf); 445 xoff = MHD_http_unescape (xbuf); 446 /* finally: call application! */ 447 pp->must_ikvi = MHD_NO; 448 if (MHD_NO == pp->ikvi (pp->cls, MHD_POSTDATA_KIND, (const char *) &pp[1], /* key */ 449 NULL, NULL, NULL, xbuf, pp->value_offset, 450 xoff)) 451 { 452 pp->state = PP_Error; 453 return MHD_NO; 454 } 455 pp->value_offset += xoff; 456 457 /* are we done with the value? */ 458 if (end_of_value_found) 459 { 460 /* we found the end of the value! */ 461 if ((post_data[poff] == '\n') || (post_data[poff] == '\r')) 462 { 463 pp->state = PP_ExpectNewLine; 464 } 465 else if (post_data[poff] == '&') 466 { 467 poff++; /* skip '&' */ 468 pp->state = PP_Init; 469 } 470 } 471 break; 472 case PP_ExpectNewLine: 473 if ((post_data[poff] == '\n') || (post_data[poff] == '\r')) 474 { 475 poff++; 476 /* we are done, report error if we receive any more... */ 477 pp->state = PP_Done; 478 return MHD_YES; 479 } 480 return MHD_NO; 481 default: 482 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); /* should never happen! */ 483 } 484 } 485 return MHD_YES; 486} 487 488 489/** 490 * If the given line matches the prefix, strdup the 491 * rest of the line into the suffix ptr. 492 * 493 * @param prefix prefix to match 494 * @param line line to match prefix in 495 * @param suffix set to a copy of the rest of the line, starting at the end of the match 496 * @return #MHD_YES if there was a match, #MHD_NO if not 497 */ 498static int 499try_match_header (const char *prefix, char *line, char **suffix) 500{ 501 if (NULL != *suffix) 502 return MHD_NO; 503 while (*line != 0) 504 { 505 if (MHD_str_equal_caseless_n_ (prefix, line, strlen (prefix))) 506 { 507 *suffix = strdup (&line[strlen (prefix)]); 508 return MHD_YES; 509 } 510 ++line; 511 } 512 return MHD_NO; 513} 514 515 516/** 517 * 518 * @param pp post processor context 519 * @param boundary boundary to look for 520 * @param blen number of bytes in boundary 521 * @param ioffptr set to the end of the boundary if found, 522 * otherwise incremented by one (FIXME: quirky API!) 523 * @param next_state state to which we should advance the post processor 524 * if the boundary is found 525 * @param next_dash_state dash_state to which we should advance the 526 * post processor if the boundary is found 527 * @return #MHD_NO if the boundary is not found, #MHD_YES if we did find it 528 */ 529static int 530find_boundary (struct MHD_PostProcessor *pp, 531 const char *boundary, 532 size_t blen, 533 size_t *ioffptr, 534 enum PP_State next_state, enum PP_State next_dash_state) 535{ 536 char *buf = (char *) &pp[1]; 537 const char *dash; 538 539 if (pp->buffer_pos < 2 + blen) 540 { 541 if (pp->buffer_pos == pp->buffer_size) 542 pp->state = PP_Error; /* out of memory */ 543 // ++(*ioffptr); 544 return MHD_NO; /* not enough data */ 545 } 546 if ((0 != memcmp ("--", buf, 2)) || (0 != memcmp (&buf[2], boundary, blen))) 547 { 548 if (pp->state != PP_Init) 549 { 550 /* garbage not allowed */ 551 pp->state = PP_Error; 552 } 553 else 554 { 555 /* skip over garbage (RFC 2046, 5.1.1) */ 556 dash = memchr (buf, '-', pp->buffer_pos); 557 if (NULL == dash) 558 (*ioffptr) += pp->buffer_pos; /* skip entire buffer */ 559 else 560 if (dash == buf) 561 (*ioffptr)++; /* at least skip one byte */ 562 else 563 (*ioffptr) += dash - buf; /* skip to first possible boundary */ 564 } 565 return MHD_NO; /* expected boundary */ 566 } 567 /* remove boundary from buffer */ 568 (*ioffptr) += 2 + blen; 569 /* next: start with headers */ 570 pp->skip_rn = RN_Dash; 571 pp->state = next_state; 572 pp->dash_state = next_dash_state; 573 return MHD_YES; 574} 575 576 577/** 578 * In buf, there maybe an expression '$key="$value"'. If that is the 579 * case, copy a copy of $value to destination. 580 * 581 * If destination is already non-NULL, do nothing. 582 */ 583static void 584try_get_value (const char *buf, 585 const char *key, 586 char **destination) 587{ 588 const char *spos; 589 const char *bpos; 590 const char *endv; 591 size_t klen; 592 size_t vlen; 593 594 if (NULL != *destination) 595 return; 596 bpos = buf; 597 klen = strlen (key); 598 while (NULL != (spos = strstr (bpos, key))) 599 { 600 if ((spos[klen] != '=') || ((spos != buf) && (spos[-1] != ' '))) 601 { 602 /* no match */ 603 bpos = spos + 1; 604 continue; 605 } 606 if (spos[klen + 1] != '"') 607 return; /* not quoted */ 608 if (NULL == (endv = strchr (&spos[klen + 2], '\"'))) 609 return; /* no end-quote */ 610 vlen = endv - spos - klen - 1; 611 *destination = malloc (vlen); 612 if (NULL == *destination) 613 return; /* out of memory */ 614 (*destination)[vlen - 1] = '\0'; 615 memcpy (*destination, &spos[klen + 2], vlen - 1); 616 return; /* success */ 617 } 618} 619 620 621/** 622 * Go over the headers of the part and update 623 * the fields in "pp" according to what we find. 624 * If we are at the end of the headers (as indicated 625 * by an empty line), transition into next_state. 626 * 627 * @param pp post processor context 628 * @param ioffptr set to how many bytes have been 629 * processed 630 * @param next_state state to which the post processor should 631 * be advanced if we find the end of the headers 632 * @return #MHD_YES if we can continue processing, 633 * #MHD_NO on error or if we do not have 634 * enough data yet 635 */ 636static int 637process_multipart_headers (struct MHD_PostProcessor *pp, 638 size_t *ioffptr, enum PP_State next_state) 639{ 640 char *buf = (char *) &pp[1]; 641 size_t newline; 642 643 newline = 0; 644 while ((newline < pp->buffer_pos) && 645 (buf[newline] != '\r') && (buf[newline] != '\n')) 646 newline++; 647 if (newline == pp->buffer_size) 648 { 649 pp->state = PP_Error; 650 return MHD_NO; /* out of memory */ 651 } 652 if (newline == pp->buffer_pos) 653 return MHD_NO; /* will need more data */ 654 if (0 == newline) 655 { 656 /* empty line - end of headers */ 657 pp->skip_rn = RN_Full; 658 pp->state = next_state; 659 return MHD_YES; 660 } 661 /* got an actual header */ 662 if (buf[newline] == '\r') 663 pp->skip_rn = RN_OptN; 664 buf[newline] = '\0'; 665 if (MHD_str_equal_caseless_n_ ("Content-disposition: ", 666 buf, strlen ("Content-disposition: "))) 667 { 668 try_get_value (&buf[strlen ("Content-disposition: ")], 669 "name", &pp->content_name); 670 try_get_value (&buf[strlen ("Content-disposition: ")], 671 "filename", &pp->content_filename); 672 } 673 else 674 { 675 try_match_header ("Content-type: ", buf, &pp->content_type); 676 try_match_header ("Content-Transfer-Encoding: ", 677 buf, &pp->content_transfer_encoding); 678 } 679 (*ioffptr) += newline + 1; 680 return MHD_YES; 681} 682 683 684/** 685 * We have the value until we hit the given boundary; 686 * process accordingly. 687 * 688 * @param pp post processor context 689 * @param ioffptr incremented based on the number of bytes processed 690 * @param boundary the boundary to look for 691 * @param blen strlen(boundary) 692 * @param next_state what state to go into after the 693 * boundary was found 694 * @param next_dash_state state to go into if the next 695 * boundary ends with "--" 696 * @return #MHD_YES if we can continue processing, 697 * #MHD_NO on error or if we do not have 698 * enough data yet 699 */ 700static int 701process_value_to_boundary (struct MHD_PostProcessor *pp, 702 size_t *ioffptr, 703 const char *boundary, 704 size_t blen, 705 enum PP_State next_state, 706 enum PP_State next_dash_state) 707{ 708 char *buf = (char *) &pp[1]; 709 size_t newline; 710 const char *r; 711 712 /* all data in buf until the boundary 713 (\r\n--+boundary) is part of the value */ 714 newline = 0; 715 while (1) 716 { 717 while (newline + 4 < pp->buffer_pos) 718 { 719 r = memchr (&buf[newline], '\r', pp->buffer_pos - newline - 4); 720 if (NULL == r) 721 { 722 newline = pp->buffer_pos - 4; 723 break; 724 } 725 newline = r - buf; 726 if (0 == memcmp ("\r\n--", &buf[newline], 4)) 727 break; 728 newline++; 729 } 730 if (newline + pp->blen + 4 <= pp->buffer_pos) 731 { 732 /* can check boundary */ 733 if (0 != memcmp (&buf[newline + 4], boundary, pp->blen)) 734 { 735 /* no boundary, "\r\n--" is part of content, skip */ 736 newline += 4; 737 continue; 738 } 739 else 740 { 741 /* boundary found, process until newline then 742 skip boundary and go back to init */ 743 pp->skip_rn = RN_Dash; 744 pp->state = next_state; 745 pp->dash_state = next_dash_state; 746 (*ioffptr) += pp->blen + 4; /* skip boundary as well */ 747 buf[newline] = '\0'; 748 break; 749 } 750 } 751 else 752 { 753 /* cannot check for boundary, process content that 754 we have and check again later; except, if we have 755 no content, abort (out of memory) */ 756 if ((0 == newline) && (pp->buffer_pos == pp->buffer_size)) 757 { 758 pp->state = PP_Error; 759 return MHD_NO; 760 } 761 break; 762 } 763 } 764 /* newline is either at beginning of boundary or 765 at least at the last character that we are sure 766 is not part of the boundary */ 767 if ( ( (MHD_YES == pp->must_ikvi) || 768 (0 != newline) ) && 769 (MHD_NO == pp->ikvi (pp->cls, 770 MHD_POSTDATA_KIND, 771 pp->content_name, 772 pp->content_filename, 773 pp->content_type, 774 pp->content_transfer_encoding, 775 buf, pp->value_offset, newline)) ) 776 { 777 pp->state = PP_Error; 778 return MHD_NO; 779 } 780 pp->must_ikvi = MHD_NO; 781 pp->value_offset += newline; 782 (*ioffptr) += newline; 783 return MHD_YES; 784} 785 786 787/** 788 * 789 * @param pp post processor context 790 */ 791static void 792free_unmarked (struct MHD_PostProcessor *pp) 793{ 794 if ((NULL != pp->content_name) && (0 == (pp->have & NE_content_name))) 795 { 796 free (pp->content_name); 797 pp->content_name = NULL; 798 } 799 if ((NULL != pp->content_type) && (0 == (pp->have & NE_content_type))) 800 { 801 free (pp->content_type); 802 pp->content_type = NULL; 803 } 804 if ((NULL != pp->content_filename) && 805 (0 == (pp->have & NE_content_filename))) 806 { 807 free (pp->content_filename); 808 pp->content_filename = NULL; 809 } 810 if ((NULL != pp->content_transfer_encoding) && 811 (0 == (pp->have & NE_content_transfer_encoding))) 812 { 813 free (pp->content_transfer_encoding); 814 pp->content_transfer_encoding = NULL; 815 } 816} 817 818 819/** 820 * Decode multipart POST data. 821 * 822 * @param pp post processor context 823 * @param post_data data to decode 824 * @param post_data_len number of bytes in @a post_data 825 * @return #MHD_NO on error, 826 */ 827static int 828post_process_multipart (struct MHD_PostProcessor *pp, 829 const char *post_data, 830 size_t post_data_len) 831{ 832 char *buf; 833 size_t max; 834 size_t ioff; 835 size_t poff; 836 int state_changed; 837 838 buf = (char *) &pp[1]; 839 ioff = 0; 840 poff = 0; 841 state_changed = 1; 842 while ((poff < post_data_len) || 843 ((pp->buffer_pos > 0) && (state_changed != 0))) 844 { 845 /* first, move as much input data 846 as possible to our internal buffer */ 847 max = pp->buffer_size - pp->buffer_pos; 848 if (max > post_data_len - poff) 849 max = post_data_len - poff; 850 memcpy (&buf[pp->buffer_pos], &post_data[poff], max); 851 poff += max; 852 pp->buffer_pos += max; 853 if ((max == 0) && (state_changed == 0) && (poff < post_data_len)) 854 { 855 pp->state = PP_Error; 856 return MHD_NO; /* out of memory */ 857 } 858 state_changed = 0; 859 860 /* first state machine for '\r'-'\n' and '--' handling */ 861 switch (pp->skip_rn) 862 { 863 case RN_Inactive: 864 break; 865 case RN_OptN: 866 if (buf[0] == '\n') 867 { 868 ioff++; 869 pp->skip_rn = RN_Inactive; 870 goto AGAIN; 871 } 872 /* fall-through! */ 873 case RN_Dash: 874 if (buf[0] == '-') 875 { 876 ioff++; 877 pp->skip_rn = RN_Dash2; 878 goto AGAIN; 879 } 880 pp->skip_rn = RN_Full; 881 /* fall-through! */ 882 case RN_Full: 883 if (buf[0] == '\r') 884 { 885 if ((pp->buffer_pos > 1) && (buf[1] == '\n')) 886 { 887 pp->skip_rn = RN_Inactive; 888 ioff += 2; 889 } 890 else 891 { 892 pp->skip_rn = RN_OptN; 893 ioff++; 894 } 895 goto AGAIN; 896 } 897 if (buf[0] == '\n') 898 { 899 ioff++; 900 pp->skip_rn = RN_Inactive; 901 goto AGAIN; 902 } 903 pp->skip_rn = RN_Inactive; 904 pp->state = PP_Error; 905 return MHD_NO; /* no '\r\n' */ 906 case RN_Dash2: 907 if (buf[0] == '-') 908 { 909 ioff++; 910 pp->skip_rn = RN_Full; 911 pp->state = pp->dash_state; 912 goto AGAIN; 913 } 914 pp->state = PP_Error; 915 break; 916 } 917 918 /* main state engine */ 919 switch (pp->state) 920 { 921 case PP_Error: 922 return MHD_NO; 923 case PP_Done: 924 /* did not expect to receive more data */ 925 pp->state = PP_Error; 926 return MHD_NO; 927 case PP_Init: 928 /** 929 * Per RFC2046 5.1.1 NOTE TO IMPLEMENTORS, consume anything 930 * prior to the first multipart boundary: 931 * 932 * > There appears to be room for additional information prior 933 * > to the first boundary delimiter line and following the 934 * > final boundary delimiter line. These areas should 935 * > generally be left blank, and implementations must ignore 936 * > anything that appears before the first boundary delimiter 937 * > line or after the last one. 938 */ 939 (void) find_boundary (pp, 940 pp->boundary, 941 pp->blen, 942 &ioff, 943 PP_ProcessEntryHeaders, PP_Done); 944 break; 945 case PP_NextBoundary: 946 if (MHD_NO == find_boundary (pp, 947 pp->boundary, 948 pp->blen, 949 &ioff, 950 PP_ProcessEntryHeaders, PP_Done)) 951 { 952 if (pp->state == PP_Error) 953 return MHD_NO; 954 goto END; 955 } 956 break; 957 case PP_ProcessEntryHeaders: 958 pp->must_ikvi = MHD_YES; 959 if (MHD_NO == 960 process_multipart_headers (pp, &ioff, PP_PerformCheckMultipart)) 961 { 962 if (pp->state == PP_Error) 963 return MHD_NO; 964 else 965 goto END; 966 } 967 state_changed = 1; 968 break; 969 case PP_PerformCheckMultipart: 970 if ((pp->content_type != NULL) && 971 (MHD_str_equal_caseless_n_ (pp->content_type, 972 "multipart/mixed", 973 strlen ("multipart/mixed")))) 974 { 975 pp->nested_boundary = strstr (pp->content_type, "boundary="); 976 if (pp->nested_boundary == NULL) 977 { 978 pp->state = PP_Error; 979 return MHD_NO; 980 } 981 pp->nested_boundary = 982 strdup (&pp->nested_boundary[strlen ("boundary=")]); 983 if (pp->nested_boundary == NULL) 984 { 985 /* out of memory */ 986 pp->state = PP_Error; 987 return MHD_NO; 988 } 989 /* free old content type, we will need that field 990 for the content type of the nested elements */ 991 free (pp->content_type); 992 pp->content_type = NULL; 993 pp->nlen = strlen (pp->nested_boundary); 994 pp->state = PP_Nested_Init; 995 state_changed = 1; 996 break; 997 } 998 pp->state = PP_ProcessValueToBoundary; 999 pp->value_offset = 0; 1000 state_changed = 1; 1001 break; 1002 case PP_ProcessValueToBoundary: 1003 if (MHD_NO == process_value_to_boundary (pp, 1004 &ioff, 1005 pp->boundary, 1006 pp->blen, 1007 PP_PerformCleanup, 1008 PP_Done)) 1009 { 1010 if (pp->state == PP_Error) 1011 return MHD_NO; 1012 break; 1013 } 1014 break; 1015 case PP_PerformCleanup: 1016 /* clean up state of one multipart form-data element! */ 1017 pp->have = NE_none; 1018 free_unmarked (pp); 1019 if (pp->nested_boundary != NULL) 1020 { 1021 free (pp->nested_boundary); 1022 pp->nested_boundary = NULL; 1023 } 1024 pp->state = PP_ProcessEntryHeaders; 1025 state_changed = 1; 1026 break; 1027 case PP_Nested_Init: 1028 if (pp->nested_boundary == NULL) 1029 { 1030 pp->state = PP_Error; 1031 return MHD_NO; 1032 } 1033 if (MHD_NO == find_boundary (pp, 1034 pp->nested_boundary, 1035 pp->nlen, 1036 &ioff, 1037 PP_Nested_PerformMarking, 1038 PP_NextBoundary /* or PP_Error? */ )) 1039 { 1040 if (pp->state == PP_Error) 1041 return MHD_NO; 1042 goto END; 1043 } 1044 break; 1045 case PP_Nested_PerformMarking: 1046 /* remember what headers were given 1047 globally */ 1048 pp->have = NE_none; 1049 if (pp->content_name != NULL) 1050 pp->have |= NE_content_name; 1051 if (pp->content_type != NULL) 1052 pp->have |= NE_content_type; 1053 if (pp->content_filename != NULL) 1054 pp->have |= NE_content_filename; 1055 if (pp->content_transfer_encoding != NULL) 1056 pp->have |= NE_content_transfer_encoding; 1057 pp->state = PP_Nested_ProcessEntryHeaders; 1058 state_changed = 1; 1059 break; 1060 case PP_Nested_ProcessEntryHeaders: 1061 pp->value_offset = 0; 1062 if (MHD_NO == 1063 process_multipart_headers (pp, &ioff, 1064 PP_Nested_ProcessValueToBoundary)) 1065 { 1066 if (pp->state == PP_Error) 1067 return MHD_NO; 1068 else 1069 goto END; 1070 } 1071 state_changed = 1; 1072 break; 1073 case PP_Nested_ProcessValueToBoundary: 1074 if (MHD_NO == process_value_to_boundary (pp, 1075 &ioff, 1076 pp->nested_boundary, 1077 pp->nlen, 1078 PP_Nested_PerformCleanup, 1079 PP_NextBoundary)) 1080 { 1081 if (pp->state == PP_Error) 1082 return MHD_NO; 1083 break; 1084 } 1085 break; 1086 case PP_Nested_PerformCleanup: 1087 free_unmarked (pp); 1088 pp->state = PP_Nested_ProcessEntryHeaders; 1089 state_changed = 1; 1090 break; 1091 default: 1092 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); /* should never happen! */ 1093 } 1094 AGAIN: 1095 if (ioff > 0) 1096 { 1097 memmove (buf, &buf[ioff], pp->buffer_pos - ioff); 1098 pp->buffer_pos -= ioff; 1099 ioff = 0; 1100 state_changed = 1; 1101 } 1102 } 1103END: 1104 if (ioff != 0) 1105 { 1106 memmove (buf, &buf[ioff], pp->buffer_pos - ioff); 1107 pp->buffer_pos -= ioff; 1108 } 1109 if (poff < post_data_len) 1110 { 1111 pp->state = PP_Error; 1112 return MHD_NO; /* serious error */ 1113 } 1114 return MHD_YES; 1115} 1116 1117 1118/** 1119 * Parse and process POST data. Call this function when POST data is 1120 * available (usually during an #MHD_AccessHandlerCallback) with the 1121 * "upload_data" and "upload_data_size". Whenever possible, this will 1122 * then cause calls to the #MHD_PostDataIterator. 1123 * 1124 * @param pp the post processor 1125 * @param post_data @a post_data_len bytes of POST data 1126 * @param post_data_len length of @a post_data 1127 * @return #MHD_YES on success, #MHD_NO on error 1128 * (out-of-memory, iterator aborted, parse error) 1129 * @ingroup request 1130 */ 1131int 1132MHD_post_process (struct MHD_PostProcessor *pp, 1133 const char *post_data, size_t post_data_len) 1134{ 1135 if (0 == post_data_len) 1136 return MHD_YES; 1137 if (NULL == pp) 1138 return MHD_NO; 1139 if (MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, pp->encoding, 1140 strlen(MHD_HTTP_POST_ENCODING_FORM_URLENCODED))) 1141 return post_process_urlencoded (pp, post_data, post_data_len); 1142 if (MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, pp->encoding, 1143 strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA))) 1144 return post_process_multipart (pp, post_data, post_data_len); 1145 /* this should never be reached */ 1146 return MHD_NO; 1147} 1148 1149 1150/** 1151 * Release PostProcessor resources. 1152 * 1153 * @param pp post processor context to destroy 1154 * @return #MHD_YES if processing completed nicely, 1155 * #MHD_NO if there were spurious characters / formatting 1156 * problems; it is common to ignore the return 1157 * value of this function 1158 * @ingroup request 1159 */ 1160int 1161MHD_destroy_post_processor (struct MHD_PostProcessor *pp) 1162{ 1163 int ret; 1164 1165 if (NULL == pp) 1166 return MHD_YES; 1167 if (PP_ProcessValue == pp->state) 1168 { 1169 /* key without terminated value left at the end of the 1170 buffer; fake receiving a termination character to 1171 ensure it is also processed */ 1172 post_process_urlencoded (pp, "\n", 1); 1173 } 1174 /* These internal strings need cleaning up since 1175 the post-processing may have been interrupted 1176 at any stage */ 1177 if ((pp->xbuf_pos > 0) || 1178 ( (pp->state != PP_Done) && 1179 (pp->state != PP_ExpectNewLine))) 1180 ret = MHD_NO; 1181 else 1182 ret = MHD_YES; 1183 pp->have = NE_none; 1184 free_unmarked (pp); 1185 if (pp->nested_boundary != NULL) 1186 free (pp->nested_boundary); 1187 free (pp); 1188 return ret; 1189} 1190 1191/* end of postprocessor.c */ 1192