00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "internal.h"
00027
00033 #define XBUF_SIZE 512
00034
00038 enum PP_State
00039 {
00040
00041 PP_Error,
00042 PP_Done,
00043 PP_Init,
00044 PP_NextBoundary,
00045
00046
00047 PP_ProcessValue,
00048 PP_ExpectNewLine,
00049
00050
00051 PP_ProcessEntryHeaders,
00052 PP_PerformCheckMultipart,
00053 PP_ProcessValueToBoundary,
00054 PP_PerformCleanup,
00055
00056
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
00279 boundary = strstr (boundary, "boundary=");
00280 if (NULL == boundary)
00281 return NULL;
00282 boundary += strlen ("boundary=");
00283 blen = strlen (boundary);
00284 if ((blen == 0) || (blen * 2 + 2 > buffer_size))
00285 return NULL;
00286 if ( (boundary[0] == '"') && (boundary[blen - 1] == '"') )
00287 {
00288
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
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;
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;
00354 buf[pp->buffer_pos] = '\0';
00355 pp->buffer_pos = 0;
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
00363 memcpy (xbuf, pp->xbuf, pp->xbuf_pos);
00364 xoff = pp->xbuf_pos;
00365 pp->xbuf_pos = 0;
00366
00367
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
00380
00381 delta = amper;
00382 if (delta > XBUF_SIZE - xoff)
00383 delta = XBUF_SIZE - xoff;
00384
00385
00386 memcpy (&xbuf[xoff], &post_data[poff], delta);
00387 xoff += delta;
00388 poff += delta;
00389
00390
00391
00392
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
00400
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
00409
00410
00411 if ((xoff == 0) && (poff == post_data_len))
00412 continue;
00413
00414
00415 xbuf[xoff] = '\0';
00416 xoff = MHD_http_unescape (NULL, NULL, xbuf);
00417
00418 if (MHD_NO == pp->ikvi (pp->cls, MHD_POSTDATA_KIND, (const char *) &pp[1],
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
00428 if (end_of_value_found)
00429 {
00430
00431 if ((post_data[poff] == '\n') || (post_data[poff] == '\r'))
00432 {
00433 pp->state = PP_ExpectNewLine;
00434 }
00435 else
00436 {
00437 poff++;
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
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);
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;
00494 return MHD_NO;
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;
00501 }
00502
00503 (*ioffptr) += 2 + blen;
00504
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
00537 bpos = spos + 1;
00538 continue;
00539 }
00540 if (spos[klen + 1] != '"')
00541 return;
00542 if (NULL == (endv = strchr (&spos[klen + 2], '\"')))
00543 return;
00544 vlen = endv - spos - klen - 1;
00545 *destination = malloc (vlen);
00546 if (NULL == *destination)
00547 return;
00548 (*destination)[vlen - 1] = '\0';
00549 memcpy (*destination, &spos[klen + 2], vlen - 1);
00550 return;
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;
00581 }
00582 if (newline == pp->buffer_pos)
00583 return MHD_NO;
00584 if (newline == 0)
00585 {
00586
00587 pp->skip_rn = RN_Full;
00588 pp->state = next_state;
00589 return MHD_YES;
00590 }
00591
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
00639
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
00649 if (0 != memcmp (&buf[newline + 4], boundary, pp->blen))
00650 {
00651
00652 newline += 4;
00653 continue;
00654 }
00655 else
00656 {
00657
00658
00659 pp->skip_rn = RN_Dash;
00660 pp->state = next_state;
00661 pp->dash_state = next_dash_state;
00662 (*ioffptr) += pp->blen + 4;
00663 buf[newline] = '\0';
00664 break;
00665 }
00666 }
00667 else
00668 {
00669
00670
00671
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
00681
00682
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
00748
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;
00759 }
00760 state_changed = 0;
00761
00762
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
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
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;
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
00821 switch (pp->state)
00822 {
00823 case PP_Error:
00824 return MHD_NO;
00825 case PP_Done:
00826
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
00888 pp->state = PP_Error;
00889 return MHD_NO;
00890 }
00891
00892
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
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 ))
00941 {
00942 if (pp->state == PP_Error)
00943 return MHD_NO;
00944 goto END;
00945 }
00946 break;
00947 case PP_Nested_PerformMarking:
00948
00949
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);
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;
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
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
01063
01064
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