aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/daemon/Makefile.am2
-rw-r--r--src/daemon/connection.c18
-rw-r--r--src/daemon/daemon.c77
-rw-r--r--src/daemon/minimal_example.c5
-rw-r--r--src/daemon/postprocessor.c745
-rw-r--r--src/daemon/postprocessor_test.c159
-rw-r--r--src/daemon/response.c8
7 files changed, 497 insertions, 517 deletions
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am
index 254dab8c..b2f58c94 100644
--- a/src/daemon/Makefile.am
+++ b/src/daemon/Makefile.am
@@ -12,7 +12,7 @@ lib_LTLIBRARIES = \
12 libmicrohttpd.la 12 libmicrohttpd.la
13 13
14libmicrohttpd_la_LDFLAGS = \ 14libmicrohttpd_la_LDFLAGS = \
15 -export-dynamic -version-info 3:1:0 $(retaincommand) 15 -export-dynamic -version-info 3:2:0 $(retaincommand)
16libmicrohttpd_la_SOURCES = \ 16libmicrohttpd_la_SOURCES = \
17 connection.c connection.h \ 17 connection.c connection.h \
18 reason_phrase.c reason_phrase.h \ 18 reason_phrase.c reason_phrase.h \
diff --git a/src/daemon/connection.c b/src/daemon/connection.c
index 08b503d7..60cbfe43 100644
--- a/src/daemon/connection.c
+++ b/src/daemon/connection.c
@@ -654,9 +654,9 @@ MHD_connection_get_fdset (struct MHD_Connection *connection,
654 case MHD_CONNECTION_CONTINUE_SENT: 654 case MHD_CONNECTION_CONTINUE_SENT:
655 if (connection->read_buffer_offset == connection->read_buffer_size) 655 if (connection->read_buffer_offset == connection->read_buffer_size)
656 try_grow_read_buffer (connection); 656 try_grow_read_buffer (connection);
657 if ( (connection->read_buffer_offset < connection->read_buffer_size) && 657 if ((connection->read_buffer_offset < connection->read_buffer_size)
658 (MHD_NO == connection->read_closed) ) 658 && (MHD_NO == connection->read_closed))
659 do_fd_set (fd, read_fd_set, max_fd); 659 do_fd_set (fd, read_fd_set, max_fd);
660 break; 660 break;
661 case MHD_CONNECTION_BODY_RECEIVED: 661 case MHD_CONNECTION_BODY_RECEIVED:
662 case MHD_CONNECTION_FOOTER_PART_RECEIVED: 662 case MHD_CONNECTION_FOOTER_PART_RECEIVED:
@@ -1797,13 +1797,9 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
1797 if (((MHD_YES == connection->read_closed) && 1797 if (((MHD_YES == connection->read_closed) &&
1798 (0 == connection->read_buffer_offset)) || 1798 (0 == connection->read_buffer_offset)) ||
1799 (connection->version == NULL) || 1799 (connection->version == NULL) ||
1800 (connection->method == NULL) || 1800 (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)))
1801 ( (0 != strcasecmp (MHD_HTTP_METHOD_HEAD, connection->method)) &&
1802 (0 != strcasecmp (MHD_HTTP_METHOD_GET, connection->method)) ) ||
1803 (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)))
1804 { 1801 {
1805 /* http 1.0, version-less or non-HEAD/GET requests cannot be 1802 /* http 1.0, version-less requests cannot be pipelined */
1806 pipelined */
1807 connection->state = MHD_CONNECTION_CLOSED; 1803 connection->state = MHD_CONNECTION_CLOSED;
1808 MHD_pool_destroy (connection->pool); 1804 MHD_pool_destroy (connection->pool);
1809 connection->pool = NULL; 1805 connection->pool = NULL;
@@ -1832,8 +1828,8 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
1832 break; 1828 break;
1833 } 1829 }
1834 timeout = connection->daemon->connection_timeout; 1830 timeout = connection->daemon->connection_timeout;
1835 if ( (connection->socket_fd != -1) && 1831 if ((connection->socket_fd != -1) &&
1836 (timeout != 0) && (time (NULL) - timeout > connection->last_activity)) 1832 (timeout != 0) && (time (NULL) - timeout > connection->last_activity))
1837 { 1833 {
1838 connection_close_error (connection); 1834 connection_close_error (connection);
1839 return MHD_NO; 1835 return MHD_NO;
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c
index e971c9b2..971196f8 100644
--- a/src/daemon/daemon.c
+++ b/src/daemon/daemon.c
@@ -172,7 +172,7 @@ MHD_handle_connection (void *data)
172static int 172static int
173MHD_accept_connection (struct MHD_Daemon *daemon) 173MHD_accept_connection (struct MHD_Daemon *daemon)
174{ 174{
175 struct MHD_Connection *pos; 175 struct MHD_Connection *pos;
176 struct MHD_Connection *connection; 176 struct MHD_Connection *connection;
177 struct sockaddr_in6 addr6; 177 struct sockaddr_in6 addr6;
178 struct sockaddr *addr = (struct sockaddr *) &addr6; 178 struct sockaddr *addr = (struct sockaddr *) &addr6;
@@ -204,42 +204,44 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
204#if DEBUG_CONNECT 204#if DEBUG_CONNECT
205 MHD_DLOG (daemon, "Accepted connection on socket %d\n", s); 205 MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
206#endif 206#endif
207 have = 0; 207 have = 0;
208 if ( (daemon->per_ip_connection_limit != 0) && 208 if ((daemon->per_ip_connection_limit != 0) && (daemon->max_connections > 0))
209 (daemon->max_connections > 0) )
210 { 209 {
211 pos = daemon->connections; 210 pos = daemon->connections;
212 while (pos != NULL) 211 while (pos != NULL)
213 { 212 {
214 if ( (pos->addr != NULL) && 213 if ((pos->addr != NULL) && (pos->addr_len == addrlen))
215 (pos->addr_len == addrlen) ) 214 {
216 { 215 if (addrlen == sizeof (struct sockaddr_in))
217 if (addrlen == sizeof(struct sockaddr_in)) 216 {
218 { 217 const struct sockaddr_in *a1 =
219 const struct sockaddr_in * a1 = (const struct sockaddr_in *) &addr; 218 (const struct sockaddr_in *) &addr;
220 const struct sockaddr_in * a2 = (const struct sockaddr_in *) pos->addr; 219 const struct sockaddr_in *a2 =
221 if (0 == memcmp(&a1->sin_addr, 220 (const struct sockaddr_in *) pos->addr;
222 &a2->sin_addr, 221 if (0 ==
223 sizeof(struct in_addr))) 222 memcmp (&a1->sin_addr, &a2->sin_addr,
224 have++; 223 sizeof (struct in_addr)))
225 } 224 have++;
226 if (addrlen == sizeof(struct sockaddr_in6)) 225 }
227 { 226 if (addrlen == sizeof (struct sockaddr_in6))
228 const struct sockaddr_in6 * a1 = (const struct sockaddr_in6 *) &addr; 227 {
229 const struct sockaddr_in6 * a2 = (const struct sockaddr_in6 *) pos->addr; 228 const struct sockaddr_in6 *a1 =
230 if (0 == memcmp(&a1->sin6_addr, 229 (const struct sockaddr_in6 *) &addr;
231 &a2->sin6_addr, 230 const struct sockaddr_in6 *a2 =
232 sizeof(struct in6_addr))) 231 (const struct sockaddr_in6 *) pos->addr;
233 have++; 232 if (0 ==
234 } 233 memcmp (&a1->sin6_addr, &a2->sin6_addr,
235 } 234 sizeof (struct in6_addr)))
236 pos = pos->next; 235 have++;
237 } 236 }
237 }
238 pos = pos->next;
239 }
238 } 240 }
239 241
240 if ( (daemon->max_connections == 0) || 242 if ((daemon->max_connections == 0) ||
241 ( (daemon->per_ip_connection_limit != 0) && 243 ((daemon->per_ip_connection_limit != 0) &&
242 (daemon->per_ip_connection_limit <= have) ) ) 244 (daemon->per_ip_connection_limit <= have)))
243 { 245 {
244 /* above connection limit - reject */ 246 /* above connection limit - reject */
245#if HAVE_MESSAGES 247#if HAVE_MESSAGES
@@ -635,7 +637,7 @@ MHD_start_daemon (unsigned int options,
635 retVal = malloc (sizeof (struct MHD_Daemon)); 637 retVal = malloc (sizeof (struct MHD_Daemon));
636 if (retVal == NULL) 638 if (retVal == NULL)
637 { 639 {
638 CLOSE(socket_fd); 640 CLOSE (socket_fd);
639 return NULL; 641 return NULL;
640 } 642 }
641 memset (retVal, 0, sizeof (struct MHD_Daemon)); 643 memset (retVal, 0, sizeof (struct MHD_Daemon));
@@ -668,10 +670,9 @@ MHD_start_daemon (unsigned int options,
668 va_arg (ap, MHD_RequestCompletedCallback); 670 va_arg (ap, MHD_RequestCompletedCallback);
669 retVal->notify_completed_cls = va_arg (ap, void *); 671 retVal->notify_completed_cls = va_arg (ap, void *);
670 break; 672 break;
671 case MHD_OPTION_PER_IP_CONNECTION_LIMIT: 673 case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
672 retVal->per_ip_connection_limit 674 retVal->per_ip_connection_limit = va_arg (ap, unsigned int);
673 = va_arg (ap, unsigned int); 675 break;
674 break;
675 default: 676 default:
676#if HAVE_MESSAGES 677#if HAVE_MESSAGES
677 fprintf (stderr, 678 fprintf (stderr,
diff --git a/src/daemon/minimal_example.c b/src/daemon/minimal_example.c
index 0cbf3a14..647a4776 100644
--- a/src/daemon/minimal_example.c
+++ b/src/daemon/minimal_example.c
@@ -40,9 +40,8 @@ ahc_echo (void *cls,
40 struct MHD_Connection *connection, 40 struct MHD_Connection *connection,
41 const char *url, 41 const char *url,
42 const char *method, 42 const char *method,
43 const char *version, 43 const char *version,
44 const char *upload_data, 44 const char *upload_data, unsigned int *upload_data_size, void **ptr)
45 unsigned int *upload_data_size, void **ptr)
46{ 45{
47 static int aptr; 46 static int aptr;
48 const char *me = cls; 47 const char *me = cls;
diff --git a/src/daemon/postprocessor.c b/src/daemon/postprocessor.c
index 5b8f01a2..8be3ee89 100644
--- a/src/daemon/postprocessor.c
+++ b/src/daemon/postprocessor.c
@@ -40,13 +40,13 @@ enum PP_State
40 PP_Done, 40 PP_Done,
41 PP_Init, 41 PP_Init,
42 42
43 /* url encoding-states*/ 43 /* url encoding-states */
44 PP_ProcessValue, 44 PP_ProcessValue,
45 PP_ExpectNewLine, 45 PP_ExpectNewLine,
46 46
47 /* post encoding-states */ 47 /* post encoding-states */
48 PP_ProcessEntryHeaders, 48 PP_ProcessEntryHeaders,
49 PP_PerformCheckMultipart, 49 PP_PerformCheckMultipart,
50 PP_ProcessValueToBoundary, 50 PP_ProcessValueToBoundary,
51 PP_PerformCleanup, 51 PP_PerformCleanup,
52 52
@@ -56,7 +56,7 @@ enum PP_State
56 PP_Nested_ProcessEntryHeaders, 56 PP_Nested_ProcessEntryHeaders,
57 PP_Nested_ProcessValueToBoundary, 57 PP_Nested_ProcessValueToBoundary,
58 PP_Nested_PerformCleanup, 58 PP_Nested_PerformCleanup,
59 59
60}; 60};
61 61
62enum RN_State 62enum RN_State
@@ -76,11 +76,11 @@ enum RN_State
76 * Expect '\r\n' (and only '\r\n'). As always, we also 76 * Expect '\r\n' (and only '\r\n'). As always, we also
77 * expect only '\r' or only '\n'. 77 * expect only '\r' or only '\n'.
78 */ 78 */
79 RN_Full = 2, 79 RN_Full = 2,
80 80
81 /** 81 /**
82 * Expect either '\r\n' or '--\r\n'. If '--\r\n', transition into dash-state 82 * Expect either '\r\n' or '--\r\n'. If '--\r\n', transition into dash-state
83 * for the main state machine 83 * for the main state machine
84 */ 84 */
85 RN_Dash = 3, 85 RN_Dash = 3,
86 86
@@ -94,8 +94,8 @@ enum RN_State
94 * Bits for the globally known fields that 94 * Bits for the globally known fields that
95 * should not be deleted when we exit the 95 * should not be deleted when we exit the
96 * nested state. 96 * nested state.
97 */ 97 */
98enum NE_State 98enum NE_State
99{ 99{
100 NE_none = 0, 100 NE_none = 0,
101 NE_content_name = 1, 101 NE_content_name = 1,
@@ -136,12 +136,12 @@ struct MHD_PostProcessor
136 /** 136 /**
137 * Primary boundary (points into encoding string) 137 * Primary boundary (points into encoding string)
138 */ 138 */
139 const char * boundary; 139 const char *boundary;
140 140
141 /** 141 /**
142 * Nested boundary (if we have multipart/mixed encoding). 142 * Nested boundary (if we have multipart/mixed encoding).
143 */ 143 */
144 char * nested_boundary; 144 char *nested_boundary;
145 145
146 /** 146 /**
147 * Pointer to the name given in disposition. 147 * Pointer to the name given in disposition.
@@ -263,23 +263,22 @@ MHD_create_post_processor (struct MHD_Connection *connection,
263 if (encoding == NULL) 263 if (encoding == NULL)
264 return NULL; 264 return NULL;
265 boundary = NULL; 265 boundary = NULL;
266 if (0 != strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, 266 if (0 != strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, encoding))
267 encoding))
268 { 267 {
269 if (0 != strncasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, encoding, 268 if (0 !=
270 strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA))) 269 strncasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, encoding,
271 return NULL; 270 strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)))
271 return NULL;
272 boundary = 272 boundary =
273 &encoding[strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)]; 273 &encoding[strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)];
274 /* Q: should this be "strcasestr"? */ 274 /* Q: should this be "strcasestr"? */
275 if (NULL != strstr (boundary, "boundary=")) 275 if (NULL != strstr (boundary, "boundary="))
276 boundary = strstr (boundary, "boundary=") + strlen ("boundary="); 276 boundary = strstr (boundary, "boundary=") + strlen ("boundary=");
277 else 277 else
278 return NULL; /* failed to determine boundary */ 278 return NULL; /* failed to determine boundary */
279 blen = strlen (boundary); 279 blen = strlen (boundary);
280 if ( (blen == 0) || 280 if ((blen == 0) || (blen * 2 + 2 > buffer_size))
281 (blen * 2 + 2 > buffer_size) ) 281 return NULL; /* (will be) out of memory or invalid boundary */
282 return NULL; /* (will be) out of memory or invalid boundary */
283 } 282 }
284 else 283 else
285 blen = 0; 284 blen = 0;
@@ -322,10 +321,10 @@ post_process_urlencoded (struct MHD_PostProcessor *pp,
322 { 321 {
323 case PP_Error: 322 case PP_Error:
324 return MHD_NO; 323 return MHD_NO;
325 case PP_Done: 324 case PP_Done:
326 /* did not expect to receive more data */ 325 /* did not expect to receive more data */
327 pp->state = PP_Error; 326 pp->state = PP_Error;
328 return MHD_NO; 327 return MHD_NO;
329 case PP_Init: 328 case PP_Init:
330 equals = 0; 329 equals = 0;
331 while ((equals + poff < post_data_len) && 330 while ((equals + poff < post_data_len) &&
@@ -444,39 +443,37 @@ try_match_header (const char *prefix, char *line, char **suffix)
444{ 443{
445 if (NULL != *suffix) 444 if (NULL != *suffix)
446 return MHD_NO; 445 return MHD_NO;
447 while(*line != 0) 446 while (*line != 0)
448 { 447 {
449 if (0 == strncasecmp (prefix, line, strlen (prefix))) 448 if (0 == strncasecmp (prefix, line, strlen (prefix)))
450 { 449 {
451 *suffix = strdup (&line[strlen (prefix)]); 450 *suffix = strdup (&line[strlen (prefix)]);
452 return MHD_YES; 451 return MHD_YES;
453 } 452 }
454 ++line; 453 ++line;
455 } 454 }
456 return MHD_NO; 455 return MHD_NO;
457} 456}
458 457
459static int 458static int
460find_boundary(struct MHD_PostProcessor * pp, 459find_boundary (struct MHD_PostProcessor *pp,
461 const char * boundary, 460 const char *boundary,
462 size_t blen, 461 size_t blen,
463 unsigned int * ioffptr, 462 unsigned int *ioffptr,
464 enum PP_State next_state, 463 enum PP_State next_state, enum PP_State next_dash_state)
465 enum PP_State next_dash_state)
466{ 464{
467 char * buf = (char*) &pp[1]; 465 char *buf = (char *) &pp[1];
468 466
469 if (pp->buffer_pos < 2 + blen) 467 if (pp->buffer_pos < 2 + blen)
470 { 468 {
471 if (pp->buffer_pos == pp->buffer_size) 469 if (pp->buffer_pos == pp->buffer_size)
472 pp->state = PP_Error; /* out of memory */ 470 pp->state = PP_Error; /* out of memory */
473 return MHD_NO; /* not enough data */ 471 return MHD_NO; /* not enough data */
474 } 472 }
475 if ( (0 != memcmp ("--", buf, 2)) || 473 if ((0 != memcmp ("--", buf, 2)) || (0 != memcmp (&buf[2], boundary, blen)))
476 (0 != memcmp (&buf[2], boundary, blen)))
477 { 474 {
478 pp->state = PP_Error; 475 pp->state = PP_Error;
479 return MHD_NO; /* expected boundary */ 476 return MHD_NO; /* expected boundary */
480 } 477 }
481 /* remove boundary from buffer */ 478 /* remove boundary from buffer */
482 (*ioffptr) += 2 + blen; 479 (*ioffptr) += 2 + blen;
@@ -491,49 +488,43 @@ find_boundary(struct MHD_PostProcessor * pp,
491 * In buf, there maybe an expression 488 * In buf, there maybe an expression
492 * '$key="$value"'. If that is the case, 489 * '$key="$value"'. If that is the case,
493 * copy a copy of $value to destination. 490 * copy a copy of $value to destination.
494 * 491 *
495 * If destination is already non-NULL, 492 * If destination is already non-NULL,
496 * do nothing. 493 * do nothing.
497 */ 494 */
498static void 495static void
499try_get_value(const char * buf, 496try_get_value (const char *buf, const char *key, char **destination)
500 const char * key,
501 char ** destination)
502{ 497{
503 const char * spos; 498 const char *spos;
504 const char * bpos; 499 const char *bpos;
505 const char * endv; 500 const char *endv;
506 size_t klen; 501 size_t klen;
507 size_t vlen; 502 size_t vlen;
508 503
509 if (NULL != *destination) 504 if (NULL != *destination)
510 return; 505 return;
511 bpos = buf; 506 bpos = buf;
512 klen = strlen(key); 507 klen = strlen (key);
513 while (NULL != (spos = strstr(bpos, key))) 508 while (NULL != (spos = strstr (bpos, key)))
514 { 509 {
515 if ( (spos[klen] != '=') || 510 if ((spos[klen] != '=') || ((spos != buf) && (spos[-1] != ' ')))
516 ( (spos != buf) && 511 {
517 (spos[-1] != ' ') ) ) 512 /* no match */
518 { 513 bpos = spos + 1;
519 /* no match */ 514 continue;
520 bpos = spos + 1; 515 }
521 continue;
522 }
523 if (spos[klen + 1] != '"') 516 if (spos[klen + 1] != '"')
524 return; /* not quoted */ 517 return; /* not quoted */
525 if (NULL == (endv = strstr(&spos[klen+2], "\""))) 518 if (NULL == (endv = strstr (&spos[klen + 2], "\"")))
526 return; /* no end-quote */ 519 return; /* no end-quote */
527 vlen = endv - spos - klen - 1; 520 vlen = endv - spos - klen - 1;
528 *destination = malloc(vlen); 521 *destination = malloc (vlen);
529 if (NULL == *destination) 522 if (NULL == *destination)
530 return; /* out of memory */ 523 return; /* out of memory */
531 (*destination)[vlen - 1] = '\0'; 524 (*destination)[vlen - 1] = '\0';
532 memcpy(*destination, 525 memcpy (*destination, &spos[klen + 2], vlen - 1);
533 &spos[klen + 2], 526 return; /* success */
534 vlen - 1); 527 }
535 return; /* success */
536 }
537} 528}
538 529
539/** 530/**
@@ -541,37 +532,35 @@ try_get_value(const char * buf,
541 * the fields in "pp" according to what we find. 532 * the fields in "pp" according to what we find.
542 * If we are at the end of the headers (as indicated 533 * If we are at the end of the headers (as indicated
543 * by an empty line), transition into next_state. 534 * by an empty line), transition into next_state.
544 * 535 *
545 * @param ioffptr set to how many bytes have been 536 * @param ioffptr set to how many bytes have been
546 * processed 537 * processed
547 * @return MHD_YES if we can continue processing, 538 * @return MHD_YES if we can continue processing,
548 * MHD_NO on error or if we do not have 539 * MHD_NO on error or if we do not have
549 * enough data yet 540 * enough data yet
550 */ 541 */
551static int 542static int
552process_multipart_headers(struct MHD_PostProcessor * pp, 543process_multipart_headers (struct MHD_PostProcessor *pp,
553 unsigned int * ioffptr, 544 unsigned int *ioffptr, enum PP_State next_state)
554 enum PP_State next_state)
555{ 545{
556 char * buf = (char*) &pp[1]; 546 char *buf = (char *) &pp[1];
557 unsigned int newline; 547 unsigned int newline;
558 548
559 newline = 0; 549 newline = 0;
560 while ((newline < pp->buffer_pos) && 550 while ((newline < pp->buffer_pos) &&
561 (buf[newline] != '\r') && 551 (buf[newline] != '\r') && (buf[newline] != '\n'))
562 (buf[newline] != '\n'))
563 newline++; 552 newline++;
564 if (newline == pp->buffer_size) 553 if (newline == pp->buffer_size)
565 { 554 {
566 pp->state = PP_Error; 555 pp->state = PP_Error;
567 return MHD_NO; /* out of memory */ 556 return MHD_NO; /* out of memory */
568 } 557 }
569 if (newline == pp->buffer_pos) 558 if (newline == pp->buffer_pos)
570 return MHD_NO; /* will need more data */ 559 return MHD_NO; /* will need more data */
571 if (newline == 0) 560 if (newline == 0)
572 { 561 {
573 /* empty line - end of headers */ 562 /* empty line - end of headers */
574 pp->skip_rn = RN_Full; 563 pp->skip_rn = RN_Full;
575 pp->state = next_state; 564 pp->state = next_state;
576 return MHD_YES; 565 return MHD_YES;
577 } 566 }
@@ -579,24 +568,21 @@ process_multipart_headers(struct MHD_PostProcessor * pp,
579 if (buf[newline] == '\r') 568 if (buf[newline] == '\r')
580 pp->skip_rn = RN_OptN; 569 pp->skip_rn = RN_OptN;
581 buf[newline] = '\0'; 570 buf[newline] = '\0';
582 if (0 == strncasecmp("Content-disposition: ", 571 if (0 == strncasecmp ("Content-disposition: ",
583 buf, 572 buf, strlen ("Content-disposition: ")))
584 strlen("Content-disposition: "))) 573 {
585 { 574 try_get_value (&buf[strlen ("Content-disposition: ")],
586 try_get_value(&buf[strlen("Content-disposition: ")], 575 "name", &pp->content_name);
587 "name", 576 try_get_value (&buf[strlen ("Content-disposition: ")],
588 &pp->content_name); 577 "filename", &pp->content_filename);
589 try_get_value(&buf[strlen("Content-disposition: ")],
590 "filename",
591 &pp->content_filename);
592 } 578 }
593 else 579 else
594 { 580 {
595 try_match_header ("Content-type: ", buf, &pp->content_type); 581 try_match_header ("Content-type: ", buf, &pp->content_type);
596 try_match_header ("Content-Transfer-Encoding: ", 582 try_match_header ("Content-Transfer-Encoding: ",
597 buf, &pp->content_transfer_encoding); 583 buf, &pp->content_transfer_encoding);
598} 584 }
599 (*ioffptr) += newline + 1; 585 (*ioffptr) += newline + 1;
600 return MHD_YES; 586 return MHD_YES;
601} 587}
602 588
@@ -615,14 +601,14 @@ process_multipart_headers(struct MHD_PostProcessor * pp,
615 * enough data yet 601 * enough data yet
616 */ 602 */
617static int 603static int
618process_value_to_boundary(struct MHD_PostProcessor * pp, 604process_value_to_boundary (struct MHD_PostProcessor *pp,
619 unsigned int * ioffptr, 605 unsigned int *ioffptr,
620 const char * boundary, 606 const char *boundary,
621 size_t blen, 607 size_t blen,
622 enum PP_State next_state, 608 enum PP_State next_state,
623 enum PP_State next_dash_state) 609 enum PP_State next_dash_state)
624{ 610{
625 char * buf = (char*) &pp[1]; 611 char *buf = (char *) &pp[1];
626 unsigned int newline; 612 unsigned int newline;
627 613
628 /* all data in buf until the boundary 614 /* all data in buf until the boundary
@@ -631,53 +617,51 @@ process_value_to_boundary(struct MHD_PostProcessor * pp,
631 while (1) 617 while (1)
632 { 618 {
633 while ((newline + 4 < pp->buffer_pos) && 619 while ((newline + 4 < pp->buffer_pos) &&
634 (0 != memcmp ("\r\n--", &buf[newline], 4))) 620 (0 != memcmp ("\r\n--", &buf[newline], 4)))
635 newline++; 621 newline++;
636 if (newline + pp->blen + 4 <= pp->buffer_pos) 622 if (newline + pp->blen + 4 <= pp->buffer_pos)
637 { 623 {
638 /* can check boundary */ 624 /* can check boundary */
639 if (0 != memcmp (&buf[newline + 4], boundary, pp->blen)) 625 if (0 != memcmp (&buf[newline + 4], boundary, pp->blen))
640 { 626 {
641 /* no boundary, "\r\n--" is part of content, skip */ 627 /* no boundary, "\r\n--" is part of content, skip */
642 newline += 4; 628 newline += 4;
643 continue; 629 continue;
644 } 630 }
645 else 631 else
646 { 632 {
647 /* boundary found, process until newline then 633 /* boundary found, process until newline then
648 skip boundary and go back to init */ 634 skip boundary and go back to init */
649 pp->skip_rn = RN_Dash; 635 pp->skip_rn = RN_Dash;
650 pp->state = next_state; 636 pp->state = next_state;
651 pp->dash_state = next_dash_state; 637 pp->dash_state = next_dash_state;
652 (*ioffptr) += pp->blen + 4; /* skip boundary as well */ 638 (*ioffptr) += pp->blen + 4; /* skip boundary as well */
653 break; 639 break;
654 } 640 }
655 } 641 }
656 else 642 else
657 { 643 {
658 /* cannot check for boundary, process content that 644 /* cannot check for boundary, process content that
659 we have and check again later; except, if we have 645 we have and check again later; except, if we have
660 no content, abort (out of memory) */ 646 no content, abort (out of memory) */
661 if ( (newline == 0) && 647 if ((newline == 0) && (pp->buffer_pos == pp->buffer_size))
662 (pp->buffer_pos == pp->buffer_size) ) 648 {
663 { 649 pp->state = PP_Error;
664 pp->state = PP_Error; 650 return MHD_NO;
665 return MHD_NO; 651 }
666 } 652 break;
667 return MHD_NO; 653 }
668 }
669 } 654 }
670 /* newline is either at beginning of boundary or 655 /* newline is either at beginning of boundary or
671 at least at the last character that we are sure 656 at least at the last character that we are sure
672 is not part of the boundary */ 657 is not part of the boundary */
673 if (MHD_NO == pp->ikvi (pp->cls, 658 if (MHD_NO == pp->ikvi (pp->cls,
674 MHD_POSTDATA_KIND, 659 MHD_POSTDATA_KIND,
675 pp->content_name, 660 pp->content_name,
676 pp->content_filename, 661 pp->content_filename,
677 pp->content_type, 662 pp->content_type,
678 pp->content_transfer_encoding, 663 pp->content_transfer_encoding,
679 buf, 664 buf, pp->value_offset, newline))
680 pp->value_offset, newline))
681 { 665 {
682 pp->state = PP_Error; 666 pp->state = PP_Error;
683 return MHD_NO; 667 return MHD_NO;
@@ -688,30 +672,28 @@ process_value_to_boundary(struct MHD_PostProcessor * pp,
688} 672}
689 673
690static void 674static void
691free_unmarked(struct MHD_PostProcessor * pp) 675free_unmarked (struct MHD_PostProcessor *pp)
692{ 676{
693 if ( (pp->content_name != NULL) && 677 if ((pp->content_name != NULL) && (0 == (pp->have & NE_content_name)))
694 (0 == (pp->have & NE_content_name)) )
695 { 678 {
696 free(pp->content_name); 679 free (pp->content_name);
697 pp->content_name = NULL; 680 pp->content_name = NULL;
698 } 681 }
699 if ( (pp->content_type != NULL) && 682 if ((pp->content_type != NULL) && (0 == (pp->have & NE_content_type)))
700 (0 == (pp->have & NE_content_type)) )
701 { 683 {
702 free(pp->content_type); 684 free (pp->content_type);
703 pp->content_type = NULL; 685 pp->content_type = NULL;
704 } 686 }
705 if ( (pp->content_filename != NULL) && 687 if ((pp->content_filename != NULL) &&
706 (0 == (pp->have & NE_content_filename)) ) 688 (0 == (pp->have & NE_content_filename)))
707 { 689 {
708 free(pp->content_filename); 690 free (pp->content_filename);
709 pp->content_filename = NULL; 691 pp->content_filename = NULL;
710 } 692 }
711 if ( (pp->content_transfer_encoding != NULL) && 693 if ((pp->content_transfer_encoding != NULL) &&
712 (0 == (pp->have & NE_content_transfer_encoding)) ) 694 (0 == (pp->have & NE_content_transfer_encoding)))
713 { 695 {
714 free(pp->content_transfer_encoding); 696 free (pp->content_transfer_encoding);
715 pp->content_transfer_encoding = NULL; 697 pp->content_transfer_encoding = NULL;
716 } 698 }
717} 699}
@@ -727,251 +709,252 @@ post_process_multipart (struct MHD_PostProcessor *pp,
727 unsigned int max; 709 unsigned int max;
728 unsigned int ioff; 710 unsigned int ioff;
729 unsigned int poff; 711 unsigned int poff;
712 int state_changed;
730 713
731 buf = (char *) &pp[1]; 714 buf = (char *) &pp[1];
732 ioff = 0; 715 ioff = 0;
733 poff = 0; 716 poff = 0;
734 max = 1; 717 state_changed = 1;
735 while ( (poff < post_data_len) || 718 while ((poff < post_data_len) ||
736 ( (pp->buffer_pos > 0) && 719 ((pp->buffer_pos > 0) && (state_changed != 0)))
737 (max != 0) ) )
738 { 720 {
739 /* first, move as much input data 721 /* first, move as much input data
740 as possible to our internal buffer */ 722 as possible to our internal buffer */
741 max = pp->buffer_size - pp->buffer_pos; 723 max = pp->buffer_size - pp->buffer_pos;
742 if (max > post_data_len - poff) 724 if (max > post_data_len - poff)
743 max = post_data_len - poff; 725 max = post_data_len - poff;
744 memcpy (&buf[pp->buffer_pos], &post_data[poff], max); 726 memcpy (&buf[pp->buffer_pos], &post_data[poff], max);
745 poff += max; 727 poff += max;
746 pp->buffer_pos += max; 728 pp->buffer_pos += max;
747 if ( (max == 0) && 729 if ((max == 0) && (state_changed == 0) && (poff < post_data_len))
748 (poff < post_data_len) ) 730 {
749 { 731 pp->state = PP_Error;
750 pp->state = PP_Error; 732 return MHD_NO; /* out of memory */
751 return MHD_NO; /* out of memory */ 733 }
752 } 734 state_changed = 0;
753 735
754 /* first state machine for '\r'-'\n' and '--' handling */ 736 /* first state machine for '\r'-'\n' and '--' handling */
755 switch (pp->skip_rn) 737 switch (pp->skip_rn)
756 { 738 {
757 case RN_Inactive: 739 case RN_Inactive:
758 break; 740 break;
759 case RN_OptN: 741 case RN_OptN:
760 if (buf[0] == '\n') 742 if (buf[0] == '\n')
761 { 743 {
762 ioff++; 744 ioff++;
763 pp->skip_rn = RN_Inactive; 745 pp->skip_rn = RN_Inactive;
764 goto AGAIN; 746 goto AGAIN;
765 } 747 }
766 case RN_Dash: 748 case RN_Dash:
767 if (buf[0] == '-') 749 if (buf[0] == '-')
768 { 750 {
769 ioff++; 751 ioff++;
770 pp->skip_rn = RN_Dash2; 752 pp->skip_rn = RN_Dash2;
771 goto AGAIN; 753 goto AGAIN;
772 } 754 }
773 pp->skip_rn = RN_Full; 755 pp->skip_rn = RN_Full;
774 /* fall-through! */ 756 /* fall-through! */
775 case RN_Full: 757 case RN_Full:
776 if (buf[0] == '\r') 758 if (buf[0] == '\r')
777 { 759 {
778 if ( (pp->buffer_pos > 1) && 760 if ((pp->buffer_pos > 1) && (buf[1] == '\n'))
779 (buf[1] == '\n') ) 761 {
780 { 762 pp->skip_rn = RN_Inactive;
781 pp->skip_rn = RN_Inactive; 763 ioff += 2;
782 ioff += 2; 764 }
783 } 765 else
784 else 766 {
785 { 767 pp->skip_rn = RN_OptN;
786 pp->skip_rn = RN_OptN; 768 ioff++;
787 ioff++; 769 }
788 } 770 goto AGAIN;
789 goto AGAIN; 771 }
790 } 772 if (buf[0] == '\n')
791 if (buf[0] == '\n') 773 {
792 { 774 ioff++;
793 ioff++; 775 pp->skip_rn = RN_Inactive;
794 pp->skip_rn = RN_Inactive; 776 goto AGAIN;
795 goto AGAIN; 777 }
796 } 778 pp->skip_rn = RN_Inactive;
797 pp->skip_rn = RN_Inactive; 779 pp->state = PP_Error;
798 pp->state = PP_Error; 780 return MHD_NO; /* no '\r\n' */
799 return MHD_NO; /* no '\r\n' */ 781 case RN_Dash2:
800 case RN_Dash2: 782 if (buf[0] == '-')
801 if (buf[0] == '-') 783 {
802 { 784 ioff++;
803 ioff++; 785 pp->skip_rn = RN_Full;
804 pp->skip_rn = RN_Full; 786 pp->state = pp->dash_state;
805 pp->state = pp->dash_state; 787 goto AGAIN;
806 goto AGAIN; 788 }
807 } 789 pp->state = PP_Error;
808 pp->state = PP_Error; 790 break;
809 break; 791 }
810 }
811 792
812 /* main state engine */ 793 /* main state engine */
813 switch (pp->state) 794 switch (pp->state)
814 { 795 {
815 case PP_Error: 796 case PP_Error:
816 return MHD_NO; 797 return MHD_NO;
817 case PP_Done: 798 case PP_Done:
818 /* did not expect to receive more data */ 799 /* did not expect to receive more data */
819 pp->state = PP_Error; 800 pp->state = PP_Error;
820 return MHD_NO; 801 return MHD_NO;
821 case PP_Init: 802 case PP_Init:
822 if (MHD_NO == find_boundary(pp, 803 if (MHD_NO == find_boundary (pp,
823 pp->boundary, 804 pp->boundary,
824 pp->blen, 805 pp->blen,
825 &ioff, 806 &ioff,
826 PP_ProcessEntryHeaders, 807 PP_ProcessEntryHeaders, PP_Done))
827 PP_Done)) 808 {
828 { 809 if (pp->state == PP_Error)
829 if (pp->state == PP_Error) 810 return MHD_NO;
830 return MHD_NO; 811 goto END;
831 goto END; 812 }
832 } 813 break;
833 break; 814 case PP_ProcessEntryHeaders:
834 case PP_ProcessEntryHeaders: 815 if (MHD_NO ==
835 if (MHD_NO == process_multipart_headers(pp, &ioff, PP_PerformCheckMultipart)) 816 process_multipart_headers (pp, &ioff, PP_PerformCheckMultipart))
836 { 817 {
837 if (pp->state == PP_Error) 818 if (pp->state == PP_Error)
838 return MHD_NO; 819 return MHD_NO;
839 else 820 else
840 goto END; 821 goto END;
841 } 822 }
842 max = 1; 823 state_changed = 1;
843 break; 824 break;
844 case PP_PerformCheckMultipart: 825 case PP_PerformCheckMultipart:
845 if ( (pp->content_type != NULL) && 826 if ((pp->content_type != NULL) &&
846 (0 == strncasecmp(pp->content_type, 827 (0 == strncasecmp (pp->content_type,
847 "multipart/mixed", 828 "multipart/mixed",
848 strlen("multipart/mixed")) ) ) 829 strlen ("multipart/mixed"))))
849 { 830 {
850 pp->nested_boundary = strstr(pp->content_type, 831 pp->nested_boundary = strstr (pp->content_type, "boundary=");
851 "boundary="); 832 if (pp->nested_boundary == NULL)
852 if (pp->nested_boundary == NULL) 833 {
853 { 834 pp->state = PP_Error;
854 pp->state = PP_Error; 835 return MHD_NO;
855 return MHD_NO; 836 }
856 } 837 pp->nested_boundary =
857 pp->nested_boundary = strdup(&pp->nested_boundary[strlen("boundary=")]); 838 strdup (&pp->nested_boundary[strlen ("boundary=")]);
858 if (pp->nested_boundary == NULL) 839 if (pp->nested_boundary == NULL)
859 { 840 {
860 /* out of memory */ 841 /* out of memory */
861 pp->state = PP_Error; 842 pp->state = PP_Error;
862 return MHD_NO; 843 return MHD_NO;
863 } 844 }
864 /* free old content type, we will need that field 845 /* free old content type, we will need that field
865 for the content type of the nested elements */ 846 for the content type of the nested elements */
866 free(pp->content_type); 847 free (pp->content_type);
867 pp->content_type = NULL; 848 pp->content_type = NULL;
868 pp->nlen = strlen(pp->nested_boundary); 849 pp->nlen = strlen (pp->nested_boundary);
869 pp->state = PP_Nested_Init; 850 pp->state = PP_Nested_Init;
870 max = 1; 851 state_changed = 1;
871 break; 852 break;
872 } 853 }
873 pp->state = PP_ProcessValueToBoundary; 854 pp->state = PP_ProcessValueToBoundary;
874 pp->value_offset = 0; 855 pp->value_offset = 0;
875 max = 1; 856 state_changed = 1;
876 break; 857 break;
877 case PP_ProcessValueToBoundary: 858 case PP_ProcessValueToBoundary:
878 if (MHD_NO == process_value_to_boundary(pp, 859 if (MHD_NO == process_value_to_boundary (pp,
879 &ioff, 860 &ioff,
880 pp->boundary, 861 pp->boundary,
881 pp->blen, 862 pp->blen,
882 PP_PerformCleanup, 863 PP_PerformCleanup,
883 PP_Done)) 864 PP_Done))
884 { 865 {
885 if (pp->state == PP_Error) 866 if (pp->state == PP_Error)
886 return MHD_NO; 867 return MHD_NO;
887 break; 868 break;
888 } 869 }
889 break; 870 break;
890 case PP_PerformCleanup: 871 case PP_PerformCleanup:
891 /* clean up state of one multipart form-data element! */ 872 /* clean up state of one multipart form-data element! */
892 pp->have = NE_none; 873 pp->have = NE_none;
893 free_unmarked(pp); 874 free_unmarked (pp);
894 if (pp->nested_boundary != NULL) 875 if (pp->nested_boundary != NULL)
895 { 876 {
896 free (pp->nested_boundary); 877 free (pp->nested_boundary);
897 pp->nested_boundary = NULL; 878 pp->nested_boundary = NULL;
898 } 879 }
899 pp->state = PP_ProcessEntryHeaders; 880 pp->state = PP_ProcessEntryHeaders;
900 max = 1; 881 state_changed = 1;
901 break; 882 break;
902 case PP_Nested_Init: 883 case PP_Nested_Init:
903 if (pp->nested_boundary == NULL) 884 if (pp->nested_boundary == NULL)
904 { 885 {
905 pp->state = PP_Error; 886 pp->state = PP_Error;
906 return MHD_NO; 887 return MHD_NO;
907 } 888 }
908 if (MHD_NO == find_boundary(pp, 889 if (MHD_NO == find_boundary (pp,
909 pp->nested_boundary, 890 pp->nested_boundary,
910 pp->nlen, 891 pp->nlen,
911 &ioff, 892 &ioff,
912 PP_Nested_PerformMarking, 893 PP_Nested_PerformMarking,
913 PP_Init /* or PP_Error? */)) 894 PP_Init /* or PP_Error? */ ))
914 { 895 {
915 if (pp->state == PP_Error) 896 if (pp->state == PP_Error)
916 return MHD_NO; 897 return MHD_NO;
917 goto END; 898 goto END;
918 } 899 }
919 break; 900 break;
920 case PP_Nested_PerformMarking: 901 case PP_Nested_PerformMarking:
921 /* remember what headers were given 902 /* remember what headers were given
922 globally */ 903 globally */
923 pp->have = NE_none; 904 pp->have = NE_none;
924 if (pp->content_name != NULL) 905 if (pp->content_name != NULL)
925 pp->have |= NE_content_name; 906 pp->have |= NE_content_name;
926 if (pp->content_type != NULL) 907 if (pp->content_type != NULL)
927 pp->have |= NE_content_type; 908 pp->have |= NE_content_type;
928 if (pp->content_filename != NULL) 909 if (pp->content_filename != NULL)
929 pp->have |= NE_content_filename; 910 pp->have |= NE_content_filename;
930 if (pp->content_transfer_encoding != NULL) 911 if (pp->content_transfer_encoding != NULL)
931 pp->have |= NE_content_transfer_encoding; 912 pp->have |= NE_content_transfer_encoding;
932 pp->state = PP_Nested_ProcessEntryHeaders; 913 pp->state = PP_Nested_ProcessEntryHeaders;
933 max = 1; 914 state_changed = 1;
934 break; 915 break;
935 case PP_Nested_ProcessEntryHeaders: 916 case PP_Nested_ProcessEntryHeaders:
936 pp->value_offset = 0; 917 pp->value_offset = 0;
937 if (MHD_NO == process_multipart_headers(pp, &ioff, PP_Nested_ProcessValueToBoundary)) 918 if (MHD_NO ==
938 { 919 process_multipart_headers (pp, &ioff,
939 if (pp->state == PP_Error) 920 PP_Nested_ProcessValueToBoundary))
940 return MHD_NO; 921 {
941 else 922 if (pp->state == PP_Error)
942 goto END; 923 return MHD_NO;
943 } 924 else
944 max = 1; 925 goto END;
926 }
927 state_changed = 1;
928 break;
929 case PP_Nested_ProcessValueToBoundary:
930 if (MHD_NO == process_value_to_boundary (pp,
931 &ioff,
932 pp->nested_boundary,
933 pp->nlen,
934 PP_Nested_PerformCleanup,
935 PP_Init))
936 {
937 if (pp->state == PP_Error)
938 return MHD_NO;
939 break;
940 }
941 break;
942 case PP_Nested_PerformCleanup:
943 free_unmarked (pp);
944 pp->state = PP_Nested_ProcessEntryHeaders;
945 state_changed = 1;
945 break; 946 break;
946 case PP_Nested_ProcessValueToBoundary:
947 if (MHD_NO == process_value_to_boundary(pp,
948 &ioff,
949 pp->nested_boundary,
950 pp->nlen,
951 PP_Nested_PerformCleanup,
952 PP_Init))
953 {
954 if (pp->state == PP_Error)
955 return MHD_NO;
956 break;
957 }
958 break;
959 case PP_Nested_PerformCleanup:
960 free_unmarked(pp);
961 pp->state = PP_Nested_ProcessEntryHeaders;
962 max = 1;
963 break;
964 default: 947 default:
965 abort (); /* should never happen! */ 948 abort (); /* should never happen! */
966 } 949 }
967AGAIN: 950 AGAIN:
968 if (ioff > 0) 951 if (ioff > 0)
969 { 952 {
970 memmove (buf, &buf[ioff], pp->buffer_pos - ioff); 953 memmove (buf, &buf[ioff], pp->buffer_pos - ioff);
971 pp->buffer_pos -= ioff; 954 pp->buffer_pos -= ioff;
972 ioff = 0; 955 ioff = 0;
973 max = 1; 956 state_changed = 1;
974 } 957 }
975 } 958 }
976END: 959END:
977 if (ioff != 0) 960 if (ioff != 0)
@@ -979,10 +962,10 @@ END:
979 memmove (buf, &buf[ioff], pp->buffer_pos - ioff); 962 memmove (buf, &buf[ioff], pp->buffer_pos - ioff);
980 pp->buffer_pos -= ioff; 963 pp->buffer_pos -= ioff;
981 } 964 }
982 if (poff < post_data_len) 965 if (poff < post_data_len)
983 { 966 {
984 pp->state = PP_Error; 967 pp->state = PP_Error;
985 return MHD_NO; /* serious error */ 968 return MHD_NO; /* serious error */
986 } 969 }
987 return MHD_YES; 970 return MHD_YES;
988} 971}
@@ -1027,9 +1010,9 @@ MHD_destroy_post_processor (struct MHD_PostProcessor *pp)
1027 the post-processing may have been interrupted 1010 the post-processing may have been interrupted
1028 at any stage */ 1011 at any stage */
1029 pp->have = NE_none; 1012 pp->have = NE_none;
1030 free_unmarked(pp); 1013 free_unmarked (pp);
1031 if (pp->nested_boundary != NULL) 1014 if (pp->nested_boundary != NULL)
1032 free(pp->nested_boundary); 1015 free (pp->nested_boundary);
1033 free (pp); 1016 free (pp);
1034} 1017}
1035 1018
diff --git a/src/daemon/postprocessor_test.c b/src/daemon/postprocessor_test.c
index a931b300..6641fe1e 100644
--- a/src/daemon/postprocessor_test.c
+++ b/src/daemon/postprocessor_test.c
@@ -40,10 +40,10 @@
40 * Each series of checks should be terminated by 40 * Each series of checks should be terminated by
41 * five NULL-entries. 41 * five NULL-entries.
42 */ 42 */
43const char * want[] = { 43const char *want[] = {
44#define URL_DATA "abc=def&x=5" 44#define URL_DATA "abc=def&x=5"
45#define URL_START 0 45#define URL_START 0
46 "abc", NULL, NULL, NULL, "def", 46 "abc", NULL, NULL, NULL, "def",
47 "x", NULL, NULL, NULL, "5", 47 "x", NULL, NULL, NULL, "5",
48#define URL_END (URL_START + 10) 48#define URL_END (URL_START + 10)
49 NULL, NULL, NULL, NULL, NULL, 49 NULL, NULL, NULL, NULL, NULL,
@@ -63,81 +63,80 @@ const char * want[] = {
63}; 63};
64 64
65static int 65static int
66mismatch(const char * a, const char * b) { 66mismatch (const char *a, const char *b)
67 if (a == b) 67{
68 if (a == b)
68 return 0; 69 return 0;
69 if ( (a == NULL) || 70 if ((a == NULL) || (b == NULL))
70 (b == NULL) )
71 return 1; 71 return 1;
72 return 0 != strcmp(a, b); 72 return 0 != strcmp (a, b);
73} 73}
74 74
75static int 75static int
76value_checker(void * cls, 76value_checker (void *cls,
77 enum MHD_ValueKind kind, 77 enum MHD_ValueKind kind,
78 const char * key, 78 const char *key,
79 const char * filename, 79 const char *filename,
80 const char * content_type, 80 const char *content_type,
81 const char * transfer_encoding, 81 const char *transfer_encoding,
82 const char * data, 82 const char *data, size_t off, size_t size)
83 size_t off, 83{
84 size_t size) { 84 int *want_off = cls;
85 int * want_off = cls;
86 int idx = *want_off; 85 int idx = *want_off;
87 86
88#if 0 87#if 0
89 fprintf(stderr, 88 fprintf (stderr,
90 "VC: `%s' `%s' `%s' `%s' `%.*s'\n", 89 "VC: `%s' `%s' `%s' `%s' `%.*s'\n",
91 key, filename, content_type, transfer_encoding, size, data); 90 key, filename, content_type, transfer_encoding, size, data);
92#endif 91#endif
93 if (size == 0) 92 if (size == 0)
94 return MHD_YES; 93 return MHD_YES;
95 if ( (idx < 0) || 94 if ((idx < 0) ||
96 (want[idx] == NULL) || 95 (want[idx] == NULL) ||
97 (0 != strcmp(key, want[idx])) || 96 (0 != strcmp (key, want[idx])) ||
98 (mismatch(filename, want[idx+1])) || 97 (mismatch (filename, want[idx + 1])) ||
99 (mismatch(content_type, want[idx+2])) || 98 (mismatch (content_type, want[idx + 2])) ||
100 (mismatch(transfer_encoding, want[idx+3])) || 99 (mismatch (transfer_encoding, want[idx + 3])) ||
101 (0 != memcmp(data, &want[idx+4][off], size)) ) 100 (0 != memcmp (data, &want[idx + 4][off], size)))
102 { 101 {
103 *want_off = -1; 102 *want_off = -1;
104 return MHD_NO; 103 return MHD_NO;
105 } 104 }
106 if (off + size == strlen(want[idx+4])) 105 if (off + size == strlen (want[idx + 4]))
107 *want_off = idx + 5; 106 *want_off = idx + 5;
108 return MHD_YES; 107 return MHD_YES;
109 108
110} 109}
111 110
112 111
113static int 112static int
114test_urlencoding() { 113test_urlencoding ()
114{
115 struct MHD_Connection connection; 115 struct MHD_Connection connection;
116 struct MHD_HTTP_Header header; 116 struct MHD_HTTP_Header header;
117 struct MHD_PostProcessor * pp; 117 struct MHD_PostProcessor *pp;
118 unsigned int want_off = URL_START; 118 unsigned int want_off = URL_START;
119 int i; 119 int i;
120 int delta; 120 int delta;
121 size_t size; 121 size_t size;
122 122
123 memset(&connection, 0, sizeof(struct MHD_Connection)); 123 memset (&connection, 0, sizeof (struct MHD_Connection));
124 memset(&header, 0, sizeof(struct MHD_HTTP_Header)); 124 memset (&header, 0, sizeof (struct MHD_HTTP_Header));
125 connection.headers_received = &header; 125 connection.headers_received = &header;
126 header.header = MHD_HTTP_HEADER_CONTENT_TYPE; 126 header.header = MHD_HTTP_HEADER_CONTENT_TYPE;
127 header.value = MHD_HTTP_POST_ENCODING_FORM_URLENCODED; 127 header.value = MHD_HTTP_POST_ENCODING_FORM_URLENCODED;
128 header.kind = MHD_HEADER_KIND; 128 header.kind = MHD_HEADER_KIND;
129 pp = MHD_create_post_processor(&connection, 129 pp = MHD_create_post_processor (&connection,
130 1024, 130 1024, &value_checker, &want_off);
131 &value_checker,
132 &want_off);
133 i = 0; 131 i = 0;
134 size = strlen(URL_DATA); 132 size = strlen (URL_DATA);
135 while (i < size) { 133 while (i < size)
136 delta = 1 + random() % (size - i); 134 {
137 MHD_post_process(pp, &URL_DATA[i], delta); 135 delta = 1 + random () % (size - i);
138 i += delta; 136 MHD_post_process (pp, &URL_DATA[i], delta);
139 } 137 i += delta;
140 MHD_destroy_post_processor(pp); 138 }
139 MHD_destroy_post_processor (pp);
141 if (want_off != URL_END) 140 if (want_off != URL_END)
142 return 1; 141 return 1;
143 return 0; 142 return 0;
@@ -145,33 +144,34 @@ test_urlencoding() {
145 144
146 145
147static int 146static int
148test_multipart() { 147test_multipart ()
148{
149 struct MHD_Connection connection; 149 struct MHD_Connection connection;
150 struct MHD_HTTP_Header header; 150 struct MHD_HTTP_Header header;
151 struct MHD_PostProcessor * pp; 151 struct MHD_PostProcessor *pp;
152 unsigned int want_off = FORM_START; 152 unsigned int want_off = FORM_START;
153 int i; 153 int i;
154 int delta; 154 int delta;
155 size_t size; 155 size_t size;
156 156
157 memset(&connection, 0, sizeof(struct MHD_Connection)); 157 memset (&connection, 0, sizeof (struct MHD_Connection));
158 memset(&header, 0, sizeof(struct MHD_HTTP_Header)); 158 memset (&header, 0, sizeof (struct MHD_HTTP_Header));
159 connection.headers_received = &header; 159 connection.headers_received = &header;
160 header.header = MHD_HTTP_HEADER_CONTENT_TYPE; 160 header.header = MHD_HTTP_HEADER_CONTENT_TYPE;
161 header.value = MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA ", boundary=AaB03x"; 161 header.value =
162 MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA ", boundary=AaB03x";
162 header.kind = MHD_HEADER_KIND; 163 header.kind = MHD_HEADER_KIND;
163 pp = MHD_create_post_processor(&connection, 164 pp = MHD_create_post_processor (&connection,
164 1024, 165 1024, &value_checker, &want_off);
165 &value_checker,
166 &want_off);
167 i = 0; 166 i = 0;
168 size = strlen(FORM_DATA); 167 size = strlen (FORM_DATA);
169 while (i < size) { 168 while (i < size)
170 delta = 1 + random() % (size - i); 169 {
171 MHD_post_process(pp, &FORM_DATA[i], delta); 170 delta = 1 + random () % (size - i);
172 i += delta; 171 MHD_post_process (pp, &FORM_DATA[i], delta);
173 } 172 i += delta;
174 MHD_destroy_post_processor(pp); 173 }
174 MHD_destroy_post_processor (pp);
175 if (want_off != FORM_END) 175 if (want_off != FORM_END)
176 return 2; 176 return 2;
177 return 0; 177 return 0;
@@ -179,33 +179,34 @@ test_multipart() {
179 179
180 180
181static int 181static int
182test_nested_multipart() { 182test_nested_multipart ()
183{
183 struct MHD_Connection connection; 184 struct MHD_Connection connection;
184 struct MHD_HTTP_Header header; 185 struct MHD_HTTP_Header header;
185 struct MHD_PostProcessor * pp; 186 struct MHD_PostProcessor *pp;
186 unsigned int want_off = FORM_NESTED_START; 187 unsigned int want_off = FORM_NESTED_START;
187 int i; 188 int i;
188 int delta; 189 int delta;
189 size_t size; 190 size_t size;
190 191
191 memset(&connection, 0, sizeof(struct MHD_Connection)); 192 memset (&connection, 0, sizeof (struct MHD_Connection));
192 memset(&header, 0, sizeof(struct MHD_HTTP_Header)); 193 memset (&header, 0, sizeof (struct MHD_HTTP_Header));
193 connection.headers_received = &header; 194 connection.headers_received = &header;
194 header.header = MHD_HTTP_HEADER_CONTENT_TYPE; 195 header.header = MHD_HTTP_HEADER_CONTENT_TYPE;
195 header.value = MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA ", boundary=AaB03x"; 196 header.value =
197 MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA ", boundary=AaB03x";
196 header.kind = MHD_HEADER_KIND; 198 header.kind = MHD_HEADER_KIND;
197 pp = MHD_create_post_processor(&connection, 199 pp = MHD_create_post_processor (&connection,
198 1024, 200 1024, &value_checker, &want_off);
199 &value_checker,
200 &want_off);
201 i = 0; 201 i = 0;
202 size = strlen(FORM_NESTED_DATA); 202 size = strlen (FORM_NESTED_DATA);
203 while (i < size) { 203 while (i < size)
204 delta = 1 + random() % (size - i); 204 {
205 MHD_post_process(pp, &FORM_NESTED_DATA[i], delta); 205 delta = 1 + random () % (size - i);
206 i += delta; 206 MHD_post_process (pp, &FORM_NESTED_DATA[i], delta);
207 } 207 i += delta;
208 MHD_destroy_post_processor(pp); 208 }
209 MHD_destroy_post_processor (pp);
209 if (want_off != FORM_NESTED_END) 210 if (want_off != FORM_NESTED_END)
210 return 4; 211 return 4;
211 return 0; 212 return 0;
@@ -216,9 +217,9 @@ main (int argc, char *const *argv)
216{ 217{
217 unsigned int errorCount = 0; 218 unsigned int errorCount = 0;
218 219
219 errorCount += test_urlencoding(); 220 errorCount += test_urlencoding ();
220 errorCount += test_multipart(); 221 errorCount += test_multipart ();
221 errorCount += test_nested_multipart(); 222 errorCount += test_nested_multipart ();
222 if (errorCount != 0) 223 if (errorCount != 0)
223 fprintf (stderr, "Error (code: %u)\n", errorCount); 224 fprintf (stderr, "Error (code: %u)\n", errorCount);
224 return errorCount != 0; /* 0 == pass */ 225 return errorCount != 0; /* 0 == pass */
diff --git a/src/daemon/response.c b/src/daemon/response.c
index ea1fe9c0..3089e6c1 100644
--- a/src/daemon/response.c
+++ b/src/daemon/response.c
@@ -238,10 +238,10 @@ MHD_create_response_from_data (size_t size,
238 { 238 {
239 tmp = malloc (size); 239 tmp = malloc (size);
240 if (tmp == NULL) 240 if (tmp == NULL)
241 { 241 {
242 free(retVal); 242 free (retVal);
243 return NULL; 243 return NULL;
244 } 244 }
245 memcpy (tmp, data, size); 245 memcpy (tmp, data, size);
246 must_free = 1; 246 must_free = 1;
247 data = tmp; 247 data = tmp;