]> git.pld-linux.org Git - packages/lighttpd.git/blob - lighttpd-mod_deflate.patch
up to 1.4.38
[packages/lighttpd.git] / lighttpd-mod_deflate.patch
1 diff -Naur lighttpd-1.4.19/configure.in lighttpd-1.4.19.mod_deflate.jz/configure.in
2 --- lighttpd-1.4.19/configure.in
3 +++ lighttpd-1.4.19.mod_deflate.jz/configure.in
4 @@ -558,7 +558,7 @@
5  AC_OUTPUT
6  
7  
8 -do_build="mod_cgi mod_fastcgi mod_extforward mod_proxy mod_evhost mod_simple_vhost mod_access mod_alias mod_setenv mod_usertrack mod_auth mod_status mod_accesslog mod_rrdtool mod_secdownload mod_expire mod_compress mod_dirlisting mod_indexfiles mod_userdir mod_webdav mod_staticfile mod_scgi mod_flv_streaming"
9 +do_build="mod_cgi mod_fastcgi mod_extforward mod_proxy mod_evhost mod_simple_vhost mod_access mod_alias mod_setenv mod_usertrack mod_auth mod_status mod_accesslog mod_rrdtool mod_secdownload mod_expire mod_compress mod_dirlisting mod_indexfiles mod_userdir mod_webdav mod_staticfile mod_scgi mod_flv_streaming mod_deflate"
10  
11  plugins="mod_rewrite mod_redirect mod_ssi mod_trigger_b4_dl"
12  features="regex-conditionals"
13 diff -Naur lighttpd-1.4.19/src/base.h lighttpd-1.4.19.mod_deflate.jz/src/base.h
14 --- lighttpd-1.4.19/src/base.h
15 +++ lighttpd-1.4.19.mod_deflate.jz/src/base.h
16 @@ -149,6 +149,7 @@
17  
18         http_method_t  http_method;
19         http_version_t http_version;
20 +       int true_http_10_client;
21  
22         buffer *request_line;
23  
24 @@ -360,8 +361,10 @@
25  
26         int file_started;
27         int file_finished;
28 +       int end_chunk; /* used for chunked transfer encoding. */
29  
30 -       chunkqueue *write_queue;      /* a large queue for low-level write ( HTTP response ) [ file, mem ] */
31 +       chunkqueue *write_queue;  /* a large queue for HTTP response content [ file, mem ] */
32 +       chunkqueue *output_queue; /* a large queue for low-level write ( HTTP response ) [ file, mem ] */
33         chunkqueue *read_queue;       /* a small queue for low-level read ( HTTP request ) [ mem ] */
34         chunkqueue *request_content_queue; /* takes request-content into tempfile if necessary [ tempfile, mem ]*/
35  
36 @@ -596,6 +599,7 @@
37  
38         connections *conns;
39         connections *joblist;
40 +       connections *joblist_prev;
41         connections *fdwaitqueue;
42  
43         stat_cache  *stat_cache;
44 diff -Naur lighttpd-1.4.19/src/chunk.c lighttpd-1.4.19.mod_deflate.jz/src/chunk.c
45 --- lighttpd-1.4.19/src/chunk.c
46 +++ lighttpd-1.4.19.mod_deflate.jz/src/chunk.c
47 @@ -16,7 +16,9 @@
48  #include <errno.h>
49  #include <string.h>
50  
51 +#include "server.h"
52  #include "chunk.h"
53 +#include "log.h"
54  
55  chunkqueue *chunkqueue_init(void) {
56         chunkqueue *cq;
57 @@ -241,6 +243,16 @@
58         return 0;
59  }
60  
61 +int chunkqueue_append_chunkqueue(chunkqueue *cq, chunkqueue *src) {
62 +       if(src == NULL) return 0;
63 +       chunkqueue_append_chunk(cq, src->first);
64 +       cq->last = src->last;
65 +       src->first = NULL;
66 +       src->last = NULL;
67 +
68 +       return 0;
69 +}
70 +
71  buffer * chunkqueue_get_prepend_buffer(chunkqueue *cq) {
72         chunk *c;
73  
74 @@ -400,3 +412,105 @@
75  
76         return 0;
77  }
78 +
79 +/**
80 + * the HTTP chunk-API
81 + * 
82 + * 
83 + */
84 +
85 +static int chunk_encode_append_len(chunkqueue *cq, size_t len) {
86 +       size_t i, olen = len, j;
87 +       buffer *b;
88 +       
89 +       /*b = srv->tmp_chunk_len;*/
90 +       /*b = buffer_init();*/
91 +       b = chunkqueue_get_append_buffer(cq);
92 +       
93 +       if (len == 0) {
94 +               buffer_copy_string(b, "0");
95 +       } else {
96 +               for (i = 0; i < 8 && len; i++) {
97 +                       len >>= 4;
98 +               }
99 +               
100 +               /* i is the number of hex digits we have */
101 +               buffer_prepare_copy(b, i + 1);
102 +               
103 +               for (j = i-1, len = olen; j+1 > 0; j--) {
104 +                       b->ptr[j] = (len & 0xf) + (((len & 0xf) <= 9) ? '0' : 'a' - 10);
105 +                       len >>= 4;
106 +               }
107 +               b->used = i;
108 +               b->ptr[b->used++] = '\0';
109 +       }
110 +               
111 +       buffer_append_string(b, "\r\n");
112 +       /*
113 +       chunkqueue_append_buffer(cq, b);
114 +       buffer_free(b);
115 +       */
116 +       
117 +       return 0;
118 +}
119 +
120 +
121 +int chunk_encode_append_file(chunkqueue *cq, buffer *fn, off_t offset, off_t len) {
122 +       if (!cq) return -1;
123 +       if (len == 0) return 0;
124 +       
125 +       chunk_encode_append_len(cq, len);
126 +       
127 +       chunkqueue_append_file(cq, fn, offset, len);
128 +       
129 +       chunkqueue_append_mem(cq, "\r\n", 2 + 1);
130 +       
131 +       return 0;
132 +}
133 +
134 +int chunk_encode_append_buffer(chunkqueue *cq, buffer *mem) {
135 +       if (!cq) return -1;
136 +       if (mem->used <= 1) return 0;
137 +       
138 +       chunk_encode_append_len(cq, mem->used - 1);
139 +       
140 +       chunkqueue_append_buffer(cq, mem);
141 +       
142 +       chunkqueue_append_mem(cq, "\r\n", 2 + 1);
143 +       
144 +       return 0;
145 +}
146 +
147 +int chunk_encode_append_mem(chunkqueue *cq, const char * mem, size_t len) {
148 +       if (!cq) return -1;
149 +       if (len <= 1) return 0;
150 +       
151 +       chunk_encode_append_len(cq, len - 1);
152 +       
153 +       chunkqueue_append_mem(cq, mem, len);
154 +       
155 +       chunkqueue_append_mem(cq, "\r\n", 2 + 1);
156 +       
157 +       return 0;
158 +}
159 +
160 +int chunk_encode_append_queue(chunkqueue *cq, chunkqueue *src) {
161 +       int len = chunkqueue_length(src);
162 +       if (!cq) return -1;
163 +       if (len == 0) return 0;
164 +       
165 +       chunk_encode_append_len(cq, len);
166 +       
167 +       chunkqueue_append_chunkqueue(cq, src);
168 +       
169 +       chunkqueue_append_mem(cq, "\r\n", 2 + 1);
170 +       
171 +       return 0;
172 +}
173 +
174 +int chunk_encode_end(chunkqueue *cq) {
175 +       chunk_encode_append_len(cq, 0);
176 +       chunkqueue_append_mem(cq, "\r\n", 2 + 1);
177 +       return 0;
178 +}
179 +
180 diff -Naur lighttpd-1.4.19/src/chunk.h lighttpd-1.4.19.mod_deflate.jz/src/chunk.h
181 --- lighttpd-1.4.19/src/chunk.h
182 +++ lighttpd-1.4.19.mod_deflate.jz/src/chunk.h
183 @@ -52,6 +52,7 @@
184  int chunkqueue_append_mem(chunkqueue *c, const char *mem, size_t len);
185  int chunkqueue_append_buffer(chunkqueue *c, buffer *mem);
186  int chunkqueue_append_buffer_weak(chunkqueue *c, buffer *mem);
187 +int chunkqueue_append_chunkqueue(chunkqueue *cq, chunkqueue *src);
188  int chunkqueue_prepend_buffer(chunkqueue *c, buffer *mem);
189  
190  buffer * chunkqueue_get_append_buffer(chunkqueue *c);
191 @@ -67,4 +68,10 @@
192  
193  int chunkqueue_is_empty(chunkqueue *c);
194  
195 +int chunk_encode_append_mem(chunkqueue *cq, const char * mem, size_t len);
196 +int chunk_encode_append_buffer(chunkqueue *cq, buffer *mem);
197 +int chunk_encode_append_file(chunkqueue *cq, buffer *fn, off_t offset, off_t len);
198 +int chunk_encode_append_queue(chunkqueue *cq, chunkqueue *src);
199 +int chunk_encode_end(chunkqueue *cq);
200 +
201  #endif
202 diff -Naur lighttpd-1.4.19/src/connections.c lighttpd-1.4.19.mod_deflate.jz/src/connections.c
203 --- lighttpd-1.4.19/src/connections.c
204 +++ lighttpd-1.4.19.mod_deflate.jz/src/connections.c
205 @@ -18,6 +18,7 @@
206  #include "response.h"
207  #include "network.h"
208  #include "http_chunk.h"
209 +#include "chunk.h"
210  #include "stat_cache.h"
211  #include "joblist.h"
212  
213 @@ -146,6 +147,12 @@
214         return 0;
215  }
216  
217 +int connection_queue_is_empty(connection *con) {
218 +       if(!chunkqueue_is_empty(con->write_queue)) return 0;
219 +       if(!chunkqueue_is_empty(con->output_queue)) return 0;
220 +       return 1;
221 +}
222 +
223  #if 0
224  static void dump_packet(const unsigned char *data, size_t len) {
225         size_t i, j;
226 @@ -405,6 +412,7 @@
227                                 con->file_finished = 1;
228  
229                                 chunkqueue_reset(con->write_queue);
230 +                               chunkqueue_reset(con->output_queue);
231                         }
232                         break;
233                 default:
234 @@ -517,12 +525,27 @@
235                 /* disable chunked encoding again as we have no body */
236                 con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
237                 con->parsed_response &= ~HTTP_CONTENT_LENGTH;
238                 chunkqueue_reset(con->write_queue);
239 +               chunkqueue_reset(con->output_queue);
240  
241                 con->file_finished = 1;
242                 break;
243         }
244  
245 +       /* Allow filter plugins to change response headers before they are written. */
246 +       switch(plugins_call_handle_response_start(srv, con)) {
247 +       case HANDLER_GO_ON:
248 +       case HANDLER_FINISHED:
249 +               /* response start is finished */
250 +               break;
251 +       default:
252 +               /* something strange happend */
253 +               log_error_write(srv, __FILE__, __LINE__, "s", "Filter plugin failed.");
254 +               connection_set_state(srv, con, CON_STATE_ERROR);
255 +               joblist_append(srv, con);
256 +               break;
257 +       }
258 +
259         if (con->file_finished) {
260                 /* we have all the content and chunked encoding is not used, set a content-length */
261  
262 @@ -592,8 +615,9 @@
263                  * without the content
264                  */
265                 con->file_finished = 1;
266  
267                 chunkqueue_reset(con->write_queue);
268 +               chunkqueue_reset(con->output_queue);
269                 con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
270         }
271  
272 @@ -603,11 +627,57 @@
273  }
274  
275  static int connection_handle_write(server *srv, connection *con) {
276 -       switch(network_write_chunkqueue(srv, con, con->write_queue)) {
277 +       int finished = 0;
278 +       int len;
279 +
280 +       /* Allow filter plugins to modify response conent */
281 +       switch(plugins_call_handle_response_filter(srv, con)) {
282 +       case HANDLER_GO_ON:
283 +               finished = con->file_finished;
284 +               /* response content not changed */
285 +               break;
286 +       case HANDLER_COMEBACK:
287 +               /* response filter has more work */
288 +               finished = 0;
289 +               break;
290 +       case HANDLER_FINISHED:
291 +               /* response filter is finished */
292 +               finished = 1;
293 +               break;
294 +       default:
295 +               /* something strange happend */
296 +               log_error_write(srv, __FILE__, __LINE__, "s", "Filter plugin failed.");
297 +               connection_set_state(srv, con, CON_STATE_ERROR);
298 +               joblist_append(srv, con);
299 +               finished = 1;
300 +               break;
301 +       }
302 +
303 +       /* move chunks from write_queue to output_queue. */
304 +       if (con->request.http_method == HTTP_METHOD_HEAD) {
305 +               chunkqueue_reset(con->write_queue);
306 +       } else {
307 +               len = chunkqueue_length(con->write_queue);
308 +               if(con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
309 +                       chunk_encode_append_queue(con->output_queue, con->write_queue);
310 +                       if(finished && !con->end_chunk) {
311 +                               con->end_chunk = 1;
312 +                               chunk_encode_end(con->output_queue);
313 +                       }
314 +               } else {
315 +                       chunkqueue_append_chunkqueue(con->output_queue, con->write_queue);
316 +               }
317 +               con->write_queue->bytes_out += len;
318 +       }
319 +       /* write chunks from output_queue to network */
320 +       switch(network_write_chunkqueue(srv, con, con->output_queue)) {
321         case 0:
322 -               if (con->file_finished) {
323 +               if (finished) {
324                         connection_set_state(srv, con, CON_STATE_RESPONSE_END);
325                         joblist_append(srv, con);
326 +               } else {
327 +                       /* not finished yet -> WRITE */
328 +                       con->is_writable = 1;
329                 }
330                 break;
331         case -1: /* error on our side */
332 @@ -678,6 +747,7 @@
333  
334  #undef CLEAN
335         con->write_queue = chunkqueue_init();
336 +       con->output_queue = chunkqueue_init();
337         con->read_queue = chunkqueue_init();
338         con->request_content_queue = chunkqueue_init();
339         chunkqueue_set_tempdirs(con->request_content_queue, srv->srvconf.upload_tempdirs);
340 @@ -705,6 +776,7 @@
341                 connection_reset(srv, con);
342  
343                 chunkqueue_free(con->write_queue);
344 +               chunkqueue_free(con->output_queue);
345                 chunkqueue_free(con->read_queue);
346                 chunkqueue_free(con->request_content_queue);
347                 array_free(con->request.headers);
348 @@ -759,7 +831,10 @@
349         con->http_status = 0;
350         con->file_finished = 0;
351         con->file_started = 0;
352 +       con->end_chunk = 0;
353         con->got_response = 0;
354 +//     con->use_cache_file = 0;
355 +//     con->write_cache_file = 0;
356  
357         con->parsed_response = 0;
358  
359 @@ -829,6 +904,7 @@
360         array_reset(con->environment);
361  
362         chunkqueue_reset(con->write_queue);
363 +       chunkqueue_reset(con->output_queue);
364         chunkqueue_reset(con->request_content_queue);
365  
366         /* the plugins should cleanup themself */
367 @@ -1223,7 +1299,6 @@
368         }
369  
370         if (con->state == CON_STATE_WRITE &&
371 -           !chunkqueue_is_empty(con->write_queue) &&
372             con->is_writable) {
373  
374                 if (-1 == connection_handle_write(srv, con)) {
375 @@ -1640,15 +1715,15 @@
376                         }
377  
378                         /* only try to write if we have something in the queue */
379 -                       if (!chunkqueue_is_empty(con->write_queue)) {
380  #if 0
381 +                       if (!connection_queue_is_empty(con)) {
382                                 log_error_write(srv, __FILE__, __LINE__, "dsd",
383                                                 con->fd,
384                                                 "packets to write:",
385 -                                               con->write_queue->used);
386 -#endif
387 +                                               con->output_queue->used);
388                         }
389 -                       if (!chunkqueue_is_empty(con->write_queue) && con->is_writable) {
390 +#endif
391 +                       if (con->is_writable) {
392                                 if (-1 == connection_handle_write(srv, con)) {
393                                         log_error_write(srv, __FILE__, __LINE__, "ds",
394                                                         con->fd,
395 @@ -1758,9 +1833,9 @@
396                  * - if we have data to write
397                  * - if the socket is not writable yet
398                  */
399 -               if (!chunkqueue_is_empty(con->write_queue) &&
400 -                   (con->is_writable == 0) &&
401 -                   (con->traffic_limit_reached == 0)) {
402 +               if ((con->is_writable == 0) &&
403 +                   (con->traffic_limit_reached == 0) &&
404 +                               !connection_queue_is_empty(con)) {
405                         fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT);
406                 } else {
407                         fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
408 diff -Naur lighttpd-1.4.19/src/http_chunk.c lighttpd-1.4.19.mod_deflate.jz/src/http_chunk.c
409 --- lighttpd-1.4.19/src/http_chunk.c
410 +++ lighttpd-1.4.19.mod_deflate.jz/src/http_chunk.c
411 @@ -58,16 +58,9 @@
412  
413         cq = con->write_queue;
414  
415 -       if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
416 -               http_chunk_append_len(srv, con, len);
417 -       }
418  
419         chunkqueue_append_file(cq, fn, offset, len);
420  
421 -       if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && len > 0) {
422 -               chunkqueue_append_mem(cq, "\r\n", 2 + 1);
423 -       }
424 -
425         return 0;
426  }
427  
428 @@ -78,16 +71,9 @@
429  
430         cq = con->write_queue;
431  
432 -       if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
433 -               http_chunk_append_len(srv, con, mem->used - 1);
434 -       }
435  
436         chunkqueue_append_buffer(cq, mem);
437  
438 -       if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && mem->used > 0) {
439 -               chunkqueue_append_mem(cq, "\r\n", 2 + 1);
440 -       }
441 -
442         return 0;
443  }
444  
445 @@ -99,24 +85,11 @@
446         cq = con->write_queue;
447  
448         if (len == 0) {
449 -               if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
450 -                       chunkqueue_append_mem(cq, "0\r\n\r\n", 5 + 1);
451 -               } else {
452 -                       chunkqueue_append_mem(cq, "", 1);
453 -               }
454                 return 0;
455         }
456  
457 -       if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
458 -               http_chunk_append_len(srv, con, len - 1);
459 -       }
460 -
461         chunkqueue_append_mem(cq, mem, len);
462  
463 -       if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
464 -               chunkqueue_append_mem(cq, "\r\n", 2 + 1);
465 -       }
466 -
467         return 0;
468  }
469  
470 diff -Naur lighttpd-1.4.19/src/joblist.c lighttpd-1.4.19.mod_deflate.jz/src/joblist.c
471 --- lighttpd-1.4.19/src/joblist.c
472 +++ lighttpd-1.4.19.mod_deflate.jz/src/joblist.c
473 @@ -7,6 +7,7 @@
474  
475  int joblist_append(server *srv, connection *con) {
476         if (con->in_joblist) return 0;
477 +       con->in_joblist = 1;
478  
479         if (srv->joblist->size == 0) {
480                 srv->joblist->size  = 16;
481 diff -Naur lighttpd-1.4.19/src/Makefile.am lighttpd-1.4.19.mod_deflate.jz/src/Makefile.am
482 --- lighttpd-1.4.19/src/Makefile.am
483 +++ lighttpd-1.4.19.mod_deflate.jz/src/Makefile.am
484 @@ -241,6 +241,11 @@
485  mod_accesslog_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
486  mod_accesslog_la_LIBADD = $(common_libadd)
487  
488 +lib_LTLIBRARIES += mod_deflate.la
489 +mod_deflate_la_SOURCES = mod_deflate.c 
490 +mod_deflate_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
491 +mod_deflate_la_LIBADD = $(Z_LIB) $(BZ_LIB) $(common_libadd)
492 +
493  
494  hdr = server.h buffer.h network.h log.h keyvalue.h \
495        response.h request.h fastcgi.h chunk.h \
496 diff -Naur lighttpd-1.4.19/src/Makefile.in lighttpd-1.4.19.mod_deflate.jz/src/Makefile.in
497 --- lighttpd-1.4.19/src/Makefile.in
498 +++ lighttpd-1.4.19.mod_deflate.jz/src/Makefile.in
499 @@ -158,8 +158,15 @@
500  am_mod_compress_la_OBJECTS = mod_compress.lo
501  mod_compress_la_OBJECTS = $(am_mod_compress_la_OBJECTS)
502  mod_compress_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
503         $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
504         $(mod_compress_la_LDFLAGS) $(LDFLAGS) -o $@
505 +mod_deflate_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
506 +       $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
507 +am_mod_deflate_la_OBJECTS = mod_deflate.lo
508 +mod_deflate_la_OBJECTS = $(am_mod_deflate_la_OBJECTS)
509 +mod_deflate_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
510 +       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
511 +       $(mod_deflate_la_LDFLAGS) $(LDFLAGS) -o $@
512  mod_dirlisting_la_DEPENDENCIES = $(am__DEPENDENCIES_2) \
513         $(am__DEPENDENCIES_1)
514  am_mod_dirlisting_la_OBJECTS = mod_dirlisting.lo
515 @@ -399,6 +404,7 @@
516         $(mod_accesslog_la_SOURCES) $(mod_alias_la_SOURCES) \
517         $(mod_auth_la_SOURCES) $(mod_cgi_la_SOURCES) \
518         $(mod_cml_la_SOURCES) $(mod_compress_la_SOURCES) \
519 +       $(mod_deflate_la_SOURCES) \
520         $(mod_dirlisting_la_SOURCES) $(mod_evasive_la_SOURCES) \
521         $(mod_evhost_la_SOURCES) $(mod_expire_la_SOURCES) \
522         $(mod_fastcgi_la_SOURCES) $(mod_flv_streaming_la_SOURCES) \
523 @@ -614,7 +619,7 @@
524         mod_ssi.la mod_secdownload.la mod_expire.la mod_evhost.la \
525         mod_simple_vhost.la mod_fastcgi.la mod_extforward.la \
526         mod_access.la mod_compress.la mod_auth.la mod_rewrite.la \
527 -       mod_redirect.la mod_status.la mod_accesslog.la
528 +       mod_redirect.la mod_status.la mod_accesslog.la mod_deflate.la
529  @NO_RDYNAMIC_TRUE@liblightcomp_la_SOURCES = $(common_src)
530  @NO_RDYNAMIC_TRUE@liblightcomp_la_CFLAGS = $(AM_CFLAGS)
531  @NO_RDYNAMIC_TRUE@liblightcomp_la_LDFLAGS = -avoid-version -no-undefined
532 @@ -721,6 +726,9 @@
533  mod_accesslog_la_SOURCES = mod_accesslog.c
534  mod_accesslog_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
535  mod_accesslog_la_LIBADD = $(common_libadd)
536 +mod_deflate_la_SOURCES = mod_deflate.c 
537 +mod_deflate_la_LDFLAGS = -module -export-dynamic -no-undefined
538 +mod_deflate_la_LIBADD = $(Z_LIB) $(BZ_LIB) $(common_libadd)
539  hdr = server.h buffer.h network.h log.h keyvalue.h \
540        response.h request.h fastcgi.h chunk.h \
541        settings.h http_chunk.h http_auth_digest.h \
542 @@ -832,6 +840,8 @@
543         $(mod_cml_la_LINK) -rpath $(libdir) $(mod_cml_la_OBJECTS) $(mod_cml_la_LIBADD) $(LIBS)
544  mod_compress.la: $(mod_compress_la_OBJECTS) $(mod_compress_la_DEPENDENCIES) 
545         $(mod_compress_la_LINK) -rpath $(libdir) $(mod_compress_la_OBJECTS) $(mod_compress_la_LIBADD) $(LIBS)
546 +mod_deflate.la: $(mod_deflate_la_OBJECTS) $(mod_deflate_la_DEPENDENCIES) 
547 +       $(mod_deflate_la_LINK) -rpath $(libdir) $(mod_deflate_la_LDFLAGS) $(mod_deflate_la_OBJECTS) $(mod_deflate_la_LIBADD) $(LIBS)
548  mod_dirlisting.la: $(mod_dirlisting_la_OBJECTS) $(mod_dirlisting_la_DEPENDENCIES) 
549         $(mod_dirlisting_la_LINK) -rpath $(libdir) $(mod_dirlisting_la_OBJECTS) $(mod_dirlisting_la_LIBADD) $(LIBS)
550  mod_evasive.la: $(mod_evasive_la_OBJECTS) $(mod_evasive_la_DEPENDENCIES) 
551 @@ -1050,6 +1060,7 @@
552  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_cml_la-mod_cml_funcs.Plo@am__quote@
553  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_cml_la-mod_cml_lua.Plo@am__quote@
554  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_compress.Plo@am__quote@
555 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_deflate.Plo@am__quote@
556  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_dirlisting.Plo@am__quote@
557  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_evasive.Plo@am__quote@
558  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_evhost.Plo@am__quote@
559 diff -Naur lighttpd-1.4.19/src/mod_deflate.c lighttpd-1.4.19.mod_deflate.jz/src/mod_deflate.c
560 --- lighttpd-1.4.19/src/mod_deflate.c
561 +++ lighttpd-1.4.19.mod_deflate.jz/src/mod_deflate.c
562 @@ -0,0 +1,1420 @@
563 +/* bug fix on Robert Jakabosky from alphatrade.com's lighttp 1.4.10 mod_deflate patch
564 + *
565 + * new module option:
566 + * deflate.nocompress-url = "^/nocompressurl/" # pcre regex which don't compress
567 + *
568 + * Bug fix and new features:
569 + * 1) fix loop bug when content-length is bigger than work-block-size*k
570 + * 2) prevent compress on buggy http 1.0 client with Accept Encoding: gzip, deflate
571 + * 3) fix bug with chunk transfer encoding (under mod_fastcgi+php environment)
572 + * 
573 + * deflate.sync-flush = "enable" is buggy on chunk encoding transfer. Use it carefully,
574 + */
575 +#include <sys/types.h>
576 +#include <sys/stat.h>
577 +
578 +#include <fcntl.h>
579 +#include <unistd.h>
580 +#include <ctype.h>
581 +#include <stdlib.h>
582 +#include <string.h>
583 +#include <errno.h>
584 +#include <time.h>
585 +#include <assert.h>
586 +
587 +#if defined(HAVE_PCRE_H)
588 +#include <pcre.h>
589 +#endif
590 +
591 +#include "base.h"
592 +#include "log.h"
593 +#include "buffer.h"
594 +#include "response.h"
595 +#include "joblist.h"
596 +#include "stat_cache.h"
597 +
598 +#include "plugin.h"
599 +
600 +#include "crc32.h"
601 +#include "etag.h"
602 +#include "inet_ntop_cache.h"
603 +
604 +#if defined HAVE_ZLIB_H && defined HAVE_LIBZ
605 +# define USE_ZLIB
606 +# include <zlib.h>
607 +#else
608 +# define Z_DEFAULT_COMPRESSION 1
609 +#endif
610 +
611 +#if defined HAVE_BZLIB_H && defined HAVE_LIBBZ2
612 +# define USE_BZ2LIB
613 +/* we don't need stdio interface */
614 +# define BZ_NO_STDIO
615 +# include <bzlib.h>
616 +#endif
617 +
618 +#include "sys-mmap.h"
619 +
620 +/* request: accept-encoding */
621 +#define HTTP_ACCEPT_ENCODING_IDENTITY BV(0)
622 +#define HTTP_ACCEPT_ENCODING_GZIP     BV(1)
623 +#define HTTP_ACCEPT_ENCODING_DEFLATE  BV(2)
624 +#define HTTP_ACCEPT_ENCODING_COMPRESS BV(3)
625 +#define HTTP_ACCEPT_ENCODING_BZIP2    BV(4)
626 +
627 +#define KByte * 1024
628 +#define MByte * 1024 KByte
629 +#define GByte * 1024 MByte
630 +
631 +typedef struct {
632 +       unsigned short  debug;
633 +       unsigned short  enabled;
634 +       unsigned short  bzip2;
635 +       unsigned short  sync_flush;
636 +       unsigned short  output_buffer_size;
637 +       unsigned short  min_compress_size;
638 +       unsigned short  work_block_size;
639 +       short           mem_level;
640 +       short           compression_level;
641 +       short           window_size;
642 +       array           *mimetypes;
643 +       buffer          *nocompress_url;
644 +#if defined(HAVE_PCRE_H)
645 +       pcre    *nocompress_regex;
646 +#endif
647 +} plugin_config;
648 +
649 +typedef struct {
650 +       PLUGIN_DATA;
651 +       buffer *tmp_buf;
652 +       
653 +       plugin_config **config_storage;
654 +       plugin_config conf; 
655 +} plugin_data;
656 +
657 +typedef struct {
658 +       int bytes_in;
659 +       int bytes_out;
660 +       chunkqueue *in_queue;
661 +       buffer *output;
662 +       /* compression type & state */
663 +       int compression_type;
664 +       int stream_open;
665 +#ifdef USE_ZLIB
666 +       unsigned long crc;
667 +       z_stream z;
668 +       unsigned short gzip_header;
669 +#endif
670 +#ifdef USE_BZ2LIB
671 +       bz_stream bz;
672 +#endif
673 +       plugin_data *plugin_data;
674 +} handler_ctx;
675 +
676 +static handler_ctx *handler_ctx_init() {
677 +       handler_ctx *hctx;
678 +
679 +       hctx = calloc(1, sizeof(*hctx));
680 +       hctx->in_queue = chunkqueue_init();
681 +
682 +       return hctx;
683 +}
684 +
685 +static void handler_ctx_free(handler_ctx *hctx) {
686 +       chunkqueue_free(hctx->in_queue);
687 +       free(hctx);
688 +}
689 +
690 +INIT_FUNC(mod_deflate_init) {
691 +       plugin_data *p;
692 +       
693 +       p = calloc(1, sizeof(*p));
694 +
695 +       p->tmp_buf = buffer_init();
696 +       
697 +       return p;
698 +}
699 +
700 +FREE_FUNC(mod_deflate_free) {
701 +       plugin_data *p = p_d;
702 +       
703 +       UNUSED(srv);
704 +
705 +       if (!p) return HANDLER_GO_ON;
706 +       
707 +       if (p->config_storage) {
708 +               size_t i;
709 +               for (i = 0; i < srv->config_context->used; i++) {
710 +                       plugin_config *s = p->config_storage[i];
711 +
712 +                       if (!s) continue;
713 +                       
714 +                       array_free(s->mimetypes);
715 +                       buffer_free(s->nocompress_url);
716 +#if defined(HAVE_PCRE_H)
717 +                       if (s->nocompress_regex) pcre_free(s->nocompress_regex);
718 +#endif
719 +                       free(s);
720 +               }
721 +               free(p->config_storage);
722 +       }
723 +
724 +       buffer_free(p->tmp_buf);
725 +       
726 +       free(p);
727 +       
728 +       return HANDLER_GO_ON;
729 +}
730 +
731 +SETDEFAULTS_FUNC(mod_deflate_setdefaults) {
732 +       plugin_data *p = p_d;
733 +       size_t i = 0;
734 +       
735 +       config_values_t cv[] = { 
736 +               { "deflate.output-buffer-size",    NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
737 +               { "deflate.mimetypes",             NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
738 +               { "deflate.compression-level",     NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
739 +               { "deflate.mem-level",             NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
740 +               { "deflate.window-size",           NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
741 +               { "deflate.min-compress-size",     NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
742 +               { "deflate.work-block-size",       NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
743 +               { "deflate.enabled",               NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
744 +               { "deflate.debug",                 NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
745 +               { "deflate.bzip2",                 NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
746 +               { "deflate.sync-flush",            NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
747 +               { "deflate.nocompress-url",        NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
748 +               { NULL,                            NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
749 +       };
750 +       
751 +       p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
752 +       
753 +       for (i = 0; i < srv->config_context->used; i++) {
754 +               plugin_config *s;
755 +#if defined(HAVE_PCRE_H)
756 +               const char *errptr;
757 +               int erroff;
758 +#endif
759 +               
760 +               s = calloc(1, sizeof(plugin_config));
761 +               s->enabled = 1;
762 +               s->bzip2 = 1;
763 +               s->sync_flush = 0;
764 +               s->debug = 0;
765 +               s->output_buffer_size = 0;
766 +               s->mem_level = 9;
767 +               s->window_size = 15;
768 +               s->min_compress_size = 0;
769 +               s->work_block_size = 2048;
770 +               s->compression_level = Z_DEFAULT_COMPRESSION;
771 +               s->mimetypes = array_init();
772 +               s->nocompress_url = buffer_init();
773 +#if defined(HAVE_PCRE_H)
774 +               s->nocompress_regex = NULL;
775 +#endif
776 +
777 +               cv[0].destination = &(s->output_buffer_size);
778 +               cv[1].destination = s->mimetypes;
779 +               cv[2].destination = &(s->compression_level);
780 +               cv[3].destination = &(s->mem_level);
781 +               cv[4].destination = &(s->window_size);
782 +               cv[5].destination = &(s->min_compress_size);
783 +               cv[6].destination = &(s->work_block_size);
784 +               cv[7].destination = &(s->enabled);
785 +               cv[8].destination = &(s->debug);
786 +               cv[9].destination = &(s->bzip2);
787 +               cv[10].destination = &(s->sync_flush);
788 +               cv[11].destination = s->nocompress_url;
789 +               
790 +               p->config_storage[i] = s;
791 +       
792 +               if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
793 +                       return HANDLER_ERROR;
794 +               }
795 +
796 +#if defined(HAVE_PCRE_H)               
797 +               if (!buffer_is_empty(s->nocompress_url)) {
798 +                       if (NULL == (s->nocompress_regex = pcre_compile(s->nocompress_url->ptr,
799 +                                                                     0, &errptr, &erroff, NULL))) {
800 +                               
801 +                               log_error_write(srv, __FILE__, __LINE__, "sbss", 
802 +                                               "compiling regex for nocompress-url failed:", 
803 +                                               s->nocompress_url, "pos:", erroff);
804 +                               return HANDLER_ERROR;
805 +                       }
806 +               }
807 +#endif
808 +               if((s->compression_level < 1 || s->compression_level > 9) &&
809 +                               s->compression_level != Z_DEFAULT_COMPRESSION) {
810 +                       log_error_write(srv, __FILE__, __LINE__, "sd", 
811 +                               "compression-level must be between 1 and 9:", s->compression_level);
812 +                       return HANDLER_ERROR;
813 +               }
814 +
815 +               if(s->mem_level < 1 || s->mem_level > 9) {
816 +                       log_error_write(srv, __FILE__, __LINE__, "sd", 
817 +                               "mem-level must be between 1 and 9:", s->mem_level);
818 +                       return HANDLER_ERROR;
819 +               }
820 +
821 +               if(s->window_size < 1 || s->window_size > 15) {
822 +                       log_error_write(srv, __FILE__, __LINE__, "sd", 
823 +                               "window-size must be between 1 and 15:", s->window_size);
824 +                       return HANDLER_ERROR;
825 +               }
826 +               s->window_size = 0 - s->window_size;
827 +
828 +               if(s->sync_flush) {
829 +                       s->output_buffer_size = 0;
830 +               }
831 +       }
832 +       
833 +       return HANDLER_GO_ON;
834 +       
835 +}
836 +
837 +#ifdef USE_ZLIB
838 +/* Copied gzip_header from apache 2.2's mod_deflate.c */
839 +/* RFC 1952 Section 2.3 defines the gzip header:
840 + *
841 + * +---+---+---+---+---+---+---+---+---+---+
842 + * |ID1|ID2|CM |FLG|     MTIME     |XFL|OS |
843 + * +---+---+---+---+---+---+---+---+---+---+
844 + */
845 +static const char gzip_header[10] =
846 +{ '\037', '\213', Z_DEFLATED, 0,
847 +  0, 0, 0, 0, /* mtime */
848 +  0, 0x03 /* Unix OS_CODE */
849 +};
850 +static int stream_deflate_init(server *srv, connection *con, handler_ctx *hctx) {
851 +       plugin_data *p = hctx->plugin_data;
852 +       z_stream *z;
853 +
854 +       UNUSED(srv);
855 +       UNUSED(con);
856 +
857 +       z = &(hctx->z);
858 +       z->zalloc = Z_NULL;
859 +       z->zfree = Z_NULL;
860 +       z->opaque = Z_NULL;
861 +       z->total_in = 0;
862 +       z->total_out = 0;
863 +       z->next_out = NULL;
864 +       z->avail_out = 0;
865 +       
866 +       if(p->conf.debug) {
867 +               log_error_write(srv, __FILE__, __LINE__, "sd", 
868 +                       "output-buffer-size:", p->conf.output_buffer_size);
869 +               log_error_write(srv, __FILE__, __LINE__, "sd", 
870 +                       "compression-level:", p->conf.compression_level);
871 +               log_error_write(srv, __FILE__, __LINE__, "sd", 
872 +                       "mem-level:", p->conf.mem_level);
873 +               log_error_write(srv, __FILE__, __LINE__, "sd", 
874 +                       "window-size:", p->conf.window_size);
875 +               log_error_write(srv, __FILE__, __LINE__, "sd", 
876 +                       "min-compress-size:", p->conf.min_compress_size);
877 +               log_error_write(srv, __FILE__, __LINE__, "sd", 
878 +                       "work-block-size:", p->conf.work_block_size);
879 +       }
880 +       if (Z_OK != deflateInit2(z, 
881 +                                p->conf.compression_level,
882 +                                Z_DEFLATED, 
883 +                                p->conf.window_size,  /* supress zlib-header */
884 +                                p->conf.mem_level,
885 +                                Z_DEFAULT_STRATEGY)) {
886 +               return -1;
887 +       }
888 +       hctx->stream_open = 1;
889 +               
890 +       return 0;
891 +}
892 +
893 +static int stream_deflate_compress(server *srv, connection *con, handler_ctx *hctx, unsigned char *start, off_t st_size) {
894 +       plugin_data *p = hctx->plugin_data;
895 +       z_stream *z;
896 +       int len;
897 +       int in = 0, out = 0;
898 +
899 +       UNUSED(srv);
900 +       z = &(hctx->z);
901 +
902 +       if(z->next_out == NULL) {
903 +               z->next_out = (unsigned char *)hctx->output->ptr;
904 +               z->avail_out = hctx->output->size;
905 +       }
906 +       
907 +       if(hctx->compression_type == HTTP_ACCEPT_ENCODING_GZIP) {
908 +               if(hctx->gzip_header == 0) {
909 +                       hctx->gzip_header = 1;
910 +                       /* copy gzip header into output buffer */
911 +                       buffer_copy_memory(hctx->output, gzip_header, sizeof(gzip_header));
912 +                       if(p->conf.debug) {
913 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
914 +                                               "gzip_header len=", sizeof(gzip_header));
915 +                       }
916 +                       /* initialize crc32 */
917 +                       hctx->crc = crc32(0L, Z_NULL, 0);
918 +                       z->next_out = (unsigned char *)(hctx->output->ptr + sizeof(gzip_header));
919 +                       z->avail_out = hctx->output->size - sizeof(gzip_header);
920 +               }
921 +               hctx->crc = crc32(hctx->crc, start, st_size);
922 +       }
923 +
924 +       z->next_in = start;
925 +       z->avail_in = st_size;
926 +       hctx->bytes_in += st_size;
927 +               
928 +       /* compress data */
929 +       in = z->avail_in;
930 +       do {
931 +               if (Z_OK != deflate(z, Z_NO_FLUSH)) {
932 +                       deflateEnd(z);
933 +                       hctx->stream_open = 0;
934 +                       return -1;
935 +               }
936 +
937 +               if(z->avail_out == 0 || z->avail_in > 0) {
938 +                       len = hctx->output->size - z->avail_out;
939 +                       hctx->bytes_out += len;
940 +                       out += len;
941 +                       chunkqueue_append_mem(con->write_queue, hctx->output->ptr, len+1);
942 +                       z->next_out = (unsigned char *)hctx->output->ptr;
943 +                       z->avail_out = hctx->output->size;
944 +               }
945 +       } while (z->avail_in > 0);
946 +
947 +       if(p->conf.debug) {
948 +               log_error_write(srv, __FILE__, __LINE__, "sdsd",
949 +                               "compress: in=", in, ", out=", out);
950 +       }
951 +       return 0;
952 +}
953 +
954 +static int stream_deflate_flush(server *srv, connection *con, handler_ctx *hctx, int end) {
955 +       plugin_data *p = hctx->plugin_data;
956 +       z_stream *z;
957 +       int len;
958 +       int rc = 0;
959 +       int done;
960 +       int flush = 1;
961 +       int in = 0, out = 0;
962 +
963 +       UNUSED(srv);
964 +
965 +       z = &(hctx->z);
966 +
967 +       if(z->next_out == NULL) {
968 +               z->next_out = (unsigned char *)hctx->output->ptr;
969 +               z->avail_out = hctx->output->size;
970 +       }
971 +       /* compress data */
972 +       in = z->avail_in;
973 +       do {
974 +               done = 1;
975 +               if(end) {
976 +                       rc = deflate(z, Z_FINISH);
977 +                       if (rc == Z_OK) {
978 +                               done = 0;
979 +                       } else if (rc != Z_STREAM_END) {
980 +                               deflateEnd(z);
981 +                               hctx->stream_open = 0;
982 +                               return -1;
983 +                       }
984 +               } else {
985 +                       if(p->conf.sync_flush) {
986 +                               rc = deflate(z, Z_SYNC_FLUSH);
987 +                       } else if(z->avail_in > 0) {
988 +                               if(p->conf.output_buffer_size > 0) flush = 0;
989 +                               rc = deflate(z, Z_NO_FLUSH);
990 +                       } else {
991 +                               if(p->conf.output_buffer_size > 0) flush = 0;
992 +                               rc = Z_OK;
993 +                       }
994 +                       if (rc != Z_OK) {
995 +                               deflateEnd(z);
996 +                               hctx->stream_open = 0;
997 +                               return -1;
998 +                       }
999 +               }
1000 +
1001 +               len = hctx->output->size - z->avail_out;
1002 +               if(z->avail_out == 0 || (flush && len > 0)) {
1003 +                       hctx->bytes_out += len;
1004 +                       out += len;
1005 +                       chunkqueue_append_mem(con->write_queue, hctx->output->ptr, len+1);
1006 +                       z->next_out = (unsigned char *)hctx->output->ptr;
1007 +                       z->avail_out = hctx->output->size;
1008 +               }
1009 +       } while (z->avail_in != 0 || !done);
1010 +
1011 +
1012 +       if(p->conf.debug) {
1013 +               log_error_write(srv, __FILE__, __LINE__, "sdsd",
1014 +                               "flush: in=", in, ", out=", out);
1015 +       }
1016 +       if(p->conf.sync_flush) {
1017 +               z->next_out = NULL;
1018 +               z->avail_out = 0;
1019 +       }
1020 +       return 0;
1021 +}
1022 +
1023 +static int stream_deflate_end(server *srv, connection *con, handler_ctx *hctx) {
1024 +       plugin_data *p = hctx->plugin_data;
1025 +       z_stream *z;
1026 +       int rc;
1027 +
1028 +       UNUSED(srv);
1029 +
1030 +       z = &(hctx->z);
1031 +       if(!hctx->stream_open) return 0;
1032 +       hctx->stream_open = 0;
1033 +
1034 +       if(hctx->compression_type == HTTP_ACCEPT_ENCODING_GZIP && hctx->bytes_out > 0 &&
1035 +                       (unsigned int )hctx->bytes_out >= sizeof(gzip_header)) {
1036 +               /* write gzip footer */
1037 +               unsigned char c[8];
1038 +
1039 +               c[0] = (hctx->crc >>  0) & 0xff;
1040 +               c[1] = (hctx->crc >>  8) & 0xff;
1041 +               c[2] = (hctx->crc >> 16) & 0xff;
1042 +               c[3] = (hctx->crc >> 24) & 0xff;
1043 +               c[4] = (z->total_in >>  0) & 0xff;
1044 +               c[5] = (z->total_in >>  8) & 0xff;
1045 +               c[6] = (z->total_in >> 16) & 0xff;
1046 +               c[7] = (z->total_in >> 24) & 0xff;
1047 +               /* append footer to write_queue */
1048 +               chunkqueue_append_mem(con->write_queue, (char *)c, 9);
1049 +               hctx->bytes_out += 8;
1050 +               if(p->conf.debug) {
1051 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
1052 +                                       "gzip_footer len=", 8);
1053 +               }
1054 +       }
1055 +
1056 +       if ((rc = deflateEnd(z)) != Z_OK) {
1057 +               if(rc == Z_DATA_ERROR) return 0;
1058 +               if(z->msg != NULL) {
1059 +                       log_error_write(srv, __FILE__, __LINE__, "sdss",
1060 +                                       "deflateEnd error ret=", rc, ", msg=", z->msg);
1061 +               } else {
1062 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
1063 +                                       "deflateEnd error ret=", rc);
1064 +               }
1065 +               return -1;
1066 +       }
1067 +       return 0;
1068 +}
1069 +
1070 +#endif
1071 +
1072 +#ifdef USE_BZ2LIB
1073 +static int stream_bzip2_init(server *srv, connection *con, handler_ctx *hctx) {
1074 +       plugin_data *p = hctx->plugin_data;
1075 +       bz_stream *bz;
1076 +
1077 +       UNUSED(srv);
1078 +       UNUSED(con);
1079 +
1080 +       bz = &(hctx->bz);
1081 +       bz->bzalloc = NULL;
1082 +       bz->bzfree = NULL;
1083 +       bz->opaque = NULL;
1084 +       bz->total_in_lo32 = 0;
1085 +       bz->total_in_hi32 = 0;
1086 +       bz->total_out_lo32 = 0;
1087 +       bz->total_out_hi32 = 0;
1088 +       
1089 +       if(p->conf.debug) {
1090 +               log_error_write(srv, __FILE__, __LINE__, "sd", 
1091 +                       "output-buffer-size:", p->conf.output_buffer_size);
1092 +               log_error_write(srv, __FILE__, __LINE__, "sd", 
1093 +                       "compression-level:", p->conf.compression_level);
1094 +               log_error_write(srv, __FILE__, __LINE__, "sd", 
1095 +                       "mem-level:", p->conf.mem_level);
1096 +               log_error_write(srv, __FILE__, __LINE__, "sd", 
1097 +                       "window-size:", p->conf.window_size);
1098 +               log_error_write(srv, __FILE__, __LINE__, "sd", 
1099 +                       "min-compress-size:", p->conf.min_compress_size);
1100 +               log_error_write(srv, __FILE__, __LINE__, "sd", 
1101 +                       "work-block-size:", p->conf.work_block_size);
1102 +       }
1103 +       if (BZ_OK != BZ2_bzCompressInit(bz, 
1104 +                                       p->conf.compression_level, /* blocksize = 900k */
1105 +                                       0, /* no output */
1106 +                                       30)) { /* workFactor: default */
1107 +               return -1;
1108 +       }
1109 +       hctx->stream_open = 1;
1110 +               
1111 +       return 0;
1112 +}
1113 +
1114 +static int stream_bzip2_compress(server *srv, connection *con, handler_ctx *hctx, unsigned char *start, off_t st_size) {
1115 +       plugin_data *p = hctx->plugin_data;
1116 +       bz_stream *bz;
1117 +       int len;
1118 +       int rc;
1119 +       int in = 0, out = 0;
1120 +
1121 +       UNUSED(srv);
1122 +
1123 +       bz = &(hctx->bz);
1124 +
1125 +       if(bz->next_out == NULL) {
1126 +               bz->next_out = hctx->output->ptr;
1127 +               bz->avail_out = hctx->output->size;
1128 +       }
1129 +       
1130 +       bz->next_in = (char *)start;
1131 +       bz->avail_in = st_size;
1132 +       hctx->bytes_in += st_size;
1133 +               
1134 +       /* compress data */
1135 +       in = bz->avail_in;
1136 +       do {
1137 +               rc = BZ2_bzCompress(bz, BZ_RUN);
1138 +               if (rc != BZ_RUN_OK) {
1139 +                       BZ2_bzCompressEnd(bz);
1140 +                       hctx->stream_open = 0;
1141 +                       return -1;
1142 +               }
1143 +
1144 +               if(bz->avail_out == 0 || bz->avail_in > 0) {
1145 +                       len = hctx->output->size - bz->avail_out;
1146 +                       hctx->bytes_out += len;
1147 +                       out += len;
1148 +                       chunkqueue_append_mem(con->write_queue, hctx->output->ptr, len+1);
1149 +                       bz->next_out = hctx->output->ptr;
1150 +                       bz->avail_out = hctx->output->size;
1151 +               }
1152 +       } while (bz->avail_in > 0);
1153 +       if(p->conf.debug) {
1154 +               log_error_write(srv, __FILE__, __LINE__, "sdsd",
1155 +                               "compress: in=", in, ", out=", out);
1156 +       }
1157 +       return 0;
1158 +}
1159 +
1160 +static int stream_bzip2_flush(server *srv, connection *con, handler_ctx *hctx, int end) {
1161 +       plugin_data *p = hctx->plugin_data;
1162 +       bz_stream *bz;
1163 +       int len;
1164 +       int rc;
1165 +       int done;
1166 +       int flush = 1;
1167 +       int in = 0, out = 0;
1168 +
1169 +       UNUSED(srv);
1170 +
1171 +       bz = &(hctx->bz);
1172 +
1173 +       if(bz->next_out == NULL) {
1174 +               bz->next_out = hctx->output->ptr;
1175 +               bz->avail_out = hctx->output->size;
1176 +       }
1177 +       /* compress data */
1178 +       in = bz->avail_in;
1179 +       do {
1180 +               done = 1;
1181 +               if(end) {
1182 +                       rc = BZ2_bzCompress(bz, BZ_FINISH);
1183 +                       if (rc == BZ_FINISH_OK) {
1184 +                               done = 0;
1185 +                       } else if (rc != BZ_STREAM_END) {
1186 +                               BZ2_bzCompressEnd(bz);
1187 +                               hctx->stream_open = 0;
1188 +                               return -1;
1189 +                       }
1190 +               } else if(bz->avail_in > 0) {
1191 +                       rc = BZ2_bzCompress(bz, BZ_RUN);
1192 +                       if (rc != BZ_RUN_OK) {
1193 +                               BZ2_bzCompressEnd(bz);
1194 +                               hctx->stream_open = 0;
1195 +                               return -1;
1196 +                       }
1197 +                       if(p->conf.output_buffer_size > 0) flush = 0;
1198 +               }
1199 +
1200 +               len = hctx->output->size - bz->avail_out;
1201 +               if(bz->avail_out == 0 || (flush && len > 0)) {
1202 +                       hctx->bytes_out += len;
1203 +                       out += len;
1204 +                       chunkqueue_append_mem(con->write_queue, hctx->output->ptr, len+1);
1205 +                       bz->next_out = hctx->output->ptr;
1206 +                       bz->avail_out = hctx->output->size;
1207 +               }
1208 +       } while (bz->avail_in != 0 || !done);
1209 +       if(p->conf.debug) {
1210 +               log_error_write(srv, __FILE__, __LINE__, "sdsd",
1211 +                               "flush: in=", in, ", out=", out);
1212 +       }
1213 +       if(p->conf.sync_flush) {
1214 +               bz->next_out = NULL;
1215 +               bz->avail_out = 0;
1216 +       }
1217 +       return 0;
1218 +}
1219 +
1220 +static int stream_bzip2_end(server *srv, connection *con, handler_ctx *hctx) {
1221 +       plugin_data *p = hctx->plugin_data;
1222 +       bz_stream *bz;
1223 +       int rc;
1224 +
1225 +       UNUSED(p);
1226 +       UNUSED(con);
1227 +
1228 +       bz = &(hctx->bz);
1229 +       if(!hctx->stream_open) return 0;
1230 +       hctx->stream_open = 0;
1231 +
1232 +       if ((rc = BZ2_bzCompressEnd(bz)) != BZ_OK) {
1233 +               if(rc == BZ_DATA_ERROR) return 0;
1234 +               log_error_write(srv, __FILE__, __LINE__, "sd",
1235 +                               "BZ2_bzCompressEnd error ret=", rc);
1236 +               return -1;
1237 +       }
1238 +       return 0;
1239 +}
1240 +
1241 +#endif
1242 +
1243 +static int mod_deflate_compress(server *srv, connection *con, handler_ctx *hctx, unsigned char *start, off_t st_size) {
1244 +       int ret = -1;
1245 +       if(st_size == 0) return 0;
1246 +       switch(hctx->compression_type) {
1247 +#ifdef USE_ZLIB
1248 +       case HTTP_ACCEPT_ENCODING_GZIP: 
1249 +       case HTTP_ACCEPT_ENCODING_DEFLATE: 
1250 +               ret = stream_deflate_compress(srv, con, hctx, start, st_size);
1251 +               break;
1252 +#endif
1253 +#ifdef USE_BZ2LIB
1254 +       case HTTP_ACCEPT_ENCODING_BZIP2: 
1255 +               ret = stream_bzip2_compress(srv, con, hctx, start, st_size);
1256 +               break;
1257 +#endif
1258 +       default:
1259 +               ret = -1;
1260 +               break;
1261 +       }
1262 +
1263 +       return ret;
1264 +}
1265 +
1266 +static int mod_deflate_stream_flush(server *srv, connection *con, handler_ctx *hctx, int end) {
1267 +       int ret = -1;
1268 +       if(hctx->bytes_in == 0) return 0;
1269 +       switch(hctx->compression_type) {
1270 +#ifdef USE_ZLIB
1271 +       case HTTP_ACCEPT_ENCODING_GZIP: 
1272 +       case HTTP_ACCEPT_ENCODING_DEFLATE: 
1273 +               ret = stream_deflate_flush(srv, con, hctx, end);
1274 +               break;
1275 +#endif
1276 +#ifdef USE_BZ2LIB
1277 +       case HTTP_ACCEPT_ENCODING_BZIP2: 
1278 +               ret = stream_bzip2_flush(srv, con, hctx, end);
1279 +               break;
1280 +#endif
1281 +       default:
1282 +               ret = -1;
1283 +               break;
1284 +       }
1285 +
1286 +       return ret;
1287 +}
1288 +
1289 +static int mod_deflate_stream_end(server *srv, connection *con, handler_ctx *hctx) {
1290 +       int ret = -1;
1291 +       switch(hctx->compression_type) {
1292 +#ifdef USE_ZLIB
1293 +       case HTTP_ACCEPT_ENCODING_GZIP: 
1294 +       case HTTP_ACCEPT_ENCODING_DEFLATE: 
1295 +               ret = stream_deflate_end(srv, con, hctx);
1296 +               break;
1297 +#endif
1298 +#ifdef USE_BZ2LIB
1299 +       case HTTP_ACCEPT_ENCODING_BZIP2: 
1300 +               ret = stream_bzip2_end(srv, con, hctx);
1301 +               break;
1302 +#endif
1303 +       default:
1304 +               ret = -1;
1305 +               break;
1306 +       }
1307 +
1308 +       return ret;
1309 +}
1310 +
1311 +static int mod_deflate_file_chunk(server *srv, connection *con, handler_ctx *hctx, chunk *c, off_t st_size) {
1312 +       plugin_data *p = hctx->plugin_data;
1313 +       off_t abs_offset;
1314 +       off_t toSend;
1315 +       stat_cache_entry *sce = NULL;
1316 +       off_t we_want_to_mmap = 2 MByte; 
1317 +       off_t we_want_to_send = st_size;
1318 +       char *start = NULL;
1319 +
1320 +       if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
1321 +               log_error_write(srv, __FILE__, __LINE__, "sb",
1322 +                               strerror(errno), c->file.name);
1323 +               return -1;
1324 +       }
1325 +
1326 +       abs_offset = c->file.start + c->offset;
1327 +       
1328 +       if (abs_offset > sce->st.st_size) {
1329 +               log_error_write(srv, __FILE__, __LINE__, "sb", 
1330 +                               "file was shrinked:", c->file.name);
1331 +               
1332 +               return -1;
1333 +       }
1334 +
1335 +       we_want_to_send = st_size;
1336 +       /* mmap the buffer 
1337 +        * - first mmap 
1338 +        * - new mmap as the we are at the end of the last one */
1339 +       if (c->file.mmap.start == MAP_FAILED ||
1340 +           abs_offset == (off_t)(c->file.mmap.offset + c->file.mmap.length)) {
1341 +
1342 +               /* Optimizations for the future:
1343 +                *
1344 +                * adaptive mem-mapping
1345 +                *   the problem:
1346 +                *     we mmap() the whole file. If someone has alot large files and 32bit
1347 +                *     machine the virtual address area will be unrun and we will have a failing 
1348 +                *     mmap() call.
1349 +                *   solution:
1350 +                *     only mmap 16M in one chunk and move the window as soon as we have finished
1351 +                *     the first 8M
1352 +                *
1353 +                * read-ahead buffering
1354 +                *   the problem:
1355 +                *     sending out several large files in parallel trashes the read-ahead of the
1356 +                *     kernel leading to long wait-for-seek times.
1357 +                *   solutions: (increasing complexity)
1358 +                *     1. use madvise
1359 +                *     2. use a internal read-ahead buffer in the chunk-structure
1360 +                *     3. use non-blocking IO for file-transfers
1361 +                *   */
1362 +
1363 +               /* all mmap()ed areas are 512kb expect the last which might be smaller */
1364 +               size_t to_mmap;
1365 +
1366 +               /* this is a remap, move the mmap-offset */
1367 +               if (c->file.mmap.start != MAP_FAILED) {
1368 +                       munmap(c->file.mmap.start, c->file.mmap.length);
1369 +                       c->file.mmap.offset += we_want_to_mmap;
1370 +               } else {
1371 +                       /* in case the range-offset is after the first mmap()ed area we skip the area */
1372 +                       c->file.mmap.offset = 0;
1373 +
1374 +                       while (c->file.mmap.offset + we_want_to_mmap < c->file.start) {
1375 +                               c->file.mmap.offset += we_want_to_mmap;
1376 +                       }
1377 +               }
1378 +
1379 +               /* length is rel, c->offset too, assume there is no limit at the mmap-boundaries */
1380 +               to_mmap = (c->file.start + c->file.length) - c->file.mmap.offset;
1381 +               if(to_mmap > we_want_to_mmap) to_mmap = we_want_to_mmap;
1382 +               /* we have more to send than we can mmap() at once */
1383 +               if(we_want_to_send > to_mmap) we_want_to_send = to_mmap;
1384 +
1385 +               if (-1 == c->file.fd) {  /* open the file if not already open */
1386 +                       if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
1387 +                               log_error_write(srv, __FILE__, __LINE__, "sbs", "open failed for:", c->file.name, strerror(errno));
1388 +               
1389 +                               return -1;
1390 +                       }
1391 +#ifdef FD_CLOEXEC
1392 +                       fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
1393 +#endif
1394 +               }
1395 +
1396 +               if (MAP_FAILED == (c->file.mmap.start = mmap(0, to_mmap, PROT_READ, MAP_SHARED, c->file.fd, c->file.mmap.offset))) {
1397 +                       /* close it here, otherwise we'd have to set FD_CLOEXEC */
1398 +
1399 +                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:", 
1400 +                                       strerror(errno), c->file.name, c->file.fd);
1401 +
1402 +                       return -1;
1403 +               }
1404 +
1405 +               c->file.mmap.length = to_mmap;
1406 +#ifdef LOCAL_BUFFERING
1407 +               buffer_copy_string_len(c->mem, c->file.mmap.start, c->file.mmap.length);
1408 +#else
1409 +#ifdef HAVE_MADVISE
1410 +               /* don't advise files < 64Kb */
1411 +               if (c->file.mmap.length > (64 KByte) && 
1412 +                   0 != madvise(c->file.mmap.start, c->file.mmap.length, MADV_WILLNEED)) {
1413 +                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "madvise failed:", 
1414 +                                       strerror(errno), c->file.name, c->file.fd);
1415 +               }
1416 +#endif
1417 +#endif
1418 +
1419 +               /* chunk_reset() or chunk_free() will cleanup for us */
1420 +       }
1421 +
1422 +       /* to_send = abs_mmap_end - abs_offset */
1423 +       toSend = (c->file.mmap.offset + c->file.mmap.length) - (abs_offset);
1424 +       if(toSend > we_want_to_send) toSend = we_want_to_send;
1425 +
1426 +       if (toSend < 0) {
1427 +               log_error_write(srv, __FILE__, __LINE__, "soooo", 
1428 +                               "toSend is negative:",
1429 +                               toSend,
1430 +                               c->file.mmap.length,
1431 +                               abs_offset,
1432 +                               c->file.mmap.offset); 
1433 +               assert(toSend < 0);
1434 +       }
1435 +
1436 +#ifdef LOCAL_BUFFERING
1437 +       start = c->mem->ptr;
1438 +#else
1439 +       start = c->file.mmap.start;
1440 +#endif
1441 +
1442 +       if(p->conf.debug) {
1443 +               log_error_write(srv, __FILE__, __LINE__, "sdsd",
1444 +                               "compress file chunk: offset=", (int)c->offset,
1445 +                               ", toSend=", (int)toSend);
1446 +       }
1447 +       if (mod_deflate_compress(srv, con, hctx,
1448 +                               (unsigned char *)start + (abs_offset - c->file.mmap.offset), toSend) < 0) {
1449 +               log_error_write(srv, __FILE__, __LINE__, "s", 
1450 +                               "compress failed.");
1451 +               return -1;
1452 +       }
1453 +
1454 +       c->offset += toSend;
1455 +       if (c->offset == c->file.length) {
1456 +               /* we don't need the mmaping anymore */
1457 +               if (c->file.mmap.start != MAP_FAILED) {
1458 +                       munmap(c->file.mmap.start, c->file.mmap.length);
1459 +                       c->file.mmap.start = MAP_FAILED;
1460 +               }
1461 +       }
1462 +
1463 +       return toSend;
1464 +}
1465 +
1466 +static int deflate_compress_cleanup(server *srv, connection *con, handler_ctx *hctx) {
1467 +       plugin_data *p = hctx->plugin_data;
1468 +       int rc;
1469 +
1470 +       rc = mod_deflate_stream_end(srv, con, hctx);
1471 +       if(rc < 0) {
1472 +               log_error_write(srv, __FILE__, __LINE__, "s", "error closing stream");
1473 +       }
1474 +
1475 +       if (hctx->bytes_in < hctx->bytes_out) {
1476 +               log_error_write(srv, __FILE__, __LINE__, "sbsdsd",
1477 +                               "uri ", con->uri.path_raw, " in=", hctx->bytes_in, " smaller than out=", hctx->bytes_out);
1478 +       }
1479 +
1480 +       if(p->conf.debug) {
1481 +               log_error_write(srv, __FILE__, __LINE__, "sdsd",
1482 +                               " in:", hctx->bytes_in,
1483 +                               " out:", hctx->bytes_out);
1484 +       }
1485 +
1486 +       /* cleanup compression state */
1487 +       if(hctx->output != p->tmp_buf) {
1488 +               buffer_free(hctx->output);
1489 +       }
1490 +       handler_ctx_free(hctx);
1491 +       con->plugin_ctx[p->id] = NULL;
1492 +
1493 +       return 0;
1494 +}
1495 +
1496 +static handler_t deflate_compress_response(server *srv, connection *con, handler_ctx *hctx, int end) { 
1497 +       plugin_data *p = hctx->plugin_data;
1498 +       chunk *c;
1499 +       size_t chunks_written = 0;
1500 +       int chunk_finished = 0;
1501 +       int rc=-1;
1502 +       int close_stream = 0, len = 0;
1503 +       unsigned int out = 0, max = 0;
1504 +       
1505 +       /* move all chunk from write_queue into our in_queue */
1506 +       chunkqueue_append_chunkqueue(hctx->in_queue, con->write_queue);
1507 +
1508 +       len = chunkqueue_length(hctx->in_queue);
1509 +       if(p->conf.debug) {
1510 +               log_error_write(srv, __FILE__, __LINE__, "sd",
1511 +                               "compress: in_queue len=", len);
1512 +       }
1513 +       /* calculate max bytes to compress for this call. */
1514 +       if(!end) {
1515 +               max = p->conf.work_block_size * 1024;
1516 +               if(max == 0 || max > len) max = len;
1517 +       } else {
1518 +               max = len;
1519 +       }
1520 +
1521 +       /* Compress chunks from in_queue into chunks for write_queue */
1522 +       for(c = hctx->in_queue->first; c && out < max; c = c->next) {
1523 +               chunk_finished = 0;
1524 +               len = 0;
1525 +               
1526 +               switch(c->type) {
1527 +               case MEM_CHUNK:
1528 +                       len = c->mem->used - 1;
1529 +                       if(len > (max - out)) len = max - out;
1530 +                       if (mod_deflate_compress(srv, con, hctx, (unsigned char *)c->mem->ptr, len) < 0) {
1531 +                               log_error_write(srv, __FILE__, __LINE__, "s", 
1532 +                                               "compress failed.");
1533 +                               return HANDLER_ERROR;
1534 +                       }
1535 +                       c->offset += len;
1536 +                       out += len;
1537 +                       if (c->offset == c->mem->used - 1) {
1538 +                               chunk_finished = 1;
1539 +                               chunks_written++;
1540 +                       }
1541 +                       break;
1542 +               case FILE_CHUNK:
1543 +                       len = c->file.length - c->offset;
1544 +                       if(len > (max - out)) len = max - out;
1545 +                       if ((len = mod_deflate_file_chunk(srv, con, hctx, c, len)) < 0) {
1546 +                               log_error_write(srv, __FILE__, __LINE__, "s", 
1547 +                                               "compress file chunk failed.");
1548 +                               return HANDLER_ERROR;
1549 +                       }
1550 +                       out += len;
1551 +                       if (c->offset == c->file.length) {
1552 +                               chunk_finished = 1;
1553 +                               chunks_written++;
1554 +                       }
1555 +                       break;
1556 +               default:
1557 +                       
1558 +                       log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
1559 +                       
1560 +                       return HANDLER_ERROR;
1561 +               }
1562 +               if(!chunk_finished) break;
1563 +       }
1564 +       if(p->conf.debug) {
1565 +               log_error_write(srv, __FILE__, __LINE__, "sd",
1566 +                               "compressed bytes:", out);
1567 +       }
1568 +       hctx->in_queue->bytes_out += out;
1569 +
1570 +       if(chunks_written > 0) {
1571 +               chunkqueue_remove_finished_chunks(hctx->in_queue);
1572 +       }
1573 +
1574 +       close_stream = (con->file_finished && chunkqueue_is_empty(hctx->in_queue));
1575 +       rc = mod_deflate_stream_flush(srv, con, hctx, close_stream);
1576 +       if(rc < 0) {
1577 +               log_error_write(srv, __FILE__, __LINE__, "s", "flush error");
1578 +       }
1579 +       if(close_stream || end) {
1580 +               deflate_compress_cleanup(srv, con, hctx);
1581 +               if(p->conf.debug) {
1582 +                       log_error_write(srv, __FILE__, __LINE__, "sbsb",
1583 +                                       "finished uri:", con->uri.path_raw, ", query:", con->uri.query);
1584 +               }
1585 +               return HANDLER_FINISHED;
1586 +       } else {
1587 +               if(!chunkqueue_is_empty(hctx->in_queue)) {
1588 +                       /* We have more data to compress. */
1589 +                       joblist_append(srv, con);
1590 +               }
1591 +               return HANDLER_COMEBACK;
1592 +       }
1593 +}
1594 +
1595 +#define PATCH(x) \
1596 +       p->conf.x = s->x;
1597 +static int mod_deflate_patch_connection(server *srv, connection *con, plugin_data *p) {
1598 +       size_t i, j;
1599 +       plugin_config *s = p->config_storage[0];
1600 +
1601 +       PATCH(output_buffer_size);
1602 +       PATCH(mimetypes);
1603 +       PATCH(compression_level);
1604 +       PATCH(mem_level);
1605 +       PATCH(window_size);
1606 +       PATCH(min_compress_size);
1607 +       PATCH(work_block_size);
1608 +       PATCH(enabled);
1609 +       PATCH(debug);
1610 +       PATCH(bzip2);
1611 +       PATCH(sync_flush);
1612 +#if defined(HAVE_PCRE_H)
1613 +       PATCH(nocompress_regex);
1614 +#endif 
1615 +       
1616 +       /* skip the first, the global context */
1617 +       for (i = 1; i < srv->config_context->used; i++) {
1618 +               data_config *dc = (data_config *)srv->config_context->data[i];
1619 +               s = p->config_storage[i];
1620 +               
1621 +               /* condition didn't match */
1622 +               if (!config_check_cond(srv, con, dc)) continue;
1623 +               
1624 +               /* merge config */
1625 +               for (j = 0; j < dc->value->used; j++) {
1626 +                       data_unset *du = dc->value->data[j];
1627 +                       
1628 +                       if (buffer_is_equal_string(du->key, CONST_STR_LEN("deflate.output-buffer-size"))) {
1629 +                               PATCH(output_buffer_size);
1630 +                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("deflate.mimetypes"))) {
1631 +                               PATCH(mimetypes);
1632 +                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("deflate.compression-level"))) {
1633 +                               PATCH(compression_level);
1634 +                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("deflate.mem-level"))) {
1635 +                               PATCH(mem_level);
1636 +                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("deflate.window-size"))) {
1637 +                               PATCH(window_size);
1638 +                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("deflate.min-compress-size"))) {
1639 +                               PATCH(min_compress_size);
1640 +                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("deflate.work-block-size"))) {
1641 +                               PATCH(work_block_size);
1642 +                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("deflate.enabled"))) {
1643 +                               PATCH(enabled);
1644 +                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("deflate.debug"))) {
1645 +                               PATCH(debug);
1646 +                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("deflate.bzip2"))) {
1647 +                               PATCH(bzip2);
1648 +                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("deflate.sync-flush"))) {
1649 +                               PATCH(sync_flush);
1650 +                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("deflate.nocompress-url"))) {
1651 +#if defined(HAVE_PCRE_H)
1652 +                               PATCH(nocompress_regex);
1653 +#endif
1654 +                       }
1655 +               }
1656 +       }
1657 +       
1658 +       return 0;
1659 +}
1660 +#undef PATCH
1661 +
1662 +PHYSICALPATH_FUNC(mod_deflate_handle_response_start) {
1663 +       plugin_data *p = p_d;
1664 +       handler_ctx *hctx;
1665 +       data_string *ds;
1666 +       int accept_encoding = 0;
1667 +       char *value;
1668 +       int srv_encodings = 0;
1669 +       int matched_encodings = 0;
1670 +       const char *dflt_gzip = "gzip";
1671 +       const char *dflt_deflate = "deflate";
1672 +       const char *dflt_bzip2 = "bzip2";
1673 +       const char *compression_name = NULL;
1674 +       int file_len=0;
1675 +       int rc=-2;
1676 +       int end = 0;
1677 +       size_t m;
1678 +#if defined(HAVE_PCRE_H)
1679 +       int n;
1680 +# define N 10
1681 +       int ovec[N * 3];
1682 +#endif
1683 +       
1684 +       /* disable compression for some http status types. */
1685 +       switch(con->http_status) {
1686 +       case 100:
1687 +       case 101:
1688 +       case 204:
1689 +       case 205:
1690 +       case 304:
1691 +               /* disable compression as we have no response entity */
1692 +               return HANDLER_GO_ON;
1693 +       default:
1694 +               break;
1695 +       }
1696 +
1697 +       mod_deflate_patch_connection(srv, con, p);
1698 +
1699 +       /* is compression allowed */
1700 +       if(!p->conf.enabled) {
1701 +               if(p->conf.debug) {
1702 +                       log_error_write(srv, __FILE__, __LINE__, "s", "compression disabled.");
1703 +               }
1704 +               return HANDLER_GO_ON;
1705 +       }
1706 +
1707 +#if defined(HAVE_PCRE_H)
1708 +       if(p->conf.nocompress_regex) { /*check no compress regex now */
1709 +               if ((n = pcre_exec(p->conf.nocompress_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
1710 +                       if (n != PCRE_ERROR_NOMATCH) {
1711 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
1712 +                                       "execution error while matching:", n);
1713 +                               return HANDLER_ERROR;
1714 +                       }
1715 +               } else {
1716 +                       if(p->conf.debug) {
1717 +                               log_error_write(srv, __FILE__, __LINE__, "sb", "no compress for url:", con->uri.path);
1718 +                       }
1719 +                       return HANDLER_GO_ON;
1720 +               }
1721 +       }
1722 +#endif
1723 +       /* Check if response has a Content-Encoding. */
1724 +       if (NULL != (ds = (data_string *)array_get_element(con->response.headers, "Content-Encoding"))) {
1725 +               return HANDLER_GO_ON;
1726 +       }
1727 +
1728 +       /* Check Accept-Encoding for supported encoding. */
1729 +       if (NULL == (ds = (data_string *)array_get_element(con->request.headers, "Accept-Encoding"))) {
1730 +               return HANDLER_GO_ON;
1731 +       }
1732 +               
1733 +       /* get client side support encodings */
1734 +       value = ds->value->ptr;
1735 +#ifdef USE_ZLIB
1736 +       if (NULL != strstr(value, "gzip")) accept_encoding |= HTTP_ACCEPT_ENCODING_GZIP;
1737 +       if (NULL != strstr(value, "deflate")) accept_encoding |= HTTP_ACCEPT_ENCODING_DEFLATE;
1738 +#endif
1739 +       /* if (NULL != strstr(value, "compress")) accept_encoding |= HTTP_ACCEPT_ENCODING_COMPRESS; */
1740 +#ifdef USE_BZ2LIB
1741 +       if(p->conf.bzip2) {
1742 +               if (NULL != strstr(value, "bzip2")) accept_encoding |= HTTP_ACCEPT_ENCODING_BZIP2;
1743 +       }
1744 +#endif
1745 +       if (NULL != strstr(value, "identity")) accept_encoding |= HTTP_ACCEPT_ENCODING_IDENTITY;
1746 +               
1747 +       /* get server side supported ones */
1748 +#ifdef USE_BZ2LIB
1749 +       if(p->conf.bzip2) {
1750 +               srv_encodings |= HTTP_ACCEPT_ENCODING_BZIP2;
1751 +       }
1752 +#endif
1753 +#ifdef USE_ZLIB
1754 +       srv_encodings |= HTTP_ACCEPT_ENCODING_GZIP;
1755 +       srv_encodings |= HTTP_ACCEPT_ENCODING_DEFLATE;
1756 +#endif
1757 +               
1758 +       /* find matching encodings */
1759 +       matched_encodings = accept_encoding & srv_encodings;
1760 +       if (!matched_encodings) {
1761 +               return HANDLER_GO_ON;
1762 +       }
1763 +
1764 +       if (con->request.true_http_10_client) { 
1765 +               /*disable gzip/bzip2 when we meet HTTP 1.0 client with Accept-Encoding
1766 +                * maybe old buggy proxy server
1767 +                */
1768 +               /* most of buggy clients are Yahoo Slurp;) */
1769 +               if (p->conf.debug) log_error_write(srv, __FILE__, __LINE__, "ss",
1770 +                               "Buggy HTTP 1.0 client sending Accept Encoding: gzip, deflate", 
1771 +                               (char *) inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
1772 +               return HANDLER_GO_ON;
1773 +       }
1774 +       /* check if size of response is below min-compress-size */
1775 +       if(con->file_finished && con->request.http_method != HTTP_METHOD_HEAD) {
1776 +               file_len = chunkqueue_length(con->write_queue);
1777 +               if(file_len == 0) return HANDLER_GO_ON;
1778 +       } else {
1779 +               file_len = 0;
1780 +       }
1781 +
1782 +       if(file_len > 0 && p->conf.min_compress_size > 0 && file_len < p->conf.min_compress_size) {
1783 +               if(p->conf.debug) {
1784 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
1785 +                                       "Content-Length smaller then min_compress_size: file_len=", file_len);
1786 +               }
1787 +               return HANDLER_GO_ON;
1788 +       }
1789 +
1790 +       /* Check mimetype in response header "Content-Type" */
1791 +       if (NULL != (ds = (data_string *)array_get_element(con->response.headers, "Content-Type"))) {
1792 +               int found = 0;
1793 +               if(p->conf.debug) {
1794 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
1795 +                                       "Content-Type:", ds->value);
1796 +               }
1797 +               for (m = 0; m < p->conf.mimetypes->used; m++) {
1798 +                       data_string *mimetype = (data_string *)p->conf.mimetypes->data[m];
1799 +
1800 +                       if(p->conf.debug) {
1801 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
1802 +                                               "mime-type:", mimetype->value);
1803 +                       }
1804 +                       if (strncmp(mimetype->value->ptr, ds->value->ptr, mimetype->value->used-1) == 0) {
1805 +/*                     if (buffer_is_equal(mimetype->value, ds->value)) { */
1806 +                               /* mimetype found */
1807 +                               found = 1;
1808 +                               break;
1809 +                       }
1810 +               }
1811 +               if(!found && p->conf.mimetypes->used > 0) {
1812 +                       if(p->conf.debug) {
1813 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
1814 +                                               "No compression for mimetype:", ds->value);
1815 +                       }
1816 +                       return HANDLER_GO_ON;
1817 +               }
1818 +#if 0
1819 +               if(strncasecmp(ds->value->ptr, "application/x-javascript", 24) == 0) {
1820 +                       /*reset compress type to deflate for javascript
1821 +                        * prevent buggy IE6 SP1 doesn't work for js in IFrame
1822 +                        */
1823 +                       matched_encodings = HTTP_ACCEPT_ENCODING_DEFLATE;
1824 +               }
1825 +#endif
1826 +       }
1827 +       
1828 +       if(p->conf.debug) {
1829 +               log_error_write(srv, __FILE__, __LINE__, "sb",
1830 +                               "enable compression for ", con->uri.path);
1831 +       }
1832 +
1833 +       /* the response might change according to Accept-Encoding */
1834 +       if (NULL != (ds = (data_string *)array_get_element(con->response.headers, "Vary"))) {
1835 +               /* append Accept-Encoding to Vary header */
1836 +               if (NULL == strstr(ds->value->ptr, "Accept-Encoding")) {
1837 +                       buffer_append_string(ds->value, ",Accept-Encoding");
1838 +                       if (p->conf.debug) {
1839 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
1840 +                                               "appending ,Accept-Encoding for ", con->uri.path);
1841 +                       }
1842 +               }
1843 +       } else {
1844 +               if (p->conf.debug) {
1845 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
1846 +                                       "add Vary: Accept-Encoding for ", con->uri.path);
1847 +               }
1848 +               response_header_insert(srv, con, CONST_STR_LEN("Vary"),
1849 +                               CONST_STR_LEN("Accept-Encoding"));
1850 +       }
1851 +
1852 +       /* enable compression */
1853 +       hctx = handler_ctx_init();
1854 +       hctx->plugin_data = p;
1855 +
1856 +       /* select best matching encoding */
1857 +       if (matched_encodings & HTTP_ACCEPT_ENCODING_BZIP2) {
1858 +               hctx->compression_type = HTTP_ACCEPT_ENCODING_BZIP2;
1859 +               compression_name = dflt_bzip2;
1860 +               rc = stream_bzip2_init(srv, con, hctx);
1861 +       } else if (matched_encodings & HTTP_ACCEPT_ENCODING_GZIP) {
1862 +               hctx->compression_type = HTTP_ACCEPT_ENCODING_GZIP;
1863 +               compression_name = dflt_gzip;
1864 +               rc = stream_deflate_init(srv, con, hctx);
1865 +       } else if (matched_encodings & HTTP_ACCEPT_ENCODING_DEFLATE) {
1866 +               hctx->compression_type = HTTP_ACCEPT_ENCODING_DEFLATE;
1867 +               compression_name = dflt_deflate;
1868 +               rc = stream_deflate_init(srv, con, hctx);
1869 +       }
1870 +       if(rc == -1) {
1871 +               log_error_write(srv, __FILE__, __LINE__, "s",
1872 +                               "Failed to initialize compression.");
1873 +       }
1874 +
1875 +       if(rc < 0) {
1876 +               handler_ctx_free(hctx);
1877 +               return HANDLER_GO_ON;
1878 +       }
1879 +
1880 +       /* setup output buffer. */
1881 +       if(p->conf.sync_flush || p->conf.output_buffer_size == 0) {
1882 +               buffer_prepare_copy(p->tmp_buf, 32 * 1024);
1883 +               hctx->output = p->tmp_buf;
1884 +       } else {
1885 +               hctx->output = buffer_init();
1886 +               buffer_prepare_copy(hctx->output, p->conf.output_buffer_size);
1887 +       }
1888 +       con->plugin_ctx[p->id] = hctx;
1889 +
1890 +       /* set Content-Encoding to show selected compression type. */
1891 +       response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
1892 +
1893 +       if (con->file_finished) end = 1;
1894 +
1895 +       con->parsed_response &= ~(HTTP_CONTENT_LENGTH); 
1896 +#if 0
1897 +       /* debug */
1898 +       if (con->parsed_response & HTTP_TRANSFER_ENCODING_CHUNKED)
1899 +               log_error_write(srv, __FILE__, __LINE__, "s",
1900 +                       "deflate: response with chunked encoding");
1901 +       if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED)
1902 +               log_error_write(srv, __FILE__, __LINE__, "s",
1903 +                       "deflate: transfer encoding with chunked encoding");
1904 +#endif
1905 +
1906 +       if (con->file_finished && (p->conf.work_block_size == 0 || file_len < (p->conf.work_block_size * 1024))
1907 +                       && con->request.http_method != HTTP_METHOD_HEAD) {
1908 +               /* disable chunk transfer */
1909 +               con->response.transfer_encoding = 0; 
1910 +               con->parsed_response &= ~(HTTP_TRANSFER_ENCODING_CHUNKED);
1911 +               if(p->conf.debug) {
1912 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
1913 +                                       "Compress all content and use Content-Length header: uncompress len=", file_len);
1914 +               }
1915 +               return deflate_compress_response(srv, con, hctx, end); 
1916 +       } else {
1917 +               if (con->request.http_version == HTTP_VERSION_1_1) {
1918 +                       if (p->conf.debug) 
1919 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
1920 +                                       "chunk transfer encoding for uri", con->uri.path);
1921 +                       /* Make sure to use chunked encoding. */
1922 +                       con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED; 
1923 +               } else {
1924 +                       if (p->conf.debug) 
1925 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
1926 +                                       "http 1.0 encoding for uri", con->uri.path);
1927 +                       /* We don't have to use chunked encoding because HTTP 1.0 don't support it. */
1928 +                       con->response.transfer_encoding = 0;
1929 +                       con->parsed_response &= ~(HTTP_TRANSFER_ENCODING_CHUNKED);
1930 +               }
1931 +       }
1932 +
1933 +       if (p->conf.debug) 
1934 +               log_error_write(srv, __FILE__, __LINE__, "sdsb", "end =", end, "for uri", con->uri.path);
1935 +
1936 +       deflate_compress_response(srv, con, hctx, end);
1937 +       return HANDLER_GO_ON;
1938 +}
1939 +
1940 +JOBLIST_FUNC(mod_deflate_handle_response_filter) {
1941 +       plugin_data *p = p_d;
1942 +       handler_ctx *hctx = con->plugin_ctx[p->id];
1943 +
1944 +       if(hctx == NULL) return HANDLER_GO_ON;
1945 +       if(!hctx->stream_open) return HANDLER_GO_ON;
1946 +       if(con->request.http_method == HTTP_METHOD_HEAD) return HANDLER_GO_ON;
1947 +
1948 +       return deflate_compress_response(srv, con, hctx, 0); 
1949 +}
1950 +
1951 +handler_t mod_deflate_cleanup(server *srv, connection *con, void *p_d) {
1952 +       plugin_data *p = p_d;
1953 +       handler_ctx *hctx = con->plugin_ctx[p->id];
1954 +
1955 +       if(hctx == NULL) return HANDLER_GO_ON;
1956 +
1957 +       if(p->conf.debug && hctx->stream_open) {
1958 +               log_error_write(srv, __FILE__, __LINE__, "sbsb",
1959 +                               "stream open at cleanup. uri=", con->uri.path_raw, ", query=", con->uri.query);
1960 +       }
1961 +
1962 +       deflate_compress_cleanup(srv, con, hctx);
1963 +
1964 +       return HANDLER_GO_ON;
1965 +}
1966 +
1967 +int mod_deflate_plugin_init(plugin *p) {
1968 +       p->version     = LIGHTTPD_VERSION_ID;
1969 +       p->name        = buffer_init_string("deflate");
1970 +       
1971 +       p->init         = mod_deflate_init;
1972 +       p->cleanup      = mod_deflate_free;
1973 +       p->set_defaults = mod_deflate_setdefaults;
1974 +       p->connection_reset     = mod_deflate_cleanup;
1975 +       p->handle_connection_close      = mod_deflate_cleanup;
1976 +       p->handle_response_start        = mod_deflate_handle_response_start;
1977 +       p->handle_response_filter       = mod_deflate_handle_response_filter;
1978 +       
1979 +       p->data        = NULL;
1980 +       
1981 +       return 0;
1982 +}
1983 diff -Naur lighttpd-1.4.19/src/plugin.c lighttpd-1.4.19.mod_deflate.jz/src/plugin.c
1984 --- lighttpd-1.4.19/src/plugin.c
1985 +++ lighttpd-1.4.19.mod_deflate.jz/src/plugin.c
1986 @@ -40,6 +40,8 @@
1987                 PLUGIN_FUNC_HANDLE_SIGHUP,
1988                 PLUGIN_FUNC_HANDLE_SUBREQUEST,
1989                 PLUGIN_FUNC_HANDLE_SUBREQUEST_START,
1990 +               PLUGIN_FUNC_HANDLE_RESPONSE_START,
1991 +               PLUGIN_FUNC_HANDLE_RESPONSE_FILTER,
1992                 PLUGIN_FUNC_HANDLE_JOBLIST,
1993                 PLUGIN_FUNC_HANDLE_DOCROOT,
1994                 PLUGIN_FUNC_HANDLE_PHYSICAL,
1995 @@ -266,6 +268,8 @@
1996  PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close)
1997  PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST, handle_subrequest)
1998  PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST_START, handle_subrequest_start)
1999 +PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_RESPONSE_START, handle_response_start)
2000 +PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_RESPONSE_FILTER, handle_response_filter)
2001  PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_JOBLIST, handle_joblist)
2002  PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_DOCROOT, handle_docroot)
2003  PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_PHYSICAL, handle_physical)
2004 @@ -395,6 +399,8 @@
2005                 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup);
2006                 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST, handle_subrequest);
2007                 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST_START, handle_subrequest_start);
2008 +               PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_RESPONSE_START, handle_response_start);
2009 +               PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_RESPONSE_FILTER, handle_response_filter);
2010                 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_JOBLIST, handle_joblist);
2011                 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_DOCROOT, handle_docroot);
2012                 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_PHYSICAL, handle_physical);
2013 diff -Naur lighttpd-1.4.19/src/plugin.h lighttpd-1.4.19.mod_deflate.jz/src/plugin.h
2014 --- lighttpd-1.4.19/src/plugin.h
2015 +++ lighttpd-1.4.19.mod_deflate.jz/src/plugin.h
2016 @@ -54,6 +54,8 @@
2017                                                                                             * has to be found
2018                                                                                             */
2019         handler_t (* handle_subrequest)      (server *srv, connection *con, void *p_d);    /* */
2020 +       handler_t (* handle_response_start)  (server *srv, connection *con, void *p_d);    /* before response headers are written */
2021 +       handler_t (* handle_response_filter) (server *srv, connection *con, void *p_d);    /* response content filter */
2022         handler_t (* connection_reset)       (server *srv, connection *con, void *p_d);    /* */
2023         void *data;
2024  
2025 @@ -68,6 +70,8 @@
2026  handler_t plugins_call_handle_uri_clean(server *srv, connection *con);
2027  handler_t plugins_call_handle_subrequest_start(server *srv, connection *con);
2028  handler_t plugins_call_handle_subrequest(server *srv, connection *con);
2029 +handler_t plugins_call_handle_response_start(server *srv, connection *con);
2030 +handler_t plugins_call_handle_response_filter(server *srv, connection *con);
2031  handler_t plugins_call_handle_request_done(server *srv, connection *con);
2032  handler_t plugins_call_handle_docroot(server *srv, connection *con);
2033  handler_t plugins_call_handle_physical(server *srv, connection *con);
2034 diff -Naur lighttpd-1.4.19/src/request.c lighttpd-1.4.19.mod_deflate.jz/src/request.c
2035 --- lighttpd-1.4.19/src/request.c
2036 +++ lighttpd-1.4.19.mod_deflate.jz/src/request.c
2037 @@ -415,8 +415,10 @@
2038  
2039                                         if (major_num == 1 && minor_num == 1) {
2040                                                 con->request.http_version = con->conf.allow_http11 ? HTTP_VERSION_1_1 : HTTP_VERSION_1_0;
2041 +                                               con->request.true_http_10_client = 0;
2042                                         } else if (major_num == 1 && minor_num == 0) {
2043                                                 con->request.http_version = HTTP_VERSION_1_0;
2044 +                                               con->request.true_http_10_client = 1;
2045                                         } else {
2046                                                 con->http_status = 505;
2047  
2048 diff -Naur lighttpd-1.4.19/src/response.c lighttpd-1.4.19.mod_deflate.jz/src/response.c
2049 --- lighttpd-1.4.19/src/response.c
2050 +++ lighttpd-1.4.19.mod_deflate.jz/src/response.c
2051 @@ -32,7 +32,7 @@
2052         int have_date = 0;
2053         int have_server = 0;
2054  
2055 -       b = chunkqueue_get_prepend_buffer(con->write_queue);
2056 +       b = chunkqueue_get_prepend_buffer(con->output_queue);
2057  
2058         if (con->request.http_version == HTTP_VERSION_1_1) {
2059                 BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
2060 @@ -49,6 +49,8 @@
2061         }
2062  
2063         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
2064 +/*     if (!(con->parsed_response & HTTP_TRANSFER_ENCODING_CHUNKED) &&
2065 +            (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED)) { */
2066                 BUFFER_APPEND_STRING_CONST(b, "\r\nTransfer-Encoding: chunked");
2067         }
2068  
2069 @@ -65,6 +67,16 @@
2070                         if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Date"))) have_date = 1;
2071                         if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Server"))) have_server = 1;
2072  
2073 +                       /* remove Transfer-Encoding: chunked header when HTTP 1.0
2074 +                        * or transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED == 0
2075 +                        */
2076 +                       if ( (con->request.http_version == HTTP_VERSION_1_0 || 
2077 +                            !(con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED)) &&
2078 +                            0 == strncasecmp(ds->value->ptr, "chunked", sizeof("chunked")-1) &&
2079 +                            0 == strncasecmp(ds->key->ptr, "Transfer-Encoding", sizeof("Transfer-Encoding") - 1)) {
2080 +                               continue ;
2081 +                       }
2082 +
2083                         BUFFER_APPEND_STRING_CONST(b, "\r\n");
2084                         buffer_append_string_buffer(b, ds->key);
2085                         BUFFER_APPEND_STRING_CONST(b, ": ");
2086 @@ -576,7 +588,7 @@
2087                                 }
2088  
2089                                 if (slash) pathinfo = slash;
2090 -                       } while ((found == 0) && (slash != NULL) && ((size_t)(slash - srv->tmp_buf->ptr) > (con->physical.basedir->used - 2)));
2091 +                       } while ((found == 0) && (slash != NULL) && ((size_t)(slash - srv->tmp_buf->ptr) > con->physical.basedir->used - 2));
2092  
2093                         if (found == 0) {
2094                                 /* no it really doesn't exists */
2095 diff -Naur lighttpd-1.4.19/src/server.c lighttpd-1.4.19.mod_deflate.jz/src/server.c
2096 --- lighttpd-1.4.19/src/server.c
2097 +++ lighttpd-1.4.19.mod_deflate.jz/src/server.c
2098 @@ -203,6 +203,9 @@
2099         srv->joblist = calloc(1, sizeof(*srv->joblist));
2100         assert(srv->joblist);
2101  
2102 +       srv->joblist_prev = calloc(1, sizeof(*srv->joblist));
2103 +       assert(srv->joblist_prev);
2104 +
2105         srv->fdwaitqueue = calloc(1, sizeof(*srv->fdwaitqueue));
2106         assert(srv->fdwaitqueue);
2107  
2108 @@ -294,6 +297,7 @@
2109  #undef CLEAN
2110  
2111         joblist_free(srv, srv->joblist);
2112 +       joblist_free(srv, srv->joblist_prev);
2113         fdwaitqueue_free(srv, srv->fdwaitqueue);
2114  
2115         if (srv->stat_cache) {
2116 @@ -1137,6 +1141,7 @@
2117         /* main-loop */
2118         while (!srv_shutdown) {
2119                 int n;
2120 +               int timeout;
2121                 size_t ndx;
2122                 time_t min_ts;
2123  
2124 @@ -1388,7 +1393,12 @@
2125                         }
2126                 }
2127  
2128 -               if ((n = fdevent_poll(srv->ev, 1000)) > 0) {
2129 +               if(srv->joblist->used > 0) {
2130 +                       timeout = 500;
2131 +               } else {
2132 +                       timeout = 1000;
2133 +               }
2134 +               if ((n = fdevent_poll(srv->ev, timeout)) > 0) {
2135                         /* n is the number of events */
2136                         int revents;
2137                         int fd_ndx;
2138 @@ -1436,10 +1446,16 @@
2139                                         strerror(errno));
2140                 }
2141  
2142 -               for (ndx = 0; ndx < srv->joblist->used; ndx++) {
2143 -                       connection *con = srv->joblist->ptr[ndx];
2144 +               if(srv->joblist->used > 0) {
2145 +                       connections *joblist = srv->joblist;
2146 +                       /* switch joblist queues. */
2147 +                       srv->joblist = srv->joblist_prev;
2148 +                       srv->joblist_prev = joblist;
2149 +                       for (ndx = 0; ndx < joblist->used; ndx++) {
2150 +                               connection *con = joblist->ptr[ndx];
2151                         handler_t r;
2152  
2153 +                               con->in_joblist = 0;
2154                         connection_state_machine(srv, con);
2155  
2156                         switch(r = plugins_call_handle_joblist(srv, con)) {
2157 @@ -1450,11 +1466,9 @@
2158                                 log_error_write(srv, __FILE__, __LINE__, "d", r);
2159                                 break;
2160                         }
2161 -
2162 -                       con->in_joblist = 0;
2163                 }
2164 -
2165 -               srv->joblist->used = 0;
2166 +                       joblist->used = 0;
2167 +               }
2168         }
2169  
2170         if (srv->srvconf.pid_file->used &&
This page took 0.616128 seconds and 3 git commands to generate.