-# Revision 2711
-Index: src/mod_cgi.c
-===================================================================
---- src/mod_cgi.c (.../tags/lighttpd-1.4.25)
-+++ src/mod_cgi.c (.../branches/lighttpd-1.4.x)
-@@ -747,6 +747,8 @@
- }
-
- if (pipe(from_cgi_fds)) {
-+ close(to_cgi_fds[0]);
-+ close(to_cgi_fds[1]);
- log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
- return -1;
- }
-@@ -1035,6 +1037,10 @@
- case -1:
- /* error */
- log_error_write(srv, __FILE__, __LINE__, "ss", "fork failed:", strerror(errno));
-+ close(from_cgi_fds[0]);
-+ close(from_cgi_fds[1]);
-+ close(to_cgi_fds[0]);
-+ close(to_cgi_fds[1]);
- return -1;
- break;
- default: {
-@@ -1181,6 +1187,7 @@
- plugin_config *s = p->config_storage[0];
-
- PATCH(cgi);
-+ PATCH(execute_x_only);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
-Index: src/base.h
-===================================================================
---- src/base.h (.../tags/lighttpd-1.4.25)
-+++ src/base.h (.../branches/lighttpd-1.4.x)
-@@ -431,7 +431,6 @@
-
- #ifdef USE_OPENSSL
- SSL *ssl;
-- buffer *ssl_error_want_reuse_buffer;
- # ifndef OPENSSL_NO_TLSEXT
- buffer *tlsext_server_name;
- # endif
-Index: src/mod_rewrite.c
-===================================================================
---- src/mod_rewrite.c (.../tags/lighttpd-1.4.25)
-+++ src/mod_rewrite.c (.../branches/lighttpd-1.4.x)
-@@ -394,7 +394,7 @@
- buffer_reset(con->request.uri);
-
- start = 0;
-- for (k = 0; k < pattern_len; k++) {
-+ for (k = 0; k+1 < pattern_len; k++) {
- if (pattern[k] == '$' || pattern[k] == '%') {
- /* got one */
-
+# Revision 2724
Index: src/connections.c
===================================================================
---- src/connections.c (.../tags/lighttpd-1.4.25)
+--- src/connections.c (.../tags/lighttpd-1.4.26)
+++ src/connections.c (.../branches/lighttpd-1.4.x)
-@@ -192,40 +192,42 @@
-
- static int connection_handle_read_ssl(server *srv, connection *con) {
- #ifdef USE_OPENSSL
-- int r, ssl_err, len, count = 0;
-+ int r, ssl_err, len, count = 0, read_offset, toread;
- buffer *b = NULL;
+@@ -82,6 +82,11 @@
- if (!con->conf.is_ssl) return -1;
+ if (-1 == con->ndx) return -1;
-- /* don't resize the buffer if we were in SSL_ERROR_WANT_* */
--
- ERR_clear_error();
- do {
-- if (!con->ssl_error_want_reuse_buffer) {
-- b = buffer_init();
-- buffer_prepare_copy(b, SSL_pending(con->ssl) + (16 * 1024)); /* the pending bytes + 16kb */
-+ if (NULL != con->read_queue->last) {
-+ b = con->read_queue->last->mem;
-+ }
-
-+ if (NULL == b || b->size - b->used < 1024) {
-+ b = chunkqueue_get_append_buffer(con->read_queue);
-+ len = SSL_pending(con->ssl);
-+ if (len < 4*1024) len = 4*1024; /* always alloc >= 4k buffer */
-+ buffer_prepare_copy(b, len + 1);
++ buffer_reset(con->uri.authority);
++ buffer_reset(con->uri.path);
++ buffer_reset(con->uri.query);
++ buffer_reset(con->request.orig_uri);
+
- /* overwrite everything with 0 */
- memset(b->ptr, 0, b->size);
-- } else {
-- b = con->ssl_error_want_reuse_buffer;
- }
+ i = con->ndx;
-- len = SSL_read(con->ssl, b->ptr, b->size - 1);
-- con->ssl_error_want_reuse_buffer = NULL; /* reuse it only once */
-+ read_offset = (b->used > 0) ? b->used - 1 : 0;
-+ toread = b->size - 1 - read_offset;
+ /* not last element */
+Index: src/network.c
+===================================================================
+--- src/network.c (.../tags/lighttpd-1.4.26)
++++ src/network.c (.../branches/lighttpd-1.4.x)
+@@ -82,6 +82,9 @@
+ buffer_copy_string(con->tlsext_server_name, servername);
+ buffer_to_lower(con->tlsext_server_name);
-+ len = SSL_read(con->ssl, b->ptr + read_offset, toread);
++ /* Sometimes this is still set, confusing COMP_HTTP_HOST */
++ buffer_reset(con->uri.authority);
+
- if (len > 0) {
-- b->used = len;
-+ if (b->used > 0) b->used--;
-+ b->used += len;
- b->ptr[b->used++] = '\0';
-
-- /* we move the buffer to the chunk-queue, no need to free it */
-+ con->bytes_read += len;
+ config_cond_cache_reset(srv, con);
+ config_setup_connection(srv, con);
-- chunkqueue_append_buffer_weak(con->read_queue, b);
- count += len;
-- con->bytes_read += len;
-- b = NULL;
- }
-- } while (len > 0 && count < MAX_READ_LIMIT);
-+ } while (len == toread && count < MAX_READ_LIMIT);
-
-
- if (len < 0) {
-@@ -234,11 +236,11 @@
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
- con->is_readable = 0;
-- con->ssl_error_want_reuse_buffer = b;
-
-- b = NULL;
-+ /* the manual says we have to call SSL_read with the same arguments next time.
-+ * we ignore this restriction; no one has complained about it in 1.5 yet, so it probably works anyway.
-+ */
-
-- /* we have to steal the buffer from the queue-queue */
- return 0;
- case SSL_ERROR_SYSCALL:
- /**
-@@ -297,16 +299,11 @@
-
- connection_set_state(srv, con, CON_STATE_ERROR);
-
-- buffer_free(b);
--
- return -1;
- } else if (len == 0) {
- con->is_readable = 0;
- /* the other end close the connection -> KEEP-ALIVE */
-
-- /* pipelining */
-- buffer_free(b);
--
- return -2;
- }
-
-@@ -321,26 +318,41 @@
- static int connection_handle_read(server *srv, connection *con) {
- int len;
- buffer *b;
-- int toread;
-+ int toread, read_offset;
-
- if (con->conf.is_ssl) {
- return connection_handle_read_ssl(srv, con);
- }
+@@ -525,7 +528,7 @@
-+ b = (NULL != con->read_queue->last) ? con->read_queue->last->mem : NULL;
-+
-+ /* default size for chunks is 4kb; only use bigger chunks if FIONREAD tells
-+ * us more than 4kb is available
-+ * if FIONREAD doesn't signal a big chunk we fill the previous buffer
-+ * if it has >= 1kb free
-+ */
- #if defined(__WIN32)
-- b = chunkqueue_get_append_buffer(con->read_queue);
-- buffer_prepare_copy(b, 4 * 1024);
-- len = recv(con->fd, b->ptr, b->size - 1, 0);
--#else
-- if (ioctl(con->fd, FIONREAD, &toread) || toread == 0) {
-+ if (NULL == b || b->size - b->used < 1024) {
- b = chunkqueue_get_append_buffer(con->read_queue);
- buffer_prepare_copy(b, 4 * 1024);
-+ }
-+
-+ read_offset = (b->used == 0) ? 0 : b->used - 1;
-+ len = recv(con->fd, b->ptr + read_offset, b->size - 1 - read_offset, 0);
-+#else
-+ if (ioctl(con->fd, FIONREAD, &toread) || toread == 0 || toread <= 4*1024) {
-+ if (NULL == b || b->size - b->used < 1024) {
-+ b = chunkqueue_get_append_buffer(con->read_queue);
-+ buffer_prepare_copy(b, 4 * 1024);
-+ }
- } else {
- if (toread > MAX_READ_LIMIT) toread = MAX_READ_LIMIT;
- b = chunkqueue_get_append_buffer(con->read_queue);
- buffer_prepare_copy(b, toread + 1);
- }
-- len = read(con->fd, b->ptr, b->size - 1);
+ if (!s->ssl_use_sslv2) {
+ /* disable SSLv2 */
+- if (SSL_OP_NO_SSLv2 != SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2)) {
++ if (!(SSL_OP_NO_SSLv2 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2))) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+ ERR_error_string(ERR_get_error(), NULL));
+ return -1;
+Index: src/response.c
+===================================================================
+--- src/response.c (.../tags/lighttpd-1.4.26)
++++ src/response.c (.../branches/lighttpd-1.4.x)
+@@ -136,6 +136,8 @@
+ X509 *xs;
+ X509_NAME *xn;
+ X509_NAME_ENTRY *xe;
++ int i, nentries;
+
-+ read_offset = (b->used == 0) ? 0 : b->used - 1;
-+ len = read(con->fd, b->ptr + read_offset, b->size - 1 - read_offset);
+ if (
+ SSL_get_verify_result(con->ssl) != X509_V_OK
+ || !(xs = SSL_get_peer_certificate(con->ssl))
+@@ -144,7 +146,7 @@
+ }
+
+ xn = X509_get_subject_name(xs);
+- for (int i = 0, nentries = X509_NAME_entry_count(xn); i < nentries; ++i) {
++ for (i = 0, nentries = X509_NAME_entry_count(xn); i < nentries; ++i) {
+ int xobjnid;
+ const char * xobjsn;
+ data_string *envds;
+@@ -581,7 +583,7 @@
+ };
#endif
+ if (S_ISDIR(sce->st.st_mode)) {
+- if (con->physical.path->ptr[con->physical.path->used - 2] != '/') {
++ if (con->uri.path->ptr[con->uri.path->used - 2] != '/') {
+ /* redirect to .../ */
- if (len < 0) {
-@@ -374,7 +386,8 @@
- con->is_readable = 0;
+ http_response_redirect_to_directory(srv, con);
+Index: src/mod_proxy.c
+===================================================================
+--- src/mod_proxy.c (.../tags/lighttpd-1.4.26)
++++ src/mod_proxy.c (.../branches/lighttpd-1.4.x)
+@@ -349,6 +349,10 @@
+ srv->cur_fds--;
}
-- b->used = len;
-+ if (b->used > 0) b->used--;
-+ b->used += len;
- b->ptr[b->used++] = '\0';
-
- con->bytes_read += len;
-@@ -850,13 +863,6 @@
- /* The cond_cache gets reset in response.c */
- /* config_cond_cache_reset(srv, con); */
-
--#ifdef USE_OPENSSL
-- if (con->ssl_error_want_reuse_buffer) {
-- buffer_free(con->ssl_error_want_reuse_buffer);
-- con->ssl_error_want_reuse_buffer = NULL;
-- }
--#endif
--
- con->header_len = 0;
- con->in_error_handler = 0;
-
-@@ -945,62 +951,50 @@
- last_chunk = NULL;
- last_offset = 0;
-
-- for (c = cq->first; !last_chunk && c; c = c->next) {
-+ for (c = cq->first; c; c = c->next) {
- buffer b;
- size_t i;
-
- b.ptr = c->mem->ptr + c->offset;
- b.used = c->mem->used - c->offset;
-+ if (b.used > 0) b.used--; /* buffer "used" includes terminating zero */
-
-- for (i = 0; !last_chunk && i < b.used; i++) {
-+ for (i = 0; i < b.used; i++) {
- char ch = b.ptr[i];
-- size_t have_chars = 0;
-
-- switch (ch) {
-- case '\r':
-- /* we have to do a 4 char lookup */
-- have_chars = b.used - i - 1;
-+ if ('\r' == ch) {
-+ /* chec if \n\r\n follows */
-+ size_t j = i+1;
-+ chunk *cc = c;
-+ const char header_end[] = "\r\n\r\n";
-+ int header_end_match_pos = 1;
-
-- if (have_chars >= 4) {
-- /* all chars are in this buffer */
-+ for ( ; cc; cc = cc->next, j = 0 ) {
-+ buffer bb;
-+ bb.ptr = cc->mem->ptr + cc->offset;
-+ bb.used = cc->mem->used - cc->offset;
-+ if (bb.used > 0) bb.used--; /* buffer "used" includes terminating zero */
++ if (hctx->host) {
++ hctx->host->usage--;
++ }
++
+ handler_ctx_free(hctx);
+ con->plugin_ctx[p->id] = NULL;
+ }
+@@ -848,11 +852,11 @@
+ if (-1 == ret) { /* error on our side */
+ log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
-- if (0 == strncmp(b.ptr + i, "\r\n\r\n", 4)) {
-- /* found */
-- last_chunk = c;
-- last_offset = i + 4;
-+ for ( ; j < bb.used; j++) {
-+ ch = bb.ptr[j];
+- return HANDLER_WAIT_FOR_EVENT;
++ return HANDLER_ERROR;
+ } else if (-2 == ret) { /* remote close */
+ log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed, remote connection close:", strerror(errno), errno);
-- break;
-- }
-- } else {
-- chunk *lookahead_chunk = c->next;
-- size_t missing_chars;
-- /* looks like the following chars are not in the same chunk */
--
-- missing_chars = 4 - have_chars;
--
-- if (lookahead_chunk && lookahead_chunk->type == MEM_CHUNK) {
-- /* is the chunk long enough to contain the other chars ? */
--
-- if (lookahead_chunk->mem->used > missing_chars) {
-- if (0 == strncmp(b.ptr + i, "\r\n\r\n", have_chars) &&
-- 0 == strncmp(lookahead_chunk->mem->ptr, "\r\n\r\n" + have_chars, missing_chars)) {
--
-- last_chunk = lookahead_chunk;
-- last_offset = missing_chars;
--
-- break;
-+ if (ch == header_end[header_end_match_pos]) {
-+ header_end_match_pos++;
-+ if (4 == header_end_match_pos) {
-+ last_chunk = cc;
-+ last_offset = j+1;
-+ goto found_header_end;
- }
- } else {
-- /* a splited \r \n */
-- break;
-+ goto reset_search;
- }
- }
- }
--
-- break;
- }
-+reset_search: ;
- }
+- return HANDLER_WAIT_FOR_EVENT;
++ return HANDLER_ERROR;
}
-+found_header_end:
-
- /* found */
- if (last_chunk) {
-@@ -1140,8 +1134,15 @@
- } else {
- buffer *b;
-
-- b = chunkqueue_get_append_buffer(dst_cq);
-- buffer_copy_string_len(b, c->mem->ptr + c->offset, toRead);
-+ if (dst_cq->last &&
-+ dst_cq->last->type == MEM_CHUNK) {
-+ b = dst_cq->last->mem;
-+ } else {
-+ b = chunkqueue_get_append_buffer(dst_cq);
-+ /* prepare buffer size for remaining POST data; is < 64kb */
-+ buffer_prepare_copy(b, con->request.content_length - dst_cq->bytes_in + 1);
-+ }
-+ buffer_append_string_len(b, c->mem->ptr + c->offset, toRead);
- }
-
- c->offset += toRead;
-Index: src/chunk.c
-===================================================================
---- src/chunk.c (.../tags/lighttpd-1.4.25)
-+++ src/chunk.c (.../branches/lighttpd-1.4.x)
-@@ -197,8 +197,6 @@
- int chunkqueue_append_buffer_weak(chunkqueue *cq, buffer *mem) {
- chunk *c;
-- if (mem->used == 0) return 0;
+ if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
+@@ -989,8 +993,6 @@
+ case 0:
+ break;
+ case 1:
+- hctx->host->usage--;
-
- c = chunkqueue_get_unused_chunk(cq);
- c->type = MEM_CHUNK;
- c->offset = 0;
-Index: src/mod_proxy.c
-===================================================================
---- src/mod_proxy.c (.../tags/lighttpd-1.4.25)
-+++ src/mod_proxy.c (.../branches/lighttpd-1.4.x)
-@@ -1047,12 +1047,33 @@
- *
- */
-
-- proxy_connection_close(srv, hctx);
-- joblist_append(srv, con);
-+ if (hctx->host) {
-+ hctx->host->is_disabled = 1;
-+ hctx->host->disable_ts = srv->cur_ts;
-+ log_error_write(srv, __FILE__, __LINE__, "sbdd", "proxy-server disabled:",
-+ hctx->host->host,
-+ hctx->host->port,
-+ hctx->fd);
+ /* we are done */
+ proxy_connection_close(srv, hctx);
-- con->http_status = 503;
-- con->mode = DIRECT;
-+ /* disable this server */
-+ hctx->host->is_disabled = 1;
-+ hctx->host->disable_ts = srv->cur_ts;
-
-+ proxy_connection_close(srv, hctx);
-+
-+ /* reset the enviroment and restart the sub-request */
-+ buffer_reset(con->physical.path);
-+ con->mode = DIRECT;
-+
-+ joblist_append(srv, con);
-+ } else {
-+ proxy_connection_close(srv, hctx);
-+ joblist_append(srv, con);
-+
-+ con->mode = DIRECT;
-+ con->http_status = 503;
-+ }
-+
+@@ -1077,8 +1079,11 @@
return HANDLER_FINISHED;
}
-Index: src/mod_redirect.c
-===================================================================
---- src/mod_redirect.c (.../tags/lighttpd-1.4.25)
-+++ src/mod_redirect.c (.../branches/lighttpd-1.4.x)
-@@ -210,7 +210,7 @@
- buffer_reset(p->location);
-
- start = 0;
-- for (k = 0; k < pattern_len; k++) {
-+ for (k = 0; k + 1 < pattern_len; k++) {
- if (pattern[k] == '$' || pattern[k] == '%') {
- /* got one */
-
-Index: src/mod_fastcgi.c
-===================================================================
---- src/mod_fastcgi.c (.../tags/lighttpd-1.4.25)
-+++ src/mod_fastcgi.c (.../branches/lighttpd-1.4.x)
-@@ -2307,6 +2307,9 @@
- filename = pos;
- if (NULL == (range = strchr(pos, ' '))) {
- /* missing range */
-+ if (p->conf.debug) {
-+ log_error_write(srv, __FILE__, __LINE__, "ss", "Couldn't find range after filename:", filename);
-+ }
- return 1;
- }
- buffer_copy_string_len(srv->tmp_buf, filename, range - filename);
-@@ -2338,14 +2341,24 @@
- char *rpos = NULL;
- errno = 0;
- begin_range = strtoll(range, &rpos, 10);
-- if (errno != 0 || begin_range < 0 || rpos == range) return 1;
-- if ('-' != *rpos++) return 1;
-+ if (errno != 0 || begin_range < 0 || rpos == range) goto range_failed;
-+ if ('-' != *rpos++) goto range_failed;
- if (rpos != pos) {
- range = rpos;
- end_range = strtoll(range, &rpos, 10);
-- if (errno != 0 || end_range < 0 || rpos == range) return 1;
-+ if (errno != 0 || end_range < 0 || rpos == range) goto range_failed;
- }
-- if (rpos != pos) return 1;
-+ if (rpos != pos) goto range_failed;
-+
-+ goto range_success;
++ if (!con->file_finished) {
++ http_chunk_append_mem(srv, con, NULL, 0);
++ }
+
-+range_failed:
-+ if (p->conf.debug) {
-+ log_error_write(srv, __FILE__, __LINE__, "ss", "Couldn't decode range after filename:", filename);
+ con->file_finished = 1;
+-
+ proxy_connection_close(srv, hctx);
+ joblist_append(srv, con);
+ } else if (revents & FDEVENT_ERR) {
+@@ -1086,6 +1091,7 @@
+
+ log_error_write(srv, __FILE__, __LINE__, "sd", "proxy-FDEVENT_ERR, but no HUP", revents);
+
++ con->file_finished = 1;
+ joblist_append(srv, con);
+ proxy_connection_close(srv, hctx);
+ }
+Index: src/Makefile.am
+===================================================================
+--- src/Makefile.am (.../tags/lighttpd-1.4.26)
++++ src/Makefile.am (.../branches/lighttpd-1.4.x)
+@@ -19,7 +19,7 @@
+ REVISION=""; \
+ fi; \
+ fi; \
+- if test -z "$$REVISION" -a -x "`which git`"; then \
++ if test -z "$$REVISION" -a -d "$(top_srcdir)/.git" -a -x "`which git`"; then \
+ REVISION="$$(cd "$(top_srcdir)"; LANG= LC_ALL=C git describe --always 2>/dev/null || echo)"; \
+ fi; \
+ if test -n "$$REVISION"; then \
+Index: src/mod_compress.c
+===================================================================
+--- src/mod_compress.c (.../tags/lighttpd-1.4.26)
++++ src/mod_compress.c (.../branches/lighttpd-1.4.x)
+@@ -744,6 +744,7 @@
+ int accept_encoding = 0;
+ char *value = ds->value->ptr;
+ int matched_encodings = 0;
++ int use_etag = sce->etag != NULL && sce->etag->ptr != NULL;
+
+ /* get client side support encodings */
+ #ifdef USE_ZLIB
+@@ -770,12 +771,14 @@
+ mtime = strftime_cache_get(srv, sce->st.st_mtime);
+
+ /* try matching original etag of uncompressed version */
+- etag_mutate(con->physical.etag, sce->etag);
+- if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
+- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
+- response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
+- response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
+- return HANDLER_FINISHED;
++ if (use_etag) {
++ etag_mutate(con->physical.etag, sce->etag);
++ if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
++ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
++ response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
++ response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
++ return HANDLER_FINISHED;
+ }
-+ return 1;
-+
-+range_success: ;
}
- /* no parameters accepted */
-Index: src/mod_accesslog.c
-===================================================================
---- src/mod_accesslog.c (.../tags/lighttpd-1.4.25)
-+++ src/mod_accesslog.c (.../branches/lighttpd-1.4.x)
-@@ -788,6 +788,13 @@
- buffer_append_string_len(b, CONST_STR_LEN("-"));
- }
- break;
-+ case FORMAT_ENV:
-+ if (NULL != (ds = (data_string *)array_get_element(con->environment, p->conf.parsed_format->ptr[j]->string->ptr))) {
-+ accesslog_append_escaped(b, ds->value);
-+ } else {
-+ buffer_append_string_len(b, CONST_STR_LEN("-"));
-+ }
-+ break;
- case FORMAT_FILENAME:
- if (con->physical.path->used > 1) {
- buffer_append_string_buffer(b, con->physical.path);
-@@ -864,7 +871,6 @@
- { 'A', FORMAT_LOCAL_ADDR },
- { 'C', FORMAT_COOKIE },
- { 'D', FORMAT_TIME_USED_MS },
-- { 'e', FORMAT_ENV },
- */
-
- break;
-Index: tests/request.t
-===================================================================
---- tests/request.t (.../tags/lighttpd-1.4.25)
-+++ tests/request.t (.../branches/lighttpd-1.4.x)
-@@ -8,7 +8,7 @@
-
- use strict;
- use IO::Socket;
--use Test::More tests => 41;
-+use Test::More tests => 42;
- use LightyTest;
-
- my $tf = LightyTest->new();
-@@ -389,5 +389,14 @@
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304, '-Content-Length' => '' } ];
- ok($tf->handle_http($t) == 0, 'Status 304 has no Content-Length (#1002)');
-
-+$t->{REQUEST} = ( <<EOF
-+GET /12345.txt HTTP/1.0
-+Host: 123.example.org
-+EOF
-+ );
-+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '12345'."\n", 'Content-Type' => 'text/plain' } ];
-+$t->{SLOWREQUEST} = 1;
-+ok($tf->handle_http($t) == 0, 'GET, slow \\r\\n\\r\\n (#2105)');
-+
- ok($tf->stop_proc == 0, "Stopping lighttpd");
-
-Index: tests/LightyTest.pm
-===================================================================
---- tests/LightyTest.pm (.../tags/lighttpd-1.4.25)
-+++ tests/LightyTest.pm (.../branches/lighttpd-1.4.x)
-@@ -76,7 +76,7 @@
- kill('TERM', $pid) or return -1;
- return -1 if ($pid != waitpid($pid, 0));
- } else {
-- diag("Process not started, nothing to stop");
-+ diag("\nProcess not started, nothing to stop");
- return -1;
- }
-
-@@ -98,7 +98,7 @@
- return -1;
- }
- if (0 >= $timeout) {
-- diag("Timeout while trying to connect; killing child");
-+ diag("\nTimeout while trying to connect; killing child");
- kill('TERM', $child);
- return -1;
- }
-@@ -128,10 +128,10 @@
- } elsif (defined $ENV{"TRACEME"} && $ENV{"TRACEME"} eq 'valgrind') {
- $cmdline = "valgrind --tool=memcheck --show-reachable=yes --leak-check=yes --log-file=valgrind ".$cmdline;
- }
-- # diag("starting lighttpd at :".$self->{PORT}.", cmdline: ".$cmdline );
-+ # diag("\nstarting lighttpd at :".$self->{PORT}.", cmdline: ".$cmdline );
- my $child = fork();
- if (not defined $child) {
-- diag("Fork failed");
-+ diag("\nFork failed");
- return -1;
- }
- if ($child == 0) {
-@@ -139,7 +139,7 @@
- }
-
- if (0 != $self->wait_for_port_with_proc($self->{PORT}, $child)) {
-- diag(sprintf('The process %i is not up', $child));
-+ diag(sprintf('\nThe process %i is not up', $child));
- return -1;
- }
-
-@@ -157,6 +157,7 @@
-
- my @request = $t->{REQUEST};
- my @response = $t->{RESPONSE};
-+ my $slow = defined $t->{SLOWREQUEST};
- my $is_debug = $ENV{"TRACE_HTTP"};
-
- my $remote =
-@@ -165,33 +166,56 @@
- PeerPort => $self->{PORT});
-
- if (not defined $remote) {
-- diag("connect failed: $!");
-+ diag("\nconnect failed: $!");
- return -1;
- }
-
- $remote->autoflush(1);
-
-- diag("sending request header to ".$host.":".$self->{PORT}) if $is_debug;
-- foreach(@request) {
-- # pipeline requests
-- s/\r//g;
-- s/\n/$EOL/g;
-+ if (!$slow) {
-+ diag("\nsending request header to ".$host.":".$self->{PORT}) if $is_debug;
-+ foreach(@request) {
-+ # pipeline requests
-+ s/\r//g;
-+ s/\n/$EOL/g;
-
-- print $remote $_.$BLANK;
-- diag("<< ".$_) if $is_debug;
-+ print $remote $_.$BLANK;
-+ diag("\n<< ".$_) if $is_debug;
-+ }
-+ shutdown($remote, 1); # I've stopped writing data
-+ } else {
-+ diag("\nsending request header to ".$host.":".$self->{PORT}) if $is_debug;
-+ foreach(@request) {
-+ # pipeline requests
-+ chomp;
-+ s/\r//g;
-+ s/\n/$EOL/g;
-+
-+ print $remote $_;
-+ diag("<< ".$_."\n") if $is_debug;
-+ select(undef, undef, undef, 0.1);
-+ print $remote "\015";
-+ select(undef, undef, undef, 0.1);
-+ print $remote "\012";
-+ select(undef, undef, undef, 0.1);
-+ print $remote "\015";
-+ select(undef, undef, undef, 0.1);
-+ print $remote "\012";
-+ select(undef, undef, undef, 0.1);
-+ }
-+
- }
-- shutdown($remote, 1); # I've stopped writing data
-- diag("... done") if $is_debug;
-+ diag("\n... done") if $is_debug;
-
- my $lines = "";
-
-- diag("receiving response") if $is_debug;
-+ diag("\nreceiving response") if $is_debug;
- # read everything
- while(<$remote>) {
- $lines .= $_;
- diag(">> ".$_) if $is_debug;
- }
-- diag("... done") if $is_debug;
-+ diag("\n... done") if $is_debug;
-
- close $remote;
-
-@@ -209,7 +233,7 @@
- (my $line, $lines) = split($EOL, $lines, 2);
-
- # header finished
-- last if(length($line) == 0);
-+ last if(!defined $line or length($line) == 0);
-
- if ($ln == 0) {
- # response header
-@@ -221,21 +245,21 @@
- (my $h = $1) =~ tr/[A-Z]/[a-z]/;
-
- if (defined $resp_hdr{$h}) {
--# diag(sprintf("header '%s' is duplicated: '%s' and '%s'\n",
-+# diag(sprintf("\nheader '%s' is duplicated: '%s' and '%s'\n",
- # $h, $resp_hdr{$h}, $2));
- $resp_hdr{$h} .= ', '.$2;
- } else {
- $resp_hdr{$h} = $2;
+ /* select best matching encoding */
+@@ -790,22 +793,26 @@
+ compression_name = dflt_deflate;
}
- } else {
-- diag(sprintf("unexpected line '%s'\n", $line));
-+ diag(sprintf("\nunexpected line '%s'", $line));
- return -1;
- }
- }
- }
- if (not defined($resp_line)) {
-- diag(sprintf("empty response\n"));
-+ diag(sprintf("\nempty response"));
- return -1;
- }
-
-@@ -259,29 +283,29 @@
- # check conditions
- if ($resp_line =~ /^(HTTP\/1\.[01]) ([0-9]{3}) .+$/) {
- if ($href->{'HTTP-Protocol'} ne $1) {
-- diag(sprintf("proto failed: expected '%s', got '%s'\n", $href->{'HTTP-Protocol'}, $1));
-+ diag(sprintf("\nproto failed: expected '%s', got '%s'", $href->{'HTTP-Protocol'}, $1));
- return -1;
- }
- if ($href->{'HTTP-Status'} ne $2) {
-- diag(sprintf("status failed: expected '%s', got '%s'\n", $href->{'HTTP-Status'}, $2));
-+ diag(sprintf("\nstatus failed: expected '%s', got '%s'", $href->{'HTTP-Status'}, $2));
- return -1;
- }
- } else {
-- diag(sprintf("unexpected resp_line '%s'\n", $resp_line));
-+ diag(sprintf("\nunexpected resp_line '%s'", $resp_line));
- return -1;
- }
-
- if (defined $href->{'HTTP-Content'}) {
- $resp_body = "" unless defined $resp_body;
- if ($href->{'HTTP-Content'} ne $resp_body) {
-- diag(sprintf("body failed: expected '%s', got '%s'\n", $href->{'HTTP-Content'}, $resp_body));
-+ diag(sprintf("\nbody failed: expected '%s', got '%s'", $href->{'HTTP-Content'}, $resp_body));
- return -1;
- }
- }
-
- if (defined $href->{'-HTTP-Content'}) {
- if (defined $resp_body && $resp_body ne '') {
-- diag(sprintf("body failed: expected empty body, got '%s'\n", $resp_body));
-+ diag(sprintf("\nbody failed: expected empty body, got '%s'", $resp_body));
- return -1;
- }
- }
-@@ -309,12 +333,12 @@
-
- if ($key_inverted) {
- if (defined $resp_hdr{$k}) {
-- diag(sprintf("header '%s' MUST not be set\n", $k));
-+ diag(sprintf("\nheader '%s' MUST not be set", $k));
- return -1;
- }
- } else {
- if (not defined $resp_hdr{$k}) {
-- diag(sprintf("required header '%s' is missing\n", $k));
-+ diag(sprintf("\nrequired header '%s' is missing", $k));
- return -1;
- }
- }
-@@ -322,12 +346,12 @@
- if ($verify_value) {
- if ($href->{$_} =~ /^\/(.+)\/$/) {
- if ($resp_hdr{$k} !~ /$1/) {
-- diag(sprintf("response-header failed: expected '%s', got '%s', regex: %s\n",
-+ diag(sprintf("\nresponse-header failed: expected '%s', got '%s', regex: %s",
- $href->{$_}, $resp_hdr{$k}, $1));
- return -1;
+- /* try matching etag of compressed version */
+- buffer_copy_string_buffer(srv->tmp_buf, sce->etag);
+- buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("-"));
+- buffer_append_string(srv->tmp_buf, compression_name);
+- etag_mutate(con->physical.etag, srv->tmp_buf);
++ if (use_etag) {
++ /* try matching etag of compressed version */
++ buffer_copy_string_buffer(srv->tmp_buf, sce->etag);
++ buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("-"));
++ buffer_append_string(srv->tmp_buf, compression_name);
++ etag_mutate(con->physical.etag, srv->tmp_buf);
++ }
+
+ if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
+ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
+ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
+ response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
+- response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
++ if (use_etag) {
++ response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
++ }
+ return HANDLER_FINISHED;
}
- } elsif ($href->{$_} ne $resp_hdr{$k}) {
-- diag(sprintf("response-header failed: expected '%s', got '%s'\n",
-+ diag(sprintf("\nresponse-header failed: expected '%s', got '%s'",
- $href->{$_}, $resp_hdr{$k}));
- return -1;
- }
-@@ -337,7 +361,7 @@
- # we should have sucked up everything
- if (defined $lines) {
-- diag(sprintf("unexpected lines '%s'\n", $lines));
-+ diag(sprintf("\nunexpected lines '%s'", $lines));
- return -1;
- }
-
-@@ -348,7 +372,7 @@
- my ($self, $binary, $port) = @_;
- my $child = fork();
- if (not defined $child) {
-- diag("Couldn't fork\n");
-+ diag("\nCouldn't fork");
- return -1;
- }
- if ($child == 0) {
-@@ -362,7 +386,7 @@
- exec $binary or die($?);
- } else {
- if (0 != $self->wait_for_port_with_proc($port, $child)) {
-- diag(sprintf('The process %i is not up (port %i, %s)', $child, $port, $binary));
-+ diag(sprintf("\nThe process %i is not up (port %i, %s)", $child, $port, $binary));
- return -1;
- }
- return $child;
-Index: tests/run-tests.pl
-===================================================================
---- tests/run-tests.pl (.../tags/lighttpd-1.4.25)
-+++ tests/run-tests.pl (.../branches/lighttpd-1.4.x)
-@@ -17,4 +17,4 @@
- }
- }
- closedir DIR;
--runtests @fs;
-+runtests (sort @fs);
+ /* deflate it */
+- if (p->conf.compress_cache_dir->used) {
++ if (use_etag && p->conf.compress_cache_dir->used) {
+ if (0 != deflate_file_to_file(srv, con, p, con->physical.path, sce, compression_type))
+ return HANDLER_GO_ON;
+ } else {
+@@ -814,7 +821,9 @@
+ }
+ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
+ response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
+- response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
++ if (use_etag) {
++ response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
++ }
+ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
+ /* let mod_staticfile handle the cached compressed files, physical path was modified */
+ return p->conf.compress_cache_dir->used ? HANDLER_GO_ON : HANDLER_FINISHED;
Index: configure.ac
===================================================================
Index: SConstruct
===================================================================
Index: NEWS
===================================================================
---- NEWS (.../tags/lighttpd-1.4.25)
+--- NEWS (.../tags/lighttpd-1.4.26)
+++ NEWS (.../branches/lighttpd-1.4.x)
-@@ -3,7 +3,18 @@
+@@ -3,7 +3,16 @@
NEWS
====
--- 1.4.25 -
-+- 1.4.26 -
-+ * Fix request parser to handle packets with splitted \r\n\r\n (fixes #2105)
-+ * Remove dependency on automake >= 1.11 with m4_ifdef check
-+ * mod_accesslog: support %e (fixes #2113, thx presbrey)
-+ * Fix mod_cgi cgi.execute-x-only option in global block
-+ * mod_fastcgi: x-sendfile2 parse error debugging
-+ * Fix mod_proxy dead host detection if connect() fails
-+ * Fix fd leaks in mod_cgi (fds not closed on pipe/fork failures, found by Rodrigo, fixes #2158, #2159)
-+ * Fix segfault with broken rewrite/redirect patterns (fixes #2140, found by crypt)
-+ * Append to previous buffer in con read (fixes #2147, found by liming, CVE-2010-0295)
+-- 1.4.26 -
++- 1.4.27 -
++ * Fix handling return value of SSL_CTX_set_options (fixes #2157, thx mlcreech)
++ * Fix mod_proxy HUP handling (send final chunk, fix usage counter)
++ * mod_proxy: close connection on write error (fixes #2114)
++ * Check uri instead of physical path for directory redirect
++ * Fix detecting git repository (fixes #2173, thx ncopa)
++ * [mod_compress] Fix segfault when etags are disabled (fixes #2169)
++ * Reset uri.authority before TLS servername handling, reset all "keep-alive" data in connection_del (fixes #2125)
+
-+- 1.4.25 - 2009-11-21
- * mod_magnet: fix pairs() for normal tables and strings (fixes #1307)
- * mod_magnet: add traceback for printing lua errors
- * mod_rewrite: fix compile error if compiled without pcre
++- 1.4.26 - 2010-02-07
+ * Fix request parser to handle packets with splitted \r\n\r\n (fixes #2105)
+ * Remove dependency on automake >= 1.11 with m4_ifdef check
+ * mod_accesslog: support %e (fixes #2113, thx presbrey)
Index: CMakeLists.txt
===================================================================