2 ===================================================================
3 Index: src/configfile-glue.c
4 ===================================================================
5 --- src/configfile-glue.c (.../tags/lighttpd-1.4.18) (revision 2118)
6 +++ src/configfile-glue.c (.../branches/lighttpd-1.4.x) (revision 2118)
11 - case COMP_HTTP_REMOTEIP: {
12 + case COMP_HTTP_REMOTE_IP: {
14 /* handle remoteip limitations
20 + case COMP_HTTP_SCHEME:
21 + l = con->uri.scheme;
28 - case COMP_HTTP_QUERYSTRING:
29 + case COMP_HTTP_QUERY_STRING:
37 - case COMP_HTTP_USERAGENT: {
38 + case COMP_HTTP_USER_AGENT: {
40 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "User-Agent"))) {
46 + case COMP_HTTP_REQUEST_METHOD: {
47 + const char *method = get_http_method_name(con->request.http_method);
49 + /* we only have the request method as const char but we need a buffer for comparing */
51 + buffer_copy_string(srv->tmp_buf, method);
58 return COND_RESULT_FALSE;
61 ===================================================================
62 --- src/mod_cgi.c (.../tags/lighttpd-1.4.18) (revision 2118)
63 +++ src/mod_cgi.c (.../branches/lighttpd-1.4.x) (revision 2118)
67 log_error_write(srv, __FILE__, __LINE__, "ss", "fork failed:", strerror(errno));
72 @@ -1227,8 +1228,14 @@
74 log_error_write(srv, __FILE__, __LINE__, "sd", "(debug) cgi exited fine, pid:", p->cgi_pid.ptr[ndx]);
76 + } else if (WIFSIGNALED(status)) {
77 + /* FIXME: what if we killed the CGI script with a kill(..., SIGTERM) ?
79 + if (WTERMSIG(status) != SIGTERM) {
80 + log_error_write(srv, __FILE__, __LINE__, "sd", "cleaning up CGI: process died with signal", WTERMSIG(status));
83 - log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
84 + log_error_write(srv, __FILE__, __LINE__, "s", "cleaning up CGI: ended unexpectedly");
87 cgi_pid_del(srv, p, p->cgi_pid.ptr[ndx]);
88 Index: src/mod_secure_download.c
89 ===================================================================
90 --- src/mod_secure_download.c (.../tags/lighttpd-1.4.18) (revision 2118)
91 +++ src/mod_secure_download.c (.../branches/lighttpd-1.4.x) (revision 2118)
94 if (srv->cur_ts - ts > p->conf.timeout ||
95 srv->cur_ts - ts < -p->conf.timeout) {
96 - con->http_status = 408;
97 + /* "Gone" as the url will never be valid again instead of "408 - Timeout" where the request may be repeated */
98 + con->http_status = 410;
100 return HANDLER_FINISHED;
103 ===================================================================
104 --- src/base.h (.../tags/lighttpd-1.4.18) (revision 2118)
105 +++ src/base.h (.../branches/lighttpd-1.4.x) (revision 2118)
110 + unsigned short is_proxy_ssl;
114 Index: src/connections.c
115 ===================================================================
116 --- src/connections.c (.../tags/lighttpd-1.4.18) (revision 2118)
117 +++ src/connections.c (.../branches/lighttpd-1.4.x) (revision 2118)
118 @@ -394,10 +394,13 @@
119 * 403 is from the response handler when noone else catched it
122 - if (con->uri.path->used &&
123 + if ((!con->http_status || con->http_status == 200) && con->uri.path->used &&
124 con->uri.path->ptr[0] != '*') {
125 response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
127 + con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
128 + con->parsed_response &= ~HTTP_CONTENT_LENGTH;
130 con->http_status = 200;
131 con->file_finished = 1;
135 case 200: /* class: header + body */
144 case 206: /* write_queue is already prepared */
145 @@ -511,13 +516,13 @@
147 /* disable chunked encoding again as we have no body */
148 con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
149 + con->parsed_response &= ~HTTP_CONTENT_LENGTH;
150 chunkqueue_reset(con->write_queue);
152 con->file_finished = 1;
157 if (con->file_finished) {
158 /* we have all the content and chunked encoding is not used, set a content-length */
160 @@ -536,12 +541,16 @@
161 if ((con->http_status >= 100 && con->http_status < 200) ||
162 con->http_status == 204 ||
163 con->http_status == 304) {
165 /* no Content-Body, no Content-Length */
166 - } else if (qlen >= 0) {
167 + if (NULL != (ds = (data_string*) array_get_element(con->response.headers, "Content-Length"))) {
168 + buffer_reset(ds->value); // Headers with empty values are ignored for output
170 + } else if (qlen > 0 || con->request.http_method != HTTP_METHOD_HEAD) {
171 /* qlen = 0 is important for Redirects (301, ...) as they MAY have
172 * a content. Browsers are waiting for a Content otherwise
174 - buffer_copy_off_t(srv->tmp_buf, chunkqueue_length(con->write_queue));
175 + buffer_copy_off_t(srv->tmp_buf, qlen);
177 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf));
180 * a HEAD request has the same as a GET
181 * without the content
183 + con->file_finished = 1;
185 chunkqueue_reset(con->write_queue);
186 con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
189 con->plugin_ctx[pd->id] = NULL;
192 -#if COND_RESULT_UNSET
193 - for (i = srv->config_context->used - 1; i >= 0; i --) {
194 - con->cond_cache[i].result = COND_RESULT_UNSET;
195 - con->cond_cache[i].patterncount = 0;
198 - memset(con->cond_cache, 0, sizeof(cond_cache_t) * srv->config_context->used);
200 + /* The cond_cache gets reset in response.c */
201 +// config_cond_cache_reset(srv, con);
204 if (con->ssl_error_want_reuse_buffer) {
206 ===================================================================
207 --- src/array.h (.../tags/lighttpd-1.4.18) (revision 2118)
208 +++ src/array.h (.../branches/lighttpd-1.4.x) (revision 2118)
213 - COMP_HTTP_USERAGENT,
214 + COMP_HTTP_USER_AGENT,
216 - COMP_HTTP_REMOTEIP,
217 - COMP_HTTP_QUERYSTRING,
218 + COMP_HTTP_REMOTE_IP,
219 + COMP_HTTP_QUERY_STRING,
221 + COMP_HTTP_REQUEST_METHOD,
225 Index: src/mod_staticfile.c
226 ===================================================================
227 --- src/mod_staticfile.c (.../tags/lighttpd-1.4.18) (revision 2118)
228 +++ src/mod_staticfile.c (.../branches/lighttpd-1.4.x) (revision 2118)
232 stat_cache_entry *sce = NULL;
234 + buffer *mtime = NULL;
236 int allow_caching = 1;
242 - response_header_overwrite(srv, con, CONST_STR_LEN("Accept-Ranges"), CONST_STR_LEN("bytes"));
243 + if (con->conf.range_requests) {
244 + response_header_overwrite(srv, con, CONST_STR_LEN("Accept-Ranges"), CONST_STR_LEN("bytes"));
248 if (p->conf.etags_used && con->etag_flags != 0 && !buffer_is_empty(sce->etag)) {
250 /* if the value is the same as our ETag, we do a Range-request,
251 * otherwise a full 200 */
253 - if (!buffer_is_equal(ds->value, con->physical.etag)) {
254 + if (ds->value->ptr[0] == '"') {
256 + * client wants a ETag
258 + if (!con->physical.etag) {
259 + do_range_request = 0;
260 + } else if (!buffer_is_equal(ds->value, con->physical.etag)) {
261 + do_range_request = 0;
263 + } else if (!mtime) {
265 + * we don't have a Last-Modified and can match the If-Range:
269 do_range_request = 0;
270 + } else if (!buffer_is_equal(ds->value, mtime)) {
271 + do_range_request = 0;
275 Index: src/fdevent_solaris_devpoll.c
276 ===================================================================
277 --- src/fdevent_solaris_devpoll.c (.../tags/lighttpd-1.4.18) (revision 2118)
278 +++ src/fdevent_solaris_devpoll.c (.../branches/lighttpd-1.4.x) (revision 2118)
282 dopoll.dp_timeout = timeout_ms;
283 - dopoll.dp_nfds = ev->maxfds;
284 + dopoll.dp_nfds = ev->maxfds - 1;
285 dopoll.dp_fds = ev->devpollfds;
287 ret = ioctl(ev->devpoll_fd, DP_POLL, &dopoll);
289 ===================================================================
290 --- src/etag.c (.../tags/lighttpd-1.4.18) (revision 2118)
291 +++ src/etag.c (.../branches/lighttpd-1.4.x) (revision 2118)
295 +#ifdef HAVE_CONFIG_H
299 +#if defined HAVE_STDINT_H
301 +#elif defined HAVE_INTTYPES_H
302 +#include <inttypes.h>
307 Index: src/mod_scgi.c
308 ===================================================================
309 --- src/mod_scgi.c (.../tags/lighttpd-1.4.18) (revision 2118)
310 +++ src/mod_scgi.c (.../branches/lighttpd-1.4.x) (revision 2118)
311 @@ -1057,6 +1057,9 @@
312 /* a local socket + self spawning */
315 + /* HACK: just to make sure the adaptive spawing is disabled */
316 + df->min_procs = df->max_procs;
318 if (df->min_procs > df->max_procs) df->max_procs = df->min_procs;
319 if (df->max_load_per_proc < 1) df->max_load_per_proc = 0;
321 @@ -2694,8 +2697,9 @@
322 if (s_len < ct_len) continue;
324 /* check extension in the form "/scgi_pattern" */
325 - if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
327 + if (*(extension->key->ptr) == '/') {
328 + if (strncmp(fn->ptr, extension->key->ptr, ct_len) == 0)
330 } else if (0 == strncmp(fn->ptr + s_len - ct_len, extension->key->ptr, ct_len)) {
331 /* check extension in the form ".fcg" */
333 Index: src/response.c
334 ===================================================================
335 --- src/response.c (.../tags/lighttpd-1.4.18) (revision 2118)
336 +++ src/response.c (.../branches/lighttpd-1.4.x) (revision 2118)
338 #include "stat_cache.h"
341 +#include "configfile.h"
342 #include "connections.h"
346 ds = (data_string *)con->response.headers->data[i];
348 if (ds->value->used && ds->key->used &&
349 - 0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1)) {
350 + 0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1) &&
351 + 0 != strncmp(ds->key->ptr, "X-Sendfile", sizeof("X-Sendfile") - 1)) {
352 if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Date"))) have_date = 1;
353 if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Server"))) have_server = 1;
359 + config_cond_cache_reset(srv, con);
360 + config_setup_connection(srv, con); // Perhaps this could be removed at other places.
362 if (con->conf.log_condition_handling) {
363 log_error_write(srv, __FILE__, __LINE__, "s", "run condition");
365 @@ -180,11 +185,13 @@
366 buffer_copy_string_buffer(con->uri.authority, con->request.http_host);
367 buffer_to_lower(con->uri.authority);
369 + config_patch_connection(srv, con, COMP_HTTP_SCHEME); /* Scheme: */
370 config_patch_connection(srv, con, COMP_HTTP_HOST); /* Host: */
371 - config_patch_connection(srv, con, COMP_HTTP_REMOTEIP); /* Client-IP */
372 + config_patch_connection(srv, con, COMP_HTTP_REMOTE_IP); /* Client-IP */
373 config_patch_connection(srv, con, COMP_HTTP_REFERER); /* Referer: */
374 - config_patch_connection(srv, con, COMP_HTTP_USERAGENT); /* User-Agent: */
375 + config_patch_connection(srv, con, COMP_HTTP_USER_AGENT);/* User-Agent: */
376 config_patch_connection(srv, con, COMP_HTTP_COOKIE); /* Cookie: */
377 + config_patch_connection(srv, con, COMP_HTTP_REQUEST_METHOD); /* REQUEST_METHOD */
379 /** their might be a fragment which has to be cut away */
380 if (NULL != (qstr = strchr(con->request.uri->ptr, '#'))) {
384 config_patch_connection(srv, con, COMP_HTTP_URL); /* HTTPurl */
385 - config_patch_connection(srv, con, COMP_HTTP_QUERYSTRING); /* HTTPqs */
386 + config_patch_connection(srv, con, COMP_HTTP_QUERY_STRING); /* HTTPqs */
388 /* do we have to downgrade to 1.0 ? */
389 if (!con->conf.allow_http11) {
390 @@ -547,17 +554,14 @@
391 buffer_copy_string_buffer(srv->tmp_buf, con->physical.path);
397 buffer_copy_string_len(con->physical.path, srv->tmp_buf->ptr, slash - srv->tmp_buf->ptr);
399 buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
402 - if (0 == stat(con->physical.path->ptr, &(st)) &&
403 - S_ISREG(st.st_mode)) {
405 + if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
406 + found = S_ISREG(sce->st.st_mode);
411 return HANDLER_FINISHED;
415 + if ((sce->is_symlink != 0) && !con->conf.follow_symlink) {
416 + con->http_status = 403;
418 + if (con->conf.log_request_handling) {
419 + log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied due symlink restriction");
420 + log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
423 + buffer_reset(con->physical.path);
424 + return HANDLER_FINISHED;
428 /* we have a PATHINFO */
430 buffer_copy_string(con->request.pathinfo, pathinfo);
433 /* if we are still here, no one wanted the file, status 403 is ok I think */
435 - if (con->mode == DIRECT) {
436 - con->http_status = 403;
437 + if (con->mode == DIRECT && con->http_status == 0) {
438 + switch (con->request.http_method) {
439 + case HTTP_METHOD_OPTIONS:
440 + con->http_status = 200;
443 + con->http_status = 403;
446 return HANDLER_FINISHED;
448 Index: src/mod_userdir.c
449 ===================================================================
450 --- src/mod_userdir.c (.../tags/lighttpd-1.4.18) (revision 2118)
451 +++ src/mod_userdir.c (.../branches/lighttpd-1.4.x) (revision 2118)
456 + unsigned short letterhomes;
461 { "userdir.exclude-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
462 { "userdir.include-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
463 { "userdir.basepath", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
464 + { "userdir.letterhomes", NULL, T_CONFIG_BOOLEAN,T_CONFIG_SCOPE_CONNECTION }, /* 4 */
465 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
468 @@ -102,11 +104,13 @@
469 s->include_user = array_init();
470 s->path = buffer_init();
471 s->basepath = buffer_init();
472 + s->letterhomes = 0;
474 cv[0].destination = s->path;
475 cv[1].destination = s->exclude_user;
476 cv[2].destination = s->include_user;
477 cv[3].destination = s->basepath;
478 + cv[4].destination = &(s->letterhomes);
480 p->config_storage[i] = s;
486 + PATCH(letterhomes);
488 /* skip the first, the global context */
489 for (i = 1; i < srv->config_context->used; i++) {
492 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.basepath"))) {
494 + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.letterhomes"))) {
495 + PATCH(letterhomes);
501 buffer_copy_string_buffer(p->temp_path, p->conf.basepath);
502 BUFFER_APPEND_SLASH(p->temp_path);
503 + if (p->conf.letterhomes) {
504 + buffer_append_string_len(p->temp_path, p->username->ptr, 1);
505 + BUFFER_APPEND_SLASH(p->temp_path);
507 buffer_append_string_buffer(p->temp_path, p->username);
509 BUFFER_APPEND_SLASH(p->temp_path);
510 Index: src/mod_proxy.c
511 ===================================================================
512 --- src/mod_proxy.c (.../tags/lighttpd-1.4.18) (revision 2118)
513 +++ src/mod_proxy.c (.../branches/lighttpd-1.4.x) (revision 2118)
514 @@ -1093,15 +1093,17 @@
515 if (s_len < ct_len) continue;
517 /* check extension in the form "/proxy_pattern" */
518 - if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
519 - if (s_len > ct_len + 1) {
521 + if (*(extension->key->ptr) == '/') {
522 + if (strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
523 + if (s_len > ct_len + 1) {
526 - if (0 != (pi_offset = strchr(fn->ptr + ct_len + 1, '/'))) {
527 - path_info_offset = pi_offset - fn->ptr;
528 + if (0 != (pi_offset = strchr(fn->ptr + ct_len + 1, '/'))) {
529 + path_info_offset = pi_offset - fn->ptr;
535 } else if (0 == strncmp(fn->ptr + s_len - ct_len, extension->key->ptr, ct_len)) {
536 /* check extension in the form ".fcg" */
538 @@ -1203,7 +1205,7 @@
541 /* didn't found a higher id, wrap to the start */
542 - if (ndx != -1 && max_usage != INT_MAX) {
543 + if (ndx == -1 && max_usage != INT_MAX) {
547 Index: src/mod_extforward.c
548 ===================================================================
549 --- src/mod_extforward.c (.../tags/lighttpd-1.4.18) (revision 2118)
550 +++ src/mod_extforward.c (.../branches/lighttpd-1.4.x) (revision 2118)
553 * mod_extforward.c for lighttpd, by comman.kang <at> gmail <dot> com
554 * extended, modified by Lionel Elie Mamane (LEM), lionel <at> mamane <dot> lu
555 + * support chained proxies by glen@delfi.ee, #1528
560 * Note that "all" has precedence over specific entries,
561 * so "all except" setups will not work.
563 + * In case you have chained proxies, you can add all their IP's to the
564 + * config. However "all" has effect only on connecting IP, as the
565 + * X-Forwarded-For header can not be trusted.
567 * Note: The effect of this module is variable on $HTTP["remotip"] directives and
568 * other module's remote ip dependent actions.
569 * Things done by modules before we change the remoteip or after we reset it will match on the proxy's IP.
570 @@ -225,18 +230,16 @@
572 /* state variable, 0 means not in string, 1 means in string */
574 - for (base = pbuffer->ptr, curr = pbuffer->ptr; *curr; curr++)
576 + for (base = pbuffer->ptr, curr = pbuffer->ptr; *curr; curr++) {
578 - if ( (*curr > '9' || *curr < '0') && *curr != '.' && *curr != ':' ) {
579 + if ((*curr > '9' || *curr < '0') && *curr != '.' && *curr != ':') {
580 /* found an separator , insert value into result array */
581 - put_string_into_array_len(result, base, curr-base);
582 + put_string_into_array_len(result, base, curr - base);
583 /* change state to not in string */
587 - if (*curr >= '0' && *curr <= '9')
589 + if (*curr >= '0' && *curr <= '9') {
590 /* found leading char of an IP address, move base pointer and change state */
596 /* if breaking out while in str, we got to the end of string, so add it */
599 - put_string_into_array_len(result, base, curr-base);
601 + put_string_into_array_len(result, base, curr - base);
605 @@ -255,20 +257,42 @@
607 #define IP_UNTRUSTED 0
609 - check whether ip is trusted, return 1 for trusted , 0 for untrusted
611 + * check whether ip is trusted, return 1 for trusted , 0 for untrusted
613 static int is_proxy_trusted(const char *ipstr, plugin_data *p)
615 - data_string* allds = (data_string *) array_get_element(p->conf.forwarder,"all");
616 + data_string* allds = (data_string *)array_get_element(p->conf.forwarder, "all");
619 - if (strcasecmp(allds->value->ptr,"trust") == 0)
620 + if (strcasecmp(allds->value->ptr, "trust") == 0) {
627 - return (data_string *)array_get_element(p->conf.forwarder,ipstr) ? IP_TRUSTED : IP_UNTRUSTED ;
629 + return (data_string *)array_get_element(p->conf.forwarder, ipstr) ? IP_TRUSTED : IP_UNTRUSTED;
633 + * Return char *ip of last address of proxy that is not trusted.
634 + * Do not accept "all" keyword here.
636 +static const char *last_not_in_array(array *a, plugin_data *p)
638 + array *forwarder = p->conf.forwarder;
640 + for (int i = a->used - 1; i >= 0; i--) {
641 + data_string *ds = (data_string *)a->data[i];
642 + const char *ip = ds->value->ptr;
644 + if (!array_get_element(forwarder, ip)) {
651 struct addrinfo *ipstr_to_sockaddr(const char *host)
653 struct addrinfo hints, *res0;
657 static void clean_cond_cache(server *srv, connection *con) {
658 - config_cond_cache_reset_item(srv, con, COMP_HTTP_REMOTEIP);
659 + config_cond_cache_reset_item(srv, con, COMP_HTTP_REMOTE_IP);
662 URIHANDLER_FUNC(mod_extforward_uri_handler) {
664 struct addrinfo *addrlist = NULL;
666 const char *dst_addr_str = NULL;
668 array *forward_array = NULL;
669 - char *real_remote_addr = NULL;
670 + const char *real_remote_addr = NULL;
675 return HANDLER_GO_ON;
678 - /* if the remote ip itself is not trusted , then do nothing */
680 dst_addr_str = inet_ntop(con->dst_addr.plain.sa_family,
681 con->dst_addr.plain.sa_family == AF_INET6 ?
684 dst_addr_str = inet_ntoa(con->dst_addr.ipv4.sin_addr);
686 - if (IP_UNTRUSTED == is_proxy_trusted (dst_addr_str, p) ) {
688 + /* if the remote ip itself is not trusted, then do nothing */
689 + if (IP_UNTRUSTED == is_proxy_trusted(dst_addr_str, p)) {
690 if (con->conf.log_request_handling) {
691 log_error_write(srv, __FILE__, __LINE__, "s",
692 "remote address is NOT a trusted proxy, skipping");
693 @@ -362,40 +386,34 @@
694 return HANDLER_GO_ON;
697 + /* build forward_array from forwarded data_string */
698 forward_array = extract_forward_array(forwarded->value);
699 + real_remote_addr = last_not_in_array(forward_array, p);
701 - /* Testing shows that multiple headers and multiple values in one header
702 - come in _reverse_ order. So the first one we get is the last one in the request. */
703 - for (i = forward_array->used - 1; i >= 0; i--) {
704 - data_string *ds = (data_string *) forward_array->data[i];
706 - real_remote_addr = ds->value->ptr;
709 - /* bug ? bailing out here */
714 if (real_remote_addr != NULL) { /* parsed */
717 struct addrinfo *addrs_left;
718 + server_socket *srv_sock = con->srv_socket;
719 + data_string *forwarded_proto = (data_string *)array_get_element(con->request.headers, "X-Forwarded-Proto");
721 + if (forwarded_proto && !strcmp(forwarded_proto->value->ptr, "https")) {
722 + srv_sock->is_proxy_ssl = 1;
724 + srv_sock->is_proxy_ssl = 0;
727 if (con->conf.log_request_handling) {
728 - log_error_write(srv, __FILE__, __LINE__, "ss",
729 - "using address:", real_remote_addr);
730 + log_error_write(srv, __FILE__, __LINE__, "ss", "using address:", real_remote_addr);
733 addrlist = ipstr_to_sockaddr(real_remote_addr);
734 sock.plain.sa_family = AF_UNSPEC;
735 - for (addrs_left = addrlist; addrs_left != NULL;
736 - addrs_left = addrs_left -> ai_next) {
737 + for (addrs_left = addrlist; addrs_left != NULL; addrs_left = addrs_left -> ai_next) {
738 sock.plain.sa_family = addrs_left->ai_family;
739 - if ( sock.plain.sa_family == AF_INET ) {
740 + if (sock.plain.sa_family == AF_INET) {
741 sock.ipv4.sin_addr = ((struct sockaddr_in*)addrs_left->ai_addr)->sin_addr;
743 - } else if ( sock.plain.sa_family == AF_INET6 ) {
744 + } else if (sock.plain.sa_family == AF_INET6) {
745 sock.ipv6.sin6_addr = ((struct sockaddr_in6*)addrs_left->ai_addr)->sin6_addr;
749 if (addrlist != NULL ) freeaddrinfo(addrlist);
752 - array_free(forward_array);
753 + array_free(forward_array);
756 return HANDLER_GO_ON;
757 Index: src/Makefile.am
758 ===================================================================
759 --- src/Makefile.am (.../tags/lighttpd-1.4.18) (revision 2118)
760 +++ src/Makefile.am (.../branches/lighttpd-1.4.x) (revision 2118)
762 configparser.c configparser.h:
763 mod_ssi_exprparser.c mod_ssi_exprparser.h:
765 -configparser.y: lemon
766 -mod_ssi_exprparser.y: lemon
767 +$(srcdir)/configparser.y: lemon
768 +$(srcdir)/mod_ssi_exprparser.y: lemon
770 -configparser.c configparser.h: configparser.y
771 +configparser.c configparser.h: $(srcdir)/configparser.y
773 $(LEMON) -q $(srcdir)/configparser.y $(srcdir)/lempar.c
775 -mod_ssi_exprparser.c mod_ssi_exprparser.h: mod_ssi_exprparser.y
776 +mod_ssi_exprparser.c mod_ssi_exprparser.h: $(srcdir)/mod_ssi_exprparser.y
777 rm -f mod_ssi_exprparser.h
778 $(LEMON) -q $(srcdir)/mod_ssi_exprparser.y $(srcdir)/lempar.c
781 -configfile.c: configparser.h
782 -mod_ssi_expr.c: mod_ssi_exprparser.h
783 +$(srcdir)/configfile.c: configparser.h
784 +$(srcdir)/mod_ssi_expr.c: mod_ssi_exprparser.h
786 common_src=buffer.c log.c \
791 noinst_HEADERS = $(hdr)
792 -EXTRA_DIST = mod_skeleton.c configparser.y mod_ssi_exprparser.y lempar.c
793 +EXTRA_DIST = mod_skeleton.c configparser.y mod_ssi_exprparser.y lempar.c SConscript
794 Index: src/network_openssl.c
795 ===================================================================
796 --- src/network_openssl.c (.../tags/lighttpd-1.4.18) (revision 2118)
797 +++ src/network_openssl.c (.../branches/lighttpd-1.4.x) (revision 2118)
799 SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
802 - /* evil hack for opera 9.01 and 8.54 and earlier
804 - * opera hangs if the trainling 0\r\n\r\n is in a seperate SSL-packet
806 - * we try to move the packet into the previous mem-chunk if possible
808 - if ((cq == con->write_queue) &&
809 - (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) &&
810 - (con->file_finished)) {
811 - /* merge the last chunk into the previous chunk */
813 - for(c = cq->first; c && c->next && c->next->next; c = c->next);
816 - c->type == MEM_CHUNK &&
818 - c->next->type == MEM_CHUNK &&
819 - c->next->mem->used == sizeof("0\r\n\r\n") &&
820 - 0 == strcmp(c->next->mem->ptr, "0\r\n\r\n")) {
821 - buffer_append_string_buffer(c->mem, c->next->mem);
823 - c->next->mem->used = 0;
827 for(c = cq->first; c; c = c->next) {
828 int chunk_finished = 0;
831 /* no, but we have errno */
837 log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
839 /* no, but we have errno */
845 log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
846 Index: src/http_auth.c
847 ===================================================================
848 --- src/http_auth.c (.../tags/lighttpd-1.4.18) (revision 2118)
849 +++ src/http_auth.c (.../branches/lighttpd-1.4.x) (revision 2118)
852 #include "http_auth.h"
853 #include "http_auth_digest.h"
854 +#include "inet_ntop_cache.h"
860 /* password doesn't match */
861 if (http_auth_basic_password_compare(srv, p, req, username, realm->value, password, pw)) {
862 - log_error_write(srv, __FILE__, __LINE__, "sbb", "password doesn't match for", con->uri.path, username);
863 + log_error_write(srv, __FILE__, __LINE__, "sbbss", "password doesn't match for ", con->uri.path, username, ", IP:", inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
865 buffer_free(username);
866 buffer_free(password);
867 @@ -1130,7 +1131,7 @@
870 log_error_write(srv, __FILE__, __LINE__, "sss",
871 - "digest: auth failed for", username, "wrong password");
872 + "digest: auth failed for ", username, ": wrong password, IP:", inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
876 Index: src/configparser.y
877 ===================================================================
878 --- src/configparser.y (.../tags/lighttpd-1.4.18) (revision 2118)
879 +++ src/configparser.y (.../branches/lighttpd-1.4.x) (revision 2118)
884 -/* op1 is to be eat/return by this function, op1->key is not cared
885 +/* op1 is to be eat/return by this function if success, op1->key is not cared
886 op2 is left untouch, unreferenced
888 data_unset *configparser_merge_data(data_unset *op1, const data_unset *op2) {
890 return (data_unset *)ds;
892 fprintf(stderr, "data type mismatch, cannot be merge\n");
898 %type aelement {data_unset *}
899 %type condline {data_config *}
900 %type condlines {data_config *}
901 +%type global {data_config *}
902 %type aelements {array *}
903 %type array {array *}
905 @@ -142,22 +142,24 @@
906 %token_destructor { buffer_free($$); }
908 varline ::= key(A) ASSIGN expression(B). {
909 - buffer_copy_string_buffer(B->key, A);
910 - if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
911 - fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
912 - ctx->current->context_ndx,
913 - ctx->current->key->ptr, A->ptr);
915 - } else if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
916 - array_insert_unique(ctx->current->value, B);
919 - fprintf(stderr, "Duplicate config variable in conditional %d %s: %s\n",
920 - ctx->current->context_ndx,
921 - ctx->current->key->ptr, B->key->ptr);
926 + buffer_copy_string_buffer(B->key, A);
927 + if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
928 + fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
929 + ctx->current->context_ndx,
930 + ctx->current->key->ptr, A->ptr);
932 + } else if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
933 + array_insert_unique(ctx->current->value, B);
936 + fprintf(stderr, "Duplicate config variable in conditional %d %s: %s\n",
937 + ctx->current->context_ndx,
938 + ctx->current->key->ptr, B->key->ptr);
947 du = configparser_merge_data(du, B);
953 buffer_copy_string_buffer(du->key, A);
954 @@ -418,10 +421,15 @@
955 { COMP_HTTP_URL, CONST_STR_LEN("HTTP[\"url\"]" ) },
956 { COMP_HTTP_HOST, CONST_STR_LEN("HTTP[\"host\"]" ) },
957 { COMP_HTTP_REFERER, CONST_STR_LEN("HTTP[\"referer\"]" ) },
958 - { COMP_HTTP_USERAGENT, CONST_STR_LEN("HTTP[\"useragent\"]" ) },
959 + { COMP_HTTP_USER_AGENT, CONST_STR_LEN("HTTP[\"useragent\"]" ) },
960 + { COMP_HTTP_USER_AGENT, CONST_STR_LEN("HTTP[\"user-agent\"]" ) },
961 { COMP_HTTP_COOKIE, CONST_STR_LEN("HTTP[\"cookie\"]" ) },
962 - { COMP_HTTP_REMOTEIP, CONST_STR_LEN("HTTP[\"remoteip\"]" ) },
963 - { COMP_HTTP_QUERYSTRING, CONST_STR_LEN("HTTP[\"querystring\"]") },
964 + { COMP_HTTP_REMOTE_IP, CONST_STR_LEN("HTTP[\"remoteip\"]" ) },
965 + { COMP_HTTP_REMOTE_IP, CONST_STR_LEN("HTTP[\"remote-ip\"]" ) },
966 + { COMP_HTTP_QUERY_STRING, CONST_STR_LEN("HTTP[\"querystring\"]") },
967 + { COMP_HTTP_QUERY_STRING, CONST_STR_LEN("HTTP[\"query-string\"]") },
968 + { COMP_HTTP_REQUEST_METHOD, CONST_STR_LEN("HTTP[\"request-method\"]") },
969 + { COMP_HTTP_SCHEME, CONST_STR_LEN("HTTP[\"scheme\"]" ) },
970 { COMP_UNSET, NULL, 0 },
973 Index: src/mod_status.c
974 ===================================================================
975 --- src/mod_status.c (.../tags/lighttpd-1.4.18) (revision 2118)
976 +++ src/mod_status.c (.../branches/lighttpd-1.4.x) (revision 2118)
984 b = chunkqueue_get_append_buffer(con->write_queue);
987 buffer_append_long(b, srv->conns->used);
988 BUFFER_APPEND_STRING_CONST(b, "\n");
990 + BUFFER_APPEND_STRING_CONST(b, "IdleServers: ");
991 + buffer_append_long(b, srv->conns->size - srv->conns->used);
992 + BUFFER_APPEND_STRING_CONST(b, "\n");
994 + /* output scoreboard */
995 + BUFFER_APPEND_STRING_CONST(b, "Scoreboard: ");
996 + for (k = 0; k < srv->conns->used; k++) {
997 + connection *c = srv->conns->ptr[k];
998 + const char *state = connection_get_short_state(c->state);
999 + buffer_append_string_len(b, state, 1);
1001 + for (l = 0; l < srv->conns->size - srv->conns->used; l++) {
1002 + BUFFER_APPEND_STRING_CONST(b, "_");
1004 + BUFFER_APPEND_STRING_CONST(b, "\n");
1006 /* set text/plain output */
1008 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
1009 Index: src/mod_compress.c
1010 ===================================================================
1011 --- src/mod_compress.c (.../tags/lighttpd-1.4.18) (revision 2118)
1012 +++ src/mod_compress.c (.../branches/lighttpd-1.4.x) (revision 2118)
1013 @@ -102,6 +102,50 @@
1014 return HANDLER_GO_ON;
1017 +// 0 on success, -1 for error
1018 +int mkdir_recursive(char *dir) {
1021 + if (!dir || !dir[0])
1024 + while ((p = strchr(p + 1, '/')) != NULL) {
1027 + if ((mkdir(dir, 0700) != 0) && (errno != EEXIST)) {
1033 + if (!*p) return 0; // Ignore trailing slash
1036 + return (mkdir(dir, 0700) != 0) && (errno != EEXIST) ? -1 : 0;
1039 +// 0 on success, -1 for error
1040 +int mkdir_for_file(char *filename) {
1041 + char *p = filename;
1043 + if (!filename || !filename[0])
1046 + while ((p = strchr(p + 1, '/')) != NULL) {
1049 + if ((mkdir(filename, 0700) != 0) && (errno != EEXIST)) {
1055 + if (!*p) return -1; // Unexpected trailing slash in filename
1061 SETDEFAULTS_FUNC(mod_compress_setdefaults) {
1062 plugin_data *p = p_d;
1067 if (!buffer_is_empty(s->compress_cache_dir)) {
1068 + mkdir_recursive(s->compress_cache_dir->ptr);
1071 if (0 != stat(s->compress_cache_dir->ptr, &st)) {
1072 log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir",
1073 @@ -342,27 +388,8 @@
1074 BUFFER_APPEND_SLASH(p->ofn);
1076 if (0 == strncmp(con->physical.path->ptr, con->physical.doc_root->ptr, con->physical.doc_root->used-1)) {
1077 - size_t offset = p->ofn->used - 1;
1078 - char *dir, *nextdir;
1080 buffer_append_string(p->ofn, con->physical.path->ptr + con->physical.doc_root->used - 1);
1082 buffer_copy_string_buffer(p->b, p->ofn);
1084 - /* mkdir -p ... */
1085 - for (dir = p->b->ptr + offset; NULL != (nextdir = strchr(dir, '/')); dir = nextdir + 1) {
1088 - if (-1 == mkdir(p->b->ptr, 0700)) {
1089 - if (errno != EEXIST) {
1090 - log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cache-directory", p->b, "failed", strerror(errno));
1099 buffer_append_string_buffer(p->ofn, con->uri.path);
1101 @@ -384,6 +411,11 @@
1103 buffer_append_string_buffer(p->ofn, sce->etag);
1105 + if (-1 == mkdir_for_file(p->ofn->ptr)) {
1106 + log_error_write(srv, __FILE__, __LINE__, "sb", "couldn't create directory for file", p->ofn);
1110 if (-1 == (ofd = open(p->ofn->ptr, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600))) {
1111 if (errno == EEXIST) {
1112 /* cache-entry exists */
1113 @@ -407,6 +439,11 @@
1117 + /* Remove the incomplete cache file, so that later hits aren't served from it */
1118 + if (-1 == unlink(p->ofn->ptr)) {
1119 + log_error_write(srv, __FILE__, __LINE__, "sbss", "unlinking incomplete cachefile", p->ofn, "failed:", strerror(errno));
1125 @@ -416,6 +453,12 @@
1130 + /* Remove the incomplete cache file, so that later hits aren't served from it */
1131 + if (-1 == unlink(p->ofn->ptr)) {
1132 + log_error_write(srv, __FILE__, __LINE__, "sbss", "unlinking incomplete cachefile", p->ofn, "failed:", strerror(errno));
1138 @@ -438,23 +481,30 @@
1142 - if (-1 == (r = write(ofd, p->b->ptr, p->b->used))) {
1143 - munmap(start, sce->st.st_size);
1148 + r = write(ofd, p->b->ptr, p->b->used);
1150 + log_error_write(srv, __FILE__, __LINE__, "sbss", "writing cachefile", p->ofn, "failed:", strerror(errno));
1152 + } else if ((size_t)r != p->b->used) {
1153 + log_error_write(srv, __FILE__, __LINE__, "sbs", "writing cachefile", p->ofn, "failed: not enough bytes written");
1158 - if ((size_t)r != p->b->used) {
1162 munmap(start, sce->st.st_size);
1166 - if (ret != 0) return -1;
1168 + /* Remove the incomplete cache file, so that later hits aren't served from it */
1169 + if (-1 == unlink(p->ofn->ptr)) {
1170 + log_error_write(srv, __FILE__, __LINE__, "sbss", "unlinking incomplete cachefile", p->ofn, "failed:", strerror(errno));
1176 buffer_copy_string_buffer(con->physical.path, p->ofn);
1181 stat_cache_entry *sce = NULL;
1183 + if (con->mode != DIRECT || con->http_status) return HANDLER_GO_ON;
1185 /* only GET and POST can get compressed */
1186 if (con->request.http_method != HTTP_METHOD_GET &&
1187 con->request.http_method != HTTP_METHOD_POST) {
1188 @@ -678,8 +730,16 @@
1190 } else if (0 == deflate_file_to_buffer(srv, con, p,
1191 con->physical.path, sce, compression_type)) {
1194 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
1196 + mtime = strftime_cache_get(srv, sce->st.st_mtime);
1197 + response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
1199 + etag_mutate(con->physical.etag, sce->etag);
1200 + response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
1202 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
1204 return HANDLER_FINISHED;
1205 Index: src/mod_ssi.c
1206 ===================================================================
1207 --- src/mod_ssi.c (.../tags/lighttpd-1.4.18) (revision 2118)
1208 +++ src/mod_ssi.c (.../branches/lighttpd-1.4.x) (revision 2118)
1210 #include <sys/filio.h>
1215 +/* The newest modified time of included files for include statement */
1216 +static volatile time_t include_file_last_mtime = 0;
1218 /* init the plugin data */
1219 INIT_FUNC(mod_ssi_init) {
1221 @@ -575,6 +580,11 @@
1224 chunkqueue_append_file(con->write_queue, p->stat_fn, 0, st.st_size);
1226 + /* Keep the newest mtime of included files */
1227 + if (st.st_mtime > include_file_last_mtime)
1228 + include_file_last_mtime = st.st_mtime;
1234 build_ssi_cgi_vars(srv, con, p);
1237 + /* Reset the modified time of included files */
1238 + include_file_last_mtime = 0;
1240 if (-1 == stream_open(&s, con->physical.path)) {
1241 log_error_write(srv, __FILE__, __LINE__, "sb",
1242 "stream-open: ", con->physical.path);
1243 @@ -1010,6 +1023,30 @@
1245 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
1248 + /* Generate "ETag" & "Last-Modified" headers */
1250 + stat_cache_entry *sce = NULL;
1251 + time_t lm_time = 0;
1252 + buffer *mtime = NULL;
1254 + stat_cache_get_entry(srv, con, con->physical.path, &sce);
1256 + etag_mutate(con->physical.etag, sce->etag);
1257 + response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
1259 + if (sce->st.st_mtime > include_file_last_mtime)
1260 + lm_time = sce->st.st_mtime;
1262 + lm_time = include_file_last_mtime;
1264 + mtime = strftime_cache_get(srv, lm_time);
1265 + response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
1268 + /* Reset the modified time of included files */
1269 + include_file_last_mtime = 0;
1271 /* reset physical.path */
1272 buffer_reset(con->physical.path);
1274 Index: src/spawn-fcgi.c
1275 ===================================================================
1276 --- src/spawn-fcgi.c (.../tags/lighttpd-1.4.18) (revision 2118)
1277 +++ src/spawn-fcgi.c (.../branches/lighttpd-1.4.x) (revision 2118)
1281 #ifdef HAVE_SYS_UN_H
1282 -int fcgi_spawn_connection(char *appPath, char *addr, unsigned short port, const char *unixsocket, int child_count, int pid_fd, int nofork) {
1283 +int fcgi_spawn_connection(char *appPath, char **appArgv, char *addr, unsigned short port, const char *unixsocket, int child_count, int pid_fd, int nofork) {
1285 int socket_type, status;
1286 struct timeval tv = { 0, 100 * 1000 };
1294 if (child_count < 2) {
1299 socket_type = AF_UNIX;
1300 fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
1302 + /* check if some backend is listening on the socket
1303 + * as if we delete the socket-file and rebind there will be no "socket already in use" error
1305 + if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
1306 + fprintf(stderr, "%s.%d\n",
1307 + __FILE__, __LINE__);
1311 + if (-1 != connect(fcgi_fd, fcgi_addr, servlen)) {
1312 + fprintf(stderr, "%s.%d: socket is already used, can't spawn\n",
1313 + __FILE__, __LINE__);
1317 + /* cleanup previous socket if it exists */
1318 + unlink(unixsocket);
1321 fcgi_addr_in.sin_family = AF_INET;
1323 @@ -85,144 +107,128 @@
1324 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
1328 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
1329 fprintf(stderr, "%s.%d\n",
1330 __FILE__, __LINE__);
1334 - if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
1335 - /* server is not up, spawn in */
1339 + if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
1340 + fprintf(stderr, "%s.%d\n",
1341 + __FILE__, __LINE__);
1345 - if (unixsocket) unlink(unixsocket);
1346 + /* create socket */
1347 + if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
1348 + fprintf(stderr, "%s.%d: bind failed: %s\n",
1349 + __FILE__, __LINE__,
1355 + if (-1 == listen(fcgi_fd, 1024)) {
1356 + fprintf(stderr, "%s.%d: fd = -1\n",
1357 + __FILE__, __LINE__);
1361 - /* reopen socket */
1362 - if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
1363 - fprintf(stderr, "%s.%d\n",
1364 - __FILE__, __LINE__);
1374 - if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
1375 - fprintf(stderr, "%s.%d\n",
1376 - __FILE__, __LINE__);
1381 + char cgi_childs[64];
1383 - /* create socket */
1384 - if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
1385 - fprintf(stderr, "%s.%d: bind failed: %s\n",
1386 - __FILE__, __LINE__,
1392 - if (-1 == listen(fcgi_fd, 1024)) {
1393 - fprintf(stderr, "%s.%d: fd = -1\n",
1394 - __FILE__, __LINE__);
1396 + /* is safe as we limit to 256 childs */
1397 + sprintf(cgi_childs, "PHP_FCGI_CHILDREN=%d", child_count);
1399 + if(fcgi_fd != FCGI_LISTENSOCK_FILENO) {
1400 + close(FCGI_LISTENSOCK_FILENO);
1401 + dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
1409 + /* we don't need the client socket */
1410 + for (i = 3; i < 256; i++) {
1416 - char cgi_childs[64];
1418 + /* create environment */
1421 + putenv(cgi_childs);
1423 - /* is save as we limit to 256 childs */
1424 - sprintf(cgi_childs, "PHP_FCGI_CHILDREN=%d", child_count);
1425 + /* fork and replace shell */
1427 + execv(appArgv[0], appArgv);
1429 - if(fcgi_fd != FCGI_LISTENSOCK_FILENO) {
1430 - close(FCGI_LISTENSOCK_FILENO);
1431 - dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
1435 - /* we don't need the client socket */
1436 - for (i = 3; i < 256; i++) {
1440 - /* create environment */
1442 - putenv(cgi_childs);
1444 - /* fork and replace shell */
1445 - b = malloc(strlen("exec ") + strlen(appPath) + 1);
1447 + char *b = malloc(strlen("exec ") + strlen(appPath) + 1);
1452 execl("/bin/sh", "sh", "-c", b, (char *)NULL);
1474 - select(0, NULL, NULL, NULL, &tv);
1476 + select(0, NULL, NULL, NULL, &tv);
1478 - switch (waitpid(child, &status, WNOHANG)) {
1480 - fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n",
1481 - __FILE__, __LINE__,
1483 + switch (waitpid(child, &status, WNOHANG)) {
1485 + fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n",
1486 + __FILE__, __LINE__,
1489 - /* write pid file */
1490 - if (pid_fd != -1) {
1491 - /* assume a 32bit pid_t */
1493 + /* write pid file */
1494 + if (pid_fd != -1) {
1495 + /* assume a 32bit pid_t */
1498 - snprintf(pidbuf, sizeof(pidbuf) - 1, "%d", child);
1499 + snprintf(pidbuf, sizeof(pidbuf) - 1, "%d", child);
1501 - write(pid_fd, pidbuf, strlen(pidbuf));
1510 - if (WIFEXITED(status)) {
1511 - fprintf(stderr, "%s.%d: child exited with: %d, %s\n",
1512 - __FILE__, __LINE__,
1513 - WEXITSTATUS(status), strerror(WEXITSTATUS(status)));
1514 - } else if (WIFSIGNALED(status)) {
1515 - fprintf(stderr, "%s.%d: child signaled: %d\n",
1516 - __FILE__, __LINE__,
1517 - WTERMSIG(status));
1519 - fprintf(stderr, "%s.%d: child died somehow: %d\n",
1520 - __FILE__, __LINE__,
1523 + write(pid_fd, pidbuf, strlen(pidbuf));
1532 + if (WIFEXITED(status)) {
1533 + fprintf(stderr, "%s.%d: child exited with: %d, %s\n",
1534 + __FILE__, __LINE__,
1535 + WEXITSTATUS(status), strerror(WEXITSTATUS(status)));
1536 + } else if (WIFSIGNALED(status)) {
1537 + fprintf(stderr, "%s.%d: child signaled: %d\n",
1538 + __FILE__, __LINE__,
1539 + WTERMSIG(status));
1541 + fprintf(stderr, "%s.%d: child died somehow: %d\n",
1542 + __FILE__, __LINE__,
1547 - fprintf(stderr, "%s.%d: socket is already used, can't spawn\n",
1548 - __FILE__, __LINE__);
1555 @@ -239,9 +245,12 @@
1559 - char *b = "spawn-fcgi" "-" PACKAGE_VERSION \
1560 -" - spawns fastcgi processes\n" \
1563 +"Usage: spawn-fcgi [options] -- <fcgiapp> [fcgi app arguments]\n" \
1565 +"spawn-fcgi v" PACKAGE_VERSION " - spawns fastcgi processes\n" \
1568 " -f <fcgiapp> filename of the fcgi-application\n" \
1569 " -a <addr> bind to ip address\n" \
1570 " -p <port> bind to tcp-port\n" \
1572 char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
1573 *groupname = NULL, *unixsocket = NULL, *pid_file = NULL,
1575 + char **fcgi_app_argv = { NULL };
1576 unsigned short port = 0;
1577 int child_count = 5;
1579 @@ -274,10 +284,10 @@
1581 i_am_root = (getuid() == 0);
1583 - while(-1 != (o = getopt(argc, argv, "c:f:g:hna:p:u:vC:s:P:"))) {
1584 + while(-1 != (o = getopt(argc, argv, "c:f:g:hna:p:u:vC:s:P:"))) {
1586 case 'f': fcgi_app = optarg; break;
1587 - case 'a': addr = optarg;/* ip addr */ break;
1588 + case 'a': addr = optarg;/* ip addr */ break;
1589 case 'p': port = strtol(optarg, NULL, 10);/* port */ break;
1590 case 'C': child_count = strtol(optarg, NULL, 10);/* */ break;
1591 case 's': unixsocket = optarg; /* unix-domain socket */ break;
1592 @@ -294,7 +304,11 @@
1596 - if (fcgi_app == NULL || (port == 0 && unixsocket == NULL)) {
1597 + if (optind < argc) {
1598 + fcgi_app_argv = &argv[optind];
1601 + if ((fcgi_app == NULL && fcgi_app_argv == NULL) || (port == 0 && unixsocket == NULL)) {
1605 @@ -404,6 +418,18 @@
1610 + * Change group before chroot, when we have access
1614 + setgid(grp->gr_gid);
1615 + setgroups(0, NULL);
1617 + initgroups(username, grp->gr_gid);
1622 if (-1 == chroot(changeroot)) {
1623 fprintf(stderr, "%s.%d: %s %s\n",
1624 @@ -420,18 +446,12 @@
1627 /* drop root privs */
1629 - setgid(grp->gr_gid);
1633 - initgroups(username, grp->gr_gid);
1635 setuid(pwd->pw_uid);
1639 - return fcgi_spawn_connection(fcgi_app, addr, port, unixsocket, child_count, pid_fd, nofork);
1640 + return fcgi_spawn_connection(fcgi_app, fcgi_app_argv, addr, port, unixsocket, child_count, pid_fd, nofork);
1644 Index: src/mod_auth.c
1645 ===================================================================
1646 --- src/mod_auth.c (.../tags/lighttpd-1.4.18) (revision 2118)
1647 +++ src/mod_auth.c (.../branches/lighttpd-1.4.x) (revision 2118)
1648 @@ -238,13 +238,13 @@
1649 int auth_type_len = auth_realm - http_authorization;
1651 if ((auth_type_len == 5) &&
1652 - (0 == strncmp(http_authorization, "Basic", auth_type_len))) {
1653 + (0 == strncasecmp(http_authorization, "Basic", auth_type_len))) {
1655 if (0 == strcmp(method->value->ptr, "basic")) {
1656 auth_satisfied = http_auth_basic_check(srv, con, p, req, con->uri.path, auth_realm+1);
1658 } else if ((auth_type_len == 6) &&
1659 - (0 == strncmp(http_authorization, "Digest", auth_type_len))) {
1660 + (0 == strncasecmp(http_authorization, "Digest", auth_type_len))) {
1661 if (0 == strcmp(method->value->ptr, "digest")) {
1662 if (-1 == (auth_satisfied = http_auth_digest_check(srv, con, p, req, con->uri.path, auth_realm+1))) {
1663 con->http_status = 400;
1664 Index: src/mod_fastcgi.c
1665 ===================================================================
1666 --- src/mod_fastcgi.c (.../tags/lighttpd-1.4.18) (revision 2118)
1667 +++ src/mod_fastcgi.c (.../branches/lighttpd-1.4.x) (revision 2118)
1669 * if host is one of the local IP adresses the
1670 * whole connection is local
1672 - * if tcp/ip should be used host AND port have
1674 + * if port is not 0, and host is not specified,
1675 + * "localhost" (INADDR_LOOPBACK) is assumed.
1679 @@ -823,12 +823,12 @@
1680 fcgi_addr_in.sin_family = AF_INET;
1682 if (buffer_is_empty(host->host)) {
1683 - fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
1684 + fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1688 /* set a useful default */
1689 - fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
1690 + fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1693 if (NULL == (he = gethostbyname(host->host->ptr))) {
1694 @@ -858,7 +858,11 @@
1695 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
1697 buffer_copy_string(proc->connection_name, "tcp:");
1698 - buffer_append_string_buffer(proc->connection_name, host->host);
1699 + if (!buffer_is_empty(host->host)) {
1700 + buffer_append_string_buffer(proc->connection_name, host->host);
1702 + buffer_append_string(proc->connection_name, "localhost");
1704 buffer_append_string(proc->connection_name, ":");
1705 buffer_append_long(proc->connection_name, proc->port);
1707 @@ -1687,12 +1691,16 @@
1710 fcgi_addr_in.sin_family = AF_INET;
1711 - if (0 == inet_aton(host->host->ptr, &(fcgi_addr_in.sin_addr))) {
1712 - log_error_write(srv, __FILE__, __LINE__, "sbs",
1713 - "converting IP address failed for", host->host,
1714 - "\nBe sure to specify an IP address here");
1717 + if (!buffer_is_empty(host->host)) {
1718 + if (0 == inet_aton(host->host->ptr, &(fcgi_addr_in.sin_addr))) {
1719 + log_error_write(srv, __FILE__, __LINE__, "sbs",
1720 + "converting IP address failed for", host->host,
1721 + "\nBe sure to specify an IP address here");
1726 + fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1728 fcgi_addr_in.sin_port = htons(proc->port);
1729 servlen = sizeof(fcgi_addr_in);
1730 @@ -1702,7 +1710,11 @@
1731 if (buffer_is_empty(proc->connection_name)) {
1732 /* on remote spawing we have to set the connection-name now */
1733 buffer_copy_string(proc->connection_name, "tcp:");
1734 - buffer_append_string_buffer(proc->connection_name, host->host);
1735 + if (!buffer_is_empty(host->host)) {
1736 + buffer_append_string_buffer(proc->connection_name, host->host);
1738 + buffer_append_string(proc->connection_name, "localhost");
1740 buffer_append_string(proc->connection_name, ":");
1741 buffer_append_long(proc->connection_name, proc->port);
1743 @@ -2045,13 +2057,10 @@
1744 s = get_http_version_name(con->request.http_version);
1745 FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s)),con)
1748 - if (srv_sock->is_ssl) {
1749 + if (srv_sock->is_ssl || srv_sock->is_proxy_ssl) {
1750 FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on")),con)
1755 FCGI_ENV_ADD_CHECK(fcgi_env_add_request_headers(srv, con, p), con);
1757 fcgi_header(&(header), FCGI_PARAMS, request_id, p->fcgi_env->used, 0);
1758 @@ -2530,15 +2539,28 @@
1761 if (host->allow_xsendfile &&
1762 - NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-LIGHTTPD-send-file"))) {
1763 + (NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-LIGHTTPD-send-file"))
1764 + || NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-Sendfile")))) {
1765 stat_cache_entry *sce;
1767 if (HANDLER_ERROR != stat_cache_get_entry(srv, con, ds->value, &sce)) {
1768 + data_string *dcls = data_string_init();
1771 http_chunk_append_file(srv, con, ds->value, 0, sce->st.st_size);
1772 hctx->send_content_body = 0; /* ignore the content */
1773 joblist_append(srv, con);
1775 + buffer_copy_string_len(dcls->key, "Content-Length", sizeof("Content-Length")-1);
1776 + buffer_copy_long(dcls->value, sce->st.st_size);
1777 + dcls = (data_string*) array_replace(con->response.headers, (data_unset *)dcls);
1778 + if (dcls) dcls->free((data_unset*)dcls);
1780 + con->parsed_response |= HTTP_CONTENT_LENGTH;
1781 + con->response.content_length = sce->st.st_size;
1783 + log_error_write(srv, __FILE__, __LINE__, "sb",
1784 + "send-file error: couldn't get stat_cache entry for:",
1789 @@ -2719,9 +2741,14 @@
1793 - /* sanity check */
1797 + * - tcp socket (do not check host->host->uses, as it may be not set which means INADDR_LOOPBACK)
1801 - ((!host->host->used || !host->port) && !host->unixsocket->used)) {
1802 + (!host->port && !host->unixsocket->used)) {
1803 log_error_write(srv, __FILE__, __LINE__, "sxddd",
1806 @@ -3456,8 +3483,9 @@
1807 if (s_len < ct_len) continue;
1809 /* check extension in the form "/fcgi_pattern" */
1810 - if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
1812 + if (*(extension->key->ptr) == '/') {
1813 + if (strncmp(fn->ptr, extension->key->ptr, ct_len) == 0)
1815 } else if (0 == strncmp(fn->ptr + s_len - ct_len, extension->key->ptr, ct_len)) {
1816 /* check extension in the form ".fcg" */
1818 @@ -3473,7 +3501,7 @@
1819 for (k = 0; k < extension->used; k++) {
1820 host = extension->hosts[k];
1822 - /* we should have at least one proc that can do somthing */
1823 + /* we should have at least one proc that can do something */
1824 if (host->active_procs == 0) {
1828 ===================================================================
1829 --- src/stream.c (.../tags/lighttpd-1.4.18) (revision 2118)
1830 +++ src/stream.c (.../branches/lighttpd-1.4.x) (revision 2118)
1838 FORMAT_MESSAGE_ALLOCATE_BUFFER |
1840 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1849 ===================================================================
1850 --- src/server.c (.../tags/lighttpd-1.4.18) (revision 2118)
1851 +++ src/server.c (.../branches/lighttpd-1.4.x) (revision 2118)
1856 - /* #372: solaris need some fds extra for devpoll */
1857 - if (rlim.rlim_cur > 10) rlim.rlim_cur -= 10;
1859 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
1860 srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
1862 @@ -759,6 +756,19 @@
1868 + * Change group before chroot, when we have access
1871 + if (srv->srvconf.groupname->used) {
1872 + setgid(grp->gr_gid);
1873 + setgroups(0, NULL);
1874 + if (srv->srvconf.username->used) {
1875 + initgroups(srv->srvconf.username->ptr, grp->gr_gid);
1880 if (srv->srvconf.changeroot->used) {
1882 @@ -775,15 +785,7 @@
1885 /* drop root privs */
1886 - if (srv->srvconf.groupname->used) {
1887 - setgid(grp->gr_gid);
1888 - setgroups(0, NULL);
1891 if (srv->srvconf.username->used) {
1892 - if (srv->srvconf.groupname->used) {
1893 - initgroups(srv->srvconf.username->ptr, grp->gr_gid);
1895 setuid(pwd->pw_uid);
1898 @@ -891,6 +893,17 @@
1902 + // Close stderr ASAP in the child process to make sure that nothing
1903 + // is being written to that fd which may not be valid anymore.
1904 + if (-1 == log_error_open(srv)) {
1905 + log_error_write(srv, __FILE__, __LINE__, "s", "Opening errorlog failed. Going down.");
1907 + plugins_free(srv);
1908 + network_close(srv);
1913 if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) {
1914 log_error_write(srv, __FILE__, __LINE__, "s", "Configuration of plugins failed. Going down.");
1916 @@ -941,15 +954,7 @@
1920 - if (-1 == log_error_open(srv)) {
1921 - log_error_write(srv, __FILE__, __LINE__, "s",
1922 - "opening errorlog failed, dying");
1924 - plugins_free(srv);
1925 - network_close(srv);
1931 #ifdef HAVE_SIGACTION
1932 Index: src/network_linux_sendfile.c
1933 ===================================================================
1934 --- src/network_linux_sendfile.c (.../tags/lighttpd-1.4.18) (revision 2118)
1935 +++ src/network_linux_sendfile.c (.../branches/lighttpd-1.4.x) (revision 2118)
1940 + /* ok, we can't send more, let's try later again */
1945 "sendfile failed:", strerror(errno), fd);
1951 + } else if (r == 0) {
1953 /* We got an event to write but we wrote nothing
1955 Index: tests/mod-access.t
1956 ===================================================================
1957 --- tests/mod-access.t (.../tags/lighttpd-1.4.18) (revision 2118)
1958 +++ tests/mod-access.t (.../branches/lighttpd-1.4.x) (revision 2118)
1962 - # add current source dir to the include-path
1963 - # we need this for make distcheck
1964 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
1965 - unshift @INC, $srcdir;
1966 + # add current source dir to the include-path
1967 + # we need this for make distcheck
1968 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
1969 + unshift @INC, $srcdir;
1973 Index: tests/mod-auth.t
1974 ===================================================================
1975 --- tests/mod-auth.t (.../tags/lighttpd-1.4.18) (revision 2118)
1976 +++ tests/mod-auth.t (.../branches/lighttpd-1.4.x) (revision 2118)
1980 - # add current source dir to the include-path
1981 - # we need this for make distcheck
1982 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
1983 - unshift @INC, $srcdir;
1984 + # add current source dir to the include-path
1985 + # we need this for make distcheck
1986 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
1987 + unshift @INC, $srcdir;
1992 -use Test::More tests => 13;
1993 +use Test::More tests => 14;
1996 my $tf = LightyTest->new();
1998 $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
1999 ok($tf->handle_http($t) == 0, 'Basic-Auth: Valid Auth-token - htpasswd (des)');
2001 +$t->{REQUEST} = ( <<EOF
2002 +GET /server-config HTTP/1.0
2003 +Host: auth-htpasswd.example.org
2004 +Authorization: basic ZGVzOmRlcw==
2007 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
2008 +ok($tf->handle_http($t) == 0, 'Basic-Auth: Valid Auth-token - htpasswd (des) (lowercase)');
2012 skip "no md5 for crypt under cygwin", 1 if $^O eq 'cygwin';
2013 $t->{REQUEST} = ( <<EOF
2014 Index: tests/mod-secdownload.t
2015 ===================================================================
2016 Index: tests/core-response.t
2017 ===================================================================
2018 --- tests/core-response.t (.../tags/lighttpd-1.4.18) (revision 2118)
2019 +++ tests/core-response.t (.../branches/lighttpd-1.4.x) (revision 2118)
2024 - # add current source dir to the include-path
2025 - # we need this for make distcheck
2026 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
2027 - unshift @INC, $srcdir;
2028 + # add current source dir to the include-path
2029 + # we need this for make distcheck
2030 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
2031 + unshift @INC, $srcdir;
2035 Index: tests/mod-extforward.conf
2036 ===================================================================
2037 --- tests/mod-extforward.conf (.../tags/lighttpd-1.4.18) (revision 0)
2038 +++ tests/mod-extforward.conf (.../branches/lighttpd-1.4.x) (revision 2118)
2040 +debug.log-request-handling = "enable"
2041 +debug.log-response-header = "disable"
2042 +debug.log-request-header = "disable"
2044 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
2045 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
2047 +## bind to port (default: 80)
2050 +## bind to localhost (default: all interfaces)
2051 +server.bind = "localhost"
2052 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
2053 +server.name = "www.example.org"
2054 +server.tag = "Apache 1.3.29"
2061 +######################## MODULE CONFIG ############################
2063 +mimetype.assign = ( ".html" => "text/html" )
2065 +cgi.assign = (".pl" => "/usr/bin/perl" )
2067 +extforward.forwarder = (
2068 + "127.0.0.1" => "trust",
2069 + "127.0.30.1" => "trust",
2071 Index: tests/symlink.t
2072 ===================================================================
2073 Index: tests/request.t
2074 ===================================================================
2075 --- tests/request.t (.../tags/lighttpd-1.4.18) (revision 2118)
2076 +++ tests/request.t (.../branches/lighttpd-1.4.x) (revision 2118)
2080 - # add current source dir to the include-path
2081 - # we need this for make distcheck
2082 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
2083 - unshift @INC, $srcdir;
2084 + # add current source dir to the include-path
2085 + # we need this for make distcheck
2086 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
2087 + unshift @INC, $srcdir;
2091 Index: tests/mod-userdir.t
2092 ===================================================================
2093 --- tests/mod-userdir.t (.../tags/lighttpd-1.4.18) (revision 2118)
2094 +++ tests/mod-userdir.t (.../branches/lighttpd-1.4.x) (revision 2118)
2098 - # add current source dir to the include-path
2099 - # we need this for make distcheck
2100 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
2101 - unshift @INC, $srcdir;
2102 + # add current source dir to the include-path
2103 + # we need this for make distcheck
2104 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
2105 + unshift @INC, $srcdir;
2109 Index: tests/core-keepalive.t
2110 ===================================================================
2111 --- tests/core-keepalive.t (.../tags/lighttpd-1.4.18) (revision 2118)
2112 +++ tests/core-keepalive.t (.../branches/lighttpd-1.4.x) (revision 2118)
2117 - # add current source dir to the include-path
2118 - # we need this for make distcheck
2119 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
2120 - unshift @INC, $srcdir;
2121 + # add current source dir to the include-path
2122 + # we need this for make distcheck
2123 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
2124 + unshift @INC, $srcdir;
2128 Index: tests/mod-proxy.t
2129 ===================================================================
2130 Index: tests/env-variables.t
2131 ===================================================================
2132 Index: tests/core-var-include.t
2133 ===================================================================
2134 --- tests/core-var-include.t (.../tags/lighttpd-1.4.18) (revision 2118)
2135 +++ tests/core-var-include.t (.../branches/lighttpd-1.4.x) (revision 2118)
2139 - # add current source dir to the include-path
2140 - # we need this for make distcheck
2141 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
2142 - unshift @INC, $srcdir;
2143 + # add current source dir to the include-path
2144 + # we need this for make distcheck
2145 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
2146 + unshift @INC, $srcdir;
2150 Index: tests/mod-extforward.t
2151 ===================================================================
2152 --- tests/mod-extforward.t (.../tags/lighttpd-1.4.18) (revision 0)
2153 +++ tests/mod-extforward.t (.../branches/lighttpd-1.4.x) (revision 2118)
2155 +#!/usr/bin/env perl
2157 + # add current source dir to the include-path
2158 + # we need this for make distcheck
2159 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
2160 + unshift @INC, $srcdir;
2165 +use Test::More tests => 5;
2168 +my $tf = LightyTest->new();
2171 +$tf->{CONFIGFILE} = 'mod-extforward.conf';
2173 +ok($tf->start_proc == 0, "Starting lighttpd") or die();
2175 +$t->{REQUEST} = ( <<EOF
2176 +GET /ip.pl HTTP/1.0
2177 +Host: www.example.org
2178 +X-Forwarded-For: 127.0.10.1
2181 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '127.0.10.1' } ];
2182 +ok($tf->handle_http($t) == 0, 'expect 127.0.10.1, from single ip');
2184 +$t->{REQUEST} = ( <<EOF
2185 +GET /ip.pl HTTP/1.0
2186 +Host: www.example.org
2187 +X-Forwarded-For: 127.0.10.1, 127.0.20.1
2190 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '127.0.20.1' } ];
2191 +ok($tf->handle_http($t) == 0, 'expect 127.0.20.1, from two ips');
2193 +$t->{REQUEST} = ( <<EOF
2194 +GET /ip.pl HTTP/1.0
2195 +Host: www.example.org
2196 +X-Forwarded-For: 127.0.10.1, 127.0.20.1, 127.0.30.1
2199 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '127.0.20.1' } ];
2200 +ok($tf->handle_http($t) == 0, 'expect 127.0.20.1, from chained proxies');
2202 +ok($tf->stop_proc == 0, "Stopping lighttpd");
2204 Property changes on: tests/mod-extforward.t
2205 ___________________________________________________________________
2206 Name: svn:executable
2209 Index: tests/core-request.t
2210 ===================================================================
2211 --- tests/core-request.t (.../tags/lighttpd-1.4.18) (revision 2118)
2212 +++ tests/core-request.t (.../branches/lighttpd-1.4.x) (revision 2118)
2216 - # add current source dir to the include-path
2217 - # we need this for make distcheck
2218 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
2219 - unshift @INC, $srcdir;
2220 + # add current source dir to the include-path
2221 + # we need this for make distcheck
2222 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
2223 + unshift @INC, $srcdir;
2227 Index: tests/mod-redirect.t
2228 ===================================================================
2229 --- tests/mod-redirect.t (.../tags/lighttpd-1.4.18) (revision 2118)
2230 +++ tests/mod-redirect.t (.../branches/lighttpd-1.4.x) (revision 2118)
2234 - # add current source dir to the include-path
2235 - # we need this for make distcheck
2236 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
2237 - unshift @INC, $srcdir;
2238 + # add current source dir to the include-path
2239 + # we need this for make distcheck
2240 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
2241 + unshift @INC, $srcdir;
2245 Index: tests/mod-cgi.t
2246 ===================================================================
2247 --- tests/mod-cgi.t (.../tags/lighttpd-1.4.18) (revision 2118)
2248 +++ tests/mod-cgi.t (.../branches/lighttpd-1.4.x) (revision 2118)
2252 - # add current source dir to the include-path
2253 - # we need this for make distcheck
2254 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
2255 - unshift @INC, $srcdir;
2256 + # add current source dir to the include-path
2257 + # we need this for make distcheck
2258 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
2259 + unshift @INC, $srcdir;
2263 Index: tests/mod-setenv.t
2264 ===================================================================
2265 --- tests/mod-setenv.t (.../tags/lighttpd-1.4.18) (revision 2118)
2266 +++ tests/mod-setenv.t (.../branches/lighttpd-1.4.x) (revision 2118)
2271 - # add current source dir to the include-path
2272 - # we need this for make distcheck
2273 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
2274 - unshift @INC, $srcdir;
2275 + # add current source dir to the include-path
2276 + # we need this for make distcheck
2277 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
2278 + unshift @INC, $srcdir;
2282 Index: tests/cachable.t
2283 ===================================================================
2284 --- tests/cachable.t (.../tags/lighttpd-1.4.18) (revision 2118)
2285 +++ tests/cachable.t (.../branches/lighttpd-1.4.x) (revision 2118)
2289 - # add current source dir to the include-path
2290 - # we need this for make distcheck
2291 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
2292 - unshift @INC, $srcdir;
2293 + # add current source dir to the include-path
2294 + # we need this for make distcheck
2295 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
2296 + unshift @INC, $srcdir;
2300 Index: tests/lowercase.t
2301 ===================================================================
2302 --- tests/lowercase.t (.../tags/lighttpd-1.4.18) (revision 2118)
2303 +++ tests/lowercase.t (.../branches/lighttpd-1.4.x) (revision 2118)
2307 - # add current source dir to the include-path
2308 - # we need this for make distcheck
2309 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
2310 - unshift @INC, $srcdir;
2311 + # add current source dir to the include-path
2312 + # we need this for make distcheck
2313 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
2314 + unshift @INC, $srcdir;
2318 Index: tests/fcgi-responder.c
2319 ===================================================================
2320 --- tests/fcgi-responder.c (.../tags/lighttpd-1.4.18) (revision 2118)
2321 +++ tests/fcgi-responder.c (.../branches/lighttpd-1.4.x) (revision 2118)
2323 +#ifdef HAVE_CONFIG_H
2326 #ifdef HAVE_FASTCGI_FASTCGI_H
2327 #include <fastcgi/fcgi_stdio.h>
2329 Index: tests/fcgi-auth.c
2330 ===================================================================
2331 --- tests/fcgi-auth.c (.../tags/lighttpd-1.4.18) (revision 2118)
2332 +++ tests/fcgi-auth.c (.../branches/lighttpd-1.4.x) (revision 2118)
2334 +#ifdef HAVE_CONFIG_H
2337 #ifdef HAVE_FASTCGI_FASTCGI_H
2338 #include <fastcgi/fcgi_stdio.h>
2341 ===================================================================
2342 --- tests/core.t (.../tags/lighttpd-1.4.18) (revision 2118)
2343 +++ tests/core.t (.../branches/lighttpd-1.4.x) (revision 2118)
2348 - # add current source dir to the include-path
2349 - # we need this for make distcheck
2350 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
2351 - unshift @INC, $srcdir;
2352 + # add current source dir to the include-path
2353 + # we need this for make distcheck
2354 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
2355 + unshift @INC, $srcdir;
2359 Index: tests/mod-fastcgi.t
2360 ===================================================================
2361 --- tests/mod-fastcgi.t (.../tags/lighttpd-1.4.18) (revision 2118)
2362 +++ tests/mod-fastcgi.t (.../branches/lighttpd-1.4.x) (revision 2118)
2366 - # add current source dir to the include-path
2367 - # we need this for make distcheck
2368 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
2369 - unshift @INC, $srcdir;
2370 + # add current source dir to the include-path
2371 + # we need this for make distcheck
2372 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
2373 + unshift @INC, $srcdir;
2377 -use Test::More tests => 46;
2378 +use Test::More tests => 47;
2381 my $tf = LightyTest->new();
2386 - skip "no php found", 4 unless -x "/usr/bin/php-cgi";
2387 + skip "no php found", 5 unless -x "/usr/bin/php-cgi";
2388 $tf->{CONFIGFILE} = 'fastcgi-13.conf';
2389 ok($tf->start_proc == 0, "Starting lighttpd with $tf->{CONFIGFILE}") or die();
2390 $t->{REQUEST} = ( <<EOF
2391 @@ -234,6 +234,15 @@
2392 $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
2393 ok($tf->handle_http($t) == 0, 'FastCGI + local spawning');
2395 + $t->{REQUEST} = ( <<EOF
2396 +HEAD /indexfile/index.php HTTP/1.0
2397 +Host: www.example.org
2400 + $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '-Content-Length' => '0' } ];
2401 + # Of course a valid content-length != 0 would be ok, but we assume for now that such one is not generated.
2402 + ok($tf->handle_http($t) == 0, 'Check for buggy content length with HEAD');
2404 $t->{REQUEST} = ( <<EOF
2405 GET /get-env.php?env=MAIL HTTP/1.0
2406 Host: www.example.org
2407 Index: tests/mod-rewrite.t
2408 ===================================================================
2409 --- tests/mod-rewrite.t (.../tags/lighttpd-1.4.18) (revision 2118)
2410 +++ tests/mod-rewrite.t (.../branches/lighttpd-1.4.x) (revision 2118)
2414 - # add current source dir to the include-path
2415 - # we need this for make distcheck
2416 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
2417 - unshift @INC, $srcdir;
2418 + # add current source dir to the include-path
2419 + # we need this for make distcheck
2420 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
2421 + unshift @INC, $srcdir;
2425 Index: tests/docroot/www/ip.pl
2426 ===================================================================
2427 --- tests/docroot/www/ip.pl (.../tags/lighttpd-1.4.18) (revision 0)
2428 +++ tests/docroot/www/ip.pl (.../branches/lighttpd-1.4.x) (revision 2118)
2431 +print "Content-Type: text/html\r\n\r\n";
2432 +print $ENV{'REMOTE_ADDR'};
2434 +if ($ENV{'QUERY_STRING'} eq 'info') {
2435 + print "\nF:",$ENV{'HTTP_X_FORWARDED_FOR'},"\n";
2437 + while (my($key, $value) = each %ENV) {
2438 + printf "%s => %s\n", $key, $value;
2444 Property changes on: tests/docroot/www/ip.pl
2445 ___________________________________________________________________
2446 Name: svn:executable
2449 Index: tests/Makefile.am
2450 ===================================================================
2451 --- tests/Makefile.am (.../tags/lighttpd-1.4.18) (revision 2118)
2452 +++ tests/Makefile.am (.../branches/lighttpd-1.4.x) (revision 2118)
2459 + mod-secdownload.t \
2470 + env-variables.conf \
2476 core-404-handler.t \
2480 TESTS_ENVIRONMENT=$(srcdir)/wrapper.sh $(srcdir) $(top_builddir)
2482 EXTRA_DIST=wrapper.sh lighttpd.conf \
2489 Index: tests/core-404-handler.t
2490 ===================================================================
2491 --- tests/core-404-handler.t (.../tags/lighttpd-1.4.18) (revision 2118)
2492 +++ tests/core-404-handler.t (.../branches/lighttpd-1.4.x) (revision 2118)
2494 # returning no status -> 200
2497 - # add current source dir to the include-path
2498 - # we need this for make distcheck
2499 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
2500 - unshift @INC, $srcdir;
2501 + # add current source dir to the include-path
2502 + # we need this for make distcheck
2503 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
2504 + unshift @INC, $srcdir;
2508 Index: tests/mod-compress.t
2509 ===================================================================
2510 --- tests/mod-compress.t (.../tags/lighttpd-1.4.18) (revision 2118)
2511 +++ tests/mod-compress.t (.../branches/lighttpd-1.4.x) (revision 2118)
2515 - # add current source dir to the include-path
2516 - # we need this for make distcheck
2517 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
2518 - unshift @INC, $srcdir;
2519 + # add current source dir to the include-path
2520 + # we need this for make distcheck
2521 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
2522 + unshift @INC, $srcdir;
2526 Index: tests/LightyTest.pm
2527 ===================================================================
2528 --- tests/LightyTest.pm (.../tags/lighttpd-1.4.18) (revision 2118)
2529 +++ tests/LightyTest.pm (.../branches/lighttpd-1.4.x) (revision 2118)
2533 kill('TERM',$pid) or return -1;
2534 - select(undef, undef, undef, 0.01);
2535 + select(undef, undef, undef, 0.1);
2539 Index: tests/mod-ssi.t
2540 ===================================================================
2541 --- tests/mod-ssi.t (.../tags/lighttpd-1.4.18) (revision 2118)
2542 +++ tests/mod-ssi.t (.../branches/lighttpd-1.4.x) (revision 2118)
2546 - # add current source dir to the include-path
2547 - # we need this for make distcheck
2548 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
2549 - unshift @INC, $srcdir;
2550 + # add current source dir to the include-path
2551 + # we need this for make distcheck
2552 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
2553 + unshift @INC, $srcdir;
2557 Index: tests/core-condition.t
2558 ===================================================================
2559 --- tests/core-condition.t (.../tags/lighttpd-1.4.18) (revision 2118)
2560 +++ tests/core-condition.t (.../branches/lighttpd-1.4.x) (revision 2118)
2564 - # add current source dir to the include-path
2565 - # we need this for make distcheck
2566 - (my $srcdir = $0) =~ s#/[^/]+$#/#;
2567 - unshift @INC, $srcdir;
2568 + # add current source dir to the include-path
2569 + # we need this for make distcheck
2570 + (my $srcdir = $0) =~ s,/[^/]+$,/,;
2571 + unshift @INC, $srcdir;
2575 Index: tests/run-tests.pl
2576 ===================================================================
2577 --- tests/run-tests.pl (.../tags/lighttpd-1.4.18) (revision 2118)
2578 +++ tests/run-tests.pl (.../branches/lighttpd-1.4.x) (revision 2118)
2582 use Test::Harness qw(&runtests $verbose);
2584 +$verbose = (defined $ENV{'VERBOSE'} ? $ENV{'VERBOSE'} : 0);;
2586 my $srcdir = (defined $ENV{'srcdir'} ? $ENV{'srcdir'} : '.');
2588 Index: doc/configuration.txt
2589 ===================================================================
2590 --- doc/configuration.txt (.../tags/lighttpd-1.4.18) (revision 2118)
2591 +++ doc/configuration.txt (.../branches/lighttpd-1.4.x) (revision 2118)
2601 Index: doc/lighttpd.conf
2602 ===================================================================
2603 --- doc/lighttpd.conf (.../tags/lighttpd-1.4.18) (revision 2118)
2604 +++ doc/lighttpd.conf (.../branches/lighttpd-1.4.x) (revision 2118)
2606 ".ogg" => "application/ogg",
2607 ".wav" => "audio/x-wav",
2608 ".gif" => "image/gif",
2609 + ".jar" => "application/x-java-archive",
2610 ".jpg" => "image/jpeg",
2611 ".jpeg" => "image/jpeg",
2612 ".png" => "image/png",
2614 ===================================================================
2616 ===================================================================
2617 --- Makefile.am (.../tags/lighttpd-1.4.18) (revision 2118)
2618 +++ Makefile.am (.../branches/lighttpd-1.4.x) (revision 2118)
2620 SUBDIRS=src doc tests cygwin openwrt
2622 -EXTRA_DIST=lighttpd.spec
2623 +EXTRA_DIST=lighttpd.spec autogen.sh SConstruct
2625 ===================================================================
2626 --- NEWS (.../tags/lighttpd-1.4.18) (revision 2118)
2627 +++ NEWS (.../branches/lighttpd-1.4.x) (revision 2118)
2634 + * added support for If-Range: <date> (#1346)
2635 + * added support for matching $HTTP["scheme"] in configs
2636 + * fixed initgroups() called after chroot (#1384)
2637 + * fixed case-sensitive check for Auth-Method (#1456)
2638 + * execute fcgi app without /bin/sh if used as argument to spawn-fcgi (#1428)
2639 + * fixed a bug that made /-prefixed extensions being handled also when
2640 + matching the end of the uri in fcgi,scgi and proxy modules (#1489)
2641 + * print error if X-LIGHTTPD-send-file cannot be done; reset header
2642 + Content-Length for send-file. Patches by Stefan Buehler
2643 + * prevent crash in certain php-fcgi configurations (#841)
2644 + * add IdleServers and Scoreboard directives in ?auto mode for mod_status (#1507)
2645 + * open log immediately after daemonizing, fixes SIGPIPEs on startup (#165)
2646 + * HTTPS env var should be "on" when using mod_extforward and the X-Forwarded-Proto header is set. (#1499)
2647 + * generate ETag and Last-Modified headers for mod_ssi based on newest modified include (#1491)
2648 + * support letterhomes in mod_userdir (#1473)
2649 + * support chained proxies in mod_extforward (#1528)
2650 + * fixed bogus "cgi died ?" if we kill the CGI process on shutdown
2651 + * fixed ECONNRESET handling in network-openssl
2652 + * fixed handling of EAGAIN in network-linux-sendfile (#657)
2653 + * reset conditional cache (#1164)
2654 + * create directories in mod_compress (was broken with alias/userdir) (#1027)
2655 + * fixed out of range access in fd array (#1562, #372)
2656 + * mod_compress should check if the request is already handled, e.g. by fastcgi (#1565)
2657 + * remove broken workaround for buggy Opera version with ssl/chunked encoding (#285)
2658 + * generate etag/last-modified header for on-the-fly-compressed files (#1171)
2659 + * req-method OPTIONS: do not insert default response if request was denied, do not deny OPTIONS by default (#1324)
2660 + * fixed memory leak on windows (#1347)
2661 + * fixed building outside of the src dir (#1349)
2662 + * fixed including of stdint.h/inttypes.h in etag.c (#1413)
2663 + * do not add Accept-Ranges header if range-request is disabled (#1449)
2664 + * log the ip of failed auth tries in error.log (enhancement #1544)
2665 + * fixed RoundRobin in mod_proxy (#516)
2666 + * check for symlinks after successful pathinfo matching (#1574)
2667 + * fixed mod-proxy.t to run with a builddir outside of the src dir
2668 + * do not suppress content on "307 Temporary Redirect" (#1412)
2669 + * fixed Content-Length header if response body gets removed in connections.c (#1412, part 2)
2670 + * do not generate a "Content-Length: 0" header for HEAD requests, added test too
2671 + * remove compress cache file if compression or write failed (#1150)
2672 + * fixed body handling of status 300 requests
2673 + * spawn-fcgi: only try to connect to unix socket (not tcp) before spawning (#1575)
2674 + * fix sending source of cgi script instead of 500 error if fork fails
2675 + * fix min-procs handling in mod_scgi.c, just set to max-procs (patch from #623)
2676 + * fix sending "408 - Timeout" instead of "410 - Gone" for timedout urls in mod_secdownload (#1440)
2678 - 1.4.18 - 2007-09-09
2680 * fixed compile error on IRIX 6.5.x on prctl() (#1333)
2681 Index: lighttpd.spec.in
2682 ===================================================================
2683 --- lighttpd.spec.in (.../tags/lighttpd-1.4.18) (revision 2118)
2684 +++ lighttpd.spec.in (.../branches/lighttpd-1.4.x) (revision 2118)
2686 Packager: Jan Kneschke <jan@kneschke.de>
2688 Group: Networking/Daemons
2689 -URL: http://jan.kneschke.de/projects/lighttpd/
2690 +URL: http://www.lighttpd.net/
2691 Requires: pcre >= 3.1 zlib
2692 -BuildPrereq: libtool zlib-devel
2693 +BuildRequires: libtool zlib-devel
2694 BuildRoot: %{_tmppath}/%{name}-root
2698 lighttpd is intented to be a frontend for ad-servers which have to deliver
2699 small files concurrently to many connections.
2701 -Available rpmbuild rebuild options :
2702 ---with : ssl mysql lua memcache
2703 +Available rpmbuild rebuild options:
2704 +--with: ssl mysql lua memcache
2718 mkdir -p %{buildroot}%{_sysconfdir}/{init.d,sysconfig}
2719 -if test -f /etc/redhat-release -o -f /etc/fedora-release; then
2720 - install -m 755 doc/rc.lighttpd.redhat %{buildroot}%{_sysconfdir}/init.d/lighttpd
2721 +if [ -f /etc/redhat-release -o -f /etc/fedora-release ]; then
2722 + install -m 755 doc/rc.lighttpd.redhat %{buildroot}%{_sysconfdir}/init.d/lighttpd
2724 - install -m 755 doc/rc.lighttpd %{buildroot}%{_sysconfdir}/init.d/lighttpd
2725 + install -m 755 doc/rc.lighttpd %{buildroot}%{_sysconfdir}/init.d/lighttpd
2727 install -m 644 doc/sysconfig.lighttpd %{buildroot}%{_sysconfdir}/sysconfig/lighttpd
2732 ## read http://www.fedora.us/docs/spec.html next time :)
2733 -if test "$1" = "1"; then
2734 - # real install, not upgrade
2735 - /sbin/chkconfig --add lighttpd
2736 +if [ "$1" = "1" ]; then
2737 + # real install, not upgrade
2738 + /sbin/chkconfig --add lighttpd
2742 -if test "$1" = "0"; then
2743 - # real uninstall, not upgrade
2744 - %{_sysconfdir}/init.d/lighttpd stop
2745 - /sbin/chkconfig --del lighttpd
2746 +if [ "$1" = "0"]; then
2747 + # real uninstall, not upgrade
2748 + %{_sysconfdir}/init.d/lighttpd stop
2749 + /sbin/chkconfig --del lighttpd
2754 Property changes on: .
2755 ___________________________________________________________________
2757 - a98e19e4-a712-0410-8832-6551a15ffc53:/local/branches/lighttpd-1.4.x:1557
2758 + 152afb58-edef-0310-8abb-c4023f1b3aa9:/branches/lighttpd-1.3.x:499
2759 152afb58-edef-0310-8abb-c4023f1b3aa9:/branches/lighttpd-1.4.11-ssl-fixes:1346
2760 152afb58-edef-0310-8abb-c4023f1b3aa9:/branches/lighttpd-merge-1.4.x:1041
2761 152afb58-edef-0310-8abb-c4023f1b3aa9:/tags/lighttpd-1.4.11:1042
2762 152afb58-edef-0310-8abb-c4023f1b3aa9:/tags/release-1.3.13:105
2763 152afb58-edef-0310-8abb-c4023f1b3aa9:/trunk:104
2764 a98e19e4-a712-0410-8832-6551a15ffc53:/local/branches/lighttpd-1.4.x:1557
2765 ebd0e9cf-3e47-4385-9dd4-f0e25e97baa2:/local/lighttpd/branches/lighttpd-1.4.x:2154