GNU libmicrohttpd 0.9.5
|
00001 /* 00002 This file is part of libmicrohttpd 00003 (C) 2007, 2009 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 00031 #define XBUF_SIZE 1024 00032 00036 enum PP_State 00037 { 00038 /* general states */ 00039 PP_Error, 00040 PP_Done, 00041 PP_Init, 00042 00043 /* url encoding-states */ 00044 PP_ProcessValue, 00045 PP_ExpectNewLine, 00046 00047 /* post encoding-states */ 00048 PP_ProcessEntryHeaders, 00049 PP_PerformCheckMultipart, 00050 PP_ProcessValueToBoundary, 00051 PP_PerformCleanup, 00052 00053 /* nested post-encoding states */ 00054 PP_Nested_Init, 00055 PP_Nested_PerformMarking, 00056 PP_Nested_ProcessEntryHeaders, 00057 PP_Nested_ProcessValueToBoundary, 00058 PP_Nested_PerformCleanup, 00059 00060 }; 00061 00062 enum RN_State 00063 { 00067 RN_Inactive = 0, 00068 00073 RN_OptN = 1, 00074 00079 RN_Full = 2, 00080 00085 RN_Dash = 3, 00086 00090 RN_Dash2 = 4, 00091 }; 00092 00098 enum NE_State 00099 { 00100 NE_none = 0, 00101 NE_content_name = 1, 00102 NE_content_type = 2, 00103 NE_content_filename = 4, 00104 NE_content_transfer_encoding = 8, 00105 }; 00106 00111 struct MHD_PostProcessor 00112 { 00113 00118 struct MHD_Connection *connection; 00119 00123 MHD_PostDataIterator ikvi; 00124 00128 void *cls; 00129 00134 const char *encoding; 00135 00139 const char *boundary; 00140 00144 char *nested_boundary; 00145 00149 char *content_name; 00150 00154 char *content_type; 00155 00159 char *content_filename; 00160 00164 char *content_transfer_encoding; 00165 00170 char xbuf[8]; 00171 00175 size_t buffer_size; 00176 00180 size_t buffer_pos; 00181 00185 size_t xbuf_pos; 00186 00190 uint64_t value_offset; 00191 00195 size_t blen; 00196 00200 size_t nlen; 00201 00205 enum PP_State state; 00206 00213 enum RN_State skip_rn; 00214 00219 enum PP_State dash_state; 00220 00225 enum NE_State have; 00226 00227 }; 00228 00229 00248 struct MHD_PostProcessor * 00249 MHD_create_post_processor (struct MHD_Connection *connection, 00250 size_t buffer_size, 00251 MHD_PostDataIterator ikvi, void *cls) 00252 { 00253 struct MHD_PostProcessor *ret; 00254 const char *encoding; 00255 const char *boundary; 00256 size_t blen; 00257 00258 if ((buffer_size < 256) || (connection == NULL) || (ikvi == NULL)) 00259 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); 00260 encoding = MHD_lookup_connection_value (connection, 00261 MHD_HEADER_KIND, 00262 MHD_HTTP_HEADER_CONTENT_TYPE); 00263 if (encoding == NULL) 00264 return NULL; 00265 boundary = NULL; 00266 if (0 != strncasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, encoding, 00267 strlen (MHD_HTTP_POST_ENCODING_FORM_URLENCODED))) 00268 { 00269 if (0 != 00270 strncasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, encoding, 00271 strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA))) 00272 return NULL; 00273 boundary = 00274 &encoding[strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)]; 00275 /* Q: should this be "strcasestr"? */ 00276 boundary = strstr (boundary, "boundary="); 00277 if (NULL == boundary) 00278 return NULL; /* failed to determine boundary */ 00279 boundary += strlen ("boundary="); 00280 blen = strlen (boundary); 00281 if ((blen == 0) || (blen * 2 + 2 > buffer_size)) 00282 return NULL; /* (will be) out of memory or invalid boundary */ 00283 } 00284 else 00285 blen = 0; 00286 ret = malloc (sizeof (struct MHD_PostProcessor) + buffer_size + 1); 00287 if (ret == NULL) 00288 return NULL; 00289 memset (ret, 0, sizeof (struct MHD_PostProcessor) + buffer_size + 1); 00290 ret->connection = connection; 00291 ret->ikvi = ikvi; 00292 ret->cls = cls; 00293 ret->encoding = encoding; 00294 ret->buffer_size = buffer_size; 00295 ret->state = PP_Init; 00296 ret->blen = blen; 00297 ret->boundary = boundary; 00298 ret->skip_rn = RN_Inactive; 00299 return ret; 00300 } 00301 00305 static int 00306 post_process_urlencoded (struct MHD_PostProcessor *pp, 00307 const char *post_data, 00308 size_t post_data_len) 00309 { 00310 size_t equals; 00311 size_t amper; 00312 size_t poff; 00313 size_t xoff; 00314 size_t delta; 00315 int end_of_value_found; 00316 char *buf; 00317 char xbuf[XBUF_SIZE + 1]; 00318 00319 buf = (char *) &pp[1]; 00320 poff = 0; 00321 while (poff < post_data_len) 00322 { 00323 switch (pp->state) 00324 { 00325 case PP_Error: 00326 return MHD_NO; 00327 case PP_Done: 00328 /* did not expect to receive more data */ 00329 pp->state = PP_Error; 00330 return MHD_NO; 00331 case PP_Init: 00332 equals = 0; 00333 while ((equals + poff < post_data_len) && 00334 (post_data[equals + poff] != '=')) 00335 equals++; 00336 if (equals + pp->buffer_pos > pp->buffer_size) 00337 { 00338 pp->state = PP_Error; /* out of memory */ 00339 return MHD_NO; 00340 } 00341 memcpy (&buf[pp->buffer_pos], &post_data[poff], equals); 00342 pp->buffer_pos += equals; 00343 if (equals + poff == post_data_len) 00344 return MHD_YES; /* no '=' yet */ 00345 buf[pp->buffer_pos] = '\0'; /* 0-terminate key */ 00346 pp->buffer_pos = 0; /* reset for next key */ 00347 MHD_http_unescape (NULL, NULL, buf); 00348 poff += equals + 1; 00349 pp->state = PP_ProcessValue; 00350 pp->value_offset = 0; 00351 break; 00352 case PP_ProcessValue: 00353 /* obtain rest of value from previous iteration */ 00354 memcpy (xbuf, pp->xbuf, pp->xbuf_pos); 00355 xoff = pp->xbuf_pos; 00356 pp->xbuf_pos = 0; 00357 00358 /* find last position in input buffer that is part of the value */ 00359 amper = 0; 00360 while ((amper + poff < post_data_len) && 00361 (amper < XBUF_SIZE) && 00362 (post_data[amper + poff] != '&') && 00363 (post_data[amper + poff] != '\n') && 00364 (post_data[amper + poff] != '\r')) 00365 amper++; 00366 end_of_value_found = ((amper + poff < post_data_len) && 00367 ((post_data[amper + poff] == '&') || 00368 (post_data[amper + poff] == '\n') || 00369 (post_data[amper + poff] == '\r'))); 00370 /* compute delta, the maximum number of bytes that we will be able to 00371 process right now (either amper-limited of xbuf-size limited) */ 00372 delta = amper; 00373 if (delta > XBUF_SIZE - xoff) 00374 delta = XBUF_SIZE - xoff; 00375 00376 /* move input into processing buffer */ 00377 memcpy (&xbuf[xoff], &post_data[poff], delta); 00378 xoff += delta; 00379 poff += delta; 00380 00381 /* find if escape sequence is at the end of the processing buffer; 00382 if so, exclude those from processing (reduce delta to point at 00383 end of processed region) */ 00384 delta = xoff; 00385 if ((delta > 0) && (xbuf[delta - 1] == '%')) 00386 delta--; 00387 else if ((delta > 1) && (xbuf[delta - 2] == '%')) 00388 delta -= 2; 00389 00390 /* if we have an incomplete escape sequence, save it to 00391 pp->xbuf for later */ 00392 if (delta < xoff) 00393 { 00394 memcpy (pp->xbuf, &xbuf[delta], xoff - delta); 00395 pp->xbuf_pos = xoff - delta; 00396 xoff = delta; 00397 } 00398 00399 /* If we have nothing to do (delta == 0) and 00400 not just because the value is empty (are 00401 waiting for more data), go for next iteration */ 00402 if ((xoff == 0) && (poff == post_data_len)) 00403 continue; 00404 00405 /* unescape */ 00406 xbuf[xoff] = '\0'; /* 0-terminate in preparation */ 00407 xoff = MHD_http_unescape (NULL, NULL, xbuf); 00408 /* finally: call application! */ 00409 if (MHD_NO == pp->ikvi (pp->cls, MHD_POSTDATA_KIND, (const char *) &pp[1], /* key */ 00410 NULL, NULL, NULL, xbuf, pp->value_offset, 00411 xoff)) 00412 { 00413 pp->state = PP_Error; 00414 return MHD_NO; 00415 } 00416 pp->value_offset += xoff; 00417 00418 /* are we done with the value? */ 00419 if (end_of_value_found) 00420 { 00421 /* we found the end of the value! */ 00422 if ((post_data[poff] == '\n') || (post_data[poff] == '\r')) 00423 { 00424 pp->state = PP_ExpectNewLine; 00425 } 00426 else 00427 { 00428 poff++; /* skip '&' */ 00429 pp->state = PP_Init; 00430 } 00431 } 00432 break; 00433 case PP_ExpectNewLine: 00434 if ((post_data[poff] == '\n') || (post_data[poff] == '\r')) 00435 { 00436 poff++; 00437 /* we are done, report error if we receive any more... */ 00438 pp->state = PP_Done; 00439 return MHD_YES; 00440 } 00441 return MHD_NO; 00442 default: 00443 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); /* should never happen! */ 00444 } 00445 } 00446 return MHD_YES; 00447 } 00448 00455 static int 00456 try_match_header (const char *prefix, char *line, char **suffix) 00457 { 00458 if (NULL != *suffix) 00459 return MHD_NO; 00460 while (*line != 0) 00461 { 00462 if (0 == strncasecmp (prefix, line, strlen (prefix))) 00463 { 00464 *suffix = strdup (&line[strlen (prefix)]); 00465 return MHD_YES; 00466 } 00467 ++line; 00468 } 00469 return MHD_NO; 00470 } 00471 00472 static int 00473 find_boundary (struct MHD_PostProcessor *pp, 00474 const char *boundary, 00475 size_t blen, 00476 size_t *ioffptr, 00477 enum PP_State next_state, enum PP_State next_dash_state) 00478 { 00479 char *buf = (char *) &pp[1]; 00480 00481 if (pp->buffer_pos < 2 + blen) 00482 { 00483 if (pp->buffer_pos == pp->buffer_size) 00484 pp->state = PP_Error; /* out of memory */ 00485 return MHD_NO; /* not enough data */ 00486 } 00487 if ((0 != memcmp ("--", buf, 2)) || (0 != memcmp (&buf[2], boundary, blen))) 00488 { 00489 pp->state = PP_Error; 00490 return MHD_NO; /* expected boundary */ 00491 } 00492 /* remove boundary from buffer */ 00493 (*ioffptr) += 2 + blen; 00494 /* next: start with headers */ 00495 pp->skip_rn = RN_Dash; 00496 pp->state = next_state; 00497 pp->dash_state = next_dash_state; 00498 return MHD_YES; 00499 } 00500 00509 static void 00510 try_get_value (const char *buf, const char *key, char **destination) 00511 { 00512 const char *spos; 00513 const char *bpos; 00514 const char *endv; 00515 size_t klen; 00516 size_t vlen; 00517 00518 if (NULL != *destination) 00519 return; 00520 bpos = buf; 00521 klen = strlen (key); 00522 while (NULL != (spos = strstr (bpos, key))) 00523 { 00524 if ((spos[klen] != '=') || ((spos != buf) && (spos[-1] != ' '))) 00525 { 00526 /* no match */ 00527 bpos = spos + 1; 00528 continue; 00529 } 00530 if (spos[klen + 1] != '"') 00531 return; /* not quoted */ 00532 if (NULL == (endv = strstr (&spos[klen + 2], "\""))) 00533 return; /* no end-quote */ 00534 vlen = endv - spos - klen - 1; 00535 *destination = malloc (vlen); 00536 if (NULL == *destination) 00537 return; /* out of memory */ 00538 (*destination)[vlen - 1] = '\0'; 00539 memcpy (*destination, &spos[klen + 2], vlen - 1); 00540 return; /* success */ 00541 } 00542 } 00543 00556 static int 00557 process_multipart_headers (struct MHD_PostProcessor *pp, 00558 size_t *ioffptr, enum PP_State next_state) 00559 { 00560 char *buf = (char *) &pp[1]; 00561 size_t newline; 00562 00563 newline = 0; 00564 while ((newline < pp->buffer_pos) && 00565 (buf[newline] != '\r') && (buf[newline] != '\n')) 00566 newline++; 00567 if (newline == pp->buffer_size) 00568 { 00569 pp->state = PP_Error; 00570 return MHD_NO; /* out of memory */ 00571 } 00572 if (newline == pp->buffer_pos) 00573 return MHD_NO; /* will need more data */ 00574 if (newline == 0) 00575 { 00576 /* empty line - end of headers */ 00577 pp->skip_rn = RN_Full; 00578 pp->state = next_state; 00579 return MHD_YES; 00580 } 00581 /* got an actual header */ 00582 if (buf[newline] == '\r') 00583 pp->skip_rn = RN_OptN; 00584 buf[newline] = '\0'; 00585 if (0 == strncasecmp ("Content-disposition: ", 00586 buf, strlen ("Content-disposition: "))) 00587 { 00588 try_get_value (&buf[strlen ("Content-disposition: ")], 00589 "name", &pp->content_name); 00590 try_get_value (&buf[strlen ("Content-disposition: ")], 00591 "filename", &pp->content_filename); 00592 } 00593 else 00594 { 00595 try_match_header ("Content-type: ", buf, &pp->content_type); 00596 try_match_header ("Content-Transfer-Encoding: ", 00597 buf, &pp->content_transfer_encoding); 00598 } 00599 (*ioffptr) += newline + 1; 00600 return MHD_YES; 00601 } 00602 00617 static int 00618 process_value_to_boundary (struct MHD_PostProcessor *pp, 00619 size_t *ioffptr, 00620 const char *boundary, 00621 size_t blen, 00622 enum PP_State next_state, 00623 enum PP_State next_dash_state) 00624 { 00625 char *buf = (char *) &pp[1]; 00626 size_t newline; 00627 00628 /* all data in buf until the boundary 00629 (\r\n--+boundary) is part of the value */ 00630 newline = 0; 00631 while (1) 00632 { 00633 while ((newline + 4 < pp->buffer_pos) && 00634 (0 != memcmp ("\r\n--", &buf[newline], 4))) 00635 newline++; 00636 if (newline + pp->blen + 4 <= pp->buffer_pos) 00637 { 00638 /* can check boundary */ 00639 if (0 != memcmp (&buf[newline + 4], boundary, pp->blen)) 00640 { 00641 /* no boundary, "\r\n--" is part of content, skip */ 00642 newline += 4; 00643 continue; 00644 } 00645 else 00646 { 00647 /* boundary found, process until newline then 00648 skip boundary and go back to init */ 00649 pp->skip_rn = RN_Dash; 00650 pp->state = next_state; 00651 pp->dash_state = next_dash_state; 00652 (*ioffptr) += pp->blen + 4; /* skip boundary as well */ 00653 break; 00654 } 00655 } 00656 else 00657 { 00658 /* cannot check for boundary, process content that 00659 we have and check again later; except, if we have 00660 no content, abort (out of memory) */ 00661 if ((newline == 0) && (pp->buffer_pos == pp->buffer_size)) 00662 { 00663 pp->state = PP_Error; 00664 return MHD_NO; 00665 } 00666 break; 00667 } 00668 } 00669 /* newline is either at beginning of boundary or 00670 at least at the last character that we are sure 00671 is not part of the boundary */ 00672 if (MHD_NO == pp->ikvi (pp->cls, 00673 MHD_POSTDATA_KIND, 00674 pp->content_name, 00675 pp->content_filename, 00676 pp->content_type, 00677 pp->content_transfer_encoding, 00678 buf, pp->value_offset, newline)) 00679 { 00680 pp->state = PP_Error; 00681 return MHD_NO; 00682 } 00683 pp->value_offset += newline; 00684 (*ioffptr) += newline; 00685 return MHD_YES; 00686 } 00687 00688 static void 00689 free_unmarked (struct MHD_PostProcessor *pp) 00690 { 00691 if ((pp->content_name != NULL) && (0 == (pp->have & NE_content_name))) 00692 { 00693 free (pp->content_name); 00694 pp->content_name = NULL; 00695 } 00696 if ((pp->content_type != NULL) && (0 == (pp->have & NE_content_type))) 00697 { 00698 free (pp->content_type); 00699 pp->content_type = NULL; 00700 } 00701 if ((pp->content_filename != NULL) && 00702 (0 == (pp->have & NE_content_filename))) 00703 { 00704 free (pp->content_filename); 00705 pp->content_filename = NULL; 00706 } 00707 if ((pp->content_transfer_encoding != NULL) && 00708 (0 == (pp->have & NE_content_transfer_encoding))) 00709 { 00710 free (pp->content_transfer_encoding); 00711 pp->content_transfer_encoding = NULL; 00712 } 00713 } 00714 00718 static int 00719 post_process_multipart (struct MHD_PostProcessor *pp, 00720 const char *post_data, 00721 size_t post_data_len) 00722 { 00723 char *buf; 00724 size_t max; 00725 size_t ioff; 00726 size_t poff; 00727 int state_changed; 00728 00729 buf = (char *) &pp[1]; 00730 ioff = 0; 00731 poff = 0; 00732 state_changed = 1; 00733 while ((poff < post_data_len) || 00734 ((pp->buffer_pos > 0) && (state_changed != 0))) 00735 { 00736 /* first, move as much input data 00737 as possible to our internal buffer */ 00738 max = pp->buffer_size - pp->buffer_pos; 00739 if (max > post_data_len - poff) 00740 max = post_data_len - poff; 00741 memcpy (&buf[pp->buffer_pos], &post_data[poff], max); 00742 poff += max; 00743 pp->buffer_pos += max; 00744 if ((max == 0) && (state_changed == 0) && (poff < post_data_len)) 00745 { 00746 pp->state = PP_Error; 00747 return MHD_NO; /* out of memory */ 00748 } 00749 state_changed = 0; 00750 00751 /* first state machine for '\r'-'\n' and '--' handling */ 00752 switch (pp->skip_rn) 00753 { 00754 case RN_Inactive: 00755 break; 00756 case RN_OptN: 00757 if (buf[0] == '\n') 00758 { 00759 ioff++; 00760 pp->skip_rn = RN_Inactive; 00761 goto AGAIN; 00762 } 00763 /* fall-through! */ 00764 case RN_Dash: 00765 if (buf[0] == '-') 00766 { 00767 ioff++; 00768 pp->skip_rn = RN_Dash2; 00769 goto AGAIN; 00770 } 00771 pp->skip_rn = RN_Full; 00772 /* fall-through! */ 00773 case RN_Full: 00774 if (buf[0] == '\r') 00775 { 00776 if ((pp->buffer_pos > 1) && (buf[1] == '\n')) 00777 { 00778 pp->skip_rn = RN_Inactive; 00779 ioff += 2; 00780 } 00781 else 00782 { 00783 pp->skip_rn = RN_OptN; 00784 ioff++; 00785 } 00786 goto AGAIN; 00787 } 00788 if (buf[0] == '\n') 00789 { 00790 ioff++; 00791 pp->skip_rn = RN_Inactive; 00792 goto AGAIN; 00793 } 00794 pp->skip_rn = RN_Inactive; 00795 pp->state = PP_Error; 00796 return MHD_NO; /* no '\r\n' */ 00797 case RN_Dash2: 00798 if (buf[0] == '-') 00799 { 00800 ioff++; 00801 pp->skip_rn = RN_Full; 00802 pp->state = pp->dash_state; 00803 goto AGAIN; 00804 } 00805 pp->state = PP_Error; 00806 break; 00807 } 00808 00809 /* main state engine */ 00810 switch (pp->state) 00811 { 00812 case PP_Error: 00813 return MHD_NO; 00814 case PP_Done: 00815 /* did not expect to receive more data */ 00816 pp->state = PP_Error; 00817 return MHD_NO; 00818 case PP_Init: 00819 if (MHD_NO == find_boundary (pp, 00820 pp->boundary, 00821 pp->blen, 00822 &ioff, 00823 PP_ProcessEntryHeaders, PP_Done)) 00824 { 00825 if (pp->state == PP_Error) 00826 return MHD_NO; 00827 goto END; 00828 } 00829 break; 00830 case PP_ProcessEntryHeaders: 00831 if (MHD_NO == 00832 process_multipart_headers (pp, &ioff, PP_PerformCheckMultipart)) 00833 { 00834 if (pp->state == PP_Error) 00835 return MHD_NO; 00836 else 00837 goto END; 00838 } 00839 state_changed = 1; 00840 break; 00841 case PP_PerformCheckMultipart: 00842 if ((pp->content_type != NULL) && 00843 (0 == strncasecmp (pp->content_type, 00844 "multipart/mixed", 00845 strlen ("multipart/mixed")))) 00846 { 00847 pp->nested_boundary = strstr (pp->content_type, "boundary="); 00848 if (pp->nested_boundary == NULL) 00849 { 00850 pp->state = PP_Error; 00851 return MHD_NO; 00852 } 00853 pp->nested_boundary = 00854 strdup (&pp->nested_boundary[strlen ("boundary=")]); 00855 if (pp->nested_boundary == NULL) 00856 { 00857 /* out of memory */ 00858 pp->state = PP_Error; 00859 return MHD_NO; 00860 } 00861 /* free old content type, we will need that field 00862 for the content type of the nested elements */ 00863 free (pp->content_type); 00864 pp->content_type = NULL; 00865 pp->nlen = strlen (pp->nested_boundary); 00866 pp->state = PP_Nested_Init; 00867 state_changed = 1; 00868 break; 00869 } 00870 pp->state = PP_ProcessValueToBoundary; 00871 pp->value_offset = 0; 00872 state_changed = 1; 00873 break; 00874 case PP_ProcessValueToBoundary: 00875 if (MHD_NO == process_value_to_boundary (pp, 00876 &ioff, 00877 pp->boundary, 00878 pp->blen, 00879 PP_PerformCleanup, 00880 PP_Done)) 00881 { 00882 if (pp->state == PP_Error) 00883 return MHD_NO; 00884 break; 00885 } 00886 break; 00887 case PP_PerformCleanup: 00888 /* clean up state of one multipart form-data element! */ 00889 pp->have = NE_none; 00890 free_unmarked (pp); 00891 if (pp->nested_boundary != NULL) 00892 { 00893 free (pp->nested_boundary); 00894 pp->nested_boundary = NULL; 00895 } 00896 pp->state = PP_ProcessEntryHeaders; 00897 state_changed = 1; 00898 break; 00899 case PP_Nested_Init: 00900 if (pp->nested_boundary == NULL) 00901 { 00902 pp->state = PP_Error; 00903 return MHD_NO; 00904 } 00905 if (MHD_NO == find_boundary (pp, 00906 pp->nested_boundary, 00907 pp->nlen, 00908 &ioff, 00909 PP_Nested_PerformMarking, 00910 PP_Init /* or PP_Error? */ )) 00911 { 00912 if (pp->state == PP_Error) 00913 return MHD_NO; 00914 goto END; 00915 } 00916 break; 00917 case PP_Nested_PerformMarking: 00918 /* remember what headers were given 00919 globally */ 00920 pp->have = NE_none; 00921 if (pp->content_name != NULL) 00922 pp->have |= NE_content_name; 00923 if (pp->content_type != NULL) 00924 pp->have |= NE_content_type; 00925 if (pp->content_filename != NULL) 00926 pp->have |= NE_content_filename; 00927 if (pp->content_transfer_encoding != NULL) 00928 pp->have |= NE_content_transfer_encoding; 00929 pp->state = PP_Nested_ProcessEntryHeaders; 00930 state_changed = 1; 00931 break; 00932 case PP_Nested_ProcessEntryHeaders: 00933 pp->value_offset = 0; 00934 if (MHD_NO == 00935 process_multipart_headers (pp, &ioff, 00936 PP_Nested_ProcessValueToBoundary)) 00937 { 00938 if (pp->state == PP_Error) 00939 return MHD_NO; 00940 else 00941 goto END; 00942 } 00943 state_changed = 1; 00944 break; 00945 case PP_Nested_ProcessValueToBoundary: 00946 if (MHD_NO == process_value_to_boundary (pp, 00947 &ioff, 00948 pp->nested_boundary, 00949 pp->nlen, 00950 PP_Nested_PerformCleanup, 00951 PP_Init)) 00952 { 00953 if (pp->state == PP_Error) 00954 return MHD_NO; 00955 break; 00956 } 00957 break; 00958 case PP_Nested_PerformCleanup: 00959 free_unmarked (pp); 00960 pp->state = PP_Nested_ProcessEntryHeaders; 00961 state_changed = 1; 00962 break; 00963 default: 00964 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); /* should never happen! */ 00965 } 00966 AGAIN: 00967 if (ioff > 0) 00968 { 00969 memmove (buf, &buf[ioff], pp->buffer_pos - ioff); 00970 pp->buffer_pos -= ioff; 00971 ioff = 0; 00972 state_changed = 1; 00973 } 00974 } 00975 END: 00976 if (ioff != 0) 00977 { 00978 memmove (buf, &buf[ioff], pp->buffer_pos - ioff); 00979 pp->buffer_pos -= ioff; 00980 } 00981 if (poff < post_data_len) 00982 { 00983 pp->state = PP_Error; 00984 return MHD_NO; /* serious error */ 00985 } 00986 return MHD_YES; 00987 } 00988 01003 int 01004 MHD_post_process (struct MHD_PostProcessor *pp, 01005 const char *post_data, size_t post_data_len) 01006 { 01007 if (post_data_len == 0) 01008 return MHD_YES; 01009 if (pp == NULL) 01010 return MHD_NO; 01011 if (0 == strncasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, pp->encoding, 01012 strlen(MHD_HTTP_POST_ENCODING_FORM_URLENCODED))) 01013 return post_process_urlencoded (pp, post_data, post_data_len); 01014 if (0 == 01015 strncasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, pp->encoding, 01016 strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA))) 01017 return post_process_multipart (pp, post_data, post_data_len); 01018 /* this should never be reached */ 01019 return MHD_NO; 01020 } 01021 01025 int 01026 MHD_destroy_post_processor (struct MHD_PostProcessor *pp) 01027 { 01028 int ret; 01029 01030 /* These internal strings need cleaning up since 01031 the post-processing may have been interrupted 01032 at any stage */ 01033 if ((pp->xbuf_pos > 0) || (pp->state != PP_Done)) 01034 ret = MHD_NO; 01035 else 01036 ret = MHD_YES; 01037 pp->have = NE_none; 01038 free_unmarked (pp); 01039 if (pp->nested_boundary != NULL) 01040 free (pp->nested_boundary); 01041 free (pp); 01042 return ret; 01043 } 01044 01045 /* end of postprocessor.c */