1diff -ur thttpd-2.21b/Makefile.in thttpd-2.21b-cool/Makefile.in 2--- thttpd-2.21b/Makefile.in Thu Mar 29 20:36:21 2001 3+++ thttpd-2.21b-cool/Makefile.in Sat Sep 20 14:43:20 2003 4@@ -46,13 +46,15 @@ 5 6 # You shouldn't need to edit anything below here. 7 8+include php_makefile 9+ 10 CC = @CC@ 11 CCOPT = @V_CCOPT@ 12 DEFS = @DEFS@ 13-INCLS = -I. 14+INCLS = -I. $(PHP_CFLAGS) 15 CFLAGS = $(CCOPT) $(DEFS) $(INCLS) 16-LDFLAGS = @LDFLAGS@ 17-LIBS = @LIBS@ 18+LDFLAGS = @LDFLAGS@ $(PHP_LDFLAGS) 19+LIBS = @LIBS@ $(PHP_LIBS) 20 NETLIBS = @V_NETLIBS@ 21 INSTALL = @INSTALL@ 22 23@@ -62,7 +64,7 @@ 24 @rm -f $@ 25 $(CC) $(CFLAGS) -c $*.c 26 27-SRC = thttpd.c libhttpd.c fdwatch.c mmc.c timers.c match.c tdate_parse.c syslog.c 28+SRC = thttpd.c libhttpd.c fdwatch.c mmc.c timers.c match.c tdate_parse.c syslog.c php_thttpd.c 29 30 OBJ = $(SRC:.c=.o) @LIBOBJS@ 31 32@@ -77,7 +79,7 @@ 33 all: this subdirs 34 this: $(ALL) 35 36-thttpd: $(OBJ) 37+thttpd: $(OBJ) libphp5.a 38 @rm -f $@ 39 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(NETLIBS) 40 41diff -ur thttpd-2.21b/config.h thttpd-2.21b-cool/config.h 42--- thttpd-2.21b/config.h Mon Apr 9 23:57:36 2001 43+++ thttpd-2.21b-cool/config.h Sat Sep 20 14:43:20 2003 44@@ -82,6 +82,11 @@ 45 */ 46 #define IDLE_READ_TIMELIMIT 60 47 48+/* CONFIGURE: How many seconds to allow for reading the subsequent requests 49+** on a keep-alive connection. Should be simiar to LINGER_TIME 50+*/ 51+#define IDLE_KEEPALIVE_TIMELIMIT 2 52+ 53 /* CONFIGURE: How many seconds before an idle connection gets closed. 54 */ 55 #define IDLE_SEND_TIMELIMIT 300 56@@ -316,7 +321,7 @@ 57 /* CONFIGURE: A list of index filenames to check. The files are searched 58 ** for in this order. 59 */ 60-#define INDEX_NAMES "index.html", "index.htm", "Default.htm", "index.cgi" 61+#define INDEX_NAMES "index.php", "index.html", "index.htm", "Default.htm", "index.cgi" 62 63 /* CONFIGURE: If this is defined then thttpd will automatically generate 64 ** index pages for directories that don't have an explicit index file. 65diff -ur thttpd-2.21b/configure thttpd-2.21b-cool/configure 66--- thttpd-2.21b/configure Sat Apr 21 02:07:14 2001 67+++ thttpd-2.21b-cool/configure Sat Sep 20 14:43:20 2003 68@@ -1021,7 +1021,7 @@ 69 fi 70 echo "$ac_t""$CPP" 1>&6 71 72-for ac_hdr in fcntl.h grp.h memory.h paths.h poll.h sys/poll.h sys/event.h osreldate.h 73+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 74 do 75 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` 76 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 77diff -ur thttpd-2.21b/configure.in thttpd-2.21b-cool/configure.in 78--- thttpd-2.21b/configure.in Sat Apr 21 02:06:23 2001 79+++ thttpd-2.21b-cool/configure.in Sat Sep 20 14:43:20 2003 80@@ -64,7 +64,7 @@ 81 AC_MSG_RESULT(no) 82 fi 83 84-AC_CHECK_HEADERS(fcntl.h grp.h memory.h paths.h poll.h sys/poll.h sys/event.h osreldate.h) 85+AC_CHECK_HEADERS(fcntl.h grp.h memory.h paths.h poll.h sys/poll.h sys/event.h osreldate.h netinet/tcp.h) 86 AC_HEADER_TIME 87 AC_HEADER_DIRENT 88 89diff -ur thttpd-2.21b/fdwatch.c thttpd-2.21b-cool/fdwatch.c 90--- thttpd-2.21b/fdwatch.c Fri Apr 13 07:36:08 2001 91+++ thttpd-2.21b-cool/fdwatch.c Sat Sep 20 14:43:20 2003 92@@ -419,6 +419,7 @@ 93 if ( pollfds == (struct pollfd*) 0 || poll_fdidx == (int*) 0 || 94 poll_rfdidx == (int*) 0 ) 95 return -1; 96+ memset(pollfds, 0, sizeof(struct pollfd) * nfiles); 97 return 0; 98 } 99 100@@ -460,7 +461,7 @@ 101 102 ridx = 0; 103 for ( i = 0; i < npollfds; ++i ) 104- if ( pollfds[i].revents & ( POLLIN | POLLOUT ) ) 105+ if ( pollfds[i].revents & ( POLLIN | POLLOUT | POLLERR | POLLHUP | POLLNVAL ) ) 106 poll_rfdidx[ridx++] = pollfds[i].fd; 107 108 return r; 109@@ -472,8 +473,8 @@ 110 { 111 switch ( fd_rw[fd] ) 112 { 113- case FDW_READ: return pollfds[poll_fdidx[fd]].revents & POLLIN; 114- case FDW_WRITE: return pollfds[poll_fdidx[fd]].revents & POLLOUT; 115+ case FDW_READ: return pollfds[poll_fdidx[fd]].revents & ( POLLIN | POLLERR | POLLHUP | POLLNVAL ); 116+ case FDW_WRITE: return pollfds[poll_fdidx[fd]].revents & ( POLLOUT | POLLERR | POLLHUP | POLLNVAL ); 117 default: return 0; 118 } 119 } 120diff -ur thttpd-2.21b/libhttpd.c thttpd-2.21b-cool/libhttpd.c 121--- thttpd-2.21b/libhttpd.c Tue Apr 24 00:42:40 2001 122+++ thttpd-2.21b-cool/libhttpd.c Sat Sep 20 14:43:29 2003 123@@ -56,6 +56,10 @@ 124 #include <unistd.h> 125 #include <stdarg.h> 126 127+#ifdef HAVE_NETINET_TCP_H 128+#include <netinet/tcp.h> 129+#endif 130+ 131 #ifdef HAVE_OSRELDATE_H 132 #include <osreldate.h> 133 #endif /* HAVE_OSRELDATE_H */ 134@@ -85,6 +89,12 @@ 135 #include "match.h" 136 #include "tdate_parse.h" 137 138+#include "php_thttpd.h" 139+ 140+#ifdef __CYGWIN__ 141+# define timezone _timezone 142+#endif 143+ 144 #ifndef STDIN_FILENO 145 #define STDIN_FILENO 0 146 #endif 147@@ -111,7 +121,7 @@ 148 static int initialize_listen_socket( httpd_sockaddr* saP ); 149 static void unlisten( httpd_server* hs ); 150 static void add_response( httpd_conn* hc, char* str ); 151-static void send_mime( httpd_conn* hc, int status, char* title, char* encodings, char* extraheads, char* type, int length, time_t mod ); 152+static void send_mime( httpd_conn* hc, int status, char* title, char* encodings, char* extraheads, char* type, int length, time_t mod, const char *, size_t ); 153 static void send_response( httpd_conn* hc, int status, char* title, char* extraheads, char* form, char* arg ); 154 static void send_response_tail( httpd_conn* hc ); 155 static void defang( char* str, char* dfstr, int dfsize ); 156@@ -242,6 +252,10 @@ 157 free( (void*) hs->cwd ); 158 if ( hs->cgi_pattern != (char*) 0 ) 159 free( (void*) hs->cgi_pattern ); 160+ if ( hs->php_pattern != (char*) 0 ) 161+ free( (void*) hs->php_pattern ); 162+ if ( hs->phps_pattern != (char*) 0 ) 163+ free( (void*) hs->phps_pattern ); 164 if ( hs->charset != (char*) 0 ) 165 free( (void*) hs->charset ); 166 if ( hs->url_pattern != (char*) 0 ) 167@@ -249,6 +263,7 @@ 168 if ( hs->local_pattern != (char*) 0 ) 169 free( (void*) hs->local_pattern ); 170 free( (void*) hs ); 171+ thttpd_php_shutdown(); 172 } 173 174 175@@ -257,7 +272,8 @@ 176 char* hostname, httpd_sockaddr* sa4P, httpd_sockaddr* sa6P, int port, 177 char* cgi_pattern, char* charset, char* cwd, int no_log, FILE* logfp, 178 int no_symlink, int vhost, int global_passwd, char* url_pattern, 179- char* local_pattern, int no_empty_referers ) 180+ char* local_pattern, int no_empty_referers, char* php_pattern, 181+ char* phps_pattern ) 182 { 183 httpd_server* hs; 184 static char ghnbuf[256]; 185@@ -312,6 +328,8 @@ 186 } 187 188 hs->port = port; 189+ hs->php_pattern = strdup(php_pattern); 190+ hs->phps_pattern = strdup(phps_pattern); 191 if ( cgi_pattern == (char*) 0 ) 192 hs->cgi_pattern = (char*) 0; 193 else 194@@ -329,7 +347,7 @@ 195 while ( ( cp = strstr( hs->cgi_pattern, "|/" ) ) != (char*) 0 ) 196 (void) strcpy( cp + 1, cp + 2 ); 197 } 198- hs->charset = strdup( charset ); 199+ hs->charset = strdup( charset ); 200 hs->cwd = strdup( cwd ); 201 if ( hs->cwd == (char*) 0 ) 202 { 203@@ -385,6 +403,8 @@ 204 return (httpd_server*) 0; 205 } 206 207+ thttpd_php_init(); 208+ 209 /* Done initializing. */ 210 if ( hs->binding_hostname == (char*) 0 ) 211 syslog( LOG_INFO, "%.80s starting on port %d", SERVER_SOFTWARE, hs->port ); 212@@ -418,6 +438,11 @@ 213 } 214 (void) fcntl( listen_fd, F_SETFD, 1 ); 215 216+#if defined(TCP_DEFER_ACCEPT) && defined(SOL_TCP) 217+ on = 30; /* give clients 30s to send first data packet */ 218+ setsockopt(listen_fd, SOL_TCP, TCP_DEFER_ACCEPT, &on, sizeof(on)); 219+#endif 220+ 221 /* Allow reuse of local addresses. */ 222 on = 1; 223 if ( setsockopt( 224@@ -582,6 +607,9 @@ 225 /* And send it, if necessary. */ 226 if ( hc->responselen > 0 ) 227 { 228+/* 229+printf("**RESPONSE [%d]** len = %d\n%*.*s\n", hc->conn_fd, hc->responselen, hc->responselen, hc->responselen, hc->response); 230+*/ 231 (void) write( hc->conn_fd, hc->response, hc->responselen ); 232 hc->responselen = 0; 233 } 234@@ -619,18 +647,22 @@ 235 } 236 } 237 238+extern time_t httpd_time_now; 239+extern char httpd_now_buf[]; 240+ 241+#define SMART_STR_USE_REALLOC 242+ 243+#include "ext/standard/php_smart_str.h" 244 245 static void 246-send_mime( httpd_conn* hc, int status, char* title, char* encodings, char* extraheads, char* type, int length, time_t mod ) 247+send_mime( httpd_conn* hc, int status, char* title, char* encodings, char* extraheads, char* type, int length, time_t mod, const char *last_modified, size_t last_modified_len) 248 { 249- time_t now; 250 const char* rfc1123fmt = "%a, %d %b %Y %H:%M:%S GMT"; 251- char nowbuf[100]; 252 char modbuf[100]; 253- char fixed_type[500]; 254- char buf[1000]; 255 int partial_content; 256- 257+ smart_str s = {0}; 258+ int type_len; 259+ 260 hc->status = status; 261 hc->bytes_to_send = length; 262 if ( hc->mime_flag ) 263@@ -649,41 +681,89 @@ 264 else 265 partial_content = 0; 266 267- now = time( (time_t*) 0 ); 268 if ( mod == (time_t) 0 ) 269- mod = now; 270- (void) strftime( nowbuf, sizeof(nowbuf), rfc1123fmt, gmtime( &now ) ); 271- (void) strftime( modbuf, sizeof(modbuf), rfc1123fmt, gmtime( &mod ) ); 272- (void) my_snprintf( 273- fixed_type, sizeof(fixed_type), type, hc->hs->charset ); 274- (void) my_snprintf( buf, sizeof(buf), 275- "%.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", 276- hc->protocol, status, title, EXPOSED_SERVER_SOFTWARE, fixed_type, 277- nowbuf, modbuf ); 278- add_response( hc, buf ); 279+ mod = httpd_time_now; 280+ 281+ if (last_modified == 0) { 282+ (void) strftime( modbuf, sizeof(modbuf), rfc1123fmt, gmtime( &mod ) ); 283+ last_modified = modbuf; 284+ last_modified_len = strlen(modbuf); 285+ } 286+ 287+ type_len = strlen(type); 288+ 289+ if (hc->response) { 290+ s.c = hc->response; 291+ s.len = 0; 292+ s.a = hc->maxresponse; 293+ hc->response = 0; 294+ hc->maxresponse = 0; 295+ } 296+ 297+ smart_str_appends(&s, "HTTP/1.1 "); 298+ smart_str_append_long(&s, status); 299+ smart_str_appends(&s, " HTTP\r\nServer: " EXPOSED_SERVER_SOFTWARE "\r\n" 300+ "Content-Type: "); 301+ 302+ if (type[type_len-2] == '%' && type[type_len-1] == 's') { 303+ smart_str_appendl(&s, type, type_len - 2); 304+ smart_str_appends(&s, hc->hs->charset); 305+ } else { 306+ smart_str_appendl(&s, type, type_len); 307+ } 308+ 309+ 310+ smart_str_appends(&s, "\r\nDate: "); 311+ smart_str_appends(&s, httpd_now_buf); 312+ smart_str_appends(&s, "\r\nLast-Modified: "); 313+ smart_str_appendl(&s, last_modified, last_modified_len); 314+ smart_str_appends(&s, "\r\nAccept-Ranges: bytes\r\n"); 315+ 316 if ( encodings[0] != '\0' ) 317 { 318- (void) my_snprintf( buf, sizeof(buf), 319- "Content-Encoding: %s\r\n", encodings ); 320- add_response( hc, buf ); 321+ smart_str_appends(&s, "Content-Encoding: "); 322+ smart_str_appends(&s, encodings); 323+ smart_str_appends(&s, "\r\n"); 324 } 325 if ( partial_content ) 326 { 327- (void) my_snprintf( buf, sizeof(buf), 328- "Content-Range: bytes %ld-%ld/%d\r\nContent-Length: %ld\r\n", 329- (long) hc->init_byte_loc, (long) hc->end_byte_loc, length, 330- (long) ( hc->end_byte_loc - hc->init_byte_loc + 1 ) ); 331- add_response( hc, buf ); 332+ 333+ smart_str_appends(&s, "Content-Range: bytes "); 334+ smart_str_append_long(&s, hc->init_byte_loc); 335+ smart_str_appendc(&s, '-'); 336+ smart_str_append_long(&s, hc->end_byte_loc); 337+ smart_str_appendc(&s, '/'); 338+ smart_str_append_long(&s, length); 339+ smart_str_appends(&s, "\r\nContent-Length: "); 340+ smart_str_append_long(&s, hc->end_byte_loc - hc->init_byte_loc + 1); 341+ smart_str_appends(&s, "\r\n"); 342+ 343 } 344 else if ( length >= 0 ) 345 { 346- (void) my_snprintf( buf, sizeof(buf), 347- "Content-Length: %d\r\n", length ); 348- add_response( hc, buf ); 349+ smart_str_appends(&s, "Content-Length: "); 350+ smart_str_append_long(&s, length); 351+ smart_str_appends(&s, "\r\n"); 352 } 353+ else { 354+ hc->do_keep_alive = 0; 355+ } 356 if ( extraheads[0] != '\0' ) 357- add_response( hc, extraheads ); 358- add_response( hc, "\r\n" ); 359+ smart_str_appends(&s, extraheads); 360+ if (hc->do_keep_alive) { 361+ smart_str_appends(&s, "Connection: keep-alive\r\n\r\n" ); 362+ } else { 363+ smart_str_appends(&s, "Connection: close\r\n\r\n" ); 364+ } 365+ smart_str_0(&s); 366+ 367+ if (hc->response) { 368+ free(hc->response); 369+ } 370+ hc->response = s.c; 371+ hc->maxresponse = s.a; 372+ hc->responselen = s.len; 373+ 374 } 375 } 376 377@@ -725,7 +805,7 @@ 378 { 379 char defanged_arg[1000], buf[2000]; 380 381- send_mime( hc, status, title, "", extraheads, "text/html", -1, 0 ); 382+ send_mime( hc, status, title, "", extraheads, "text/html", -1, 0, 0, 0 ); 383 (void) my_snprintf( buf, sizeof(buf), 384 "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n<BODY BGCOLOR=\"#cc9999\"><H2>%d %s</H2>\n", 385 status, title, status, title ); 386@@ -764,7 +844,7 @@ 387 char* cp2; 388 389 for ( cp1 = str, cp2 = dfstr; 390- *cp1 != '\0' && cp2 - dfstr < dfsize - 1; 391+ *cp1 != '\0' && cp2 - dfstr < dfsize - 5; 392 ++cp1, ++cp2 ) 393 { 394 switch ( *cp1 ) 395@@ -834,7 +914,7 @@ 396 fp = fopen( filename, "r" ); 397 if ( fp == (FILE*) 0 ) 398 return 0; 399- send_mime( hc, status, title, "", extraheads, "text/html", -1, 0 ); 400+ send_mime( hc, status, title, "", extraheads, "text/html", -1, 0, 0, 0 ); 401 for (;;) 402 { 403 r = fread( buf, 1, sizeof(buf) - 1, fp ); 404@@ -1336,6 +1416,9 @@ 405 if ( hc->tildemapped ) 406 return 1; 407 408+ if ( hc->hostname[0] == '.' || strchr( hc->hostname, '/' ) != (char*) 0 ) 409+ return 0; 410+ 411 /* Figure out the host directory. */ 412 #ifdef VHOST_DIRLEVELS 413 httpd_realloc_str( 414@@ -1436,7 +1519,7 @@ 415 restlen = strlen( path ); 416 httpd_realloc_str( &rest, &maxrest, restlen ); 417 (void) strcpy( rest, path ); 418- if ( rest[restlen - 1] == '/' ) 419+ if ( restlen > 0 && rest[restlen - 1] == '/' ) 420 rest[--restlen] = '\0'; /* trim trailing slash */ 421 if ( ! tildemapped ) 422 /* Remove any leading slashes. */ 423@@ -1603,6 +1686,70 @@ 424 425 426 int 427+httpd_request_reset(httpd_conn* hc, int preserve_read_buf ) 428+{ 429+ if (!preserve_read_buf) { 430+ hc->read_idx = 0; 431+ hc->checked_idx = 0; 432+ } 433+ 434+ if (hc->read_buf_is_mmap) { 435+ hc->read_buf_is_mmap = 0; 436+ munmap(hc->read_buf, hc->read_size); 437+ hc->read_buf = NULL; 438+ hc->read_size = 0; 439+ httpd_realloc_str( &hc->read_buf, &hc->read_size, 500 ); 440+ } 441+ hc->checked_state = CHST_FIRSTWORD; 442+ hc->method = METHOD_UNKNOWN; 443+ hc->status = 0; 444+ hc->bytes_to_send = 0; 445+ hc->bytes_sent = 0; 446+ hc->encodedurl = ""; 447+ hc->decodedurl[0] = '\0'; 448+ hc->protocol = "UNKNOWN"; 449+ hc->origfilename[0] = '\0'; 450+ hc->expnfilename[0] = '\0'; 451+ hc->encodings[0] = '\0'; 452+ hc->pathinfo[0] = '\0'; 453+ hc->query[0] = '\0'; 454+ hc->referer = ""; 455+ hc->useragent = ""; 456+ hc->accept[0] = '\0'; 457+ hc->accepte[0] = '\0'; 458+ hc->acceptl = ""; 459+ hc->cookie = ""; 460+ hc->contenttype = ""; 461+ hc->reqhost[0] = '\0'; 462+ hc->hdrhost = ""; 463+ hc->hostdir[0] = '\0'; 464+ hc->authorization = ""; 465+ hc->remoteuser[0] = '\0'; 466+ hc->response[0] = '\0'; 467+#ifdef TILDE_MAP_2 468+ hc->altdir[0] = '\0'; 469+#endif /* TILDE_MAP_2 */ 470+ hc->responselen = 0; 471+ hc->if_modified_since = (time_t) -1; 472+ hc->range_if = (time_t) -1; 473+ hc->contentlength = -1; 474+ hc->type = ""; 475+ hc->hostname = (char*) 0; 476+ hc->mime_flag = 1; 477+ hc->one_one = 0; 478+ hc->got_range = 0; 479+ hc->tildemapped = 0; 480+ hc->init_byte_loc = 0; 481+ hc->end_byte_loc = -1; 482+ hc->keep_alive = 0; 483+ hc->do_keep_alive = 0; 484+ hc->should_linger = 0; 485+ hc->file_address = (char*) 0; 486+ hc->read_body_into_mem = 0; 487+ return GC_OK; 488+} 489+ 490+int 491 httpd_get_conn( httpd_server* hs, int listen_fd, httpd_conn* hc ) 492 { 493 httpd_sockaddr sa; 494@@ -1612,6 +1759,7 @@ 495 { 496 hc->read_size = 0; 497 httpd_realloc_str( &hc->read_buf, &hc->read_size, 500 ); 498+ hc->read_buf_is_mmap = 0; 499 hc->maxdecodedurl = 500 hc->maxorigfilename = hc->maxexpnfilename = hc->maxencodings = 501 hc->maxpathinfo = hc->maxquery = hc->maxaccept = 502@@ -1631,12 +1779,19 @@ 503 httpd_realloc_str( &hc->reqhost, &hc->maxreqhost, 0 ); 504 httpd_realloc_str( &hc->hostdir, &hc->maxhostdir, 0 ); 505 httpd_realloc_str( &hc->remoteuser, &hc->maxremoteuser, 0 ); 506- httpd_realloc_str( &hc->response, &hc->maxresponse, 0 ); 507+ httpd_realloc_str( &hc->response, &hc->maxresponse, 350 ); 508 #ifdef TILDE_MAP_2 509 httpd_realloc_str( &hc->altdir, &hc->maxaltdir, 0 ); 510 #endif /* TILDE_MAP_2 */ 511 hc->initialized = 1; 512 } 513+ if (hc->read_buf_is_mmap) { 514+ hc->read_buf_is_mmap = 0; 515+ munmap(hc->read_buf, hc->read_size); 516+ hc->read_buf = NULL; 517+ hc->read_size = 0; 518+ httpd_realloc_str( &hc->read_buf, &hc->read_size, 500 ); 519+ } 520 521 /* Accept the new connection. */ 522 sz = sizeof(sa); 523@@ -1657,53 +1812,12 @@ 524 hc->hs = hs; 525 memset( &hc->client_addr, 0, sizeof(hc->client_addr) ); 526 memcpy( &hc->client_addr, &sa, sockaddr_len( &sa ) ); 527- hc->read_idx = 0; 528- hc->checked_idx = 0; 529- hc->checked_state = CHST_FIRSTWORD; 530- hc->method = METHOD_UNKNOWN; 531- hc->status = 0; 532- hc->bytes_to_send = 0; 533- hc->bytes_sent = 0; 534- hc->encodedurl = ""; 535- hc->decodedurl[0] = '\0'; 536- hc->protocol = "UNKNOWN"; 537- hc->origfilename[0] = '\0'; 538- hc->expnfilename[0] = '\0'; 539- hc->encodings[0] = '\0'; 540- hc->pathinfo[0] = '\0'; 541- hc->query[0] = '\0'; 542- hc->referer = ""; 543- hc->useragent = ""; 544- hc->accept[0] = '\0'; 545- hc->accepte[0] = '\0'; 546- hc->acceptl = ""; 547- hc->cookie = ""; 548- hc->contenttype = ""; 549- hc->reqhost[0] = '\0'; 550- hc->hdrhost = ""; 551- hc->hostdir[0] = '\0'; 552- hc->authorization = ""; 553- hc->remoteuser[0] = '\0'; 554- hc->response[0] = '\0'; 555-#ifdef TILDE_MAP_2 556- hc->altdir[0] = '\0'; 557-#endif /* TILDE_MAP_2 */ 558- hc->responselen = 0; 559- hc->if_modified_since = (time_t) -1; 560- hc->range_if = (time_t) -1; 561- hc->contentlength = -1; 562- hc->type = ""; 563- hc->hostname = (char*) 0; 564- hc->mime_flag = 1; 565- hc->one_one = 0; 566- hc->got_range = 0; 567- hc->tildemapped = 0; 568- hc->init_byte_loc = 0; 569- hc->end_byte_loc = -1; 570- hc->keep_alive = 0; 571- hc->should_linger = 0; 572- hc->file_address = (char*) 0; 573- return GC_OK; 574+ 575+/* 576+printf("doing httpd_get_con(%d)\n", hc->conn_fd); 577+*/ 578+ 579+ return httpd_request_reset(hc, 0); 580 } 581 582 583@@ -1720,6 +1834,9 @@ 584 { 585 char c; 586 587+/* 588+printf("**REQUEST [%d]**\n%*.*s\n", hc->conn_fd, hc->read_idx, hc->read_idx, hc->read_buf); 589+*/ 590 for ( ; hc->checked_idx < hc->read_idx; ++hc->checked_idx ) 591 { 592 c = hc->read_buf[hc->checked_idx]; 593@@ -1912,8 +2029,11 @@ 594 eol = strpbrk( protocol, " \t\n\r" ); 595 if ( eol != (char*) 0 ) 596 *eol = '\0'; 597- if ( strcasecmp( protocol, "HTTP/1.0" ) != 0 ) 598+ if ( strcasecmp( protocol, "HTTP/1.0" ) != 0 ) { 599 hc->one_one = 1; 600+ hc->keep_alive = 1; 601+ hc->do_keep_alive = 1; 602+ } 603 } 604 } 605 /* Check for HTTP/1.1 absolute URL. */ 606@@ -2129,6 +2249,7 @@ 607 cp = &buf[11]; 608 cp += strspn( cp, " \t" ); 609 if ( strcasecmp( cp, "keep-alive" ) == 0 ) 610+ hc->do_keep_alive = 1; 611 hc->keep_alive = 1; 612 } 613 #ifdef LOG_UNKNOWN_HEADERS 614@@ -2168,6 +2289,9 @@ 615 } 616 } 617 618+/* 619+printf("one_one = %d keep_alive = %d\n", hc->one_one, hc->keep_alive); 620+*/ 621 if ( hc->one_one ) 622 { 623 /* Check that HTTP/1.1 requests specify a host, as required. */ 624@@ -2177,14 +2301,14 @@ 625 return -1; 626 } 627 628- /* If the client wants to do keep-alives, it might also be doing 629- ** pipelining. There's no way for us to tell. Since we don't 630- ** implement keep-alives yet, if we close such a connection there 631- ** might be unread pipelined requests waiting. So, we have to 632- ** do a lingering close. 633+ /* 634+ ** Disable keep alive support for bad browsers, 635+ ** list taken from Apache 1.3.19 636 */ 637- if ( hc->keep_alive ) 638- hc->should_linger = 1; 639+ if ( hc->do_keep_alive && 640+ ( strstr(hc->useragent, "Mozilla/2") != NULL || 641+ strstr(hc->useragent, "MSIE 4.0b2;") != NULL)) 642+ hc->do_keep_alive = 0; 643 } 644 645 /* Ok, the request has been parsed. Now we resolve stuff that 646@@ -2349,15 +2473,24 @@ 647 648 649 void 650-httpd_close_conn( httpd_conn* hc, struct timeval* nowP ) 651- { 652- make_log_entry( hc, nowP ); 653+httpd_complete_request( httpd_conn* hc, struct timeval* nowP) 654+{ 655+ if (hc->method != METHOD_UNKNOWN) 656+ make_log_entry( hc, nowP ); 657 658- if ( hc->file_address != (char*) 0 ) 659+ if ( hc->file_address == (char*) 1 ) 660+ { 661+ thttpd_closed_conn(hc->conn_fd); 662+ } else if ( hc->file_address != (char*) 0 ) 663 { 664 mmc_unmap( hc->file_address, &(hc->sb), nowP ); 665 hc->file_address = (char*) 0; 666 } 667+ } 668+ 669+void 670+httpd_close_conn( httpd_conn* hc, struct timeval* nowP ) 671+{ 672 if ( hc->conn_fd >= 0 ) 673 { 674 (void) close( hc->conn_fd ); 675@@ -2370,7 +2503,12 @@ 676 { 677 if ( hc->initialized ) 678 { 679- free( (void*) hc->read_buf ); 680+ 681+ if ( hc->read_buf_is_mmap ) { 682+ munmap( hc->read_buf, hc->read_size ); 683+ } else { 684+ free( (void*) hc->read_buf ); 685+ } 686 free( (void*) hc->decodedurl ); 687 free( (void*) hc->origfilename ); 688 free( (void*) hc->expnfilename ); 689@@ -2556,7 +2694,7 @@ 690 return -1; 691 } 692 693- send_mime( hc, 200, ok200title, "", "", "text/html", -1, hc->sb.st_mtime ); 694+ send_mime( hc, 200, ok200title, "", "", "text/html", -1, hc->sb.st_mtime, 0, 0 ); 695 if ( hc->method == METHOD_HEAD ) 696 closedir( dirp ); 697 else if ( hc->method == METHOD_GET ) 698@@ -3026,11 +3164,9 @@ 699 post_post_garbage_hack( httpd_conn* hc ) 700 { 701 char buf[2]; 702- int r; 703 704- r = recv( hc->conn_fd, buf, sizeof(buf), MSG_PEEK ); 705- if ( r > 0 ) 706- (void) read( hc->conn_fd, buf, r ); 707+ fcntl(hc->conn_fd, F_SETFL, O_NONBLOCK); 708+ (void) read( hc->conn_fd, buf, 2 ); 709 } 710 711 712@@ -3313,6 +3449,11 @@ 713 int r; 714 ClientData client_data; 715 716+ /* 717+ ** We are not going to leave the socket open after a CGI... too hard 718+ */ 719+ hc->do_keep_alive = 0; 720+ 721 if ( hc->method == METHOD_GET || hc->method == METHOD_POST ) 722 { 723 httpd_clear_ndelay( hc->conn_fd ); 724@@ -3369,6 +3510,7 @@ 725 int expnlen, indxlen; 726 char* cp; 727 char* pi; 728+ int nocache = 0; 729 730 expnlen = strlen( hc->expnfilename ); 731 732@@ -3561,6 +3703,16 @@ 733 match( hc->hs->cgi_pattern, hc->expnfilename ) ) 734 return cgi( hc ); 735 736+ if ( hc->hs->php_pattern != (char*) 0 && 737+ match( hc->hs->php_pattern, hc->expnfilename)) { 738+ return thttpd_php_request( hc, 0 ); 739+ } 740+ 741+ if ( hc->hs->phps_pattern != (char*) 0 && 742+ match( hc->hs->phps_pattern, hc->expnfilename)) { 743+ return thttpd_php_request( hc, 1 ); 744+ } 745+ 746 /* It's not CGI. If it's executable or there's pathinfo, someone's 747 ** trying to either serve or run a non-CGI file as CGI. Either case 748 ** is prohibited. 749@@ -3594,32 +3746,46 @@ 750 hc->end_byte_loc = hc->sb.st_size - 1; 751 752 figure_mime( hc ); 753+ if ( strncmp(hc->decodedurl, "/nocache/", sizeof("/nocache/") - 1 ) == 0 ) 754+ nocache = 1; 755 756 if ( hc->method == METHOD_HEAD ) 757 { 758 send_mime( 759 hc, 200, ok200title, hc->encodings, "", hc->type, hc->sb.st_size, 760- hc->sb.st_mtime ); 761+ hc->sb.st_mtime, 0, 0 ); 762 } 763- else if ( hc->if_modified_since != (time_t) -1 && 764+ else if ( !nocache && hc->if_modified_since != (time_t) -1 && 765 hc->if_modified_since >= hc->sb.st_mtime ) 766 { 767- hc->method = METHOD_HEAD; 768 send_mime( 769- hc, 304, err304title, hc->encodings, "", hc->type, hc->sb.st_size, 770- hc->sb.st_mtime ); 771+ hc, 304, err304title, hc->encodings, "", hc->type, -1, 772+ hc->sb.st_mtime, 0, 0 ); 773 } 774 else 775 { 776- hc->file_address = mmc_map( hc->expnfilename, &(hc->sb), nowP ); 777+ char *extraheads = ""; 778+ char *lm; 779+ size_t lml; 780+ 781+ if ( nocache ) 782+ { 783+ extraheads = "Expires: Thu, 19 Nov 1981 08:52:00 GMT\r\n" 784+ "Cache-Control: no-store, no-cache, must-revalidate, " 785+ "post-check=0, pre-check=0\r\n" 786+ "Pragma: no-cache\r\n"; 787+ } 788+ 789+ hc->file_address = mmc_map( hc->expnfilename, &(hc->sb), nowP, nocache, &lm, &lml ); 790 if ( hc->file_address == (char*) 0 ) 791 { 792 httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl ); 793 return -1; 794 } 795+ 796 send_mime( 797- hc, 200, ok200title, hc->encodings, "", hc->type, hc->sb.st_size, 798- hc->sb.st_mtime ); 799+ hc, 200, ok200title, hc->encodings, extraheads, hc->type, hc->sb.st_size, 800+ hc->sb.st_mtime, lm, lml ); 801 } 802 803 return 0; 804@@ -3638,6 +3804,9 @@ 805 return r; 806 } 807 808+#define smart_str_append_const(a,b) smart_str_appendl(a,b,sizeof(b)-1) 809+ 810+static smart_str bentries; 811 812 static void 813 make_log_entry( httpd_conn* hc, struct timeval* nowP ) 814@@ -3648,88 +3817,62 @@ 815 816 if ( hc->hs->no_log ) 817 return; 818- 819- /* This is straight CERN Combined Log Format - the only tweak 820- ** being that if we're using syslog() we leave out the date, because 821- ** syslogd puts it in. The included syslogtocern script turns the 822- ** results into true CERN format. 823- */ 824- 825 /* Format remote user. */ 826 if ( hc->remoteuser[0] != '\0' ) 827- ru = hc->remoteuser; 828+ ru = hc->remoteuser; 829 else 830- ru = "-"; 831+ ru = "-"; 832 /* If we're vhosting, prepend the hostname to the url. This is 833 ** a little weird, perhaps writing separate log files for 834 ** each vhost would make more sense. 835 */ 836- if ( hc->hs->vhost && ! hc->tildemapped ) 837- (void) my_snprintf( url, sizeof(url), 838- "/%.100s%.200s", 839- hc->hostname == (char*) 0 ? hc->hs->server_hostname : hc->hostname, 840- hc->encodedurl ); 841- else 842- (void) my_snprintf( url, sizeof(url), 843- "%.200s", hc->encodedurl ); 844- /* Format the bytes. */ 845- if ( (long) hc->bytes_sent >= 0 ) 846- (void) my_snprintf( bytes, sizeof(bytes), 847- "%ld", (long) hc->bytes_sent ); 848- else 849- (void) strcpy( bytes, "-" ); 850 851 /* Logfile or syslog? */ 852 if ( hc->hs->logfp != (FILE*) 0 ) 853- { 854- time_t now; 855- struct tm* t; 856- const char* cernfmt_nozone = "%d/%b/%Y:%H:%M:%S"; 857- char date_nozone[100]; 858- int zone; 859- char sign; 860- char date[100]; 861- 862- /* Get the current time, if necessary. */ 863- if ( nowP != (struct timeval*) 0 ) 864- now = nowP->tv_sec; 865- else 866- now = time( (time_t*) 0 ); 867- /* Format the time, forcing a numeric timezone (some log analyzers 868- ** are stoooopid about this). 869- */ 870- t = localtime( &now ); 871- (void) strftime( date_nozone, sizeof(date_nozone), cernfmt_nozone, t ); 872-#ifdef HAVE_TM_GMTOFF 873- zone = t->tm_gmtoff / 60L; 874-#else 875- zone = -timezone / 60L; 876- /* Probably have to add something about daylight time here. */ 877-#endif 878- if ( zone >= 0 ) 879- sign = '+'; 880- else 881- { 882- sign = '-'; 883- zone = -zone; 884- } 885- zone = ( zone / 60 ) * 100 + zone % 60; 886- (void) my_snprintf( date, sizeof(date), 887- "%s %c%04d", date_nozone, sign, zone ); 888- /* And write the log entry. */ 889- (void) fprintf( hc->hs->logfp, 890- "%.80s - %.80s [%s] \"%.80s %.300s %.80s\" %d %s \"%.200s\" \"%.80s\"\n", 891- httpd_ntoa( &hc->client_addr ), ru, date, 892- httpd_method_str( hc->method ), url, hc->protocol, 893- hc->status, bytes, hc->referer, hc->useragent ); 894- (void) fflush( hc->hs->logfp ); /* don't need to flush every time */ 895- } 896- else 897- syslog( LOG_INFO, 898- "%.80s - %.80s \"%.80s %.200s %.80s\" %d %s \"%.200s\" \"%.80s\"", 899- httpd_ntoa( &hc->client_addr ), ru, 900- httpd_method_str( hc->method ), url, hc->protocol, 901- hc->status, bytes, hc->referer, hc->useragent ); 902+ { 903+ /* XXXXXXX */ 904+ 905+ smart_str_appends(&bentries, httpd_ntoa(&hc->client_addr)); 906+ smart_str_append_const(&bentries, " - "); 907+ smart_str_appends(&bentries, ru); 908+ smart_str_append_const(&bentries, " ["); 909+ smart_str_appendl(&bentries, hc->hs->log_date, hc->hs->log_date_len); 910+ smart_str_append_const(&bentries, "] \""); 911+ smart_str_appends(&bentries, httpd_method_str(hc->method)); 912+ smart_str_appendc(&bentries, ' '); 913+ 914+ if (hc->hs->vhost && ! hc->tildemapped) { 915+ smart_str_appendc(&bentries, '/'); 916+ if (hc->hostname) 917+ smart_str_appends(&bentries, hc->hostname); 918+ else 919+ smart_str_appends(&bentries, hc->hs->server_hostname); 920+ } 921+ smart_str_appends(&bentries, hc->encodedurl); 922+ 923+ smart_str_appendc(&bentries, ' '); 924+ smart_str_appends(&bentries, hc->protocol); 925+ smart_str_append_const(&bentries, "\" "); 926+ smart_str_append_long(&bentries, hc->status); 927+ if (hc->bytes_sent >= 0) { 928+ smart_str_appendc(&bentries, ' '); 929+ smart_str_append_long(&bentries, hc->bytes_sent); 930+ smart_str_append_const(&bentries, " \""); 931+ } else { 932+ smart_str_append_const(&bentries, " - \""); 933+ } 934+ smart_str_appends(&bentries, hc->referer); 935+ smart_str_append_const(&bentries, "\" \""); 936+ smart_str_appends(&bentries, hc->useragent); 937+ smart_str_append_const(&bentries, "\"\n"); 938+ 939+ if (bentries.len > 16384) { 940+ int fd = fileno(hc->hs->logfp); 941+ write(fd, bentries.c, bentries.len); 942+ bentries.len = 0; 943+ } 944+ } 945+ 946 } 947 948 949@@ -3840,7 +3983,24 @@ 950 { 951 #ifdef HAVE_GETNAMEINFO 952 static char str[200]; 953+ static smart_str httpd_ntoa_buf; 954+ 955+ if (saP->sa_in.sin_family == AF_INET) { 956+ unsigned long n = ntohl(saP->sa_in.sin_addr.s_addr); 957 958+ httpd_ntoa_buf.len = 0; 959+ smart_str_append_long(&httpd_ntoa_buf, (n >> 24)); 960+ smart_str_appendc(&httpd_ntoa_buf, '.'); 961+ smart_str_append_long(&httpd_ntoa_buf, (n >> 16) & 255); 962+ smart_str_appendc(&httpd_ntoa_buf, '.'); 963+ smart_str_append_long(&httpd_ntoa_buf, (n >> 8) & 255); 964+ smart_str_appendc(&httpd_ntoa_buf, '.'); 965+ smart_str_append_long(&httpd_ntoa_buf, (n >> 0) & 255); 966+ smart_str_0(&httpd_ntoa_buf); 967+ 968+ return httpd_ntoa_buf.c; 969+ } 970+ 971 if ( getnameinfo( &saP->sa, sockaddr_len( saP ), str, sizeof(str), 0, 0, NI_NUMERICHOST ) != 0 ) 972 { 973 str[0] = '?'; 974diff -ur thttpd-2.21b/libhttpd.h thttpd-2.21b-cool/libhttpd.h 975--- thttpd-2.21b/libhttpd.h Tue Apr 24 00:36:50 2001 976+++ thttpd-2.21b-cool/libhttpd.h Sat Sep 20 14:43:20 2003 977@@ -69,6 +69,8 @@ 978 char* server_hostname; 979 int port; 980 char* cgi_pattern; 981+ char* php_pattern; 982+ char* phps_pattern; 983 char* charset; 984 char* cwd; 985 int listen4_fd, listen6_fd; 986@@ -80,6 +82,8 @@ 987 char* url_pattern; 988 char* local_pattern; 989 int no_empty_referers; 990+ size_t log_date_len; 991+ char log_date[100]; 992 } httpd_server; 993 994 /* A connection. */ 995@@ -88,6 +92,7 @@ 996 httpd_server* hs; 997 httpd_sockaddr client_addr; 998 char* read_buf; 999+ char read_buf_is_mmap; 1000 int read_size, read_idx, checked_idx; 1001 int checked_state; 1002 int method; 1003@@ -132,11 +137,12 @@ 1004 int got_range; 1005 int tildemapped; /* this connection got tilde-mapped */ 1006 off_t init_byte_loc, end_byte_loc; 1007- int keep_alive; 1008+ int keep_alive, do_keep_alive; 1009 int should_linger; 1010 struct stat sb; 1011 int conn_fd; 1012 char* file_address; 1013+ char read_body_into_mem; 1014 } httpd_conn; 1015 1016 /* Methods. */ 1017@@ -168,7 +174,8 @@ 1018 char* hostname, httpd_sockaddr* sa4P, httpd_sockaddr* sa6P, int port, 1019 char* cgi_pattern, char* charset, char* cwd, int no_log, FILE* logfp, 1020 int no_symlink, int vhost, int global_passwd, char* url_pattern, 1021- char* local_pattern, int no_empty_referers ); 1022+ char* local_pattern, int no_empty_referers, char* php_pattern, 1023+ char* phps_pattern ); 1024 1025 /* Change the log file. */ 1026 extern void httpd_set_logfp( httpd_server* hs, FILE* logfp ); 1027@@ -229,6 +236,8 @@ 1028 ** If you don't have a current timeval handy just pass in 0. 1029 */ 1030 extern void httpd_close_conn( httpd_conn* hc, struct timeval* nowP ); 1031+void httpd_complete_request( httpd_conn* hc, struct timeval* nowP); 1032+int httpd_request_reset(httpd_conn* hc,int ); 1033 1034 /* Call this to de-initialize a connection struct and *really* free the 1035 ** mallocced strings. 1036diff -ur thttpd-2.21b/mime_encodings.txt thttpd-2.21b-cool/mime_encodings.txt 1037--- thttpd-2.21b/mime_encodings.txt Wed May 10 03:22:28 2000 1038+++ thttpd-2.21b-cool/mime_encodings.txt Sat Sep 20 14:43:20 2003 1039@@ -3,6 +3,6 @@ 1040 # A list of file extensions followed by the corresponding MIME encoding. 1041 # Extensions not found in the table proceed to the mime_types table. 1042 1043-Z x-compress 1044-gz x-gzip 1045+Z compress 1046+gz gzip 1047 uu x-uuencode 1048diff -ur thttpd-2.21b/mime_types.txt thttpd-2.21b-cool/mime_types.txt 1049--- thttpd-2.21b/mime_types.txt Sat Apr 14 04:53:30 2001 1050+++ thttpd-2.21b-cool/mime_types.txt Sat Sep 20 14:43:20 2003 1051@@ -1,135 +1,138 @@ 1052-# mime_types.txt 1053-# 1054-# A list of file extensions followed by the corresponding MIME type. 1055-# Extensions not found in the table are returned as text/plain. 1056- 1057-html text/html; charset=%s 1058-htm text/html; charset=%s 1059-txt text/plain; charset=%s 1060-rtx text/richtext 1061-etx text/x-setext 1062-tsv text/tab-separated-values 1063-css text/css 1064-xml text/xml 1065-dtd text/xml 1066- 1067-gif image/gif 1068-jpg image/jpeg 1069-jpeg image/jpeg 1070-jpe image/jpeg 1071-jfif image/jpeg 1072-tif image/tiff 1073-tiff image/tiff 1074-pbm image/x-portable-bitmap 1075-pgm image/x-portable-graymap 1076-ppm image/x-portable-pixmap 1077-pnm image/x-portable-anymap 1078-xbm image/x-xbitmap 1079-xpm image/x-xpixmap 1080-xwd image/x-xwindowdump 1081-ief image/ief 1082-png image/png 1083- 1084-au audio/basic 1085-snd audio/basic 1086-aif audio/x-aiff 1087-aiff audio/x-aiff 1088-aifc audio/x-aiff 1089-ra audio/x-pn-realaudio 1090-ram audio/x-pn-realaudio 1091-rm audio/x-pn-realaudio 1092-rpm audio/x-pn-realaudio-plugin 1093-wav audio/wav 1094-mid audio/midi 1095-midi audio/midi 1096-kar audio/midi 1097-mpga audio/mpeg 1098-mp2 audio/mpeg 1099-mp3 audio/mpeg 1100- 1101-mpeg video/mpeg 1102-mpg video/mpeg 1103-mpe video/mpeg 1104-qt video/quicktime 1105-mov video/quicktime 1106-avi video/x-msvideo 1107-movie video/x-sgi-movie 1108-mv video/x-sgi-movie 1109-vx video/x-rad-screenplay 1110- 1111-a application/octet-stream 1112+ez application/andrew-inset 1113+hqx application/mac-binhex40 1114+cpt application/mac-compactpro 1115+doc application/msword 1116 bin application/octet-stream 1117+dms application/octet-stream 1118+lha application/octet-stream 1119+lzh application/octet-stream 1120 exe application/octet-stream 1121-dump application/octet-stream 1122-o application/octet-stream 1123-class application/java 1124-js application/x-javascript 1125+class application/octet-stream 1126+so application/octet-stream 1127+dll application/octet-stream 1128+oda application/oda 1129+pdf application/pdf 1130 ai application/postscript 1131 eps application/postscript 1132 ps application/postscript 1133-dir application/x-director 1134+smi application/smil 1135+smil application/smil 1136+mif application/vnd.mif 1137+xls application/vnd.ms-excel 1138+ppt application/vnd.ms-powerpoint 1139+wbxml application/vnd.wap.wbxml 1140+wmlc application/vnd.wap.wmlc 1141+wmlsc application/vnd.wap.wmlscriptc 1142+bcpio application/x-bcpio 1143+vcd application/x-cdlink 1144+pgn application/x-chess-pgn 1145+cpio application/x-cpio 1146+csh application/x-csh 1147 dcr application/x-director 1148+dir application/x-director 1149 dxr application/x-director 1150-fgd application/x-director 1151-aam application/x-authorware-map 1152-aas application/x-authorware-seg 1153-aab application/x-authorware-bin 1154-fh4 image/x-freehand 1155-fh7 image/x-freehand 1156-fh5 image/x-freehand 1157-fhc image/x-freehand 1158-fh image/x-freehand 1159-spl application/futuresplash 1160-swf application/x-shockwave-flash 1161 dvi application/x-dvi 1162+spl application/x-futuresplash 1163 gtar application/x-gtar 1164 hdf application/x-hdf 1165-hqx application/mac-binhex40 1166-iv application/x-inventor 1167+js application/x-javascript 1168+skp application/x-koan 1169+skd application/x-koan 1170+skt application/x-koan 1171+skm application/x-koan 1172 latex application/x-latex 1173-man application/x-troff-man 1174-me application/x-troff-me 1175-mif application/x-mif 1176-ms application/x-troff-ms 1177-oda application/oda 1178-pdf application/pdf 1179-rtf application/rtf 1180-bcpio application/x-bcpio 1181-cpio application/x-cpio 1182-sv4cpio application/x-sv4cpio 1183-sv4crc application/x-sv4crc 1184-sh application/x-shar 1185+nc application/x-netcdf 1186+cdf application/x-netcdf 1187+sh application/x-sh 1188 shar application/x-shar 1189+swf application/x-shockwave-flash 1190 sit application/x-stuffit 1191+sv4cpio application/x-sv4cpio 1192+sv4crc application/x-sv4crc 1193 tar application/x-tar 1194+tcl application/x-tcl 1195 tex application/x-tex 1196-texi application/x-texinfo 1197 texinfo application/x-texinfo 1198+texi application/x-texinfo 1199+t application/x-troff 1200 tr application/x-troff 1201 roff application/x-troff 1202 man application/x-troff-man 1203 me application/x-troff-me 1204 ms application/x-troff-ms 1205-zip application/x-zip-compressed 1206-tsp application/dsptype 1207-wsrc application/x-wais-source 1208 ustar application/x-ustar 1209-cdf application/x-netcdf 1210-nc application/x-netcdf 1211-doc application/msword 1212-ppt application/powerpoint 1213- 1214-crt application/x-x509-ca-cert 1215-crl application/x-pkcs7-crl 1216- 1217+src application/x-wais-source 1218+xhtml application/xhtml+xml 1219+xht application/xhtml+xml 1220+zip application/zip 1221+au audio/basic 1222+snd audio/basic 1223+mid audio/midi 1224+midi audio/midi 1225+kar audio/midi 1226+mpga audio/mpeg 1227+mp2 audio/mpeg 1228+mp3 audio/mpeg 1229+aif audio/x-aiff 1230+aiff audio/x-aiff 1231+aifc audio/x-aiff 1232+m3u audio/x-mpegurl 1233+ram audio/x-pn-realaudio 1234+rm audio/x-pn-realaudio 1235+rpm audio/x-pn-realaudio-plugin 1236+ra audio/x-realaudio 1237+wav audio/x-wav 1238+pdb chemical/x-pdb 1239+xyz chemical/x-xyz 1240+bmp image/bmp 1241+gif image/gif 1242+ief image/ief 1243+jpeg image/jpeg 1244+jpg image/jpeg 1245+jpe image/jpeg 1246+png image/png 1247+tiff image/tiff 1248+tif image/tiff 1249+djvu image/vnd.djvu 1250+djv image/vnd.djvu 1251+wbmp image/vnd.wap.wbmp 1252+ras image/x-cmu-raster 1253+pnm image/x-portable-anymap 1254+pbm image/x-portable-bitmap 1255+pgm image/x-portable-graymap 1256+ppm image/x-portable-pixmap 1257+rgb image/x-rgb 1258+xbm image/x-xbitmap 1259+xpm image/x-xpixmap 1260+xwd image/x-xwindowdump 1261+igs model/iges 1262+iges model/iges 1263+msh model/mesh 1264+mesh model/mesh 1265+silo model/mesh 1266 wrl model/vrml 1267 vrml model/vrml 1268-mime message/rfc822 1269- 1270-pac application/x-ns-proxy-autoconfig 1271- 1272+css text/css 1273+html text/html; charset=%s 1274+htm text/html; charset=%s 1275+asc text/plain; charset=%s 1276+txt text/plain; charset=%s 1277+rtx text/richtext 1278+rtf text/rtf 1279+sgml text/sgml 1280+sgm text/sgml 1281+tsv text/tab-separated-values 1282 wml text/vnd.wap.wml 1283-wmlc application/vnd.wap.wmlc 1284 wmls text/vnd.wap.wmlscript 1285-wmlsc application/vnd.wap.wmlscriptc 1286-wbmp image/vnd.wap.wbmp 1287+etx text/x-setext 1288+xml text/xml 1289+xsl text/xml 1290+mpeg video/mpeg 1291+mpg video/mpeg 1292+mpe video/mpeg 1293+qt video/quicktime 1294+mov video/quicktime 1295+mxu video/vnd.mpegurl 1296+avi video/x-msvideo 1297+movie video/x-sgi-movie 1298+ice x-conference/x-cooltalk 1299diff -ur thttpd-2.21b/mmc.c thttpd-2.21b-cool/mmc.c 1300--- thttpd-2.21b/mmc.c Fri Apr 13 23:02:15 2001 1301+++ thttpd-2.21b-cool/mmc.c Sat Sep 20 14:43:20 2003 1302@@ -70,6 +70,9 @@ 1303 unsigned int hash; 1304 int hash_idx; 1305 struct MapStruct* next; 1306+ char nocache; 1307+ size_t last_modified_len; 1308+ char last_modified[100]; 1309 } Map; 1310 1311 1312@@ -93,12 +96,13 @@ 1313 1314 1315 void* 1316-mmc_map( char* filename, struct stat* sbP, struct timeval* nowP ) 1317+mmc_map( char* filename, struct stat* sbP, struct timeval* nowP, int nocache, char **last_modified, size_t *last_modified_len ) 1318 { 1319 time_t now; 1320 struct stat sb; 1321 Map* m; 1322 int fd; 1323+ const char* rfc1123fmt = "%a, %d %b %Y %H:%M:%S GMT"; 1324 1325 /* Stat the file, if necessary. */ 1326 if ( sbP != (struct stat*) 0 ) 1327@@ -130,7 +134,7 @@ 1328 /* Yep. Just return the existing map */ 1329 ++m->refcount; 1330 m->reftime = now; 1331- return m->addr; 1332+ goto done; 1333 } 1334 1335 /* Open the file. */ 1336@@ -167,12 +171,13 @@ 1337 m->ctime = sb.st_ctime; 1338 m->refcount = 1; 1339 m->reftime = now; 1340+ m->nocache = (char) nocache; 1341 1342 /* Avoid doing anything for zero-length files; some systems don't like 1343 ** to mmap them, other systems dislike mallocing zero bytes. 1344 */ 1345 if ( m->size == 0 ) 1346- m->addr = (void*) 1; /* arbitrary non-NULL address */ 1347+ m->addr = (void*) 5; /* arbitrary non-NULL address */ 1348 else 1349 { 1350 #ifdef HAVE_MMAP 1351@@ -223,6 +228,13 @@ 1352 maps = m; 1353 ++map_count; 1354 1355+ strftime( m->last_modified, sizeof(m->last_modified), rfc1123fmt, gmtime( &sb.st_mtime ) ); 1356+ m->last_modified_len = strlen(m->last_modified); 1357+ 1358+done: 1359+ *last_modified = m->last_modified; 1360+ *last_modified_len = m->last_modified_len; 1361+ 1362 /* And return the address. */ 1363 return m->addr; 1364 } 1365@@ -231,27 +243,32 @@ 1366 void 1367 mmc_unmap( void* addr, struct stat* sbP, struct timeval* nowP ) 1368 { 1369- Map* m = (Map*) 0; 1370+ Map* m = (Map*) 0, **mm = &maps; 1371 1372 /* Find the Map entry for this address. First try a hash. */ 1373 if ( sbP != (struct stat*) 0 ) 1374 { 1375 m = find_hash( sbP->st_ino, sbP->st_dev, sbP->st_size, sbP->st_ctime ); 1376- if ( m != (Map*) 0 && m->addr != addr ) 1377+ if ( m != (Map*) 0 && ( m->addr != addr || m->nocache == 1 ) ) 1378 m = (Map*) 0; 1379 } 1380 /* If that didn't work, try a full search. */ 1381 if ( m == (Map*) 0 ) 1382- for ( m = maps; m != (Map*) 0; m = m->next ) 1383+ for ( m = maps; m != (Map*) 0; m = m->next ) { 1384 if ( m->addr == addr ) 1385 break; 1386+ mm = &m->next; 1387+ } 1388 if ( m == (Map*) 0 ) 1389 syslog( LOG_ERR, "mmc_unmap failed to find entry!" ); 1390 else if ( m->refcount <= 0 ) 1391 syslog( LOG_ERR, "mmc_unmap found zero or negative refcount!" ); 1392 else 1393 { 1394- --m->refcount; 1395+ if ( --m->refcount == 0 && m->nocache == 1 ) { 1396+ really_unmap( mm ); 1397+ return; 1398+ } 1399 if ( nowP != (struct timeval*) 0 ) 1400 m->reftime = nowP->tv_sec; 1401 else 1402diff -ur thttpd-2.21b/mmc.h thttpd-2.21b-cool/mmc.h 1403--- thttpd-2.21b/mmc.h Fri Apr 13 07:36:54 2001 1404+++ thttpd-2.21b-cool/mmc.h Sat Sep 20 14:43:20 2003 1405@@ -31,8 +31,9 @@ 1406 /* Returns an mmap()ed area for the given file, or (void*) 0 on errors. 1407 ** If you have a stat buffer on the file, pass it in, otherwise pass 0. 1408 ** Same for the current time. 1409+** Set nocache to 1, if this entry is supposed to be removed quickly. 1410 */ 1411-extern void* mmc_map( char* filename, struct stat* sbP, struct timeval* nowP ); 1412+extern void* mmc_map( char* filename, struct stat* sbP, struct timeval* nowP, int nocache, char **last_modified, size_t *last_modified_len ); 1413 1414 /* Done with an mmap()ed area that was returned by mmc_map(). 1415 ** If you have a stat buffer on the file, pass it in, otherwise pass 0. 1416diff -ur thttpd-2.21b/thttpd.c thttpd-2.21b-cool/thttpd.c 1417--- thttpd-2.21b/thttpd.c Tue Apr 24 00:41:57 2001 1418+++ thttpd-2.21b-cool/thttpd.c Sat Sep 20 14:43:20 2003 1419@@ -53,6 +53,10 @@ 1420 #endif 1421 #include <unistd.h> 1422 1423+#include <sys/mman.h> 1424+ 1425+#include <limits.h> 1426+ 1427 #include "fdwatch.h" 1428 #include "libhttpd.h" 1429 #include "mmc.h" 1430@@ -66,6 +70,8 @@ 1431 static char* dir; 1432 static int do_chroot, no_log, no_symlink, do_vhost, do_global_passwd; 1433 static char* cgi_pattern; 1434+static char* php_pattern; 1435+static char* phps_pattern; 1436 static char* url_pattern; 1437 static int no_empty_referers; 1438 static char* local_pattern; 1439@@ -95,10 +101,10 @@ 1440 httpd_conn* hc; 1441 int tnums[MAXTHROTTLENUMS]; /* throttle indexes */ 1442 int numtnums; 1443+ int keep_alive; 1444 long limit; 1445 time_t started_at; 1446- Timer* idle_read_timer; 1447- Timer* idle_send_timer; 1448+ time_t last_io; 1449 Timer* wakeup_timer; 1450 Timer* linger_timer; 1451 long wouldblock_delay; 1452@@ -106,17 +112,22 @@ 1453 off_t bytes_sent; 1454 off_t bytes_to_send; 1455 } connecttab; 1456-static connecttab* connects; 1457+static connecttab* connects, **free_connects; 1458+static int next_free_connect; 1459 static int numconnects, maxconnects; 1460 static int httpd_conn_count; 1461 1462 /* The connection states. */ 1463-#define CNST_FREE 0 1464-#define CNST_READING 1 1465-#define CNST_SENDING 2 1466-#define CNST_PAUSING 3 1467-#define CNST_LINGERING 4 1468- 1469+enum { 1470+ CNST_FREE = 0, 1471+ CNST_READING, 1472+ CNST_SENDING, 1473+ CNST_PAUSING, 1474+ CNST_LINGERING, 1475+ CNST_SENDING_RESP, 1476+ CNST_READING_BODY, 1477+ CNST_TOTAL_NR 1478+}; 1479 1480 static httpd_server* hs = (httpd_server*) 0; 1481 int terminate = 0; 1482@@ -140,23 +151,32 @@ 1483 static int handle_newconnect( struct timeval* tvP, int listen_fd ); 1484 static void handle_read( connecttab* c, struct timeval* tvP ); 1485 static void handle_send( connecttab* c, struct timeval* tvP ); 1486+static void handle_send_resp( connecttab* c, struct timeval* tvP ); 1487+static void handle_read_body( connecttab* c, struct timeval* tvP ); 1488 static void handle_linger( connecttab* c, struct timeval* tvP ); 1489 static int check_throttles( connecttab* c ); 1490+static void timeout_conns( ClientData client_data, struct timeval* nowP ); 1491 static void clear_throttles( connecttab* c, struct timeval* tvP ); 1492 static void update_throttles( ClientData client_data, struct timeval* nowP ); 1493-static void clear_connection( connecttab* c, struct timeval* tvP ); 1494+static void clear_connection( connecttab* c, struct timeval* tvP, int ); 1495 static void really_clear_connection( connecttab* c, struct timeval* tvP ); 1496-static void idle_read_connection( ClientData client_data, struct timeval* nowP ); 1497-static void idle_send_connection( ClientData client_data, struct timeval* nowP ); 1498 static void wakeup_connection( ClientData client_data, struct timeval* nowP ); 1499 static void linger_clear_connection( ClientData client_data, struct timeval* nowP ); 1500 static void occasional( ClientData client_data, struct timeval* nowP ); 1501+static void periodic_jobs( ClientData client_data, struct timeval* nowP ); 1502 #ifdef STATS_TIME 1503 static void show_stats( ClientData client_data, struct timeval* nowP ); 1504 #endif /* STATS_TIME */ 1505 static void logstats( struct timeval* nowP ); 1506 static void thttpd_logstats( long secs ); 1507+static void boot_request(connecttab *c, struct timeval *tvP); 1508+ 1509+typedef void (*handler_func)(connecttab*, struct timeval *); 1510+ 1511+handler_func handler_array[CNST_TOTAL_NR] = 1512+{NULL, handle_read, handle_send, NULL, handle_linger, handle_send_resp, handle_read_body}; 1513 1514+#define RUN_HANDLER(type, c) if (handler_array[type]) handler_array[type](c, &tv) 1515 1516 static void 1517 handle_term( int sig ) 1518@@ -177,7 +197,7 @@ 1519 return; 1520 1521 /* Re-open the log file. */ 1522- if ( logfile != (char*) 0 ) 1523+ if ( logfile != (char*) 0 && strcmp(logfile, "-") != 0) 1524 { 1525 logfp = fopen( logfile, "a" ); 1526 if ( logfp == (FILE*) 0 ) 1527@@ -198,6 +218,8 @@ 1528 } 1529 1530 1531+time_t httpd_time_now; 1532+ 1533 static void 1534 handle_usr2( int sig ) 1535 { 1536@@ -217,7 +239,6 @@ 1537 int num_ready; 1538 int cnum, ridx; 1539 connecttab* c; 1540- httpd_conn* hc; 1541 httpd_sockaddr sa4; 1542 httpd_sockaddr sa6; 1543 int gotv4, gotv6; 1544@@ -270,7 +291,9 @@ 1545 no_log = 1; 1546 logfp = (FILE*) 0; 1547 } 1548- else 1549+ else if (strcmp(logfile, "-") == 0) { 1550+ logfp = stdout; 1551+ } else 1552 { 1553 logfp = fopen( logfile, "a" ); 1554 if ( logfp == (FILE*) 0 ) 1555@@ -420,7 +443,8 @@ 1556 hostname, 1557 gotv4 ? &sa4 : (httpd_sockaddr*) 0, gotv6 ? &sa6 : (httpd_sockaddr*) 0, 1558 port, cgi_pattern, charset, cwd, no_log, logfp, no_symlink, do_vhost, 1559- do_global_passwd, url_pattern, local_pattern, no_empty_referers ); 1560+ do_global_passwd, url_pattern, local_pattern, no_empty_referers, 1561+ php_pattern, phps_pattern); 1562 if ( hs == (httpd_server*) 0 ) 1563 exit( 1 ); 1564 1565@@ -430,6 +454,12 @@ 1566 syslog( LOG_CRIT, "tmr_create(occasional) failed" ); 1567 exit( 1 ); 1568 } 1569+ 1570+ if (tmr_create(0, timeout_conns, JunkClientData, 30 * 1000, 1) == 0) { 1571+ syslog(LOG_CRIT, "tmr_create(timeout_conns) failed"); 1572+ exit(1); 1573+ } 1574+ 1575 if ( numthrottles > 0 ) 1576 { 1577 /* Set up the throttles timer. */ 1578@@ -439,6 +469,12 @@ 1579 exit( 1 ); 1580 } 1581 } 1582+ 1583+ if (tmr_create(0, periodic_jobs, JunkClientData, 2000, 1) == 0) { 1584+ syslog(LOG_CRIT, "tmr_create failed"); 1585+ exit(1); 1586+ } 1587+ 1588 #ifdef STATS_TIME 1589 /* Set up the stats timer. */ 1590 if ( tmr_create( (struct timeval*) 0, show_stats, JunkClientData, STATS_TIME * 1000L, 1 ) == (Timer*) 0 ) 1591@@ -454,12 +490,14 @@ 1592 /* If we're root, try to become someone else. */ 1593 if ( getuid() == 0 ) 1594 { 1595+#ifndef __CYGWIN__ 1596 /* Set aux groups to null. */ 1597 if ( setgroups( 0, (const gid_t*) 0 ) < 0 ) 1598 { 1599 syslog( LOG_CRIT, "setgroups - %m" ); 1600 exit( 1 ); 1601 } 1602+#endif 1603 /* Set primary group. */ 1604 if ( setgid( gid ) < 0 ) 1605 { 1606@@ -495,13 +533,17 @@ 1607 } 1608 maxconnects -= SPARE_FDS; 1609 connects = NEW( connecttab, maxconnects ); 1610+ free_connects = malloc(sizeof(connecttab *) * maxconnects); 1611+ next_free_connect = maxconnects; 1612 if ( connects == (connecttab*) 0 ) 1613 { 1614 syslog( LOG_CRIT, "out of memory allocating a connecttab" ); 1615 exit( 1 ); 1616 } 1617+ 1618 for ( cnum = 0; cnum < maxconnects; ++cnum ) 1619 { 1620+ free_connects[cnum] = &connects[maxconnects - cnum - 1]; 1621 connects[cnum].conn_state = CNST_FREE; 1622 connects[cnum].hc = (httpd_conn*) 0; 1623 } 1624@@ -518,6 +560,9 @@ 1625 1626 /* Main loop. */ 1627 (void) gettimeofday( &tv, (struct timezone*) 0 ); 1628+ httpd_time_now = tv.tv_sec; 1629+ periodic_jobs(JunkClientData, &tv); 1630+ 1631 while ( ( ! terminate ) || numconnects > 0 ) 1632 { 1633 /* Do the fd watch. */ 1634@@ -530,6 +575,7 @@ 1635 exit( 1 ); 1636 } 1637 (void) gettimeofday( &tv, (struct timezone*) 0 ); 1638+ httpd_time_now = tv.tv_sec; 1639 if ( num_ready == 0 ) 1640 { 1641 /* No fd's are ready - run the timers. */ 1642@@ -565,16 +611,10 @@ 1643 c = (connecttab*) fdwatch_get_client_data( ridx ); 1644 if ( c == (connecttab*) 0 ) 1645 continue; 1646- hc = c->hc; 1647- if ( c->conn_state == CNST_READING && 1648- fdwatch_check_fd( hc->conn_fd ) ) 1649- handle_read( c, &tv ); 1650- else if ( c->conn_state == CNST_SENDING && 1651- fdwatch_check_fd( hc->conn_fd ) ) 1652- handle_send( c, &tv ); 1653- else if ( c->conn_state == CNST_LINGERING && 1654- fdwatch_check_fd( hc->conn_fd ) ) 1655- handle_linger( c, &tv ); 1656+#if DO_UNNECESSARY_CHECK_FD 1657+ fdwatch_check_fd(c->hc->conn_fd); 1658+#endif 1659+ RUN_HANDLER(c->conn_state, c); 1660 } 1661 tmr_run( &tv ); 1662 1663@@ -627,6 +667,8 @@ 1664 #else /* CGI_PATTERN */ 1665 cgi_pattern = (char*) 0; 1666 #endif /* CGI_PATTERN */ 1667+ php_pattern = "**.php"; 1668+ phps_pattern = "**.phps"; 1669 url_pattern = (char*) 0; 1670 no_empty_referers = 0; 1671 local_pattern = (char*) 0; 1672@@ -833,6 +875,16 @@ 1673 value_required( name, value ); 1674 cgi_pattern = e_strdup( value ); 1675 } 1676+ else if ( strcasecmp( name, "phppat" ) == 0 ) 1677+ { 1678+ value_required( name, value ); 1679+ php_pattern = e_strdup( value ); 1680+ } 1681+ else if ( strcasecmp( name, "phpspat" ) == 0 ) 1682+ { 1683+ value_required( name, value ); 1684+ phps_pattern = e_strdup( value ); 1685+ } 1686 else if ( strcasecmp( name, "urlpat" ) == 0 ) 1687 { 1688 value_required( name, value ); 1689@@ -1196,8 +1248,10 @@ 1690 logstats( &tv ); 1691 for ( cnum = 0; cnum < maxconnects; ++cnum ) 1692 { 1693- if ( connects[cnum].conn_state != CNST_FREE ) 1694+ if ( connects[cnum].conn_state != CNST_FREE ) { 1695+ httpd_complete_request( connects[cnum].hc, &tv ); 1696 httpd_close_conn( connects[cnum].hc, &tv ); 1697+ } 1698 if ( connects[cnum].hc != (httpd_conn*) 0 ) 1699 { 1700 httpd_destroy_conn( connects[cnum].hc ); 1701@@ -1214,6 +1268,7 @@ 1702 } 1703 mmc_destroy(); 1704 tmr_destroy(); 1705+ free( (void*) free_connects ); 1706 free( (void*) connects ); 1707 if ( throttles != (throttletab*) 0 ) 1708 free( (void*) throttles ); 1709@@ -1234,7 +1289,7 @@ 1710 for (;;) 1711 { 1712 /* Is there room in the connection table? */ 1713- if ( numconnects >= maxconnects ) 1714+ if ( numconnects >= maxconnects || next_free_connect == 0 ) 1715 { 1716 /* Out of connection slots. Run the timers, then the 1717 ** existing connections, and maybe we'll free up a slot 1718@@ -1245,10 +1300,10 @@ 1719 return 0; 1720 } 1721 /* Find a free connection entry. */ 1722- for ( cnum = 0; cnum < maxconnects; ++cnum ) 1723- if ( connects[cnum].conn_state == CNST_FREE ) 1724- break; 1725- c = &connects[cnum]; 1726+ 1727+ c = free_connects[--next_free_connect]; 1728+ free_connects[next_free_connect] = NULL; 1729+ 1730 /* Make the httpd_conn if necessary. */ 1731 if ( c->hc == (httpd_conn*) 0 ) 1732 { 1733@@ -1267,24 +1322,18 @@ 1734 { 1735 case GC_FAIL: 1736 case GC_NO_MORE: 1737+ free_connects[next_free_connect++] = c; 1738 return 1; 1739 } 1740 c->conn_state = CNST_READING; 1741 ++numconnects; 1742 client_data.p = c; 1743- c->idle_read_timer = tmr_create( 1744- tvP, idle_read_connection, client_data, IDLE_READ_TIMELIMIT * 1000L, 1745- 0 ); 1746- if ( c->idle_read_timer == (Timer*) 0 ) 1747- { 1748- syslog( LOG_CRIT, "tmr_create(idle_read_connection) failed" ); 1749- exit( 1 ); 1750- } 1751- c->idle_send_timer = (Timer*) 0; 1752 c->wakeup_timer = (Timer*) 0; 1753 c->linger_timer = (Timer*) 0; 1754 c->bytes_sent = 0; 1755 c->numtnums = 0; 1756+ c->keep_alive = 0; 1757+ c->last_io = httpd_time_now; 1758 1759 /* Set the connection file descriptor to no-delay mode. */ 1760 httpd_set_ndelay( c->hc->conn_fd ); 1761@@ -1298,11 +1347,100 @@ 1762 } 1763 1764 1765+#define FIXUP(x) if (hc->x >= oldptr && hc->x < pe) hc->x += d 1766+ 1767+static void 1768+realign_hc(httpd_conn *hc, char *oldptr) 1769+{ 1770+ int d = hc->read_buf - oldptr; 1771+ char *pe = oldptr + hc->checked_idx; 1772+ 1773+ FIXUP(encodedurl); 1774+ FIXUP(protocol); 1775+ FIXUP(referer); 1776+ FIXUP(useragent); 1777+ FIXUP(acceptl); 1778+ FIXUP(cookie); 1779+ FIXUP(contenttype); 1780+ FIXUP(hdrhost); 1781+ FIXUP(authorization); 1782+} 1783+ 1784+#undef FIXUP 1785+ 1786+static void 1787+setup_read_body(connecttab *c, struct timeval *tvP) 1788+{ 1789+ httpd_conn *hc = c->hc; 1790+ int already, missing; 1791+ char *oldptr = hc->read_buf; 1792+ 1793+ c->conn_state = CNST_READING_BODY; 1794+ 1795+ hc->read_body_into_mem = 0; 1796+ 1797+ already = hc->read_idx - hc->checked_idx; 1798+ missing = hc->contentlength - already; 1799+ 1800+ if (missing > 16384) { 1801+ char filename[] = "/tmp/thttpd.upload.XXXXXX"; 1802+ int tmp = mkstemp(filename); 1803+ 1804+ if (tmp >= 0) { 1805+ void *p; 1806+ size_t sz = hc->contentlength + hc->checked_idx + 10; 1807+ 1808+ unlink(filename); 1809+ 1810+ ftruncate(tmp, sz); 1811+ p = mmap(NULL, sz, 1812+ PROT_READ|PROT_WRITE, MAP_PRIVATE, tmp, 0); 1813+ 1814+ if (p != MAP_FAILED) { 1815+ memcpy(p, hc->read_buf, hc->read_idx); 1816+ free(hc->read_buf); 1817+ hc->read_size = sz; 1818+ hc->read_buf = p; 1819+ hc->read_buf_is_mmap = 1; 1820+ } 1821+ close(tmp); 1822+ } 1823+ 1824+ if (!hc->read_buf_is_mmap) { 1825+ clear_connection( c, tvP, 0 ); 1826+ return; 1827+ } 1828+ } else if (missing > 0) { 1829+ httpd_realloc_str(&hc->read_buf, &hc->read_size, hc->checked_idx + hc->contentlength + 10); 1830+ } 1831+ if (oldptr != hc->read_buf) realign_hc(hc, oldptr); 1832+ 1833+ fdwatch_del_fd( hc->conn_fd ); 1834+ fdwatch_add_fd( hc->conn_fd, c, FDW_READ ); 1835+} 1836+ 1837+static void 1838+setup_sending(connecttab *c, int state, struct timeval *tvP) 1839+{ 1840+ httpd_conn *hc = c->hc; 1841+ ClientData client_data; 1842+ 1843+ c->conn_state = state; 1844+ c->started_at = tvP->tv_sec; 1845+ c->wouldblock_delay = 0; 1846+ client_data.p = c; 1847+ 1848+ fdwatch_del_fd( hc->conn_fd ); 1849+ fdwatch_add_fd( hc->conn_fd, c, FDW_WRITE ); 1850+} 1851+ 1852+static void handle_request( connecttab *c, struct timeval *tvP); 1853+ 1854+ 1855 static void 1856 handle_read( connecttab* c, struct timeval* tvP ) 1857 { 1858 int sz; 1859- ClientData client_data; 1860 httpd_conn* hc = c->hc; 1861 1862 /* Is there room in our buffer to read more bytes? */ 1863@@ -1311,7 +1449,7 @@ 1864 if ( hc->read_size > 5000 ) 1865 { 1866 httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" ); 1867- clear_connection( c, tvP ); 1868+ clear_connection( c, tvP, 0 ); 1869 return; 1870 } 1871 httpd_realloc_str( 1872@@ -1327,14 +1465,53 @@ 1873 ** EWOULDBLOCK; however, this apparently can happen if a packet gets 1874 ** garbled. 1875 */ 1876- if ( sz == 0 || ( sz < 0 && ( errno != EWOULDBLOCK ) ) ) 1877- { 1878- httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" ); 1879- clear_connection( c, tvP ); 1880+ if ( sz == 0 ) { 1881+ if (! c->keep_alive) { 1882+ httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" ); 1883+ } 1884+ clear_connection( c, tvP, 0 ); 1885+ return; 1886+ } else if ( sz < 0 ) { 1887+ if (errno != EWOULDBLOCK) { 1888+ clear_connection( c, tvP, 0 ); 1889+ } 1890 return; 1891+ } 1892+ 1893+ /* If this is a persistent PHP connection, we must not receive 1894+ ** any further requests on this connection. Some broken HTTP/1.1 1895+ ** implementations (e.g. Mozilla 1.0.1) are known to do 1896+ ** pipelining on a connection, although a prior response included 1897+ ** Connection: close 1898+ */ 1899+ if (c->hc->file_address == (char *) 1) { 1900+ return; 1901+ } 1902+ 1903+ c->last_io = httpd_time_now; 1904+ if (sz > 0) hc->read_idx += sz; 1905+ 1906+ /* 1907+ ** if we start getting new data on this socket, "promote" it 1908+ ** to read timeout 1909+ */ 1910+ if ( hc->keep_alive ) { 1911+ ClientData client_data; 1912+ 1913+ 1914+ client_data.p = c; 1915+ 1916+ hc->keep_alive = 0; 1917+ } 1918+ handle_request(c, tvP); 1919 } 1920- hc->read_idx += sz; 1921 1922+ 1923+static void 1924+handle_request( connecttab *c, struct timeval *tvP) 1925+{ 1926+ httpd_conn* hc = c->hc; 1927+ 1928 /* Do we have a complete request yet? */ 1929 switch ( httpd_got_request( hc ) ) 1930 { 1931@@ -1342,14 +1519,14 @@ 1932 return; 1933 case GR_BAD_REQUEST: 1934 httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" ); 1935- clear_connection( c, tvP ); 1936+ clear_connection( c, tvP, 0 ); 1937 return; 1938 } 1939 1940 /* Yes. Try parsing and resolving it. */ 1941 if ( httpd_parse_request( hc ) < 0 ) 1942 { 1943- clear_connection( c, tvP ); 1944+ clear_connection( c, tvP, 0 ); 1945 return; 1946 } 1947 1948@@ -1358,18 +1535,28 @@ 1949 { 1950 httpd_send_err( 1951 hc, 503, httpd_err503title, "", httpd_err503form, hc->encodedurl ); 1952- clear_connection( c, tvP ); 1953+ clear_connection( c, tvP, 0 ); 1954 return; 1955 } 1956+ boot_request(c, tvP); 1957+} 1958 1959+static void boot_request(connecttab *c, struct timeval *tvP) 1960+{ 1961+ httpd_conn *hc = c->hc; 1962 /* Start the connection going. */ 1963 if ( httpd_start_request( hc, tvP ) < 0 ) 1964 { 1965 /* Something went wrong. Close down the connection. */ 1966- clear_connection( c, tvP ); 1967+ clear_connection( c, tvP, 0 ); 1968 return; 1969 } 1970 1971+ if ( hc->read_body_into_mem ) { 1972+ setup_read_body( c, tvP ); 1973+ return; 1974+ } 1975+ 1976 /* Fill in bytes_to_send. */ 1977 if ( hc->got_range ) 1978 { 1979@@ -1384,37 +1571,25 @@ 1980 { 1981 /* No file address means someone else is handling it. */ 1982 c->bytes_sent = hc->bytes_sent; 1983- clear_connection( c, tvP ); 1984+ clear_connection( c, tvP, 1 ); 1985 return; 1986 } 1987+ if (hc->file_address == (char *) 1) { 1988+ c->last_io = (time_t) LONG_MAX; 1989+ c->wouldblock_delay = 0; 1990+ return; 1991+ } 1992 if ( c->bytes_sent >= c->bytes_to_send ) 1993 { 1994 /* There's nothing to send. */ 1995- clear_connection( c, tvP ); 1996+ clear_connection( c, tvP, 1 ); 1997 return; 1998 } 1999 2000 /* Cool, we have a valid connection and a file to send to it. */ 2001- c->conn_state = CNST_SENDING; 2002- c->started_at = tvP->tv_sec; 2003- c->wouldblock_delay = 0; 2004- client_data.p = c; 2005- tmr_cancel( c->idle_read_timer ); 2006- c->idle_read_timer = (Timer*) 0; 2007- c->idle_send_timer = tmr_create( 2008- tvP, idle_send_connection, client_data, IDLE_SEND_TIMELIMIT * 1000L, 2009- 0 ); 2010- if ( c->idle_send_timer == (Timer*) 0 ) 2011- { 2012- syslog( LOG_CRIT, "tmr_create(idle_send_connection) failed" ); 2013- exit( 1 ); 2014- } 2015- 2016- fdwatch_del_fd( hc->conn_fd ); 2017- fdwatch_add_fd( hc->conn_fd, c, FDW_WRITE ); 2018+ setup_sending(c, CNST_SENDING, tvP); 2019 } 2020 2021- 2022 static void 2023 handle_send( connecttab* c, struct timeval* tvP ) 2024 { 2025@@ -1443,6 +1618,9 @@ 2026 iv[1].iov_base = &(hc->file_address[c->bytes_sent]); 2027 iv[1].iov_len = MIN( c->bytes_to_send - c->bytes_sent, c->limit ); 2028 sz = writev( hc->conn_fd, iv, 2 ); 2029+/* 2030+printf("**RESPONSE2 [%d]** len = %d\n%*.*s\n", hc->conn_fd, hc->responselen, hc->responselen, hc->responselen, hc->response); 2031+*/ 2032 } 2033 2034 if ( sz == 0 || 2035@@ -1486,12 +1664,12 @@ 2036 */ 2037 if ( errno != EPIPE && errno != EINVAL && errno != ECONNRESET ) 2038 syslog( LOG_ERR, "write - %m sending %.80s", hc->encodedurl ); 2039- clear_connection( c, tvP ); 2040+ clear_connection( c, tvP, 0 ); 2041 return; 2042 } 2043 2044 /* Ok, we wrote something. */ 2045- tmr_reset( tvP, c->idle_send_timer ); 2046+ c->last_io = httpd_time_now; 2047 /* Was this a headers + file writev()? */ 2048 if ( hc->responselen > 0 ) 2049 { 2050@@ -1500,7 +1678,7 @@ 2051 { 2052 /* Yes; move the unwritten part to the front of the buffer. */ 2053 int newlen = hc->responselen - sz; 2054- (void) memcpy( hc->response, &(hc->response[sz]), newlen ); 2055+ (void) memmove( hc->response, &(hc->response[sz]), newlen ); 2056 hc->responselen = newlen; 2057 sz = 0; 2058 } 2059@@ -1519,7 +1697,7 @@ 2060 if ( c->bytes_sent >= c->bytes_to_send ) 2061 { 2062 /* This conection is finished! */ 2063- clear_connection( c, tvP ); 2064+ clear_connection( c, tvP, 1 ); 2065 return; 2066 } 2067 2068@@ -1560,6 +1738,9 @@ 2069 char buf[1024]; 2070 int r; 2071 2072+/* 2073+printf("*LINGER read\n"); 2074+*/ 2075 /* In lingering-close mode we just read and ignore bytes. An error 2076 ** or EOF ends things, otherwise we go until a timeout. 2077 */ 2078@@ -1569,6 +1750,63 @@ 2079 } 2080 2081 2082+static void 2083+handle_read_body(connecttab *c, struct timeval *tvP) 2084+{ 2085+ httpd_conn *hc = c->hc; 2086+ int n; 2087+ 2088+ n = read(hc->conn_fd, hc->read_buf + hc->read_idx, 2089+ hc->contentlength - (hc->read_idx - hc->checked_idx)); 2090+ 2091+ if (n <= 0) { 2092+ if (errno == EAGAIN) 2093+ return; 2094+ clear_connection(c, tvP, 0); 2095+ return; 2096+ } 2097+ 2098+ c->last_io = httpd_time_now; 2099+ 2100+ hc->read_idx += n; 2101+ 2102+ if (hc->contentlength == hc->read_idx - hc->checked_idx) { 2103+ boot_request(c, tvP); 2104+ return; 2105+ } 2106+} 2107+ 2108+static void 2109+handle_send_resp(connecttab *c, struct timeval *tvP) 2110+{ 2111+ httpd_conn* hc = c->hc; 2112+ int n = send(hc->conn_fd, hc->response, hc->responselen, 0); 2113+ int dokeep = 1; 2114+ 2115+ if (n < 0) { 2116+ if (errno == EAGAIN) 2117+ return; 2118+ 2119+ dokeep = 0; 2120+ goto clear; 2121+ } 2122+ 2123+ c->last_io = httpd_time_now; 2124+ 2125+ if (n == hc->responselen) { 2126+clear: 2127+ hc->response = realloc(hc->response, hc->maxresponse + 1); 2128+ hc->responselen = 0; 2129+ 2130+ clear_connection(c, tvP, dokeep); 2131+ return; 2132+ } 2133+ 2134+ hc->responselen -= n; 2135+ 2136+ memmove(hc->response, hc->response + n, hc->responselen); 2137+} 2138+ 2139 static int 2140 check_throttles( connecttab* c ) 2141 { 2142@@ -1635,23 +1873,18 @@ 2143 2144 2145 static void 2146-clear_connection( connecttab* c, struct timeval* tvP ) 2147+clear_connection( connecttab* c, struct timeval* tvP, int doKeep ) 2148 { 2149 ClientData client_data; 2150+ int linger; 2151 2152 /* If we haven't actually sent the buffered response yet, do so now. */ 2153- httpd_write_response( c->hc ); 2154+ if (c->hc->responselen && c->conn_state != CNST_SENDING_RESP) { 2155+ setup_sending(c, CNST_SENDING_RESP, tvP); 2156 2157- if ( c->idle_read_timer != (Timer*) 0 ) 2158- { 2159- tmr_cancel( c->idle_read_timer ); 2160- c->idle_read_timer = 0; 2161- } 2162- if ( c->idle_send_timer != (Timer*) 0 ) 2163- { 2164- tmr_cancel( c->idle_send_timer ); 2165- c->idle_send_timer = 0; 2166+ return; 2167 } 2168+ 2169 if ( c->wakeup_timer != (Timer*) 0 ) 2170 { 2171 tmr_cancel( c->wakeup_timer ); 2172@@ -1669,13 +1902,36 @@ 2173 ** circumstances that make a lingering close necessary. If the flag 2174 ** isn't set we do the real close now. 2175 */ 2176- if ( c->hc->should_linger ) 2177+ 2178+ if ( c->hc->do_keep_alive && doKeep) 2179 { 2180- c->conn_state = CNST_LINGERING; 2181+ httpd_conn *hc = c->hc; 2182+ c->conn_state = CNST_READING; 2183+ 2184+ client_data.p = c; 2185+ c->bytes_sent = 0; 2186+ c->numtnums = 0; 2187+ c->keep_alive = 1; 2188+ 2189+ httpd_complete_request( c->hc, tvP ); 2190+ 2191 fdwatch_del_fd( c->hc->conn_fd ); 2192 fdwatch_add_fd( c->hc->conn_fd, c, FDW_READ ); 2193+ 2194+ httpd_request_reset( c->hc, 1 ); 2195+ 2196+ hc->read_idx -= hc->checked_idx; 2197+ memmove(hc->read_buf, hc->read_buf + hc->checked_idx, hc->read_idx); 2198+ hc->checked_idx = 0; 2199+ 2200 /* Make sure we are still in no-delay mode. */ 2201 httpd_set_ndelay( c->hc->conn_fd ); 2202+ handle_request(c, tvP); 2203+ } 2204+ else if ( c->hc->should_linger ) 2205+ { 2206+ c->conn_state = CNST_LINGERING; 2207+ 2208 client_data.p = c; 2209 c->linger_timer = tmr_create( 2210 tvP, linger_clear_connection, client_data, LINGER_TIME * 1000L, 0 ); 2211@@ -1684,9 +1940,19 @@ 2212 syslog( LOG_CRIT, "tmr_create(linger_clear_connection) failed" ); 2213 exit( 1 ); 2214 } 2215+ 2216+ httpd_complete_request( c->hc, tvP ); 2217+ 2218+ fdwatch_del_fd( c->hc->conn_fd ); 2219+ fdwatch_add_fd( c->hc->conn_fd, c, FDW_READ ); 2220+ /* Make sure we are still in no-delay mode. */ 2221+ httpd_set_ndelay( c->hc->conn_fd ); 2222 } 2223- else 2224+ else 2225+ { 2226+ httpd_complete_request( c->hc, tvP ); 2227 really_clear_connection( c, tvP ); 2228+ } 2229 } 2230 2231 2232@@ -1702,45 +1968,12 @@ 2233 tmr_cancel( c->linger_timer ); 2234 c->linger_timer = 0; 2235 } 2236+ free_connects[next_free_connect++] = c; 2237 c->conn_state = CNST_FREE; 2238 --numconnects; 2239 } 2240 2241 2242-static void 2243-idle_read_connection( ClientData client_data, struct timeval* nowP ) 2244- { 2245- connecttab* c; 2246- 2247- c = (connecttab*) client_data.p; 2248- c->idle_read_timer = (Timer*) 0; 2249- if ( c->conn_state != CNST_FREE ) 2250- { 2251- syslog( LOG_INFO, 2252- "%.80s connection timed out reading", 2253- httpd_ntoa( &c->hc->client_addr ) ); 2254- httpd_send_err( c->hc, 408, httpd_err408title, "", httpd_err408form, "" ); 2255- clear_connection( c, nowP ); 2256- } 2257- } 2258- 2259- 2260-static void 2261-idle_send_connection( ClientData client_data, struct timeval* nowP ) 2262- { 2263- connecttab* c; 2264- 2265- c = (connecttab*) client_data.p; 2266- c->idle_send_timer = (Timer*) 0; 2267- if ( c->conn_state != CNST_FREE ) 2268- { 2269- syslog( LOG_INFO, 2270- "%.80s connection timed out sending", 2271- httpd_ntoa( &c->hc->client_addr ) ); 2272- clear_connection( c, nowP ); 2273- } 2274- } 2275- 2276 2277 static void 2278 wakeup_connection( ClientData client_data, struct timeval* nowP ) 2279@@ -1783,6 +2016,43 @@ 2280 } 2281 #endif /* STATS_TIME */ 2282 2283+char httpd_now_buf[100]; 2284+ 2285+ 2286+ 2287+static void 2288+periodic_jobs( ClientData client_data, struct timeval* nowP ) 2289+{ 2290+ const char* rfc1123fmt = "%a, %d %b %Y %H:%M:%S GMT"; 2291+ struct tm *t; 2292+ char date_nozone[100]; 2293+ const char* cernfmt_nozone = "%d/%b/%Y:%H:%M:%S"; 2294+ char data[100]; 2295+ int zone; 2296+ char sign; 2297+ 2298+ strftime( httpd_now_buf, sizeof(httpd_now_buf), rfc1123fmt, gmtime( &nowP->tv_sec ) ); 2299+ 2300+ t = localtime(&nowP->tv_sec); 2301+ strftime( date_nozone, sizeof(date_nozone), cernfmt_nozone, t ); 2302+#ifdef HAVE_TM_GMTOFF 2303+ zone = t->tm_gmtoff / 60L; 2304+#else 2305+ zone = -timezone / 60L; 2306+ /* Probably have to add something about daylight time here. */ 2307+#endif 2308+ if ( zone >= 0 ) 2309+ sign = '+'; 2310+ else 2311+ { 2312+ sign = '-'; 2313+ zone = -zone; 2314+ } 2315+ zone = ( zone / 60 ) * 100 + zone % 60; 2316+ hs->log_date_len = sprintf( hs->log_date, "%s %c%04d", date_nozone, sign, 2317+ zone ); 2318+} 2319+ 2320 2321 /* Generate debugging statistics syslog messages for all packages. */ 2322 static void 2323@@ -1826,3 +2096,42 @@ 2324 stats_connections = stats_bytes = 0L; 2325 stats_simultaneous = 0; 2326 } 2327+ 2328+static void 2329+timeout_conns(ClientData client_data, struct timeval *nowP) 2330+{ 2331+ connecttab *c = connects, *ce = c + maxconnects; 2332+ time_t now = nowP->tv_sec; 2333+ int r = 0, w = 0; 2334+ int checked = 0; 2335+ 2336+ while (c < ce) { 2337+ switch (c->conn_state) { 2338+ case CNST_SENDING: 2339+ case CNST_SENDING_RESP: 2340+ checked++; 2341+ if ((now - c->last_io) > IDLE_SEND_TIMELIMIT) { 2342+ clear_connection( c, nowP, 0 ); 2343+ w++; 2344+ } 2345+ break; 2346+ case CNST_READING: 2347+ case CNST_READING_BODY: 2348+ checked++; 2349+ if ((now - c->last_io) > IDLE_READ_TIMELIMIT) { 2350+ clear_connection( c, nowP, 0 ); 2351+ r++; 2352+ } 2353+ break; 2354+ case CNST_FREE: break; 2355+ default: checked++; break; 2356+ } 2357+ c++; 2358+ if (checked >= numconnects) break; 2359+ } 2360+ 2361+ if (r > 0 || w > 0) { 2362+ syslog(LOG_INFO, "Expired %d/%d connections in read/write state", r, w); 2363+ } 2364+} 2365+ 2366diff -ur thttpd-2.21b/version.h thttpd-2.21b-cool/version.h 2367--- thttpd-2.21b/version.h Tue Apr 24 04:05:23 2001 2368+++ thttpd-2.21b-cool/version.h Sat Sep 20 14:43:20 2003 2369@@ -3,7 +3,7 @@ 2370 #ifndef _VERSION_H_ 2371 #define _VERSION_H_ 2372 2373-#define SERVER_SOFTWARE "thttpd/2.21b 23apr2001" 2374+#define SERVER_SOFTWARE "thttpd/2.21b PHP/20030920" 2375 #define SERVER_ADDRESS "http://www.acme.com/software/thttpd/" 2376 2377 #endif /* _VERSION_H_ */ 2378