Annotation of embedaddon/php/sapi/thttpd/thttpd_patch, revision 1.1.1.1

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_ */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>