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
00066 enum RN_State
00067 {
00071 RN_Inactive = 0,
00072
00077 RN_OptN = 1,
00078
00083 RN_Full = 2,
00084
00089 RN_Dash = 3,
00090
00094 RN_Dash2 = 4
00095 };
00096
00097
00103 enum NE_State
00104 {
00105 NE_none = 0,
00106 NE_content_name = 1,
00107 NE_content_type = 2,
00108 NE_content_filename = 4,
00109 NE_content_transfer_encoding = 8
00110 };
00111
00112
00117 struct MHD_PostProcessor
00118 {
00119
00124 struct MHD_Connection *connection;
00125
00129 MHD_PostDataIterator ikvi;
00130
00134 void *cls;
00135
00140 const char *encoding;
00141
00145 const char *boundary;
00146
00150 char *nested_boundary;
00151
00155 char *content_name;
00156
00160 char *content_type;
00161
00165 char *content_filename;
00166
00170 char *content_transfer_encoding;
00171
00176 char xbuf[8];
00177
00181 size_t buffer_size;
00182
00186 size_t buffer_pos;
00187
00191 size_t xbuf_pos;
00192
00196 uint64_t value_offset;
00197
00201 size_t blen;
00202
00206 size_t nlen;
00207
00216 int must_ikvi;
00217
00221 enum PP_State state;
00222
00229 enum RN_State skip_rn;
00230
00235 enum PP_State dash_state;
00236
00241 enum NE_State have;
00242
00243 };
00244
00245
00271 struct MHD_PostProcessor *
00272 MHD_create_post_processor (struct MHD_Connection *connection,
00273 size_t buffer_size,
00274 MHD_PostDataIterator iter, void *iter_cls)
00275 {
00276 struct MHD_PostProcessor *ret;
00277 const char *encoding;
00278 const char *boundary;
00279 size_t blen;
00280
00281 if ((buffer_size < 256) || (connection == NULL) || (iter == NULL))
00282 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
00283 encoding = MHD_lookup_connection_value (connection,
00284 MHD_HEADER_KIND,
00285 MHD_HTTP_HEADER_CONTENT_TYPE);
00286 if (encoding == NULL)
00287 return NULL;
00288 boundary = NULL;
00289 if (0 != strncasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, encoding,
00290 strlen (MHD_HTTP_POST_ENCODING_FORM_URLENCODED)))
00291 {
00292 if (0 !=
00293 strncasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, encoding,
00294 strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)))
00295 return NULL;
00296 boundary =
00297 &encoding[strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)];
00298
00299 boundary = strstr (boundary, "boundary=");
00300 if (NULL == boundary)
00301 return NULL;
00302 boundary += strlen ("boundary=");
00303 blen = strlen (boundary);
00304 if ((blen == 0) || (blen * 2 + 2 > buffer_size))
00305 return NULL;
00306 if ( (boundary[0] == '"') && (boundary[blen - 1] == '"') )
00307 {
00308
00309 ++boundary;
00310 blen -= 2;
00311 }
00312 }
00313 else
00314 blen = 0;
00315 buffer_size += 4;
00316
00317
00318 if (NULL == (ret = malloc (sizeof (struct MHD_PostProcessor) + buffer_size + 1)))
00319 return NULL;
00320 memset (ret, 0, sizeof (struct MHD_PostProcessor) + buffer_size + 1);
00321 ret->connection = connection;
00322 ret->ikvi = iter;
00323 ret->cls = iter_cls;
00324 ret->encoding = encoding;
00325 ret->buffer_size = buffer_size;
00326 ret->state = PP_Init;
00327 ret->blen = blen;
00328 ret->boundary = boundary;
00329 ret->skip_rn = RN_Inactive;
00330 return ret;
00331 }
00332
00333
00342 static int
00343 post_process_urlencoded (struct MHD_PostProcessor *pp,
00344 const char *post_data,
00345 size_t post_data_len)
00346 {
00347 size_t equals;
00348 size_t amper;
00349 size_t poff;
00350 size_t xoff;
00351 size_t delta;
00352 int end_of_value_found;
00353 char *buf;
00354 char xbuf[XBUF_SIZE + 1];
00355
00356 buf = (char *) &pp[1];
00357 poff = 0;
00358 while (poff < post_data_len)
00359 {
00360 switch (pp->state)
00361 {
00362 case PP_Error:
00363 return MHD_NO;
00364 case PP_Done:
00365
00366 pp->state = PP_Error;
00367 return MHD_NO;
00368 case PP_Init:
00369 equals = 0;
00370 while ((equals + poff < post_data_len) &&
00371 (post_data[equals + poff] != '='))
00372 equals++;
00373 if (equals + pp->buffer_pos > pp->buffer_size)
00374 {
00375 pp->state = PP_Error;
00376 return MHD_NO;
00377 }
00378 memcpy (&buf[pp->buffer_pos], &post_data[poff], equals);
00379 pp->buffer_pos += equals;
00380 if (equals + poff == post_data_len)
00381 return MHD_YES;
00382 buf[pp->buffer_pos] = '\0';
00383 pp->buffer_pos = 0;
00384 MHD_http_unescape (NULL, NULL, buf);
00385 poff += equals + 1;
00386 pp->state = PP_ProcessValue;
00387 pp->value_offset = 0;
00388 break;
00389 case PP_ProcessValue:
00390
00391 memcpy (xbuf, pp->xbuf, pp->xbuf_pos);
00392 xoff = pp->xbuf_pos;
00393 pp->xbuf_pos = 0;
00394
00395
00396 amper = 0;
00397 while ((amper + poff < post_data_len) &&
00398 (amper < XBUF_SIZE) &&
00399 (post_data[amper + poff] != '&') &&
00400 (post_data[amper + poff] != '\n') &&
00401 (post_data[amper + poff] != '\r'))
00402 amper++;
00403 end_of_value_found = ((amper + poff < post_data_len) &&
00404 ((post_data[amper + poff] == '&') ||
00405 (post_data[amper + poff] == '\n') ||
00406 (post_data[amper + poff] == '\r')));
00407
00408
00409 delta = amper;
00410 if (delta > XBUF_SIZE - xoff)
00411 delta = XBUF_SIZE - xoff;
00412
00413
00414 memcpy (&xbuf[xoff], &post_data[poff], delta);
00415 xoff += delta;
00416 poff += delta;
00417
00418
00419
00420
00421 delta = xoff;
00422 if ((delta > 0) && (xbuf[delta - 1] == '%'))
00423 delta--;
00424 else if ((delta > 1) && (xbuf[delta - 2] == '%'))
00425 delta -= 2;
00426
00427
00428
00429 if (delta < xoff)
00430 {
00431 memcpy (pp->xbuf, &xbuf[delta], xoff - delta);
00432 pp->xbuf_pos = xoff - delta;
00433 xoff = delta;
00434 }
00435
00436
00437
00438
00439 if ((xoff == 0) && (poff == post_data_len))
00440 continue;
00441
00442
00443 xbuf[xoff] = '\0';
00444 xoff = MHD_http_unescape (NULL, NULL, xbuf);
00445
00446 pp->must_ikvi = MHD_NO;
00447 if (MHD_NO == pp->ikvi (pp->cls, MHD_POSTDATA_KIND, (const char *) &pp[1],
00448 NULL, NULL, NULL, xbuf, pp->value_offset,
00449 xoff))
00450 {
00451 pp->state = PP_Error;
00452 return MHD_NO;
00453 }
00454 pp->value_offset += xoff;
00455
00456
00457 if (end_of_value_found)
00458 {
00459
00460 if ((post_data[poff] == '\n') || (post_data[poff] == '\r'))
00461 {
00462 pp->state = PP_ExpectNewLine;
00463 }
00464 else if (post_data[poff] == '&')
00465 {
00466 poff++;
00467 pp->state = PP_Init;
00468 }
00469 }
00470 break;
00471 case PP_ExpectNewLine:
00472 if ((post_data[poff] == '\n') || (post_data[poff] == '\r'))
00473 {
00474 poff++;
00475
00476 pp->state = PP_Done;
00477 return MHD_YES;
00478 }
00479 return MHD_NO;
00480 default:
00481 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
00482 }
00483 }
00484 return MHD_YES;
00485 }
00486
00487
00497 static int
00498 try_match_header (const char *prefix, char *line, char **suffix)
00499 {
00500 if (NULL != *suffix)
00501 return MHD_NO;
00502 while (*line != 0)
00503 {
00504 if (0 == strncasecmp (prefix, line, strlen (prefix)))
00505 {
00506 *suffix = strdup (&line[strlen (prefix)]);
00507 return MHD_YES;
00508 }
00509 ++line;
00510 }
00511 return MHD_NO;
00512 }
00513
00514
00528 static int
00529 find_boundary (struct MHD_PostProcessor *pp,
00530 const char *boundary,
00531 size_t blen,
00532 size_t *ioffptr,
00533 enum PP_State next_state, enum PP_State next_dash_state)
00534 {
00535 char *buf = (char *) &pp[1];
00536 const char *dash;
00537
00538 if (pp->buffer_pos < 2 + blen)
00539 {
00540 if (pp->buffer_pos == pp->buffer_size)
00541 pp->state = PP_Error;
00542
00543 return MHD_NO;
00544 }
00545 if ((0 != memcmp ("--", buf, 2)) || (0 != memcmp (&buf[2], boundary, blen)))
00546 {
00547 if (pp->state != PP_Init)
00548 {
00549
00550 pp->state = PP_Error;
00551 }
00552 else
00553 {
00554
00555 dash = memchr (buf, '-', pp->buffer_pos);
00556 if (NULL == dash)
00557 (*ioffptr) += pp->buffer_pos;
00558 else
00559 if (dash == buf)
00560 (*ioffptr)++;
00561 else
00562 (*ioffptr) += dash - buf;
00563 }
00564 return MHD_NO;
00565 }
00566
00567 (*ioffptr) += 2 + blen;
00568
00569 pp->skip_rn = RN_Dash;
00570 pp->state = next_state;
00571 pp->dash_state = next_dash_state;
00572 return MHD_YES;
00573 }
00574
00575
00582 static void
00583 try_get_value (const char *buf,
00584 const char *key,
00585 char **destination)
00586 {
00587 const char *spos;
00588 const char *bpos;
00589 const char *endv;
00590 size_t klen;
00591 size_t vlen;
00592
00593 if (NULL != *destination)
00594 return;
00595 bpos = buf;
00596 klen = strlen (key);
00597 while (NULL != (spos = strstr (bpos, key)))
00598 {
00599 if ((spos[klen] != '=') || ((spos != buf) && (spos[-1] != ' ')))
00600 {
00601
00602 bpos = spos + 1;
00603 continue;
00604 }
00605 if (spos[klen + 1] != '"')
00606 return;
00607 if (NULL == (endv = strchr (&spos[klen + 2], '\"')))
00608 return;
00609 vlen = endv - spos - klen - 1;
00610 *destination = malloc (vlen);
00611 if (NULL == *destination)
00612 return;
00613 (*destination)[vlen - 1] = '\0';
00614 memcpy (*destination, &spos[klen + 2], vlen - 1);
00615 return;
00616 }
00617 }
00618
00619
00635 static int
00636 process_multipart_headers (struct MHD_PostProcessor *pp,
00637 size_t *ioffptr, enum PP_State next_state)
00638 {
00639 char *buf = (char *) &pp[1];
00640 size_t newline;
00641
00642 newline = 0;
00643 while ((newline < pp->buffer_pos) &&
00644 (buf[newline] != '\r') && (buf[newline] != '\n'))
00645 newline++;
00646 if (newline == pp->buffer_size)
00647 {
00648 pp->state = PP_Error;
00649 return MHD_NO;
00650 }
00651 if (newline == pp->buffer_pos)
00652 return MHD_NO;
00653 if (0 == newline)
00654 {
00655
00656 pp->skip_rn = RN_Full;
00657 pp->state = next_state;
00658 return MHD_YES;
00659 }
00660
00661 if (buf[newline] == '\r')
00662 pp->skip_rn = RN_OptN;
00663 buf[newline] = '\0';
00664 if (0 == strncasecmp ("Content-disposition: ",
00665 buf, strlen ("Content-disposition: ")))
00666 {
00667 try_get_value (&buf[strlen ("Content-disposition: ")],
00668 "name", &pp->content_name);
00669 try_get_value (&buf[strlen ("Content-disposition: ")],
00670 "filename", &pp->content_filename);
00671 }
00672 else
00673 {
00674 try_match_header ("Content-type: ", buf, &pp->content_type);
00675 try_match_header ("Content-Transfer-Encoding: ",
00676 buf, &pp->content_transfer_encoding);
00677 }
00678 (*ioffptr) += newline + 1;
00679 return MHD_YES;
00680 }
00681
00682
00699 static int
00700 process_value_to_boundary (struct MHD_PostProcessor *pp,
00701 size_t *ioffptr,
00702 const char *boundary,
00703 size_t blen,
00704 enum PP_State next_state,
00705 enum PP_State next_dash_state)
00706 {
00707 char *buf = (char *) &pp[1];
00708 size_t newline;
00709 const char *r;
00710
00711
00712
00713 newline = 0;
00714 while (1)
00715 {
00716 while (newline + 4 < pp->buffer_pos)
00717 {
00718 r = memchr (&buf[newline], '\r', pp->buffer_pos - newline - 4);
00719 if (NULL == r)
00720 {
00721 newline = pp->buffer_pos - 4;
00722 break;
00723 }
00724 newline = r - buf;
00725 if (0 == memcmp ("\r\n--", &buf[newline], 4))
00726 break;
00727 newline++;
00728 }
00729 if (newline + pp->blen + 4 <= pp->buffer_pos)
00730 {
00731
00732 if (0 != memcmp (&buf[newline + 4], boundary, pp->blen))
00733 {
00734
00735 newline += 4;
00736 continue;
00737 }
00738 else
00739 {
00740
00741
00742 pp->skip_rn = RN_Dash;
00743 pp->state = next_state;
00744 pp->dash_state = next_dash_state;
00745 (*ioffptr) += pp->blen + 4;
00746 buf[newline] = '\0';
00747 break;
00748 }
00749 }
00750 else
00751 {
00752
00753
00754
00755 if ((0 == newline) && (pp->buffer_pos == pp->buffer_size))
00756 {
00757 pp->state = PP_Error;
00758 return MHD_NO;
00759 }
00760 break;
00761 }
00762 }
00763
00764
00765
00766 if ( ( (MHD_YES == pp->must_ikvi) ||
00767 (0 != newline) ) &&
00768 (MHD_NO == pp->ikvi (pp->cls,
00769 MHD_POSTDATA_KIND,
00770 pp->content_name,
00771 pp->content_filename,
00772 pp->content_type,
00773 pp->content_transfer_encoding,
00774 buf, pp->value_offset, newline)) )
00775 {
00776 pp->state = PP_Error;
00777 return MHD_NO;
00778 }
00779 pp->must_ikvi = MHD_NO;
00780 pp->value_offset += newline;
00781 (*ioffptr) += newline;
00782 return MHD_YES;
00783 }
00784
00785
00790 static void
00791 free_unmarked (struct MHD_PostProcessor *pp)
00792 {
00793 if ((NULL != pp->content_name) && (0 == (pp->have & NE_content_name)))
00794 {
00795 free (pp->content_name);
00796 pp->content_name = NULL;
00797 }
00798 if ((NULL != pp->content_type) && (0 == (pp->have & NE_content_type)))
00799 {
00800 free (pp->content_type);
00801 pp->content_type = NULL;
00802 }
00803 if ((NULL != pp->content_filename) &&
00804 (0 == (pp->have & NE_content_filename)))
00805 {
00806 free (pp->content_filename);
00807 pp->content_filename = NULL;
00808 }
00809 if ((NULL != pp->content_transfer_encoding) &&
00810 (0 == (pp->have & NE_content_transfer_encoding)))
00811 {
00812 free (pp->content_transfer_encoding);
00813 pp->content_transfer_encoding = NULL;
00814 }
00815 }
00816
00817
00826 static int
00827 post_process_multipart (struct MHD_PostProcessor *pp,
00828 const char *post_data,
00829 size_t post_data_len)
00830 {
00831 char *buf;
00832 size_t max;
00833 size_t ioff;
00834 size_t poff;
00835 int state_changed;
00836
00837 buf = (char *) &pp[1];
00838 ioff = 0;
00839 poff = 0;
00840 state_changed = 1;
00841 while ((poff < post_data_len) ||
00842 ((pp->buffer_pos > 0) && (state_changed != 0)))
00843 {
00844
00845
00846 max = pp->buffer_size - pp->buffer_pos;
00847 if (max > post_data_len - poff)
00848 max = post_data_len - poff;
00849 memcpy (&buf[pp->buffer_pos], &post_data[poff], max);
00850 poff += max;
00851 pp->buffer_pos += max;
00852 if ((max == 0) && (state_changed == 0) && (poff < post_data_len))
00853 {
00854 pp->state = PP_Error;
00855 return MHD_NO;
00856 }
00857 state_changed = 0;
00858
00859
00860 switch (pp->skip_rn)
00861 {
00862 case RN_Inactive:
00863 break;
00864 case RN_OptN:
00865 if (buf[0] == '\n')
00866 {
00867 ioff++;
00868 pp->skip_rn = RN_Inactive;
00869 goto AGAIN;
00870 }
00871
00872 case RN_Dash:
00873 if (buf[0] == '-')
00874 {
00875 ioff++;
00876 pp->skip_rn = RN_Dash2;
00877 goto AGAIN;
00878 }
00879 pp->skip_rn = RN_Full;
00880
00881 case RN_Full:
00882 if (buf[0] == '\r')
00883 {
00884 if ((pp->buffer_pos > 1) && (buf[1] == '\n'))
00885 {
00886 pp->skip_rn = RN_Inactive;
00887 ioff += 2;
00888 }
00889 else
00890 {
00891 pp->skip_rn = RN_OptN;
00892 ioff++;
00893 }
00894 goto AGAIN;
00895 }
00896 if (buf[0] == '\n')
00897 {
00898 ioff++;
00899 pp->skip_rn = RN_Inactive;
00900 goto AGAIN;
00901 }
00902 pp->skip_rn = RN_Inactive;
00903 pp->state = PP_Error;
00904 return MHD_NO;
00905 case RN_Dash2:
00906 if (buf[0] == '-')
00907 {
00908 ioff++;
00909 pp->skip_rn = RN_Full;
00910 pp->state = pp->dash_state;
00911 goto AGAIN;
00912 }
00913 pp->state = PP_Error;
00914 break;
00915 }
00916
00917
00918 switch (pp->state)
00919 {
00920 case PP_Error:
00921 return MHD_NO;
00922 case PP_Done:
00923
00924 pp->state = PP_Error;
00925 return MHD_NO;
00926 case PP_Init:
00938 (void) find_boundary (pp,
00939 pp->boundary,
00940 pp->blen,
00941 &ioff,
00942 PP_ProcessEntryHeaders, PP_Done);
00943 break;
00944 case PP_NextBoundary:
00945 if (MHD_NO == find_boundary (pp,
00946 pp->boundary,
00947 pp->blen,
00948 &ioff,
00949 PP_ProcessEntryHeaders, PP_Done))
00950 {
00951 if (pp->state == PP_Error)
00952 return MHD_NO;
00953 goto END;
00954 }
00955 break;
00956 case PP_ProcessEntryHeaders:
00957 pp->must_ikvi = MHD_YES;
00958 if (MHD_NO ==
00959 process_multipart_headers (pp, &ioff, PP_PerformCheckMultipart))
00960 {
00961 if (pp->state == PP_Error)
00962 return MHD_NO;
00963 else
00964 goto END;
00965 }
00966 state_changed = 1;
00967 break;
00968 case PP_PerformCheckMultipart:
00969 if ((pp->content_type != NULL) &&
00970 (0 == strncasecmp (pp->content_type,
00971 "multipart/mixed",
00972 strlen ("multipart/mixed"))))
00973 {
00974 pp->nested_boundary = strstr (pp->content_type, "boundary=");
00975 if (pp->nested_boundary == NULL)
00976 {
00977 pp->state = PP_Error;
00978 return MHD_NO;
00979 }
00980 pp->nested_boundary =
00981 strdup (&pp->nested_boundary[strlen ("boundary=")]);
00982 if (pp->nested_boundary == NULL)
00983 {
00984
00985 pp->state = PP_Error;
00986 return MHD_NO;
00987 }
00988
00989
00990 free (pp->content_type);
00991 pp->content_type = NULL;
00992 pp->nlen = strlen (pp->nested_boundary);
00993 pp->state = PP_Nested_Init;
00994 state_changed = 1;
00995 break;
00996 }
00997 pp->state = PP_ProcessValueToBoundary;
00998 pp->value_offset = 0;
00999 state_changed = 1;
01000 break;
01001 case PP_ProcessValueToBoundary:
01002 if (MHD_NO == process_value_to_boundary (pp,
01003 &ioff,
01004 pp->boundary,
01005 pp->blen,
01006 PP_PerformCleanup,
01007 PP_Done))
01008 {
01009 if (pp->state == PP_Error)
01010 return MHD_NO;
01011 break;
01012 }
01013 break;
01014 case PP_PerformCleanup:
01015
01016 pp->have = NE_none;
01017 free_unmarked (pp);
01018 if (pp->nested_boundary != NULL)
01019 {
01020 free (pp->nested_boundary);
01021 pp->nested_boundary = NULL;
01022 }
01023 pp->state = PP_ProcessEntryHeaders;
01024 state_changed = 1;
01025 break;
01026 case PP_Nested_Init:
01027 if (pp->nested_boundary == NULL)
01028 {
01029 pp->state = PP_Error;
01030 return MHD_NO;
01031 }
01032 if (MHD_NO == find_boundary (pp,
01033 pp->nested_boundary,
01034 pp->nlen,
01035 &ioff,
01036 PP_Nested_PerformMarking,
01037 PP_NextBoundary ))
01038 {
01039 if (pp->state == PP_Error)
01040 return MHD_NO;
01041 goto END;
01042 }
01043 break;
01044 case PP_Nested_PerformMarking:
01045
01046
01047 pp->have = NE_none;
01048 if (pp->content_name != NULL)
01049 pp->have |= NE_content_name;
01050 if (pp->content_type != NULL)
01051 pp->have |= NE_content_type;
01052 if (pp->content_filename != NULL)
01053 pp->have |= NE_content_filename;
01054 if (pp->content_transfer_encoding != NULL)
01055 pp->have |= NE_content_transfer_encoding;
01056 pp->state = PP_Nested_ProcessEntryHeaders;
01057 state_changed = 1;
01058 break;
01059 case PP_Nested_ProcessEntryHeaders:
01060 pp->value_offset = 0;
01061 if (MHD_NO ==
01062 process_multipart_headers (pp, &ioff,
01063 PP_Nested_ProcessValueToBoundary))
01064 {
01065 if (pp->state == PP_Error)
01066 return MHD_NO;
01067 else
01068 goto END;
01069 }
01070 state_changed = 1;
01071 break;
01072 case PP_Nested_ProcessValueToBoundary:
01073 if (MHD_NO == process_value_to_boundary (pp,
01074 &ioff,
01075 pp->nested_boundary,
01076 pp->nlen,
01077 PP_Nested_PerformCleanup,
01078 PP_NextBoundary))
01079 {
01080 if (pp->state == PP_Error)
01081 return MHD_NO;
01082 break;
01083 }
01084 break;
01085 case PP_Nested_PerformCleanup:
01086 free_unmarked (pp);
01087 pp->state = PP_Nested_ProcessEntryHeaders;
01088 state_changed = 1;
01089 break;
01090 default:
01091 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
01092 }
01093 AGAIN:
01094 if (ioff > 0)
01095 {
01096 memmove (buf, &buf[ioff], pp->buffer_pos - ioff);
01097 pp->buffer_pos -= ioff;
01098 ioff = 0;
01099 state_changed = 1;
01100 }
01101 }
01102 END:
01103 if (ioff != 0)
01104 {
01105 memmove (buf, &buf[ioff], pp->buffer_pos - ioff);
01106 pp->buffer_pos -= ioff;
01107 }
01108 if (poff < post_data_len)
01109 {
01110 pp->state = PP_Error;
01111 return MHD_NO;
01112 }
01113 return MHD_YES;
01114 }
01115
01116
01130 int
01131 MHD_post_process (struct MHD_PostProcessor *pp,
01132 const char *post_data, size_t post_data_len)
01133 {
01134 if (0 == post_data_len)
01135 return MHD_YES;
01136 if (NULL == pp)
01137 return MHD_NO;
01138 if (0 == strncasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, pp->encoding,
01139 strlen(MHD_HTTP_POST_ENCODING_FORM_URLENCODED)))
01140 return post_process_urlencoded (pp, post_data, post_data_len);
01141 if (0 ==
01142 strncasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, pp->encoding,
01143 strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)))
01144 return post_process_multipart (pp, post_data, post_data_len);
01145
01146 return MHD_NO;
01147 }
01148
01149
01160 int
01161 MHD_destroy_post_processor (struct MHD_PostProcessor *pp)
01162 {
01163 int ret;
01164
01165 if (NULL == pp)
01166 return MHD_YES;
01167 if (PP_ProcessValue == pp->state)
01168 {
01169
01170
01171
01172 post_process_urlencoded (pp, "\n", 1);
01173 }
01174
01175
01176
01177 if ((pp->xbuf_pos > 0) ||
01178 ( (pp->state != PP_Done) &&
01179 (pp->state != PP_ExpectNewLine)))
01180 ret = MHD_NO;
01181 else
01182 ret = MHD_YES;
01183 pp->have = NE_none;
01184 free_unmarked (pp);
01185 if (pp->nested_boundary != NULL)
01186 free (pp->nested_boundary);
01187 free (pp);
01188 return ret;
01189 }
01190
01191