Return to thttpd_patch CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / sapi / thttpd |
1.1 ! misho 1: diff -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: ! 41: diff -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. ! 65: diff -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 ! 77: diff -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: ! 89: diff -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: } ! 120: diff -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] = '?'; ! 974: diff -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. ! 1036: diff -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 ! 1048: diff -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 ! 1299: diff -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 ! 1402: diff -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. ! 1416: diff -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: + ! 2366: diff -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_ */