|
GNU libmicrohttpd
0.9.5
|
00001 /* 00002 This file is part of libmicrohttpd 00003 (C) 2007, 2009, 2010, 2011, 2012 Daniel Pittman and Christian Grothoff 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Lesser General Public 00007 License as published by the Free Software Foundation; either 00008 version 2.1 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Lesser General Public License for more details. 00014 00015 You should have received a copy of the GNU Lesser General Public 00016 License along with this library; if not, write to the Free Software 00017 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00018 */ 00019 00026 #include "internal.h" 00027 00033 #define XBUF_SIZE 512 00034 00038 enum PP_State 00039 { 00040 /* general states */ 00041 PP_Error, 00042 PP_Done, 00043 PP_Init, 00044 PP_NextBoundary, 00045 00046 /* url encoding-states */ 00047 PP_ProcessValue, 00048 PP_ExpectNewLine, 00049 00050 /* post encoding-states */ 00051 PP_ProcessEntryHeaders, 00052 PP_PerformCheckMultipart, 00053 PP_ProcessValueToBoundary, 00054 PP_PerformCleanup, 00055 00056 /* nested post-encoding states */ 00057 PP_Nested_Init, 00058 PP_Nested_PerformMarking, 00059 PP_Nested_ProcessEntryHeaders, 00060 PP_Nested_ProcessValueToBoundary, 00061 PP_Nested_PerformCleanup, 00062 00063 }; 00064 00065 enum RN_State 00066 { 00070 RN_Inactive = 0, 00071 00076 RN_OptN = 1, 00077 00082 RN_Full = 2, 00083 00088 RN_Dash = 3, 00089 00093 RN_Dash2 = 4, 00094 }; 00095 00101 enum NE_State 00102 { 00103 NE_none = 0, 00104 NE_content_name = 1, 00105 NE_content_type = 2, 00106 NE_content_filename = 4, 00107 NE_content_transfer_encoding = 8, 00108 }; 00109 00114 struct MHD_PostProcessor 00115 { 00116 00121 struct MHD_Connection *connection; 00122 00126 MHD_PostDataIterator ikvi; 00127 00131 void *cls; 00132 00137 const char *encoding; 00138 00142 const char *boundary; 00143 00147 char *nested_boundary; 00148 00152 char *content_name; 00153 00157 char *content_type; 00158 00162 char *content_filename; 00163 00167 char *content_transfer_encoding; 00168 00173 char xbuf[8]; 00174 00178 size_t buffer_size; 00179 00183 size_t buffer_pos; 00184 00188 size_t xbuf_pos; 00189 00193 uint64_t value_offset; 00194 00198 size_t blen; 00199 00203 size_t nlen; 00204 00208 enum PP_State state; 00209 00216 enum RN_State skip_rn; 00217 00222 enum PP_State dash_state; 00223 00228 enum NE_State have; 00229 00230 }; 00231 00232 00251 struct MHD_PostProcessor * 00252 MHD_create_post_processor (struct MHD_Connection *connection, 00253 size_t buffer_size, 00254 MHD_PostDataIterator ikvi, void *cls) 00255 { 00256 struct MHD_PostProcessor *ret; 00257 const char *encoding; 00258 const char *boundary; 00259 size_t blen; 00260 00261 if ((buffer_size < 256) || (connection == NULL) || (ikvi == NULL)) 00262 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); 00263 encoding = MHD_lookup_connection_value (connection, 00264 MHD_HEADER_KIND, 00265 MHD_HTTP_HEADER_CONTENT_TYPE); 00266 if (encoding == NULL) 00267 return NULL; 00268 boundary = NULL; 00269 if (0 != strncasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, encoding, 00270 strlen (MHD_HTTP_POST_ENCODING_FORM_URLENCODED))) 00271 { 00272 if (0 != 00273 strncasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, encoding, 00274 strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA))) 00275 return NULL; 00276 boundary = 00277 &encoding[strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)]; 00278 /* Q: should this be "strcasestr"? */ 00279 boundary = strstr (boundary, "boundary="); 00280 if (NULL == boundary) 00281 return NULL; /* failed to determine boundary */ 00282 boundary += strlen ("boundary="); 00283 blen = strlen (boundary); 00284 if ((blen == 0) || (blen * 2 + 2 > buffer_size)) 00285 return NULL; /* (will be) out of memory or invalid boundary */ 00286 if ( (boundary[0] == '"') && (boundary[blen - 1] == '"') ) 00287 { 00288 /* remove enclosing quotes */ 00289 ++boundary; 00290 blen -= 2; 00291 } 00292 } 00293 else 00294 blen = 0; 00295 ret = malloc (sizeof (struct MHD_PostProcessor) + buffer_size + 1); 00296 if (ret == NULL) 00297 return NULL; 00298 memset (ret, 0, sizeof (struct MHD_PostProcessor) + buffer_size + 1); 00299 ret->connection = connection; 00300 ret->ikvi = ikvi; 00301 ret->cls = cls; 00302 ret->encoding = encoding; 00303 ret->buffer_size = buffer_size; 00304 ret->state = PP_Init; 00305 ret->blen = blen; 00306 ret->boundary = boundary; 00307 ret->skip_rn = RN_Inactive; 00308 return ret; 00309 } 00310 00314 static int 00315 post_process_urlencoded (struct MHD_PostProcessor *pp, 00316 const char *post_data, 00317 size_t post_data_len) 00318 { 00319 size_t equals; 00320 size_t amper; 00321 size_t poff; 00322 size_t xoff; 00323 size_t delta; 00324 int end_of_value_found; 00325 char *buf; 00326 char xbuf[XBUF_SIZE + 1]; 00327 00328 buf = (char *) &pp[1]; 00329 poff = 0; 00330 while (poff < post_data_len) 00331 { 00332 switch (pp->state) 00333 { 00334 case PP_Error: 00335 return MHD_NO; 00336 case PP_Done: 00337 /* did not expect to receive more data */ 00338 pp->state = PP_Error; 00339 return MHD_NO; 00340 case PP_Init: 00341 equals = 0; 00342 while ((equals + poff < post_data_len) && 00343 (post_data[equals + poff] != '=')) 00344 equals++; 00345 if (equals + pp->buffer_pos > pp->buffer_size) 00346 { 00347 pp->state = PP_Error; /* out of memory */ 00348 return MHD_NO; 00349 } 00350 memcpy (&buf[pp->buffer_pos], &post_data[poff], equals); 00351 pp->buffer_pos += equals; 00352 if (equals + poff == post_data_len) 00353 return MHD_YES; /* no '=' yet */ 00354 buf[pp->buffer_pos] = '\0'; /* 0-terminate key */ 00355 pp->buffer_pos = 0; /* reset for next key */ 00356 MHD_http_unescape (NULL, NULL, buf); 00357 poff += equals + 1; 00358 pp->state = PP_ProcessValue; 00359 pp->value_offset = 0; 00360 break; 00361 case PP_ProcessValue: 00362 /* obtain rest of value from previous iteration */ 00363 memcpy (xbuf, pp->xbuf, pp->xbuf_pos); 00364 xoff = pp->xbuf_pos; 00365 pp->xbuf_pos = 0; 00366 00367 /* find last position in input buffer that is part of the value */ 00368 amper = 0; 00369 while ((amper + poff < post_data_len) && 00370 (amper < XBUF_SIZE) && 00371 (post_data[amper + poff] != '&') && 00372 (post_data[amper + poff] != '\n') && 00373 (post_data[amper + poff] != '\r')) 00374 amper++; 00375 end_of_value_found = ((amper + poff < post_data_len) && 00376 ((post_data[amper + poff] == '&') || 00377 (post_data[amper + poff] == '\n') || 00378 (post_data[amper + poff] == '\r'))); 00379 /* compute delta, the maximum number of bytes that we will be able to 00380 process right now (either amper-limited of xbuf-size limited) */ 00381 delta = amper; 00382 if (delta > XBUF_SIZE - xoff) 00383 delta = XBUF_SIZE - xoff; 00384 00385 /* move input into processing buffer */ 00386 memcpy (&xbuf[xoff], &post_data[poff], delta); 00387 xoff += delta; 00388 poff += delta; 00389 00390 /* find if escape sequence is at the end of the processing buffer; 00391 if so, exclude those from processing (reduce delta to point at 00392 end of processed region) */ 00393 delta = xoff; 00394 if ((delta > 0) && (xbuf[delta - 1] == '%')) 00395 delta--; 00396 else if ((delta > 1) && (xbuf[delta - 2] == '%')) 00397 delta -= 2; 00398 00399 /* if we have an incomplete escape sequence, save it to 00400 pp->xbuf for later */ 00401 if (delta < xoff) 00402 { 00403 memcpy (pp->xbuf, &xbuf[delta], xoff - delta); 00404 pp->xbuf_pos = xoff - delta; 00405 xoff = delta; 00406 } 00407 00408 /* If we have nothing to do (delta == 0) and 00409 not just because the value is empty (are 00410 waiting for more data), go for next iteration */ 00411 if ((xoff == 0) && (poff == post_data_len)) 00412 continue; 00413 00414 /* unescape */ 00415 xbuf[xoff] = '\0'; /* 0-terminate in preparation */ 00416 xoff = MHD_http_unescape (NULL, NULL, xbuf); 00417 /* finally: call application! */ 00418 if (MHD_NO == pp->ikvi (pp->cls, MHD_POSTDATA_KIND, (const char *) &pp[1], /* key */ 00419 NULL, NULL, NULL, xbuf, pp->value_offset, 00420 xoff)) 00421 { 00422 pp->state = PP_Error; 00423 return MHD_NO; 00424 } 00425 pp->value_offset += xoff; 00426 00427 /* are we done with the value? */ 00428 if (end_of_value_found) 00429 { 00430 /* we found the end of the value! */ 00431 if ((post_data[poff] == '\n') || (post_data[poff] == '\r')) 00432 { 00433 pp->state = PP_ExpectNewLine; 00434 } 00435 else 00436 { 00437 poff++; /* skip '&' */ 00438 pp->state = PP_Init; 00439 } 00440 } 00441 break; 00442 case PP_ExpectNewLine: 00443 if ((post_data[poff] == '\n') || (post_data[poff] == '\r')) 00444 { 00445 poff++; 00446 /* we are done, report error if we receive any more... */ 00447 pp->state = PP_Done; 00448 return MHD_YES; 00449 } 00450 return MHD_NO; 00451 default: 00452 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); /* should never happen! */ 00453 } 00454 } 00455 return MHD_YES; 00456 } 00457 00464 static int 00465 try_match_header (const char *prefix, char *line, char **suffix) 00466 { 00467 if (NULL != *suffix) 00468 return MHD_NO; 00469 while (*line != 0) 00470 { 00471 if (0 == strncasecmp (prefix, line, strlen (prefix))) 00472 { 00473 *suffix = strdup (&line[strlen (prefix)]); 00474 return MHD_YES; 00475 } 00476 ++line; 00477 } 00478 return MHD_NO; 00479 } 00480 00481 static int 00482 find_boundary (struct MHD_PostProcessor *pp, 00483 const char *boundary, 00484 size_t blen, 00485 size_t *ioffptr, 00486 enum PP_State next_state, enum PP_State next_dash_state) 00487 { 00488 char *buf = (char *) &pp[1]; 00489 00490 if (pp->buffer_pos < 2 + blen) 00491 { 00492 if (pp->buffer_pos == pp->buffer_size) 00493 pp->state = PP_Error; /* out of memory */ 00494 return MHD_NO; /* not enough data */ 00495 } 00496 if ((0 != memcmp ("--", buf, 2)) || (0 != memcmp (&buf[2], boundary, blen))) 00497 { 00498 if (pp->state != PP_Init) 00499 pp->state = PP_Error; 00500 return MHD_NO; /* expected boundary */ 00501 } 00502 /* remove boundary from buffer */ 00503 (*ioffptr) += 2 + blen; 00504 /* next: start with headers */ 00505 pp->skip_rn = RN_Dash; 00506 pp->state = next_state; 00507 pp->dash_state = next_dash_state; 00508 return MHD_YES; 00509 } 00510 00519 static void 00520 try_get_value (const char *buf, const char *key, char **destination) 00521 { 00522 const char *spos; 00523 const char *bpos; 00524 const char *endv; 00525 size_t klen; 00526 size_t vlen; 00527 00528 if (NULL != *destination) 00529 return; 00530 bpos = buf; 00531 klen = strlen (key); 00532 while (NULL != (spos = strstr (bpos, key))) 00533 { 00534 if ((spos[klen] != '=') || ((spos != buf) && (spos[-1] != ' '))) 00535 { 00536 /* no match */ 00537 bpos = spos + 1; 00538 continue; 00539 } 00540 if (spos[klen + 1] != '"') 00541 return; /* not quoted */ 00542 if (NULL == (endv = strchr (&spos[klen + 2], '\"'))) 00543 return; /* no end-quote */ 00544 vlen = endv - spos - klen - 1; 00545 *destination = malloc (vlen); 00546 if (NULL == *destination) 00547 return; /* out of memory */ 00548 (*destination)[vlen - 1] = '\0'; 00549 memcpy (*destination, &spos[klen + 2], vlen - 1); 00550 return; /* success */ 00551 } 00552 } 00553 00566 static int 00567 process_multipart_headers (struct MHD_PostProcessor *pp, 00568 size_t *ioffptr, enum PP_State next_state) 00569 { 00570 char *buf = (char *) &pp[1]; 00571 size_t newline; 00572 00573 newline = 0; 00574 while ((newline < pp->buffer_pos) && 00575 (buf[newline] != '\r') && (buf[newline] != '\n')) 00576 newline++; 00577 if (newline == pp->buffer_size) 00578 { 00579 pp->state = PP_Error; 00580 return MHD_NO; /* out of memory */ 00581 } 00582 if (newline == pp->buffer_pos) 00583 return MHD_NO; /* will need more data */ 00584 if (newline == 0) 00585 { 00586 /* empty line - end of headers */ 00587 pp->skip_rn = RN_Full; 00588 pp->state = next_state; 00589 return MHD_YES; 00590 } 00591 /* got an actual header */ 00592 if (buf[newline] == '\r') 00593 pp->skip_rn = RN_OptN; 00594 buf[newline] = '\0'; 00595 if (0 == strncasecmp ("Content-disposition: ", 00596 buf, strlen ("Content-disposition: "))) 00597 { 00598 try_get_value (&buf[strlen ("Content-disposition: ")], 00599 "name", &pp->content_name); 00600 try_get_value (&buf[strlen ("Content-disposition: ")], 00601 "filename", &pp->content_filename); 00602 } 00603 else 00604 { 00605 try_match_header ("Content-type: ", buf, &pp->content_type); 00606 try_match_header ("Content-Transfer-Encoding: ", 00607 buf, &pp->content_transfer_encoding); 00608 } 00609 (*ioffptr) += newline + 1; 00610 return MHD_YES; 00611 } 00612 00627 static int 00628 process_value_to_boundary (struct MHD_PostProcessor *pp, 00629 size_t *ioffptr, 00630 const char *boundary, 00631 size_t blen, 00632 enum PP_State next_state, 00633 enum PP_State next_dash_state) 00634 { 00635 char *buf = (char *) &pp[1]; 00636 size_t newline; 00637 00638 /* all data in buf until the boundary 00639 (\r\n--+boundary) is part of the value */ 00640 newline = 0; 00641 while (1) 00642 { 00643 while ((newline + 4 < pp->buffer_pos) && 00644 (0 != memcmp ("\r\n--", &buf[newline], 4))) 00645 newline++; 00646 if (newline + pp->blen + 4 <= pp->buffer_pos) 00647 { 00648 /* can check boundary */ 00649 if (0 != memcmp (&buf[newline + 4], boundary, pp->blen)) 00650 { 00651 /* no boundary, "\r\n--" is part of content, skip */ 00652 newline += 4; 00653 continue; 00654 } 00655 else 00656 { 00657 /* boundary found, process until newline then 00658 skip boundary and go back to init */ 00659 pp->skip_rn = RN_Dash; 00660 pp->state = next_state; 00661 pp->dash_state = next_dash_state; 00662 (*ioffptr) += pp->blen + 4; /* skip boundary as well */ 00663 buf[newline] = '\0'; 00664 break; 00665 } 00666 } 00667 else 00668 { 00669 /* cannot check for boundary, process content that 00670 we have and check again later; except, if we have 00671 no content, abort (out of memory) */ 00672 if ((newline == 0) && (pp->buffer_pos == pp->buffer_size)) 00673 { 00674 pp->state = PP_Error; 00675 return MHD_NO; 00676 } 00677 break; 00678 } 00679 } 00680 /* newline is either at beginning of boundary or 00681 at least at the last character that we are sure 00682 is not part of the boundary */ 00683 if (MHD_NO == pp->ikvi (pp->cls, 00684 MHD_POSTDATA_KIND, 00685 pp->content_name, 00686 pp->content_filename, 00687 pp->content_type, 00688 pp->content_transfer_encoding, 00689 buf, pp->value_offset, newline)) 00690 { 00691 pp->state = PP_Error; 00692 return MHD_NO; 00693 } 00694 pp->value_offset += newline; 00695 (*ioffptr) += newline; 00696 return MHD_YES; 00697 } 00698 00699 static void 00700 free_unmarked (struct MHD_PostProcessor *pp) 00701 { 00702 if ((pp->content_name != NULL) && (0 == (pp->have & NE_content_name))) 00703 { 00704 free (pp->content_name); 00705 pp->content_name = NULL; 00706 } 00707 if ((pp->content_type != NULL) && (0 == (pp->have & NE_content_type))) 00708 { 00709 free (pp->content_type); 00710 pp->content_type = NULL; 00711 } 00712 if ((pp->content_filename != NULL) && 00713 (0 == (pp->have & NE_content_filename))) 00714 { 00715 free (pp->content_filename); 00716 pp->content_filename = NULL; 00717 } 00718 if ((pp->content_transfer_encoding != NULL) && 00719 (0 == (pp->have & NE_content_transfer_encoding))) 00720 { 00721 free (pp->content_transfer_encoding); 00722 pp->content_transfer_encoding = NULL; 00723 } 00724 } 00725 00729 static int 00730 post_process_multipart (struct MHD_PostProcessor *pp, 00731 const char *post_data, 00732 size_t post_data_len) 00733 { 00734 char *buf; 00735 size_t max; 00736 size_t ioff; 00737 size_t poff; 00738 int state_changed; 00739 00740 buf = (char *) &pp[1]; 00741 ioff = 0; 00742 poff = 0; 00743 state_changed = 1; 00744 while ((poff < post_data_len) || 00745 ((pp->buffer_pos > 0) && (state_changed != 0))) 00746 { 00747 /* first, move as much input data 00748 as possible to our internal buffer */ 00749 max = pp->buffer_size - pp->buffer_pos; 00750 if (max > post_data_len - poff) 00751 max = post_data_len - poff; 00752 memcpy (&buf[pp->buffer_pos], &post_data[poff], max); 00753 poff += max; 00754 pp->buffer_pos += max; 00755 if ((max == 0) && (state_changed == 0) && (poff < post_data_len)) 00756 { 00757 pp->state = PP_Error; 00758 return MHD_NO; /* out of memory */ 00759 } 00760 state_changed = 0; 00761 00762 /* first state machine for '\r'-'\n' and '--' handling */ 00763 switch (pp->skip_rn) 00764 { 00765 case RN_Inactive: 00766 break; 00767 case RN_OptN: 00768 if (buf[0] == '\n') 00769 { 00770 ioff++; 00771 pp->skip_rn = RN_Inactive; 00772 goto AGAIN; 00773 } 00774 /* fall-through! */ 00775 case RN_Dash: 00776 if (buf[0] == '-') 00777 { 00778 ioff++; 00779 pp->skip_rn = RN_Dash2; 00780 goto AGAIN; 00781 } 00782 pp->skip_rn = RN_Full; 00783 /* fall-through! */ 00784 case RN_Full: 00785 if (buf[0] == '\r') 00786 { 00787 if ((pp->buffer_pos > 1) && (buf[1] == '\n')) 00788 { 00789 pp->skip_rn = RN_Inactive; 00790 ioff += 2; 00791 } 00792 else 00793 { 00794 pp->skip_rn = RN_OptN; 00795 ioff++; 00796 } 00797 goto AGAIN; 00798 } 00799 if (buf[0] == '\n') 00800 { 00801 ioff++; 00802 pp->skip_rn = RN_Inactive; 00803 goto AGAIN; 00804 } 00805 pp->skip_rn = RN_Inactive; 00806 pp->state = PP_Error; 00807 return MHD_NO; /* no '\r\n' */ 00808 case RN_Dash2: 00809 if (buf[0] == '-') 00810 { 00811 ioff++; 00812 pp->skip_rn = RN_Full; 00813 pp->state = pp->dash_state; 00814 goto AGAIN; 00815 } 00816 pp->state = PP_Error; 00817 break; 00818 } 00819 00820 /* main state engine */ 00821 switch (pp->state) 00822 { 00823 case PP_Error: 00824 return MHD_NO; 00825 case PP_Done: 00826 /* did not expect to receive more data */ 00827 pp->state = PP_Error; 00828 return MHD_NO; 00829 case PP_Init: 00841 if (MHD_NO == find_boundary (pp, 00842 pp->boundary, 00843 pp->blen, 00844 &ioff, 00845 PP_ProcessEntryHeaders, PP_Done)) 00846 ++ioff; 00847 break; 00848 case PP_NextBoundary: 00849 if (MHD_NO == find_boundary (pp, 00850 pp->boundary, 00851 pp->blen, 00852 &ioff, 00853 PP_ProcessEntryHeaders, PP_Done)) 00854 { 00855 if (pp->state == PP_Error) 00856 return MHD_NO; 00857 goto END; 00858 } 00859 break; 00860 case PP_ProcessEntryHeaders: 00861 if (MHD_NO == 00862 process_multipart_headers (pp, &ioff, PP_PerformCheckMultipart)) 00863 { 00864 if (pp->state == PP_Error) 00865 return MHD_NO; 00866 else 00867 goto END; 00868 } 00869 state_changed = 1; 00870 break; 00871 case PP_PerformCheckMultipart: 00872 if ((pp->content_type != NULL) && 00873 (0 == strncasecmp (pp->content_type, 00874 "multipart/mixed", 00875 strlen ("multipart/mixed")))) 00876 { 00877 pp->nested_boundary = strstr (pp->content_type, "boundary="); 00878 if (pp->nested_boundary == NULL) 00879 { 00880 pp->state = PP_Error; 00881 return MHD_NO; 00882 } 00883 pp->nested_boundary = 00884 strdup (&pp->nested_boundary[strlen ("boundary=")]); 00885 if (pp->nested_boundary == NULL) 00886 { 00887 /* out of memory */ 00888 pp->state = PP_Error; 00889 return MHD_NO; 00890 } 00891 /* free old content type, we will need that field 00892 for the content type of the nested elements */ 00893 free (pp->content_type); 00894 pp->content_type = NULL; 00895 pp->nlen = strlen (pp->nested_boundary); 00896 pp->state = PP_Nested_Init; 00897 state_changed = 1; 00898 break; 00899 } 00900 pp->state = PP_ProcessValueToBoundary; 00901 pp->value_offset = 0; 00902 state_changed = 1; 00903 break; 00904 case PP_ProcessValueToBoundary: 00905 if (MHD_NO == process_value_to_boundary (pp, 00906 &ioff, 00907 pp->boundary, 00908 pp->blen, 00909 PP_PerformCleanup, 00910 PP_Done)) 00911 { 00912 if (pp->state == PP_Error) 00913 return MHD_NO; 00914 break; 00915 } 00916 break; 00917 case PP_PerformCleanup: 00918 /* clean up state of one multipart form-data element! */ 00919 pp->have = NE_none; 00920 free_unmarked (pp); 00921 if (pp->nested_boundary != NULL) 00922 { 00923 free (pp->nested_boundary); 00924 pp->nested_boundary = NULL; 00925 } 00926 pp->state = PP_ProcessEntryHeaders; 00927 state_changed = 1; 00928 break; 00929 case PP_Nested_Init: 00930 if (pp->nested_boundary == NULL) 00931 { 00932 pp->state = PP_Error; 00933 return MHD_NO; 00934 } 00935 if (MHD_NO == find_boundary (pp, 00936 pp->nested_boundary, 00937 pp->nlen, 00938 &ioff, 00939 PP_Nested_PerformMarking, 00940 PP_NextBoundary /* or PP_Error? */ )) 00941 { 00942 if (pp->state == PP_Error) 00943 return MHD_NO; 00944 goto END; 00945 } 00946 break; 00947 case PP_Nested_PerformMarking: 00948 /* remember what headers were given 00949 globally */ 00950 pp->have = NE_none; 00951 if (pp->content_name != NULL) 00952 pp->have |= NE_content_name; 00953 if (pp->content_type != NULL) 00954 pp->have |= NE_content_type; 00955 if (pp->content_filename != NULL) 00956 pp->have |= NE_content_filename; 00957 if (pp->content_transfer_encoding != NULL) 00958 pp->have |= NE_content_transfer_encoding; 00959 pp->state = PP_Nested_ProcessEntryHeaders; 00960 state_changed = 1; 00961 break; 00962 case PP_Nested_ProcessEntryHeaders: 00963 pp->value_offset = 0; 00964 if (MHD_NO == 00965 process_multipart_headers (pp, &ioff, 00966 PP_Nested_ProcessValueToBoundary)) 00967 { 00968 if (pp->state == PP_Error) 00969 return MHD_NO; 00970 else 00971 goto END; 00972 } 00973 state_changed = 1; 00974 break; 00975 case PP_Nested_ProcessValueToBoundary: 00976 if (MHD_NO == process_value_to_boundary (pp, 00977 &ioff, 00978 pp->nested_boundary, 00979 pp->nlen, 00980 PP_Nested_PerformCleanup, 00981 PP_NextBoundary)) 00982 { 00983 if (pp->state == PP_Error) 00984 return MHD_NO; 00985 break; 00986 } 00987 break; 00988 case PP_Nested_PerformCleanup: 00989 free_unmarked (pp); 00990 pp->state = PP_Nested_ProcessEntryHeaders; 00991 state_changed = 1; 00992 break; 00993 default: 00994 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); /* should never happen! */ 00995 } 00996 AGAIN: 00997 if (ioff > 0) 00998 { 00999 memmove (buf, &buf[ioff], pp->buffer_pos - ioff); 01000 pp->buffer_pos -= ioff; 01001 ioff = 0; 01002 state_changed = 1; 01003 } 01004 } 01005 END: 01006 if (ioff != 0) 01007 { 01008 memmove (buf, &buf[ioff], pp->buffer_pos - ioff); 01009 pp->buffer_pos -= ioff; 01010 } 01011 if (poff < post_data_len) 01012 { 01013 pp->state = PP_Error; 01014 return MHD_NO; /* serious error */ 01015 } 01016 return MHD_YES; 01017 } 01018 01033 int 01034 MHD_post_process (struct MHD_PostProcessor *pp, 01035 const char *post_data, size_t post_data_len) 01036 { 01037 if (post_data_len == 0) 01038 return MHD_YES; 01039 if (pp == NULL) 01040 return MHD_NO; 01041 if (0 == strncasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, pp->encoding, 01042 strlen(MHD_HTTP_POST_ENCODING_FORM_URLENCODED))) 01043 return post_process_urlencoded (pp, post_data, post_data_len); 01044 if (0 == 01045 strncasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, pp->encoding, 01046 strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA))) 01047 return post_process_multipart (pp, post_data, post_data_len); 01048 /* this should never be reached */ 01049 return MHD_NO; 01050 } 01051 01055 int 01056 MHD_destroy_post_processor (struct MHD_PostProcessor *pp) 01057 { 01058 int ret; 01059 01060 if (NULL == pp) 01061 return MHD_YES; 01062 /* These internal strings need cleaning up since 01063 the post-processing may have been interrupted 01064 at any stage */ 01065 if ((pp->xbuf_pos > 0) || (pp->state != PP_Done)) 01066 ret = MHD_NO; 01067 else 01068 ret = MHD_YES; 01069 pp->have = NE_none; 01070 free_unmarked (pp); 01071 if (pp->nested_boundary != NULL) 01072 free (pp->nested_boundary); 01073 free (pp); 01074 return ret; 01075 } 01076 01077 /* end of postprocessor.c */