diff options
Diffstat (limited to 'src/microhttpd/postprocessor.c')
-rw-r--r-- | src/microhttpd/postprocessor.c | 1205 |
1 files changed, 605 insertions, 600 deletions
diff --git a/src/microhttpd/postprocessor.c b/src/microhttpd/postprocessor.c index e9d40ef7..8b6a33ea 100644 --- a/src/microhttpd/postprocessor.c +++ b/src/microhttpd/postprocessor.c | |||
@@ -291,44 +291,48 @@ MHD_create_post_processor (struct MHD_Connection *connection, | |||
291 | if (MHD_NO == MHD_lookup_connection_value_n (connection, | 291 | if (MHD_NO == MHD_lookup_connection_value_n (connection, |
292 | MHD_HEADER_KIND, | 292 | MHD_HEADER_KIND, |
293 | MHD_HTTP_HEADER_CONTENT_TYPE, | 293 | MHD_HTTP_HEADER_CONTENT_TYPE, |
294 | MHD_STATICSTR_LEN_(MHD_HTTP_HEADER_CONTENT_TYPE), | 294 | MHD_STATICSTR_LEN_ ( |
295 | MHD_HTTP_HEADER_CONTENT_TYPE), | ||
295 | &encoding, | 296 | &encoding, |
296 | NULL)) | 297 | NULL)) |
297 | return NULL; | 298 | return NULL; |
298 | boundary = NULL; | 299 | boundary = NULL; |
299 | if (! MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, | 300 | if (! MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, |
300 | encoding, | 301 | encoding, |
301 | MHD_STATICSTR_LEN_ (MHD_HTTP_POST_ENCODING_FORM_URLENCODED))) | 302 | MHD_STATICSTR_LEN_ ( |
303 | MHD_HTTP_POST_ENCODING_FORM_URLENCODED))) | ||
304 | { | ||
305 | if (! MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, | ||
306 | encoding, | ||
307 | MHD_STATICSTR_LEN_ ( | ||
308 | MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA))) | ||
309 | return NULL; | ||
310 | boundary = | ||
311 | &encoding[MHD_STATICSTR_LEN_ (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)]; | ||
312 | /* Q: should this be "strcasestr"? */ | ||
313 | boundary = strstr (boundary, "boundary="); | ||
314 | if (NULL == boundary) | ||
315 | return NULL; /* failed to determine boundary */ | ||
316 | boundary += MHD_STATICSTR_LEN_ ("boundary="); | ||
317 | blen = strlen (boundary); | ||
318 | if ( (blen == 0) || | ||
319 | (blen * 2 + 2 > buffer_size) ) | ||
320 | return NULL; /* (will be) out of memory or invalid boundary */ | ||
321 | if ( (boundary[0] == '"') && | ||
322 | (boundary[blen - 1] == '"') ) | ||
302 | { | 323 | { |
303 | if (! MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, | 324 | /* remove enclosing quotes */ |
304 | encoding, | 325 | ++boundary; |
305 | MHD_STATICSTR_LEN_ (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA))) | 326 | blen -= 2; |
306 | return NULL; | ||
307 | boundary = | ||
308 | &encoding[MHD_STATICSTR_LEN_ (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)]; | ||
309 | /* Q: should this be "strcasestr"? */ | ||
310 | boundary = strstr (boundary, "boundary="); | ||
311 | if (NULL == boundary) | ||
312 | return NULL; /* failed to determine boundary */ | ||
313 | boundary += MHD_STATICSTR_LEN_ ("boundary="); | ||
314 | blen = strlen (boundary); | ||
315 | if ( (blen == 0) || | ||
316 | (blen * 2 + 2 > buffer_size) ) | ||
317 | return NULL; /* (will be) out of memory or invalid boundary */ | ||
318 | if ( (boundary[0] == '"') && | ||
319 | (boundary[blen - 1] == '"') ) | ||
320 | { | ||
321 | /* remove enclosing quotes */ | ||
322 | ++boundary; | ||
323 | blen -= 2; | ||
324 | } | ||
325 | } | 327 | } |
328 | } | ||
326 | else | 329 | else |
327 | blen = 0; | 330 | blen = 0; |
328 | buffer_size += 4; /* round up to get nice block sizes despite boundary search */ | 331 | buffer_size += 4; /* round up to get nice block sizes despite boundary search */ |
329 | 332 | ||
330 | /* add +1 to ensure we ALWAYS have a zero-termination at the end */ | 333 | /* add +1 to ensure we ALWAYS have a zero-termination at the end */ |
331 | if (NULL == (ret = MHD_calloc_ (1, sizeof (struct MHD_PostProcessor) + buffer_size + 1))) | 334 | if (NULL == (ret = MHD_calloc_ (1, sizeof (struct MHD_PostProcessor) |
335 | + buffer_size + 1))) | ||
332 | return NULL; | 336 | return NULL; |
333 | ret->connection = connection; | 337 | ret->connection = connection; |
334 | ret->ikvi = iter; | 338 | ret->ikvi = iter; |
@@ -354,7 +358,7 @@ MHD_create_post_processor (struct MHD_Connection *connection, | |||
354 | static int | 358 | static int |
355 | post_process_urlencoded (struct MHD_PostProcessor *pp, | 359 | post_process_urlencoded (struct MHD_PostProcessor *pp, |
356 | const char *post_data, | 360 | const char *post_data, |
357 | size_t post_data_len) | 361 | size_t post_data_len) |
358 | { | 362 | { |
359 | size_t equals; | 363 | size_t equals; |
360 | size_t amper; | 364 | size_t amper; |
@@ -368,149 +372,149 @@ post_process_urlencoded (struct MHD_PostProcessor *pp, | |||
368 | buf = (char *) &pp[1]; | 372 | buf = (char *) &pp[1]; |
369 | poff = 0; | 373 | poff = 0; |
370 | while (poff < post_data_len) | 374 | while (poff < post_data_len) |
375 | { | ||
376 | switch (pp->state) | ||
371 | { | 377 | { |
372 | switch (pp->state) | 378 | case PP_Error: |
379 | return MHD_NO; | ||
380 | case PP_Done: | ||
381 | /* did not expect to receive more data */ | ||
382 | pp->state = PP_Error; | ||
383 | return MHD_NO; | ||
384 | case PP_Init: | ||
385 | equals = 0; | ||
386 | while ((equals + poff < post_data_len) && | ||
387 | (post_data[equals + poff] != '=')) | ||
388 | equals++; | ||
389 | if (equals + pp->buffer_pos > pp->buffer_size) | ||
390 | { | ||
391 | pp->state = PP_Error; /* out of memory */ | ||
392 | return MHD_NO; | ||
393 | } | ||
394 | memcpy (&buf[pp->buffer_pos], &post_data[poff], equals); | ||
395 | pp->buffer_pos += equals; | ||
396 | if (equals + poff == post_data_len) | ||
397 | return MHD_YES; /* no '=' yet */ | ||
398 | buf[pp->buffer_pos] = '\0'; /* 0-terminate key */ | ||
399 | pp->buffer_pos = 0; /* reset for next key */ | ||
400 | MHD_unescape_plus (buf); | ||
401 | MHD_http_unescape (buf); | ||
402 | poff += equals + 1; | ||
403 | pp->state = PP_ProcessValue; | ||
404 | pp->value_offset = 0; | ||
405 | break; | ||
406 | case PP_ProcessValue: | ||
407 | /* obtain rest of value from previous iteration */ | ||
408 | memcpy (xbuf, pp->xbuf, pp->xbuf_pos); | ||
409 | xoff = pp->xbuf_pos; | ||
410 | pp->xbuf_pos = 0; | ||
411 | |||
412 | /* find last position in input buffer that is part of the value */ | ||
413 | amper = 0; | ||
414 | while ((amper + poff < post_data_len) && | ||
415 | (amper < XBUF_SIZE) && | ||
416 | (post_data[amper + poff] != '&') && | ||
417 | (post_data[amper + poff] != '\n') && | ||
418 | (post_data[amper + poff] != '\r')) | ||
419 | amper++; | ||
420 | end_of_value_found = ((amper + poff < post_data_len) && | ||
421 | ((post_data[amper + poff] == '&') || | ||
422 | (post_data[amper + poff] == '\n') || | ||
423 | (post_data[amper + poff] == '\r'))); | ||
424 | /* compute delta, the maximum number of bytes that we will be able to | ||
425 | process right now (either amper-limited of xbuf-size limited) */ | ||
426 | delta = amper; | ||
427 | if (delta > XBUF_SIZE - xoff) | ||
428 | delta = XBUF_SIZE - xoff; | ||
429 | |||
430 | /* move input into processing buffer */ | ||
431 | memcpy (&xbuf[xoff], &post_data[poff], delta); | ||
432 | xoff += delta; | ||
433 | poff += delta; | ||
434 | |||
435 | /* find if escape sequence is at the end of the processing buffer; | ||
436 | if so, exclude those from processing (reduce delta to point at | ||
437 | end of processed region) */ | ||
438 | delta = xoff; | ||
439 | if ((delta > 0) && | ||
440 | ('%' == xbuf[delta - 1])) | ||
441 | delta--; | ||
442 | else if ((delta > 1) && | ||
443 | ('%' == xbuf[delta - 2])) | ||
444 | delta -= 2; | ||
445 | |||
446 | /* if we have an incomplete escape sequence, save it to | ||
447 | pp->xbuf for later */ | ||
448 | if (delta < xoff) | ||
449 | { | ||
450 | memcpy (pp->xbuf, | ||
451 | &xbuf[delta], | ||
452 | xoff - delta); | ||
453 | pp->xbuf_pos = xoff - delta; | ||
454 | xoff = delta; | ||
455 | } | ||
456 | |||
457 | /* If we have nothing to do (delta == 0) and | ||
458 | not just because the value is empty (are | ||
459 | waiting for more data), go for next iteration */ | ||
460 | if ( (0 == xoff) && | ||
461 | (poff == post_data_len)) | ||
462 | continue; | ||
463 | |||
464 | /* unescape */ | ||
465 | xbuf[xoff] = '\0'; /* 0-terminate in preparation */ | ||
466 | MHD_unescape_plus (xbuf); | ||
467 | xoff = MHD_http_unescape (xbuf); | ||
468 | /* finally: call application! */ | ||
469 | pp->must_ikvi = MHD_NO; | ||
470 | if (MHD_NO == pp->ikvi (pp->cls, | ||
471 | MHD_POSTDATA_KIND, | ||
472 | (const char *) &pp[1], /* key */ | ||
473 | NULL, | ||
474 | NULL, | ||
475 | NULL, | ||
476 | xbuf, | ||
477 | pp->value_offset, | ||
478 | xoff)) | ||
479 | { | ||
480 | pp->state = PP_Error; | ||
481 | return MHD_NO; | ||
482 | } | ||
483 | pp->value_offset += xoff; | ||
484 | |||
485 | /* are we done with the value? */ | ||
486 | if (end_of_value_found) | ||
487 | { | ||
488 | /* we found the end of the value! */ | ||
489 | if ( ('\n' == post_data[poff]) || | ||
490 | ('\r' == post_data[poff]) ) | ||
373 | { | 491 | { |
374 | case PP_Error: | 492 | pp->state = PP_ExpectNewLine; |
375 | return MHD_NO; | 493 | } |
376 | case PP_Done: | 494 | else if ('&' == post_data[poff]) |
377 | /* did not expect to receive more data */ | 495 | { |
378 | pp->state = PP_Error; | 496 | poff++; /* skip '&' */ |
379 | return MHD_NO; | 497 | pp->state = PP_Init; |
380 | case PP_Init: | ||
381 | equals = 0; | ||
382 | while ((equals + poff < post_data_len) && | ||
383 | (post_data[equals + poff] != '=')) | ||
384 | equals++; | ||
385 | if (equals + pp->buffer_pos > pp->buffer_size) | ||
386 | { | ||
387 | pp->state = PP_Error; /* out of memory */ | ||
388 | return MHD_NO; | ||
389 | } | ||
390 | memcpy (&buf[pp->buffer_pos], &post_data[poff], equals); | ||
391 | pp->buffer_pos += equals; | ||
392 | if (equals + poff == post_data_len) | ||
393 | return MHD_YES; /* no '=' yet */ | ||
394 | buf[pp->buffer_pos] = '\0'; /* 0-terminate key */ | ||
395 | pp->buffer_pos = 0; /* reset for next key */ | ||
396 | MHD_unescape_plus (buf); | ||
397 | MHD_http_unescape (buf); | ||
398 | poff += equals + 1; | ||
399 | pp->state = PP_ProcessValue; | ||
400 | pp->value_offset = 0; | ||
401 | break; | ||
402 | case PP_ProcessValue: | ||
403 | /* obtain rest of value from previous iteration */ | ||
404 | memcpy (xbuf, pp->xbuf, pp->xbuf_pos); | ||
405 | xoff = pp->xbuf_pos; | ||
406 | pp->xbuf_pos = 0; | ||
407 | |||
408 | /* find last position in input buffer that is part of the value */ | ||
409 | amper = 0; | ||
410 | while ((amper + poff < post_data_len) && | ||
411 | (amper < XBUF_SIZE) && | ||
412 | (post_data[amper + poff] != '&') && | ||
413 | (post_data[amper + poff] != '\n') && | ||
414 | (post_data[amper + poff] != '\r')) | ||
415 | amper++; | ||
416 | end_of_value_found = ((amper + poff < post_data_len) && | ||
417 | ((post_data[amper + poff] == '&') || | ||
418 | (post_data[amper + poff] == '\n') || | ||
419 | (post_data[amper + poff] == '\r'))); | ||
420 | /* compute delta, the maximum number of bytes that we will be able to | ||
421 | process right now (either amper-limited of xbuf-size limited) */ | ||
422 | delta = amper; | ||
423 | if (delta > XBUF_SIZE - xoff) | ||
424 | delta = XBUF_SIZE - xoff; | ||
425 | |||
426 | /* move input into processing buffer */ | ||
427 | memcpy (&xbuf[xoff], &post_data[poff], delta); | ||
428 | xoff += delta; | ||
429 | poff += delta; | ||
430 | |||
431 | /* find if escape sequence is at the end of the processing buffer; | ||
432 | if so, exclude those from processing (reduce delta to point at | ||
433 | end of processed region) */ | ||
434 | delta = xoff; | ||
435 | if ((delta > 0) && | ||
436 | ('%' == xbuf[delta - 1])) | ||
437 | delta--; | ||
438 | else if ((delta > 1) && | ||
439 | ('%' == xbuf[delta - 2])) | ||
440 | delta -= 2; | ||
441 | |||
442 | /* if we have an incomplete escape sequence, save it to | ||
443 | pp->xbuf for later */ | ||
444 | if (delta < xoff) | ||
445 | { | ||
446 | memcpy (pp->xbuf, | ||
447 | &xbuf[delta], | ||
448 | xoff - delta); | ||
449 | pp->xbuf_pos = xoff - delta; | ||
450 | xoff = delta; | ||
451 | } | ||
452 | |||
453 | /* If we have nothing to do (delta == 0) and | ||
454 | not just because the value is empty (are | ||
455 | waiting for more data), go for next iteration */ | ||
456 | if ( (0 == xoff) && | ||
457 | (poff == post_data_len)) | ||
458 | continue; | ||
459 | |||
460 | /* unescape */ | ||
461 | xbuf[xoff] = '\0'; /* 0-terminate in preparation */ | ||
462 | MHD_unescape_plus (xbuf); | ||
463 | xoff = MHD_http_unescape (xbuf); | ||
464 | /* finally: call application! */ | ||
465 | pp->must_ikvi = MHD_NO; | ||
466 | if (MHD_NO == pp->ikvi (pp->cls, | ||
467 | MHD_POSTDATA_KIND, | ||
468 | (const char *) &pp[1], /* key */ | ||
469 | NULL, | ||
470 | NULL, | ||
471 | NULL, | ||
472 | xbuf, | ||
473 | pp->value_offset, | ||
474 | xoff)) | ||
475 | { | ||
476 | pp->state = PP_Error; | ||
477 | return MHD_NO; | ||
478 | } | ||
479 | pp->value_offset += xoff; | ||
480 | |||
481 | /* are we done with the value? */ | ||
482 | if (end_of_value_found) | ||
483 | { | ||
484 | /* we found the end of the value! */ | ||
485 | if ( ('\n' == post_data[poff]) || | ||
486 | ('\r' == post_data[poff]) ) | ||
487 | { | ||
488 | pp->state = PP_ExpectNewLine; | ||
489 | } | ||
490 | else if ('&' == post_data[poff]) | ||
491 | { | ||
492 | poff++; /* skip '&' */ | ||
493 | pp->state = PP_Init; | ||
494 | } | ||
495 | } | ||
496 | break; | ||
497 | case PP_ExpectNewLine: | ||
498 | if ( ('\n' == post_data[poff]) || | ||
499 | ('\r' == post_data[poff]) ) | ||
500 | { | ||
501 | poff++; | ||
502 | /* we are done, report error if we receive any more... */ | ||
503 | pp->state = PP_Done; | ||
504 | return MHD_YES; | ||
505 | } | ||
506 | return MHD_NO; | ||
507 | default: | ||
508 | mhd_panic (mhd_panic_cls, | ||
509 | __FILE__, | ||
510 | __LINE__, | ||
511 | NULL); /* should never happen! */ | ||
512 | } | 498 | } |
499 | } | ||
500 | break; | ||
501 | case PP_ExpectNewLine: | ||
502 | if ( ('\n' == post_data[poff]) || | ||
503 | ('\r' == post_data[poff]) ) | ||
504 | { | ||
505 | poff++; | ||
506 | /* we are done, report error if we receive any more... */ | ||
507 | pp->state = PP_Done; | ||
508 | return MHD_YES; | ||
509 | } | ||
510 | return MHD_NO; | ||
511 | default: | ||
512 | mhd_panic (mhd_panic_cls, | ||
513 | __FILE__, | ||
514 | __LINE__, | ||
515 | NULL); /* should never happen! */ | ||
513 | } | 516 | } |
517 | } | ||
514 | return MHD_YES; | 518 | return MHD_YES; |
515 | } | 519 | } |
516 | 520 | ||
@@ -534,16 +538,16 @@ try_match_header (const char *prefix, | |||
534 | if (NULL != *suffix) | 538 | if (NULL != *suffix) |
535 | return MHD_NO; | 539 | return MHD_NO; |
536 | while (0 != *line) | 540 | while (0 != *line) |
541 | { | ||
542 | if (MHD_str_equal_caseless_n_ (prefix, | ||
543 | line, | ||
544 | prefix_len)) | ||
537 | { | 545 | { |
538 | if (MHD_str_equal_caseless_n_ (prefix, | 546 | *suffix = strdup (&line[prefix_len]); |
539 | line, | 547 | return MHD_YES; |
540 | prefix_len)) | ||
541 | { | ||
542 | *suffix = strdup (&line[prefix_len]); | ||
543 | return MHD_YES; | ||
544 | } | ||
545 | ++line; | ||
546 | } | 548 | } |
549 | ++line; | ||
550 | } | ||
547 | return MHD_NO; | 551 | return MHD_NO; |
548 | } | 552 | } |
549 | 553 | ||
@@ -573,40 +577,39 @@ find_boundary (struct MHD_PostProcessor *pp, | |||
573 | const char *dash; | 577 | const char *dash; |
574 | 578 | ||
575 | if (pp->buffer_pos < 2 + blen) | 579 | if (pp->buffer_pos < 2 + blen) |
576 | { | 580 | { |
577 | if (pp->buffer_pos == pp->buffer_size) | 581 | if (pp->buffer_pos == pp->buffer_size) |
578 | pp->state = PP_Error; /* out of memory */ | 582 | pp->state = PP_Error; /* out of memory */ |
579 | /* ++(*ioffptr); */ | 583 | /* ++(*ioffptr); */ |
580 | return MHD_NO; /* not enough data */ | 584 | return MHD_NO; /* not enough data */ |
581 | } | 585 | } |
582 | if ( (0 != memcmp ("--", | 586 | if ( (0 != memcmp ("--", |
583 | buf, | 587 | buf, |
584 | 2)) || | 588 | 2)) || |
585 | (0 != memcmp (&buf[2], | 589 | (0 != memcmp (&buf[2], |
586 | boundary, | 590 | boundary, |
587 | blen))) | 591 | blen))) |
592 | { | ||
593 | if (pp->state != PP_Init) | ||
588 | { | 594 | { |
589 | if (pp->state != PP_Init) | 595 | /* garbage not allowed */ |
590 | { | 596 | pp->state = PP_Error; |
591 | /* garbage not allowed */ | 597 | } |
592 | pp->state = PP_Error; | 598 | else |
593 | } | 599 | { |
600 | /* skip over garbage (RFC 2046, 5.1.1) */ | ||
601 | dash = memchr (buf, | ||
602 | '-', | ||
603 | pp->buffer_pos); | ||
604 | if (NULL == dash) | ||
605 | (*ioffptr) += pp->buffer_pos; /* skip entire buffer */ | ||
606 | else if (dash == buf) | ||
607 | (*ioffptr)++; /* at least skip one byte */ | ||
594 | else | 608 | else |
595 | { | 609 | (*ioffptr) += dash - buf; /* skip to first possible boundary */ |
596 | /* skip over garbage (RFC 2046, 5.1.1) */ | ||
597 | dash = memchr (buf, | ||
598 | '-', | ||
599 | pp->buffer_pos); | ||
600 | if (NULL == dash) | ||
601 | (*ioffptr) += pp->buffer_pos; /* skip entire buffer */ | ||
602 | else | ||
603 | if (dash == buf) | ||
604 | (*ioffptr)++; /* at least skip one byte */ | ||
605 | else | ||
606 | (*ioffptr) += dash - buf; /* skip to first possible boundary */ | ||
607 | } | ||
608 | return MHD_NO; /* expected boundary */ | ||
609 | } | 610 | } |
611 | return MHD_NO; /* expected boundary */ | ||
612 | } | ||
610 | /* remove boundary from buffer */ | 613 | /* remove boundary from buffer */ |
611 | (*ioffptr) += 2 + blen; | 614 | (*ioffptr) += 2 + blen; |
612 | /* next: start with headers */ | 615 | /* next: start with headers */ |
@@ -625,8 +628,8 @@ find_boundary (struct MHD_PostProcessor *pp, | |||
625 | */ | 628 | */ |
626 | static void | 629 | static void |
627 | try_get_value (const char *buf, | 630 | try_get_value (const char *buf, |
628 | const char *key, | 631 | const char *key, |
629 | char **destination) | 632 | char **destination) |
630 | { | 633 | { |
631 | const char *spos; | 634 | const char *spos; |
632 | const char *bpos; | 635 | const char *bpos; |
@@ -639,30 +642,30 @@ try_get_value (const char *buf, | |||
639 | bpos = buf; | 642 | bpos = buf; |
640 | klen = strlen (key); | 643 | klen = strlen (key); |
641 | while (NULL != (spos = strstr (bpos, key))) | 644 | while (NULL != (spos = strstr (bpos, key))) |
645 | { | ||
646 | if ( (spos[klen] != '=') || | ||
647 | ( (spos != buf) && | ||
648 | (spos[-1] != ' ') ) ) | ||
642 | { | 649 | { |
643 | if ( (spos[klen] != '=') || | 650 | /* no match */ |
644 | ( (spos != buf) && | 651 | bpos = spos + 1; |
645 | (spos[-1] != ' ') ) ) | 652 | continue; |
646 | { | ||
647 | /* no match */ | ||
648 | bpos = spos + 1; | ||
649 | continue; | ||
650 | } | ||
651 | if (spos[klen + 1] != '"') | ||
652 | return; /* not quoted */ | ||
653 | if (NULL == (endv = strchr (&spos[klen + 2], | ||
654 | '\"'))) | ||
655 | return; /* no end-quote */ | ||
656 | vlen = endv - spos - klen - 1; | ||
657 | *destination = malloc (vlen); | ||
658 | if (NULL == *destination) | ||
659 | return; /* out of memory */ | ||
660 | (*destination)[vlen - 1] = '\0'; | ||
661 | memcpy (*destination, | ||
662 | &spos[klen + 2], | ||
663 | vlen - 1); | ||
664 | return; /* success */ | ||
665 | } | 653 | } |
654 | if (spos[klen + 1] != '"') | ||
655 | return; /* not quoted */ | ||
656 | if (NULL == (endv = strchr (&spos[klen + 2], | ||
657 | '\"'))) | ||
658 | return; /* no end-quote */ | ||
659 | vlen = endv - spos - klen - 1; | ||
660 | *destination = malloc (vlen); | ||
661 | if (NULL == *destination) | ||
662 | return; /* out of memory */ | ||
663 | (*destination)[vlen - 1] = '\0'; | ||
664 | memcpy (*destination, | ||
665 | &spos[klen + 2], | ||
666 | vlen - 1); | ||
667 | return; /* success */ | ||
668 | } | ||
666 | } | 669 | } |
667 | 670 | ||
668 | 671 | ||
@@ -695,19 +698,19 @@ process_multipart_headers (struct MHD_PostProcessor *pp, | |||
695 | (buf[newline] != '\n') ) | 698 | (buf[newline] != '\n') ) |
696 | newline++; | 699 | newline++; |
697 | if (newline == pp->buffer_size) | 700 | if (newline == pp->buffer_size) |
698 | { | 701 | { |
699 | pp->state = PP_Error; | 702 | pp->state = PP_Error; |
700 | return MHD_NO; /* out of memory */ | 703 | return MHD_NO; /* out of memory */ |
701 | } | 704 | } |
702 | if (newline == pp->buffer_pos) | 705 | if (newline == pp->buffer_pos) |
703 | return MHD_NO; /* will need more data */ | 706 | return MHD_NO; /* will need more data */ |
704 | if (0 == newline) | 707 | if (0 == newline) |
705 | { | 708 | { |
706 | /* empty line - end of headers */ | 709 | /* empty line - end of headers */ |
707 | pp->skip_rn = RN_Full; | 710 | pp->skip_rn = RN_Full; |
708 | pp->state = next_state; | 711 | pp->state = next_state; |
709 | return MHD_YES; | 712 | return MHD_YES; |
710 | } | 713 | } |
711 | /* got an actual header */ | 714 | /* got an actual header */ |
712 | if (buf[newline] == '\r') | 715 | if (buf[newline] == '\r') |
713 | pp->skip_rn = RN_OptN; | 716 | pp->skip_rn = RN_OptN; |
@@ -715,25 +718,25 @@ process_multipart_headers (struct MHD_PostProcessor *pp, | |||
715 | if (MHD_str_equal_caseless_n_ ("Content-disposition: ", | 718 | if (MHD_str_equal_caseless_n_ ("Content-disposition: ", |
716 | buf, | 719 | buf, |
717 | MHD_STATICSTR_LEN_ ("Content-disposition: "))) | 720 | MHD_STATICSTR_LEN_ ("Content-disposition: "))) |
718 | { | 721 | { |
719 | try_get_value (&buf[MHD_STATICSTR_LEN_ ("Content-disposition: ")], | 722 | try_get_value (&buf[MHD_STATICSTR_LEN_ ("Content-disposition: ")], |
720 | "name", | 723 | "name", |
721 | &pp->content_name); | 724 | &pp->content_name); |
722 | try_get_value (&buf[MHD_STATICSTR_LEN_ ("Content-disposition: ")], | 725 | try_get_value (&buf[MHD_STATICSTR_LEN_ ("Content-disposition: ")], |
723 | "filename", | 726 | "filename", |
724 | &pp->content_filename); | 727 | &pp->content_filename); |
725 | } | 728 | } |
726 | else | 729 | else |
727 | { | 730 | { |
728 | try_match_header ("Content-type: ", | 731 | try_match_header ("Content-type: ", |
729 | MHD_STATICSTR_LEN_("Content-type: "), | 732 | MHD_STATICSTR_LEN_ ("Content-type: "), |
730 | buf, | 733 | buf, |
731 | &pp->content_type); | 734 | &pp->content_type); |
732 | try_match_header ("Content-Transfer-Encoding: ", | 735 | try_match_header ("Content-Transfer-Encoding: ", |
733 | MHD_STATICSTR_LEN_("Content-Transfer-Encoding: "), | 736 | MHD_STATICSTR_LEN_ ("Content-Transfer-Encoding: "), |
734 | buf, | 737 | buf, |
735 | &pp->content_transfer_encoding); | 738 | &pp->content_transfer_encoding); |
736 | } | 739 | } |
737 | (*ioffptr) += newline + 1; | 740 | (*ioffptr) += newline + 1; |
738 | return MHD_YES; | 741 | return MHD_YES; |
739 | } | 742 | } |
@@ -771,79 +774,79 @@ process_value_to_boundary (struct MHD_PostProcessor *pp, | |||
771 | (\r\n--+boundary) is part of the value */ | 774 | (\r\n--+boundary) is part of the value */ |
772 | newline = 0; | 775 | newline = 0; |
773 | while (1) | 776 | while (1) |
777 | { | ||
778 | while (newline + 4 < pp->buffer_pos) | ||
774 | { | 779 | { |
775 | while (newline + 4 < pp->buffer_pos) | 780 | r = memchr (&buf[newline], |
776 | { | 781 | '\r', |
777 | r = memchr (&buf[newline], | 782 | pp->buffer_pos - newline - 4); |
778 | '\r', | 783 | if (NULL == r) |
779 | pp->buffer_pos - newline - 4); | 784 | { |
780 | if (NULL == r) | 785 | newline = pp->buffer_pos - 4; |
781 | { | 786 | break; |
782 | newline = pp->buffer_pos - 4; | 787 | } |
783 | break; | 788 | newline = r - buf; |
784 | } | 789 | if (0 == memcmp ("\r\n--", |
785 | newline = r - buf; | 790 | &buf[newline], |
786 | if (0 == memcmp ("\r\n--", | 791 | 4)) |
787 | &buf[newline], | 792 | break; |
788 | 4)) | 793 | newline++; |
789 | break; | 794 | } |
790 | newline++; | 795 | if (newline + blen + 4 <= pp->buffer_pos) |
791 | } | 796 | { |
792 | if (newline + blen + 4 <= pp->buffer_pos) | 797 | /* can check boundary */ |
793 | { | 798 | if (0 != memcmp (&buf[newline + 4], |
794 | /* can check boundary */ | 799 | boundary, |
795 | if (0 != memcmp (&buf[newline + 4], | 800 | blen)) |
796 | boundary, | 801 | { |
797 | blen)) | 802 | /* no boundary, "\r\n--" is part of content, skip */ |
798 | { | 803 | newline += 4; |
799 | /* no boundary, "\r\n--" is part of content, skip */ | 804 | continue; |
800 | newline += 4; | 805 | } |
801 | continue; | ||
802 | } | ||
803 | else | ||
804 | { | ||
805 | /* boundary found, process until newline then | ||
806 | skip boundary and go back to init */ | ||
807 | pp->skip_rn = RN_Dash; | ||
808 | pp->state = next_state; | ||
809 | pp->dash_state = next_dash_state; | ||
810 | (*ioffptr) += blen + 4; /* skip boundary as well */ | ||
811 | buf[newline] = '\0'; | ||
812 | break; | ||
813 | } | ||
814 | } | ||
815 | else | 806 | else |
816 | { | 807 | { |
817 | /* cannot check for boundary, process content that | 808 | /* boundary found, process until newline then |
818 | we have and check again later; except, if we have | 809 | skip boundary and go back to init */ |
819 | no content, abort (out of memory) */ | 810 | pp->skip_rn = RN_Dash; |
820 | if ( (0 == newline) && | 811 | pp->state = next_state; |
821 | (pp->buffer_pos == pp->buffer_size) ) | 812 | pp->dash_state = next_dash_state; |
822 | { | 813 | (*ioffptr) += blen + 4; /* skip boundary as well */ |
823 | pp->state = PP_Error; | 814 | buf[newline] = '\0'; |
824 | return MHD_NO; | 815 | break; |
825 | } | 816 | } |
826 | break; | ||
827 | } | ||
828 | } | 817 | } |
818 | else | ||
819 | { | ||
820 | /* cannot check for boundary, process content that | ||
821 | we have and check again later; except, if we have | ||
822 | no content, abort (out of memory) */ | ||
823 | if ( (0 == newline) && | ||
824 | (pp->buffer_pos == pp->buffer_size) ) | ||
825 | { | ||
826 | pp->state = PP_Error; | ||
827 | return MHD_NO; | ||
828 | } | ||
829 | break; | ||
830 | } | ||
831 | } | ||
829 | /* newline is either at beginning of boundary or | 832 | /* newline is either at beginning of boundary or |
830 | at least at the last character that we are sure | 833 | at least at the last character that we are sure |
831 | is not part of the boundary */ | 834 | is not part of the boundary */ |
832 | if ( ( (MHD_YES == pp->must_ikvi) || | 835 | if ( ( (MHD_YES == pp->must_ikvi) || |
833 | (0 != newline) ) && | 836 | (0 != newline) ) && |
834 | (MHD_NO == pp->ikvi (pp->cls, | 837 | (MHD_NO == pp->ikvi (pp->cls, |
835 | MHD_POSTDATA_KIND, | 838 | MHD_POSTDATA_KIND, |
836 | pp->content_name, | 839 | pp->content_name, |
837 | pp->content_filename, | 840 | pp->content_filename, |
838 | pp->content_type, | 841 | pp->content_type, |
839 | pp->content_transfer_encoding, | 842 | pp->content_transfer_encoding, |
840 | buf, | 843 | buf, |
841 | pp->value_offset, | 844 | pp->value_offset, |
842 | newline)) ) | 845 | newline)) ) |
843 | { | 846 | { |
844 | pp->state = PP_Error; | 847 | pp->state = PP_Error; |
845 | return MHD_NO; | 848 | return MHD_NO; |
846 | } | 849 | } |
847 | pp->must_ikvi = MHD_NO; | 850 | pp->must_ikvi = MHD_NO; |
848 | pp->value_offset += newline; | 851 | pp->value_offset += newline; |
849 | (*ioffptr) += newline; | 852 | (*ioffptr) += newline; |
@@ -860,28 +863,28 @@ free_unmarked (struct MHD_PostProcessor *pp) | |||
860 | { | 863 | { |
861 | if ( (NULL != pp->content_name) && | 864 | if ( (NULL != pp->content_name) && |
862 | (0 == (pp->have & NE_content_name)) ) | 865 | (0 == (pp->have & NE_content_name)) ) |
863 | { | 866 | { |
864 | free (pp->content_name); | 867 | free (pp->content_name); |
865 | pp->content_name = NULL; | 868 | pp->content_name = NULL; |
866 | } | 869 | } |
867 | if ( (NULL != pp->content_type) && | 870 | if ( (NULL != pp->content_type) && |
868 | (0 == (pp->have & NE_content_type)) ) | 871 | (0 == (pp->have & NE_content_type)) ) |
869 | { | 872 | { |
870 | free (pp->content_type); | 873 | free (pp->content_type); |
871 | pp->content_type = NULL; | 874 | pp->content_type = NULL; |
872 | } | 875 | } |
873 | if ( (NULL != pp->content_filename) && | 876 | if ( (NULL != pp->content_filename) && |
874 | (0 == (pp->have & NE_content_filename)) ) | 877 | (0 == (pp->have & NE_content_filename)) ) |
875 | { | 878 | { |
876 | free (pp->content_filename); | 879 | free (pp->content_filename); |
877 | pp->content_filename = NULL; | 880 | pp->content_filename = NULL; |
878 | } | 881 | } |
879 | if ( (NULL != pp->content_transfer_encoding) && | 882 | if ( (NULL != pp->content_transfer_encoding) && |
880 | (0 == (pp->have & NE_content_transfer_encoding)) ) | 883 | (0 == (pp->have & NE_content_transfer_encoding)) ) |
881 | { | 884 | { |
882 | free (pp->content_transfer_encoding); | 885 | free (pp->content_transfer_encoding); |
883 | pp->content_transfer_encoding = NULL; | 886 | pp->content_transfer_encoding = NULL; |
884 | } | 887 | } |
885 | } | 888 | } |
886 | 889 | ||
887 | 890 | ||
@@ -896,7 +899,7 @@ free_unmarked (struct MHD_PostProcessor *pp) | |||
896 | static int | 899 | static int |
897 | post_process_multipart (struct MHD_PostProcessor *pp, | 900 | post_process_multipart (struct MHD_PostProcessor *pp, |
898 | const char *post_data, | 901 | const char *post_data, |
899 | size_t post_data_len) | 902 | size_t post_data_len) |
900 | { | 903 | { |
901 | char *buf; | 904 | char *buf; |
902 | size_t max; | 905 | size_t max; |
@@ -911,294 +914,294 @@ post_process_multipart (struct MHD_PostProcessor *pp, | |||
911 | while ( (poff < post_data_len) || | 914 | while ( (poff < post_data_len) || |
912 | ( (pp->buffer_pos > 0) && | 915 | ( (pp->buffer_pos > 0) && |
913 | (0 != state_changed) ) ) | 916 | (0 != state_changed) ) ) |
917 | { | ||
918 | /* first, move as much input data | ||
919 | as possible to our internal buffer */ | ||
920 | max = pp->buffer_size - pp->buffer_pos; | ||
921 | if (max > post_data_len - poff) | ||
922 | max = post_data_len - poff; | ||
923 | memcpy (&buf[pp->buffer_pos], | ||
924 | &post_data[poff], | ||
925 | max); | ||
926 | poff += max; | ||
927 | pp->buffer_pos += max; | ||
928 | if ( (0 == max) && | ||
929 | (0 == state_changed) && | ||
930 | (poff < post_data_len) ) | ||
914 | { | 931 | { |
915 | /* first, move as much input data | 932 | pp->state = PP_Error; |
916 | as possible to our internal buffer */ | 933 | return MHD_NO; /* out of memory */ |
917 | max = pp->buffer_size - pp->buffer_pos; | 934 | } |
918 | if (max > post_data_len - poff) | 935 | state_changed = 0; |
919 | max = post_data_len - poff; | ||
920 | memcpy (&buf[pp->buffer_pos], | ||
921 | &post_data[poff], | ||
922 | max); | ||
923 | poff += max; | ||
924 | pp->buffer_pos += max; | ||
925 | if ( (0 == max) && | ||
926 | (0 == state_changed) && | ||
927 | (poff < post_data_len) ) | ||
928 | { | ||
929 | pp->state = PP_Error; | ||
930 | return MHD_NO; /* out of memory */ | ||
931 | } | ||
932 | state_changed = 0; | ||
933 | 936 | ||
934 | /* first state machine for '\r'-'\n' and '--' handling */ | 937 | /* first state machine for '\r'-'\n' and '--' handling */ |
935 | switch (pp->skip_rn) | 938 | switch (pp->skip_rn) |
939 | { | ||
940 | case RN_Inactive: | ||
941 | break; | ||
942 | case RN_OptN: | ||
943 | if (buf[0] == '\n') | ||
944 | { | ||
945 | ioff++; | ||
946 | pp->skip_rn = RN_Inactive; | ||
947 | goto AGAIN; | ||
948 | } | ||
949 | /* fall-through! */ | ||
950 | case RN_Dash: | ||
951 | if (buf[0] == '-') | ||
952 | { | ||
953 | ioff++; | ||
954 | pp->skip_rn = RN_Dash2; | ||
955 | goto AGAIN; | ||
956 | } | ||
957 | pp->skip_rn = RN_Full; | ||
958 | /* fall-through! */ | ||
959 | case RN_Full: | ||
960 | if (buf[0] == '\r') | ||
961 | { | ||
962 | if ( (pp->buffer_pos > 1) && | ||
963 | ('\n' == buf[1]) ) | ||
936 | { | 964 | { |
937 | case RN_Inactive: | ||
938 | break; | ||
939 | case RN_OptN: | ||
940 | if (buf[0] == '\n') | ||
941 | { | ||
942 | ioff++; | ||
943 | pp->skip_rn = RN_Inactive; | ||
944 | goto AGAIN; | ||
945 | } | ||
946 | /* fall-through! */ | ||
947 | case RN_Dash: | ||
948 | if (buf[0] == '-') | ||
949 | { | ||
950 | ioff++; | ||
951 | pp->skip_rn = RN_Dash2; | ||
952 | goto AGAIN; | ||
953 | } | ||
954 | pp->skip_rn = RN_Full; | ||
955 | /* fall-through! */ | ||
956 | case RN_Full: | ||
957 | if (buf[0] == '\r') | ||
958 | { | ||
959 | if ( (pp->buffer_pos > 1) && | ||
960 | ('\n' == buf[1]) ) | ||
961 | { | ||
962 | pp->skip_rn = RN_Inactive; | ||
963 | ioff += 2; | ||
964 | } | ||
965 | else | ||
966 | { | ||
967 | pp->skip_rn = RN_OptN; | ||
968 | ioff++; | ||
969 | } | ||
970 | goto AGAIN; | ||
971 | } | ||
972 | if (buf[0] == '\n') | ||
973 | { | ||
974 | ioff++; | ||
975 | pp->skip_rn = RN_Inactive; | ||
976 | goto AGAIN; | ||
977 | } | ||
978 | pp->skip_rn = RN_Inactive; | 965 | pp->skip_rn = RN_Inactive; |
979 | pp->state = PP_Error; | 966 | ioff += 2; |
980 | return MHD_NO; /* no '\r\n' */ | ||
981 | case RN_Dash2: | ||
982 | if (buf[0] == '-') | ||
983 | { | ||
984 | ioff++; | ||
985 | pp->skip_rn = RN_Full; | ||
986 | pp->state = pp->dash_state; | ||
987 | goto AGAIN; | ||
988 | } | ||
989 | pp->state = PP_Error; | ||
990 | break; | ||
991 | } | 967 | } |
992 | 968 | else | |
993 | /* main state engine */ | ||
994 | switch (pp->state) | ||
995 | { | 969 | { |
996 | case PP_Error: | 970 | pp->skip_rn = RN_OptN; |
971 | ioff++; | ||
972 | } | ||
973 | goto AGAIN; | ||
974 | } | ||
975 | if (buf[0] == '\n') | ||
976 | { | ||
977 | ioff++; | ||
978 | pp->skip_rn = RN_Inactive; | ||
979 | goto AGAIN; | ||
980 | } | ||
981 | pp->skip_rn = RN_Inactive; | ||
982 | pp->state = PP_Error; | ||
983 | return MHD_NO; /* no '\r\n' */ | ||
984 | case RN_Dash2: | ||
985 | if (buf[0] == '-') | ||
986 | { | ||
987 | ioff++; | ||
988 | pp->skip_rn = RN_Full; | ||
989 | pp->state = pp->dash_state; | ||
990 | goto AGAIN; | ||
991 | } | ||
992 | pp->state = PP_Error; | ||
993 | break; | ||
994 | } | ||
995 | |||
996 | /* main state engine */ | ||
997 | switch (pp->state) | ||
998 | { | ||
999 | case PP_Error: | ||
1000 | return MHD_NO; | ||
1001 | case PP_Done: | ||
1002 | /* did not expect to receive more data */ | ||
1003 | pp->state = PP_Error; | ||
1004 | return MHD_NO; | ||
1005 | case PP_Init: | ||
1006 | /** | ||
1007 | * Per RFC2046 5.1.1 NOTE TO IMPLEMENTORS, consume anything | ||
1008 | * prior to the first multipart boundary: | ||
1009 | * | ||
1010 | * > There appears to be room for additional information prior | ||
1011 | * > to the first boundary delimiter line and following the | ||
1012 | * > final boundary delimiter line. These areas should | ||
1013 | * > generally be left blank, and implementations must ignore | ||
1014 | * > anything that appears before the first boundary delimiter | ||
1015 | * > line or after the last one. | ||
1016 | */ | ||
1017 | (void) find_boundary (pp, | ||
1018 | pp->boundary, | ||
1019 | pp->blen, | ||
1020 | &ioff, | ||
1021 | PP_ProcessEntryHeaders, | ||
1022 | PP_Done); | ||
1023 | break; | ||
1024 | case PP_NextBoundary: | ||
1025 | if (MHD_NO == find_boundary (pp, | ||
1026 | pp->boundary, | ||
1027 | pp->blen, | ||
1028 | &ioff, | ||
1029 | PP_ProcessEntryHeaders, | ||
1030 | PP_Done)) | ||
1031 | { | ||
1032 | if (pp->state == PP_Error) | ||
997 | return MHD_NO; | 1033 | return MHD_NO; |
998 | case PP_Done: | 1034 | goto END; |
999 | /* did not expect to receive more data */ | 1035 | } |
1036 | break; | ||
1037 | case PP_ProcessEntryHeaders: | ||
1038 | pp->must_ikvi = MHD_YES; | ||
1039 | if (MHD_NO == | ||
1040 | process_multipart_headers (pp, | ||
1041 | &ioff, | ||
1042 | PP_PerformCheckMultipart)) | ||
1043 | { | ||
1044 | if (pp->state == PP_Error) | ||
1045 | return MHD_NO; | ||
1046 | else | ||
1047 | goto END; | ||
1048 | } | ||
1049 | state_changed = 1; | ||
1050 | break; | ||
1051 | case PP_PerformCheckMultipart: | ||
1052 | if ( (NULL != pp->content_type) && | ||
1053 | (MHD_str_equal_caseless_n_ (pp->content_type, | ||
1054 | "multipart/mixed", | ||
1055 | MHD_STATICSTR_LEN_ ("multipart/mixed")))) | ||
1056 | { | ||
1057 | pp->nested_boundary = strstr (pp->content_type, | ||
1058 | "boundary="); | ||
1059 | if (NULL == pp->nested_boundary) | ||
1060 | { | ||
1000 | pp->state = PP_Error; | 1061 | pp->state = PP_Error; |
1001 | return MHD_NO; | 1062 | return MHD_NO; |
1002 | case PP_Init: | ||
1003 | /** | ||
1004 | * Per RFC2046 5.1.1 NOTE TO IMPLEMENTORS, consume anything | ||
1005 | * prior to the first multipart boundary: | ||
1006 | * | ||
1007 | * > There appears to be room for additional information prior | ||
1008 | * > to the first boundary delimiter line and following the | ||
1009 | * > final boundary delimiter line. These areas should | ||
1010 | * > generally be left blank, and implementations must ignore | ||
1011 | * > anything that appears before the first boundary delimiter | ||
1012 | * > line or after the last one. | ||
1013 | */ | ||
1014 | (void) find_boundary (pp, | ||
1015 | pp->boundary, | ||
1016 | pp->blen, | ||
1017 | &ioff, | ||
1018 | PP_ProcessEntryHeaders, | ||
1019 | PP_Done); | ||
1020 | break; | ||
1021 | case PP_NextBoundary: | ||
1022 | if (MHD_NO == find_boundary (pp, | ||
1023 | pp->boundary, | ||
1024 | pp->blen, | ||
1025 | &ioff, | ||
1026 | PP_ProcessEntryHeaders, | ||
1027 | PP_Done)) | ||
1028 | { | ||
1029 | if (pp->state == PP_Error) | ||
1030 | return MHD_NO; | ||
1031 | goto END; | ||
1032 | } | ||
1033 | break; | ||
1034 | case PP_ProcessEntryHeaders: | ||
1035 | pp->must_ikvi = MHD_YES; | ||
1036 | if (MHD_NO == | ||
1037 | process_multipart_headers (pp, | ||
1038 | &ioff, | ||
1039 | PP_PerformCheckMultipart)) | ||
1040 | { | ||
1041 | if (pp->state == PP_Error) | ||
1042 | return MHD_NO; | ||
1043 | else | ||
1044 | goto END; | ||
1045 | } | ||
1046 | state_changed = 1; | ||
1047 | break; | ||
1048 | case PP_PerformCheckMultipart: | ||
1049 | if ( (NULL != pp->content_type) && | ||
1050 | (MHD_str_equal_caseless_n_ (pp->content_type, | ||
1051 | "multipart/mixed", | ||
1052 | MHD_STATICSTR_LEN_ ("multipart/mixed")))) | ||
1053 | { | ||
1054 | pp->nested_boundary = strstr (pp->content_type, | ||
1055 | "boundary="); | ||
1056 | if (NULL == pp->nested_boundary) | ||
1057 | { | ||
1058 | pp->state = PP_Error; | ||
1059 | return MHD_NO; | ||
1060 | } | ||
1061 | pp->nested_boundary = | ||
1062 | strdup (&pp->nested_boundary[MHD_STATICSTR_LEN_ ("boundary=")]); | ||
1063 | if (NULL == pp->nested_boundary) | ||
1064 | { | ||
1065 | /* out of memory */ | ||
1066 | pp->state = PP_Error; | ||
1067 | return MHD_NO; | ||
1068 | } | ||
1069 | /* free old content type, we will need that field | ||
1070 | for the content type of the nested elements */ | ||
1071 | free (pp->content_type); | ||
1072 | pp->content_type = NULL; | ||
1073 | pp->nlen = strlen (pp->nested_boundary); | ||
1074 | pp->state = PP_Nested_Init; | ||
1075 | state_changed = 1; | ||
1076 | break; | ||
1077 | } | ||
1078 | pp->state = PP_ProcessValueToBoundary; | ||
1079 | pp->value_offset = 0; | ||
1080 | state_changed = 1; | ||
1081 | break; | ||
1082 | case PP_ProcessValueToBoundary: | ||
1083 | if (MHD_NO == process_value_to_boundary (pp, | ||
1084 | &ioff, | ||
1085 | pp->boundary, | ||
1086 | pp->blen, | ||
1087 | PP_PerformCleanup, | ||
1088 | PP_Done)) | ||
1089 | { | ||
1090 | if (pp->state == PP_Error) | ||
1091 | return MHD_NO; | ||
1092 | break; | ||
1093 | } | ||
1094 | break; | ||
1095 | case PP_PerformCleanup: | ||
1096 | /* clean up state of one multipart form-data element! */ | ||
1097 | pp->have = NE_none; | ||
1098 | free_unmarked (pp); | ||
1099 | if (NULL != pp->nested_boundary) | ||
1100 | { | ||
1101 | free (pp->nested_boundary); | ||
1102 | pp->nested_boundary = NULL; | ||
1103 | } | ||
1104 | pp->state = PP_ProcessEntryHeaders; | ||
1105 | state_changed = 1; | ||
1106 | break; | ||
1107 | case PP_Nested_Init: | ||
1108 | if (NULL == pp->nested_boundary) | ||
1109 | { | ||
1110 | pp->state = PP_Error; | ||
1111 | return MHD_NO; | ||
1112 | } | ||
1113 | if (MHD_NO == find_boundary (pp, | ||
1114 | pp->nested_boundary, | ||
1115 | pp->nlen, | ||
1116 | &ioff, | ||
1117 | PP_Nested_PerformMarking, | ||
1118 | PP_NextBoundary /* or PP_Error? */ )) | ||
1119 | { | ||
1120 | if (pp->state == PP_Error) | ||
1121 | return MHD_NO; | ||
1122 | goto END; | ||
1123 | } | ||
1124 | break; | ||
1125 | case PP_Nested_PerformMarking: | ||
1126 | /* remember what headers were given | ||
1127 | globally */ | ||
1128 | pp->have = NE_none; | ||
1129 | if (NULL != pp->content_name) | ||
1130 | pp->have |= NE_content_name; | ||
1131 | if (NULL != pp->content_type) | ||
1132 | pp->have |= NE_content_type; | ||
1133 | if (NULL != pp->content_filename) | ||
1134 | pp->have |= NE_content_filename; | ||
1135 | if (NULL != pp->content_transfer_encoding) | ||
1136 | pp->have |= NE_content_transfer_encoding; | ||
1137 | pp->state = PP_Nested_ProcessEntryHeaders; | ||
1138 | state_changed = 1; | ||
1139 | break; | ||
1140 | case PP_Nested_ProcessEntryHeaders: | ||
1141 | pp->value_offset = 0; | ||
1142 | if (MHD_NO == | ||
1143 | process_multipart_headers (pp, | ||
1144 | &ioff, | ||
1145 | PP_Nested_ProcessValueToBoundary)) | ||
1146 | { | ||
1147 | if (pp->state == PP_Error) | ||
1148 | return MHD_NO; | ||
1149 | else | ||
1150 | goto END; | ||
1151 | } | ||
1152 | state_changed = 1; | ||
1153 | break; | ||
1154 | case PP_Nested_ProcessValueToBoundary: | ||
1155 | if (MHD_NO == process_value_to_boundary (pp, | ||
1156 | &ioff, | ||
1157 | pp->nested_boundary, | ||
1158 | pp->nlen, | ||
1159 | PP_Nested_PerformCleanup, | ||
1160 | PP_NextBoundary)) | ||
1161 | { | ||
1162 | if (pp->state == PP_Error) | ||
1163 | return MHD_NO; | ||
1164 | break; | ||
1165 | } | ||
1166 | break; | ||
1167 | case PP_Nested_PerformCleanup: | ||
1168 | free_unmarked (pp); | ||
1169 | pp->state = PP_Nested_ProcessEntryHeaders; | ||
1170 | state_changed = 1; | ||
1171 | break; | ||
1172 | default: | ||
1173 | mhd_panic (mhd_panic_cls, | ||
1174 | __FILE__, | ||
1175 | __LINE__, | ||
1176 | NULL); /* should never happen! */ | ||
1177 | } | 1063 | } |
1178 | AGAIN: | 1064 | pp->nested_boundary = |
1179 | if (ioff > 0) | 1065 | strdup (&pp->nested_boundary[MHD_STATICSTR_LEN_ ("boundary=")]); |
1066 | if (NULL == pp->nested_boundary) | ||
1180 | { | 1067 | { |
1181 | memmove (buf, | 1068 | /* out of memory */ |
1182 | &buf[ioff], | 1069 | pp->state = PP_Error; |
1183 | pp->buffer_pos - ioff); | 1070 | return MHD_NO; |
1184 | pp->buffer_pos -= ioff; | ||
1185 | ioff = 0; | ||
1186 | state_changed = 1; | ||
1187 | } | 1071 | } |
1072 | /* free old content type, we will need that field | ||
1073 | for the content type of the nested elements */ | ||
1074 | free (pp->content_type); | ||
1075 | pp->content_type = NULL; | ||
1076 | pp->nlen = strlen (pp->nested_boundary); | ||
1077 | pp->state = PP_Nested_Init; | ||
1078 | state_changed = 1; | ||
1079 | break; | ||
1080 | } | ||
1081 | pp->state = PP_ProcessValueToBoundary; | ||
1082 | pp->value_offset = 0; | ||
1083 | state_changed = 1; | ||
1084 | break; | ||
1085 | case PP_ProcessValueToBoundary: | ||
1086 | if (MHD_NO == process_value_to_boundary (pp, | ||
1087 | &ioff, | ||
1088 | pp->boundary, | ||
1089 | pp->blen, | ||
1090 | PP_PerformCleanup, | ||
1091 | PP_Done)) | ||
1092 | { | ||
1093 | if (pp->state == PP_Error) | ||
1094 | return MHD_NO; | ||
1095 | break; | ||
1096 | } | ||
1097 | break; | ||
1098 | case PP_PerformCleanup: | ||
1099 | /* clean up state of one multipart form-data element! */ | ||
1100 | pp->have = NE_none; | ||
1101 | free_unmarked (pp); | ||
1102 | if (NULL != pp->nested_boundary) | ||
1103 | { | ||
1104 | free (pp->nested_boundary); | ||
1105 | pp->nested_boundary = NULL; | ||
1106 | } | ||
1107 | pp->state = PP_ProcessEntryHeaders; | ||
1108 | state_changed = 1; | ||
1109 | break; | ||
1110 | case PP_Nested_Init: | ||
1111 | if (NULL == pp->nested_boundary) | ||
1112 | { | ||
1113 | pp->state = PP_Error; | ||
1114 | return MHD_NO; | ||
1115 | } | ||
1116 | if (MHD_NO == find_boundary (pp, | ||
1117 | pp->nested_boundary, | ||
1118 | pp->nlen, | ||
1119 | &ioff, | ||
1120 | PP_Nested_PerformMarking, | ||
1121 | PP_NextBoundary /* or PP_Error? */)) | ||
1122 | { | ||
1123 | if (pp->state == PP_Error) | ||
1124 | return MHD_NO; | ||
1125 | goto END; | ||
1126 | } | ||
1127 | break; | ||
1128 | case PP_Nested_PerformMarking: | ||
1129 | /* remember what headers were given | ||
1130 | globally */ | ||
1131 | pp->have = NE_none; | ||
1132 | if (NULL != pp->content_name) | ||
1133 | pp->have |= NE_content_name; | ||
1134 | if (NULL != pp->content_type) | ||
1135 | pp->have |= NE_content_type; | ||
1136 | if (NULL != pp->content_filename) | ||
1137 | pp->have |= NE_content_filename; | ||
1138 | if (NULL != pp->content_transfer_encoding) | ||
1139 | pp->have |= NE_content_transfer_encoding; | ||
1140 | pp->state = PP_Nested_ProcessEntryHeaders; | ||
1141 | state_changed = 1; | ||
1142 | break; | ||
1143 | case PP_Nested_ProcessEntryHeaders: | ||
1144 | pp->value_offset = 0; | ||
1145 | if (MHD_NO == | ||
1146 | process_multipart_headers (pp, | ||
1147 | &ioff, | ||
1148 | PP_Nested_ProcessValueToBoundary)) | ||
1149 | { | ||
1150 | if (pp->state == PP_Error) | ||
1151 | return MHD_NO; | ||
1152 | else | ||
1153 | goto END; | ||
1154 | } | ||
1155 | state_changed = 1; | ||
1156 | break; | ||
1157 | case PP_Nested_ProcessValueToBoundary: | ||
1158 | if (MHD_NO == process_value_to_boundary (pp, | ||
1159 | &ioff, | ||
1160 | pp->nested_boundary, | ||
1161 | pp->nlen, | ||
1162 | PP_Nested_PerformCleanup, | ||
1163 | PP_NextBoundary)) | ||
1164 | { | ||
1165 | if (pp->state == PP_Error) | ||
1166 | return MHD_NO; | ||
1167 | break; | ||
1168 | } | ||
1169 | break; | ||
1170 | case PP_Nested_PerformCleanup: | ||
1171 | free_unmarked (pp); | ||
1172 | pp->state = PP_Nested_ProcessEntryHeaders; | ||
1173 | state_changed = 1; | ||
1174 | break; | ||
1175 | default: | ||
1176 | mhd_panic (mhd_panic_cls, | ||
1177 | __FILE__, | ||
1178 | __LINE__, | ||
1179 | NULL); /* should never happen! */ | ||
1188 | } | 1180 | } |
1189 | END: | 1181 | AGAIN: |
1190 | if (0 != ioff) | 1182 | if (ioff > 0) |
1191 | { | 1183 | { |
1192 | memmove (buf, | 1184 | memmove (buf, |
1193 | &buf[ioff], | 1185 | &buf[ioff], |
1194 | pp->buffer_pos - ioff); | 1186 | pp->buffer_pos - ioff); |
1195 | pp->buffer_pos -= ioff; | 1187 | pp->buffer_pos -= ioff; |
1188 | ioff = 0; | ||
1189 | state_changed = 1; | ||
1196 | } | 1190 | } |
1191 | } | ||
1192 | END: | ||
1193 | if (0 != ioff) | ||
1194 | { | ||
1195 | memmove (buf, | ||
1196 | &buf[ioff], | ||
1197 | pp->buffer_pos - ioff); | ||
1198 | pp->buffer_pos -= ioff; | ||
1199 | } | ||
1197 | if (poff < post_data_len) | 1200 | if (poff < post_data_len) |
1198 | { | 1201 | { |
1199 | pp->state = PP_Error; | 1202 | pp->state = PP_Error; |
1200 | return MHD_NO; /* serious error */ | 1203 | return MHD_NO; /* serious error */ |
1201 | } | 1204 | } |
1202 | return MHD_YES; | 1205 | return MHD_YES; |
1203 | } | 1206 | } |
1204 | 1207 | ||
@@ -1227,13 +1230,15 @@ MHD_post_process (struct MHD_PostProcessor *pp, | |||
1227 | return MHD_NO; | 1230 | return MHD_NO; |
1228 | if (MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, | 1231 | if (MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, |
1229 | pp->encoding, | 1232 | pp->encoding, |
1230 | MHD_STATICSTR_LEN_(MHD_HTTP_POST_ENCODING_FORM_URLENCODED))) | 1233 | MHD_STATICSTR_LEN_ ( |
1234 | MHD_HTTP_POST_ENCODING_FORM_URLENCODED))) | ||
1231 | return post_process_urlencoded (pp, | 1235 | return post_process_urlencoded (pp, |
1232 | post_data, | 1236 | post_data, |
1233 | post_data_len); | 1237 | post_data_len); |
1234 | if (MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, | 1238 | if (MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, |
1235 | pp->encoding, | 1239 | pp->encoding, |
1236 | MHD_STATICSTR_LEN_ (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA))) | 1240 | MHD_STATICSTR_LEN_ ( |
1241 | MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA))) | ||
1237 | return post_process_multipart (pp, | 1242 | return post_process_multipart (pp, |
1238 | post_data, | 1243 | post_data, |
1239 | post_data_len); | 1244 | post_data_len); |