Annotation of embedaddon/php/sapi/thttpd/thttpd_patch, revision 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>