aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2007-06-16 05:28:11 +0000
committerChristian Grothoff <christian@grothoff.org>2007-06-16 05:28:11 +0000
commitb99e151779ca734c1f8e3e2ee66453b3a2b67120 (patch)
treebe8644346ebcfafa6c04eb1f9ecd91653a96bcfd
parent23eb4a13d8a7418bcb86757c607e40f42336f608 (diff)
downloadlibmicrohttpd-b99e151779ca734c1f8e3e2ee66453b3a2b67120.tar.gz
libmicrohttpd-b99e151779ca734c1f8e3e2ee66453b3a2b67120.zip
cookie and upload end handling
-rw-r--r--README10
-rw-r--r--configure.ac3
-rw-r--r--src/daemon/daemon.c3
-rw-r--r--src/daemon/internal.h8
-rw-r--r--src/daemon/session.c125
5 files changed, 118 insertions, 31 deletions
diff --git a/README b/README
index ef46cb20..d4b04d32 100644
--- a/README
+++ b/README
@@ -7,14 +7,7 @@ before certain features can be used at all:
7 7
8For PUT/POST: 8For PUT/POST:
9============= 9=============
10session.c: 10testing!
11- MHD_parse_session_headers (determine upload size)
12- MHD_session_handle_read (proper handling of upload end)
13
14For COOKIES:
15============
16session.c:
17- MHD_parse_session_headers: take cookie header apart
18 11
19For http-compliance: 12For http-compliance:
20==================== 13====================
@@ -47,4 +40,3 @@ Other:
47 buffers 40 buffers
48 41
49 42
50
diff --git a/configure.ac b/configure.ac
index eb6591a7..de88f861 100644
--- a/configure.ac
+++ b/configure.ac
@@ -21,7 +21,7 @@
21# 21#
22# 22#
23AC_PREREQ(2.57) 23AC_PREREQ(2.57)
24AC_INIT([libmicrohttpd], [0.0.0],[libmicrohttpd@cs.du.edu]) 24AC_INIT([libmicrohttpd], [0.0.0],[libmicrohttpd@gnunet.org])
25AM_INIT_AUTOMAKE([libmicrohttpd], [0.0.0]) 25AM_INIT_AUTOMAKE([libmicrohttpd], [0.0.0])
26AM_CONFIG_HEADER([config.h]) 26AM_CONFIG_HEADER([config.h])
27 27
@@ -37,7 +37,6 @@ AC_CANONICAL_HOST
37AM_PROG_LIBTOOL 37AM_PROG_LIBTOOL
38 38
39# set GCC options 39# set GCC options
40CFLAGS="-Wall -Werror $CFLAGS"
41# use '-fno-strict-aliasing', but only if the compiler can take it 40# use '-fno-strict-aliasing', but only if the compiler can take it
42if gcc -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1; 41if gcc -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1;
43then 42then
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c
index 70d5075f..18bfa30f 100644
--- a/src/daemon/daemon.c
+++ b/src/daemon/daemon.c
@@ -317,10 +317,9 @@ MHD_cleanup_sessions(struct MHD_Daemon * daemon) {
317 } 317 }
318 318
319 if ( (pos->headersReceived == 1) && 319 if ( (pos->headersReceived == 1) &&
320 (pos->read_buffer_size == pos->readLoc) &&
321 (pos->readLoc > 0) ) 320 (pos->readLoc > 0) )
322 MHD_call_session_handler(pos); 321 MHD_call_session_handler(pos);
323 322
324 prev = pos; 323 prev = pos;
325 pos = pos->next; 324 pos = pos->next;
326 } 325 }
diff --git a/src/daemon/internal.h b/src/daemon/internal.h
index 154021ed..fad568d8 100644
--- a/src/daemon/internal.h
+++ b/src/daemon/internal.h
@@ -230,6 +230,14 @@ struct MHD_Session {
230 * up in that case). 230 * up in that case).
231 */ 231 */
232 int socket_fd; 232 int socket_fd;
233
234 /**
235 * Has this socket been closed for reading (i.e.
236 * other side closed the connection)? If so,
237 * we must completely close the connection once
238 * we are done sending our response.
239 */
240 int read_close;
233 241
234 /** 242 /**
235 * Have we finished receiving all of the headers yet? 243 * Have we finished receiving all of the headers yet?
diff --git a/src/daemon/session.c b/src/daemon/session.c
index 29222968..e5335c83 100644
--- a/src/daemon/session.c
+++ b/src/daemon/session.c
@@ -131,8 +131,9 @@ MHD_session_get_fdset(struct MHD_Session * session,
131 fd_set * write_fd_set, 131 fd_set * write_fd_set,
132 fd_set * except_fd_set, 132 fd_set * except_fd_set,
133 int * max_fd) { 133 int * max_fd) {
134 if ( (session->headersReceived == 0) || 134 if ( (session->read_close == 0) &&
135 (session->readLoc < session->read_buffer_size) ) 135 ( (session->headersReceived == 0) ||
136 (session->readLoc < session->read_buffer_size) ) )
136 FD_SET(session->socket_fd, read_fd_set); 137 FD_SET(session->socket_fd, read_fd_set);
137 if (session->response != NULL) 138 if (session->response != NULL)
138 FD_SET(session->socket_fd, write_fd_set); 139 FD_SET(session->socket_fd, write_fd_set);
@@ -271,6 +272,63 @@ MHD_parse_arguments(struct MHD_Session * session,
271} 272}
272 273
273/** 274/**
275 * Parse the cookie header (see RFC 2109).
276 */
277static void
278MHD_parse_cookie_header(struct MHD_Session * session) {
279 const char * hdr;
280 char * cpy;
281 char * pos;
282 char * semicolon;
283 char * equals;
284 int quotes;
285
286 hdr = MHD_lookup_session_value(session,
287 MHD_HEADER_KIND,
288 "Cookie");
289 if (hdr == NULL)
290 return;
291 cpy = strdup(hdr);
292 pos = cpy;
293 while (pos != NULL) {
294 equals = strstr(pos, "=");
295 if (equals == NULL)
296 break;
297 equals[0] = '\0';
298 equals++;
299 quotes = 0;
300 semicolon = equals;
301 while ( (semicolon[0] != '\0') &&
302 ( (quotes != 0) ||
303 ( (semicolon[0] != ';') &&
304 (semicolon[0] != ',') ) ) ) {
305 if (semicolon[0] == '"')
306 quotes = (quotes + 1) & 1;
307 semicolon++;
308 }
309 if (semicolon[0] == '\0')
310 semicolon = NULL;
311 if (semicolon != NULL) {
312 semicolon[0] = '\0';
313 semicolon++;
314 }
315 /* remove quotes */
316 if ( (equals[0] == '"') &&
317 (equals[strlen(equals)-1] == '"') ) {
318 equals[strlen(equals)-1] = '\0';
319 equals++;
320 }
321 MHD_session_add_header(session,
322 pos,
323 equals,
324 MHD_COOKIE_KIND);
325 pos = semicolon;
326 }
327 free(cpy);
328}
329
330
331/**
274 * This function is designed to parse the input buffer of a given session. 332 * This function is designed to parse the input buffer of a given session.
275 * 333 *
276 * Once the header is complete, it should have set the 334 * Once the header is complete, it should have set the
@@ -287,6 +345,8 @@ MHD_parse_session_headers(struct MHD_Session * session) {
287 char * uri; 345 char * uri;
288 char * httpType; 346 char * httpType;
289 char * args; 347 char * args;
348 const char * clen;
349 unsigned long long cval;
290 350
291 if (session->bodyReceived == 1) 351 if (session->bodyReceived == 1)
292 abort(); 352 abort();
@@ -316,16 +376,38 @@ MHD_parse_session_headers(struct MHD_Session * session) {
316 } 376 }
317 /* check if this is the end of the header */ 377 /* check if this is the end of the header */
318 if (strlen(line) == 0) { 378 if (strlen(line) == 0) {
379 free(line);
319 /* end of header */ 380 /* end of header */
320 session->headersReceived = 1; 381 session->headersReceived = 1;
321 /* FIXME: check which methods may have a body, 382 clen = MHD_lookup_session_value(session,
322 check headers to find out upload size */ 383 MHD_HEADER_KIND,
323 session->uploadSize = 0; 384 "Content-Length");
324 session->bodyReceived = 1; 385 if (clen != NULL) {
325 free(line); 386 if (1 != sscanf(clen,
387 "%llu",
388 &cval)) {
389 MHD_DLOG(session->daemon,
390 "Failed to parse Content-Length header `%s', closing connection.\n",
391 clen);
392 goto DIE;
393 }
394 session->uploadSize = cval;
395 session->bodyReceived = cval == 0 ? 1 : 0;
396 } else {
397 if (NULL == MHD_lookup_session_value(session,
398 MHD_HEADER_KIND,
399 "Transfer-Encoding")) {
400 /* this request does not have a body */
401 session->uploadSize = 0;
402 session->bodyReceived = 1;
403 } else {
404 session->uploadSize = -1; /* unknown size */
405 session->bodyReceived = 0;
406 }
407 }
326 break; 408 break;
327 } 409 }
328 /* ok, line should be normal header line, find colon */ 410 /* line should be normal header line, find colon */
329 colon = strstr(line, ": "); 411 colon = strstr(line, ": ");
330 if (colon == NULL) { 412 if (colon == NULL) {
331 /* error in header line, die hard */ 413 /* error in header line, die hard */
@@ -342,7 +424,7 @@ MHD_parse_session_headers(struct MHD_Session * session) {
342 MHD_HEADER_KIND); 424 MHD_HEADER_KIND);
343 free(line); 425 free(line);
344 } 426 }
345 /* FIXME: here: find cookie header and parse that! */ 427 MHD_parse_cookie_header(session);
346 return; 428 return;
347 DIE: 429 DIE:
348 CLOSE(session->socket_fd); 430 CLOSE(session->socket_fd);
@@ -398,8 +480,12 @@ MHD_call_session_handler(struct MHD_Session * session) {
398 &session->read_buffer[session->readLoc - processed], 480 &session->read_buffer[session->readLoc - processed],
399 processed); 481 processed);
400 session->readLoc = processed; 482 session->readLoc = processed;
401 session->uploadSize -= processed; 483 if (session->uploadSize != -1)
402 if (session->uploadSize == 0) { 484 session->uploadSize -= processed;
485 if ( (session->uploadSize == 0) ||
486 ( (session->readLoc == 0) &&
487 (session->uploadSize == -1) &&
488 (session->socket_fd == -1) ) ) {
403 session->bodyReceived = 1; 489 session->bodyReceived = 1;
404 session->readLoc = 0; 490 session->readLoc = 0;
405 session->read_buffer_size = 0; 491 session->read_buffer_size = 0;
@@ -455,11 +541,9 @@ MHD_session_handle_read(struct MHD_Session * session) {
455 } 541 }
456 if (bytes_read == 0) { 542 if (bytes_read == 0) {
457 /* other side closed connection */ 543 /* other side closed connection */
458 /* FIXME: proper handling of end of upload! 544 if (session->readLoc > 0)
459 If we were receiving an unbounded upload, 545 MHD_call_session_handler(session);
460 we should finish up nicely now! */ 546 shutdown(session->socket_fd, SHUT_RD);
461 CLOSE(session->socket_fd);
462 session->socket_fd = -1;
463 return MHD_YES; 547 return MHD_YES;
464 } 548 }
465 session->readLoc += bytes_read; 549 session->readLoc += bytes_read;
@@ -487,13 +571,13 @@ MHD_add_extra_headers(struct MHD_Session * session) {
487 "Connection", 571 "Connection",
488 "close"); 572 "close");
489 } else if (NULL == MHD_get_response_header(session->response, 573 } else if (NULL == MHD_get_response_header(session->response,
490 "Content-length")) { 574 "Content-Length")) {
491 _REAL_SNPRINTF(buf, 575 _REAL_SNPRINTF(buf,
492 128, 576 128,
493 "%llu", 577 "%llu",
494 (unsigned long long) session->response->total_size); 578 (unsigned long long) session->response->total_size);
495 MHD_add_response_header(session->response, 579 MHD_add_response_header(session->response,
496 "Content-length", 580 "Content-Length",
497 buf); 581 buf);
498 } 582 }
499} 583}
@@ -662,6 +746,11 @@ MHD_session_handle_write(struct MHD_Session * session) {
662 free(session->write_buffer); 746 free(session->write_buffer);
663 session->write_buffer = NULL; 747 session->write_buffer = NULL;
664 session->write_buffer_size = 0; 748 session->write_buffer_size = 0;
749 if (session->read_close != 0) {
750 /* closed for reading => close for good! */
751 CLOSE(session->socket_fd);
752 session->socket_fd = -1;
753 }
665 } 754 }
666 return MHD_YES; 755 return MHD_YES;
667} 756}