diff options
author | SVN Migration <svn@php.net> | 2003-02-27 17:43:39 +0000 |
---|---|---|
committer | SVN Migration <svn@php.net> | 2003-02-27 17:43:39 +0000 |
commit | 078bcec0997ad0e07b720c43cc9e6d0e046a75ab (patch) | |
tree | 36cb0f6be2ef078fe3374de8c087b93ecf82f812 /sapi/thttpd/thttpd_patch | |
parent | fd61f69077f6156ca71dde60ecfd9ed9765a02db (diff) | |
download | php-git-PHP-5.tar.gz |
This commit was manufactured by cvs2svn to create branch 'PHP_5'.PHP-5
Diffstat (limited to 'sapi/thttpd/thttpd_patch')
-rw-r--r-- | sapi/thttpd/thttpd_patch | 1881 |
1 files changed, 0 insertions, 1881 deletions
diff --git a/sapi/thttpd/thttpd_patch b/sapi/thttpd/thttpd_patch deleted file mode 100644 index 404686c13c..0000000000 --- a/sapi/thttpd/thttpd_patch +++ /dev/null @@ -1,1881 +0,0 @@ -diff -ur thttpd-2.21b/Makefile.in thttpd-2.21b-cool/Makefile.in ---- thttpd-2.21b/Makefile.in Thu Mar 29 20:36:21 2001 -+++ thttpd-2.21b-cool/Makefile.in Thu Feb 13 03:27:55 2003 -@@ -46,13 +46,15 @@ - - # You shouldn't need to edit anything below here. - -+include php_makefile -+ - CC = @CC@ - CCOPT = @V_CCOPT@ - DEFS = @DEFS@ - INCLS = -I. - CFLAGS = $(CCOPT) $(DEFS) $(INCLS) --LDFLAGS = @LDFLAGS@ --LIBS = @LIBS@ -+LDFLAGS = @LDFLAGS@ $(PHP_LDFLAGS) -+LIBS = @LIBS@ $(PHP_LIBS) - NETLIBS = @V_NETLIBS@ - INSTALL = @INSTALL@ - -@@ -62,7 +64,7 @@ - @rm -f $@ - $(CC) $(CFLAGS) -c $*.c - --SRC = thttpd.c libhttpd.c fdwatch.c mmc.c timers.c match.c tdate_parse.c syslog.c -+SRC = thttpd.c libhttpd.c fdwatch.c mmc.c timers.c match.c tdate_parse.c syslog.c php_thttpd.c - - OBJ = $(SRC:.c=.o) @LIBOBJS@ - -@@ -77,7 +79,7 @@ - all: this subdirs - this: $(ALL) - --thttpd: $(OBJ) -+thttpd: $(OBJ) libphp4.a - @rm -f $@ - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(NETLIBS) - -@@ -151,6 +153,9 @@ - - tags: - ctags -wtd *.c *.h -+ -+php_thttpd.o: php_thttpd.c -+ $(CC) $(PHP_CFLAGS) $(CFLAGS) -c php_thttpd.c - - tar: - @name=`sed -n -e '/SERVER_SOFTWARE/!d' -e 's,.*thttpd/,thttpd-,' -e 's, .*,,p' version.h` ; \ -diff -ur thttpd-2.21b/config.h thttpd-2.21b-cool/config.h ---- thttpd-2.21b/config.h Mon Apr 9 23:57:36 2001 -+++ thttpd-2.21b-cool/config.h Thu Feb 13 03:27:55 2003 -@@ -82,6 +82,11 @@ - */ - #define IDLE_READ_TIMELIMIT 60 - -+/* CONFIGURE: How many seconds to allow for reading the subsequent requests -+** on a keep-alive connection. Should be simiar to LINGER_TIME -+*/ -+#define IDLE_KEEPALIVE_TIMELIMIT 2 -+ - /* CONFIGURE: How many seconds before an idle connection gets closed. - */ - #define IDLE_SEND_TIMELIMIT 300 -@@ -316,7 +321,7 @@ - /* CONFIGURE: A list of index filenames to check. The files are searched - ** for in this order. - */ --#define INDEX_NAMES "index.html", "index.htm", "Default.htm", "index.cgi" -+#define INDEX_NAMES "index.php", "index.html", "index.htm", "Default.htm", "index.cgi" - - /* CONFIGURE: If this is defined then thttpd will automatically generate - ** index pages for directories that don't have an explicit index file. -diff -ur thttpd-2.21b/configure thttpd-2.21b-cool/configure ---- thttpd-2.21b/configure Sat Apr 21 02:07:14 2001 -+++ thttpd-2.21b-cool/configure Thu Feb 13 03:27:55 2003 -@@ -1021,7 +1021,7 @@ - fi - echo "$ac_t""$CPP" 1>&6 - --for ac_hdr in fcntl.h grp.h memory.h paths.h poll.h sys/poll.h sys/event.h osreldate.h -+for ac_hdr in fcntl.h grp.h memory.h paths.h poll.h sys/poll.h sys/event.h osreldate.h netinet/tcp.h - do - ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` - echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -diff -ur thttpd-2.21b/configure.in thttpd-2.21b-cool/configure.in ---- thttpd-2.21b/configure.in Sat Apr 21 02:06:23 2001 -+++ thttpd-2.21b-cool/configure.in Thu Feb 13 03:27:55 2003 -@@ -64,7 +64,7 @@ - AC_MSG_RESULT(no) - fi - --AC_CHECK_HEADERS(fcntl.h grp.h memory.h paths.h poll.h sys/poll.h sys/event.h osreldate.h) -+AC_CHECK_HEADERS(fcntl.h grp.h memory.h paths.h poll.h sys/poll.h sys/event.h osreldate.h netinet/tcp.h) - AC_HEADER_TIME - AC_HEADER_DIRENT - -diff -ur thttpd-2.21b/fdwatch.c thttpd-2.21b-cool/fdwatch.c ---- thttpd-2.21b/fdwatch.c Fri Apr 13 07:36:08 2001 -+++ thttpd-2.21b-cool/fdwatch.c Thu Feb 13 03:27:55 2003 -@@ -460,7 +460,7 @@ - - ridx = 0; - for ( i = 0; i < npollfds; ++i ) -- if ( pollfds[i].revents & ( POLLIN | POLLOUT ) ) -+ if ( pollfds[i].revents & ( POLLIN | POLLOUT | POLLERR | POLLHUP | POLLNVAL ) ) - poll_rfdidx[ridx++] = pollfds[i].fd; - - return r; -@@ -472,8 +472,8 @@ - { - switch ( fd_rw[fd] ) - { -- case FDW_READ: return pollfds[poll_fdidx[fd]].revents & POLLIN; -- case FDW_WRITE: return pollfds[poll_fdidx[fd]].revents & POLLOUT; -+ case FDW_READ: return pollfds[poll_fdidx[fd]].revents & ( POLLIN | POLLERR | POLLHUP | POLLNVAL ); -+ case FDW_WRITE: return pollfds[poll_fdidx[fd]].revents & ( POLLOUT | POLLERR | POLLHUP | POLLNVAL ); - default: return 0; - } - } -diff -ur thttpd-2.21b/libhttpd.c thttpd-2.21b-cool/libhttpd.c ---- thttpd-2.21b/libhttpd.c Tue Apr 24 00:42:40 2001 -+++ thttpd-2.21b-cool/libhttpd.c Thu Feb 13 03:27:55 2003 -@@ -56,6 +56,10 @@ - #include <unistd.h> - #include <stdarg.h> - -+#ifdef HAVE_NETINET_TCP_H -+#include <netinet/tcp.h> -+#endif -+ - #ifdef HAVE_OSRELDATE_H - #include <osreldate.h> - #endif /* HAVE_OSRELDATE_H */ -@@ -85,6 +89,12 @@ - #include "match.h" - #include "tdate_parse.h" - -+#include "php_thttpd.h" -+ -+#ifdef __CYGWIN__ -+# define timezone _timezone -+#endif -+ - #ifndef STDIN_FILENO - #define STDIN_FILENO 0 - #endif -@@ -242,6 +252,10 @@ - free( (void*) hs->cwd ); - if ( hs->cgi_pattern != (char*) 0 ) - free( (void*) hs->cgi_pattern ); -+ if ( hs->php_pattern != (char*) 0 ) -+ free( (void*) hs->php_pattern ); -+ if ( hs->phps_pattern != (char*) 0 ) -+ free( (void*) hs->phps_pattern ); - if ( hs->charset != (char*) 0 ) - free( (void*) hs->charset ); - if ( hs->url_pattern != (char*) 0 ) -@@ -249,6 +263,7 @@ - if ( hs->local_pattern != (char*) 0 ) - free( (void*) hs->local_pattern ); - free( (void*) hs ); -+ thttpd_php_shutdown(); - } - - -@@ -257,7 +272,8 @@ - char* hostname, httpd_sockaddr* sa4P, httpd_sockaddr* sa6P, int port, - char* cgi_pattern, char* charset, char* cwd, int no_log, FILE* logfp, - int no_symlink, int vhost, int global_passwd, char* url_pattern, -- char* local_pattern, int no_empty_referers ) -+ char* local_pattern, int no_empty_referers, char* php_pattern, -+ char* phps_pattern ) - { - httpd_server* hs; - static char ghnbuf[256]; -@@ -312,6 +328,8 @@ - } - - hs->port = port; -+ hs->php_pattern = strdup(php_pattern); -+ hs->phps_pattern = strdup(phps_pattern); - if ( cgi_pattern == (char*) 0 ) - hs->cgi_pattern = (char*) 0; - else -@@ -329,7 +347,7 @@ - while ( ( cp = strstr( hs->cgi_pattern, "|/" ) ) != (char*) 0 ) - (void) strcpy( cp + 1, cp + 2 ); - } -- hs->charset = strdup( charset ); -+ hs->charset = strdup( charset ); - hs->cwd = strdup( cwd ); - if ( hs->cwd == (char*) 0 ) - { -@@ -385,6 +403,8 @@ - return (httpd_server*) 0; - } - -+ thttpd_php_init(); -+ - /* Done initializing. */ - if ( hs->binding_hostname == (char*) 0 ) - syslog( LOG_INFO, "%.80s starting on port %d", SERVER_SOFTWARE, hs->port ); -@@ -418,6 +438,11 @@ - } - (void) fcntl( listen_fd, F_SETFD, 1 ); - -+#if defined(TCP_DEFER_ACCEPT) && defined(SOL_TCP) -+ on = 30; /* give clients 30s to send first data packet */ -+ setsockopt(listen_fd, SOL_TCP, TCP_DEFER_ACCEPT, &on, sizeof(on)); -+#endif -+ - /* Allow reuse of local addresses. */ - on = 1; - if ( setsockopt( -@@ -582,6 +607,9 @@ - /* And send it, if necessary. */ - if ( hc->responselen > 0 ) - { -+/* -+printf("**RESPONSE [%d]** len = %d\n%*.*s\n", hc->conn_fd, hc->responselen, hc->responselen, hc->responselen, hc->response); -+*/ - (void) write( hc->conn_fd, hc->response, hc->responselen ); - hc->responselen = 0; - } -@@ -657,9 +685,9 @@ - (void) my_snprintf( - fixed_type, sizeof(fixed_type), type, hc->hs->charset ); - (void) my_snprintf( buf, sizeof(buf), -- "%.20s %d %s\r\nServer: %s\r\nContent-Type: %s\r\nDate: %s\r\nLast-Modified: %s\r\nAccept-Ranges: bytes\r\nConnection: close\r\n", -- hc->protocol, status, title, EXPOSED_SERVER_SOFTWARE, fixed_type, -- nowbuf, modbuf ); -+ "HTTP/1.1 %d %s\r\nServer: %s\r\nContent-Type: %s\r\nDate: %s\r\nLast-Modified: %s\r\nAccept-Ranges: bytes\r\n", -+ status, title, EXPOSED_SERVER_SOFTWARE, fixed_type, -+ nowbuf, modbuf); - add_response( hc, buf ); - if ( encodings[0] != '\0' ) - { -@@ -681,6 +709,14 @@ - "Content-Length: %d\r\n", length ); - add_response( hc, buf ); - } -+ else { -+ hc->do_keep_alive = 0; -+ } -+ if (hc->do_keep_alive) { -+ add_response( hc, "Connection: keep-alive\r\n" ); -+ } else { -+ add_response( hc, "Connection: close\r\n" ); -+ } - if ( extraheads[0] != '\0' ) - add_response( hc, extraheads ); - add_response( hc, "\r\n" ); -@@ -1603,6 +1639,70 @@ - - - int -+httpd_request_reset(httpd_conn* hc, int preserve_read_buf ) -+{ -+ if (!preserve_read_buf) { -+ hc->read_idx = 0; -+ hc->checked_idx = 0; -+ } -+ -+ if (hc->read_buf_is_mmap) { -+ hc->read_buf_is_mmap = 0; -+ munmap(hc->read_buf, hc->read_size); -+ hc->read_buf = NULL; -+ hc->read_size = 0; -+ httpd_realloc_str( &hc->read_buf, &hc->read_size, 500 ); -+ } -+ hc->checked_state = CHST_FIRSTWORD; -+ hc->method = METHOD_UNKNOWN; -+ hc->status = 0; -+ hc->bytes_to_send = 0; -+ hc->bytes_sent = 0; -+ hc->encodedurl = ""; -+ hc->decodedurl[0] = '\0'; -+ hc->protocol = "UNKNOWN"; -+ hc->origfilename[0] = '\0'; -+ hc->expnfilename[0] = '\0'; -+ hc->encodings[0] = '\0'; -+ hc->pathinfo[0] = '\0'; -+ hc->query[0] = '\0'; -+ hc->referer = ""; -+ hc->useragent = ""; -+ hc->accept[0] = '\0'; -+ hc->accepte[0] = '\0'; -+ hc->acceptl = ""; -+ hc->cookie = ""; -+ hc->contenttype = ""; -+ hc->reqhost[0] = '\0'; -+ hc->hdrhost = ""; -+ hc->hostdir[0] = '\0'; -+ hc->authorization = ""; -+ hc->remoteuser[0] = '\0'; -+ hc->response[0] = '\0'; -+#ifdef TILDE_MAP_2 -+ hc->altdir[0] = '\0'; -+#endif /* TILDE_MAP_2 */ -+ hc->responselen = 0; -+ hc->if_modified_since = (time_t) -1; -+ hc->range_if = (time_t) -1; -+ hc->contentlength = -1; -+ hc->type = ""; -+ hc->hostname = (char*) 0; -+ hc->mime_flag = 1; -+ hc->one_one = 0; -+ hc->got_range = 0; -+ hc->tildemapped = 0; -+ hc->init_byte_loc = 0; -+ hc->end_byte_loc = -1; -+ hc->keep_alive = 0; -+ hc->do_keep_alive = 0; -+ hc->should_linger = 0; -+ hc->file_address = (char*) 0; -+ hc->read_body_into_mem = 0; -+ return GC_OK; -+} -+ -+int - httpd_get_conn( httpd_server* hs, int listen_fd, httpd_conn* hc ) - { - httpd_sockaddr sa; -@@ -1612,6 +1712,7 @@ - { - hc->read_size = 0; - httpd_realloc_str( &hc->read_buf, &hc->read_size, 500 ); -+ hc->read_buf_is_mmap = 0; - hc->maxdecodedurl = - hc->maxorigfilename = hc->maxexpnfilename = hc->maxencodings = - hc->maxpathinfo = hc->maxquery = hc->maxaccept = -@@ -1637,6 +1738,13 @@ - #endif /* TILDE_MAP_2 */ - hc->initialized = 1; - } -+ if (hc->read_buf_is_mmap) { -+ hc->read_buf_is_mmap = 0; -+ munmap(hc->read_buf, hc->read_size); -+ hc->read_buf = NULL; -+ hc->read_size = 0; -+ httpd_realloc_str( &hc->read_buf, &hc->read_size, 500 ); -+ } - - /* Accept the new connection. */ - sz = sizeof(sa); -@@ -1657,53 +1765,12 @@ - hc->hs = hs; - memset( &hc->client_addr, 0, sizeof(hc->client_addr) ); - memcpy( &hc->client_addr, &sa, sockaddr_len( &sa ) ); -- hc->read_idx = 0; -- hc->checked_idx = 0; -- hc->checked_state = CHST_FIRSTWORD; -- hc->method = METHOD_UNKNOWN; -- hc->status = 0; -- hc->bytes_to_send = 0; -- hc->bytes_sent = 0; -- hc->encodedurl = ""; -- hc->decodedurl[0] = '\0'; -- hc->protocol = "UNKNOWN"; -- hc->origfilename[0] = '\0'; -- hc->expnfilename[0] = '\0'; -- hc->encodings[0] = '\0'; -- hc->pathinfo[0] = '\0'; -- hc->query[0] = '\0'; -- hc->referer = ""; -- hc->useragent = ""; -- hc->accept[0] = '\0'; -- hc->accepte[0] = '\0'; -- hc->acceptl = ""; -- hc->cookie = ""; -- hc->contenttype = ""; -- hc->reqhost[0] = '\0'; -- hc->hdrhost = ""; -- hc->hostdir[0] = '\0'; -- hc->authorization = ""; -- hc->remoteuser[0] = '\0'; -- hc->response[0] = '\0'; --#ifdef TILDE_MAP_2 -- hc->altdir[0] = '\0'; --#endif /* TILDE_MAP_2 */ -- hc->responselen = 0; -- hc->if_modified_since = (time_t) -1; -- hc->range_if = (time_t) -1; -- hc->contentlength = -1; -- hc->type = ""; -- hc->hostname = (char*) 0; -- hc->mime_flag = 1; -- hc->one_one = 0; -- hc->got_range = 0; -- hc->tildemapped = 0; -- hc->init_byte_loc = 0; -- hc->end_byte_loc = -1; -- hc->keep_alive = 0; -- hc->should_linger = 0; -- hc->file_address = (char*) 0; -- return GC_OK; -+ -+/* -+printf("doing httpd_get_con(%d)\n", hc->conn_fd); -+*/ -+ -+ return httpd_request_reset(hc, 0); - } - - -@@ -1720,6 +1787,9 @@ - { - char c; - -+/* -+printf("**REQUEST [%d]**\n%*.*s\n", hc->conn_fd, hc->read_idx, hc->read_idx, hc->read_buf); -+*/ - for ( ; hc->checked_idx < hc->read_idx; ++hc->checked_idx ) - { - c = hc->read_buf[hc->checked_idx]; -@@ -1912,8 +1982,11 @@ - eol = strpbrk( protocol, " \t\n\r" ); - if ( eol != (char*) 0 ) - *eol = '\0'; -- if ( strcasecmp( protocol, "HTTP/1.0" ) != 0 ) -+ if ( strcasecmp( protocol, "HTTP/1.0" ) != 0 ) { - hc->one_one = 1; -+ hc->keep_alive = 1; -+ hc->do_keep_alive = 1; -+ } - } - } - /* Check for HTTP/1.1 absolute URL. */ -@@ -2012,6 +2085,11 @@ - cp = strchr( hc->hdrhost, ':' ); - if ( cp != (char*) 0 ) - *cp = '\0'; -+ if ( hc->hdrhost[0] == '.' || strpbrk( hc->hdrhost, "/\\" ) != 0 ) -+ { -+ httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" ); -+ return -1; -+ } - } - else if ( strncasecmp( buf, "Accept:", 7 ) == 0 ) - { -@@ -2129,6 +2207,7 @@ - cp = &buf[11]; - cp += strspn( cp, " \t" ); - if ( strcasecmp( cp, "keep-alive" ) == 0 ) -+ hc->do_keep_alive = 1; - hc->keep_alive = 1; - } - #ifdef LOG_UNKNOWN_HEADERS -@@ -2168,6 +2247,9 @@ - } - } - -+/* -+printf("one_one = %d keep_alive = %d\n", hc->one_one, hc->keep_alive); -+*/ - if ( hc->one_one ) - { - /* Check that HTTP/1.1 requests specify a host, as required. */ -@@ -2177,14 +2259,14 @@ - return -1; - } - -- /* If the client wants to do keep-alives, it might also be doing -- ** pipelining. There's no way for us to tell. Since we don't -- ** implement keep-alives yet, if we close such a connection there -- ** might be unread pipelined requests waiting. So, we have to -- ** do a lingering close. -+ /* -+ ** Disable keep alive support for bad browsers, -+ ** list taken from Apache 1.3.19 - */ -- if ( hc->keep_alive ) -- hc->should_linger = 1; -+ if ( hc->do_keep_alive && -+ ( strstr(hc->useragent, "Mozilla/2") != NULL || -+ strstr(hc->useragent, "MSIE 4.0b2;") != NULL)) -+ hc->do_keep_alive = 0; - } - - /* Ok, the request has been parsed. Now we resolve stuff that -@@ -2349,15 +2431,24 @@ - - - void --httpd_close_conn( httpd_conn* hc, struct timeval* nowP ) -- { -- make_log_entry( hc, nowP ); -+httpd_complete_request( httpd_conn* hc, struct timeval* nowP, int logit ) -+{ -+ if (logit) -+ make_log_entry( hc, nowP ); - -- if ( hc->file_address != (char*) 0 ) -+ if ( hc->file_address == (char*) 1 ) -+ { -+ thttpd_closed_conn(hc->conn_fd); -+ } else if ( hc->file_address != (char*) 0 ) - { - mmc_unmap( hc->file_address, &(hc->sb), nowP ); - hc->file_address = (char*) 0; - } -+ } -+ -+void -+httpd_close_conn( httpd_conn* hc, struct timeval* nowP ) -+{ - if ( hc->conn_fd >= 0 ) - { - (void) close( hc->conn_fd ); -@@ -2370,7 +2461,12 @@ - { - if ( hc->initialized ) - { -- free( (void*) hc->read_buf ); -+ -+ if ( hc->read_buf_is_mmap ) { -+ munmap( hc->read_buf, hc->read_size ); -+ } else { -+ free( (void*) hc->read_buf ); -+ } - free( (void*) hc->decodedurl ); - free( (void*) hc->origfilename ); - free( (void*) hc->expnfilename ); -@@ -3026,11 +3122,9 @@ - post_post_garbage_hack( httpd_conn* hc ) - { - char buf[2]; -- int r; - -- r = recv( hc->conn_fd, buf, sizeof(buf), MSG_PEEK ); -- if ( r > 0 ) -- (void) read( hc->conn_fd, buf, r ); -+ fcntl(hc->conn_fd, F_SETFL, O_NONBLOCK); -+ (void) read( hc->conn_fd, buf, 2 ); - } - - -@@ -3313,6 +3407,11 @@ - int r; - ClientData client_data; - -+ /* -+ ** We are not going to leave the socket open after a CGI... too hard -+ */ -+ hc->do_keep_alive = 0; -+ - if ( hc->method == METHOD_GET || hc->method == METHOD_POST ) - { - httpd_clear_ndelay( hc->conn_fd ); -@@ -3369,6 +3468,7 @@ - int expnlen, indxlen; - char* cp; - char* pi; -+ int nocache = 0; - - expnlen = strlen( hc->expnfilename ); - -@@ -3561,6 +3661,16 @@ - match( hc->hs->cgi_pattern, hc->expnfilename ) ) - return cgi( hc ); - -+ if ( hc->hs->php_pattern != (char*) 0 && -+ match( hc->hs->php_pattern, hc->expnfilename)) { -+ return thttpd_php_request( hc, 0 ); -+ } -+ -+ if ( hc->hs->phps_pattern != (char*) 0 && -+ match( hc->hs->phps_pattern, hc->expnfilename)) { -+ return thttpd_php_request( hc, 1 ); -+ } -+ - /* It's not CGI. If it's executable or there's pathinfo, someone's - ** trying to either serve or run a non-CGI file as CGI. Either case - ** is prohibited. -@@ -3594,6 +3704,8 @@ - hc->end_byte_loc = hc->sb.st_size - 1; - - figure_mime( hc ); -+ if ( strncmp(hc->decodedurl, "/nocache/", sizeof("/nocache/") - 1 ) == 0 ) -+ nocache = 1; - - if ( hc->method == METHOD_HEAD ) - { -@@ -3601,7 +3713,7 @@ - hc, 200, ok200title, hc->encodings, "", hc->type, hc->sb.st_size, - hc->sb.st_mtime ); - } -- else if ( hc->if_modified_since != (time_t) -1 && -+ else if ( !nocache && hc->if_modified_since != (time_t) -1 && - hc->if_modified_since >= hc->sb.st_mtime ) - { - hc->method = METHOD_HEAD; -@@ -3611,14 +3723,25 @@ - } - else - { -- hc->file_address = mmc_map( hc->expnfilename, &(hc->sb), nowP ); -+ char *extraheads = ""; -+ -+ if ( nocache ) -+ { -+ extraheads = "Expires: Thu, 19 Nov 1981 08:52:00 GMT\r\n" -+ "Cache-Control: no-store, no-cache, must-revalidate, " -+ "post-check=0, pre-check=0\r\n" -+ "Pragma: no-cache\r\n"; -+ } -+ -+ hc->file_address = mmc_map( hc->expnfilename, &(hc->sb), nowP, nocache ); - if ( hc->file_address == (char*) 0 ) - { - httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl ); - return -1; - } -+ - send_mime( -- hc, 200, ok200title, hc->encodings, "", hc->type, hc->sb.st_size, -+ hc, 200, ok200title, hc->encodings, extraheads, hc->type, hc->sb.st_size, - hc->sb.st_mtime ); - } - -diff -ur thttpd-2.21b/libhttpd.h thttpd-2.21b-cool/libhttpd.h ---- thttpd-2.21b/libhttpd.h Tue Apr 24 00:36:50 2001 -+++ thttpd-2.21b-cool/libhttpd.h Thu Feb 13 03:27:55 2003 -@@ -69,6 +69,8 @@ - char* server_hostname; - int port; - char* cgi_pattern; -+ char* php_pattern; -+ char* phps_pattern; - char* charset; - char* cwd; - int listen4_fd, listen6_fd; -@@ -88,6 +90,7 @@ - httpd_server* hs; - httpd_sockaddr client_addr; - char* read_buf; -+ char read_buf_is_mmap; - int read_size, read_idx, checked_idx; - int checked_state; - int method; -@@ -132,11 +135,12 @@ - int got_range; - int tildemapped; /* this connection got tilde-mapped */ - off_t init_byte_loc, end_byte_loc; -- int keep_alive; -+ int keep_alive, do_keep_alive; - int should_linger; - struct stat sb; - int conn_fd; - char* file_address; -+ char read_body_into_mem; - } httpd_conn; - - /* Methods. */ -@@ -168,7 +172,8 @@ - char* hostname, httpd_sockaddr* sa4P, httpd_sockaddr* sa6P, int port, - char* cgi_pattern, char* charset, char* cwd, int no_log, FILE* logfp, - int no_symlink, int vhost, int global_passwd, char* url_pattern, -- char* local_pattern, int no_empty_referers ); -+ char* local_pattern, int no_empty_referers, char* php_pattern, -+ char* phps_pattern ); - - /* Change the log file. */ - extern void httpd_set_logfp( httpd_server* hs, FILE* logfp ); -@@ -229,6 +234,8 @@ - ** If you don't have a current timeval handy just pass in 0. - */ - extern void httpd_close_conn( httpd_conn* hc, struct timeval* nowP ); -+void httpd_complete_request( httpd_conn* hc, struct timeval* nowP, int logit ); -+int httpd_request_reset(httpd_conn* hc,int ); - - /* Call this to de-initialize a connection struct and *really* free the - ** mallocced strings. -diff -ur thttpd-2.21b/mime_encodings.txt thttpd-2.21b-cool/mime_encodings.txt ---- thttpd-2.21b/mime_encodings.txt Wed May 10 03:22:28 2000 -+++ thttpd-2.21b-cool/mime_encodings.txt Thu Feb 13 03:27:55 2003 -@@ -3,6 +3,6 @@ - # A list of file extensions followed by the corresponding MIME encoding. - # Extensions not found in the table proceed to the mime_types table. - --Z x-compress --gz x-gzip -+Z compress -+gz gzip - uu x-uuencode -diff -ur thttpd-2.21b/mime_types.txt thttpd-2.21b-cool/mime_types.txt ---- thttpd-2.21b/mime_types.txt Sat Apr 14 04:53:30 2001 -+++ thttpd-2.21b-cool/mime_types.txt Thu Feb 13 03:27:55 2003 -@@ -1,135 +1,138 @@ --# mime_types.txt --# --# A list of file extensions followed by the corresponding MIME type. --# Extensions not found in the table are returned as text/plain. -- --html text/html; charset=%s --htm text/html; charset=%s --txt text/plain; charset=%s --rtx text/richtext --etx text/x-setext --tsv text/tab-separated-values --css text/css --xml text/xml --dtd text/xml -- --gif image/gif --jpg image/jpeg --jpeg image/jpeg --jpe image/jpeg --jfif image/jpeg --tif image/tiff --tiff image/tiff --pbm image/x-portable-bitmap --pgm image/x-portable-graymap --ppm image/x-portable-pixmap --pnm image/x-portable-anymap --xbm image/x-xbitmap --xpm image/x-xpixmap --xwd image/x-xwindowdump --ief image/ief --png image/png -- --au audio/basic --snd audio/basic --aif audio/x-aiff --aiff audio/x-aiff --aifc audio/x-aiff --ra audio/x-pn-realaudio --ram audio/x-pn-realaudio --rm audio/x-pn-realaudio --rpm audio/x-pn-realaudio-plugin --wav audio/wav --mid audio/midi --midi audio/midi --kar audio/midi --mpga audio/mpeg --mp2 audio/mpeg --mp3 audio/mpeg -- --mpeg video/mpeg --mpg video/mpeg --mpe video/mpeg --qt video/quicktime --mov video/quicktime --avi video/x-msvideo --movie video/x-sgi-movie --mv video/x-sgi-movie --vx video/x-rad-screenplay -- --a application/octet-stream -+ez application/andrew-inset -+hqx application/mac-binhex40 -+cpt application/mac-compactpro -+doc application/msword - bin application/octet-stream -+dms application/octet-stream -+lha application/octet-stream -+lzh application/octet-stream - exe application/octet-stream --dump application/octet-stream --o application/octet-stream --class application/java --js application/x-javascript -+class application/octet-stream -+so application/octet-stream -+dll application/octet-stream -+oda application/oda -+pdf application/pdf - ai application/postscript - eps application/postscript - ps application/postscript --dir application/x-director -+smi application/smil -+smil application/smil -+mif application/vnd.mif -+xls application/vnd.ms-excel -+ppt application/vnd.ms-powerpoint -+wbxml application/vnd.wap.wbxml -+wmlc application/vnd.wap.wmlc -+wmlsc application/vnd.wap.wmlscriptc -+bcpio application/x-bcpio -+vcd application/x-cdlink -+pgn application/x-chess-pgn -+cpio application/x-cpio -+csh application/x-csh - dcr application/x-director -+dir application/x-director - dxr application/x-director --fgd application/x-director --aam application/x-authorware-map --aas application/x-authorware-seg --aab application/x-authorware-bin --fh4 image/x-freehand --fh7 image/x-freehand --fh5 image/x-freehand --fhc image/x-freehand --fh image/x-freehand --spl application/futuresplash --swf application/x-shockwave-flash - dvi application/x-dvi -+spl application/x-futuresplash - gtar application/x-gtar - hdf application/x-hdf --hqx application/mac-binhex40 --iv application/x-inventor -+js application/x-javascript -+skp application/x-koan -+skd application/x-koan -+skt application/x-koan -+skm application/x-koan - latex application/x-latex --man application/x-troff-man --me application/x-troff-me --mif application/x-mif --ms application/x-troff-ms --oda application/oda --pdf application/pdf --rtf application/rtf --bcpio application/x-bcpio --cpio application/x-cpio --sv4cpio application/x-sv4cpio --sv4crc application/x-sv4crc --sh application/x-shar -+nc application/x-netcdf -+cdf application/x-netcdf -+sh application/x-sh - shar application/x-shar -+swf application/x-shockwave-flash - sit application/x-stuffit -+sv4cpio application/x-sv4cpio -+sv4crc application/x-sv4crc - tar application/x-tar -+tcl application/x-tcl - tex application/x-tex --texi application/x-texinfo - texinfo application/x-texinfo -+texi application/x-texinfo -+t application/x-troff - tr application/x-troff - roff application/x-troff - man application/x-troff-man - me application/x-troff-me - ms application/x-troff-ms --zip application/x-zip-compressed --tsp application/dsptype --wsrc application/x-wais-source - ustar application/x-ustar --cdf application/x-netcdf --nc application/x-netcdf --doc application/msword --ppt application/powerpoint -- --crt application/x-x509-ca-cert --crl application/x-pkcs7-crl -- -+src application/x-wais-source -+xhtml application/xhtml+xml -+xht application/xhtml+xml -+zip application/zip -+au audio/basic -+snd audio/basic -+mid audio/midi -+midi audio/midi -+kar audio/midi -+mpga audio/mpeg -+mp2 audio/mpeg -+mp3 audio/mpeg -+aif audio/x-aiff -+aiff audio/x-aiff -+aifc audio/x-aiff -+m3u audio/x-mpegurl -+ram audio/x-pn-realaudio -+rm audio/x-pn-realaudio -+rpm audio/x-pn-realaudio-plugin -+ra audio/x-realaudio -+wav audio/x-wav -+pdb chemical/x-pdb -+xyz chemical/x-xyz -+bmp image/bmp -+gif image/gif -+ief image/ief -+jpeg image/jpeg -+jpg image/jpeg -+jpe image/jpeg -+png image/png -+tiff image/tiff -+tif image/tiff -+djvu image/vnd.djvu -+djv image/vnd.djvu -+wbmp image/vnd.wap.wbmp -+ras image/x-cmu-raster -+pnm image/x-portable-anymap -+pbm image/x-portable-bitmap -+pgm image/x-portable-graymap -+ppm image/x-portable-pixmap -+rgb image/x-rgb -+xbm image/x-xbitmap -+xpm image/x-xpixmap -+xwd image/x-xwindowdump -+igs model/iges -+iges model/iges -+msh model/mesh -+mesh model/mesh -+silo model/mesh - wrl model/vrml - vrml model/vrml --mime message/rfc822 -- --pac application/x-ns-proxy-autoconfig -- -+css text/css -+html text/html; charset=%s -+htm text/html; charset=%s -+asc text/plain; charset=%s -+txt text/plain; charset=%s -+rtx text/richtext -+rtf text/rtf -+sgml text/sgml -+sgm text/sgml -+tsv text/tab-separated-values - wml text/vnd.wap.wml --wmlc application/vnd.wap.wmlc - wmls text/vnd.wap.wmlscript --wmlsc application/vnd.wap.wmlscriptc --wbmp image/vnd.wap.wbmp -+etx text/x-setext -+xml text/xml -+xsl text/xml -+mpeg video/mpeg -+mpg video/mpeg -+mpe video/mpeg -+qt video/quicktime -+mov video/quicktime -+mxu video/vnd.mpegurl -+avi video/x-msvideo -+movie video/x-sgi-movie -+ice x-conference/x-cooltalk -diff -ur thttpd-2.21b/mmc.c thttpd-2.21b-cool/mmc.c ---- thttpd-2.21b/mmc.c Fri Apr 13 23:02:15 2001 -+++ thttpd-2.21b-cool/mmc.c Thu Feb 13 03:27:55 2003 -@@ -70,6 +70,7 @@ - unsigned int hash; - int hash_idx; - struct MapStruct* next; -+ char nocache; - } Map; - - -@@ -93,7 +94,7 @@ - - - void* --mmc_map( char* filename, struct stat* sbP, struct timeval* nowP ) -+mmc_map( char* filename, struct stat* sbP, struct timeval* nowP, int nocache ) - { - time_t now; - struct stat sb; -@@ -167,12 +168,13 @@ - m->ctime = sb.st_ctime; - m->refcount = 1; - m->reftime = now; -+ m->nocache = (char) nocache; - - /* Avoid doing anything for zero-length files; some systems don't like - ** to mmap them, other systems dislike mallocing zero bytes. - */ - if ( m->size == 0 ) -- m->addr = (void*) 1; /* arbitrary non-NULL address */ -+ m->addr = (void*) 5; /* arbitrary non-NULL address */ - else - { - #ifdef HAVE_MMAP -@@ -231,27 +233,32 @@ - void - mmc_unmap( void* addr, struct stat* sbP, struct timeval* nowP ) - { -- Map* m = (Map*) 0; -+ Map* m = (Map*) 0, **mm = &maps; - - /* Find the Map entry for this address. First try a hash. */ - if ( sbP != (struct stat*) 0 ) - { - m = find_hash( sbP->st_ino, sbP->st_dev, sbP->st_size, sbP->st_ctime ); -- if ( m != (Map*) 0 && m->addr != addr ) -+ if ( m != (Map*) 0 && ( m->addr != addr || m->nocache == 1 ) ) - m = (Map*) 0; - } - /* If that didn't work, try a full search. */ - if ( m == (Map*) 0 ) -- for ( m = maps; m != (Map*) 0; m = m->next ) -+ for ( m = maps; m != (Map*) 0; m = m->next ) { - if ( m->addr == addr ) - break; -+ mm = &m->next; -+ } - if ( m == (Map*) 0 ) - syslog( LOG_ERR, "mmc_unmap failed to find entry!" ); - else if ( m->refcount <= 0 ) - syslog( LOG_ERR, "mmc_unmap found zero or negative refcount!" ); - else - { -- --m->refcount; -+ if ( --m->refcount == 0 && m->nocache == 1 ) { -+ really_unmap( mm ); -+ return; -+ } - if ( nowP != (struct timeval*) 0 ) - m->reftime = nowP->tv_sec; - else -diff -ur thttpd-2.21b/mmc.h thttpd-2.21b-cool/mmc.h ---- thttpd-2.21b/mmc.h Fri Apr 13 07:36:54 2001 -+++ thttpd-2.21b-cool/mmc.h Thu Feb 13 03:27:55 2003 -@@ -31,8 +31,9 @@ - /* Returns an mmap()ed area for the given file, or (void*) 0 on errors. - ** If you have a stat buffer on the file, pass it in, otherwise pass 0. - ** Same for the current time. -+** Set nocache to 1, if this entry is supposed to be removed quickly. - */ --extern void* mmc_map( char* filename, struct stat* sbP, struct timeval* nowP ); -+extern void* mmc_map( char* filename, struct stat* sbP, struct timeval* nowP, int nocache ); - - /* Done with an mmap()ed area that was returned by mmc_map(). - ** If you have a stat buffer on the file, pass it in, otherwise pass 0. -diff -ur thttpd-2.21b/thttpd.c thttpd-2.21b-cool/thttpd.c ---- thttpd-2.21b/thttpd.c Tue Apr 24 00:41:57 2001 -+++ thttpd-2.21b-cool/thttpd.c Thu Feb 13 03:28:11 2003 -@@ -53,6 +53,10 @@ - #endif - #include <unistd.h> - -+#include <sys/mman.h> -+ -+#include <limits.h> -+ - #include "fdwatch.h" - #include "libhttpd.h" - #include "mmc.h" -@@ -66,6 +70,8 @@ - static char* dir; - static int do_chroot, no_log, no_symlink, do_vhost, do_global_passwd; - static char* cgi_pattern; -+static char* php_pattern; -+static char* phps_pattern; - static char* url_pattern; - static int no_empty_referers; - static char* local_pattern; -@@ -95,10 +101,10 @@ - httpd_conn* hc; - int tnums[MAXTHROTTLENUMS]; /* throttle indexes */ - int numtnums; -+ int keep_alive; - long limit; - time_t started_at; -- Timer* idle_read_timer; -- Timer* idle_send_timer; -+ time_t last_io; - Timer* wakeup_timer; - Timer* linger_timer; - long wouldblock_delay; -@@ -106,17 +112,22 @@ - off_t bytes_sent; - off_t bytes_to_send; - } connecttab; --static connecttab* connects; -+static connecttab* connects, **free_connects; -+static int next_free_connect; - static int numconnects, maxconnects; - static int httpd_conn_count; - - /* The connection states. */ --#define CNST_FREE 0 --#define CNST_READING 1 --#define CNST_SENDING 2 --#define CNST_PAUSING 3 --#define CNST_LINGERING 4 -- -+enum { -+ CNST_FREE = 0, -+ CNST_READING, -+ CNST_SENDING, -+ CNST_PAUSING, -+ CNST_LINGERING, -+ CNST_SENDING_RESP, -+ CNST_READING_BODY, -+ CNST_TOTAL_NR -+}; - - static httpd_server* hs = (httpd_server*) 0; - int terminate = 0; -@@ -140,14 +151,15 @@ - static int handle_newconnect( struct timeval* tvP, int listen_fd ); - static void handle_read( connecttab* c, struct timeval* tvP ); - static void handle_send( connecttab* c, struct timeval* tvP ); -+static void handle_send_resp( connecttab* c, struct timeval* tvP ); -+static void handle_read_body( connecttab* c, struct timeval* tvP ); - static void handle_linger( connecttab* c, struct timeval* tvP ); - static int check_throttles( connecttab* c ); -+static void timeout_conns( ClientData client_data, struct timeval* nowP ); - static void clear_throttles( connecttab* c, struct timeval* tvP ); - static void update_throttles( ClientData client_data, struct timeval* nowP ); --static void clear_connection( connecttab* c, struct timeval* tvP ); -+static void clear_connection( connecttab* c, struct timeval* tvP, int ); - static void really_clear_connection( connecttab* c, struct timeval* tvP ); --static void idle_read_connection( ClientData client_data, struct timeval* nowP ); --static void idle_send_connection( ClientData client_data, struct timeval* nowP ); - static void wakeup_connection( ClientData client_data, struct timeval* nowP ); - static void linger_clear_connection( ClientData client_data, struct timeval* nowP ); - static void occasional( ClientData client_data, struct timeval* nowP ); -@@ -156,7 +168,14 @@ - #endif /* STATS_TIME */ - static void logstats( struct timeval* nowP ); - static void thttpd_logstats( long secs ); -+static void boot_request(connecttab *c, struct timeval *tvP); -+ -+typedef void (*handler_func)(connecttab*, struct timeval *); -+ -+handler_func handler_array[CNST_TOTAL_NR] = -+{NULL, handle_read, handle_send, NULL, handle_linger, handle_send_resp, handle_read_body}; - -+#define RUN_HANDLER(type, c) if (handler_array[type]) handler_array[type](c, &tv) - - static void - handle_term( int sig ) -@@ -177,7 +196,7 @@ - return; - - /* Re-open the log file. */ -- if ( logfile != (char*) 0 ) -+ if ( logfile != (char*) 0 && strcmp(logfile, "-") != 0) - { - logfp = fopen( logfile, "a" ); - if ( logfp == (FILE*) 0 ) -@@ -198,6 +217,8 @@ - } - - -+static time_t httpd_time_now; -+ - static void - handle_usr2( int sig ) - { -@@ -217,7 +238,6 @@ - int num_ready; - int cnum, ridx; - connecttab* c; -- httpd_conn* hc; - httpd_sockaddr sa4; - httpd_sockaddr sa6; - int gotv4, gotv6; -@@ -270,7 +290,9 @@ - no_log = 1; - logfp = (FILE*) 0; - } -- else -+ else if (strcmp(logfile, "-") == 0) { -+ logfp = stdout; -+ } else - { - logfp = fopen( logfile, "a" ); - if ( logfp == (FILE*) 0 ) -@@ -420,7 +442,8 @@ - hostname, - gotv4 ? &sa4 : (httpd_sockaddr*) 0, gotv6 ? &sa6 : (httpd_sockaddr*) 0, - port, cgi_pattern, charset, cwd, no_log, logfp, no_symlink, do_vhost, -- do_global_passwd, url_pattern, local_pattern, no_empty_referers ); -+ do_global_passwd, url_pattern, local_pattern, no_empty_referers, -+ php_pattern, phps_pattern); - if ( hs == (httpd_server*) 0 ) - exit( 1 ); - -@@ -430,6 +453,12 @@ - syslog( LOG_CRIT, "tmr_create(occasional) failed" ); - exit( 1 ); - } -+ -+ if (tmr_create(0, timeout_conns, JunkClientData, 30 * 1000, 1) == 0) { -+ syslog(LOG_CRIT, "tmr_create(timeout_conns) failed"); -+ exit(1); -+ } -+ - if ( numthrottles > 0 ) - { - /* Set up the throttles timer. */ -@@ -454,12 +483,14 @@ - /* If we're root, try to become someone else. */ - if ( getuid() == 0 ) - { -+#ifndef __CYGWIN__ - /* Set aux groups to null. */ - if ( setgroups( 0, (const gid_t*) 0 ) < 0 ) - { - syslog( LOG_CRIT, "setgroups - %m" ); - exit( 1 ); - } -+#endif - /* Set primary group. */ - if ( setgid( gid ) < 0 ) - { -@@ -495,13 +526,17 @@ - } - maxconnects -= SPARE_FDS; - connects = NEW( connecttab, maxconnects ); -+ free_connects = malloc(sizeof(connecttab *) * maxconnects); -+ next_free_connect = maxconnects; - if ( connects == (connecttab*) 0 ) - { - syslog( LOG_CRIT, "out of memory allocating a connecttab" ); - exit( 1 ); - } -+ - for ( cnum = 0; cnum < maxconnects; ++cnum ) - { -+ free_connects[cnum] = &connects[maxconnects - cnum - 1]; - connects[cnum].conn_state = CNST_FREE; - connects[cnum].hc = (httpd_conn*) 0; - } -@@ -518,6 +553,8 @@ - - /* Main loop. */ - (void) gettimeofday( &tv, (struct timezone*) 0 ); -+ httpd_time_now = tv.tv_sec; -+ - while ( ( ! terminate ) || numconnects > 0 ) - { - /* Do the fd watch. */ -@@ -565,16 +602,10 @@ - c = (connecttab*) fdwatch_get_client_data( ridx ); - if ( c == (connecttab*) 0 ) - continue; -- hc = c->hc; -- if ( c->conn_state == CNST_READING && -- fdwatch_check_fd( hc->conn_fd ) ) -- handle_read( c, &tv ); -- else if ( c->conn_state == CNST_SENDING && -- fdwatch_check_fd( hc->conn_fd ) ) -- handle_send( c, &tv ); -- else if ( c->conn_state == CNST_LINGERING && -- fdwatch_check_fd( hc->conn_fd ) ) -- handle_linger( c, &tv ); -+#if DO_UNNECESSARY_CHECK_FD -+ fdwatch_check_fd(c->hc->conn_fd); -+#endif -+ RUN_HANDLER(c->conn_state, c); - } - tmr_run( &tv ); - -@@ -627,6 +658,8 @@ - #else /* CGI_PATTERN */ - cgi_pattern = (char*) 0; - #endif /* CGI_PATTERN */ -+ php_pattern = "**.php"; -+ phps_pattern = "**.phps"; - url_pattern = (char*) 0; - no_empty_referers = 0; - local_pattern = (char*) 0; -@@ -833,6 +866,16 @@ - value_required( name, value ); - cgi_pattern = e_strdup( value ); - } -+ else if ( strcasecmp( name, "phppat" ) == 0 ) -+ { -+ value_required( name, value ); -+ php_pattern = e_strdup( value ); -+ } -+ else if ( strcasecmp( name, "phpspat" ) == 0 ) -+ { -+ value_required( name, value ); -+ phps_pattern = e_strdup( value ); -+ } - else if ( strcasecmp( name, "urlpat" ) == 0 ) - { - value_required( name, value ); -@@ -1196,8 +1239,10 @@ - logstats( &tv ); - for ( cnum = 0; cnum < maxconnects; ++cnum ) - { -- if ( connects[cnum].conn_state != CNST_FREE ) -+ if ( connects[cnum].conn_state != CNST_FREE ) { -+ httpd_complete_request( connects[cnum].hc, &tv, 1 ); - httpd_close_conn( connects[cnum].hc, &tv ); -+ } - if ( connects[cnum].hc != (httpd_conn*) 0 ) - { - httpd_destroy_conn( connects[cnum].hc ); -@@ -1214,6 +1259,7 @@ - } - mmc_destroy(); - tmr_destroy(); -+ free( (void*) free_connects ); - free( (void*) connects ); - if ( throttles != (throttletab*) 0 ) - free( (void*) throttles ); -@@ -1234,7 +1280,7 @@ - for (;;) - { - /* Is there room in the connection table? */ -- if ( numconnects >= maxconnects ) -+ if ( numconnects >= maxconnects || next_free_connect == 0 ) - { - /* Out of connection slots. Run the timers, then the - ** existing connections, and maybe we'll free up a slot -@@ -1245,10 +1291,10 @@ - return 0; - } - /* Find a free connection entry. */ -- for ( cnum = 0; cnum < maxconnects; ++cnum ) -- if ( connects[cnum].conn_state == CNST_FREE ) -- break; -- c = &connects[cnum]; -+ -+ c = free_connects[--next_free_connect]; -+ free_connects[next_free_connect] = NULL; -+ - /* Make the httpd_conn if necessary. */ - if ( c->hc == (httpd_conn*) 0 ) - { -@@ -1267,24 +1313,18 @@ - { - case GC_FAIL: - case GC_NO_MORE: -+ free_connects[next_free_connect++] = c; - return 1; - } - c->conn_state = CNST_READING; - ++numconnects; - client_data.p = c; -- c->idle_read_timer = tmr_create( -- tvP, idle_read_connection, client_data, IDLE_READ_TIMELIMIT * 1000L, -- 0 ); -- if ( c->idle_read_timer == (Timer*) 0 ) -- { -- syslog( LOG_CRIT, "tmr_create(idle_read_connection) failed" ); -- exit( 1 ); -- } -- c->idle_send_timer = (Timer*) 0; - c->wakeup_timer = (Timer*) 0; - c->linger_timer = (Timer*) 0; - c->bytes_sent = 0; - c->numtnums = 0; -+ c->keep_alive = 0; -+ c->last_io = httpd_time_now; - - /* Set the connection file descriptor to no-delay mode. */ - httpd_set_ndelay( c->hc->conn_fd ); -@@ -1297,12 +1337,79 @@ - } - } - -+static void -+setup_read_body(connecttab *c, struct timeval *tvP) -+{ -+ httpd_conn *hc = c->hc; -+ int already, missing, unused, nalloc; -+ -+ c->conn_state = CNST_READING_BODY; -+ -+ hc->read_body_into_mem = 0; -+ -+ already = hc->read_idx - hc->checked_idx; -+ missing = hc->contentlength - already; -+ unused = hc->read_size - hc->read_idx; -+ nalloc = missing - unused; -+ -+ if (missing > 16384) { -+ char filename[] = "/tmp/thttpd.upload.XXXXXX"; -+ int tmp = mkstemp(filename); -+ -+ if (tmp >= 0) { -+ void *p; -+ size_t sz = hc->contentlength + hc->checked_idx + 10; -+ -+ unlink(filename); -+ -+ ftruncate(tmp, sz); -+ p = mmap(NULL, sz, -+ PROT_READ|PROT_WRITE, MAP_PRIVATE, tmp, 0); -+ -+ if (p != MAP_FAILED) { -+ memcpy(p, hc->read_buf, hc->read_idx); -+ free(hc->read_buf); -+ hc->read_size = sz; -+ hc->read_buf = p; -+ hc->read_buf_is_mmap = 1; -+ } -+ close(tmp); -+ } -+ -+ if (!hc->read_buf_is_mmap) { -+ clear_connection( c, tvP, 0 ); -+ return; -+ } -+ } else { -+ httpd_realloc_str(&hc->read_buf, &hc->read_size, hc->checked_idx + hc->contentlength + 10); -+ } -+ -+ fdwatch_del_fd( hc->conn_fd ); -+ fdwatch_add_fd( hc->conn_fd, c, FDW_READ ); -+} -+ -+static void -+setup_sending(connecttab *c, int state, struct timeval *tvP) -+{ -+ httpd_conn *hc = c->hc; -+ ClientData client_data; -+ -+ c->conn_state = state; -+ c->started_at = tvP->tv_sec; -+ c->wouldblock_delay = 0; -+ client_data.p = c; -+ -+ fdwatch_del_fd( hc->conn_fd ); -+ fdwatch_add_fd( hc->conn_fd, c, FDW_WRITE ); -+} -+ -+static void handle_request( connecttab *c, struct timeval *tvP); -+ - - static void - handle_read( connecttab* c, struct timeval* tvP ) - { - int sz; -- ClientData client_data; - httpd_conn* hc = c->hc; - - /* Is there room in our buffer to read more bytes? */ -@@ -1311,7 +1418,7 @@ - if ( hc->read_size > 5000 ) - { - httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" ); -- clear_connection( c, tvP ); -+ clear_connection( c, tvP, 0 ); - return; - } - httpd_realloc_str( -@@ -1327,14 +1434,53 @@ - ** EWOULDBLOCK; however, this apparently can happen if a packet gets - ** garbled. - */ -- if ( sz == 0 || ( sz < 0 && ( errno != EWOULDBLOCK ) ) ) -- { -- httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" ); -- clear_connection( c, tvP ); -+ if ( sz == 0 ) { -+ if (! c->keep_alive) { -+ httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" ); -+ } -+ clear_connection( c, tvP, 0 ); - return; -+ } else if ( sz < 0 ) { -+ if (errno != EWOULDBLOCK) { -+ clear_connection( c, tvP, 0 ); -+ } -+ return; -+ } -+ -+ /* If this is a persistent PHP connection, we must not receive -+ ** any further requests on this connection. Some broken HTTP/1.1 -+ ** implementations (e.g. Mozilla 1.0.1) are known to do -+ ** pipelining on a connection, although a prior response included -+ ** Connection: close -+ */ -+ if (c->hc->file_address == (char *) 1) { -+ return; - } -- hc->read_idx += sz; -+ -+ c->last_io = httpd_time_now; -+ if (sz > 0) hc->read_idx += sz; -+ -+ /* -+ ** if we start getting new data on this socket, "promote" it -+ ** to read timeout -+ */ -+ if ( hc->keep_alive ) { -+ ClientData client_data; -+ - -+ client_data.p = c; -+ -+ hc->keep_alive = 0; -+ } -+ handle_request(c, tvP); -+ } -+ -+ -+static void -+handle_request( connecttab *c, struct timeval *tvP) -+{ -+ httpd_conn* hc = c->hc; -+ - /* Do we have a complete request yet? */ - switch ( httpd_got_request( hc ) ) - { -@@ -1342,14 +1488,14 @@ - return; - case GR_BAD_REQUEST: - httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" ); -- clear_connection( c, tvP ); -+ clear_connection( c, tvP, 0 ); - return; - } - - /* Yes. Try parsing and resolving it. */ - if ( httpd_parse_request( hc ) < 0 ) - { -- clear_connection( c, tvP ); -+ clear_connection( c, tvP, 0 ); - return; - } - -@@ -1358,18 +1504,28 @@ - { - httpd_send_err( - hc, 503, httpd_err503title, "", httpd_err503form, hc->encodedurl ); -- clear_connection( c, tvP ); -+ clear_connection( c, tvP, 0 ); - return; - } -+ boot_request(c, tvP); -+} - -+static void boot_request(connecttab *c, struct timeval *tvP) -+{ -+ httpd_conn *hc = c->hc; - /* Start the connection going. */ - if ( httpd_start_request( hc, tvP ) < 0 ) - { - /* Something went wrong. Close down the connection. */ -- clear_connection( c, tvP ); -+ clear_connection( c, tvP, 0 ); - return; - } - -+ if ( hc->read_body_into_mem ) { -+ setup_read_body( c, tvP ); -+ return; -+ } -+ - /* Fill in bytes_to_send. */ - if ( hc->got_range ) - { -@@ -1384,37 +1540,25 @@ - { - /* No file address means someone else is handling it. */ - c->bytes_sent = hc->bytes_sent; -- clear_connection( c, tvP ); -+ clear_connection( c, tvP, 1 ); - return; - } -+ if (hc->file_address == (char *) 1) { -+ c->last_io = (time_t) LONG_MAX; -+ c->wouldblock_delay = 0; -+ return; -+ } - if ( c->bytes_sent >= c->bytes_to_send ) - { - /* There's nothing to send. */ -- clear_connection( c, tvP ); -+ clear_connection( c, tvP, 1 ); - return; - } - - /* Cool, we have a valid connection and a file to send to it. */ -- c->conn_state = CNST_SENDING; -- c->started_at = tvP->tv_sec; -- c->wouldblock_delay = 0; -- client_data.p = c; -- tmr_cancel( c->idle_read_timer ); -- c->idle_read_timer = (Timer*) 0; -- c->idle_send_timer = tmr_create( -- tvP, idle_send_connection, client_data, IDLE_SEND_TIMELIMIT * 1000L, -- 0 ); -- if ( c->idle_send_timer == (Timer*) 0 ) -- { -- syslog( LOG_CRIT, "tmr_create(idle_send_connection) failed" ); -- exit( 1 ); -- } -- -- fdwatch_del_fd( hc->conn_fd ); -- fdwatch_add_fd( hc->conn_fd, c, FDW_WRITE ); -+ setup_sending(c, CNST_SENDING, tvP); - } - -- - static void - handle_send( connecttab* c, struct timeval* tvP ) - { -@@ -1443,6 +1587,9 @@ - iv[1].iov_base = &(hc->file_address[c->bytes_sent]); - iv[1].iov_len = MIN( c->bytes_to_send - c->bytes_sent, c->limit ); - sz = writev( hc->conn_fd, iv, 2 ); -+/* -+printf("**RESPONSE2 [%d]** len = %d\n%*.*s\n", hc->conn_fd, hc->responselen, hc->responselen, hc->responselen, hc->response); -+*/ - } - - if ( sz == 0 || -@@ -1486,12 +1633,12 @@ - */ - if ( errno != EPIPE && errno != EINVAL && errno != ECONNRESET ) - syslog( LOG_ERR, "write - %m sending %.80s", hc->encodedurl ); -- clear_connection( c, tvP ); -+ clear_connection( c, tvP, 0 ); - return; - } - - /* Ok, we wrote something. */ -- tmr_reset( tvP, c->idle_send_timer ); -+ c->last_io = httpd_time_now; - /* Was this a headers + file writev()? */ - if ( hc->responselen > 0 ) - { -@@ -1500,7 +1647,7 @@ - { - /* Yes; move the unwritten part to the front of the buffer. */ - int newlen = hc->responselen - sz; -- (void) memcpy( hc->response, &(hc->response[sz]), newlen ); -+ (void) memmove( hc->response, &(hc->response[sz]), newlen ); - hc->responselen = newlen; - sz = 0; - } -@@ -1519,7 +1666,7 @@ - if ( c->bytes_sent >= c->bytes_to_send ) - { - /* This conection is finished! */ -- clear_connection( c, tvP ); -+ clear_connection( c, tvP, 1 ); - return; - } - -@@ -1560,6 +1707,9 @@ - char buf[1024]; - int r; - -+/* -+printf("*LINGER read\n"); -+*/ - /* In lingering-close mode we just read and ignore bytes. An error - ** or EOF ends things, otherwise we go until a timeout. - */ -@@ -1569,6 +1719,61 @@ - } - - -+static void -+handle_read_body(connecttab *c, struct timeval *tvP) -+{ -+ httpd_conn *hc = c->hc; -+ int n; -+ -+ n = read(hc->conn_fd, hc->read_buf + hc->read_idx, -+ hc->contentlength - (hc->read_idx - hc->checked_idx)); -+ -+ if (n <= 0) { -+ if (errno == EAGAIN) -+ return; -+ clear_connection(c, tvP, 0); -+ return; -+ } -+ -+ hc->read_idx += n; -+ -+ if (hc->contentlength == hc->read_idx - hc->checked_idx) { -+ boot_request(c, tvP); -+ return; -+ } -+} -+ -+static void -+handle_send_resp(connecttab *c, struct timeval *tvP) -+{ -+ httpd_conn* hc = c->hc; -+ int n = send(hc->conn_fd, hc->response, hc->responselen, 0); -+ int dokeep = 1; -+ -+ if (n < 0) { -+ if (errno == EAGAIN) -+ return; -+ -+ dokeep = 0; -+ goto clear; -+ } -+ -+ c->last_io = httpd_time_now; -+ -+ if (n == hc->responselen) { -+clear: -+ hc->response = realloc(hc->response, hc->maxresponse + 1); -+ hc->responselen = 0; -+ -+ clear_connection(c, tvP, dokeep); -+ return; -+ } -+ -+ hc->responselen -= n; -+ -+ memmove(hc->response, hc->response + n, hc->responselen); -+} -+ - static int - check_throttles( connecttab* c ) - { -@@ -1635,23 +1840,18 @@ - - - static void --clear_connection( connecttab* c, struct timeval* tvP ) -+clear_connection( connecttab* c, struct timeval* tvP, int doKeep ) - { - ClientData client_data; -+ int linger; - - /* If we haven't actually sent the buffered response yet, do so now. */ -- httpd_write_response( c->hc ); -+ if (c->hc->responselen && c->conn_state != CNST_SENDING_RESP) { -+ setup_sending(c, CNST_SENDING_RESP, tvP); - -- if ( c->idle_read_timer != (Timer*) 0 ) -- { -- tmr_cancel( c->idle_read_timer ); -- c->idle_read_timer = 0; -- } -- if ( c->idle_send_timer != (Timer*) 0 ) -- { -- tmr_cancel( c->idle_send_timer ); -- c->idle_send_timer = 0; -+ return; - } -+ - if ( c->wakeup_timer != (Timer*) 0 ) - { - tmr_cancel( c->wakeup_timer ); -@@ -1669,13 +1869,36 @@ - ** circumstances that make a lingering close necessary. If the flag - ** isn't set we do the real close now. - */ -- if ( c->hc->should_linger ) -+ -+ if ( c->hc->do_keep_alive && doKeep) - { -- c->conn_state = CNST_LINGERING; -+ httpd_conn *hc = c->hc; -+ c->conn_state = CNST_READING; -+ -+ client_data.p = c; -+ c->bytes_sent = 0; -+ c->numtnums = 0; -+ c->keep_alive = 1; -+ -+ httpd_complete_request( c->hc, tvP, 1 ); -+ - fdwatch_del_fd( c->hc->conn_fd ); - fdwatch_add_fd( c->hc->conn_fd, c, FDW_READ ); -+ -+ httpd_request_reset( c->hc, 1 ); -+ -+ hc->read_idx -= hc->checked_idx; -+ memmove(hc->read_buf, hc->read_buf + hc->checked_idx, hc->read_idx); -+ hc->checked_idx = 0; -+ - /* Make sure we are still in no-delay mode. */ - httpd_set_ndelay( c->hc->conn_fd ); -+ handle_request(c, tvP); -+ } -+ else if ( c->hc->should_linger ) -+ { -+ c->conn_state = CNST_LINGERING; -+ - client_data.p = c; - c->linger_timer = tmr_create( - tvP, linger_clear_connection, client_data, LINGER_TIME * 1000L, 0 ); -@@ -1684,9 +1907,19 @@ - syslog( LOG_CRIT, "tmr_create(linger_clear_connection) failed" ); - exit( 1 ); - } -+ -+ httpd_complete_request( c->hc, tvP, 1 ); -+ -+ fdwatch_del_fd( c->hc->conn_fd ); -+ fdwatch_add_fd( c->hc->conn_fd, c, FDW_READ ); -+ /* Make sure we are still in no-delay mode. */ -+ httpd_set_ndelay( c->hc->conn_fd ); - } -- else -+ else -+ { -+ httpd_complete_request( c->hc, tvP, !c->keep_alive ); - really_clear_connection( c, tvP ); -+ } - } - - -@@ -1702,45 +1935,12 @@ - tmr_cancel( c->linger_timer ); - c->linger_timer = 0; - } -+ free_connects[next_free_connect++] = c; - c->conn_state = CNST_FREE; - --numconnects; - } - - --static void --idle_read_connection( ClientData client_data, struct timeval* nowP ) -- { -- connecttab* c; -- -- c = (connecttab*) client_data.p; -- c->idle_read_timer = (Timer*) 0; -- if ( c->conn_state != CNST_FREE ) -- { -- syslog( LOG_INFO, -- "%.80s connection timed out reading", -- httpd_ntoa( &c->hc->client_addr ) ); -- httpd_send_err( c->hc, 408, httpd_err408title, "", httpd_err408form, "" ); -- clear_connection( c, nowP ); -- } -- } -- -- --static void --idle_send_connection( ClientData client_data, struct timeval* nowP ) -- { -- connecttab* c; -- -- c = (connecttab*) client_data.p; -- c->idle_send_timer = (Timer*) 0; -- if ( c->conn_state != CNST_FREE ) -- { -- syslog( LOG_INFO, -- "%.80s connection timed out sending", -- httpd_ntoa( &c->hc->client_addr ) ); -- clear_connection( c, nowP ); -- } -- } -- - - static void - wakeup_connection( ClientData client_data, struct timeval* nowP ) -@@ -1826,3 +2026,41 @@ - stats_connections = stats_bytes = 0L; - stats_simultaneous = 0; - } -+ -+static void -+timeout_conns(ClientData client_data, struct timeval *nowP) -+{ -+ connecttab *c = connects, *ce = c + maxconnects; -+ time_t now = nowP->tv_sec; -+ int r = 0, w = 0; -+ int checked = 0; -+ -+ while (c < ce) { -+ switch (c->conn_state) { -+ case CNST_SENDING: -+ case CNST_SENDING_RESP: -+ checked++; -+ if ((now - c->last_io) > IDLE_SEND_TIMELIMIT) { -+ clear_connection( c, nowP, 0 ); -+ w++; -+ } -+ break; -+ case CNST_READING: -+ checked++; -+ if ((now - c->last_io) > IDLE_READ_TIMELIMIT) { -+ clear_connection( c, nowP, 0 ); -+ r++; -+ } -+ break; -+ case CNST_FREE: break; -+ default: checked++; break; -+ } -+ c++; -+ if (checked >= numconnects) break; -+ } -+ -+ if (r > 0 || w > 0) { -+ syslog(LOG_INFO, "Expired %d/%d connections in read/write state", r, w); -+ } -+} -+ |