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