00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "internal.h"
00027
00031 #define XBUF_SIZE 1024
00032
00036 enum PP_State
00037 {
00038
00039 PP_Error,
00040 PP_Done,
00041 PP_Init,
00042 PP_NextBoundary,
00043
00044
00045 PP_ProcessValue,
00046 PP_ExpectNewLine,
00047
00048
00049 PP_ProcessEntryHeaders,
00050 PP_PerformCheckMultipart,
00051 PP_ProcessValueToBoundary,
00052 PP_PerformCleanup,
00053
00054
00055 PP_Nested_Init,
00056 PP_Nested_PerformMarking,
00057 PP_Nested_ProcessEntryHeaders,
00058 PP_Nested_ProcessValueToBoundary,
00059 PP_Nested_PerformCleanup,
00060
00061 };
00062
00063 enum RN_State
00064 {
00068 RN_Inactive = 0,
00069
00074 RN_OptN = 1,
00075
00080 RN_Full = 2,
00081
00086 RN_Dash = 3,
00087
00091 RN_Dash2 = 4,
00092 };
00093
00099 enum NE_State
00100 {
00101 NE_none = 0,
00102 NE_content_name = 1,
00103 NE_content_type = 2,
00104 NE_content_filename = 4,
00105 NE_content_transfer_encoding = 8,
00106 };
00107
00112 struct MHD_PostProcessor
00113 {
00114
00119 struct MHD_Connection *connection;
00120
00124 MHD_PostDataIterator ikvi;
00125
00129 void *cls;
00130
00135 const char *encoding;
00136
00140 const char *boundary;
00141
00145 char *nested_boundary;
00146
00150 char *content_name;
00151
00155 char *content_type;
00156
00160 char *content_filename;
00161
00165 char *content_transfer_encoding;
00166
00171 char xbuf[8];
00172
00176 size_t buffer_size;
00177
00181 size_t buffer_pos;
00182
00186 size_t xbuf_pos;
00187
00191 uint64_t value_offset;
00192
00196 size_t blen;
00197
00201 size_t nlen;
00202
00206 enum PP_State state;
00207
00214 enum RN_State skip_rn;
00215
00220 enum PP_State dash_state;
00221
00226 enum NE_State have;
00227
00228 };
00229
00230
00249 struct MHD_PostProcessor *
00250 MHD_create_post_processor (struct MHD_Connection *connection,
00251 size_t buffer_size,
00252 MHD_PostDataIterator ikvi, void *cls)
00253 {
00254 struct MHD_PostProcessor *ret;
00255 const char *encoding;
00256 const char *boundary;
00257 size_t blen;
00258
00259 if ((buffer_size < 256) || (connection == NULL) || (ikvi == NULL))
00260 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
00261 encoding = MHD_lookup_connection_value (connection,
00262 MHD_HEADER_KIND,
00263 MHD_HTTP_HEADER_CONTENT_TYPE);
00264 if (encoding == NULL)
00265 return NULL;
00266 boundary = NULL;
00267 if (0 != strncasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, encoding,
00268 strlen (MHD_HTTP_POST_ENCODING_FORM_URLENCODED)))
00269 {
00270 if (0 !=
00271 strncasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, encoding,
00272 strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)))
00273 return NULL;
00274 boundary =
00275 &encoding[strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)];
00276
00277 boundary = strstr (boundary, "boundary=");
00278 if (NULL == boundary)
00279 return NULL;
00280 boundary += strlen ("boundary=");
00281 blen = strlen (boundary);
00282 if ((blen == 0) || (blen * 2 + 2 > buffer_size))
00283 return NULL;
00284 if ( (boundary[0] == '"') && (boundary[blen - 1] == '"') )
00285 {
00286
00287 ++boundary;
00288 blen -= 2;
00289 }
00290 }
00291 else
00292 blen = 0;
00293 ret = malloc (sizeof (struct MHD_PostProcessor) + buffer_size + 1);
00294 if (ret == NULL)
00295 return NULL;
00296 memset (ret, 0, sizeof (struct MHD_PostProcessor) + buffer_size + 1);
00297 ret->connection = connection;
00298 ret->ikvi = ikvi;
00299 ret->cls = cls;
00300 ret->encoding = encoding;
00301 ret->buffer_size = buffer_size;
00302 ret->state = PP_Init;
00303 ret->blen = blen;
00304 ret->boundary = boundary;
00305 ret->skip_rn = RN_Inactive;
00306 return ret;
00307 }
00308
00312 static int
00313 post_process_urlencoded (struct MHD_PostProcessor *pp,
00314 const char *post_data,
00315 size_t post_data_len)
00316 {
00317 size_t equals;
00318 size_t amper;
00319 size_t poff;
00320 size_t xoff;
00321 size_t delta;
00322 int end_of_value_found;
00323 char *buf;
00324 char xbuf[XBUF_SIZE + 1];
00325
00326 buf = (char *) &pp[1];
00327 poff = 0;
00328 while (poff < post_data_len)
00329 {
00330 switch (pp->state)
00331 {
00332 case PP_Error:
00333 return MHD_NO;
00334 case PP_Done:
00335
00336 pp->state = PP_Error;
00337 return MHD_NO;
00338 case PP_Init:
00339 equals = 0;
00340 while ((equals + poff < post_data_len) &&
00341 (post_data[equals + poff] != '='))
00342 equals++;
00343 if (equals + pp->buffer_pos > pp->buffer_size)
00344 {
00345 pp->state = PP_Error;
00346 return MHD_NO;
00347 }
00348 memcpy (&buf[pp->buffer_pos], &post_data[poff], equals);
00349 pp->buffer_pos += equals;
00350 if (equals + poff == post_data_len)
00351 return MHD_YES;
00352 buf[pp->buffer_pos] = '\0';
00353 pp->buffer_pos = 0;
00354 MHD_http_unescape (NULL, NULL, buf);
00355 poff += equals + 1;
00356 pp->state = PP_ProcessValue;
00357 pp->value_offset = 0;
00358 break;
00359 case PP_ProcessValue:
00360
00361 memcpy (xbuf, pp->xbuf, pp->xbuf_pos);
00362 xoff = pp->xbuf_pos;
00363 pp->xbuf_pos = 0;
00364
00365
00366 amper = 0;
00367 while ((amper + poff < post_data_len) &&
00368 (amper < XBUF_SIZE) &&
00369 (post_data[amper + poff] != '&') &&
00370 (post_data[amper + poff] != '\n') &&
00371 (post_data[amper + poff] != '\r'))
00372 amper++;
00373 end_of_value_found = ((amper + poff < post_data_len) &&
00374 ((post_data[amper + poff] == '&') ||
00375 (post_data[amper + poff] == '\n') ||
00376 (post_data[amper + poff] == '\r')));
00377
00378
00379 delta = amper;
00380 if (delta > XBUF_SIZE - xoff)
00381 delta = XBUF_SIZE - xoff;
00382
00383
00384 memcpy (&xbuf[xoff], &post_data[poff], delta);
00385 xoff += delta;
00386 poff += delta;
00387
00388
00389
00390
00391 delta = xoff;
00392 if ((delta > 0) && (xbuf[delta - 1] == '%'))
00393 delta--;
00394 else if ((delta > 1) && (xbuf[delta - 2] == '%'))
00395 delta -= 2;
00396
00397
00398
00399 if (delta < xoff)
00400 {
00401 memcpy (pp->xbuf, &xbuf[delta], xoff - delta);
00402 pp->xbuf_pos = xoff - delta;
00403 xoff = delta;
00404 }
00405
00406
00407
00408
00409 if ((xoff == 0) && (poff == post_data_len))
00410 continue;
00411
00412
00413 xbuf[xoff] = '\0';
00414 xoff = MHD_http_unescape (NULL, NULL, xbuf);
00415
00416 if (MHD_NO == pp->ikvi (pp->cls, MHD_POSTDATA_KIND, (const char *) &pp[1],
00417 NULL, NULL, NULL, xbuf, pp->value_offset,
00418 xoff))
00419 {
00420 pp->state = PP_Error;
00421 return MHD_NO;
00422 }
00423 pp->value_offset += xoff;
00424
00425
00426 if (end_of_value_found)
00427 {
00428
00429 if ((post_data[poff] == '\n') || (post_data[poff] == '\r'))
00430 {
00431 pp->state = PP_ExpectNewLine;
00432 }
00433 else
00434 {
00435 poff++;
00436 pp->state = PP_Init;
00437 }
00438 }
00439 break;
00440 case PP_ExpectNewLine:
00441 if ((post_data[poff] == '\n') || (post_data[poff] == '\r'))
00442 {
00443 poff++;
00444
00445 pp->state = PP_Done;
00446 return MHD_YES;
00447 }
00448 return MHD_NO;
00449 default:
00450 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
00451 }
00452 }
00453 return MHD_YES;
00454 }
00455
00462 static int
00463 try_match_header (const char *prefix, char *line, char **suffix)
00464 {
00465 if (NULL != *suffix)
00466 return MHD_NO;
00467 while (*line != 0)
00468 {
00469 if (0 == strncasecmp (prefix, line, strlen (prefix)))
00470 {
00471 *suffix = strdup (&line[strlen (prefix)]);
00472 return MHD_YES;
00473 }
00474 ++line;
00475 }
00476 return MHD_NO;
00477 }
00478
00479 static int
00480 find_boundary (struct MHD_PostProcessor *pp,
00481 const char *boundary,
00482 size_t blen,
00483 size_t *ioffptr,
00484 enum PP_State next_state, enum PP_State next_dash_state)
00485 {
00486 char *buf = (char *) &pp[1];
00487
00488 if (pp->buffer_pos < 2 + blen)
00489 {
00490 if (pp->buffer_pos == pp->buffer_size)
00491 pp->state = PP_Error;
00492 return MHD_NO;
00493 }
00494 if ((0 != memcmp ("--", buf, 2)) || (0 != memcmp (&buf[2], boundary, blen)))
00495 {
00496 if (pp->state != PP_Init)
00497 pp->state = PP_Error;
00498 return MHD_NO;
00499 }
00500
00501 (*ioffptr) += 2 + blen;
00502
00503 pp->skip_rn = RN_Dash;
00504 pp->state = next_state;
00505 pp->dash_state = next_dash_state;
00506 return MHD_YES;
00507 }
00508
00517 static void
00518 try_get_value (const char *buf, const char *key, char **destination)
00519 {
00520 const char *spos;
00521 const char *bpos;
00522 const char *endv;
00523 size_t klen;
00524 size_t vlen;
00525
00526 if (NULL != *destination)
00527 return;
00528 bpos = buf;
00529 klen = strlen (key);
00530 while (NULL != (spos = strstr (bpos, key)))
00531 {
00532 if ((spos[klen] != '=') || ((spos != buf) && (spos[-1] != ' ')))
00533 {
00534
00535 bpos = spos + 1;
00536 continue;
00537 }
00538 if (spos[klen + 1] != '"')
00539 return;
00540 if (NULL == (endv = strstr (&spos[klen + 2], "\"")))
00541 return;
00542 vlen = endv - spos - klen - 1;
00543 *destination = malloc (vlen);
00544 if (NULL == *destination)
00545 return;
00546 (*destination)[vlen - 1] = '\0';
00547 memcpy (*destination, &spos[klen + 2], vlen - 1);
00548 return;
00549 }
00550 }
00551
00564 static int
00565 process_multipart_headers (struct MHD_PostProcessor *pp,
00566 size_t *ioffptr, enum PP_State next_state)
00567 {
00568 char *buf = (char *) &pp[1];
00569 size_t newline;
00570
00571 newline = 0;
00572 while ((newline < pp->buffer_pos) &&
00573 (buf[newline] != '\r') && (buf[newline] != '\n'))
00574 newline++;
00575 if (newline == pp->buffer_size)
00576 {
00577 pp->state = PP_Error;
00578 return MHD_NO;
00579 }
00580 if (newline == pp->buffer_pos)
00581 return MHD_NO;
00582 if (newline == 0)
00583 {
00584
00585 pp->skip_rn = RN_Full;
00586 pp->state = next_state;
00587 return MHD_YES;
00588 }
00589
00590 if (buf[newline] == '\r')
00591 pp->skip_rn = RN_OptN;
00592 buf[newline] = '\0';
00593 if (0 == strncasecmp ("Content-disposition: ",
00594 buf, strlen ("Content-disposition: ")))
00595 {
00596 try_get_value (&buf[strlen ("Content-disposition: ")],
00597 "name", &pp->content_name);
00598 try_get_value (&buf[strlen ("Content-disposition: ")],
00599 "filename", &pp->content_filename);
00600 }
00601 else
00602 {
00603 try_match_header ("Content-type: ", buf, &pp->content_type);
00604 try_match_header ("Content-Transfer-Encoding: ",
00605 buf, &pp->content_transfer_encoding);
00606 }
00607 (*ioffptr) += newline + 1;
00608 return MHD_YES;
00609 }
00610
00625 static int
00626 process_value_to_boundary (struct MHD_PostProcessor *pp,
00627 size_t *ioffptr,
00628 const char *boundary,
00629 size_t blen,
00630 enum PP_State next_state,
00631 enum PP_State next_dash_state)
00632 {
00633 char *buf = (char *) &pp[1];
00634 size_t newline;
00635
00636
00637
00638 newline = 0;
00639 while (1)
00640 {
00641 while ((newline + 4 < pp->buffer_pos) &&
00642 (0 != memcmp ("\r\n--", &buf[newline], 4)))
00643 newline++;
00644 if (newline + pp->blen + 4 <= pp->buffer_pos)
00645 {
00646
00647 if (0 != memcmp (&buf[newline + 4], boundary, pp->blen))
00648 {
00649
00650 newline += 4;
00651 continue;
00652 }
00653 else
00654 {
00655
00656
00657 pp->skip_rn = RN_Dash;
00658 pp->state = next_state;
00659 pp->dash_state = next_dash_state;
00660 (*ioffptr) += pp->blen + 4;
00661 buf[newline] = '\0';
00662 break;
00663 }
00664 }
00665 else
00666 {
00667
00668
00669
00670 if ((newline == 0) && (pp->buffer_pos == pp->buffer_size))
00671 {
00672 pp->state = PP_Error;
00673 return MHD_NO;
00674 }
00675 break;
00676 }
00677 }
00678
00679
00680
00681 if (MHD_NO == pp->ikvi (pp->cls,
00682 MHD_POSTDATA_KIND,
00683 pp->content_name,
00684 pp->content_filename,
00685 pp->content_type,
00686 pp->content_transfer_encoding,
00687 buf, pp->value_offset, newline))
00688 {
00689 pp->state = PP_Error;
00690 return MHD_NO;
00691 }
00692 pp->value_offset += newline;
00693 (*ioffptr) += newline;
00694 return MHD_YES;
00695 }
00696
00697 static void
00698 free_unmarked (struct MHD_PostProcessor *pp)
00699 {
00700 if ((pp->content_name != NULL) && (0 == (pp->have & NE_content_name)))
00701 {
00702 free (pp->content_name);
00703 pp->content_name = NULL;
00704 }
00705 if ((pp->content_type != NULL) && (0 == (pp->have & NE_content_type)))
00706 {
00707 free (pp->content_type);
00708 pp->content_type = NULL;
00709 }
00710 if ((pp->content_filename != NULL) &&
00711 (0 == (pp->have & NE_content_filename)))
00712 {
00713 free (pp->content_filename);
00714 pp->content_filename = NULL;
00715 }
00716 if ((pp->content_transfer_encoding != NULL) &&
00717 (0 == (pp->have & NE_content_transfer_encoding)))
00718 {
00719 free (pp->content_transfer_encoding);
00720 pp->content_transfer_encoding = NULL;
00721 }
00722 }
00723
00727 static int
00728 post_process_multipart (struct MHD_PostProcessor *pp,
00729 const char *post_data,
00730 size_t post_data_len)
00731 {
00732 char *buf;
00733 size_t max;
00734 size_t ioff;
00735 size_t poff;
00736 int state_changed;
00737
00738 buf = (char *) &pp[1];
00739 ioff = 0;
00740 poff = 0;
00741 state_changed = 1;
00742 while ((poff < post_data_len) ||
00743 ((pp->buffer_pos > 0) && (state_changed != 0)))
00744 {
00745
00746
00747 max = pp->buffer_size - pp->buffer_pos;
00748 if (max > post_data_len - poff)
00749 max = post_data_len - poff;
00750 memcpy (&buf[pp->buffer_pos], &post_data[poff], max);
00751 poff += max;
00752 pp->buffer_pos += max;
00753 if ((max == 0) && (state_changed == 0) && (poff < post_data_len))
00754 {
00755 pp->state = PP_Error;
00756 return MHD_NO;
00757 }
00758 state_changed = 0;
00759
00760
00761 switch (pp->skip_rn)
00762 {
00763 case RN_Inactive:
00764 break;
00765 case RN_OptN:
00766 if (buf[0] == '\n')
00767 {
00768 ioff++;
00769 pp->skip_rn = RN_Inactive;
00770 goto AGAIN;
00771 }
00772
00773 case RN_Dash:
00774 if (buf[0] == '-')
00775 {
00776 ioff++;
00777 pp->skip_rn = RN_Dash2;
00778 goto AGAIN;
00779 }
00780 pp->skip_rn = RN_Full;
00781
00782 case RN_Full:
00783 if (buf[0] == '\r')
00784 {
00785 if ((pp->buffer_pos > 1) && (buf[1] == '\n'))
00786 {
00787 pp->skip_rn = RN_Inactive;
00788 ioff += 2;
00789 }
00790 else
00791 {
00792 pp->skip_rn = RN_OptN;
00793 ioff++;
00794 }
00795 goto AGAIN;
00796 }
00797 if (buf[0] == '\n')
00798 {
00799 ioff++;
00800 pp->skip_rn = RN_Inactive;
00801 goto AGAIN;
00802 }
00803 pp->skip_rn = RN_Inactive;
00804 pp->state = PP_Error;
00805 return MHD_NO;
00806 case RN_Dash2:
00807 if (buf[0] == '-')
00808 {
00809 ioff++;
00810 pp->skip_rn = RN_Full;
00811 pp->state = pp->dash_state;
00812 goto AGAIN;
00813 }
00814 pp->state = PP_Error;
00815 break;
00816 }
00817
00818
00819 switch (pp->state)
00820 {
00821 case PP_Error:
00822 return MHD_NO;
00823 case PP_Done:
00824
00825 pp->state = PP_Error;
00826 return MHD_NO;
00827 case PP_Init:
00839 if (MHD_NO == find_boundary (pp,
00840 pp->boundary,
00841 pp->blen,
00842 &ioff,
00843 PP_ProcessEntryHeaders, PP_Done))
00844 ++ioff;
00845 break;
00846 case PP_NextBoundary:
00847 if (MHD_NO == find_boundary (pp,
00848 pp->boundary,
00849 pp->blen,
00850 &ioff,
00851 PP_ProcessEntryHeaders, PP_Done))
00852 {
00853 if (pp->state == PP_Error)
00854 return MHD_NO;
00855 goto END;
00856 }
00857 break;
00858 case PP_ProcessEntryHeaders:
00859 if (MHD_NO ==
00860 process_multipart_headers (pp, &ioff, PP_PerformCheckMultipart))
00861 {
00862 if (pp->state == PP_Error)
00863 return MHD_NO;
00864 else
00865 goto END;
00866 }
00867 state_changed = 1;
00868 break;
00869 case PP_PerformCheckMultipart:
00870 if ((pp->content_type != NULL) &&
00871 (0 == strncasecmp (pp->content_type,
00872 "multipart/mixed",
00873 strlen ("multipart/mixed"))))
00874 {
00875 pp->nested_boundary = strstr (pp->content_type, "boundary=");
00876 if (pp->nested_boundary == NULL)
00877 {
00878 pp->state = PP_Error;
00879 return MHD_NO;
00880 }
00881 pp->nested_boundary =
00882 strdup (&pp->nested_boundary[strlen ("boundary=")]);
00883 if (pp->nested_boundary == NULL)
00884 {
00885
00886 pp->state = PP_Error;
00887 return MHD_NO;
00888 }
00889
00890
00891 free (pp->content_type);
00892 pp->content_type = NULL;
00893 pp->nlen = strlen (pp->nested_boundary);
00894 pp->state = PP_Nested_Init;
00895 state_changed = 1;
00896 break;
00897 }
00898 pp->state = PP_ProcessValueToBoundary;
00899 pp->value_offset = 0;
00900 state_changed = 1;
00901 break;
00902 case PP_ProcessValueToBoundary:
00903 if (MHD_NO == process_value_to_boundary (pp,
00904 &ioff,
00905 pp->boundary,
00906 pp->blen,
00907 PP_PerformCleanup,
00908 PP_Done))
00909 {
00910 if (pp->state == PP_Error)
00911 return MHD_NO;
00912 break;
00913 }
00914 break;
00915 case PP_PerformCleanup:
00916
00917 pp->have = NE_none;
00918 free_unmarked (pp);
00919 if (pp->nested_boundary != NULL)
00920 {
00921 free (pp->nested_boundary);
00922 pp->nested_boundary = NULL;
00923 }
00924 pp->state = PP_ProcessEntryHeaders;
00925 state_changed = 1;
00926 break;
00927 case PP_Nested_Init:
00928 if (pp->nested_boundary == NULL)
00929 {
00930 pp->state = PP_Error;
00931 return MHD_NO;
00932 }
00933 if (MHD_NO == find_boundary (pp,
00934 pp->nested_boundary,
00935 pp->nlen,
00936 &ioff,
00937 PP_Nested_PerformMarking,
00938 PP_NextBoundary ))
00939 {
00940 if (pp->state == PP_Error)
00941 return MHD_NO;
00942 goto END;
00943 }
00944 break;
00945 case PP_Nested_PerformMarking:
00946
00947
00948 pp->have = NE_none;
00949 if (pp->content_name != NULL)
00950 pp->have |= NE_content_name;
00951 if (pp->content_type != NULL)
00952 pp->have |= NE_content_type;
00953 if (pp->content_filename != NULL)
00954 pp->have |= NE_content_filename;
00955 if (pp->content_transfer_encoding != NULL)
00956 pp->have |= NE_content_transfer_encoding;
00957 pp->state = PP_Nested_ProcessEntryHeaders;
00958 state_changed = 1;
00959 break;
00960 case PP_Nested_ProcessEntryHeaders:
00961 pp->value_offset = 0;
00962 if (MHD_NO ==
00963 process_multipart_headers (pp, &ioff,
00964 PP_Nested_ProcessValueToBoundary))
00965 {
00966 if (pp->state == PP_Error)
00967 return MHD_NO;
00968 else
00969 goto END;
00970 }
00971 state_changed = 1;
00972 break;
00973 case PP_Nested_ProcessValueToBoundary:
00974 if (MHD_NO == process_value_to_boundary (pp,
00975 &ioff,
00976 pp->nested_boundary,
00977 pp->nlen,
00978 PP_Nested_PerformCleanup,
00979 PP_NextBoundary))
00980 {
00981 if (pp->state == PP_Error)
00982 return MHD_NO;
00983 break;
00984 }
00985 break;
00986 case PP_Nested_PerformCleanup:
00987 free_unmarked (pp);
00988 pp->state = PP_Nested_ProcessEntryHeaders;
00989 state_changed = 1;
00990 break;
00991 default:
00992 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
00993 }
00994 AGAIN:
00995 if (ioff > 0)
00996 {
00997 memmove (buf, &buf[ioff], pp->buffer_pos - ioff);
00998 pp->buffer_pos -= ioff;
00999 ioff = 0;
01000 state_changed = 1;
01001 }
01002 }
01003 END:
01004 if (ioff != 0)
01005 {
01006 memmove (buf, &buf[ioff], pp->buffer_pos - ioff);
01007 pp->buffer_pos -= ioff;
01008 }
01009 if (poff < post_data_len)
01010 {
01011 pp->state = PP_Error;
01012 return MHD_NO;
01013 }
01014 return MHD_YES;
01015 }
01016
01031 int
01032 MHD_post_process (struct MHD_PostProcessor *pp,
01033 const char *post_data, size_t post_data_len)
01034 {
01035 if (post_data_len == 0)
01036 return MHD_YES;
01037 if (pp == NULL)
01038 return MHD_NO;
01039 if (0 == strncasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, pp->encoding,
01040 strlen(MHD_HTTP_POST_ENCODING_FORM_URLENCODED)))
01041 return post_process_urlencoded (pp, post_data, post_data_len);
01042 if (0 ==
01043 strncasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, pp->encoding,
01044 strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)))
01045 return post_process_multipart (pp, post_data, post_data_len);
01046
01047 return MHD_NO;
01048 }
01049
01053 int
01054 MHD_destroy_post_processor (struct MHD_PostProcessor *pp)
01055 {
01056 int ret;
01057
01058 if (NULL == pp)
01059 return MHD_YES;
01060
01061
01062
01063 if ((pp->xbuf_pos > 0) || (pp->state != PP_Done))
01064 ret = MHD_NO;
01065 else
01066 ret = MHD_YES;
01067 pp->have = NE_none;
01068 free_unmarked (pp);
01069 if (pp->nested_boundary != NULL)
01070 free (pp->nested_boundary);
01071 free (pp);
01072 return ret;
01073 }
01074
01075