]> git.pld-linux.org Git - packages/lighttpd.git/blob - lighttpd-branch.diff
3104f45512ff0d56d0b8dccf8bd6fc68975f81a5
[packages/lighttpd.git] / lighttpd-branch.diff
1 --- lighttpd-1.4.11/Makefile.in 2006-03-07 14:21:08.000000000 +0200
2 +++ lighttpd-1.4.12/Makefile.in 2006-07-11 21:48:16.000000000 +0300
3 @@ -1,4 +1,4 @@
4 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
5 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
6  # @configure_input@
7  
8  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
9 @@ -41,7 +41,7 @@
10         $(srcdir)/distribute.sh.in $(srcdir)/lighttpd.spec.in \
11         $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
12         compile config.guess config.sub depcomp install-sh ltmain.sh \
13 -       missing mkinstalldirs
14 +       missing
15  subdir = .
16  ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
17  am__aclocal_m4_deps = $(top_srcdir)/configure.in
18 @@ -49,7 +49,7 @@
19         $(ACLOCAL_M4)
20  am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
21   configure.lineno configure.status.lineno
22 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
23 +mkinstalldirs = $(install_sh) -d
24  CONFIG_HEADER = config.h
25  CONFIG_CLEAN_FILES = lighttpd.spec distribute.sh
26  SOURCES =
27 @@ -126,7 +126,6 @@
28  LIBTOOL = @LIBTOOL@
29  LN_S = @LN_S@
30  LTLIBOBJS = @LTLIBOBJS@
31 -LUACONFIG = @LUACONFIG@
32  LUA_CFLAGS = @LUA_CFLAGS@
33  LUA_LIBS = @LUA_LIBS@
34  MAINT = @MAINT@
35 @@ -169,6 +168,7 @@
36  ac_ct_F77 = @ac_ct_F77@
37  ac_ct_RANLIB = @ac_ct_RANLIB@
38  ac_ct_STRIP = @ac_ct_STRIP@
39 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
40  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
41  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
42  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
43 --- lighttpd-1.4.11/NEWS        2006-03-09 19:34:33.000000000 +0200
44 +++ lighttpd-1.4.12/NEWS        2006-07-11 22:07:54.000000000 +0300
45 @@ -3,6 +3,23 @@
46  NEWS
47  ====
48  
49 +- 1.4.12 - 2006-..-..
50 +
51 +  * added handling of Content-Range to PUT requests in mod_webdav
52 +  * added handling of ETag and If-Modified-Since to mod_compress if 
53 +    cache-dir is not set
54 +  * added experimental LOCK support for mod_webdav 
55 +  * added support for X-Sendfile as addition to X-LIGHTTPD-send-file.
56 +    This allows compatibility with mod_xsendfile for apache
57 +    (http://celebnamer.celebworld.ws/stuff/mod_xsendfile/)
58 +  * fixed handling of If-Modified-Since if Etag is not set
59 +  * fixed hanging fastcgi connections
60 +  * fixed stalling SSL POST requests 
61 +  * fixed round-robin load-balancing in mod_proxy
62 +  * TODO: add fail-over to mod-proxy
63 +  * TODO: fix CACHE_HIT/MISS in mod_cml
64 +  * TODO: finish LOCK/UNLOCK in mod_webdav
65 +
66  - 1.4.11 - 2006-03-09
67  
68    * added ability to specify which ip address spawn-fci listens on 
69 --- lighttpd-1.4.11/configure.in        2006-03-04 16:32:38.000000000 +0200
70 +++ lighttpd-1.4.12/configure.in        2006-07-11 22:07:54.000000000 +0300
71 @@ -1,7 +1,7 @@
72  #                                               -*- Autoconf -*-
73  # Process this file with autoconf to produce a configure script.
74  AC_PREREQ(2.57)
75 -AC_INIT(lighttpd, 1.4.11, jan@kneschke.de)
76 +AC_INIT(lighttpd, 1.4.12, jan@kneschke.de)
77  AC_CONFIG_SRCDIR([src/server.c])
78  
79  AC_CANONICAL_TARGET
80 @@ -66,7 +66,7 @@
81  AC_TYPE_PID_T
82  AC_TYPE_SIZE_T
83  
84 -AC_CHECK_MEMBER(struct tm.tm_gmtoff,AC_DEFINE([HAVE_STRUCT_TM_GMTOFF],[1],[gmtoff in struct tm]),,[#include <time.h>])
85 +AC_CHECK_MEMBER(struct tm.tm_gmtoff,[AC_DEFINE([HAVE_STRUCT_TM_GMTOFF],[1],[gmtoff in struct tm])],,[#include <time.h>])
86  AC_CHECK_TYPES(struct sockaddr_storage,,,[#include <sys/socket.h>])
87  AC_CHECK_TYPES(socklen_t,,,[#include <sys/types.h>
88  #include <sys/socket.h>])
89 @@ -339,6 +339,22 @@
90      AC_DEFINE([HAVE_SQLITE3], [1], [libsqlite3])
91      AC_DEFINE([HAVE_SQLITE3_H], [1], [sqlite3.h])
92   ])
93 +
94 + AC_MSG_CHECKING(for locks in mod_webdav)
95 + AC_ARG_WITH(webdav-locks, AC_HELP_STRING([--with-webdav-locks],[locks in mod_webdav]),
96 + [WITH_WEBDAV_LOCKS=$withval],[WITH_WEBDAV_LOCKS=no])
97 + AC_MSG_RESULT([$WITH_WEBDAV_LOCKS])
98 +
99 + if test "$WITH_WEBDAV_LOCKS" != "no"; then
100 +   AC_CHECK_LIB(uuid, uuid_unparse, [
101 +         AC_CHECK_HEADERS([uuid/uuid.h],[
102 +                 UUID_LIB=-luuid
103 +                 AC_DEFINE([HAVE_UUID], [1], [libuuid])
104 +                AC_DEFINE([HAVE_UUID_H], [1], [uuid/uuid.h is available])
105 +         ])
106 + ])
107 +
108 + fi
109  fi
110  
111  dnl Check for gdbm
112 @@ -440,7 +456,7 @@
113  esac
114  
115  AC_CHECK_FUNCS([dup2 getcwd inet_ntoa inet_ntop memset mmap munmap strchr \
116 -                 strdup strerror strstr strtol sendfile  getopt socket \
117 +                 strdup strerror strstr strtol sendfile  getopt socket lstat \
118                   gethostbyname poll sigtimedwait epoll_ctl getrlimit chroot \
119                   getuid select signal pathconf madvise posix_fadvise posix_madvise \
120                   writev sigaction sendfile64 send_file kqueue port_create localtime_r])
121 @@ -538,7 +554,7 @@
122  AC_OUTPUT
123  
124  
125 -do_build="mod_cgi mod_fastcgi 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" 
126 +do_build="mod_cgi mod_fastcgi 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" 
127  
128  plugins="mod_rewrite mod_redirect mod_ssi mod_trigger_b4_dl"
129  features="regex-conditionals"
130 @@ -642,6 +658,14 @@
131         disable_feature="$disable_feature $features"
132  fi
133  
134 +features="webdav-locks"
135 +if test "x$UUID_LIB" \!= x; then
136 +       enable_feature="$enable_feature $features"
137 +else
138 +       disable_feature="$disable_feature $features"
139 +fi
140 +
141 +
142  ## output
143  
144  $ECHO
145 --- lighttpd-1.4.11/cygwin/Makefile.in  2006-03-07 14:20:57.000000000 +0200
146 +++ lighttpd-1.4.12/cygwin/Makefile.in  2006-07-11 21:48:12.000000000 +0300
147 @@ -1,4 +1,4 @@
148 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
149 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
150  # @configure_input@
151  
152  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
153 @@ -43,7 +43,7 @@
154  am__aclocal_m4_deps = $(top_srcdir)/configure.in
155  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
156         $(ACLOCAL_M4)
157 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
158 +mkinstalldirs = $(install_sh) -d
159  CONFIG_HEADER = $(top_builddir)/config.h
160  CONFIG_CLEAN_FILES = lighttpd.README
161  SOURCES =
162 @@ -101,7 +101,6 @@
163  LIBTOOL = @LIBTOOL@
164  LN_S = @LN_S@
165  LTLIBOBJS = @LTLIBOBJS@
166 -LUACONFIG = @LUACONFIG@
167  LUA_CFLAGS = @LUA_CFLAGS@
168  LUA_LIBS = @LUA_LIBS@
169  MAINT = @MAINT@
170 @@ -144,6 +143,7 @@
171  ac_ct_F77 = @ac_ct_F77@
172  ac_ct_RANLIB = @ac_ct_RANLIB@
173  ac_ct_STRIP = @ac_ct_STRIP@
174 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
175  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
176  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
177  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
178 --- lighttpd-1.4.11/cygwin/lighttpd.README      2006-03-07 14:22:19.000000000 +0200
179 +++ lighttpd-1.4.12/cygwin/lighttpd.README      2006-07-11 22:08:04.000000000 +0300
180 @@ -1,114 +1,114 @@
181 -lighttpd\r
182 -------------------------------------------\r
183 -A fast, secure and flexible webserver\r
184 -\r
185 -Runtime requirements:\r
186 -  cygwin-1.5.10 or newer\r
187 -  crypt-1.1 or newer\r
188 -  libbz2_1-1.0.2 or newer\r
189 -  libpcre0-4.5 or newer\r
190 -  openssl-0.9.7d or newer\r
191 -  zlib-1.2.1 or newer\r
192 -\r
193 -Build requirements:\r
194 -  cygwin-1.5.10 or newer\r
195 -  gcc-3.3.1-3 or newer\r
196 -  binutils-20030901-1 or newer\r
197 -  crypt\r
198 -  openssl-devel\r
199 -  openssl\r
200 -  openldap\r
201 -  openldap-devel\r
202 -  zlib\r
203 -  bzip2\r
204 -\r
205 -Canonical homepage:\r
206 -  http://jan.kneschke.de/projects/lighttpd/\r
207 -\r
208 -Canonical download:\r
209 -  http://jan.kneschke.de/projects/lighttpd/download\r
210 -\r
211 -------------------------------------\r
212 -\r
213 -Build instructions:\r
214 -  unpack lighttpd-1.4.11-<REL>-src.tar.bz2\r
215 -    if you use setup to install this src package, it will be\r
216 -        unpacked under /usr/src automatically\r
217 -  cd /usr/src\r
218 -  ./lighttpd-1.4.11-<REL>.sh all\r
219 -\r
220 -This will create:\r
221 -  /usr/src/lighttpd-1.4.11-<REL>.tar.bz2\r
222 -  /usr/src/lighttpd-1.4.11-<REL>-src.tar.bz2\r
223 -\r
224 -Or use './lighttpd-1.4.11-<REL>.sh prep' to get a patched source directory\r
225 -\r
226 --------------------------------------------\r
227 -\r
228 -Files included in the binary distribution:\r
229 -\r
230 -  /etc/lighttpd/lighttpd.conf.default\r
231 -  /usr/lib/cyglightcomp.dll\r
232 -  /usr/lib/lighttpd/mod_access.dll\r
233 -  /usr/lib/lighttpd/mod_accesslog.dll\r
234 -  /usr/lib/lighttpd/mod_auth.dll\r
235 -  /usr/lib/lighttpd/mod_cgi.dll\r
236 -  /usr/lib/lighttpd/mod_compress.dll\r
237 -  /usr/lib/lighttpd/mod_evhost.dll\r
238 -  /usr/lib/lighttpd/mod_expire.dll\r
239 -  /usr/lib/lighttpd/mod_fastcgi.dll\r
240 -  /usr/lib/lighttpd/mod_httptls.dll\r
241 -  /usr/lib/lighttpd/mod_maps.dll\r
242 -  /usr/lib/lighttpd/mod_proxy.dll\r
243 -  /usr/lib/lighttpd/mod_redirect.dll\r
244 -  /usr/lib/lighttpd/mod_rewrite.dll\r
245 -  /usr/lib/lighttpd/mod_rrdtool.dll\r
246 -  /usr/lib/lighttpd/mod_secdownload.dll\r
247 -  /usr/lib/lighttpd/mod_simple_vhost.dll\r
248 -  /usr/lib/lighttpd/mod_ssi.dll\r
249 -  /usr/lib/lighttpd/mod_status.dll\r
250 -  /usr/lib/lighttpd/mod_usertrack.dll\r
251 -  /usr/sbin/lighttpd.exe\r
252 -  /usr/share/doc/Cygwin/lighttpd-1.3.0.README\r
253 -  /usr/share/doc/lighttpd-1.3.0/accesslog.txt\r
254 -  /usr/share/doc/lighttpd-1.3.0/authentification.txt\r
255 -  /usr/share/doc/lighttpd-1.3.0/AUTHORS\r
256 -  /usr/share/doc/lighttpd-1.3.0/cgi.txt\r
257 -  /usr/share/doc/lighttpd-1.3.0/ChangeLog\r
258 -  /usr/share/doc/lighttpd-1.3.0/compress.txt\r
259 -  /usr/share/doc/lighttpd-1.3.0/configuration.txt\r
260 -  /usr/share/doc/lighttpd-1.3.0/COPYING\r
261 -  /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt\r
262 -  /usr/share/doc/lighttpd-1.3.0/fastcgi.txt\r
263 -  /usr/share/doc/lighttpd-1.3.0/features.txt\r
264 -  /usr/share/doc/lighttpd-1.3.0/INSTALL\r
265 -  /usr/share/doc/lighttpd-1.3.0/NEWS\r
266 -  /usr/share/doc/lighttpd-1.3.0/performance.txt\r
267 -  /usr/share/doc/lighttpd-1.3.0/plugins.txt\r
268 -  /usr/share/doc/lighttpd-1.3.0/proxy.txt\r
269 -  /usr/share/doc/lighttpd-1.3.0/README\r
270 -  /usr/share/doc/lighttpd-1.3.0/redirect.txt\r
271 -  /usr/share/doc/lighttpd-1.3.0/rewrite.txt\r
272 -  /usr/share/doc/lighttpd-1.3.0/rrdtool.txt\r
273 -  /usr/share/doc/lighttpd-1.3.0/secdownload.txt\r
274 -  /usr/share/doc/lighttpd-1.3.0/security.txt\r
275 -  /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt\r
276 -  /usr/share/doc/lighttpd-1.3.0/skeleton.txt\r
277 -  /usr/share/doc/lighttpd-1.3.0/ssi.txt\r
278 -  /usr/share/doc/lighttpd-1.3.0/state.txt\r
279 -  /usr/share/man/man1/lighttpd.1.gz\r
280 -\r
281 -------------------\r
282 -\r
283 -Port Notes:\r
284 -\r
285 -----------  lighttpd-1.3.1-1 -----------\r
286 -\r
287 -Updated to 1.3.1\r
288 -\r
289 -----------  lighttpd-1.3.0-1 -----------\r
290 -Initial release\r
291 -\r
292 -Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>\r
293 -Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>\r
294 -\r
295 +lighttpd
296 +------------------------------------------
297 +A fast, secure and flexible webserver
298 +
299 +Runtime requirements:
300 +  cygwin-1.5.10 or newer
301 +  crypt-1.1 or newer
302 +  libbz2_1-1.0.2 or newer
303 +  libpcre0-4.5 or newer
304 +  openssl-0.9.7d or newer
305 +  zlib-1.2.1 or newer
306 +
307 +Build requirements:
308 +  cygwin-1.5.10 or newer
309 +  gcc-3.3.1-3 or newer
310 +  binutils-20030901-1 or newer
311 +  crypt
312 +  openssl-devel
313 +  openssl
314 +  openldap
315 +  openldap-devel
316 +  zlib
317 +  bzip2
318 +
319 +Canonical homepage:
320 +  http://jan.kneschke.de/projects/lighttpd/
321 +
322 +Canonical download:
323 +  http://jan.kneschke.de/projects/lighttpd/download
324 +
325 +------------------------------------
326 +
327 +Build instructions:
328 +  unpack lighttpd-1.4.12-<REL>-src.tar.bz2
329 +    if you use setup to install this src package, it will be
330 +        unpacked under /usr/src automatically
331 +  cd /usr/src
332 +  ./lighttpd-1.4.12-<REL>.sh all
333 +
334 +This will create:
335 +  /usr/src/lighttpd-1.4.12-<REL>.tar.bz2
336 +  /usr/src/lighttpd-1.4.12-<REL>-src.tar.bz2
337 +
338 +Or use './lighttpd-1.4.12-<REL>.sh prep' to get a patched source directory
339 +
340 +-------------------------------------------
341 +
342 +Files included in the binary distribution:
343 +
344 +  /etc/lighttpd/lighttpd.conf.default
345 +  /usr/lib/cyglightcomp.dll
346 +  /usr/lib/lighttpd/mod_access.dll
347 +  /usr/lib/lighttpd/mod_accesslog.dll
348 +  /usr/lib/lighttpd/mod_auth.dll
349 +  /usr/lib/lighttpd/mod_cgi.dll
350 +  /usr/lib/lighttpd/mod_compress.dll
351 +  /usr/lib/lighttpd/mod_evhost.dll
352 +  /usr/lib/lighttpd/mod_expire.dll
353 +  /usr/lib/lighttpd/mod_fastcgi.dll
354 +  /usr/lib/lighttpd/mod_httptls.dll
355 +  /usr/lib/lighttpd/mod_maps.dll
356 +  /usr/lib/lighttpd/mod_proxy.dll
357 +  /usr/lib/lighttpd/mod_redirect.dll
358 +  /usr/lib/lighttpd/mod_rewrite.dll
359 +  /usr/lib/lighttpd/mod_rrdtool.dll
360 +  /usr/lib/lighttpd/mod_secdownload.dll
361 +  /usr/lib/lighttpd/mod_simple_vhost.dll
362 +  /usr/lib/lighttpd/mod_ssi.dll
363 +  /usr/lib/lighttpd/mod_status.dll
364 +  /usr/lib/lighttpd/mod_usertrack.dll
365 +  /usr/sbin/lighttpd.exe
366 +  /usr/share/doc/Cygwin/lighttpd-1.3.0.README
367 +  /usr/share/doc/lighttpd-1.3.0/accesslog.txt
368 +  /usr/share/doc/lighttpd-1.3.0/authentification.txt
369 +  /usr/share/doc/lighttpd-1.3.0/AUTHORS
370 +  /usr/share/doc/lighttpd-1.3.0/cgi.txt
371 +  /usr/share/doc/lighttpd-1.3.0/ChangeLog
372 +  /usr/share/doc/lighttpd-1.3.0/compress.txt
373 +  /usr/share/doc/lighttpd-1.3.0/configuration.txt
374 +  /usr/share/doc/lighttpd-1.3.0/COPYING
375 +  /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
376 +  /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
377 +  /usr/share/doc/lighttpd-1.3.0/features.txt
378 +  /usr/share/doc/lighttpd-1.3.0/INSTALL
379 +  /usr/share/doc/lighttpd-1.3.0/NEWS
380 +  /usr/share/doc/lighttpd-1.3.0/performance.txt
381 +  /usr/share/doc/lighttpd-1.3.0/plugins.txt
382 +  /usr/share/doc/lighttpd-1.3.0/proxy.txt
383 +  /usr/share/doc/lighttpd-1.3.0/README
384 +  /usr/share/doc/lighttpd-1.3.0/redirect.txt
385 +  /usr/share/doc/lighttpd-1.3.0/rewrite.txt
386 +  /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
387 +  /usr/share/doc/lighttpd-1.3.0/secdownload.txt
388 +  /usr/share/doc/lighttpd-1.3.0/security.txt
389 +  /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
390 +  /usr/share/doc/lighttpd-1.3.0/skeleton.txt
391 +  /usr/share/doc/lighttpd-1.3.0/ssi.txt
392 +  /usr/share/doc/lighttpd-1.3.0/state.txt
393 +  /usr/share/man/man1/lighttpd.1.gz
394 +
395 +------------------
396 +
397 +Port Notes:
398 +
399 +----------  lighttpd-1.3.1-1 -----------
400 +
401 +Updated to 1.3.1
402 +
403 +----------  lighttpd-1.3.0-1 -----------
404 +Initial release
405 +
406 +Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
407 +Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
408 +
409 --- lighttpd-1.4.11/cygwin/lighttpd.README.in   2005-08-11 01:26:59.000000000 +0300
410 +++ lighttpd-1.4.12/cygwin/lighttpd.README.in   2006-07-11 22:07:53.000000000 +0300
411 @@ -1,114 +1,114 @@
412 -lighttpd\r
413 -------------------------------------------\r
414 -A fast, secure and flexible webserver\r
415 -\r
416 -Runtime requirements:\r
417 -  cygwin-1.5.10 or newer\r
418 -  crypt-1.1 or newer\r
419 -  libbz2_1-1.0.2 or newer\r
420 -  libpcre0-4.5 or newer\r
421 -  openssl-0.9.7d or newer\r
422 -  zlib-1.2.1 or newer\r
423 -\r
424 -Build requirements:\r
425 -  cygwin-1.5.10 or newer\r
426 -  gcc-3.3.1-3 or newer\r
427 -  binutils-20030901-1 or newer\r
428 -  crypt\r
429 -  openssl-devel\r
430 -  openssl\r
431 -  openldap\r
432 -  openldap-devel\r
433 -  zlib\r
434 -  bzip2\r
435 -\r
436 -Canonical homepage:\r
437 -  http://jan.kneschke.de/projects/lighttpd/\r
438 -\r
439 -Canonical download:\r
440 -  http://jan.kneschke.de/projects/lighttpd/download\r
441 -\r
442 -------------------------------------\r
443 -\r
444 -Build instructions:\r
445 -  unpack lighttpd-@VERSION@-<REL>-src.tar.bz2\r
446 -    if you use setup to install this src package, it will be\r
447 -        unpacked under /usr/src automatically\r
448 -  cd /usr/src\r
449 -  ./lighttpd-@VERSION@-<REL>.sh all\r
450 -\r
451 -This will create:\r
452 -  /usr/src/lighttpd-@VERSION@-<REL>.tar.bz2\r
453 -  /usr/src/lighttpd-@VERSION@-<REL>-src.tar.bz2\r
454 -\r
455 -Or use './lighttpd-@VERSION@-<REL>.sh prep' to get a patched source directory\r
456 -\r
457 --------------------------------------------\r
458 -\r
459 -Files included in the binary distribution:\r
460 -\r
461 -  /etc/lighttpd/lighttpd.conf.default\r
462 -  /usr/lib/cyglightcomp.dll\r
463 -  /usr/lib/lighttpd/mod_access.dll\r
464 -  /usr/lib/lighttpd/mod_accesslog.dll\r
465 -  /usr/lib/lighttpd/mod_auth.dll\r
466 -  /usr/lib/lighttpd/mod_cgi.dll\r
467 -  /usr/lib/lighttpd/mod_compress.dll\r
468 -  /usr/lib/lighttpd/mod_evhost.dll\r
469 -  /usr/lib/lighttpd/mod_expire.dll\r
470 -  /usr/lib/lighttpd/mod_fastcgi.dll\r
471 -  /usr/lib/lighttpd/mod_httptls.dll\r
472 -  /usr/lib/lighttpd/mod_maps.dll\r
473 -  /usr/lib/lighttpd/mod_proxy.dll\r
474 -  /usr/lib/lighttpd/mod_redirect.dll\r
475 -  /usr/lib/lighttpd/mod_rewrite.dll\r
476 -  /usr/lib/lighttpd/mod_rrdtool.dll\r
477 -  /usr/lib/lighttpd/mod_secdownload.dll\r
478 -  /usr/lib/lighttpd/mod_simple_vhost.dll\r
479 -  /usr/lib/lighttpd/mod_ssi.dll\r
480 -  /usr/lib/lighttpd/mod_status.dll\r
481 -  /usr/lib/lighttpd/mod_usertrack.dll\r
482 -  /usr/sbin/lighttpd.exe\r
483 -  /usr/share/doc/Cygwin/lighttpd-1.3.0.README\r
484 -  /usr/share/doc/lighttpd-1.3.0/accesslog.txt\r
485 -  /usr/share/doc/lighttpd-1.3.0/authentification.txt\r
486 -  /usr/share/doc/lighttpd-1.3.0/AUTHORS\r
487 -  /usr/share/doc/lighttpd-1.3.0/cgi.txt\r
488 -  /usr/share/doc/lighttpd-1.3.0/ChangeLog\r
489 -  /usr/share/doc/lighttpd-1.3.0/compress.txt\r
490 -  /usr/share/doc/lighttpd-1.3.0/configuration.txt\r
491 -  /usr/share/doc/lighttpd-1.3.0/COPYING\r
492 -  /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt\r
493 -  /usr/share/doc/lighttpd-1.3.0/fastcgi.txt\r
494 -  /usr/share/doc/lighttpd-1.3.0/features.txt\r
495 -  /usr/share/doc/lighttpd-1.3.0/INSTALL\r
496 -  /usr/share/doc/lighttpd-1.3.0/NEWS\r
497 -  /usr/share/doc/lighttpd-1.3.0/performance.txt\r
498 -  /usr/share/doc/lighttpd-1.3.0/plugins.txt\r
499 -  /usr/share/doc/lighttpd-1.3.0/proxy.txt\r
500 -  /usr/share/doc/lighttpd-1.3.0/README\r
501 -  /usr/share/doc/lighttpd-1.3.0/redirect.txt\r
502 -  /usr/share/doc/lighttpd-1.3.0/rewrite.txt\r
503 -  /usr/share/doc/lighttpd-1.3.0/rrdtool.txt\r
504 -  /usr/share/doc/lighttpd-1.3.0/secdownload.txt\r
505 -  /usr/share/doc/lighttpd-1.3.0/security.txt\r
506 -  /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt\r
507 -  /usr/share/doc/lighttpd-1.3.0/skeleton.txt\r
508 -  /usr/share/doc/lighttpd-1.3.0/ssi.txt\r
509 -  /usr/share/doc/lighttpd-1.3.0/state.txt\r
510 -  /usr/share/man/man1/lighttpd.1.gz\r
511 -\r
512 -------------------\r
513 -\r
514 -Port Notes:\r
515 -\r
516 -----------  lighttpd-1.3.1-1 -----------\r
517 -\r
518 -Updated to 1.3.1\r
519 -\r
520 -----------  lighttpd-1.3.0-1 -----------\r
521 -Initial release\r
522 -\r
523 -Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>\r
524 -Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>\r
525 -\r
526 +lighttpd
527 +------------------------------------------
528 +A fast, secure and flexible webserver
529 +
530 +Runtime requirements:
531 +  cygwin-1.5.10 or newer
532 +  crypt-1.1 or newer
533 +  libbz2_1-1.0.2 or newer
534 +  libpcre0-4.5 or newer
535 +  openssl-0.9.7d or newer
536 +  zlib-1.2.1 or newer
537 +
538 +Build requirements:
539 +  cygwin-1.5.10 or newer
540 +  gcc-3.3.1-3 or newer
541 +  binutils-20030901-1 or newer
542 +  crypt
543 +  openssl-devel
544 +  openssl
545 +  openldap
546 +  openldap-devel
547 +  zlib
548 +  bzip2
549 +
550 +Canonical homepage:
551 +  http://jan.kneschke.de/projects/lighttpd/
552 +
553 +Canonical download:
554 +  http://jan.kneschke.de/projects/lighttpd/download
555 +
556 +------------------------------------
557 +
558 +Build instructions:
559 +  unpack lighttpd-@VERSION@-<REL>-src.tar.bz2
560 +    if you use setup to install this src package, it will be
561 +        unpacked under /usr/src automatically
562 +  cd /usr/src
563 +  ./lighttpd-@VERSION@-<REL>.sh all
564 +
565 +This will create:
566 +  /usr/src/lighttpd-@VERSION@-<REL>.tar.bz2
567 +  /usr/src/lighttpd-@VERSION@-<REL>-src.tar.bz2
568 +
569 +Or use './lighttpd-@VERSION@-<REL>.sh prep' to get a patched source directory
570 +
571 +-------------------------------------------
572 +
573 +Files included in the binary distribution:
574 +
575 +  /etc/lighttpd/lighttpd.conf.default
576 +  /usr/lib/cyglightcomp.dll
577 +  /usr/lib/lighttpd/mod_access.dll
578 +  /usr/lib/lighttpd/mod_accesslog.dll
579 +  /usr/lib/lighttpd/mod_auth.dll
580 +  /usr/lib/lighttpd/mod_cgi.dll
581 +  /usr/lib/lighttpd/mod_compress.dll
582 +  /usr/lib/lighttpd/mod_evhost.dll
583 +  /usr/lib/lighttpd/mod_expire.dll
584 +  /usr/lib/lighttpd/mod_fastcgi.dll
585 +  /usr/lib/lighttpd/mod_httptls.dll
586 +  /usr/lib/lighttpd/mod_maps.dll
587 +  /usr/lib/lighttpd/mod_proxy.dll
588 +  /usr/lib/lighttpd/mod_redirect.dll
589 +  /usr/lib/lighttpd/mod_rewrite.dll
590 +  /usr/lib/lighttpd/mod_rrdtool.dll
591 +  /usr/lib/lighttpd/mod_secdownload.dll
592 +  /usr/lib/lighttpd/mod_simple_vhost.dll
593 +  /usr/lib/lighttpd/mod_ssi.dll
594 +  /usr/lib/lighttpd/mod_status.dll
595 +  /usr/lib/lighttpd/mod_usertrack.dll
596 +  /usr/sbin/lighttpd.exe
597 +  /usr/share/doc/Cygwin/lighttpd-1.3.0.README
598 +  /usr/share/doc/lighttpd-1.3.0/accesslog.txt
599 +  /usr/share/doc/lighttpd-1.3.0/authentification.txt
600 +  /usr/share/doc/lighttpd-1.3.0/AUTHORS
601 +  /usr/share/doc/lighttpd-1.3.0/cgi.txt
602 +  /usr/share/doc/lighttpd-1.3.0/ChangeLog
603 +  /usr/share/doc/lighttpd-1.3.0/compress.txt
604 +  /usr/share/doc/lighttpd-1.3.0/configuration.txt
605 +  /usr/share/doc/lighttpd-1.3.0/COPYING
606 +  /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
607 +  /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
608 +  /usr/share/doc/lighttpd-1.3.0/features.txt
609 +  /usr/share/doc/lighttpd-1.3.0/INSTALL
610 +  /usr/share/doc/lighttpd-1.3.0/NEWS
611 +  /usr/share/doc/lighttpd-1.3.0/performance.txt
612 +  /usr/share/doc/lighttpd-1.3.0/plugins.txt
613 +  /usr/share/doc/lighttpd-1.3.0/proxy.txt
614 +  /usr/share/doc/lighttpd-1.3.0/README
615 +  /usr/share/doc/lighttpd-1.3.0/redirect.txt
616 +  /usr/share/doc/lighttpd-1.3.0/rewrite.txt
617 +  /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
618 +  /usr/share/doc/lighttpd-1.3.0/secdownload.txt
619 +  /usr/share/doc/lighttpd-1.3.0/security.txt
620 +  /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
621 +  /usr/share/doc/lighttpd-1.3.0/skeleton.txt
622 +  /usr/share/doc/lighttpd-1.3.0/ssi.txt
623 +  /usr/share/doc/lighttpd-1.3.0/state.txt
624 +  /usr/share/man/man1/lighttpd.1.gz
625 +
626 +------------------
627 +
628 +Port Notes:
629 +
630 +----------  lighttpd-1.3.1-1 -----------
631 +
632 +Updated to 1.3.1
633 +
634 +----------  lighttpd-1.3.0-1 -----------
635 +Initial release
636 +
637 +Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
638 +Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
639 +
640 --- lighttpd-1.4.11/doc/Makefile.in     2006-03-07 14:20:57.000000000 +0200
641 +++ lighttpd-1.4.12/doc/Makefile.in     2006-07-11 21:48:12.000000000 +0300
642 @@ -1,4 +1,4 @@
643 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
644 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
645  # @configure_input@
646  
647  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
648 @@ -43,7 +43,7 @@
649  am__aclocal_m4_deps = $(top_srcdir)/configure.in
650  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
651         $(ACLOCAL_M4)
652 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
653 +mkinstalldirs = $(install_sh) -d
654  CONFIG_HEADER = $(top_builddir)/config.h
655  CONFIG_CLEAN_FILES =
656  SOURCES =
657 @@ -105,7 +105,6 @@
658  LIBTOOL = @LIBTOOL@
659  LN_S = @LN_S@
660  LTLIBOBJS = @LTLIBOBJS@
661 -LUACONFIG = @LUACONFIG@
662  LUA_CFLAGS = @LUA_CFLAGS@
663  LUA_LIBS = @LUA_LIBS@
664  MAINT = @MAINT@
665 @@ -148,6 +147,7 @@
666  ac_ct_F77 = @ac_ct_F77@
667  ac_ct_RANLIB = @ac_ct_RANLIB@
668  ac_ct_STRIP = @ac_ct_STRIP@
669 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
670  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
671  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
672  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
673 --- lighttpd-1.4.11/doc/authentication.txt      2006-01-12 20:34:26.000000000 +0200
674 +++ lighttpd-1.4.12/doc/authentication.txt      2006-07-11 22:07:54.000000000 +0300
675 @@ -7,8 +7,8 @@
676  ----------------
677  
678  :Author: Jan Kneschke
679 -:Date: $Date$
680 -:Revision: $Revision$
681 +:Date: $Date$
682 +:Revision: $Revision$
683  
684  :abstract:
685    The auth module provides ...
686 --- lighttpd-1.4.11/doc/compress.txt    2005-08-11 01:26:16.000000000 +0300
687 +++ lighttpd-1.4.12/doc/compress.txt    2006-07-11 22:07:54.000000000 +0300
688 @@ -22,12 +22,38 @@
689  ===========
690  
691  Output compression reduces the network load and can improve the overall
692 -throughput of the webserver. 
693 +throughput of the webserver. All major http-clients support compression by
694 +announcing it in the Accept-Encoding header. This is used to negotiate the 
695 +most suitable compression method. We support deflate, gzip and bzip2.
696  
697 -Only static content is supported up to now.
698 +deflate (RFC1950, RFC1951) and gzip (RFC1952) depend on zlib while bzip2 
699 +depends on libbzip2. bzip2 is only supported by lynx and some other console
700 +text-browsers.
701  
702 -The server negotiates automaticly which compression method is used.
703 -Supported are gzip, deflate, bzip.
704 +Currently we limit to compression support to static files.
705 +
706 +Caching
707 +-------
708 +
709 +mod_compress can stored compressed files on disk to optimized the compression
710 +on a second request away. As soon as compress.cache-dir is set the files are
711 +compressed. 
712 +
713 +The names of the cache files are made of the filename, the compression method
714 +and the etag associated to the file.
715 +
716 +Cleaning the cache is left to the user. A cron job deleting files older than
717 +10 days should do fine.
718 +
719 +Limitations
720 +-----------
721 +
722 +The module limits the compression of files to files larger than 128 Byte and
723 +smaller than 128 MByte.
724 +
725 +The lower limit is set as small files tend to become larger by compressing due
726 +to the compression headers, the upper limit is set to work sensable with
727 +memory and cpu-time.
728  
729  Options
730  =======
731 @@ -47,15 +73,28 @@
732    Default: not set, compress the file for every request
733  
734  compress.filetype
735 -  mimetypes where might get compressed
736 +  mimetypes which might get compressed
737    
738    e.g.: ::
739    
740      compress.filetype           = ("text/plain", "text/html")
741  
742 +  Keep in mind that compressed JavaScript and CSS files are broken in some
743 +  browsers.
744 +
745    Default: not set
746  
747 +compress.max-file-size 
748 +  maximum size of the original file to be compressed kBytes.
749 +
750 +  This is meant to protect the server against DoSing as compressing large
751 +  (let's say 1Gbyte) takes a lot of time and would delay the whole operation
752 +  of the server.
753  
754 +  There is a hard upper limit of 128Mbyte.
755 +
756 +  Default: unlimited (== hard-limit of 128MByte)
757 +  
758  Compressing Dynamic Content
759  ===========================
760  
761 --- lighttpd-1.4.11/doc/configuration.txt       2006-03-09 02:10:40.000000000 +0200
762 +++ lighttpd-1.4.12/doc/configuration.txt       2006-07-11 22:07:54.000000000 +0300
763 @@ -7,8 +7,8 @@
764  ------------
765  
766  :Author: Jan Kneschke
767 -:Date: $Date$
768 -:Revision: $Revision$
769 +:Date: $Date$
770 +:Revision: $Revision$
771  
772  :abstract:
773    the layout of the configuration file
774 @@ -511,3 +511,10 @@
775  
776  debug.log-request-handling
777    default: disabled 
778 +
779 +debug.log-condition-handling
780 +  default: disabled 
781 +
782 +debug.log-condition-cache-handling
783 +  for developers only
784 +  default: disabled 
785 --- lighttpd-1.4.11/doc/fastcgi.txt     2006-02-16 17:03:52.000000000 +0200
786 +++ lighttpd-1.4.12/doc/fastcgi.txt     2006-07-11 22:07:54.000000000 +0300
787 @@ -144,8 +144,8 @@
788                  PHP can extract PATH_INFO from it (default: disabled)
789    :"disable-time": time to wait before a disabled backend is checked
790                  again
791 -  :"allow-x-send-file": controls if X-LIGHTTPD-send-file headers
792 -                are allowed 
793 +  :"allow-x-send-file": controls if X-LIGHTTPD-send-file and X-Sendfile
794 +                headers are allowed 
795  
796    If bin-path is set:
797  
798 --- lighttpd-1.4.11/doc/lighttpd.conf   2006-03-04 14:41:12.000000000 +0200
799 +++ lighttpd-1.4.12/doc/lighttpd.conf   2006-07-11 22:07:54.000000000 +0300
800 @@ -172,10 +172,11 @@
801  #dir-listing.activate       = "enable"
802  
803  ## enable debugging
804 -#debug.log-request-header   = "enable"
805 -#debug.log-response-header  = "enable"
806 -#debug.log-request-handling = "enable"
807 -#debug.log-file-not-found   = "enable"
808 +#debug.log-request-header     = "enable"
809 +#debug.log-response-header    = "enable"
810 +#debug.log-request-handling   = "enable"
811 +#debug.log-file-not-found     = "enable"
812 +#debug.log-condition-handling = "enable"
813  
814  ### only root can use these options
815  #
816 --- lighttpd-1.4.11/doc/performance.txt 2006-02-02 13:01:08.000000000 +0200
817 +++ lighttpd-1.4.12/doc/performance.txt 2006-07-11 22:07:54.000000000 +0300
818 @@ -183,6 +183,8 @@
819  
820    server.stat-cache-engine = "fam"   # either fam, simple or disabled
821  
822 +See http://oss.sgi.com/projects/fam/faq.html for information about FAM.
823 +See http://www.gnome.org/~veillard/gamin/overview.html for information about gamin.
824  
825  Platform-Specific Notes
826  =======================
827 --- lighttpd-1.4.11/doc/secdownload.txt 2005-12-20 15:58:58.000000000 +0200
828 +++ lighttpd-1.4.12/doc/secdownload.txt 2006-07-11 22:07:54.000000000 +0300
829 @@ -118,7 +118,7 @@
830    $secret = "verysecret";
831    $uri_prefix = "/dl/";
832    
833 -  # filename
834 +  # filename, make sure it's started with a "/" or you'll get 404 in the browser
835    $f = "/secret-file.txt";
836    
837    # current timestamp
838 --- lighttpd-1.4.11/lighttpd.spec       2006-03-07 14:22:18.000000000 +0200
839 +++ lighttpd-1.4.12/lighttpd.spec       2006-07-11 22:07:58.000000000 +0300
840 @@ -1,6 +1,6 @@
841  Summary: A fast webserver with minimal memory-footprint (lighttpd)
842  Name: lighttpd
843 -Version: 1.4.11
844 +Version: 1.4.12
845  Release: 1
846  Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-%version.tar.gz
847  Packager: Jan Kneschke <jan@kneschke.de>
848 --- lighttpd-1.4.11/openwrt/Makefile.in 2006-03-07 14:20:58.000000000 +0200
849 +++ lighttpd-1.4.12/openwrt/Makefile.in 2006-07-11 21:48:12.000000000 +0300
850 @@ -1,4 +1,4 @@
851 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
852 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
853  # @configure_input@
854  
855  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
856 @@ -43,7 +43,7 @@
857  am__aclocal_m4_deps = $(top_srcdir)/configure.in
858  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
859         $(ACLOCAL_M4)
860 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
861 +mkinstalldirs = $(install_sh) -d
862  CONFIG_HEADER = $(top_builddir)/config.h
863  CONFIG_CLEAN_FILES = control lighttpd.mk
864  SOURCES =
865 @@ -101,7 +101,6 @@
866  LIBTOOL = @LIBTOOL@
867  LN_S = @LN_S@
868  LTLIBOBJS = @LTLIBOBJS@
869 -LUACONFIG = @LUACONFIG@
870  LUA_CFLAGS = @LUA_CFLAGS@
871  LUA_LIBS = @LUA_LIBS@
872  MAINT = @MAINT@
873 @@ -144,6 +143,7 @@
874  ac_ct_F77 = @ac_ct_F77@
875  ac_ct_RANLIB = @ac_ct_RANLIB@
876  ac_ct_STRIP = @ac_ct_STRIP@
877 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
878  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
879  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
880  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
881 --- lighttpd-1.4.11/openwrt/control     2006-03-07 14:22:19.000000000 +0200
882 +++ lighttpd-1.4.12/openwrt/control     2006-07-11 22:08:05.000000000 +0300
883 @@ -1,8 +1,8 @@
884  Package: lighttpd
885 -Version: 1.4.11
886 +Version: 1.4.12
887  Architecture: mipsel
888  Maintainer: Jan Kneschke <jan@kneschke.de>
889 -Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-1.4.11.tar.gz
890 +Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-1.4.12.tar.gz
891  Section: net
892  Priority: optional
893  Depends:
894 --- lighttpd-1.4.11/openwrt/lighttpd.mk 2006-03-07 14:22:19.000000000 +0200
895 +++ lighttpd-1.4.12/openwrt/lighttpd.mk 2006-07-11 22:08:05.000000000 +0300
896 @@ -10,7 +10,7 @@
897  
898  #  For this example we'll use a fairly simple package that compiles easily
899  #  and has sources available for download at sourceforge
900 -LIGHTTPD=lighttpd-1.4.11
901 +LIGHTTPD=lighttpd-1.4.12
902  LIGHTTPD_TARGET=.built
903  LIGHTTPD_DIR=$(BUILD_DIR)/$(LIGHTTPD)
904  LIGHTTPD_IPK=$(BUILD_DIR)/$(LIGHTTPD)_mipsel.ipk
905 --- lighttpd-1.4.11/src/Makefile.am     2006-03-07 14:20:20.000000000 +0200
906 +++ lighttpd-1.4.12/src/Makefile.am     2006-07-11 22:07:52.000000000 +0300
907 @@ -82,9 +82,9 @@
908  
909  lib_LTLIBRARIES += mod_webdav.la
910  mod_webdav_la_SOURCES = mod_webdav.c
911 -mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
912 +mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS) 
913  mod_webdav_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
914 -mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS)
915 +mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS) $(UUID_LIB)
916  
917  lib_LTLIBRARIES += mod_cml.la
918  mod_cml_la_SOURCES = mod_cml.c mod_cml_lua.c mod_cml_funcs.c
919 --- lighttpd-1.4.11/src/Makefile.in     2006-03-07 14:21:02.000000000 +0200
920 +++ lighttpd-1.4.12/src/Makefile.in     2006-07-11 22:04:27.000000000 +0300
921 @@ -1,4 +1,4 @@
922 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
923 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
924  # @configure_input@
925  
926  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
927 @@ -16,8 +16,6 @@
928  
929  
930  
931 -SOURCES = $(liblightcomp_la_SOURCES) $(mod_access_la_SOURCES) $(mod_accesslog_la_SOURCES) $(mod_alias_la_SOURCES) $(mod_auth_la_SOURCES) $(mod_cgi_la_SOURCES) $(mod_cml_la_SOURCES) $(mod_compress_la_SOURCES) $(mod_dirlisting_la_SOURCES) $(mod_evasive_la_SOURCES) $(mod_evhost_la_SOURCES) $(mod_expire_la_SOURCES) $(mod_fastcgi_la_SOURCES) $(mod_flv_streaming_la_SOURCES) $(mod_indexfile_la_SOURCES) $(mod_mysql_vhost_la_SOURCES) $(mod_proxy_la_SOURCES) $(mod_redirect_la_SOURCES) $(mod_rewrite_la_SOURCES) $(mod_rrdtool_la_SOURCES) $(mod_scgi_la_SOURCES) $(mod_secdownload_la_SOURCES) $(mod_setenv_la_SOURCES) $(mod_simple_vhost_la_SOURCES) $(mod_ssi_la_SOURCES) $(mod_staticfile_la_SOURCES) $(mod_status_la_SOURCES) $(mod_trigger_b4_dl_la_SOURCES) $(mod_userdir_la_SOURCES) $(mod_usertrack_la_SOURCES) $(mod_webdav_la_SOURCES) $(lemon_SOURCES) $(lighttpd_SOURCES) $(proc_open_SOURCES) $(spawn_fcgi_SOURCES)
932 -
933  srcdir = @srcdir@
934  top_srcdir = @top_srcdir@
935  VPATH = @srcdir@
936 @@ -57,7 +55,7 @@
937  am__aclocal_m4_deps = $(top_srcdir)/configure.in
938  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
939         $(ACLOCAL_M4)
940 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
941 +mkinstalldirs = $(install_sh) -d
942  CONFIG_HEADER = $(top_builddir)/config.h
943  CONFIG_CLEAN_FILES =
944  am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
945 @@ -84,7 +82,8 @@
946         inet_ntop_cache.c crc32.c connections-glue.c configfile-glue.c \
947         http-header-glue.c network_write.c network_linux_sendfile.c \
948         network_freebsd_sendfile.c network_writev.c \
949 -       network_solaris_sendfilev.c network_openssl.c splaytree.c
950 +       network_solaris_sendfilev.c network_openssl.c splaytree.c \
951 +       http_resp.c http_resp_parser.c
952  am__objects_1 = liblightcomp_la-buffer.lo liblightcomp_la-log.lo \
953         liblightcomp_la-keyvalue.lo liblightcomp_la-chunk.lo \
954         liblightcomp_la-http_chunk.lo liblightcomp_la-stream.lo \
955 @@ -111,7 +110,8 @@
956         liblightcomp_la-network_writev.lo \
957         liblightcomp_la-network_solaris_sendfilev.lo \
958         liblightcomp_la-network_openssl.lo \
959 -       liblightcomp_la-splaytree.lo
960 +       liblightcomp_la-splaytree.lo liblightcomp_la-http_resp.lo \
961 +       liblightcomp_la-http_resp_parser.lo
962  @NO_RDYNAMIC_TRUE@am_liblightcomp_la_OBJECTS = $(am__objects_1)
963  liblightcomp_la_OBJECTS = $(am_liblightcomp_la_OBJECTS)
964  @NO_RDYNAMIC_TRUE@am_liblightcomp_la_rpath = -rpath $(libdir)
965 @@ -193,6 +193,9 @@
966  mod_simple_vhost_la_DEPENDENCIES = $(am__DEPENDENCIES_2)
967  am_mod_simple_vhost_la_OBJECTS = mod_simple_vhost.lo
968  mod_simple_vhost_la_OBJECTS = $(am_mod_simple_vhost_la_OBJECTS)
969 +mod_sql_vhost_core_la_DEPENDENCIES = $(am__DEPENDENCIES_2)
970 +am_mod_sql_vhost_core_la_OBJECTS = mod_sql_vhost_core.lo
971 +mod_sql_vhost_core_la_OBJECTS = $(am_mod_sql_vhost_core_la_OBJECTS)
972  mod_ssi_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
973  am_mod_ssi_la_OBJECTS = mod_ssi_exprparser.lo mod_ssi_expr.lo \
974         mod_ssi.lo
975 @@ -236,7 +239,8 @@
976         connections-glue.c configfile-glue.c http-header-glue.c \
977         network_write.c network_linux_sendfile.c \
978         network_freebsd_sendfile.c network_writev.c \
979 -       network_solaris_sendfilev.c network_openssl.c splaytree.c
980 +       network_solaris_sendfilev.c network_openssl.c splaytree.c \
981 +       http_resp.c http_resp_parser.c
982  am__objects_2 = buffer.$(OBJEXT) log.$(OBJEXT) keyvalue.$(OBJEXT) \
983         chunk.$(OBJEXT) http_chunk.$(OBJEXT) stream.$(OBJEXT) \
984         fdevent.$(OBJEXT) stat_cache.$(OBJEXT) plugin.$(OBJEXT) \
985 @@ -254,7 +258,8 @@
986         network_linux_sendfile.$(OBJEXT) \
987         network_freebsd_sendfile.$(OBJEXT) network_writev.$(OBJEXT) \
988         network_solaris_sendfilev.$(OBJEXT) network_openssl.$(OBJEXT) \
989 -       splaytree.$(OBJEXT)
990 +       splaytree.$(OBJEXT) http_resp.$(OBJEXT) \
991 +       http_resp_parser.$(OBJEXT)
992  @NO_RDYNAMIC_FALSE@am__objects_3 = $(am__objects_2)
993  am__objects_4 = server.$(OBJEXT) response.$(OBJEXT) \
994         connections.$(OBJEXT) network.$(OBJEXT) configfile.$(OBJEXT) \
995 @@ -282,8 +287,8 @@
996         $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
997         $(AM_CFLAGS) $(CFLAGS)
998  CCLD = $(CC)
999 -LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
1000 -       $(AM_LDFLAGS) $(LDFLAGS) -o $@
1001 +LINK = $(LIBTOOL) --tag=CC --mode=link "$(CCLD)" $(AM_CFLAGS) \
1002 +       $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
1003  SOURCES = $(liblightcomp_la_SOURCES) $(mod_access_la_SOURCES) \
1004         $(mod_accesslog_la_SOURCES) $(mod_alias_la_SOURCES) \
1005         $(mod_auth_la_SOURCES) $(mod_cgi_la_SOURCES) \
1006 @@ -296,11 +301,12 @@
1007         $(mod_rewrite_la_SOURCES) $(mod_rrdtool_la_SOURCES) \
1008         $(mod_scgi_la_SOURCES) $(mod_secdownload_la_SOURCES) \
1009         $(mod_setenv_la_SOURCES) $(mod_simple_vhost_la_SOURCES) \
1010 -       $(mod_ssi_la_SOURCES) $(mod_staticfile_la_SOURCES) \
1011 -       $(mod_status_la_SOURCES) $(mod_trigger_b4_dl_la_SOURCES) \
1012 -       $(mod_userdir_la_SOURCES) $(mod_usertrack_la_SOURCES) \
1013 -       $(mod_webdav_la_SOURCES) $(lemon_SOURCES) $(lighttpd_SOURCES) \
1014 -       $(proc_open_SOURCES) $(spawn_fcgi_SOURCES)
1015 +       $(mod_sql_vhost_core_la_SOURCES) $(mod_ssi_la_SOURCES) \
1016 +       $(mod_staticfile_la_SOURCES) $(mod_status_la_SOURCES) \
1017 +       $(mod_trigger_b4_dl_la_SOURCES) $(mod_userdir_la_SOURCES) \
1018 +       $(mod_usertrack_la_SOURCES) $(mod_webdav_la_SOURCES) \
1019 +       $(lemon_SOURCES) $(lighttpd_SOURCES) $(proc_open_SOURCES) \
1020 +       $(spawn_fcgi_SOURCES)
1021  DIST_SOURCES = $(am__liblightcomp_la_SOURCES_DIST) \
1022         $(mod_access_la_SOURCES) $(mod_accesslog_la_SOURCES) \
1023         $(mod_alias_la_SOURCES) $(mod_auth_la_SOURCES) \
1024 @@ -313,7 +319,8 @@
1025         $(mod_redirect_la_SOURCES) $(mod_rewrite_la_SOURCES) \
1026         $(mod_rrdtool_la_SOURCES) $(mod_scgi_la_SOURCES) \
1027         $(mod_secdownload_la_SOURCES) $(mod_setenv_la_SOURCES) \
1028 -       $(mod_simple_vhost_la_SOURCES) $(mod_ssi_la_SOURCES) \
1029 +       $(mod_simple_vhost_la_SOURCES) \
1030 +       $(mod_sql_vhost_core_la_SOURCES) $(mod_ssi_la_SOURCES) \
1031         $(mod_staticfile_la_SOURCES) $(mod_status_la_SOURCES) \
1032         $(mod_trigger_b4_dl_la_SOURCES) $(mod_userdir_la_SOURCES) \
1033         $(mod_usertrack_la_SOURCES) $(mod_webdav_la_SOURCES) \
1034 @@ -375,7 +382,6 @@
1035  LIBTOOL = @LIBTOOL@
1036  LN_S = @LN_S@
1037  LTLIBOBJS = @LTLIBOBJS@
1038 -LUACONFIG = @LUACONFIG@
1039  LUA_CFLAGS = @LUA_CFLAGS@
1040  LUA_LIBS = @LUA_LIBS@
1041  MAINT = @MAINT@
1042 @@ -418,6 +424,7 @@
1043  ac_ct_F77 = @ac_ct_F77@
1044  ac_ct_RANLIB = @ac_ct_RANLIB@
1045  ac_ct_STRIP = @ac_ct_STRIP@
1046 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
1047  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
1048  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
1049  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
1050 @@ -479,7 +486,7 @@
1051        network_write.c network_linux_sendfile.c \
1052        network_freebsd_sendfile.c network_writev.c \
1053        network_solaris_sendfilev.c network_openssl.c \
1054 -      splaytree.c 
1055 +      splaytree.c http_resp.c http_resp_parser.c 
1056  
1057  src = server.c response.c connections.c network.c configfile.c \
1058         configparser.c request.c proc_open.c $(am__append_2)
1059 @@ -491,10 +498,11 @@
1060  #mod_httptls_la_LIBADD = $(common_libadd)
1061  lib_LTLIBRARIES = $(am__append_1) mod_flv_streaming.la mod_evasive.la \
1062         mod_webdav.la mod_cml.la mod_trigger_b4_dl.la \
1063 -       mod_mysql_vhost.la mod_cgi.la mod_scgi.la mod_staticfile.la \
1064 -       mod_dirlisting.la mod_indexfile.la mod_setenv.la mod_alias.la \
1065 -       mod_userdir.la mod_rrdtool.la mod_usertrack.la mod_proxy.la \
1066 -       mod_ssi.la mod_secdownload.la mod_expire.la mod_evhost.la \
1067 +       mod_mysql_vhost.la mod_sql_vhost_core.la mod_cgi.la \
1068 +       mod_scgi.la mod_staticfile.la mod_dirlisting.la \
1069 +       mod_indexfile.la mod_setenv.la mod_alias.la mod_userdir.la \
1070 +       mod_rrdtool.la mod_usertrack.la mod_proxy.la mod_ssi.la \
1071 +       mod_secdownload.la mod_expire.la mod_evhost.la \
1072         mod_simple_vhost.la mod_fastcgi.la mod_access.la \
1073         mod_compress.la mod_auth.la mod_rewrite.la mod_redirect.la \
1074         mod_status.la mod_accesslog.la
1075 @@ -511,9 +519,9 @@
1076  mod_evasive_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1077  mod_evasive_la_LIBADD = $(common_libadd)
1078  mod_webdav_la_SOURCES = mod_webdav.c
1079 -mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
1080 +mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS) 
1081  mod_webdav_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1082 -mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS)
1083 +mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS) $(UUID_LIB)
1084  mod_cml_la_SOURCES = mod_cml.c mod_cml_lua.c mod_cml_funcs.c
1085  mod_cml_la_CFLAGS = $(AM_CFLAGS) $(LUA_CFLAGS)
1086  mod_cml_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1087 @@ -525,6 +533,9 @@
1088  mod_mysql_vhost_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1089  mod_mysql_vhost_la_LIBADD = $(MYSQL_LIBS) $(common_libadd)
1090  mod_mysql_vhost_la_CPPFLAGS = $(MYSQL_INCLUDE)
1091 +mod_sql_vhost_core_la_SOURCES = mod_sql_vhost_core.c
1092 +mod_sql_vhost_core_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1093 +mod_sql_vhost_core_la_LIBADD = $(common_libadd)
1094  mod_cgi_la_SOURCES = mod_cgi.c 
1095  mod_cgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1096  mod_cgi_la_LIBADD = $(common_libadd)
1097 @@ -608,7 +619,8 @@
1098        mod_ssi.h mod_ssi_expr.h inet_ntop_cache.h \
1099        configparser.h mod_ssi_exprparser.h \
1100        sys-mmap.h sys-socket.h mod_cml.h mod_cml_funcs.h \
1101 -      splaytree.h proc_open.h
1102 +      splaytree.h proc_open.h http_resp.h mod_sql_vhost_core.h \
1103 +         sys-files.h sys-process.h sys-strings.h
1104  
1105  lighttpd_SOURCES = $(src)
1106  lighttpd_LDADD = $(PCRE_LIB) $(DL_LIB) $(SENDFILE_LIB) $(ATTR_LIB) $(common_libadd) $(SSL_LIB) $(FAM_LIBS)
1107 @@ -739,6 +751,8 @@
1108         $(LINK) -rpath $(libdir) $(mod_setenv_la_LDFLAGS) $(mod_setenv_la_OBJECTS) $(mod_setenv_la_LIBADD) $(LIBS)
1109  mod_simple_vhost.la: $(mod_simple_vhost_la_OBJECTS) $(mod_simple_vhost_la_DEPENDENCIES) 
1110         $(LINK) -rpath $(libdir) $(mod_simple_vhost_la_LDFLAGS) $(mod_simple_vhost_la_OBJECTS) $(mod_simple_vhost_la_LIBADD) $(LIBS)
1111 +mod_sql_vhost_core.la: $(mod_sql_vhost_core_la_OBJECTS) $(mod_sql_vhost_core_la_DEPENDENCIES) 
1112 +       $(LINK) -rpath $(libdir) $(mod_sql_vhost_core_la_LDFLAGS) $(mod_sql_vhost_core_la_OBJECTS) $(mod_sql_vhost_core_la_LIBADD) $(LIBS)
1113  mod_ssi.la: $(mod_ssi_la_OBJECTS) $(mod_ssi_la_DEPENDENCIES) 
1114         $(LINK) -rpath $(libdir) $(mod_ssi_la_LDFLAGS) $(mod_ssi_la_OBJECTS) $(mod_ssi_la_LIBADD) $(LIBS)
1115  mod_staticfile.la: $(mod_staticfile_la_OBJECTS) $(mod_staticfile_la_DEPENDENCIES) 
1116 @@ -863,6 +877,8 @@
1117  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_auth.Plo@am__quote@
1118  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_auth_digest.Plo@am__quote@
1119  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_chunk.Po@am__quote@
1120 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_resp.Po@am__quote@
1121 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_resp_parser.Po@am__quote@
1122  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inet_ntop_cache.Po@am__quote@
1123  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/joblist.Po@am__quote@
1124  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keyvalue.Po@am__quote@
1125 @@ -890,6 +906,8 @@
1126  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-fdevent_solaris_devpoll.Plo@am__quote@
1127  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-http-header-glue.Plo@am__quote@
1128  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-http_chunk.Plo@am__quote@
1129 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-http_resp.Plo@am__quote@
1130 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-http_resp_parser.Plo@am__quote@
1131  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-inet_ntop_cache.Plo@am__quote@
1132  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-joblist.Plo@am__quote@
1133  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-keyvalue.Plo@am__quote@
1134 @@ -932,6 +950,7 @@
1135  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_secure_download.Plo@am__quote@
1136  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_setenv.Plo@am__quote@
1137  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_simple_vhost.Plo@am__quote@
1138 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_sql_vhost_core.Plo@am__quote@
1139  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_ssi.Plo@am__quote@
1140  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_ssi_expr.Plo@am__quote@
1141  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_ssi_exprparser.Plo@am__quote@
1142 @@ -1247,6 +1266,20 @@
1143  @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1144  @am__fastdepCC_FALSE@  $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblightcomp_la_CFLAGS) $(CFLAGS) -c -o liblightcomp_la-splaytree.lo `test -f 'splaytree.c' || echo '$(srcdir)/'`splaytree.c
1145  
1146 +liblightcomp_la-http_resp.lo: http_resp.c
1147 +@am__fastdepCC_TRUE@   if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblightcomp_la_CFLAGS) $(CFLAGS) -MT liblightcomp_la-http_resp.lo -MD -MP -MF "$(DEPDIR)/liblightcomp_la-http_resp.Tpo" -c -o liblightcomp_la-http_resp.lo `test -f 'http_resp.c' || echo '$(srcdir)/'`http_resp.c; \
1148 +@am__fastdepCC_TRUE@   then mv -f "$(DEPDIR)/liblightcomp_la-http_resp.Tpo" "$(DEPDIR)/liblightcomp_la-http_resp.Plo"; else rm -f "$(DEPDIR)/liblightcomp_la-http_resp.Tpo"; exit 1; fi
1149 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='http_resp.c' object='liblightcomp_la-http_resp.lo' libtool=yes @AMDEPBACKSLASH@
1150 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1151 +@am__fastdepCC_FALSE@  $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblightcomp_la_CFLAGS) $(CFLAGS) -c -o liblightcomp_la-http_resp.lo `test -f 'http_resp.c' || echo '$(srcdir)/'`http_resp.c
1152 +
1153 +liblightcomp_la-http_resp_parser.lo: http_resp_parser.c
1154 +@am__fastdepCC_TRUE@   if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblightcomp_la_CFLAGS) $(CFLAGS) -MT liblightcomp_la-http_resp_parser.lo -MD -MP -MF "$(DEPDIR)/liblightcomp_la-http_resp_parser.Tpo" -c -o liblightcomp_la-http_resp_parser.lo `test -f 'http_resp_parser.c' || echo '$(srcdir)/'`http_resp_parser.c; \
1155 +@am__fastdepCC_TRUE@   then mv -f "$(DEPDIR)/liblightcomp_la-http_resp_parser.Tpo" "$(DEPDIR)/liblightcomp_la-http_resp_parser.Plo"; else rm -f "$(DEPDIR)/liblightcomp_la-http_resp_parser.Tpo"; exit 1; fi
1156 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='http_resp_parser.c' object='liblightcomp_la-http_resp_parser.lo' libtool=yes @AMDEPBACKSLASH@
1157 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1158 +@am__fastdepCC_FALSE@  $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblightcomp_la_CFLAGS) $(CFLAGS) -c -o liblightcomp_la-http_resp_parser.lo `test -f 'http_resp_parser.c' || echo '$(srcdir)/'`http_resp_parser.c
1159 +
1160  mod_cml_la-mod_cml.lo: mod_cml.c
1161  @am__fastdepCC_TRUE@   if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mod_cml_la_CFLAGS) $(CFLAGS) -MT mod_cml_la-mod_cml.lo -MD -MP -MF "$(DEPDIR)/mod_cml_la-mod_cml.Tpo" -c -o mod_cml_la-mod_cml.lo `test -f 'mod_cml.c' || echo '$(srcdir)/'`mod_cml.c; \
1162  @am__fastdepCC_TRUE@   then mv -f "$(DEPDIR)/mod_cml_la-mod_cml.Tpo" "$(DEPDIR)/mod_cml_la-mod_cml.Plo"; else rm -f "$(DEPDIR)/mod_cml_la-mod_cml.Tpo"; exit 1; fi
1163 @@ -1506,14 +1539,19 @@
1164  @CROSS_COMPILING_TRUE@mod_ssi_exprparser.c mod_ssi_exprparser.h: 
1165  @CROSS_COMPILING_FALSE@configparser.y: lemon
1166  @CROSS_COMPILING_FALSE@mod_ssi_exprparser.y: lemon
1167 +@CROSS_COMPILING_FALSE@http_resp_parser.y: lemon
1168  
1169  @CROSS_COMPILING_FALSE@configparser.c configparser.h: configparser.y
1170  @CROSS_COMPILING_FALSE@        rm -f configparser.h
1171 -@CROSS_COMPILING_FALSE@        $(LEMON) -q $(srcdir)/configparser.y $(srcdir)/lempar.c
1172 +@CROSS_COMPILING_FALSE@        $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
1173 +
1174 +@CROSS_COMPILING_FALSE@http_resp_parser.c http_resp_parser.h: http_resp_parser.y
1175 +@CROSS_COMPILING_FALSE@        rm -f http_resp_parser.h
1176 +@CROSS_COMPILING_FALSE@        $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
1177  
1178  @CROSS_COMPILING_FALSE@mod_ssi_exprparser.c mod_ssi_exprparser.h: mod_ssi_exprparser.y 
1179  @CROSS_COMPILING_FALSE@        rm -f mod_ssi_exprparser.h
1180 -@CROSS_COMPILING_FALSE@        $(LEMON) -q $(srcdir)/mod_ssi_exprparser.y $(srcdir)/lempar.c
1181 +@CROSS_COMPILING_FALSE@        $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
1182  
1183  configfile.c: configparser.h
1184  mod_ssi_expr.c: mod_ssi_exprparser.h
1185 --- lighttpd-1.4.11/src/array.c 2005-11-18 13:58:32.000000000 +0200
1186 +++ lighttpd-1.4.12/src/array.c 2006-07-11 22:07:51.000000000 +0300
1187 @@ -11,12 +11,12 @@
1188  
1189  array *array_init(void) {
1190         array *a;
1191 -       
1192 +
1193         a = calloc(1, sizeof(*a));
1194         assert(a);
1195 -       
1196 +
1197         a->next_power_of_2 = 1;
1198 -       
1199 +
1200         return a;
1201  }
1202  
1203 @@ -43,29 +43,29 @@
1204  void array_free(array *a) {
1205         size_t i;
1206         if (!a) return;
1207 -       
1208 +
1209         if (!a->is_weakref) {
1210                 for (i = 0; i < a->size; i++) {
1211                         if (a->data[i]) a->data[i]->free(a->data[i]);
1212                 }
1213         }
1214 -       
1215 +
1216         if (a->data) free(a->data);
1217         if (a->sorted) free(a->sorted);
1218 -       
1219 +
1220         free(a);
1221  }
1222  
1223  void array_reset(array *a) {
1224         size_t i;
1225         if (!a) return;
1226 -       
1227 +
1228         if (!a->is_weakref) {
1229                 for (i = 0; i < a->used; i++) {
1230                         a->data[i]->reset(a->data[i]);
1231                 }
1232         }
1233 -       
1234 +
1235         a->used = 0;
1236  }
1237  
1238 @@ -84,20 +84,20 @@
1239  static int array_get_index(array *a, const char *key, size_t keylen, int *rndx) {
1240         int ndx = -1;
1241         int i, pos = 0;
1242 -       
1243 +
1244         if (key == NULL) return -1;
1245 -       
1246 +
1247         /* try to find the string */
1248         for (i = pos = a->next_power_of_2 / 2; ; i >>= 1) {
1249                 int cmp;
1250 -               
1251 +
1252                 if (pos < 0) {
1253                         pos += i;
1254                 } else if (pos >= (int)a->used) {
1255                         pos -= i;
1256                 } else {
1257                         cmp = buffer_caseless_compare(key, keylen, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used);
1258 -                       
1259 +
1260                         if (cmp == 0) {
1261                                 /* found */
1262                                 ndx = a->sorted[pos];
1263 @@ -110,46 +110,46 @@
1264                 }
1265                 if (i == 0) break;
1266         }
1267 -       
1268 +
1269         if (rndx) *rndx = pos;
1270 -       
1271 +
1272         return ndx;
1273  }
1274  
1275  data_unset *array_get_element(array *a, const char *key) {
1276         int ndx;
1277 -       
1278 +
1279         if (-1 != (ndx = array_get_index(a, key, strlen(key) + 1, NULL))) {
1280                 /* found, leave here */
1281 -               
1282 +
1283                 return a->data[ndx];
1284 -       } 
1285 -       
1286 +       }
1287 +
1288         return NULL;
1289  }
1290  
1291  data_unset *array_get_unused_element(array *a, data_type_t t) {
1292         data_unset *ds = NULL;
1293 -       
1294 +
1295         UNUSED(t);
1296  
1297         if (a->size == 0) return NULL;
1298 -       
1299 +
1300         if (a->used == a->size) return NULL;
1301  
1302         if (a->data[a->used]) {
1303                 ds = a->data[a->used];
1304 -               
1305 +
1306                 a->data[a->used] = NULL;
1307         }
1308 -       
1309 +
1310         return ds;
1311  }
1312  
1313  /* replace or insert data, return the old one with the same key */
1314  data_unset *array_replace(array *a, data_unset *du) {
1315         int ndx;
1316 -       
1317 +
1318         if (-1 == (ndx = array_get_index(a, du->key->ptr, du->key->used, NULL))) {
1319                 array_insert_unique(a, du);
1320                 return NULL;
1321 @@ -164,13 +164,13 @@
1322         int ndx = -1;
1323         int pos = 0;
1324         size_t j;
1325 -       
1326 -       /* generate unique index if neccesary */
1327 +
1328 +       /* generate unique index if necessary */
1329         if (str->key->used == 0 || str->is_index_key) {
1330                 buffer_copy_long(str->key, a->unique_ndx++);
1331                 str->is_index_key = 1;
1332         }
1333 -       
1334 +
1335         /* try to find the string */
1336         if (-1 != (ndx = array_get_index(a, str->key->ptr, str->key->used, &pos))) {
1337                 /* found, leave here */
1338 @@ -181,14 +181,14 @@
1339                 }
1340                 return 0;
1341         }
1342 -       
1343 +
1344         /* insert */
1345 -       
1346 +
1347         if (a->used+1 > INT_MAX) {
1348                 /* we can't handle more then INT_MAX entries: see array_get_index() */
1349                 return -1;
1350         }
1351 -       
1352 +
1353         if (a->size == 0) {
1354                 a->size   = 16;
1355                 a->data   = malloc(sizeof(*a->data)     * a->size);
1356 @@ -204,27 +204,27 @@
1357                 assert(a->sorted);
1358                 for (j = a->used; j < a->size; j++) a->data[j] = NULL;
1359         }
1360 -       
1361 +
1362         ndx = (int) a->used;
1363 -       
1364 +
1365         a->data[a->used++] = str;
1366 -       
1367 +
1368         if (pos != ndx &&
1369 -           ((pos < 0) || 
1370 +           ((pos < 0) ||
1371              buffer_caseless_compare(str->key->ptr, str->key->used, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used) > 0)) {
1372                 pos++;
1373 -       } 
1374 -       
1375 -       /* move everything on step to the right */
1376 +       }
1377 +
1378 +       /* move everything one step to the right */
1379         if (pos != ndx) {
1380                 memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted));
1381         }
1382 -       
1383 +
1384         /* insert */
1385         a->sorted[pos] = ndx;
1386 -       
1387 +
1388         if (a->next_power_of_2 == (size_t)ndx) a->next_power_of_2 <<= 1;
1389 -       
1390 +
1391         return 0;
1392  }
1393  
1394 @@ -254,7 +254,7 @@
1395         size_t i;
1396         size_t maxlen;
1397         int oneline = 1;
1398 -       
1399 +
1400         if (a->used > 5) {
1401                 oneline = 0;
1402         }
1403 @@ -314,7 +314,7 @@
1404         }
1405         array_print_indent(depth);
1406         fprintf(stderr, ")");
1407 -       
1408 +
1409         return 0;
1410  }
1411  
1412 @@ -323,47 +323,47 @@
1413         array *a;
1414         data_string *ds;
1415         data_count *dc;
1416 -       
1417 +
1418         UNUSED(argc);
1419         UNUSED(argv);
1420  
1421         a = array_init();
1422 -       
1423 +
1424         ds = data_string_init();
1425         buffer_copy_string(ds->key, "abc");
1426         buffer_copy_string(ds->value, "alfrag");
1427 -       
1428 +
1429         array_insert_unique(a, (data_unset *)ds);
1430 -       
1431 +
1432         ds = data_string_init();
1433         buffer_copy_string(ds->key, "abc");
1434         buffer_copy_string(ds->value, "hameplman");
1435 -       
1436 +
1437         array_insert_unique(a, (data_unset *)ds);
1438 -       
1439 +
1440         ds = data_string_init();
1441         buffer_copy_string(ds->key, "123");
1442         buffer_copy_string(ds->value, "alfrag");
1443 -       
1444 +
1445         array_insert_unique(a, (data_unset *)ds);
1446 -       
1447 +
1448         dc = data_count_init();
1449         buffer_copy_string(dc->key, "def");
1450 -       
1451 +
1452         array_insert_unique(a, (data_unset *)dc);
1453 -       
1454 +
1455         dc = data_count_init();
1456         buffer_copy_string(dc->key, "def");
1457 -       
1458 +
1459         array_insert_unique(a, (data_unset *)dc);
1460 -       
1461 +
1462         array_print(a, 0);
1463 -       
1464 +
1465         array_free(a);
1466 -       
1467 +
1468         fprintf(stderr, "%d\n",
1469                buffer_caseless_compare(CONST_STR_LEN("Content-Type"), CONST_STR_LEN("Content-type")));
1470 -       
1471 +
1472         return 0;
1473  }
1474  #endif
1475 --- lighttpd-1.4.11/src/array.h 2005-09-23 21:24:18.000000000 +0300
1476 +++ lighttpd-1.4.12/src/array.h 2006-07-11 22:07:51.000000000 +0300
1477 @@ -16,7 +16,7 @@
1478  #define DATA_UNSET \
1479         data_type_t type; \
1480         buffer *key; \
1481 -       int is_index_key; /* 1 if key is a array index (autogenerated keys) */ \
1482 +       int is_index_key; /* 1 if key is an array index (auto-generated keys) */ \
1483         struct data_unset *(*copy)(const struct data_unset *src); \
1484         void (* free)(struct data_unset *p); \
1485         void (* reset)(struct data_unset *p); \
1486 @@ -29,21 +29,21 @@
1487  
1488  typedef struct {
1489         data_unset  **data;
1490 -       
1491 +
1492         size_t *sorted;
1493 -       
1494 +
1495         size_t used;
1496         size_t size;
1497 -       
1498 +
1499         size_t unique_ndx;
1500 -       
1501 +
1502         size_t next_power_of_2;
1503         int is_weakref; /* data is weakref, don't bother the data */
1504  } array;
1505  
1506  typedef struct {
1507         DATA_UNSET;
1508 -       
1509 +
1510         int count;
1511  } data_count;
1512  
1513 @@ -51,7 +51,7 @@
1514  
1515  typedef struct {
1516         DATA_UNSET;
1517 -       
1518 +
1519         buffer *value;
1520  } data_string;
1521  
1522 @@ -60,7 +60,7 @@
1523  
1524  typedef struct {
1525         DATA_UNSET;
1526 -       
1527 +
1528         array *value;
1529  } data_array;
1530  
1531 @@ -74,7 +74,7 @@
1532         COMP_SERVER_SOCKET, COMP_HTTP_URL, COMP_HTTP_HOST, COMP_HTTP_REFERER, COMP_HTTP_USERAGENT, COMP_HTTP_COOKIE, COMP_HTTP_REMOTEIP
1533  } comp_key_t;
1534  
1535 -/* $HTTP["host"] ==    "incremental.home.kneschke.de" { ... } 
1536 +/* $HTTP["host"] ==    "incremental.home.kneschke.de" { ... }
1537   * for print:   comp_key      op    string
1538   * for compare: comp          cond  string/regex
1539   */
1540 @@ -82,15 +82,15 @@
1541  typedef struct _data_config data_config;
1542  struct _data_config {
1543         DATA_UNSET;
1544 -       
1545 +
1546         array *value;
1547 -       
1548 +
1549         buffer *comp_key;
1550         comp_key_t comp;
1551 -       
1552 +
1553         config_cond_t cond;
1554         buffer *op;
1555 -       
1556 +
1557         int context_ndx; /* more or less like an id */
1558         array *childs;
1559         /* nested */
1560 @@ -98,7 +98,7 @@
1561         /* for chaining only */
1562         data_config *prev;
1563         data_config *next;
1564 -       
1565 +
1566         buffer *string;
1567  #ifdef HAVE_PCRE_H
1568         pcre   *regex;
1569 @@ -110,7 +110,7 @@
1570  
1571  typedef struct {
1572         DATA_UNSET;
1573 -       
1574 +
1575         int value;
1576  } data_integer;
1577  
1578 @@ -120,13 +120,13 @@
1579         DATA_UNSET;
1580  
1581         buffer *host;
1582 -       
1583 +
1584         unsigned short port;
1585  
1586         time_t disable_ts;
1587         int is_disabled;
1588         size_t balance;
1589 -               
1590 +
1591         int usage; /* fair-balancing needs the no. of connections active on this host */
1592         int last_used_ndx; /* round robin */
1593  } data_fastcgi;
1594 --- lighttpd-1.4.11/src/base.h  2006-01-11 16:51:04.000000000 +0200
1595 +++ lighttpd-1.4.12/src/base.h  2006-07-11 22:07:51.000000000 +0300
1596 @@ -2,7 +2,6 @@
1597  #define _BASE_H_
1598  
1599  #include <sys/types.h>
1600 -#include <sys/time.h>
1601  #include <sys/stat.h>
1602  
1603  #ifdef HAVE_CONFIG_H
1604 @@ -26,10 +25,9 @@
1605  #include "sys-socket.h"
1606  #include "splaytree.h"
1607  
1608 -
1609  #if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H
1610  # define USE_OPENSSL
1611 -# include <openssl/ssl.h> 
1612 +# include <openssl/ssl.h>
1613  #endif
1614  
1615  #ifdef HAVE_FAM_H
1616 @@ -40,10 +38,6 @@
1617  # define O_BINARY 0
1618  #endif
1619  
1620 -#ifndef O_LARGEFILE
1621 -# define O_LARGEFILE 0
1622 -#endif
1623 -
1624  #ifndef SIZE_MAX
1625  # ifdef SIZE_T_MAX
1626  #  define SIZE_MAX SIZE_T_MAX
1627 @@ -70,7 +64,8 @@
1628  
1629  /* solaris and NetBSD 1.3.x again */
1630  #if (!defined(HAVE_STDINT_H)) && (!defined(HAVE_INTTYPES_H)) && (!defined(uint32_t))
1631 -# define uint32_t u_int32_t
1632 +//# define uint32_t u_int32_t
1633 +typedef unsigned __int32 uint32_t;
1634  #endif
1635  
1636  
1637 @@ -80,24 +75,24 @@
1638  
1639  #include "settings.h"
1640  
1641 -typedef enum { T_CONFIG_UNSET, 
1642 -               T_CONFIG_STRING, 
1643 -               T_CONFIG_SHORT, 
1644 -               T_CONFIG_BOOLEAN, 
1645 -               T_CONFIG_ARRAY, 
1646 -               T_CONFIG_LOCAL, 
1647 +typedef enum { T_CONFIG_UNSET,
1648 +               T_CONFIG_STRING,
1649 +               T_CONFIG_SHORT,
1650 +               T_CONFIG_BOOLEAN,
1651 +               T_CONFIG_ARRAY,
1652 +               T_CONFIG_LOCAL,
1653                 T_CONFIG_DEPRECATED
1654  } config_values_type_t;
1655  
1656 -typedef enum { T_CONFIG_SCOPE_UNSET, 
1657 -               T_CONFIG_SCOPE_SERVER, 
1658 +typedef enum { T_CONFIG_SCOPE_UNSET,
1659 +               T_CONFIG_SCOPE_SERVER,
1660                 T_CONFIG_SCOPE_CONNECTION
1661  } config_scope_type_t;
1662  
1663  typedef struct {
1664         const char *key;
1665         void *destination;
1666 -       
1667 +
1668         config_values_type_t type;
1669         config_scope_type_t scope;
1670  } config_values_t;
1671 @@ -142,40 +137,40 @@
1672         /* the request-line */
1673         buffer *request;
1674         buffer *uri;
1675 -       
1676 +
1677         buffer *orig_uri;
1678 -       
1679 +
1680         http_method_t  http_method;
1681         http_version_t http_version;
1682 -       
1683 +
1684         buffer *request_line;
1685 -       
1686 +
1687         /* strings to the header */
1688         buffer *http_host; /* not alloced */
1689         const char   *http_range;
1690         const char   *http_content_type;
1691         const char   *http_if_modified_since;
1692         const char   *http_if_none_match;
1693 -       
1694 +
1695         array  *headers;
1696 -       
1697 +
1698         /* CONTENT */
1699         size_t content_length; /* returned by strtoul() */
1700 -       
1701 +
1702         /* internal representation */
1703         int     accept_encoding;
1704 -       
1705 +
1706         /* internal */
1707         buffer *pathinfo;
1708  } request;
1709  
1710  typedef struct {
1711         off_t   content_length;
1712 -       int     keep_alive;               /* used by  the subrequests in proxy, cgi and fcgi to say the subrequest was keep-alive or not */
1713 -       
1714 +       int     keep_alive;               /* used by the subrequests in proxy, cgi and fcgi to say whether the subrequest was keep-alive or not */
1715 +
1716         array  *headers;
1717 -       
1718 -       enum { 
1719 +
1720 +       enum {
1721                 HTTP_TRANSFER_ENCODING_IDENTITY, HTTP_TRANSFER_ENCODING_CHUNKED
1722         } transfer_encoding;
1723  } response;
1724 @@ -191,21 +186,21 @@
1725  typedef struct {
1726         buffer *path;
1727         buffer *basedir; /* path = "(basedir)(.*)" */
1728 -       
1729 +
1730         buffer *doc_root; /* path = doc_root + rel_path */
1731         buffer *rel_path;
1732 -       
1733 +
1734         buffer *etag;
1735  } physical;
1736  
1737  typedef struct {
1738         buffer *name;
1739         buffer *etag;
1740 -       
1741 +
1742         struct stat st;
1743 -       
1744 +
1745         time_t stat_ts;
1746 -       
1747 +
1748  #ifdef HAVE_FAM_H
1749         int    dir_version;
1750         int    dir_ndx;
1751 @@ -215,8 +210,8 @@
1752  } stat_cache_entry;
1753  
1754  typedef struct {
1755 -       splay_tree *files; /* the nodes of the tree are stat_cache_entry's */
1756 -       
1757 +       splay_tree *files; /* the nodes of the tree are stat_cache_entries */
1758 +
1759         buffer *dir_name; /* for building the dirname from the filename */
1760  #ifdef HAVE_FAM_H
1761         splay_tree *dirs; /* the nodes of the tree are fam_dir_entry */
1762 @@ -228,7 +223,7 @@
1763  
1764  typedef struct {
1765         array *mimetypes;
1766 -       
1767 +
1768         /* virtual-servers */
1769         buffer *document_root;
1770         buffer *server_name;
1771 @@ -236,7 +231,7 @@
1772         buffer *server_tag;
1773         buffer *dirlist_encoding;
1774         buffer *errorfile_prefix;
1775 -       
1776 +
1777         unsigned short max_keep_alive_requests;
1778         unsigned short max_keep_alive_idle;
1779         unsigned short max_read_idle;
1780 @@ -244,16 +239,17 @@
1781         unsigned short use_xattr;
1782         unsigned short follow_symlink;
1783         unsigned short range_requests;
1784 -       
1785 +
1786         /* debug */
1787 -       
1788 +
1789         unsigned short log_file_not_found;
1790         unsigned short log_request_header;
1791         unsigned short log_request_handling;
1792         unsigned short log_response_header;
1793         unsigned short log_condition_handling;
1794 -       
1795 -       
1796 +       unsigned short log_condition_cache_handling;
1797 +
1798 +
1799         /* server wide */
1800         buffer *ssl_pemfile;
1801         buffer *ssl_ca_file;
1802 @@ -268,22 +264,22 @@
1803         /* configside */
1804         unsigned short global_kbytes_per_second; /*  */
1805  
1806 -       off_t  global_bytes_per_second_cnt; 
1807 +       off_t  global_bytes_per_second_cnt;
1808         /* server-wide traffic-shaper
1809 -        * 
1810 +        *
1811          * each context has the counter which is inited once
1812 -        * a second by the global_kbytes_per_second config-var
1813 +        * per second by the global_kbytes_per_second config-var
1814          *
1815          * as soon as global_kbytes_per_second gets below 0
1816          * the connected conns are "offline" a little bit
1817          *
1818          * the problem:
1819 -        * we somehow have to loose our "we are writable" signal 
1820 +        * we somehow have to lose our "we are writable" signal
1821          * on the way.
1822 -        * 
1823 +        *
1824          */
1825         off_t *global_bytes_per_second_cnt_ptr; /*  */
1826 -       
1827 +
1828  #ifdef USE_OPENSSL
1829         SSL_CTX *ssl_ctx;
1830  #endif
1831 @@ -291,18 +287,18 @@
1832  
1833  /* the order of the items should be the same as they are processed
1834   * read before write as we use this later */
1835 -typedef enum { 
1836 -       CON_STATE_CONNECT, 
1837 -       CON_STATE_REQUEST_START, 
1838 -       CON_STATE_READ, 
1839 -       CON_STATE_REQUEST_END, 
1840 -       CON_STATE_READ_POST, 
1841 -       CON_STATE_HANDLE_REQUEST, 
1842 -       CON_STATE_RESPONSE_START, 
1843 -       CON_STATE_WRITE, 
1844 -       CON_STATE_RESPONSE_END, 
1845 -       CON_STATE_ERROR, 
1846 -       CON_STATE_CLOSE 
1847 +typedef enum {
1848 +       CON_STATE_CONNECT,
1849 +       CON_STATE_REQUEST_START,
1850 +       CON_STATE_READ,
1851 +       CON_STATE_REQUEST_END,
1852 +       CON_STATE_READ_POST,
1853 +       CON_STATE_HANDLE_REQUEST,
1854 +       CON_STATE_RESPONSE_START,
1855 +       CON_STATE_WRITE,
1856 +       CON_STATE_RESPONSE_END,
1857 +       CON_STATE_ERROR,
1858 +       CON_STATE_CLOSE
1859  } connection_state_t;
1860  
1861  typedef enum { COND_RESULT_UNSET, COND_RESULT_FALSE, COND_RESULT_TRUE } cond_result_t;
1862 @@ -315,88 +311,88 @@
1863  
1864  typedef struct {
1865         connection_state_t state;
1866 -       
1867 +
1868         /* timestamps */
1869         time_t read_idle_ts;
1870         time_t close_timeout_ts;
1871         time_t write_request_ts;
1872 -       
1873 +
1874         time_t connection_start;
1875         time_t request_start;
1876 -       
1877 +
1878         struct timeval start_tv;
1879 -       
1880 +
1881         size_t request_count;        /* number of requests handled in this connection */
1882         size_t loops_per_request;    /* to catch endless loops in a single request
1883 -                                     * 
1884 +                                     *
1885                                       * used by mod_rewrite, mod_fastcgi, ... and others
1886                                       * this is self-protection
1887                                       */
1888 -       
1889 +
1890         int fd;                      /* the FD for this connection */
1891         int fde_ndx;                 /* index for the fdevent-handler */
1892         int ndx;                     /* reverse mapping to server->connection[ndx] */
1893 -       
1894 +
1895         /* fd states */
1896         int is_readable;
1897         int is_writable;
1898 -       
1899 -       int     keep_alive;           /* only request.c can enable it, all other just disable */
1900 -       
1901 +
1902 +       int     keep_alive;           /* only request.c can enable it, all others just disable */
1903 +
1904         int file_started;
1905         int file_finished;
1906 -       
1907 +
1908         chunkqueue *write_queue;      /* a large queue for low-level write ( HTTP response ) [ file, mem ] */
1909         chunkqueue *read_queue;       /* a small queue for low-level read ( HTTP request ) [ mem ] */
1910         chunkqueue *request_content_queue; /* takes request-content into tempfile if necessary [ tempfile, mem ]*/
1911 -       
1912 +
1913         int traffic_limit_reached;
1914 -       
1915 +
1916         off_t bytes_written;          /* used by mod_accesslog, mod_rrd */
1917         off_t bytes_written_cur_second; /* used by mod_accesslog, mod_rrd */
1918         off_t bytes_read;             /* used by mod_accesslog, mod_rrd */
1919         off_t bytes_header;
1920 -       
1921 +
1922         int http_status;
1923 -       
1924 +
1925         sock_addr dst_addr;
1926         buffer *dst_addr_buf;
1927  
1928         /* request */
1929         buffer *parse_request;
1930         unsigned int parsed_response; /* bitfield which contains the important header-fields of the parsed response header */
1931 -       
1932 +
1933         request  request;
1934         request_uri uri;
1935 -       physical physical; 
1936 +       physical physical;
1937         response response;
1938 -       
1939 +
1940         size_t header_len;
1941 -       
1942 +
1943         buffer *authed_user;
1944         array  *environment; /* used to pass lighttpd internal stuff to the FastCGI/CGI apps, setenv does that */
1945 -       
1946 +
1947         /* response */
1948         int    got_response;
1949 -       
1950 +
1951         int    in_joblist;
1952 -       
1953 +
1954         connection_type mode;
1955 -       
1956 +
1957         void **plugin_ctx;           /* plugin connection specific config */
1958 -       
1959 +
1960         specific_config conf;        /* global connection specific config */
1961         cond_cache_t *cond_cache;
1962 -       
1963 +
1964         buffer *server_name;
1965 -       
1966 +
1967         /* error-handler */
1968         buffer *error_handler;
1969         int error_handler_saved_status;
1970         int in_error_handler;
1971 -       
1972 +
1973         void *srv_socket;   /* reference to the server-socket (typecast to server_socket) */
1974 -       
1975 +
1976  #ifdef USE_OPENSSL
1977         SSL *ssl;
1978  #endif
1979 @@ -439,39 +435,48 @@
1980         size_t size;
1981  } buffer_plugin;
1982  
1983 +typedef enum {
1984 +    NETWORK_STATUS_UNSET,
1985 +    NETWORK_STATUS_SUCCESS,
1986 +    NETWORK_STATUS_FATAL_ERROR,
1987 +    NETWORK_STATUS_CONNECTION_CLOSE,
1988 +    NETWORK_STATUS_WAIT_FOR_EVENT,
1989 +    NETWORK_STATUS_INTERRUPTED
1990 +} network_status_t;
1991 +
1992  typedef struct {
1993         unsigned short port;
1994         buffer *bindhost;
1995 -       
1996 +
1997         buffer *errorlog_file;
1998         unsigned short errorlog_use_syslog;
1999 -       
2000 +
2001         unsigned short dont_daemonize;
2002         buffer *changeroot;
2003         buffer *username;
2004         buffer *groupname;
2005 -       
2006 +
2007         buffer *pid_file;
2008 -       
2009 +
2010         buffer *event_handler;
2011 -       
2012 +
2013         buffer *modules_dir;
2014         buffer *network_backend;
2015         array *modules;
2016         array *upload_tempdirs;
2017 -       
2018 +
2019         unsigned short max_worker;
2020         unsigned short max_fds;
2021         unsigned short max_conns;
2022         unsigned short max_request_size;
2023 -       
2024 +
2025         unsigned short log_request_header_on_error;
2026         unsigned short log_state_handling;
2027 -       
2028 -       enum { STAT_CACHE_ENGINE_UNSET, 
2029 -                       STAT_CACHE_ENGINE_NONE, 
2030 -                       STAT_CACHE_ENGINE_SIMPLE, 
2031 -                       STAT_CACHE_ENGINE_FAM 
2032 +
2033 +       enum { STAT_CACHE_ENGINE_UNSET,
2034 +                       STAT_CACHE_ENGINE_NONE,
2035 +                       STAT_CACHE_ENGINE_SIMPLE,
2036 +                       STAT_CACHE_ENGINE_FAM
2037         } stat_cache_engine;
2038         unsigned short enable_cores;
2039  } server_config;
2040 @@ -480,14 +485,14 @@
2041         sock_addr addr;
2042         int       fd;
2043         int       fde_ndx;
2044 -       
2045 +
2046         buffer *ssl_pemfile;
2047         buffer *ssl_ca_file;
2048         unsigned short use_ipv6;
2049         unsigned short is_ssl;
2050 -       
2051 +
2052         buffer *srv_token;
2053 -       
2054 +
2055  #ifdef USE_OPENSSL
2056         SSL_CTX *ssl_ctx;
2057  #endif
2058 @@ -495,37 +500,37 @@
2059  
2060  typedef struct {
2061         server_socket **ptr;
2062 -       
2063 +
2064         size_t size;
2065         size_t used;
2066  } server_socket_array;
2067  
2068  typedef struct server {
2069         server_socket_array srv_sockets;
2070 -       
2071 +
2072         /* the errorlog */
2073         int errorlog_fd;
2074         enum { ERRORLOG_STDERR, ERRORLOG_FILE, ERRORLOG_SYSLOG } errorlog_mode;
2075         buffer *errorlog_buf;
2076 -       
2077 +
2078         fdevents *ev, *ev_ins;
2079 -       
2080 +
2081         buffer_plugin plugins;
2082         void *plugin_slots;
2083 -       
2084 +
2085         /* counters */
2086         int con_opened;
2087         int con_read;
2088         int con_written;
2089         int con_closed;
2090 -       
2091 +
2092         int ssl_is_init;
2093 -       
2094 +
2095         int max_fds;    /* max possible fds */
2096         int cur_fds;    /* currently used fds */
2097         int want_fds;   /* waiting fds */
2098         int sockets_disabled;
2099 -       
2100 +
2101         size_t max_conns;
2102  
2103         /* buffers */
2104 @@ -533,13 +538,13 @@
2105         buffer *response_header;
2106         buffer *response_range;
2107         buffer *tmp_buf;
2108 -       
2109 +
2110         buffer *tmp_chunk_len;
2111 -       
2112 +
2113         buffer *empty_string; /* is necessary for cond_match */
2114  
2115         buffer *cond_check_buf;
2116 -       
2117 +
2118         /* caches */
2119  #ifdef HAVE_IPV6
2120         inet_ntop_cache_type inet_ntop_cache[INET_NTOP_CACHE_MAX];
2121 @@ -547,31 +552,31 @@
2122         mtime_cache_type mtime_cache[FILE_CACHE_MAX];
2123  
2124         array *split_vals;
2125 -       
2126 +
2127         /* Timestamps */
2128         time_t cur_ts;
2129         time_t last_generated_date_ts;
2130         time_t last_generated_debug_ts;
2131         time_t startup_ts;
2132 -       
2133 +
2134         buffer *ts_debug_str;
2135         buffer *ts_date_str;
2136 -       
2137 +
2138         /* config-file */
2139         array *config;
2140         array *config_touched;
2141 -       
2142 +
2143         array *config_context;
2144         specific_config **config_storage;
2145 -       
2146 +
2147         server_config  srvconf;
2148 -       
2149 +
2150         int config_deprecated;
2151 -       
2152 +
2153         connections *conns;
2154         connections *joblist;
2155         connections *fdwaitqueue;
2156 -       
2157 +
2158         stat_cache  *stat_cache;
2159  
2160         /**
2161 @@ -588,18 +593,20 @@
2162          *   fastcgi.backend.<key>.disconnects = ...
2163          */
2164         array *status;
2165 -       
2166 +
2167         fdevent_handler_t event_handler;
2168  
2169 -       int (* network_backend_write)(struct server *srv, connection *con, int fd, chunkqueue *cq);
2170 -       int (* network_backend_read)(struct server *srv, connection *con, int fd, chunkqueue *cq);
2171 +       network_status_t (* network_backend_write)(struct server *srv, connection *con, int fd, chunkqueue *cq);
2172 +       network_status_t (* network_backend_read)(struct server *srv, connection *con, int fd, chunkqueue *cq);
2173  #ifdef USE_OPENSSL
2174 -       int (* network_ssl_backend_write)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
2175 -       int (* network_ssl_backend_read)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
2176 +       network_status_t (* network_ssl_backend_write)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
2177 +       network_status_t (* network_ssl_backend_read)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
2178  #endif
2179  
2180 +#ifdef HAVE_PWD_H
2181         uid_t uid;
2182         gid_t gid;
2183 +#endif
2184  } server;
2185  
2186  
2187 --- lighttpd-1.4.11/src/buffer.c        2006-01-13 00:00:45.000000000 +0200
2188 +++ lighttpd-1.4.12/src/buffer.c        2006-07-11 22:07:52.000000000 +0300
2189 @@ -12,20 +12,20 @@
2190  
2191  
2192  /**
2193 - * init the buffer 
2194 - * 
2195 + * init the buffer
2196 + *
2197   */
2198  
2199  buffer* buffer_init(void) {
2200         buffer *b;
2201 -       
2202 +
2203         b = malloc(sizeof(*b));
2204         assert(b);
2205 -       
2206 +
2207         b->ptr = NULL;
2208         b->size = 0;
2209         b->used = 0;
2210 -       
2211 +
2212         return b;
2213  }
2214  
2215 @@ -36,8 +36,8 @@
2216  }
2217  
2218  /**
2219 - * free the buffer 
2220 - * 
2221 + * free the buffer
2222 + *
2223   */
2224  
2225  void buffer_free(buffer *b) {
2226 @@ -49,39 +49,39 @@
2227  
2228  void buffer_reset(buffer *b) {
2229         if (!b) return;
2230 -       
2231 +
2232         /* limit don't reuse buffer larger than ... bytes */
2233         if (b->size > BUFFER_MAX_REUSE_SIZE) {
2234                 free(b->ptr);
2235                 b->ptr = NULL;
2236                 b->size = 0;
2237         }
2238 -       
2239 +
2240         b->used = 0;
2241  }
2242  
2243  
2244  /**
2245 - * 
2246 - * allocate (if neccessary) enough space for 'size' bytes and 
2247 + *
2248 + * allocate (if necessary) enough space for 'size' bytes and
2249   * set the 'used' counter to 0
2250 - * 
2251 + *
2252   */
2253  
2254  #define BUFFER_PIECE_SIZE 64
2255  
2256  int buffer_prepare_copy(buffer *b, size_t size) {
2257         if (!b) return -1;
2258 -       
2259 -       if ((0 == b->size) || 
2260 +
2261 +       if ((0 == b->size) ||
2262             (size > b->size)) {
2263                 if (b->size) free(b->ptr);
2264 -               
2265 +
2266                 b->size = size;
2267 -               
2268 -               /* always allocate a multiply of BUFFER_PIECE_SIZE */
2269 +
2270 +               /* always allocate a multiple of BUFFER_PIECE_SIZE */
2271                 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
2272 -               
2273 +
2274                 b->ptr = malloc(b->size);
2275                 assert(b->ptr);
2276         }
2277 @@ -90,30 +90,30 @@
2278  }
2279  
2280  /**
2281 - * 
2282 - * increase the internal buffer (if neccessary) to append another 'size' byte
2283 + *
2284 + * increase the internal buffer (if necessary) to append another 'size' byte
2285   * ->used isn't changed
2286 - * 
2287 + *
2288   */
2289  
2290  int buffer_prepare_append(buffer *b, size_t size) {
2291         if (!b) return -1;
2292 -       
2293 +
2294         if (0 == b->size) {
2295                 b->size = size;
2296 -               
2297 -               /* always allocate a multiply of BUFFER_PIECE_SIZE */
2298 +
2299 +               /* always allocate a multiple of BUFFER_PIECE_SIZE */
2300                 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
2301 -               
2302 +
2303                 b->ptr = malloc(b->size);
2304                 b->used = 0;
2305                 assert(b->ptr);
2306         } else if (b->used + size > b->size) {
2307                 b->size += size;
2308 -               
2309 -               /* always allocate a multiply of BUFFER_PIECE_SIZE */
2310 +
2311 +               /* always allocate a multiple of BUFFER_PIECE_SIZE */
2312                 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
2313 -               
2314 +
2315                 b->ptr = realloc(b->ptr, b->size);
2316                 assert(b->ptr);
2317         }
2318 @@ -122,7 +122,7 @@
2319  
2320  int buffer_copy_string(buffer *b, const char *s) {
2321         size_t s_len;
2322 -       
2323 +
2324         if (!s || !b) return -1;
2325  
2326         s_len = strlen(s) + 1;
2327 @@ -136,26 +136,26 @@
2328  
2329  int buffer_copy_string_len(buffer *b, const char *s, size_t s_len) {
2330         if (!s || !b) return -1;
2331 -#if 0  
2332 -       /* removed optimization as we have to keep the empty string 
2333 +#if 0
2334 +       /* removed optimization as we have to keep the empty string
2335          * in some cases for the config handling
2336 -        * 
2337 +        *
2338          * url.access-deny = ( "" )
2339          */
2340         if (s_len == 0) return 0;
2341 -#endif 
2342 +#endif
2343         buffer_prepare_copy(b, s_len + 1);
2344 -       
2345 +
2346         memcpy(b->ptr, s, s_len);
2347         b->ptr[s_len] = '\0';
2348         b->used = s_len + 1;
2349 -       
2350 +
2351         return 0;
2352  }
2353  
2354  int buffer_copy_string_buffer(buffer *b, const buffer *src) {
2355         if (!src) return -1;
2356 -       
2357 +
2358         if (src->used == 0) {
2359                 b->used = 0;
2360                 return 0;
2361 @@ -201,10 +201,10 @@
2362  
2363  /**
2364   * append a string to the end of the buffer
2365 - * 
2366 - * the resulting buffer is terminated with a '\0' 
2367 - * s is treated as a un-terminated string (a \0 is handled a normal character)
2368 - * 
2369 + *
2370 + * the resulting buffer is terminated with a '\0'
2371 + * s is treated as an un-terminated string (a \0 is handled as a normal character)
2372 + *
2373   * @param b a buffer
2374   * @param s the string
2375   * @param s_len size of the string (without the terminating \0)
2376 @@ -228,7 +228,7 @@
2377  int buffer_append_string_buffer(buffer *b, const buffer *src) {
2378         if (!src) return -1;
2379         if (src->used == 0) return 0;
2380 -       
2381 +
2382         return buffer_append_string_len(b, src->ptr, src->used - 1);
2383  }
2384  
2385 @@ -245,9 +245,9 @@
2386  
2387  int buffer_copy_memory(buffer *b, const char *s, size_t s_len) {
2388         if (!s || !b) return -1;
2389 -       
2390 +
2391         b->used = 0;
2392 -       
2393 +
2394         return buffer_append_memory(b, s, s_len);
2395  }
2396  
2397 @@ -402,46 +402,115 @@
2398  
2399  
2400  /**
2401 - * init the buffer 
2402 - * 
2403 + * init the ptr buffer
2404 + *
2405 + */
2406 +buffer_ptr *buffer_ptr_init(buffer_ptr_free_t freer)
2407 +{
2408 +       buffer_ptr *l = calloc(1, sizeof(buffer_ptr));
2409 +       l->free = freer;
2410 +
2411 +       return l;
2412 +}
2413 +
2414 +/**
2415 + * free the buffer_array
2416 + *
2417 + */
2418 +void buffer_ptr_free(buffer_ptr *l)
2419 +{
2420 +       if (NULL != l) {
2421 +               buffer_ptr_clear(l);
2422 +               free(l);
2423 +       }
2424 +}
2425 +
2426 +void buffer_ptr_clear(buffer_ptr *l)
2427 +{
2428 +       assert(NULL != l);
2429 +
2430 +       if (l->free && l->used) {
2431 +               size_t i;
2432 +               for (i = 0; i < l->used; i ++) {
2433 +                       l->free(l->ptr[i]);
2434 +               }
2435 +       }
2436 +
2437 +       if (l->ptr) {
2438 +               free(l->ptr);
2439 +               l->ptr = NULL;
2440 +       }
2441 +       l->used = 0;
2442 +       l->size = 0;
2443 +}
2444 +
2445 +void buffer_ptr_append(buffer_ptr* l, void *item)
2446 +{
2447 +       assert(NULL != l);
2448 +       if (l->ptr == NULL) {
2449 +               l->size = 16;
2450 +               l->ptr = (void **)malloc(sizeof(void *) * l->size);
2451 +       }
2452 +       else if (l->used == l->size) {
2453 +               l->size += 16;
2454 +               l->ptr = realloc(l->ptr, sizeof(void *) * l->size);
2455 +       }
2456 +       l->ptr[l->used++] = item;
2457 +}
2458 +
2459 +void *buffer_ptr_pop(buffer_ptr* l)
2460 +{
2461 +       assert(NULL != l && l->used > 0);
2462 +       return l->ptr[--l->used];
2463 +}
2464 +
2465 +void *buffer_ptr_top(buffer_ptr* l)
2466 +{
2467 +       assert(NULL != l && l->used > 0);
2468 +       return l->ptr[l->used-1];
2469 +}
2470 +
2471 +/**
2472 + * init the buffer
2473 + *
2474   */
2475  
2476  buffer_array* buffer_array_init(void) {
2477         buffer_array *b;
2478 -       
2479 +
2480         b = malloc(sizeof(*b));
2481 -       
2482 +
2483         assert(b);
2484         b->ptr = NULL;
2485         b->size = 0;
2486         b->used = 0;
2487 -       
2488 +
2489         return b;
2490  }
2491  
2492  void buffer_array_reset(buffer_array *b) {
2493         size_t i;
2494 -       
2495 +
2496         if (!b) return;
2497 -       
2498 +
2499         /* if they are too large, reduce them */
2500         for (i = 0; i < b->used; i++) {
2501                 buffer_reset(b->ptr[i]);
2502         }
2503 -       
2504 +
2505         b->used = 0;
2506  }
2507  
2508  
2509  /**
2510 - * free the buffer_array 
2511 - * 
2512 + * free the buffer_array
2513 + *
2514   */
2515  
2516  void buffer_array_free(buffer_array *b) {
2517         size_t i;
2518         if (!b) return;
2519 -       
2520 +
2521         for (i = 0; i < b->size; i++) {
2522                 if (b->ptr[i]) buffer_free(b->ptr[i]);
2523         }
2524 @@ -451,7 +520,7 @@
2525  
2526  buffer *buffer_array_append_get_buffer(buffer_array *b) {
2527         size_t i;
2528 -       
2529 +
2530         if (b->size == 0) {
2531                 b->size = 16;
2532                 b->ptr = malloc(sizeof(*b->ptr) * b->size);
2533 @@ -467,13 +536,13 @@
2534                         b->ptr[i] = NULL;
2535                 }
2536         }
2537 -       
2538 +
2539         if (b->ptr[b->used] == NULL) {
2540                 b->ptr[b->used] = buffer_init();
2541         }
2542 -       
2543 +
2544         b->ptr[b->used]->used = 0;
2545 -       
2546 +
2547         return b->ptr[b->used++];
2548  }
2549  
2550 @@ -482,23 +551,23 @@
2551         size_t i;
2552         if (len == 0) return NULL;
2553         if (needle == NULL) return NULL;
2554 -       
2555 +
2556         if (b->used < len) return NULL;
2557 -       
2558 +
2559         for(i = 0; i < b->used - len; i++) {
2560                 if (0 == memcmp(b->ptr + i, needle, len)) {
2561                         return b->ptr + i;
2562                 }
2563         }
2564 -       
2565 +
2566         return NULL;
2567  }
2568  
2569  buffer *buffer_init_string(const char *str) {
2570         buffer *b = buffer_init();
2571 -       
2572 +
2573         buffer_copy_string(b, str);
2574 -       
2575 +
2576         return b;
2577  }
2578  
2579 @@ -507,8 +576,8 @@
2580  }
2581  
2582  /**
2583 - * check if two buffer contain the same data
2584 - * 
2585 + * check if two buffers contain the same data
2586 + *
2587   * HISTORY: this function was pretty much optimized, but didn't handled
2588   * alignment properly.
2589   */
2590 @@ -522,100 +591,100 @@
2591  
2592  int buffer_is_equal_string(buffer *a, const char *s, size_t b_len) {
2593         buffer b;
2594 -       
2595 +
2596         b.ptr = (char *)s;
2597         b.used = b_len + 1;
2598 -       
2599 +
2600         return buffer_is_equal(a, &b);
2601  }
2602  
2603  /* simple-assumption:
2604 - * 
2605 - * most parts are equal and doing a case conversion needs time
2606 - * 
2607 + *
2608 + * most parts are equal and doing a case conversion takes time
2609 + *
2610   */
2611  int buffer_caseless_compare(const char *a, size_t a_len, const char *b, size_t b_len) {
2612         size_t ndx = 0, max_ndx;
2613         size_t *al, *bl;
2614         size_t mask = sizeof(*al) - 1;
2615 -       
2616 +
2617         al = (size_t *)a;
2618         bl = (size_t *)b;
2619 -       
2620 -       /* is the alignment correct ? */
2621 +
2622 +       /* is the alignment correct? */
2623         if ( ((size_t)al & mask) == 0 &&
2624              ((size_t)bl & mask) == 0 ) {
2625 -               
2626 +
2627                 max_ndx = ((a_len < b_len) ? a_len : b_len) & ~mask;
2628 -               
2629 +
2630                 for (; ndx < max_ndx; ndx += sizeof(*al)) {
2631                         if (*al != *bl) break;
2632                         al++; bl++;
2633 -                       
2634 +
2635                 }
2636 -               
2637 +
2638         }
2639 -       
2640 +
2641         a = (char *)al;
2642         b = (char *)bl;
2643 -       
2644 +
2645         max_ndx = ((a_len < b_len) ? a_len : b_len);
2646 -       
2647 +
2648         for (; ndx < max_ndx; ndx++) {
2649                 char a1 = *a++, b1 = *b++;
2650 -               
2651 +
2652                 if (a1 != b1) {
2653                         if ((a1 >= 'A' && a1 <= 'Z') && (b1 >= 'a' && b1 <= 'z'))
2654                                 a1 |= 32;
2655                         else if ((a1 >= 'a' && a1 <= 'z') && (b1 >= 'A' && b1 <= 'Z'))
2656                                 b1 |= 32;
2657                         if ((a1 - b1) != 0) return (a1 - b1);
2658 -                       
2659 +
2660                 }
2661         }
2662 -       
2663 +
2664         return 0;
2665  }
2666  
2667  
2668  /**
2669   * check if the rightmost bytes of the string are equal.
2670 - * 
2671 - * 
2672 + *
2673 + *
2674   */
2675  
2676  int buffer_is_equal_right_len(buffer *b1, buffer *b2, size_t len) {
2677         /* no, len -> equal */
2678         if (len == 0) return 1;
2679 -       
2680 +
2681         /* len > 0, but empty buffers -> not equal */
2682         if (b1->used == 0 || b2->used == 0) return 0;
2683 -       
2684 +
2685         /* buffers too small -> not equal */
2686 -       if (b1->used - 1 < len || b1->used - 1 < len) return 0;
2687 -       
2688 -       if (0 == strncmp(b1->ptr + b1->used - 1 - len, 
2689 +       if (b1->used - 1 < len || b2->used - 1 < len) return 0;
2690 +
2691 +       if (0 == strncmp(b1->ptr + b1->used - 1 - len,
2692                          b2->ptr + b2->used - 1 - len, len)) {
2693                 return 1;
2694         }
2695 -       
2696 +
2697         return 0;
2698  }
2699  
2700  int buffer_copy_string_hex(buffer *b, const char *in, size_t in_len) {
2701         size_t i;
2702 -       
2703 +
2704         /* BO protection */
2705         if (in_len * 2 < in_len) return -1;
2706 -       
2707 +
2708         buffer_prepare_copy(b, in_len * 2 + 1);
2709 -       
2710 +
2711         for (i = 0; i < in_len; i++) {
2712                 b->ptr[b->used++] = hex_chars[(in[i] >> 4) & 0x0F];
2713                 b->ptr[b->used++] = hex_chars[in[i] & 0x0F];
2714         }
2715         b->ptr[b->used++] = '\0';
2716 -       
2717 +
2718         return 0;
2719  }
2720  
2721 @@ -624,7 +693,7 @@
2722         0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
2723         */
2724         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
2725 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */ 
2726 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
2727         1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1,  /*  20 -  2F space " # $ % & ' + , / */
2728         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,  /*  30 -  3F : ; = ? @ < > */
2729         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  40 -  4F */
2730 @@ -646,7 +715,7 @@
2731         0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
2732         */
2733         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
2734 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */ 
2735 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
2736         1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0,  /*  20 -  2F space " # $ % & ' + , / */
2737         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,  /*  30 -  3F : ; = ? @ < > */
2738         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  40 -  4F */
2739 @@ -668,7 +737,7 @@
2740         0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
2741         */
2742         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
2743 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */ 
2744 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
2745         0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  20 -  2F & */
2746         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,  /*  30 -  3F < > */
2747         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  40 -  4F */
2748 @@ -690,7 +759,7 @@
2749         0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
2750         */
2751         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
2752 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */ 
2753 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
2754         0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  20 -  2F & */
2755         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,  /*  30 -  3F < > */
2756         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  40 -  4F */
2757 @@ -712,12 +781,12 @@
2758         0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
2759         */
2760         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
2761 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */ 
2762 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  20 -  2F */ 
2763 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  30 -  3F */ 
2764 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  40 -  4F */ 
2765 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  50 -  5F */ 
2766 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  60 -  6F */ 
2767 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
2768 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  20 -  2F */
2769 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  30 -  3F */
2770 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  40 -  4F */
2771 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  50 -  5F */
2772 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  60 -  6F */
2773         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  70 -  7F */
2774         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  80 -  8F */
2775         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  90 -  9F */
2776 @@ -734,13 +803,13 @@
2777         unsigned char *ds, *d;
2778         size_t d_len, ndx;
2779         const char *map = NULL;
2780 -       
2781 +
2782         if (!s || !b) return -1;
2783 -       
2784 +
2785         if (b->ptr[b->used - 1] != '\0') {
2786                 SEGFAULT();
2787         }
2788 -       
2789 +
2790         if (s_len == 0) return 0;
2791  
2792         switch(encoding) {
2793 @@ -760,12 +829,12 @@
2794                 map = encoded_chars_hex;
2795                 break;
2796         case ENCODING_UNSET:
2797 -               break;
2798 +               return buffer_append_string_len(b, s, s_len);
2799         }
2800  
2801         assert(map != NULL);
2802 -       
2803 -       /* count to-be-encoded-characters */
2804 +
2805 +       /* count to-be-encoded characters */
2806         for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
2807                 if (map[*ds]) {
2808                         switch(encoding) {
2809 @@ -787,9 +856,9 @@
2810                         d_len ++;
2811                 }
2812         }
2813 -       
2814 +
2815         buffer_prepare_append(b, d_len);
2816 -       
2817 +
2818         for (ds = (unsigned char *)s, d = (unsigned char *)b->ptr + b->used - 1, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
2819                 if (map[*ds]) {
2820                         switch(encoding) {
2821 @@ -820,16 +889,16 @@
2822                 }
2823         }
2824  
2825 -       /* terminate buffer and calculate new length */ 
2826 +       /* terminate buffer and calculate new length */
2827         b->ptr[b->used + d_len - 1] = '\0';
2828 -       
2829 +
2830         b->used += d_len;
2831  
2832         return 0;
2833  }
2834  
2835  
2836 -/* decodes url-special-chars inplace.
2837 +/* decodes url-special chars in-place.
2838   * replaces non-printable characters with '_'
2839   */
2840  
2841 @@ -854,10 +923,10 @@
2842                                 low = hex2int(*(src + 2));
2843                                 if (low != 0xFF) {
2844                                         high = (high << 4) | low;
2845 -                                       
2846 -                                       /* map control-characters out */        
2847 +
2848 +                                       /* map out control characters */
2849                                         if (high < 32 || high == 127) high = '_';
2850 -                                       
2851 +
2852                                         *dst = high;
2853                                         src += 2;
2854                                 }
2855 @@ -891,7 +960,7 @@
2856   * /abc/./xyz       gets  /abc/xyz
2857   * /abc//xyz        gets  /abc/xyz
2858   *
2859 - * NOTE: src and dest can point to the same buffer, in which case,
2860 + * NOTE: src and dest can point to the same buffer, in which case
2861   *       the operation is performed in-place.
2862   */
2863  
2864 @@ -979,7 +1048,7 @@
2865  
2866  int light_isxdigit(int c) {
2867         if (light_isdigit(c)) return 1;
2868 -       
2869 +
2870         c |= 32;
2871         return (c >= 'a' && c <= 'f');
2872  }
2873 @@ -993,31 +1062,56 @@
2874         return light_isdigit(c) || light_isalpha(c);
2875  }
2876  
2877 +#undef BUFFER_CTYPE_FUNC
2878 +#define BUFFER_CTYPE_FUNC(type) \
2879 +       int buffer_is##type(buffer *b) { \
2880 +               size_t i, len; \
2881 +               if (b->used < 2) return 0; \
2882 +               /* strlen */ \
2883 +               len = b->used - 1; \
2884 +               /* c-string only */ \
2885 +               if (b->ptr[len] != '\0') { \
2886 +                       return 0; \
2887 +               } \
2888 +               /* check on the whole string */ \
2889 +               for (i = 0; i < len; i ++) { \
2890 +                       if (!light_is##type(b->ptr[i])) { \
2891 +                               return 0; \
2892 +                       } \
2893 +               } \
2894 +               return 1; \
2895 +       }
2896 +
2897 +BUFFER_CTYPE_FUNC(digit)
2898 +BUFFER_CTYPE_FUNC(xdigit)
2899 +BUFFER_CTYPE_FUNC(alpha)
2900 +BUFFER_CTYPE_FUNC(alnum)
2901 +
2902  int buffer_to_lower(buffer *b) {
2903         char *c;
2904 -       
2905 +
2906         if (b->used == 0) return 0;
2907 -       
2908 +
2909         for (c = b->ptr; *c; c++) {
2910                 if (*c >= 'A' && *c <= 'Z') {
2911                         *c |= 32;
2912                 }
2913         }
2914 -       
2915 +
2916         return 0;
2917  }
2918  
2919  
2920  int buffer_to_upper(buffer *b) {
2921         char *c;
2922 -       
2923 +
2924         if (b->used == 0) return 0;
2925 -       
2926 +
2927         for (c = b->ptr; *c; c++) {
2928                 if (*c >= 'a' && *c <= 'z') {
2929                         *c &= ~32;
2930                 }
2931         }
2932 -       
2933 +
2934         return 0;
2935  }
2936 --- lighttpd-1.4.11/src/buffer.h        2006-01-13 00:00:45.000000000 +0200
2937 +++ lighttpd-1.4.12/src/buffer.h        2006-07-11 22:07:52.000000000 +0300
2938 @@ -12,27 +12,44 @@
2939  
2940  typedef struct {
2941         char *ptr;
2942 -       
2943 +
2944         size_t used;
2945         size_t size;
2946  } buffer;
2947  
2948 +
2949 +typedef void (*buffer_ptr_free_t)(void *p);
2950 +
2951 +typedef struct {
2952 +       void **ptr;
2953 +       size_t size;
2954 +       size_t used;
2955 +       buffer_ptr_free_t free;
2956 +} buffer_ptr;
2957 +
2958  typedef struct {
2959         buffer **ptr;
2960 -       
2961 +
2962         size_t used;
2963         size_t size;
2964  } buffer_array;
2965  
2966  typedef struct {
2967         char *ptr;
2968 -       
2969 -       size_t offset; /* input-pointer */
2970 -       
2971 -       size_t used;   /* output-pointer */
2972 +
2973 +       size_t offset; /* input pointer */
2974 +
2975 +       size_t used;   /* output pointer */
2976         size_t size;
2977  } read_buffer;
2978  
2979 +buffer_ptr *buffer_ptr_init(buffer_ptr_free_t freer);
2980 +void buffer_ptr_free(buffer_ptr *b);
2981 +void buffer_ptr_clear(buffer_ptr *b);
2982 +void buffer_ptr_append(buffer_ptr *b, void *item);
2983 +void *buffer_ptr_pop(buffer_ptr *b);
2984 +void *buffer_ptr_top(buffer_ptr *b);
2985 +
2986  buffer_array* buffer_array_init(void);
2987  void buffer_array_free(buffer_array *b);
2988  void buffer_array_reset(buffer_array *b);
2989 @@ -43,7 +60,7 @@
2990  buffer* buffer_init_string(const char *str);
2991  void buffer_free(buffer *b);
2992  void buffer_reset(buffer *b);
2993 -       
2994 +
2995  int buffer_prepare_copy(buffer *b, size_t size);
2996  int buffer_prepare_append(buffer *b, size_t size);
2997  
2998 @@ -85,9 +102,9 @@
2999  
3000  typedef enum {
3001         ENCODING_UNSET,
3002 -       ENCODING_REL_URI, /* for coding a rel-uri (/with space/and%percent) nicely as part of a href */
3003 -       ENCODING_REL_URI_PART, /* same as ENC_REL_URL plus coding / too as %2F */
3004 -       ENCODING_HTML,    /* & becomes &amp; and so on */
3005 +       ENCODING_REL_URI, /* for coding a rel-uri (/with space/and%percent) nicely as part of an href */
3006 +       ENCODING_REL_URI_PART, /* same as ENC_REL_URL plus encoding "/" as "%2F" */
3007 +       ENCODING_HTML,    /* "&" becomes "&amp;" and so on */
3008         ENCODING_MINIMAL_XML, /* minimal encoding for xml */
3009         ENCODING_HEX      /* encode string as hex */
3010  } buffer_encoding_t;
3011 @@ -111,19 +128,21 @@
3012  int light_isalpha(int c);
3013  int light_isalnum(int c);
3014  
3015 +#define BUFFER_CTYPE_FUNC(type) int buffer_is##type(buffer *b);
3016 +BUFFER_CTYPE_FUNC(digit)
3017 +BUFFER_CTYPE_FUNC(xdigit)
3018 +BUFFER_CTYPE_FUNC(alpha)
3019 +BUFFER_CTYPE_FUNC(alnum)
3020 +
3021  #define BUFFER_APPEND_STRING_CONST(x, y) \
3022         buffer_append_string_len(x, y, sizeof(y) - 1)
3023  
3024  #define BUFFER_COPY_STRING_CONST(x, y) \
3025         buffer_copy_string_len(x, y, sizeof(y) - 1)
3026  
3027 -#define BUFFER_APPEND_SLASH(x) \
3028 -       if (x->used > 1 && x->ptr[x->used - 2] != '/') { BUFFER_APPEND_STRING_CONST(x, "/"); }
3029 -
3030  #define CONST_STR_LEN(x) x, x ? sizeof(x) - 1 : 0
3031  #define CONST_BUF_LEN(x) x->ptr, x->used ? x->used - 1 : 0
3032  
3033 -
3034  #define SEGFAULT() do { fprintf(stderr, "%s.%d: aborted\n", __FILE__, __LINE__); abort(); } while(0)
3035  #define UNUSED(x) ( (void)(x) )
3036  
3037 --- lighttpd-1.4.11/src/chunk.c 2005-11-18 15:18:19.000000000 +0200
3038 +++ lighttpd-1.4.12/src/chunk.c 2006-07-11 22:07:51.000000000 +0300
3039 @@ -1,16 +1,14 @@
3040  /**
3041   * the network chunk-API
3042 - * 
3043 - * 
3044 + *
3045 + *
3046   */
3047  
3048  #include <sys/types.h>
3049  #include <sys/stat.h>
3050 -#include <sys/mman.h>
3051  
3052  #include <stdlib.h>
3053  #include <fcntl.h>
3054 -#include <unistd.h>
3055  
3056  #include <stdio.h>
3057  #include <errno.h>
3058 @@ -18,36 +16,39 @@
3059  
3060  #include "chunk.h"
3061  
3062 +#include "sys-mmap.h"
3063 +#include "sys-files.h"
3064 +
3065  chunkqueue *chunkqueue_init(void) {
3066         chunkqueue *cq;
3067 -       
3068 +
3069         cq = calloc(1, sizeof(*cq));
3070 -       
3071 +
3072         cq->first = NULL;
3073         cq->last = NULL;
3074 -       
3075 +
3076         cq->unused = NULL;
3077 -       
3078 +
3079         return cq;
3080  }
3081  
3082  static chunk *chunk_init(void) {
3083         chunk *c;
3084 -       
3085 +
3086         c = calloc(1, sizeof(*c));
3087 -       
3088 +
3089         c->mem = buffer_init();
3090         c->file.name = buffer_init();
3091         c->file.fd = -1;
3092         c->file.mmap.start = MAP_FAILED;
3093         c->next = NULL;
3094 -       
3095 +
3096         return c;
3097  }
3098  
3099  static void chunk_free(chunk *c) {
3100         if (!c) return;
3101 -       
3102 +
3103         buffer_free(c->mem);
3104         buffer_free(c->file.name);
3105  
3106 @@ -56,13 +57,13 @@
3107  
3108  static void chunk_reset(chunk *c) {
3109         if (!c) return;
3110 -       
3111 +
3112         buffer_reset(c->mem);
3113  
3114         if (c->file.is_temp && !buffer_is_empty(c->file.name)) {
3115                 unlink(c->file.name->ptr);
3116         }
3117 -       
3118 +
3119         buffer_reset(c->file.name);
3120  
3121         if (c->file.fd != -1) {
3122 @@ -78,28 +79,28 @@
3123  
3124  void chunkqueue_free(chunkqueue *cq) {
3125         chunk *c, *pc;
3126 -       
3127 +
3128         if (!cq) return;
3129 -       
3130 +
3131         for (c = cq->first; c; ) {
3132                 pc = c;
3133                 c = c->next;
3134                 chunk_free(pc);
3135         }
3136 -       
3137 +
3138         for (c = cq->unused; c; ) {
3139                 pc = c;
3140                 c = c->next;
3141                 chunk_free(pc);
3142         }
3143 -       
3144 +
3145         free(cq);
3146  }
3147  
3148  static chunk *chunkqueue_get_unused_chunk(chunkqueue *cq) {
3149         chunk *c;
3150 -       
3151 -       /* check if we have a unused chunk */
3152 +
3153 +       /* check if we have an unused chunk */
3154         if (!cq->unused) {
3155                 c = chunk_init();
3156         } else {
3157 @@ -109,18 +110,18 @@
3158                 c->next = NULL;
3159                 cq->unused_chunks--;
3160         }
3161 -       
3162 +
3163         return c;
3164  }
3165  
3166  static int chunkqueue_prepend_chunk(chunkqueue *cq, chunk *c) {
3167         c->next = cq->first;
3168         cq->first = c;
3169 -       
3170 +
3171         if (cq->last == NULL) {
3172                 cq->last = c;
3173         }
3174 -       
3175 +
3176         return 0;
3177  }
3178  
3179 @@ -129,19 +130,19 @@
3180                 cq->last->next = c;
3181         }
3182         cq->last = c;
3183 -       
3184 +
3185         if (cq->first == NULL) {
3186                 cq->first = c;
3187         }
3188 -       
3189 +
3190         return 0;
3191  }
3192  
3193  void chunkqueue_reset(chunkqueue *cq) {
3194         chunk *c;
3195         /* move everything to the unused queue */
3196 -       
3197 -       /* mark all read written */ 
3198 +
3199 +       /* mark all read written */
3200         for (c = cq->first; c; c = c->next) {
3201                 switch(c->type) {
3202                 case MEM_CHUNK:
3203 @@ -150,7 +151,7 @@
3204                 case FILE_CHUNK:
3205                         c->offset = c->file.length;
3206                         break;
3207 -               default: 
3208 +               default:
3209                         break;
3210                 }
3211         }
3212 @@ -162,93 +163,93 @@
3213  
3214  int chunkqueue_append_file(chunkqueue *cq, buffer *fn, off_t offset, off_t len) {
3215         chunk *c;
3216 -       
3217 +
3218         if (len == 0) return 0;
3219 -       
3220 +
3221         c = chunkqueue_get_unused_chunk(cq);
3222 -       
3223 +
3224         c->type = FILE_CHUNK;
3225 -       
3226 +
3227         buffer_copy_string_buffer(c->file.name, fn);
3228         c->file.start = offset;
3229         c->file.length = len;
3230         c->offset = 0;
3231 -       
3232 +
3233         chunkqueue_append_chunk(cq, c);
3234 -       
3235 +
3236         return 0;
3237  }
3238  
3239  int chunkqueue_append_buffer(chunkqueue *cq, buffer *mem) {
3240         chunk *c;
3241 -       
3242 +
3243         if (mem->used == 0) return 0;
3244 -       
3245 +
3246         c = chunkqueue_get_unused_chunk(cq);
3247         c->type = MEM_CHUNK;
3248         c->offset = 0;
3249         buffer_copy_string_buffer(c->mem, mem);
3250 -       
3251 +
3252         chunkqueue_append_chunk(cq, c);
3253 -       
3254 +
3255         return 0;
3256  }
3257  
3258  int chunkqueue_prepend_buffer(chunkqueue *cq, buffer *mem) {
3259         chunk *c;
3260 -       
3261 +
3262         if (mem->used == 0) return 0;
3263 -       
3264 +
3265         c = chunkqueue_get_unused_chunk(cq);
3266         c->type = MEM_CHUNK;
3267         c->offset = 0;
3268         buffer_copy_string_buffer(c->mem, mem);
3269 -       
3270 +
3271         chunkqueue_prepend_chunk(cq, c);
3272 -       
3273 +
3274         return 0;
3275  }
3276  
3277  int chunkqueue_append_mem(chunkqueue *cq, const char * mem, size_t len) {
3278         chunk *c;
3279 -       
3280 +
3281         if (len == 0) return 0;
3282 -       
3283 +
3284         c = chunkqueue_get_unused_chunk(cq);
3285         c->type = MEM_CHUNK;
3286         c->offset = 0;
3287         buffer_copy_string_len(c->mem, mem, len - 1);
3288 -       
3289 +
3290         chunkqueue_append_chunk(cq, c);
3291 -       
3292 +
3293         return 0;
3294  }
3295  
3296  buffer * chunkqueue_get_prepend_buffer(chunkqueue *cq) {
3297         chunk *c;
3298 -       
3299 +
3300         c = chunkqueue_get_unused_chunk(cq);
3301 -       
3302 +
3303         c->type = MEM_CHUNK;
3304         c->offset = 0;
3305         buffer_reset(c->mem);
3306 -       
3307 +
3308         chunkqueue_prepend_chunk(cq, c);
3309 -       
3310 +
3311         return c->mem;
3312  }
3313  
3314  buffer *chunkqueue_get_append_buffer(chunkqueue *cq) {
3315         chunk *c;
3316 -       
3317 +
3318         c = chunkqueue_get_unused_chunk(cq);
3319 -       
3320 +
3321         c->type = MEM_CHUNK;
3322         c->offset = 0;
3323         buffer_reset(c->mem);
3324 -       
3325 +
3326         chunkqueue_append_chunk(cq, c);
3327 -       
3328 +
3329         return c->mem;
3330  }
3331  
3332 @@ -263,7 +264,7 @@
3333  chunk *chunkqueue_get_append_tempfile(chunkqueue *cq) {
3334         chunk *c;
3335         buffer *template = buffer_init_string("/var/tmp/lighttpd-upload-XXXXXX");
3336 -       
3337 +
3338         c = chunkqueue_get_unused_chunk(cq);
3339  
3340         c->type = FILE_CHUNK;
3341 @@ -273,12 +274,12 @@
3342                 size_t i;
3343  
3344                 /* we have several tempdirs, only if all of them fail we jump out */
3345 -               
3346 +
3347                 for (i = 0; i < cq->tempdirs->used; i++) {
3348                         data_string *ds = (data_string *)cq->tempdirs->data[i];
3349  
3350                         buffer_copy_string_buffer(template, ds->value);
3351 -                       BUFFER_APPEND_SLASH(template);
3352 +                       PATHNAME_APPEND_SLASH(template);
3353                         BUFFER_APPEND_STRING_CONST(template, "lighttpd-upload-XXXXXX");
3354  
3355                         if (-1 != (c->file.fd = mkstemp(template->ptr))) {
3356 @@ -300,7 +301,7 @@
3357         chunkqueue_append_chunk(cq, c);
3358  
3359         buffer_free(template);
3360 -       
3361 +
3362         return c;
3363  }
3364  
3365 @@ -308,7 +309,7 @@
3366  off_t chunkqueue_length(chunkqueue *cq) {
3367         off_t len = 0;
3368         chunk *c;
3369 -       
3370 +
3371         for (c = cq->first; c; c = c->next) {
3372                 switch (c->type) {
3373                 case MEM_CHUNK:
3374 @@ -321,14 +322,14 @@
3375                         break;
3376                 }
3377         }
3378 -       
3379 +
3380         return len;
3381  }
3382  
3383  off_t chunkqueue_written(chunkqueue *cq) {
3384         off_t len = 0;
3385         chunk *c;
3386 -       
3387 +
3388         for (c = cq->first; c; c = c->next) {
3389                 switch (c->type) {
3390                 case MEM_CHUNK:
3391 @@ -339,7 +340,7 @@
3392                         break;
3393                 }
3394         }
3395 -       
3396 +
3397         return len;
3398  }
3399  
3400 @@ -358,9 +359,9 @@
3401                         if (c->offset == (off_t)c->mem->used - 1) is_finished = 1;
3402                         break;
3403                 case FILE_CHUNK:
3404 -                       if (c->offset == c->file.length) is_finished = 1; 
3405 +                       if (c->offset == c->file.length) is_finished = 1;
3406                         break;
3407 -               default: 
3408 +               default:
3409                         break;
3410                 }
3411  
3412 --- lighttpd-1.4.11/src/chunk.h 2005-11-01 09:32:21.000000000 +0200
3413 +++ lighttpd-1.4.12/src/chunk.h 2006-07-11 22:07:51.000000000 +0300
3414 @@ -6,7 +6,7 @@
3415  
3416  typedef struct chunk {
3417         enum { UNUSED_CHUNK, MEM_CHUNK, FILE_CHUNK } type;
3418 -       
3419 +
3420         buffer *mem; /* either the storage of the mem-chunk or the read-ahead buffer */
3421  
3422         struct {
3423 @@ -16,28 +16,28 @@
3424                 off_t  length; /* octets to send from the starting offset */
3425  
3426                 int    fd;
3427 -               struct { 
3428 +               struct {
3429                         char   *start; /* the start pointer of the mmap'ed area */
3430                         size_t length; /* size of the mmap'ed area */
3431 -                       off_t  offset; /* start is <n> octet away from the start of the file */
3432 +                       off_t  offset; /* start is <n> octets away from the start of the file */
3433                 } mmap;
3434  
3435 -               int is_temp; /* file is temporary and will be deleted if on cleanup */
3436 +               int is_temp; /* file is temporary and will be deleted on cleanup */
3437         } file;
3438 -       
3439 -       off_t  offset; /* octets sent from this chunk 
3440 -                         the size of the chunk is either 
3441 +
3442 +       off_t  offset; /* octets sent from this chunk
3443 +                         the size of the chunk is either
3444                           - mem-chunk: mem->used - 1
3445                           - file-chunk: file.length
3446                         */
3447 -       
3448 +
3449         struct chunk *next;
3450  } chunk;
3451  
3452  typedef struct {
3453         chunk *first;
3454         chunk *last;
3455 -       
3456 +
3457         chunk *unused;
3458         size_t unused_chunks;
3459  
3460 --- lighttpd-1.4.11/src/configfile-glue.c       2006-03-03 20:14:56.000000000 +0200
3461 +++ lighttpd-1.4.12/src/configfile-glue.c       2006-07-11 22:07:51.000000000 +0300
3462 @@ -1,4 +1,5 @@
3463  #include <string.h>
3464 +#include <ctype.h>
3465  
3466  #include "base.h"
3467  #include "buffer.h"
3468 @@ -11,10 +12,10 @@
3469   * are the external interface of lighttpd. The functions
3470   * are used by the server itself and the plugins.
3471   *
3472 - * The main-goal is to have a small library in the end 
3473 - * which is linked against both and which will define 
3474 + * The main-goal is to have a small library in the end
3475 + * which is linked against both and which will define
3476   * the interface itself in the end.
3477 - * 
3478 + *
3479   */
3480  
3481  
3482 @@ -24,56 +25,60 @@
3483  int config_insert_values_internal(server *srv, array *ca, const config_values_t cv[]) {
3484         size_t i;
3485         data_unset *du;
3486 -       
3487 +
3488         for (i = 0; cv[i].key; i++) {
3489 -               
3490 +
3491                 if (NULL == (du = array_get_element(ca, cv[i].key))) {
3492                         /* no found */
3493 -                       
3494 +
3495                         continue;
3496                 }
3497 -               
3498 +
3499                 switch (cv[i].type) {
3500                 case T_CONFIG_ARRAY:
3501                         if (du->type == TYPE_ARRAY) {
3502                                 size_t j;
3503                                 data_array *da = (data_array *)du;
3504 -                               
3505 +
3506                                 for (j = 0; j < da->value->used; j++) {
3507                                         if (da->value->data[j]->type == TYPE_STRING) {
3508                                                 data_string *ds = data_string_init();
3509 -                                               
3510 +
3511                                                 buffer_copy_string_buffer(ds->value, ((data_string *)(da->value->data[j]))->value);
3512                                                 if (!da->is_index_key) {
3513                                                         /* the id's were generated automaticly, as we copy now we might have to renumber them
3514 -                                                        * this is used to prepend server.modules by mod_indexfiles as it has to be loaded 
3515 +                                                        * this is used to prepend server.modules by mod_indexfiles as it has to be loaded
3516                                                          * before mod_fastcgi and friends */
3517                                                         buffer_copy_string_buffer(ds->key, ((data_string *)(da->value->data[j]))->key);
3518                                                 }
3519 -                                               
3520 +
3521                                                 array_insert_unique(cv[i].destination, (data_unset *)ds);
3522                                         } else {
3523 -                                               log_error_write(srv, __FILE__, __LINE__, "sssd", 
3524 -                                                               "the key of and array can only be a string or a integer, variable:", 
3525 -                                                               cv[i].key, "type:", da->value->data[j]->type); 
3526 -                                               
3527 +                                               log_error_write(srv, __FILE__, __LINE__, "sssd",
3528 +                                                               "the key of and array can only be a string or a integer, variable:",
3529 +                                                               cv[i].key, "type:", da->value->data[j]->type);
3530 +
3531                                                 return -1;
3532                                         }
3533                                 }
3534                         } else {
3535                                 log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", cv[i].key, "array of strings");
3536 -                               
3537 +
3538                                 return -1;
3539                         }
3540                         break;
3541                 case T_CONFIG_STRING:
3542                         if (du->type == TYPE_STRING) {
3543                                 data_string *ds = (data_string *)du;
3544 -                               
3545 +
3546                                 buffer_copy_string_buffer(cv[i].destination, ds->value);
3547 +                       } else if (du->type == TYPE_INTEGER) {
3548 +                               data_integer *di = (data_integer *)du;
3549 +
3550 +                               buffer_copy_long(cv[i].destination, di->value);
3551                         } else {
3552                                 log_error_write(srv, __FILE__, __LINE__, "ssss", "unexpected type for key: ", cv[i].key, "(string)", "\"...\"");
3553 -                               
3554 +
3555                                 return -1;
3556                         }
3557                         break;
3558 @@ -81,15 +86,20 @@
3559                         switch(du->type) {
3560                         case TYPE_INTEGER: {
3561                                 data_integer *di = (data_integer *)du;
3562 -                               
3563 +
3564                                 *((unsigned short *)(cv[i].destination)) = di->value;
3565                                 break;
3566                         }
3567                         case TYPE_STRING: {
3568                                 data_string *ds = (data_string *)du;
3569 -                                       
3570 +
3571 +                               if (buffer_isdigit(ds->value)) {
3572 +                                       *((unsigned short *)(cv[i].destination)) = strtol(ds->value->ptr, NULL, 10);
3573 +                                       break;
3574 +                               }
3575 +
3576                                 log_error_write(srv, __FILE__, __LINE__, "ssb", "get a string but expected a short:", cv[i].key, ds->value);
3577 -                               
3578 +
3579                                 return -1;
3580                         }
3581                         default:
3582 @@ -100,19 +110,19 @@
3583                 case T_CONFIG_BOOLEAN:
3584                         if (du->type == TYPE_STRING) {
3585                                 data_string *ds = (data_string *)du;
3586 -                               
3587 +
3588                                 if (buffer_is_equal_string(ds->value, CONST_STR_LEN("enable"))) {
3589                                         *((unsigned short *)(cv[i].destination)) = 1;
3590                                 } else if (buffer_is_equal_string(ds->value, CONST_STR_LEN("disable"))) {
3591                                         *((unsigned short *)(cv[i].destination)) = 0;
3592                                 } else {
3593                                         log_error_write(srv, __FILE__, __LINE__, "ssbs", "ERROR: unexpected value for key:", cv[i].key, ds->value, "(enable|disable)");
3594 -                                               
3595 +
3596                                         return -1;
3597                                 }
3598                         } else {
3599                                 log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: unexpected type for key:", cv[i].key, "(string)", "\"(enable|disable)\"");
3600 -                               
3601 +
3602                                 return -1;
3603                         }
3604                         break;
3605 @@ -121,9 +131,9 @@
3606                         break;
3607                 case T_CONFIG_DEPRECATED:
3608                         log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found deprecated key:", cv[i].key, "-", (char *)(cv[i].destination));
3609 -                       
3610 +
3611                         srv->config_deprecated = 1;
3612 -                       
3613 +
3614                         break;
3615                 }
3616         }
3617 @@ -133,25 +143,25 @@
3618  int config_insert_values_global(server *srv, array *ca, const config_values_t cv[]) {
3619         size_t i;
3620         data_unset *du;
3621 -       
3622 +
3623         for (i = 0; cv[i].key; i++) {
3624                 data_string *touched;
3625 -               
3626 +
3627                 if (NULL == (du = array_get_element(ca, cv[i].key))) {
3628                         /* no found */
3629 -                       
3630 +
3631                         continue;
3632                 }
3633 -               
3634 +
3635                 /* touched */
3636                 touched = data_string_init();
3637 -               
3638 +
3639                 buffer_copy_string(touched->value, "");
3640                 buffer_copy_string_buffer(touched->key, du->key);
3641 -               
3642 +
3643                 array_insert_unique(srv->config_touched, (data_unset *)touched);
3644         }
3645 -       
3646 +
3647         return config_insert_values_internal(srv, ca, cv);
3648  }
3649  
3650 @@ -191,25 +201,25 @@
3651         }
3652  
3653         /* pass the rules */
3654 -       
3655 +
3656         switch (dc->comp) {
3657         case COMP_HTTP_HOST: {
3658                 char *ck_colon = NULL, *val_colon = NULL;
3659 -               
3660 +
3661                 if (!buffer_is_empty(con->uri.authority)) {
3662 -               
3663 -                       /* 
3664 +
3665 +                       /*
3666                          * append server-port to the HTTP_POST if necessary
3667                          */
3668 -                       
3669 +
3670                         l = con->uri.authority;
3671 -                       
3672 +
3673                         switch(dc->cond) {
3674                         case CONFIG_COND_NE:
3675                         case CONFIG_COND_EQ:
3676                                 ck_colon = strchr(dc->string->ptr, ':');
3677                                 val_colon = strchr(l->ptr, ':');
3678 -                               
3679 +
3680                                 if (ck_colon == val_colon) {
3681                                         /* nothing to do with it */
3682                                         break;
3683 @@ -230,21 +240,21 @@
3684                                 break;
3685                         }
3686                 } else {
3687 -                       l = NULL;
3688 +                       l = srv->empty_string;
3689                 }
3690                 break;
3691         }
3692         case COMP_HTTP_REMOTEIP: {
3693                 char *nm_slash;
3694 -               /* handle remoteip limitations 
3695 -                * 
3696 +               /* handle remoteip limitations
3697 +                *
3698                  * "10.0.0.1" is provided for all comparisions
3699 -                * 
3700 +                *
3701                  * only for == and != we support
3702 -                * 
3703 +                *
3704                  * "10.0.0.1/24"
3705                  */
3706 -               
3707 +
3708                 if ((dc->cond == CONFIG_COND_EQ ||
3709                      dc->cond == CONFIG_COND_NE) &&
3710                     (con->dst_addr.plain.sa_family == AF_INET) &&
3711 @@ -253,41 +263,48 @@
3712                         long nm;
3713                         char *err;
3714                         struct in_addr val_inp;
3715 -                       
3716 +
3717 +                       if (con->conf.log_condition_handling) {
3718 +                               l = srv->empty_string;
3719 +
3720 +                               log_error_write(srv, __FILE__, __LINE__,  "bsbsb", dc->comp_key,
3721 +                                               "(", l, ") compare to", dc->string);
3722 +                       }
3723 +
3724                         if (*(nm_slash+1) == '\0') {
3725                                 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", dc->string);
3726 -                                       
3727 +
3728                                 return COND_RESULT_FALSE;
3729                         }
3730 -                       
3731 +
3732                         nm_bits = strtol(nm_slash + 1, &err, 10);
3733 -                       
3734 +
3735                         if (*err) {
3736                                 log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", dc->string, *err);
3737 -                               
3738 +
3739                                 return COND_RESULT_FALSE;
3740                         }
3741 -                       
3742 +
3743                         /* take IP convert to the native */
3744                         buffer_copy_string_len(srv->cond_check_buf, dc->string->ptr, nm_slash - dc->string->ptr);
3745 -#ifdef __WIN32                 
3746 +#ifdef _WIN32
3747                         if (INADDR_NONE == (val_inp.s_addr = inet_addr(srv->cond_check_buf->ptr))) {
3748                                 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
3749 -                               
3750 +
3751                                 return COND_RESULT_FALSE;
3752                         }
3753  
3754  #else
3755                         if (0 == inet_aton(srv->cond_check_buf->ptr, &val_inp)) {
3756                                 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
3757 -                               
3758 +
3759                                 return COND_RESULT_FALSE;
3760                         }
3761  #endif
3762 -                       
3763 +
3764                         /* build netmask */
3765                         nm = htonl(~((1 << (32 - nm_bits)) - 1));
3766 -                       
3767 +
3768                         if ((val_inp.s_addr & nm) == (con->dst_addr.ipv4.sin_addr.s_addr & nm)) {
3769                                 return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE;
3770                         } else {
3771 @@ -308,7 +325,7 @@
3772  
3773         case COMP_HTTP_REFERER: {
3774                 data_string *ds;
3775 -               
3776 +
3777                 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Referer"))) {
3778                         l = ds->value;
3779                 } else {
3780 @@ -338,7 +355,7 @@
3781         default:
3782                 return COND_RESULT_FALSE;
3783         }
3784 -       
3785 +
3786         if (NULL == l) {
3787                 if (con->conf.log_condition_handling) {
3788                         log_error_write(srv, __FILE__, __LINE__,  "bsbs", dc->comp_key,
3789 @@ -346,10 +363,10 @@
3790                 }
3791                 return COND_RESULT_FALSE;
3792         }
3793 -       
3794 +
3795         if (con->conf.log_condition_handling) {
3796                 log_error_write(srv, __FILE__, __LINE__,  "bsbsb", dc->comp_key,
3797 -                               "(", l, ") compare to ", dc->string);
3798 +                               "(", l, ") compare to", dc->string);
3799         }
3800         switch(dc->cond) {
3801         case CONFIG_COND_NE:
3802 @@ -365,13 +382,13 @@
3803         case CONFIG_COND_MATCH: {
3804                 cond_cache_t *cache = &con->cond_cache[dc->context_ndx];
3805                 int n;
3806 -               
3807 +
3808  #ifndef elementsof
3809  #define elementsof(x) (sizeof(x) / sizeof(x[0]))
3810  #endif
3811                 n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0,
3812                                 cache->matches, elementsof(cache->matches));
3813 -               
3814 +
3815                 cache->patterncount = n;
3816                 if (n > 0) {
3817                         cache->comp_value = l;
3818 @@ -387,7 +404,7 @@
3819                 /* no way */
3820                 break;
3821         }
3822 -       
3823 +
3824         return COND_RESULT_FALSE;
3825  }
3826  
3827 @@ -395,6 +412,9 @@
3828         cond_cache_t *caches = con->cond_cache;
3829  
3830         if (COND_RESULT_UNSET == caches[dc->context_ndx].result) {
3831 +               if (con->conf.log_condition_handling) {
3832 +                       log_error_write(srv, __FILE__, __LINE__,  "sds",  "=== start of", dc->context_ndx, "condition block ===");
3833 +               }
3834                 if (COND_RESULT_TRUE == (caches[dc->context_ndx].result = config_check_cond_nocache(srv, con, dc))) {
3835                         if (dc->next) {
3836                                 data_config *c;
3837 @@ -409,11 +429,11 @@
3838                 }
3839                 if (con->conf.log_condition_handling) {
3840                         log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,
3841 -                                       "(uncached) result:",
3842 +                                       "result:",
3843                                         caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false");
3844                 }
3845         } else {
3846 -               if (con->conf.log_condition_handling) {
3847 +               if (con->conf.log_condition_cache_handling) {
3848                         log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,
3849                                         "(cached) result:",
3850                                         caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false");
3851 @@ -423,9 +443,6 @@
3852  }
3853  
3854  int config_check_cond(server *srv, connection *con, data_config *dc) {
3855 -       if (con->conf.log_condition_handling) {
3856 -               log_error_write(srv, __FILE__, __LINE__,  "s",  "=== start of condition block ===");
3857 -       }
3858         return (config_check_cond_cached(srv, con, dc) == COND_RESULT_TRUE);
3859  }
3860  
3861 @@ -443,3 +460,85 @@
3862         return 1;
3863  }
3864  
3865 +/* return <0 on error
3866 + * return 0-x if matched (and replaced)
3867 + */
3868 +int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result)
3869 +{
3870 +#ifdef HAVE_PCRE_H
3871 +       pcre *match;
3872 +       pcre_extra *extra;
3873 +       const char *pattern;
3874 +       size_t pattern_len;
3875 +       int n;
3876 +       size_t i;
3877 +       pcre_keyvalue *kv;
3878 +# define N 10
3879 +       int ovec[N * 3];
3880 +
3881 +       for (i = 0; i < kvb->used; i++) {
3882 +               kv = kvb->kv[i];
3883 +
3884 +               match       = kv->key;
3885 +               extra       = kv->key_extra;
3886 +               pattern     = kv->value->ptr;
3887 +               pattern_len = kv->value->used - 1;
3888 +
3889 +               if ((n = pcre_exec(match, extra, match_buf->ptr, match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
3890 +                       if (n != PCRE_ERROR_NOMATCH) {
3891 +                               return n;
3892 +                       }
3893 +               } else {
3894 +                       const char **list;
3895 +                       size_t start, end;
3896 +                       size_t k;
3897 +
3898 +                       /* it matched */
3899 +                       pcre_get_substring_list(match_buf->ptr, ovec, n, &list);
3900 +
3901 +                       /* search for $[0-9] */
3902 +
3903 +                       buffer_reset(result);
3904 +
3905 +                       start = 0; end = pattern_len;
3906 +                       for (k = 0; k < pattern_len; k++) {
3907 +                               if ((pattern[k] == '$' || pattern[k] == '%') &&
3908 +                                   isdigit((unsigned char)pattern[k + 1])) {
3909 +                                       /* got one */
3910 +
3911 +                                       size_t num = pattern[k + 1] - '0';
3912 +
3913 +                                       end = k;
3914 +
3915 +                                       buffer_append_string_len(result, pattern + start, end - start);
3916 +
3917 +                                       if (pattern[k] == '$') {
3918 +                                               /* n is always > 0 */
3919 +                                               if (num < (size_t)n) {
3920 +                                                       buffer_append_string(result, list[num]);
3921 +                                               }
3922 +                                       } else {
3923 +                                               config_append_cond_match_buffer(con, context, result, num);
3924 +                                       }
3925 +
3926 +                                       k++;
3927 +                                       start = k + 1;
3928 +                               }
3929 +                       }
3930 +
3931 +                       buffer_append_string_len(result, pattern + start, pattern_len - start);
3932 +
3933 +                       pcre_free(list);
3934 +
3935 +                       return i;
3936 +               }
3937 +       }
3938 +
3939 +       return PCRE_ERROR_NOMATCH;
3940 +#undef N
3941 +#else
3942 +       UNUSED(kvb);
3943 +       return -2;
3944 +#endif
3945 +}
3946 +
3947 --- lighttpd-1.4.11/src/configfile.c    2006-02-15 14:26:42.000000000 +0200
3948 +++ lighttpd-1.4.12/src/configfile.c    2006-07-11 22:07:51.000000000 +0300
3949 @@ -2,7 +2,6 @@
3950  
3951  #include <stdlib.h>
3952  #include <fcntl.h>
3953 -#include <unistd.h>
3954  #include <errno.h>
3955  #include <string.h>
3956  #include <stdio.h>
3957 @@ -13,21 +12,23 @@
3958  #include "log.h"
3959  #include "stream.h"
3960  #include "plugin.h"
3961 -#ifdef USE_LICENSE
3962 -#include "license.h"
3963 -#endif
3964 -
3965  #include "configparser.h"
3966  #include "configfile.h"
3967  #include "proc_open.h"
3968  
3969 +#include "sys-files.h"
3970 +
3971 +#ifndef PATH_MAX
3972 +/* win32 */
3973 +#define PATH_MAX 64
3974 +#endif
3975  
3976  static int config_insert(server *srv) {
3977         size_t i;
3978         int ret = 0;
3979         buffer *stat_cache_string;
3980 -       
3981 -       config_values_t cv[] = { 
3982 +
3983 +       config_values_t cv[] = {
3984                 { "server.bind",                 NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 0 */
3985                 { "server.errorlog",             NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 1 */
3986                 { "server.errorfile-prefix",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 2 */
3987 @@ -38,7 +39,7 @@
3988                 { "server.tag",                  NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },  /* 7 */
3989                 { "server.use-ipv6",             NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
3990                 { "server.modules",              NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_SERVER },       /* 9 */
3991 -               
3992 +
3993                 { "server.event-handler",        NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 10 */
3994                 { "server.pid-file",             NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 11 */
3995                 { "server.max-request-size",     NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },   /* 12 */
3996 @@ -49,7 +50,7 @@
3997                 { "server.max-keep-alive-requests", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 17 */
3998                 { "server.name",                 NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },  /* 18 */
3999                 { "server.max-keep-alive-idle",  NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },   /* 19 */
4000 -               
4001 +
4002                 { "server.max-read-idle",        NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },   /* 20 */
4003                 { "server.max-write-idle",       NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },   /* 21 */
4004                 { "server.error-handler-404",    NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },  /* 22 */
4005 @@ -60,19 +61,19 @@
4006                 { "mimetype.use-xattr",          NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 27 */
4007                 { "mimetype.assign",             NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },   /* 28 */
4008                 { "ssl.pemfile",                 NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 29 */
4009 -               
4010 +
4011                 { "ssl.engine",                  NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 30 */
4012 -               
4013 +
4014                 { "debug.log-file-not-found",    NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 31 */
4015                 { "debug.log-request-handling",  NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 32 */
4016                 { "debug.log-response-header",   NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 33 */
4017                 { "debug.log-request-header",    NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 34 */
4018 -               
4019 +
4020                 { "server.protocol-http11",      NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 35 */
4021                 { "debug.log-request-header-on-error", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 36 */
4022                 { "debug.log-state-handling",    NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 37 */
4023                 { "ssl.ca-file",                 NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 38 */
4024 -               
4025 +
4026                 { "server.errorlog-use-syslog",  NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 39 */
4027                 { "server.range-requests",       NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 40 */
4028                 { "server.stat-cache-engine",    NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },  /* 41 */
4029 @@ -80,7 +81,8 @@
4030                 { "server.network-backend",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },  /* 43 */
4031                 { "server.upload-dirs",          NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },   /* 44 */
4032                 { "server.core-files",           NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 45 */
4033 -               
4034 +               { "debug.log-condition-cache-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },    /* 46 */
4035 +
4036                 { "server.host",                 "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
4037                 { "server.docroot",              "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
4038                 { "server.virtual-root",         "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
4039 @@ -90,11 +92,11 @@
4040                 { "server.groupid",              "use server.groupname instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
4041                 { "server.use-keep-alive",       "use server.max-keep-alive-requests = 0 instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
4042                 { "server.force-lower-case-files",       "use server.force-lowercase-filenames instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
4043 -               
4044 +
4045                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
4046         };
4047  
4048 -       
4049 +
4050         /* 0 */
4051         cv[0].destination = srv->srvconf.bindhost;
4052         cv[1].destination = srv->srvconf.errorlog_file;
4053 @@ -102,33 +104,33 @@
4054         cv[4].destination = srv->srvconf.username;
4055         cv[5].destination = srv->srvconf.groupname;
4056         cv[6].destination = &(srv->srvconf.port);
4057 -       
4058 +
4059         cv[9].destination = srv->srvconf.modules;
4060         cv[10].destination = srv->srvconf.event_handler;
4061         cv[11].destination = srv->srvconf.pid_file;
4062 -       
4063 +
4064         cv[13].destination = &(srv->srvconf.max_worker);
4065         cv[23].destination = &(srv->srvconf.max_fds);
4066         cv[36].destination = &(srv->srvconf.log_request_header_on_error);
4067         cv[37].destination = &(srv->srvconf.log_state_handling);
4068 -       
4069 +
4070         cv[39].destination = &(srv->srvconf.errorlog_use_syslog);
4071 -       
4072 +
4073         stat_cache_string = buffer_init();
4074         cv[41].destination = stat_cache_string;
4075         cv[43].destination = srv->srvconf.network_backend;
4076         cv[44].destination = srv->srvconf.upload_tempdirs;
4077         cv[45].destination = &(srv->srvconf.enable_cores);
4078 -       
4079 +
4080         cv[42].destination = &(srv->srvconf.max_conns);
4081         cv[12].destination = &(srv->srvconf.max_request_size);
4082         srv->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
4083  
4084         assert(srv->config_storage);
4085 -       
4086 +
4087         for (i = 0; i < srv->config_context->used; i++) {
4088                 specific_config *s;
4089 -               
4090 +
4091                 s = calloc(1, sizeof(specific_config));
4092                 assert(s);
4093                 s->document_root = buffer_init();
4094 @@ -154,17 +156,18 @@
4095                 s->global_kbytes_per_second = 0;
4096                 s->global_bytes_per_second_cnt = 0;
4097                 s->global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
4098 -               
4099 +
4100                 cv[2].destination = s->errorfile_prefix;
4101 -               
4102 +
4103                 cv[7].destination = s->server_tag;
4104                 cv[8].destination = &(s->use_ipv6);
4105 -               
4106 -               
4107 +
4108 +
4109                 /* 13 max-worker */
4110                 cv[14].destination = s->document_root;
4111                 cv[15].destination = &(s->force_lowercase_filenames);
4112                 cv[16].destination = &(s->log_condition_handling);
4113 +               cv[46].destination = &(s->log_condition_cache_handling);
4114                 cv[17].destination = &(s->max_keep_alive_requests);
4115                 cv[18].destination = s->server_name;
4116                 cv[19].destination = &(s->max_keep_alive_idle);
4117 @@ -179,23 +182,23 @@
4118                 cv[28].destination = s->mimetypes;
4119                 cv[29].destination = s->ssl_pemfile;
4120                 cv[30].destination = &(s->is_ssl);
4121 -               
4122 +
4123                 cv[31].destination = &(s->log_file_not_found);
4124                 cv[32].destination = &(s->log_request_handling);
4125                 cv[33].destination = &(s->log_response_header);
4126                 cv[34].destination = &(s->log_request_header);
4127 -               
4128 +
4129                 cv[35].destination = &(s->allow_http11);
4130                 cv[38].destination = s->ssl_ca_file;
4131                 cv[40].destination = &(s->range_requests);
4132 -               
4133 +
4134                 srv->config_storage[i] = s;
4135 -       
4136 +
4137                 if (0 != (ret = config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv))) {
4138                         break;
4139                 }
4140         }
4141 -       
4142 +
4143         if (buffer_is_empty(stat_cache_string)) {
4144                 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE;
4145         } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("simple"))) {
4146 @@ -205,22 +208,22 @@
4147         } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("disable"))) {
4148                 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_NONE;
4149         } else {
4150 -               log_error_write(srv, __FILE__, __LINE__, "sb", 
4151 +               log_error_write(srv, __FILE__, __LINE__, "sb",
4152                                 "server.stat-cache-engine can be one of \"disable\", \"simple\", \"fam\", but not:", stat_cache_string);
4153                 ret = HANDLER_ERROR;
4154         }
4155 -       
4156 +
4157         buffer_free(stat_cache_string);
4158 -       
4159 +
4160         return ret;
4161 -                                                                
4162 -}
4163  
4164 +}
4165  
4166 -#define PATCH(x) con->conf.x = s->x
4167 +#define PATCH(x) \
4168 +       con->conf.x = s->x
4169  int config_setup_connection(server *srv, connection *con) {
4170         specific_config *s = srv->config_storage[0];
4171 -       
4172 +
4173         PATCH(allow_http11);
4174         PATCH(mimetypes);
4175         PATCH(document_root);
4176 @@ -236,20 +239,21 @@
4177         PATCH(kbytes_per_second);
4178         PATCH(global_kbytes_per_second);
4179         PATCH(global_bytes_per_second_cnt);
4180 -       
4181 +
4182         con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
4183         buffer_copy_string_buffer(con->server_name, s->server_name);
4184 -       
4185 +
4186         PATCH(log_request_header);
4187         PATCH(log_response_header);
4188         PATCH(log_request_handling);
4189         PATCH(log_condition_handling);
4190 +       PATCH(log_condition_cache_handling);
4191         PATCH(log_file_not_found);
4192 -       
4193 +
4194         PATCH(range_requests);
4195         PATCH(force_lowercase_filenames);
4196         PATCH(is_ssl);
4197 -       
4198 +
4199         PATCH(ssl_pemfile);
4200         PATCH(ssl_ca_file);
4201         return 0;
4202 @@ -257,22 +261,22 @@
4203  
4204  int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
4205         size_t i, j;
4206 -       
4207 +
4208         /* skip the first, the global context */
4209         for (i = 1; i < srv->config_context->used; i++) {
4210                 data_config *dc = (data_config *)srv->config_context->data[i];
4211                 specific_config *s = srv->config_storage[i];
4212 -               
4213 +
4214                 /* not our stage */
4215                 if (comp != dc->comp) continue;
4216 -               
4217 +
4218                 /* condition didn't match */
4219                 if (!config_check_cond(srv, con, dc)) continue;
4220 -               
4221 +
4222                 /* merge config */
4223                 for (j = 0; j < dc->value->used; j++) {
4224                         data_unset *du = dc->value->data[j];
4225 -                       
4226 +
4227                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.document-root"))) {
4228                                 PATCH(document_root);
4229                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.range-requests"))) {
4230 @@ -315,11 +319,13 @@
4231                                 PATCH(log_response_header);
4232                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-handling"))) {
4233                                 PATCH(log_condition_handling);
4234 +                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-cache-handling"))) {
4235 +                               PATCH(log_condition_cache_handling);
4236                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-file-not-found"))) {
4237                                 PATCH(log_file_not_found);
4238                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.protocol-http11"))) {
4239                                 PATCH(allow_http11);
4240 -                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {  
4241 +                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
4242                                 PATCH(force_lowercase_filenames);
4243                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.kbytes-per-second"))) {
4244                                 PATCH(global_kbytes_per_second);
4245 @@ -328,7 +334,7 @@
4246                         }
4247                 }
4248         }
4249 -       
4250 +
4251         return 0;
4252  }
4253  #undef PATCH
4254 @@ -336,15 +342,15 @@
4255  typedef struct {
4256         int foo;
4257         int bar;
4258 -       
4259 +
4260         const buffer *source;
4261         const char *input;
4262         size_t offset;
4263         size_t size;
4264 -       
4265 +
4266         int line_pos;
4267         int line;
4268 -       
4269 +
4270         int in_key;
4271         int in_brace;
4272         int in_cond;
4273 @@ -362,7 +368,7 @@
4274         }
4275  
4276         if (0 != stream_open(&(t->s), t->file)) {
4277 -               log_error_write(srv, __FILE__, __LINE__, "sbss", 
4278 +               log_error_write(srv, __FILE__, __LINE__, "sbss",
4279                                 "opening configfile ", t->file, "failed:", strerror(errno));
4280                 buffer_free(t->file);
4281                 return -1;
4282 @@ -373,7 +379,7 @@
4283         t->size = t->s.size;
4284         t->line = 1;
4285         t->line_pos = 1;
4286 -       
4287 +
4288         t->in_key = 1;
4289         t->in_brace = 0;
4290         t->in_cond = 0;
4291 @@ -401,7 +407,7 @@
4292  static int config_skip_comment(tokenizer_t *t) {
4293         int i;
4294         assert(t->input[t->offset] == '#');
4295 -       for (i = 1; t->input[t->offset + i] && 
4296 +       for (i = 1; t->input[t->offset + i] &&
4297              (t->input[t->offset + i] != '\n' && t->input[t->offset + i] != '\r');
4298              i++);
4299         t->offset += i;
4300 @@ -411,44 +417,44 @@
4301  static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *token) {
4302         int tid = 0;
4303         size_t i;
4304 -       
4305 +
4306         for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
4307                 char c = t->input[t->offset];
4308                 const char *start = NULL;
4309 -               
4310 +
4311                 switch (c) {
4312 -               case '=': 
4313 +               case '=':
4314                         if (t->in_brace) {
4315                                 if (t->input[t->offset + 1] == '>') {
4316                                         t->offset += 2;
4317 -                                       
4318 +
4319                                         buffer_copy_string(token, "=>");
4320 -                                       
4321 +
4322                                         tid = TK_ARRAY_ASSIGN;
4323                                 } else {
4324 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4325 +                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4326                                                         "source:", t->source,
4327 -                                                       "line:", t->line, "pos:", t->line_pos, 
4328 +                                                       "line:", t->line, "pos:", t->line_pos,
4329                                                         "use => for assignments in arrays");
4330                                         return -1;
4331                                 }
4332                         } else if (t->in_cond) {
4333                                 if (t->input[t->offset + 1] == '=') {
4334                                         t->offset += 2;
4335 -                                       
4336 +
4337                                         buffer_copy_string(token, "==");
4338 -                                       
4339 +
4340                                         tid = TK_EQ;
4341                                 } else if (t->input[t->offset + 1] == '~') {
4342                                         t->offset += 2;
4343 -                                       
4344 +
4345                                         buffer_copy_string(token, "=~");
4346 -                                       
4347 +
4348                                         tid = TK_MATCH;
4349                                 } else {
4350 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4351 +                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4352                                                         "source:", t->source,
4353 -                                                       "line:", t->line, "pos:", t->line_pos, 
4354 +                                                       "line:", t->line, "pos:", t->line_pos,
4355                                                         "only =~ and == are allowed in the condition");
4356                                         return -1;
4357                                 }
4358 @@ -456,51 +462,51 @@
4359                                 t->in_cond = 0;
4360                         } else if (t->in_key) {
4361                                 tid = TK_ASSIGN;
4362 -                               
4363 +
4364                                 buffer_copy_string_len(token, t->input + t->offset, 1);
4365 -                               
4366 +
4367                                 t->offset++;
4368                                 t->line_pos++;
4369                         } else {
4370 -                               log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4371 +                               log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4372                                                 "source:", t->source,
4373 -                                               "line:", t->line, "pos:", t->line_pos, 
4374 +                                               "line:", t->line, "pos:", t->line_pos,
4375                                                 "unexpected equal-sign: =");
4376                                 return -1;
4377                         }
4378 -                       
4379 +
4380                         break;
4381 -               case '!': 
4382 +               case '!':
4383                         if (t->in_cond) {
4384                                 if (t->input[t->offset + 1] == '=') {
4385                                         t->offset += 2;
4386 -                                       
4387 +
4388                                         buffer_copy_string(token, "!=");
4389 -                                       
4390 +
4391                                         tid = TK_NE;
4392                                 } else if (t->input[t->offset + 1] == '~') {
4393                                         t->offset += 2;
4394 -                                       
4395 +
4396                                         buffer_copy_string(token, "!~");
4397 -                                       
4398 +
4399                                         tid = TK_NOMATCH;
4400                                 } else {
4401 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4402 +                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4403                                                         "source:", t->source,
4404 -                                                       "line:", t->line, "pos:", t->line_pos, 
4405 +                                                       "line:", t->line, "pos:", t->line_pos,
4406                                                         "only !~ and != are allowed in the condition");
4407                                         return -1;
4408                                 }
4409                                 t->in_key = 1;
4410                                 t->in_cond = 0;
4411                         } else {
4412 -                               log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4413 +                               log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4414                                                 "source:", t->source,
4415 -                                               "line:", t->line, "pos:", t->line_pos, 
4416 +                                               "line:", t->line, "pos:", t->line_pos,
4417                                                 "unexpected exclamation-marks: !");
4418                                 return -1;
4419                         }
4420 -                       
4421 +
4422                         break;
4423                 case '\t':
4424                 case ' ':
4425 @@ -546,10 +552,10 @@
4426                 case ',':
4427                         if (t->in_brace > 0) {
4428                                 tid = TK_COMMA;
4429 -                               
4430 +
4431                                 buffer_copy_string(token, "(COMMA)");
4432                         }
4433 -                       
4434 +
4435                         t->offset++;
4436                         t->line_pos++;
4437                         break;
4438 @@ -557,70 +563,70 @@
4439                         /* search for the terminating " */
4440                         start = t->input + t->offset + 1;
4441                         buffer_copy_string(token, "");
4442 -                       
4443 +
4444                         for (i = 1; t->input[t->offset + i]; i++) {
4445                                 if (t->input[t->offset + i] == '\\' &&
4446                                     t->input[t->offset + i + 1] == '"') {
4447 -                                       
4448 +
4449                                         buffer_append_string_len(token, start, t->input + t->offset + i - start);
4450 -                                       
4451 +
4452                                         start = t->input + t->offset + i + 1;
4453 -                                       
4454 +
4455                                         /* skip the " */
4456                                         i++;
4457                                         continue;
4458                                 }
4459 -                               
4460 -                               
4461 +
4462 +
4463                                 if (t->input[t->offset + i] == '"') {
4464                                         tid = TK_STRING;
4465 -                               
4466 +
4467                                         buffer_append_string_len(token, start, t->input + t->offset + i - start);
4468 -                                       
4469 +
4470                                         break;
4471                                 }
4472                         }
4473  
4474                         if (t->input[t->offset + i] == '\0') {
4475                                 /* ERROR */
4476 -                               
4477 -                               log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4478 +
4479 +                               log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4480                                                 "source:", t->source,
4481 -                                               "line:", t->line, "pos:", t->line_pos, 
4482 +                                               "line:", t->line, "pos:", t->line_pos,
4483                                                 "missing closing quote");
4484 -                               
4485 +
4486                                 return -1;
4487                         }
4488 -                       
4489 +
4490                         t->offset += i + 1;
4491                         t->line_pos += i + 1;
4492 -                       
4493 +
4494                         break;
4495                 case '(':
4496                         t->offset++;
4497                         t->in_brace++;
4498 -                               
4499 +
4500                         tid = TK_LPARAN;
4501 -                               
4502 +
4503                         buffer_copy_string(token, "(");
4504                         break;
4505                 case ')':
4506                         t->offset++;
4507                         t->in_brace--;
4508 -                               
4509 +
4510                         tid = TK_RPARAN;
4511 -                               
4512 +
4513                         buffer_copy_string(token, ")");
4514                         break;
4515                 case '$':
4516                         t->offset++;
4517 -                               
4518 +
4519                         tid = TK_DOLLAR;
4520                         t->in_cond = 1;
4521                         t->in_key = 0;
4522 -                               
4523 +
4524                         buffer_copy_string(token, "$");
4525 -                       
4526 +
4527                         break;
4528  
4529                 case '+':
4530 @@ -637,96 +643,88 @@
4531  
4532                 case '{':
4533                         t->offset++;
4534 -                               
4535 +
4536                         tid = TK_LCURLY;
4537 -                               
4538 +
4539                         buffer_copy_string(token, "{");
4540 -                       
4541 +
4542                         break;
4543 -                       
4544 +
4545                 case '}':
4546                         t->offset++;
4547 -                               
4548 +
4549                         tid = TK_RCURLY;
4550 -                               
4551 +
4552                         buffer_copy_string(token, "}");
4553 -                       
4554 +
4555                         break;
4556  
4557                 case '[':
4558                         t->offset++;
4559 -                               
4560 +
4561                         tid = TK_LBRACKET;
4562 -                               
4563 +
4564                         buffer_copy_string(token, "[");
4565 -                       
4566 +
4567                         break;
4568 -                       
4569 +
4570                 case ']':
4571                         t->offset++;
4572 -                               
4573 +
4574                         tid = TK_RBRACKET;
4575 -                               
4576 +
4577                         buffer_copy_string(token, "]");
4578 -                       
4579 +
4580                         break;
4581                 case '#':
4582                         t->line_pos += config_skip_comment(t);
4583 -                       
4584 +
4585                         break;
4586                 default:
4587                         if (t->in_cond) {
4588 -                               for (i = 0; t->input[t->offset + i] && 
4589 +                               for (i = 0; t->input[t->offset + i] &&
4590                                      (isalpha((unsigned char)t->input[t->offset + i])
4591                                       ); i++);
4592 -                               
4593 +
4594                                 if (i && t->input[t->offset + i]) {
4595                                         tid = TK_SRVVARNAME;
4596                                         buffer_copy_string_len(token, t->input + t->offset, i);
4597 -                                       
4598 +
4599                                         t->offset += i;
4600                                         t->line_pos += i;
4601                                 } else {
4602                                         /* ERROR */
4603 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4604 +                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4605                                                         "source:", t->source,
4606 -                                                       "line:", t->line, "pos:", t->line_pos, 
4607 +                                                       "line:", t->line, "pos:", t->line_pos,
4608                                                         "invalid character in condition");
4609                                         return -1;
4610                                 }
4611                         } else if (isdigit((unsigned char)c)) {
4612                                 /* take all digits */
4613                                 for (i = 0; t->input[t->offset + i] && isdigit((unsigned char)t->input[t->offset + i]);  i++);
4614 -                               
4615 +
4616                                 /* was there it least a digit ? */
4617 -                               if (i && t->input[t->offset + i]) {
4618 +                               if (i) {
4619                                         tid = TK_INTEGER;
4620 -                                       
4621 +
4622                                         buffer_copy_string_len(token, t->input + t->offset, i);
4623 -                                       
4624 +
4625                                         t->offset += i;
4626                                         t->line_pos += i;
4627 -                               } else {
4628 -                                       /* ERROR */
4629 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4630 -                                                       "source:", t->source,
4631 -                                                       "line:", t->line, "pos:", t->line_pos, 
4632 -                                                       "unexpected EOF");
4633 -                                       
4634 -                                       return -1;
4635                                 }
4636                         } else {
4637                                 /* the key might consist of [-.0-9a-z] */
4638 -                               for (i = 0; t->input[t->offset + i] && 
4639 -                                    (isalnum((unsigned char)t->input[t->offset + i]) || 
4640 +                               for (i = 0; t->input[t->offset + i] &&
4641 +                                    (isalnum((unsigned char)t->input[t->offset + i]) ||
4642                                       t->input[t->offset + i] == '.' ||
4643                                       t->input[t->offset + i] == '_' || /* for env.* */
4644                                       t->input[t->offset + i] == '-'
4645                                       ); i++);
4646 -                               
4647 +
4648                                 if (i && t->input[t->offset + i]) {
4649                                         buffer_copy_string_len(token, t->input + t->offset, i);
4650 -                                       
4651 +
4652                                         if (strcmp(token->ptr, "include") == 0) {
4653                                                 tid = TK_INCLUDE;
4654                                         } else if (strcmp(token->ptr, "include_shell") == 0) {
4655 @@ -738,14 +736,14 @@
4656                                         } else {
4657                                                 tid = TK_LKEY;
4658                                         }
4659 -                                       
4660 +
4661                                         t->offset += i;
4662                                         t->line_pos += i;
4663                                 } else {
4664                                         /* ERROR */
4665 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4666 +                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4667                                                         "source:", t->source,
4668 -                                                       "line:", t->line, "pos:", t->line_pos, 
4669 +                                                       "line:", t->line, "pos:", t->line_pos,
4670                                                         "invalid character in variable name");
4671                                         return -1;
4672                                 }
4673 @@ -753,16 +751,16 @@
4674                         break;
4675                 }
4676         }
4677 -       
4678 +
4679         if (tid) {
4680                 *token_id = tid;
4681  #if 0
4682 -               log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd", 
4683 +               log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd",
4684                                 "source:", t->source,
4685                                 "line:", t->line, "pos:", t->line_pos,
4686                                 token, token->used - 1, tid);
4687  #endif
4688 -               
4689 +
4690                 return 1;
4691         } else if (t->offset < t->size) {
4692                 fprintf(stderr, "%s.%d: %d, %s\n",
4693 @@ -781,10 +779,11 @@
4694         pParser = configparserAlloc( malloc );
4695         lasttoken = buffer_init();
4696         token = buffer_init();
4697 +
4698         while((1 == (ret = config_tokenizer(srv, t, &token_id, token))) && context->ok) {
4699                 buffer_copy_string_buffer(lasttoken, token);
4700                 configparser(pParser, token_id, token, context);
4701 -               
4702 +
4703                 token = buffer_init();
4704         }
4705         buffer_free(token);
4706 @@ -797,14 +796,14 @@
4707                 }
4708         }
4709         configparserFree(pParser, free);
4710 -       
4711 +
4712         if (ret == -1) {
4713 -               log_error_write(srv, __FILE__, __LINE__, "sb", 
4714 +               log_error_write(srv, __FILE__, __LINE__, "sb",
4715                                 "configfile parser failed:", lasttoken);
4716         } else if (context->ok == 0) {
4717 -               log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb", 
4718 +               log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb",
4719                                 "source:", t->source,
4720 -                               "line:", t->line, "pos:", t->line_pos, 
4721 +                               "line:", t->line, "pos:", t->line_pos,
4722                                 "parser failed somehow near here:", lasttoken);
4723                 ret = -1;
4724         }
4725 @@ -821,7 +820,7 @@
4726         t->offset = 0;
4727         t->line = 1;
4728         t->line_pos = 1;
4729 -       
4730 +
4731         t->in_key = 1;
4732         t->in_brace = 0;
4733         t->in_cond = 0;
4734 @@ -844,7 +843,7 @@
4735         }
4736  
4737         if (0 != stream_open(&s, filename)) {
4738 -               log_error_write(srv, __FILE__, __LINE__, "sbss", 
4739 +               log_error_write(srv, __FILE__, __LINE__, "sbss",
4740                                 "opening configfile ", filename, "failed:", strerror(errno));
4741                 ret = -1;
4742         } else {
4743 @@ -866,7 +865,7 @@
4744         char oldpwd[PATH_MAX];
4745  
4746         if (NULL == getcwd(oldpwd, sizeof(oldpwd))) {
4747 -               log_error_write(srv, __FILE__, __LINE__, "s", 
4748 +               log_error_write(srv, __FILE__, __LINE__, "s",
4749                                 "cannot get cwd", strerror(errno));
4750                 return -1;
4751         }
4752 @@ -879,7 +878,7 @@
4753         }
4754  
4755         if (0 != proc_open_buffer(&proc, cmd, NULL, out, NULL)) {
4756 -               log_error_write(srv, __FILE__, __LINE__, "sbss", 
4757 +               log_error_write(srv, __FILE__, __LINE__, "sbss",
4758                                 "opening", source, "failed:", strerror(errno));
4759                 ret = -1;
4760         } else {
4761 @@ -896,13 +895,12 @@
4762  static void context_init(server *srv, config_t *context) {
4763         context->srv = srv;
4764         context->ok = 1;
4765 -       context->configs_stack = array_init();
4766 -       context->configs_stack->is_weakref = 1;
4767 +       context->configs_stack = buffer_ptr_init(NULL);
4768         context->basedir = buffer_init();
4769  }
4770  
4771  static void context_free(config_t *context) {
4772 -       array_free(context->configs_stack);
4773 +       buffer_ptr_free(context->configs_stack);
4774         buffer_free(context->basedir);
4775  }
4776  
4777 @@ -918,18 +916,15 @@
4778         context_init(srv, &context);
4779         context.all_configs = srv->config_context;
4780  
4781 -       pos = strrchr(fn,
4782 -#ifdef __WIN32
4783 -                       '\\'
4784 -#else
4785 -                       '/'
4786 -#endif
4787 -                       );
4788 +    /* use the current dir as basedir for all other includes
4789 +    */
4790 +       pos = strrchr(fn, DIR_SEPERATOR);
4791 +
4792         if (pos) {
4793                 buffer_copy_string_len(context.basedir, fn, pos - fn + 1);
4794                 fn = pos + 1;
4795         }
4796 -       
4797 +
4798         dc = data_config_init();
4799         buffer_copy_string(dc->key, "global");
4800  
4801 @@ -941,10 +936,10 @@
4802         /* default context */
4803         srv->config = dc->value;
4804         dpid = data_integer_init();
4805 -       dpid->value = getpid();
4806 +       dpid->value = /* getpid() */0;
4807         buffer_copy_string(dpid->key, "var.PID");
4808         array_insert_unique(srv->config, (data_unset *)dpid);
4809 -       
4810 +
4811         dcwd = data_string_init();
4812         buffer_prepare_copy(dcwd->value, 1024);
4813         if (NULL != getcwd(dcwd->value->ptr, dcwd->value->size - 1)) {
4814 @@ -968,7 +963,7 @@
4815         } else {
4816                 return -1;
4817         }
4818 -       
4819 +
4820         if (NULL != (modules = (data_array *)array_get_element(srv->config, "server.modules"))) {
4821                 data_string *ds;
4822                 data_array *prepends;
4823 @@ -1026,22 +1021,23 @@
4824                 buffer_copy_string(modules->key, "server.modules");
4825                 array_insert_unique(srv->config, (data_unset *)modules);
4826         }
4827 -       
4828 +
4829  
4830         if (0 != config_insert(srv)) {
4831                 return -1;
4832         }
4833 -       
4834 +
4835         return 0;
4836  }
4837  
4838 +
4839  int config_set_defaults(server *srv) {
4840         size_t i;
4841         specific_config *s = srv->config_storage[0];
4842         struct stat st1, st2;
4843 -       
4844 -       struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] = 
4845 -       { 
4846 +
4847 +       struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
4848 +       {
4849                 /* - poll is most reliable
4850                  * - select works everywhere
4851                  * - linux-* are experimental
4852 @@ -1067,20 +1063,21 @@
4853  #endif
4854                 { FDEVENT_HANDLER_UNSET,          NULL }
4855         };
4856 -       
4857  
4858 -       if (buffer_is_empty(s->document_root)) {  
4859 -               log_error_write(srv, __FILE__, __LINE__, "s",  
4860 -                               "a default document-root has to be set");  
4861 -               
4862 -               return -1;  
4863 -       }  
4864 -       
4865 +
4866 +       if (buffer_is_empty(s->document_root)) {
4867 +               log_error_write(srv, __FILE__, __LINE__, "s",
4868 +                               "a default document-root has to be set");
4869 +
4870 +               return -1;
4871 +       }
4872 +
4873         if (buffer_is_empty(srv->srvconf.changeroot)) {
4874 -               if (-1 == stat(s->document_root->ptr, &st1)) {  
4875 -                       log_error_write(srv, __FILE__, __LINE__, "sb",  
4876 +        pathname_unix2local(s->document_root);
4877 +               if (-1 == stat(s->document_root->ptr, &st1)) {
4878 +                       log_error_write(srv, __FILE__, __LINE__, "sbs",
4879                                         "base-docroot doesn't exist:",
4880 -                                       s->document_root);  
4881 +                                       s->document_root, strerror(errno));
4882                         return -1;
4883                 }
4884  
4885 @@ -1088,18 +1085,18 @@
4886                 buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.changeroot);
4887                 buffer_append_string_buffer(srv->tmp_buf, s->document_root);
4888  
4889 -               if (-1 == stat(srv->tmp_buf->ptr, &st1)) {  
4890 -                       log_error_write(srv, __FILE__, __LINE__, "sb",  
4891 +               if (-1 == stat(srv->tmp_buf->ptr, &st1)) {
4892 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
4893                                         "base-docroot doesn't exist:",
4894 -                                       srv->tmp_buf);  
4895 +                                       srv->tmp_buf);
4896                         return -1;
4897                 }
4898 -               
4899 +
4900         }
4901 -       
4902 -       buffer_copy_string_buffer(srv->tmp_buf, s->document_root);  
4903  
4904 -       buffer_to_lower(srv->tmp_buf);  
4905 +       buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
4906 +
4907 +       buffer_to_lower(srv->tmp_buf);
4908  
4909         if (0 == stat(srv->tmp_buf->ptr, &st1)) {
4910                 int is_lower = 0;
4911 @@ -1107,68 +1104,68 @@
4912                 is_lower = buffer_is_equal(srv->tmp_buf, s->document_root);
4913  
4914                 /* lower-case existed, check upper-case */
4915 -               buffer_copy_string_buffer(srv->tmp_buf, s->document_root);  
4916 +               buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
4917  
4918 -               buffer_to_upper(srv->tmp_buf);  
4919 +               buffer_to_upper(srv->tmp_buf);
4920  
4921                 /* we have to handle the special case that upper and lower-casing results in the same filename
4922                  * as in server.document-root = "/" or "/12345/" */
4923  
4924                 if (is_lower && buffer_is_equal(srv->tmp_buf, s->document_root)) {
4925 -                       /* lower-casing and upper-casing didn't result in  
4926 -                        * an other filename, no need to stat(), 
4927 +                       /* lower-casing and upper-casing didn't result in
4928 +                        * an other filename, no need to stat(),
4929                          * just assume it is case-sensitive. */
4930  
4931                         s->force_lowercase_filenames = 0;
4932 -               } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {  
4933 +               } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {
4934 +
4935 +                       /* upper case exists too, doesn't the FS handle this ? */
4936 +
4937 +                       /* upper and lower have the same inode -> case-insensitve FS */
4938 +
4939 +                       if (st1.st_ino == st2.st_ino) {
4940 +                               /* upper and lower have the same inode -> case-insensitve FS */
4941 +
4942 +                               s->force_lowercase_filenames = 1;
4943 +                       }
4944 +               }
4945 +       }
4946  
4947 -                       /* upper case exists too, doesn't the FS handle this ? */  
4948 -                       
4949 -                       /* upper and lower have the same inode -> case-insensitve FS */  
4950 -                       
4951 -                       if (st1.st_ino == st2.st_ino) {  
4952 -                               /* upper and lower have the same inode -> case-insensitve FS */  
4953 -                               
4954 -                               s->force_lowercase_filenames = 1;  
4955 -                       }  
4956 -               }  
4957 -       }  
4958 -       
4959         if (srv->srvconf.port == 0) {
4960                 srv->srvconf.port = s->is_ssl ? 443 : 80;
4961         }
4962 -       
4963 +
4964         if (srv->srvconf.event_handler->used == 0) {
4965                 /* choose a good default
4966 -                * 
4967 -                * the event_handler list is sorted by 'goodness' 
4968 +                *
4969 +                * the event_handler list is sorted by 'goodness'
4970                  * taking the first available should be the best solution
4971                  */
4972                 srv->event_handler = event_handlers[0].et;
4973 -               
4974 +
4975                 if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
4976 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
4977 +                       log_error_write(srv, __FILE__, __LINE__, "s",
4978                                         "sorry, there is no event handler for this system");
4979 -                       
4980 +
4981                         return -1;
4982                 }
4983         } else {
4984                 /*
4985                  * User override
4986                  */
4987 -               
4988 +
4989                 for (i = 0; event_handlers[i].name; i++) {
4990                         if (0 == strcmp(event_handlers[i].name, srv->srvconf.event_handler->ptr)) {
4991                                 srv->event_handler = event_handlers[i].et;
4992                                 break;
4993                         }
4994                 }
4995 -               
4996 +
4997                 if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
4998 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
4999 -                                       "the selected event-handler in unknown or not supported:", 
5000 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
5001 +                                       "the selected event-handler in unknown or not supported:",
5002                                         srv->srvconf.event_handler );
5003 -                       
5004 +
5005                         return -1;
5006                 }
5007         }
5008 @@ -1176,19 +1173,19 @@
5009         if (s->is_ssl) {
5010                 if (buffer_is_empty(s->ssl_pemfile)) {
5011                         /* PEM file is require */
5012 -                       
5013 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
5014 +
5015 +                       log_error_write(srv, __FILE__, __LINE__, "s",
5016                                         "ssl.pemfile has to be set");
5017                         return -1;
5018                 }
5019 -               
5020 +
5021  #ifndef USE_OPENSSL
5022 -               log_error_write(srv, __FILE__, __LINE__, "s", 
5023 +               log_error_write(srv, __FILE__, __LINE__, "s",
5024                                 "ssl support is missing, recompile with --with-openssl");
5025 -               
5026 +
5027                 return -1;
5028  #endif
5029         }
5030 -       
5031 +
5032         return 0;
5033  }
5034 --- lighttpd-1.4.11/src/configfile.h    2005-08-23 17:36:12.000000000 +0300
5035 +++ lighttpd-1.4.12/src/configfile.h    2006-07-11 22:07:51.000000000 +0300
5036 @@ -9,7 +9,7 @@
5037         server *srv;
5038         int     ok;
5039         array  *all_configs;
5040 -       array  *configs_stack; /* to parse nested block */
5041 +       buffer_ptr  *configs_stack; /* to parse nested block */
5042         data_config *current; /* current started with { */
5043         buffer *basedir;
5044  } config_t;
5045 --- lighttpd-1.4.11/src/configparser.c  2006-02-01 19:51:15.000000000 +0200
5046 +++ lighttpd-1.4.12/src/configparser.c  2006-07-11 22:08:02.000000000 +0300
5047 @@ -24,52 +24,34 @@
5048      dc->parent = ctx->current;
5049      array_insert_unique(dc->parent->childs, (data_unset *)dc);
5050    }
5051 -  array_insert_unique(ctx->configs_stack, (data_unset *)ctx->current);
5052 +  buffer_ptr_append(ctx->configs_stack, (void *)ctx->current);
5053    ctx->current = dc;
5054  }
5055  
5056  static data_config *configparser_pop(config_t *ctx) {
5057    data_config *old = ctx->current;
5058 -  ctx->current = (data_config *) array_pop(ctx->configs_stack);
5059 +  ctx->current = (data_config *) buffer_ptr_pop(ctx->configs_stack);
5060    return old;
5061  }
5062  
5063  /* return a copied variable */
5064  static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
5065 -  if (strncmp(key->ptr, "env.", sizeof("env.") - 1) == 0) {
5066 -    char *env;
5067 -
5068 -    if (NULL != (env = getenv(key->ptr + 4))) {
5069 -      data_string *ds;
5070 -      ds = data_string_init();
5071 -      buffer_append_string(ds->value, env);
5072 -      return (data_unset *)ds;
5073 -    }
5074 -
5075 -    fprintf(stderr, "Undefined env variable: %s\n", key->ptr + 4);
5076 -    ctx->ok = 0;
5077 -
5078 -    return NULL;
5079 -  } else {
5080 -    data_unset *du;
5081 -    data_config *dc;
5082 +  data_unset *du;
5083 +  data_config *dc;
5084  
5085  #if 0
5086 -    fprintf(stderr, "get var %s\n", key->ptr);
5087 +  fprintf(stderr, "get var %s\n", key->ptr);
5088  #endif
5089 -    for (dc = ctx->current; dc; dc = dc->parent) {
5090 +  for (dc = ctx->current; dc; dc = dc->parent) {
5091  #if 0
5092 -      fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
5093 -      array_print(dc->value, 0);
5094 +    fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
5095 +    array_print(dc->value, 0);
5096  #endif
5097 -      if (NULL != (du = array_get_element(dc->value, key->ptr))) {
5098 -        return du->copy(du);
5099 -      }
5100 +    if (NULL != (du = array_get_element(dc->value, key->ptr))) {
5101 +      return du->copy(du);
5102      }
5103 -    fprintf(stderr, "Undefined config variable: %s\n", key->ptr);
5104 -    ctx->ok = 0;
5105 -    return NULL;
5106    }
5107 +  return NULL;
5108  }
5109  
5110  /* op1 is to be eat/return by this function, op1->key is not cared
5111 @@ -124,14 +106,14 @@
5112  }
5113  
5114  
5115 -#line 128 "configparser.c"
5116 +#line 110 "configparser.c"
5117  /* Next is all token values, in a form suitable for use by makeheaders.
5118  ** This section will be null unless lemon is run with the -m switch.
5119  */
5120 -/* 
5121 +/*
5122  ** These constants (all generated automatically by the parser generator)
5123  ** specify the various kinds of tokens (terminals) that the parser
5124 -** understands. 
5125 +** understands.
5126  **
5127  ** Each symbol here is a terminal symbol in the grammar.
5128  */
5129 @@ -148,7 +130,7 @@
5130  **                       and nonterminals.  "int" is used otherwise.
5131  **    YYNOCODE           is a number of type YYCODETYPE which corresponds
5132  **                       to no legal terminal or nonterminal number.  This
5133 -**                       number is used to fill in empty slots of the hash 
5134 +**                       number is used to fill in empty slots of the hash
5135  **                       table.
5136  **    YYFALLBACK         If defined, this indicates that one or more tokens
5137  **                       have fall-back values which should be used if the
5138 @@ -157,7 +139,7 @@
5139  **                       and nonterminal numbers.  "unsigned char" is
5140  **                       used if there are fewer than 250 rules and
5141  **                       states combined.  "int" is used otherwise.
5142 -**    configparserTOKENTYPE     is the data type used for minor tokens given 
5143 +**    configparserTOKENTYPE     is the data type used for minor tokens given
5144  **                       directly to the parser from the tokenizer.
5145  **    YYMINORTYPE        is the data type used for all minor tokens.
5146  **                       This is typically a union of many types, one of
5147 @@ -192,8 +174,8 @@
5148  #define configparserARG_PDECL ,config_t *ctx
5149  #define configparserARG_FETCH config_t *ctx = yypParser->ctx
5150  #define configparserARG_STORE yypParser->ctx = ctx
5151 -#define YYNSTATE 62
5152 -#define YYNRULE 39
5153 +#define YYNSTATE 63
5154 +#define YYNRULE 40
5155  #define YYERRORSYMBOL 26
5156  #define YYERRSYMDT yy95
5157  #define YY_NO_ACTION      (YYNSTATE+YYNRULE+2)
5158 @@ -203,7 +185,7 @@
5159  /* Next are that tables used to determine what action to take based on the
5160  ** current state and lookahead token.  These tables are used to implement
5161  ** functions that take a state number and lookahead value and return an
5162 -** action integer.  
5163 +** action integer.
5164  **
5165  ** Suppose the action integer is N.  Then the action is determined as
5166  ** follows
5167 @@ -228,7 +210,7 @@
5168  ** If the index value yy_shift_ofst[S]+X is out of range or if the value
5169  ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
5170  ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
5171 -** and that yy_default[S] should be used instead.  
5172 +** and that yy_default[S] should be used instead.
5173  **
5174  ** The formula above is for computing the action when the lookahead is
5175  ** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
5176 @@ -248,67 +230,69 @@
5177  **  yy_default[]       Default action for each state.
5178  */
5179  static YYACTIONTYPE yy_action[] = {
5180 - /*     0 */     2,    3,    4,    5,   13,   14,   62,   15,    7,   44,
5181 - /*    10 */    20,   86,   16,   45,   28,   48,   40,   10,   39,   25,
5182 - /*    20 */    22,   49,   45,    8,   15,  102,    1,   20,   28,   18,
5183 - /*    30 */    57,   59,   19,   25,   22,   39,   19,   61,   98,   45,
5184 - /*    40 */    20,    6,   23,   24,   26,   28,   35,   57,   59,   12,
5185 - /*    50 */    25,   22,   28,   27,   36,   87,   29,   25,   22,   33,
5186 - /*    60 */    15,   30,   31,   20,   28,   38,    9,   17,   37,   25,
5187 - /*    70 */    22,   39,   42,   43,   10,   45,   11,   53,   54,   55,
5188 - /*    80 */    56,   28,   52,   57,   59,   34,   25,   22,   28,   27,
5189 - /*    90 */    32,   88,   41,   25,   22,   33,   28,   48,   46,   28,
5190 - /*   100 */    48,   25,   22,   58,   25,   22,   60,   21,   19,   47,
5191 - /*   110 */    51,   50,   25,   22,   88,   88,   93,
5192 + /*     0 */     2,    3,    4,    5,   13,   14,   63,   15,    7,   45,
5193 + /*    10 */    20,   88,   16,   46,   28,   49,   41,   10,   40,   25,
5194 + /*    20 */    22,   50,   46,    8,   15,  104,    1,   20,   28,   18,
5195 + /*    30 */    58,   60,    6,   25,   22,   40,   47,   62,   11,   46,
5196 + /*    40 */    20,    9,   23,   24,   26,   29,   89,   58,   60,   10,
5197 + /*    50 */    17,   38,   28,   27,   37,   19,   30,   25,   22,   34,
5198 + /*    60 */    15,  100,   20,   20,   23,   24,   26,   12,   19,   31,
5199 + /*    70 */    32,   40,   19,   44,   43,   46,   95,   35,   90,   89,
5200 + /*    80 */    28,   49,   42,   58,   60,   25,   22,   59,   28,   27,
5201 + /*    90 */    33,   48,   52,   25,   22,   34,   28,   49,   51,   28,
5202 + /*   100 */    36,   25,   22,   61,   25,   22,   89,   28,   39,   89,
5203 + /*   110 */    89,   89,   25,   22,   54,   55,   56,   57,   89,   28,
5204 + /*   120 */    53,   21,   89,   89,   25,   22,   25,   22,
5205  };
5206  static YYCODETYPE yy_lookahead[] = {
5207   /*     0 */    29,   30,   31,   32,   33,   34,    0,    1,   44,   38,
5208   /*    10 */     4,   15,   41,   16,   35,   36,   45,   46,   12,   40,
5209   /*    20 */    41,   42,   16,   15,    1,   27,   28,    4,   35,   36,
5210 - /*    30 */    24,   25,    5,   40,   41,   12,    5,   14,   11,   16,
5211 - /*    40 */     4,    1,    6,    7,    8,   35,   36,   24,   25,   28,
5212 - /*    50 */    40,   41,   35,   36,   37,   15,   39,   40,   41,   42,
5213 - /*    60 */     1,    9,   10,    4,   35,   36,   38,    2,    3,   40,
5214 - /*    70 */    41,   12,   28,   14,   46,   16,   13,   20,   21,   22,
5215 - /*    80 */    23,   35,   36,   24,   25,   11,   40,   41,   35,   36,
5216 - /*    90 */    37,   13,   13,   40,   41,   42,   35,   36,   17,   35,
5217 - /*   100 */    36,   40,   41,   42,   40,   41,   42,   35,    5,   18,
5218 - /*   110 */    43,   19,   40,   41,   47,   47,   13,
5219 + /*    30 */    24,   25,    1,   40,   41,   12,   17,   14,   13,   16,
5220 + /*    40 */     4,   38,    6,    7,    8,    9,   15,   24,   25,   46,
5221 + /*    50 */     2,    3,   35,   36,   37,    5,   39,   40,   41,   42,
5222 + /*    60 */     1,   11,    4,    4,    6,    7,    8,   28,    5,    9,
5223 + /*    70 */    10,   12,    5,   14,   28,   16,   13,   11,   13,   47,
5224 + /*    80 */    35,   36,   13,   24,   25,   40,   41,   42,   35,   36,
5225 + /*    90 */    37,   18,   43,   40,   41,   42,   35,   36,   19,   35,
5226 + /*   100 */    36,   40,   41,   42,   40,   41,   47,   35,   36,   47,
5227 + /*   110 */    47,   47,   40,   41,   20,   21,   22,   23,   47,   35,
5228 + /*   120 */    36,   35,   47,   47,   40,   41,   40,   41,
5229  };
5230  #define YY_SHIFT_USE_DFLT (-5)
5231  static signed char yy_shift_ofst[] = {
5232 - /*     0 */    -5,    6,   -5,   -5,   -5,   40,   -4,    8,   -3,   -5,
5233 - /*    10 */    63,   -5,   23,   -5,   -5,   -5,   65,   36,   31,   36,
5234 - /*    20 */    -5,   -5,   -5,   -5,   -5,   -5,   36,   27,   -5,   52,
5235 - /*    30 */    -5,   36,   -5,   74,   36,   31,   -5,   36,   31,   78,
5236 - /*    40 */    79,   -5,   59,   -5,   -5,   81,   91,   36,   31,   92,
5237 - /*    50 */    57,   36,  103,   -5,   -5,   -5,   -5,   36,   -5,   36,
5238 - /*    60 */    -5,   -5,
5239 + /*     0 */    -5,    6,   -5,   -5,   -5,   31,   -4,    8,   -3,   -5,
5240 + /*    10 */    25,   -5,   23,   -5,   -5,   -5,   48,   58,   67,   58,
5241 + /*    20 */    -5,   -5,   -5,   -5,   -5,   -5,   36,   50,   -5,   -5,
5242 + /*    30 */    60,   -5,   58,   -5,   66,   58,   67,   -5,   58,   67,
5243 + /*    40 */    65,   69,   -5,   59,   -5,   -5,   19,   73,   58,   67,
5244 + /*    50 */    79,   94,   58,   63,   -5,   -5,   -5,   -5,   58,   -5,
5245 + /*    60 */    58,   -5,   -5,
5246  };
5247  #define YY_REDUCE_USE_DFLT (-37)
5248  static signed char yy_reduce_ofst[] = {
5249 - /*     0 */    -2,  -29,  -37,  -37,  -37,  -36,  -37,  -37,   28,  -37,
5250 - /*    10 */   -37,   21,  -29,  -37,  -37,  -37,  -37,   -7,  -37,   72,
5251 + /*     0 */    -2,  -29,  -37,  -37,  -37,  -36,  -37,  -37,    3,  -37,
5252 + /*    10 */   -37,   39,  -29,  -37,  -37,  -37,  -37,   -7,  -37,   86,
5253   /*    20 */   -37,  -37,  -37,  -37,  -37,  -37,   17,  -37,  -37,  -37,
5254 - /*    30 */   -37,   53,  -37,  -37,   10,  -37,  -37,   29,  -37,  -37,
5255 - /*    40 */   -37,   44,  -29,  -37,  -37,  -37,  -37,  -21,  -37,  -37,
5256 - /*    50 */    67,   46,  -37,  -37,  -37,  -37,  -37,   61,  -37,   64,
5257 - /*    60 */   -37,  -37,
5258 + /*    30 */   -37,  -37,   53,  -37,  -37,   64,  -37,  -37,   72,  -37,
5259 + /*    40 */   -37,  -37,   46,  -29,  -37,  -37,  -37,  -37,  -21,  -37,
5260 + /*    50 */   -37,   49,   84,  -37,  -37,  -37,  -37,  -37,   45,  -37,
5261 + /*    60 */    61,  -37,  -37,
5262  };
5263  static YYACTIONTYPE yy_default[] = {
5264 - /*     0 */    64,  101,   63,   65,   66,  101,   67,  101,  101,   90,
5265 - /*    10 */   101,   64,  101,   68,   69,   70,  101,  101,   71,  101,
5266 - /*    20 */    73,   74,   76,   77,   78,   79,  101,   84,   75,  101,
5267 - /*    30 */    80,   82,   81,  101,  101,   85,   83,  101,   72,  101,
5268 - /*    40 */   101,   64,  101,   89,   91,  101,  101,  101,   98,  101,
5269 - /*    50 */   101,  101,  101,   94,   95,   96,   97,  101,   99,  101,
5270 - /*    60 */   100,   92,
5271 + /*     0 */    65,  103,   64,   66,   67,  103,   68,  103,  103,   92,
5272 + /*    10 */   103,   65,  103,   69,   70,   71,  103,  103,   72,  103,
5273 + /*    20 */    74,   75,   77,   78,   79,   80,  103,   86,   76,   81,
5274 + /*    30 */   103,   82,   84,   83,  103,  103,   87,   85,  103,   73,
5275 + /*    40 */   103,  103,   65,  103,   91,   93,  103,  103,  103,  100,
5276 + /*    50 */   103,  103,  103,  103,   96,   97,   98,   99,  103,  101,
5277 + /*    60 */   103,  102,   94,
5278  };
5279  #define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
5280  
5281  /* The next table maps tokens into fallback tokens.  If a construct
5282  ** like the following:
5283 -** 
5284 +**
5285  **      %fallback ID X Y Z.
5286  **
5287  ** appears in the grammer, then ID becomes a fallback token for X, Y,
5288 @@ -359,10 +343,10 @@
5289  #endif /* NDEBUG */
5290  
5291  #ifndef NDEBUG
5292 -/* 
5293 +/*
5294  ** Turn parser tracing on by giving a stream to which to write the trace
5295  ** and a prompt to preface each trace message.  Tracing is turned off
5296 -** by making either argument NULL 
5297 +** by making either argument NULL
5298  **
5299  ** Inputs:
5300  ** <ul>
5301 @@ -387,7 +371,7 @@
5302  #ifndef NDEBUG
5303  /* For tracing shifts, the names of all terminals and nonterminals
5304  ** are required.  The following table supplies these names */
5305 -static const char *yyTokenName[] = { 
5306 +static const char *yyTokenName[] = {
5307    "$",             "EOL",           "ASSIGN",        "APPEND",      
5308    "LKEY",          "PLUS",          "STRING",        "INTEGER",     
5309    "LPARAN",        "RPARAN",        "COMMA",         "ARRAY_ASSIGN",
5310 @@ -425,27 +409,28 @@
5311   /*  15 */ "value ::= STRING",
5312   /*  16 */ "value ::= INTEGER",
5313   /*  17 */ "value ::= array",
5314 - /*  18 */ "array ::= LPARAN aelements RPARAN",
5315 - /*  19 */ "aelements ::= aelements COMMA aelement",
5316 - /*  20 */ "aelements ::= aelements COMMA",
5317 - /*  21 */ "aelements ::= aelement",
5318 - /*  22 */ "aelement ::= expression",
5319 - /*  23 */ "aelement ::= stringop ARRAY_ASSIGN expression",
5320 - /*  24 */ "eols ::= EOL",
5321 - /*  25 */ "eols ::=",
5322 - /*  26 */ "globalstart ::= GLOBAL",
5323 - /*  27 */ "global ::= globalstart LCURLY metalines RCURLY",
5324 - /*  28 */ "condlines ::= condlines eols ELSE condline",
5325 - /*  29 */ "condlines ::= condline",
5326 - /*  30 */ "condline ::= context LCURLY metalines RCURLY",
5327 - /*  31 */ "context ::= DOLLAR SRVVARNAME LBRACKET stringop RBRACKET cond expression",
5328 - /*  32 */ "cond ::= EQ",
5329 - /*  33 */ "cond ::= MATCH",
5330 - /*  34 */ "cond ::= NE",
5331 - /*  35 */ "cond ::= NOMATCH",
5332 - /*  36 */ "stringop ::= expression",
5333 - /*  37 */ "include ::= INCLUDE stringop",
5334 - /*  38 */ "include_shell ::= INCLUDE_SHELL stringop",
5335 + /*  18 */ "array ::= LPARAN RPARAN",
5336 + /*  19 */ "array ::= LPARAN aelements RPARAN",
5337 + /*  20 */ "aelements ::= aelements COMMA aelement",
5338 + /*  21 */ "aelements ::= aelements COMMA",
5339 + /*  22 */ "aelements ::= aelement",
5340 + /*  23 */ "aelement ::= expression",
5341 + /*  24 */ "aelement ::= stringop ARRAY_ASSIGN expression",
5342 + /*  25 */ "eols ::= EOL",
5343 + /*  26 */ "eols ::=",
5344 + /*  27 */ "globalstart ::= GLOBAL",
5345 + /*  28 */ "global ::= globalstart LCURLY metalines RCURLY",
5346 + /*  29 */ "condlines ::= condlines eols ELSE condline",
5347 + /*  30 */ "condlines ::= condline",
5348 + /*  31 */ "condline ::= context LCURLY metalines RCURLY",
5349 + /*  32 */ "context ::= DOLLAR SRVVARNAME LBRACKET stringop RBRACKET cond expression",
5350 + /*  33 */ "cond ::= EQ",
5351 + /*  34 */ "cond ::= MATCH",
5352 + /*  35 */ "cond ::= NE",
5353 + /*  36 */ "cond ::= NOMATCH",
5354 + /*  37 */ "stringop ::= expression",
5355 + /*  38 */ "include ::= INCLUDE stringop",
5356 + /*  39 */ "include_shell ::= INCLUDE_SHELL stringop",
5357  };
5358  #endif /* NDEBUG */
5359  
5360 @@ -465,7 +450,7 @@
5361  #endif
5362  }
5363  
5364 -/* 
5365 +/*
5366  ** This function allocates a new parser.
5367  ** The only argument is a pointer to a function which works like
5368  ** malloc.
5369 @@ -496,7 +481,7 @@
5370      /* Here is inserted the actions which take place when a
5371      ** terminal or non-terminal is destroyed.  This can happen
5372      ** when the symbol is popped from the stack during a
5373 -    ** reduce or during error processing or when a parser is 
5374 +    ** reduce or during error processing or when a parser is
5375      ** being destroyed before it is finished parsing.
5376      **
5377      ** Note: during a reduce, the only symbols destroyed are those
5378 @@ -528,44 +513,44 @@
5379      case 23:
5380      case 24:
5381      case 25:
5382 -#line 160 "./configparser.y"
5383 +#line 143 "./configparser.y"
5384  { buffer_free((yypminor->yy0)); }
5385 -#line 533 "configparser.c"
5386 +#line 518 "configparser.c"
5387        break;
5388      case 35:
5389 -#line 151 "./configparser.y"
5390 +#line 134 "./configparser.y"
5391  { (yypminor->yy41)->free((yypminor->yy41)); }
5392 -#line 538 "configparser.c"
5393 +#line 523 "configparser.c"
5394        break;
5395      case 36:
5396 -#line 152 "./configparser.y"
5397 +#line 135 "./configparser.y"
5398  { (yypminor->yy41)->free((yypminor->yy41)); }
5399 -#line 543 "configparser.c"
5400 +#line 528 "configparser.c"
5401        break;
5402      case 37:
5403 -#line 153 "./configparser.y"
5404 +#line 136 "./configparser.y"
5405  { (yypminor->yy41)->free((yypminor->yy41)); }
5406 -#line 548 "configparser.c"
5407 +#line 533 "configparser.c"
5408        break;
5409      case 39:
5410 -#line 154 "./configparser.y"
5411 +#line 137 "./configparser.y"
5412  { array_free((yypminor->yy40)); }
5413 -#line 553 "configparser.c"
5414 +#line 538 "configparser.c"
5415        break;
5416      case 40:
5417 -#line 155 "./configparser.y"
5418 +#line 138 "./configparser.y"
5419  { array_free((yypminor->yy40)); }
5420 -#line 558 "configparser.c"
5421 +#line 543 "configparser.c"
5422        break;
5423      case 41:
5424 -#line 156 "./configparser.y"
5425 +#line 139 "./configparser.y"
5426  { buffer_free((yypminor->yy43)); }
5427 -#line 563 "configparser.c"
5428 +#line 548 "configparser.c"
5429        break;
5430      case 42:
5431 -#line 157 "./configparser.y"
5432 +#line 140 "./configparser.y"
5433  { buffer_free((yypminor->yy43)); }
5434 -#line 568 "configparser.c"
5435 +#line 553 "configparser.c"
5436        break;
5437      default:  break;   /* If no destructor action specified: do nothing */
5438    }
5439 @@ -597,7 +582,7 @@
5440    return yymajor;
5441  }
5442  
5443 -/* 
5444 +/*
5445  ** Deallocate and destroy a parser.  Destructors are all called for
5446  ** all stack elements before shutting the parser down.
5447  **
5448 @@ -633,7 +618,7 @@
5449  ){
5450    int i;
5451    int stateno = pParser->yystack[pParser->yyidx].stateno;
5452
5453 +
5454    /* if( pParser->yyidx<0 ) return YY_NO_ACTION;  */
5455    i = yy_shift_ofst[stateno];
5456    if( i==YY_SHIFT_USE_DFLT ){
5457 @@ -677,7 +662,7 @@
5458  ){
5459    int i;
5460    int stateno = pParser->yystack[pParser->yyidx].stateno;
5461
5462 +
5463    i = yy_reduce_ofst[stateno];
5464    if( i==YY_REDUCE_USE_DFLT ){
5465      return yy_default[stateno];
5466 @@ -759,6 +744,7 @@
5467    { 35, 1 },
5468    { 35, 1 },
5469    { 35, 1 },
5470 +  { 40, 2 },
5471    { 40, 3 },
5472    { 39, 3 },
5473    { 39, 2 },
5474 @@ -800,7 +786,7 @@
5475    configparserARG_FETCH;
5476    yymsp = &yypParser->yystack[yypParser->yyidx];
5477  #ifndef NDEBUG
5478 -  if( yyTraceFILE && yyruleno>=0 
5479 +  if( yyTraceFILE && yyruleno>=0
5480          && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
5481      fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
5482        yyRuleName[yyruleno]);
5483 @@ -832,9 +818,9 @@
5484          /* No destructor defined for global */
5485          break;
5486        case 5:
5487 -#line 134 "./configparser.y"
5488 +#line 116 "./configparser.y"
5489  { yymsp[-1].minor.yy78 = NULL; }
5490 -#line 837 "configparser.c"
5491 +#line 823 "configparser.c"
5492    yy_destructor(1,&yymsp[0].minor);
5493          break;
5494        case 6:
5495 @@ -847,10 +833,15 @@
5496    yy_destructor(1,&yymsp[0].minor);
5497          break;
5498        case 9:
5499 -#line 162 "./configparser.y"
5500 +#line 145 "./configparser.y"
5501  {
5502    buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
5503 -  if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) {
5504 +  if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
5505 +    fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
5506 +        ctx->current->context_ndx,
5507 +        ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
5508 +    ctx->ok = 0;
5509 +  } else if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) {
5510      array_insert_unique(ctx->current->value, yymsp[0].minor.yy41);
5511      yymsp[0].minor.yy41 = NULL;
5512    } else {
5513 @@ -864,16 +855,21 @@
5514    buffer_free(yymsp[-2].minor.yy43);
5515    yymsp[-2].minor.yy43 = NULL;
5516  }
5517 -#line 867 "configparser.c"
5518 +#line 858 "configparser.c"
5519    yy_destructor(2,&yymsp[-1].minor);
5520          break;
5521        case 10:
5522 -#line 179 "./configparser.y"
5523 +#line 167 "./configparser.y"
5524  {
5525    array *vars = ctx->current->value;
5526    data_unset *du;
5527  
5528 -  if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) {
5529 +  if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
5530 +    fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n",
5531 +        ctx->current->context_ndx,
5532 +        ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
5533 +    ctx->ok = 0;
5534 +  } else if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) {
5535      /* exists in current block */
5536      du = configparser_merge_data(du, yymsp[0].minor.yy41);
5537      if (NULL == du) {
5538 @@ -883,6 +879,7 @@
5539        buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43);
5540        array_replace(vars, du);
5541      }
5542 +    yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5543    } else if (NULL != (du = configparser_get_variable(ctx, yymsp[-2].minor.yy43))) {
5544      du = configparser_merge_data(du, yymsp[0].minor.yy41);
5545      if (NULL == du) {
5546 @@ -892,22 +889,20 @@
5547        buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43);
5548        array_insert_unique(ctx->current->value, du);
5549      }
5550 +    yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5551    } else {
5552 -    fprintf(stderr, "Undefined config variable in conditional %d %s: %s\n", 
5553 -            ctx->current->context_ndx,
5554 -            ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
5555 -    ctx->ok = 0;
5556 +    buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
5557 +    array_insert_unique(ctx->current->value, yymsp[0].minor.yy41);
5558    }
5559    buffer_free(yymsp[-2].minor.yy43);
5560    yymsp[-2].minor.yy43 = NULL;
5561 -  yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5562    yymsp[0].minor.yy41 = NULL;
5563  }
5564 -#line 906 "configparser.c"
5565 +#line 901 "configparser.c"
5566    yy_destructor(3,&yymsp[-1].minor);
5567          break;
5568        case 11:
5569 -#line 214 "./configparser.y"
5570 +#line 206 "./configparser.y"
5571  {
5572    if (strchr(yymsp[0].minor.yy0->ptr, '.') == NULL) {
5573      yygotominor.yy43 = buffer_init_string("var.");
5574 @@ -919,10 +914,10 @@
5575      yymsp[0].minor.yy0 = NULL;
5576    }
5577  }
5578 -#line 922 "configparser.c"
5579 +#line 917 "configparser.c"
5580          break;
5581        case 12:
5582 -#line 226 "./configparser.y"
5583 +#line 218 "./configparser.y"
5584  {
5585    yygotominor.yy41 = configparser_merge_data(yymsp[-2].minor.yy41, yymsp[0].minor.yy41);
5586    if (NULL == yygotominor.yy41) {
5587 @@ -932,21 +927,38 @@
5588    yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5589    yymsp[0].minor.yy41 = NULL;
5590  }
5591 -#line 935 "configparser.c"
5592 +#line 930 "configparser.c"
5593    yy_destructor(5,&yymsp[-1].minor);
5594          break;
5595        case 13:
5596 -#line 236 "./configparser.y"
5597 +#line 228 "./configparser.y"
5598  {
5599    yygotominor.yy41 = yymsp[0].minor.yy41;
5600    yymsp[0].minor.yy41 = NULL;
5601  }
5602 -#line 944 "configparser.c"
5603 +#line 939 "configparser.c"
5604          break;
5605        case 14:
5606 -#line 241 "./configparser.y"
5607 +#line 233 "./configparser.y"
5608  {
5609 -  yygotominor.yy41 = configparser_get_variable(ctx, yymsp[0].minor.yy43);
5610 +  if (strncmp(yymsp[0].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
5611 +    char *env;
5612 +
5613 +    if (NULL != (env = getenv(yymsp[0].minor.yy43->ptr + 4))) {
5614 +      data_string *ds;
5615 +      ds = data_string_init();
5616 +      buffer_append_string(ds->value, env);
5617 +      yygotominor.yy41 = (data_unset *)ds;
5618 +    }
5619 +    else {
5620 +      yygotominor.yy41 = NULL;
5621 +      fprintf(stderr, "Undefined env variable: %s\n", yymsp[0].minor.yy43->ptr + 4);
5622 +      ctx->ok = 0;
5623 +    }
5624 +  } else if (NULL == (yygotominor.yy41 = configparser_get_variable(ctx, yymsp[0].minor.yy43))) {
5625 +    fprintf(stderr, "Undefined config variable: %s\n", yymsp[0].minor.yy43->ptr);
5626 +    ctx->ok = 0;
5627 +  }
5628    if (!yygotominor.yy41) {
5629      /* make a dummy so it won't crash */
5630      yygotominor.yy41 = (data_unset *)data_string_init();
5631 @@ -954,50 +966,59 @@
5632    buffer_free(yymsp[0].minor.yy43);
5633    yymsp[0].minor.yy43 = NULL;
5634  }
5635 -#line 957 "configparser.c"
5636 +#line 969 "configparser.c"
5637          break;
5638        case 15:
5639 -#line 251 "./configparser.y"
5640 +#line 260 "./configparser.y"
5641  {
5642    yygotominor.yy41 = (data_unset *)data_string_init();
5643    buffer_copy_string_buffer(((data_string *)(yygotominor.yy41))->value, yymsp[0].minor.yy0);
5644    buffer_free(yymsp[0].minor.yy0);
5645    yymsp[0].minor.yy0 = NULL;
5646  }
5647 -#line 967 "configparser.c"
5648 +#line 979 "configparser.c"
5649          break;
5650        case 16:
5651 -#line 258 "./configparser.y"
5652 +#line 267 "./configparser.y"
5653  {
5654    yygotominor.yy41 = (data_unset *)data_integer_init();
5655    ((data_integer *)(yygotominor.yy41))->value = strtol(yymsp[0].minor.yy0->ptr, NULL, 10);
5656    buffer_free(yymsp[0].minor.yy0);
5657    yymsp[0].minor.yy0 = NULL;
5658  }
5659 -#line 977 "configparser.c"
5660 +#line 989 "configparser.c"
5661          break;
5662        case 17:
5663 -#line 264 "./configparser.y"
5664 +#line 273 "./configparser.y"
5665  {
5666    yygotominor.yy41 = (data_unset *)data_array_init();
5667    array_free(((data_array *)(yygotominor.yy41))->value);
5668    ((data_array *)(yygotominor.yy41))->value = yymsp[0].minor.yy40;
5669    yymsp[0].minor.yy40 = NULL;
5670  }
5671 -#line 987 "configparser.c"
5672 +#line 999 "configparser.c"
5673          break;
5674        case 18:
5675 -#line 270 "./configparser.y"
5676 +#line 279 "./configparser.y"
5677 +{
5678 +  yygotominor.yy40 = array_init();
5679 +}
5680 +#line 1006 "configparser.c"
5681 +  yy_destructor(8,&yymsp[-1].minor);
5682 +  yy_destructor(9,&yymsp[0].minor);
5683 +        break;
5684 +      case 19:
5685 +#line 282 "./configparser.y"
5686  {
5687    yygotominor.yy40 = yymsp[-1].minor.yy40;
5688    yymsp[-1].minor.yy40 = NULL;
5689  }
5690 -#line 995 "configparser.c"
5691 +#line 1016 "configparser.c"
5692    yy_destructor(8,&yymsp[-2].minor);
5693    yy_destructor(9,&yymsp[0].minor);
5694          break;
5695 -      case 19:
5696 -#line 275 "./configparser.y"
5697 +      case 20:
5698 +#line 287 "./configparser.y"
5699  {
5700    if (buffer_is_empty(yymsp[0].minor.yy41->key) ||
5701        NULL == array_get_element(yymsp[-2].minor.yy40, yymsp[0].minor.yy41->key->ptr)) {
5702 @@ -1014,37 +1035,37 @@
5703    yygotominor.yy40 = yymsp[-2].minor.yy40;
5704    yymsp[-2].minor.yy40 = NULL;
5705  }
5706 -#line 1017 "configparser.c"
5707 +#line 1038 "configparser.c"
5708    yy_destructor(10,&yymsp[-1].minor);
5709          break;
5710 -      case 20:
5711 -#line 292 "./configparser.y"
5712 +      case 21:
5713 +#line 304 "./configparser.y"
5714  {
5715    yygotominor.yy40 = yymsp[-1].minor.yy40;
5716    yymsp[-1].minor.yy40 = NULL;
5717  }
5718 -#line 1026 "configparser.c"
5719 +#line 1047 "configparser.c"
5720    yy_destructor(10,&yymsp[0].minor);
5721          break;
5722 -      case 21:
5723 -#line 297 "./configparser.y"
5724 +      case 22:
5725 +#line 309 "./configparser.y"
5726  {
5727    yygotominor.yy40 = array_init();
5728    array_insert_unique(yygotominor.yy40, yymsp[0].minor.yy41);
5729    yymsp[0].minor.yy41 = NULL;
5730  }
5731 -#line 1036 "configparser.c"
5732 +#line 1057 "configparser.c"
5733          break;
5734 -      case 22:
5735 -#line 303 "./configparser.y"
5736 +      case 23:
5737 +#line 315 "./configparser.y"
5738  {
5739    yygotominor.yy41 = yymsp[0].minor.yy41;
5740    yymsp[0].minor.yy41 = NULL;
5741  }
5742 -#line 1044 "configparser.c"
5743 +#line 1065 "configparser.c"
5744          break;
5745 -      case 23:
5746 -#line 307 "./configparser.y"
5747 +      case 24:
5748 +#line 319 "./configparser.y"
5749  {
5750    buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
5751    buffer_free(yymsp[-2].minor.yy43);
5752 @@ -1053,27 +1074,27 @@
5753    yygotominor.yy41 = yymsp[0].minor.yy41;
5754    yymsp[0].minor.yy41 = NULL;
5755  }
5756 -#line 1056 "configparser.c"
5757 +#line 1077 "configparser.c"
5758    yy_destructor(11,&yymsp[-1].minor);
5759          break;
5760 -      case 24:
5761 -  yy_destructor(1,&yymsp[0].minor);
5762 -        break;
5763        case 25:
5764 +  yy_destructor(1,&yymsp[0].minor);
5765          break;
5766        case 26:
5767 -#line 319 "./configparser.y"
5768 +        break;
5769 +      case 27:
5770 +#line 331 "./configparser.y"
5771  {
5772    data_config *dc;
5773    dc = (data_config *)array_get_element(ctx->srv->config_context, "global");
5774    assert(dc);
5775    configparser_push(ctx, dc, 0);
5776  }
5777 -#line 1072 "configparser.c"
5778 +#line 1093 "configparser.c"
5779    yy_destructor(12,&yymsp[0].minor);
5780          break;
5781 -      case 27:
5782 -#line 326 "./configparser.y"
5783 +      case 28:
5784 +#line 338 "./configparser.y"
5785  {
5786    data_config *cur;
5787    
5788 @@ -1082,16 +1103,16 @@
5789  
5790    assert(cur && ctx->current);
5791  
5792 -  yygotominor.yy0 = cur;
5793 +  yygotominor.yy78 = cur;
5794  }
5795 -#line 1087 "configparser.c"
5796 +#line 1108 "configparser.c"
5797          /* No destructor defined for globalstart */
5798    yy_destructor(13,&yymsp[-2].minor);
5799          /* No destructor defined for metalines */
5800    yy_destructor(14,&yymsp[0].minor);
5801          break;
5802 -      case 28:
5803 -#line 337 "./configparser.y"
5804 +      case 29:
5805 +#line 349 "./configparser.y"
5806  {
5807    assert(yymsp[-3].minor.yy78->context_ndx < yymsp[0].minor.yy78->context_ndx);
5808    yymsp[0].minor.yy78->prev = yymsp[-3].minor.yy78;
5809 @@ -1100,20 +1121,20 @@
5810    yymsp[-3].minor.yy78 = NULL;
5811    yymsp[0].minor.yy78 = NULL;
5812  }
5813 -#line 1103 "configparser.c"
5814 +#line 1124 "configparser.c"
5815          /* No destructor defined for eols */
5816    yy_destructor(15,&yymsp[-1].minor);
5817          break;
5818 -      case 29:
5819 -#line 346 "./configparser.y"
5820 +      case 30:
5821 +#line 358 "./configparser.y"
5822  {
5823    yygotominor.yy78 = yymsp[0].minor.yy78;
5824    yymsp[0].minor.yy78 = NULL;
5825  }
5826 -#line 1113 "configparser.c"
5827 +#line 1134 "configparser.c"
5828          break;
5829 -      case 30:
5830 -#line 351 "./configparser.y"
5831 +      case 31:
5832 +#line 363 "./configparser.y"
5833  {
5834    data_config *cur;
5835    
5836 @@ -1124,14 +1145,14 @@
5837  
5838    yygotominor.yy78 = cur;
5839  }
5840 -#line 1127 "configparser.c"
5841 +#line 1148 "configparser.c"
5842          /* No destructor defined for context */
5843    yy_destructor(13,&yymsp[-2].minor);
5844          /* No destructor defined for metalines */
5845    yy_destructor(14,&yymsp[0].minor);
5846          break;
5847 -      case 31:
5848 -#line 362 "./configparser.y"
5849 +      case 32:
5850 +#line 374 "./configparser.y"
5851  {
5852    data_config *dc;
5853    buffer *b, *rvalue, *op;
5854 @@ -1266,45 +1287,45 @@
5855    yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5856    yymsp[0].minor.yy41 = NULL;
5857  }
5858 -#line 1269 "configparser.c"
5859 +#line 1290 "configparser.c"
5860    yy_destructor(16,&yymsp[-6].minor);
5861    yy_destructor(18,&yymsp[-4].minor);
5862    yy_destructor(19,&yymsp[-2].minor);
5863          break;
5864 -      case 32:
5865 -#line 496 "./configparser.y"
5866 +      case 33:
5867 +#line 508 "./configparser.y"
5868  {
5869    yygotominor.yy27 = CONFIG_COND_EQ;
5870  }
5871 -#line 1279 "configparser.c"
5872 +#line 1300 "configparser.c"
5873    yy_destructor(20,&yymsp[0].minor);
5874          break;
5875 -      case 33:
5876 -#line 499 "./configparser.y"
5877 +      case 34:
5878 +#line 511 "./configparser.y"
5879  {
5880    yygotominor.yy27 = CONFIG_COND_MATCH;
5881  }
5882 -#line 1287 "configparser.c"
5883 +#line 1308 "configparser.c"
5884    yy_destructor(21,&yymsp[0].minor);
5885          break;
5886 -      case 34:
5887 -#line 502 "./configparser.y"
5888 +      case 35:
5889 +#line 514 "./configparser.y"
5890  {
5891    yygotominor.yy27 = CONFIG_COND_NE;
5892  }
5893 -#line 1295 "configparser.c"
5894 +#line 1316 "configparser.c"
5895    yy_destructor(22,&yymsp[0].minor);
5896          break;
5897 -      case 35:
5898 -#line 505 "./configparser.y"
5899 +      case 36:
5900 +#line 517 "./configparser.y"
5901  {
5902    yygotominor.yy27 = CONFIG_COND_NOMATCH;
5903  }
5904 -#line 1303 "configparser.c"
5905 +#line 1324 "configparser.c"
5906    yy_destructor(23,&yymsp[0].minor);
5907          break;
5908 -      case 36:
5909 -#line 509 "./configparser.y"
5910 +      case 37:
5911 +#line 521 "./configparser.y"
5912  {
5913    yygotominor.yy43 = NULL;
5914    if (ctx->ok) {
5915 @@ -1321,10 +1342,10 @@
5916    yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5917    yymsp[0].minor.yy41 = NULL;
5918  }
5919 -#line 1324 "configparser.c"
5920 +#line 1345 "configparser.c"
5921          break;
5922 -      case 37:
5923 -#line 526 "./configparser.y"
5924 +      case 38:
5925 +#line 538 "./configparser.y"
5926  {
5927    if (ctx->ok) {
5928      if (0 != config_parse_file(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
5929 @@ -1334,11 +1355,11 @@
5930      yymsp[0].minor.yy43 = NULL;
5931    }
5932  }
5933 -#line 1337 "configparser.c"
5934 +#line 1358 "configparser.c"
5935    yy_destructor(24,&yymsp[-1].minor);
5936          break;
5937 -      case 38:
5938 -#line 536 "./configparser.y"
5939 +      case 39:
5940 +#line 548 "./configparser.y"
5941  {
5942    if (ctx->ok) {
5943      if (0 != config_parse_cmd(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
5944 @@ -1348,7 +1369,7 @@
5945      yymsp[0].minor.yy43 = NULL;
5946    }
5947  }
5948 -#line 1351 "configparser.c"
5949 +#line 1372 "configparser.c"
5950    yy_destructor(25,&yymsp[-1].minor);
5951          break;
5952    };
5953 @@ -1378,11 +1399,11 @@
5954    while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
5955    /* Here code is inserted which will be executed whenever the
5956    ** parser fails */
5957 -#line 125 "./configparser.y"
5958 +#line 107 "./configparser.y"
5959  
5960    ctx->ok = 0;
5961  
5962 -#line 1385 "configparser.c"
5963 +#line 1406 "configparser.c"
5964    configparserARG_STORE; /* Suppress warning about unused %extra_argument variable */
5965  }
5966  
5967 @@ -1489,7 +1510,7 @@
5968  #ifdef YYERRORSYMBOL
5969        /* A syntax error has occurred.
5970        ** The response to an error depends upon whether or not the
5971 -      ** grammar defines an error token "ERROR".  
5972 +      ** grammar defines an error token "ERROR".
5973        **
5974        ** This is what we do if the grammar does define ERROR:
5975        **
5976 --- lighttpd-1.4.11/src/configparser.y  2006-01-26 18:46:25.000000000 +0200
5977 +++ lighttpd-1.4.12/src/configparser.y  2006-07-11 22:07:53.000000000 +0300
5978 @@ -21,52 +21,34 @@
5979      dc->parent = ctx->current;
5980      array_insert_unique(dc->parent->childs, (data_unset *)dc);
5981    }
5982 -  array_insert_unique(ctx->configs_stack, (data_unset *)ctx->current);
5983 +  buffer_ptr_append(ctx->configs_stack, (void *)ctx->current);
5984    ctx->current = dc;
5985  }
5986  
5987  static data_config *configparser_pop(config_t *ctx) {
5988    data_config *old = ctx->current;
5989 -  ctx->current = (data_config *) array_pop(ctx->configs_stack);
5990 +  ctx->current = (data_config *) buffer_ptr_pop(ctx->configs_stack);
5991    return old;
5992  }
5993  
5994  /* return a copied variable */
5995  static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
5996 -  if (strncmp(key->ptr, "env.", sizeof("env.") - 1) == 0) {
5997 -    char *env;
5998 -
5999 -    if (NULL != (env = getenv(key->ptr + 4))) {
6000 -      data_string *ds;
6001 -      ds = data_string_init();
6002 -      buffer_append_string(ds->value, env);
6003 -      return (data_unset *)ds;
6004 -    }
6005 -
6006 -    fprintf(stderr, "Undefined env variable: %s\n", key->ptr + 4);
6007 -    ctx->ok = 0;
6008 -
6009 -    return NULL;
6010 -  } else {
6011 -    data_unset *du;
6012 -    data_config *dc;
6013 +  data_unset *du;
6014 +  data_config *dc;
6015  
6016  #if 0
6017 -    fprintf(stderr, "get var %s\n", key->ptr);
6018 +  fprintf(stderr, "get var %s\n", key->ptr);
6019  #endif
6020 -    for (dc = ctx->current; dc; dc = dc->parent) {
6021 +  for (dc = ctx->current; dc; dc = dc->parent) {
6022  #if 0
6023 -      fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
6024 -      array_print(dc->value, 0);
6025 +    fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
6026 +    array_print(dc->value, 0);
6027  #endif
6028 -      if (NULL != (du = array_get_element(dc->value, key->ptr))) {
6029 -        return du->copy(du);
6030 -      }
6031 +    if (NULL != (du = array_get_element(dc->value, key->ptr))) {
6032 +      return du->copy(du);
6033      }
6034 -    fprintf(stderr, "Undefined config variable: %s\n", key->ptr);
6035 -    ctx->ok = 0;
6036 -    return NULL;
6037    }
6038 +  return NULL;
6039  }
6040  
6041  /* op1 is to be eat/return by this function, op1->key is not cared
6042 @@ -141,6 +123,7 @@
6043  %type       aelement               {data_unset *}
6044  %type       condline               {data_config *}
6045  %type       condlines              {data_config *}
6046 +%type       global                 {data_config *}
6047  %type       aelements              {array *}
6048  %type       array                  {array *}
6049  %type       key                    {buffer *}
6050 @@ -161,7 +144,12 @@
6051  
6052  varline ::= key(A) ASSIGN expression(B). {
6053    buffer_copy_string_buffer(B->key, A);
6054 -  if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
6055 +  if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
6056 +    fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
6057 +        ctx->current->context_ndx,
6058 +        ctx->current->key->ptr, A->ptr);
6059 +    ctx->ok = 0;
6060 +  } else if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
6061      array_insert_unique(ctx->current->value, B);
6062      B = NULL;
6063    } else {
6064 @@ -180,7 +168,12 @@
6065    array *vars = ctx->current->value;
6066    data_unset *du;
6067  
6068 -  if (NULL != (du = array_get_element(vars, A->ptr))) {
6069 +  if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
6070 +    fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n",
6071 +        ctx->current->context_ndx,
6072 +        ctx->current->key->ptr, A->ptr);
6073 +    ctx->ok = 0;
6074 +  } else if (NULL != (du = array_get_element(vars, A->ptr))) {
6075      /* exists in current block */
6076      du = configparser_merge_data(du, B);
6077      if (NULL == du) {
6078 @@ -190,6 +183,7 @@
6079        buffer_copy_string_buffer(du->key, A);
6080        array_replace(vars, du);
6081      }
6082 +    B->free(B);
6083    } else if (NULL != (du = configparser_get_variable(ctx, A))) {
6084      du = configparser_merge_data(du, B);
6085      if (NULL == du) {
6086 @@ -199,15 +193,13 @@
6087        buffer_copy_string_buffer(du->key, A);
6088        array_insert_unique(ctx->current->value, du);
6089      }
6090 +    B->free(B);
6091    } else {
6092 -    fprintf(stderr, "Undefined config variable in conditional %d %s: %s\n", 
6093 -            ctx->current->context_ndx,
6094 -            ctx->current->key->ptr, A->ptr);
6095 -    ctx->ok = 0;
6096 +    buffer_copy_string_buffer(B->key, A);
6097 +    array_insert_unique(ctx->current->value, B);
6098    }
6099    buffer_free(A);
6100    A = NULL;
6101 -  B->free(B);
6102    B = NULL;
6103  }
6104  
6105 @@ -239,7 +231,24 @@
6106  }
6107  
6108  value(A) ::= key(B). {
6109 -  A = configparser_get_variable(ctx, B);
6110 +  if (strncmp(B->ptr, "env.", sizeof("env.") - 1) == 0) {
6111 +    char *env;
6112 +
6113 +    if (NULL != (env = getenv(B->ptr + 4))) {
6114 +      data_string *ds;
6115 +      ds = data_string_init();
6116 +      buffer_append_string(ds->value, env);
6117 +      A = (data_unset *)ds;
6118 +    }
6119 +    else {
6120 +      A = NULL;
6121 +      fprintf(stderr, "Undefined env variable: %s\n", B->ptr + 4);
6122 +      ctx->ok = 0;
6123 +    }
6124 +  } else if (NULL == (A = configparser_get_variable(ctx, B))) {
6125 +    fprintf(stderr, "Undefined config variable: %s\n", B->ptr);
6126 +    ctx->ok = 0;
6127 +  }
6128    if (!A) {
6129      /* make a dummy so it won't crash */
6130      A = (data_unset *)data_string_init();
6131 @@ -267,6 +276,9 @@
6132    ((data_array *)(A))->value = B;
6133    B = NULL;
6134  }
6135 +array(A) ::= LPARAN RPARAN. {
6136 +  A = array_init();
6137 +}
6138  array(A) ::= LPARAN aelements(B) RPARAN. {
6139    A = B;
6140    B = NULL;
6141 --- lighttpd-1.4.11/src/connections-glue.c      2005-09-12 10:04:23.000000000 +0300
6142 +++ lighttpd-1.4.12/src/connections-glue.c      2006-07-11 22:07:51.000000000 +0300
6143 @@ -13,7 +13,7 @@
6144         case CON_STATE_REQUEST_END: return "req-end";
6145         case CON_STATE_RESPONSE_START: return "resp-start";
6146         case CON_STATE_RESPONSE_END: return "resp-end";
6147 -       default: return "(unknown)";    
6148 +       default: return "(unknown)";
6149         }
6150  }
6151  
6152 @@ -30,15 +30,15 @@
6153         case CON_STATE_REQUEST_END: return "Q";
6154         case CON_STATE_RESPONSE_START: return "s";
6155         case CON_STATE_RESPONSE_END: return "S";
6156 -       default: return "x";    
6157 +       default: return "x";
6158         }
6159  }
6160  
6161  int connection_set_state(server *srv, connection *con, connection_state_t state) {
6162         UNUSED(srv);
6163 -       
6164 +
6165         con->state = state;
6166 -       
6167 +
6168         return 0;
6169  }
6170  
6171 --- lighttpd-1.4.11/src/connections.c   2006-03-05 22:14:53.000000000 +0200
6172 +++ lighttpd-1.4.12/src/connections.c   2006-07-11 22:07:51.000000000 +0300
6173 @@ -2,7 +2,6 @@
6174  
6175  #include <stdlib.h>
6176  #include <stdio.h>
6177 -#include <unistd.h>
6178  #include <errno.h>
6179  #include <string.h>
6180  #include <fcntl.h>
6181 @@ -26,8 +25,8 @@
6182  #include "inet_ntop_cache.h"
6183  
6184  #ifdef USE_OPENSSL
6185 -# include <openssl/ssl.h> 
6186 -# include <openssl/err.h> 
6187 +# include <openssl/ssl.h>
6188 +# include <openssl/err.h>
6189  #endif
6190  
6191  #ifdef HAVE_SYS_FILIO_H
6192 @@ -35,6 +34,7 @@
6193  #endif
6194  
6195  #include "sys-socket.h"
6196 +#include "sys-files.h"
6197  
6198  typedef struct {
6199                 PLUGIN_DATA;
6200 @@ -43,7 +43,7 @@
6201  static connection *connections_get_new_connection(server *srv) {
6202         connections *conns = srv->conns;
6203         size_t i;
6204 -       
6205 +
6206         if (conns->size == 0) {
6207                 conns->size = 128;
6208                 conns->ptr = NULL;
6209 @@ -54,21 +54,21 @@
6210         } else if (conns->size == conns->used) {
6211                 conns->size += 128;
6212                 conns->ptr = realloc(conns->ptr, sizeof(*conns->ptr) * conns->size);
6213 -               
6214 +
6215                 for (i = conns->used; i < conns->size; i++) {
6216                         conns->ptr[i] = connection_init(srv);
6217                 }
6218         }
6219  
6220         connection_reset(srv, conns->ptr[conns->used]);
6221 -#if 0  
6222 +#if 0
6223         fprintf(stderr, "%s.%d: add: ", __FILE__, __LINE__);
6224         for (i = 0; i < conns->used + 1; i++) {
6225                 fprintf(stderr, "%d ", conns->ptr[i]->fd);
6226         }
6227         fprintf(stderr, "\n");
6228 -#endif 
6229 -       
6230 +#endif
6231 +
6232         conns->ptr[conns->used]->ndx = conns->used;
6233         return conns->ptr[conns->used++];
6234  }
6235 @@ -77,26 +77,26 @@
6236         size_t i;
6237         connections *conns = srv->conns;
6238         connection *temp;
6239 -       
6240 +
6241         if (con == NULL) return -1;
6242 -       
6243 +
6244         if (-1 == con->ndx) return -1;
6245 -       
6246 +
6247         i = con->ndx;
6248 -       
6249 +
6250         /* not last element */
6251 -       
6252 +
6253         if (i != conns->used - 1) {
6254                 temp = conns->ptr[i];
6255                 conns->ptr[i] = conns->ptr[conns->used - 1];
6256                 conns->ptr[conns->used - 1] = temp;
6257 -               
6258 +
6259                 conns->ptr[i]->ndx = i;
6260                 conns->ptr[conns->used - 1]->ndx = -1;
6261         }
6262 -       
6263 +
6264         conns->used--;
6265 -       
6266 +
6267         con->ndx = -1;
6268  #if 0
6269         fprintf(stderr, "%s.%d: del: (%d)", __FILE__, __LINE__, conns->used);
6270 @@ -104,25 +104,23 @@
6271                 fprintf(stderr, "%d ", conns->ptr[i]->fd);
6272         }
6273         fprintf(stderr, "\n");
6274 -#endif 
6275 +#endif
6276         return 0;
6277  }
6278  
6279  int connection_close(server *srv, connection *con) {
6280  #ifdef USE_OPENSSL
6281         server_socket *srv_sock = con->srv_socket;
6282 -#endif
6283 -       
6284 -#ifdef USE_OPENSSL
6285 +
6286         if (srv_sock->is_ssl) {
6287                 if (con->ssl) SSL_free(con->ssl);
6288                 con->ssl = NULL;
6289         }
6290  #endif
6291 -       
6292 +
6293         fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
6294         fdevent_unregister(srv->ev, con->fd);
6295 -#ifdef __WIN32
6296 +#ifdef _WIN32
6297         if (closesocket(con->fd)) {
6298                 log_error_write(srv, __FILE__, __LINE__, "sds",
6299                                 "(warning) close:", con->fd, strerror(errno));
6300 @@ -133,207 +131,96 @@
6301                                 "(warning) close:", con->fd, strerror(errno));
6302         }
6303  #endif
6304 -       
6305 +
6306         srv->cur_fds--;
6307  #if 0
6308         log_error_write(srv, __FILE__, __LINE__, "sd",
6309                         "closed()", con->fd);
6310  #endif
6311 -       
6312 +
6313         connection_del(srv, con);
6314         connection_set_state(srv, con, CON_STATE_CONNECT);
6315 -       
6316 +
6317         return 0;
6318  }
6319  
6320  #if 0
6321  static void dump_packet(const unsigned char *data, size_t len) {
6322         size_t i, j;
6323 -       
6324 +
6325         if (len == 0) return;
6326 -       
6327 +
6328         for (i = 0; i < len; i++) {
6329                 if (i % 16 == 0) fprintf(stderr, "  ");
6330 -               
6331 +
6332                 fprintf(stderr, "%02x ", data[i]);
6333 -               
6334 +
6335                 if ((i + 1) % 16 == 0) {
6336                         fprintf(stderr, "  ");
6337                         for (j = 0; j <= i % 16; j++) {
6338                                 unsigned char c;
6339 -                               
6340 +
6341                                 if (i-15+j >= len) break;
6342 -                               
6343 +
6344                                 c = data[i-15+j];
6345 -                               
6346 +
6347                                 fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
6348                         }
6349 -                       
6350 +
6351                         fprintf(stderr, "\n");
6352                 }
6353         }
6354 -       
6355 +
6356         if (len % 16 != 0) {
6357                 for (j = i % 16; j < 16; j++) {
6358                         fprintf(stderr, "   ");
6359                 }
6360 -               
6361 +
6362                 fprintf(stderr, "  ");
6363                 for (j = i & ~0xf; j < len; j++) {
6364                         unsigned char c;
6365 -                       
6366 +
6367                         c = data[j];
6368                         fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
6369                 }
6370                 fprintf(stderr, "\n");
6371         }
6372  }
6373 -#endif 
6374 -
6375 -static int connection_handle_read(server *srv, connection *con) {
6376 -       int len;
6377 -       buffer *b;
6378 -       int toread;
6379 -#ifdef USE_OPENSSL
6380 -       server_socket *srv_sock = con->srv_socket;
6381  #endif
6382  
6383 -       b = chunkqueue_get_append_buffer(con->read_queue);
6384 -       buffer_prepare_copy(b, 4096);
6385 +static network_status_t connection_handle_read(server *srv, connection *con) {
6386 +       off_t oldlen, newlen;
6387  
6388 -#ifdef USE_OPENSSL
6389 -       if (srv_sock->is_ssl) {
6390 -               len = SSL_read(con->ssl, b->ptr, b->size - 1);
6391 -       } else {
6392 -               if (ioctl(con->fd, FIONREAD, &toread)) {
6393 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
6394 -                                       "unexpected end-of-file:",
6395 -                                       con->fd);
6396 -                       return -1;
6397 -               }
6398 -               buffer_prepare_copy(b, toread);
6399 +    oldlen = chunkqueue_length(con->read_queue);
6400  
6401 -               len = read(con->fd, b->ptr, b->size - 1);
6402 -       }
6403 -#elif defined(__WIN32)
6404 -       len = recv(con->fd, b->ptr, b->size - 1, 0);
6405 -#else
6406 -       if (ioctl(con->fd, FIONREAD, &toread)) {
6407 -               log_error_write(srv, __FILE__, __LINE__, "sd", 
6408 -                               "unexpected end-of-file:",
6409 -                               con->fd);
6410 -               return -1;
6411 -       }
6412 -       buffer_prepare_copy(b, toread);
6413 -
6414 -       len = read(con->fd, b->ptr, b->size - 1);
6415 -#endif
6416 -       
6417 -       if (len < 0) {
6418 -               con->is_readable = 0;
6419 -               
6420 -#ifdef USE_OPENSSL
6421 -               if (srv_sock->is_ssl) {
6422 -                       int r, ssl_err;
6423 -                       
6424 -                       switch ((r = SSL_get_error(con->ssl, len))) {
6425 -                       case SSL_ERROR_WANT_READ:
6426 -                               return 0;
6427 -                       case SSL_ERROR_SYSCALL:
6428 -                               /**
6429 -                                * man SSL_get_error()
6430 -                                * 
6431 -                                * SSL_ERROR_SYSCALL
6432 -                                *   Some I/O error occurred.  The OpenSSL error queue may contain more 
6433 -                                *   information on the error.  If the error queue is empty (i.e.
6434 -                                *   ERR_get_error() returns 0), ret can be used to find out more about 
6435 -                                *   the error: If ret == 0, an EOF was observed that violates the
6436 -                                *   protocol.  If ret == -1, the underlying BIO reported an I/O error 
6437 -                                *   (for socket I/O on Unix systems, consult errno for details).
6438 -                                *
6439 -                                */
6440 -                               while((ssl_err = ERR_get_error())) {
6441 -                                       /* get all errors from the error-queue */
6442 -                                       log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:", 
6443 -                                                       r, ERR_error_string(ssl_err, NULL));
6444 -                               }
6445 +    switch(network_read_chunkqueue(srv, con, con->read_queue)) {
6446 +    case NETWORK_STATUS_SUCCESS:
6447 +        break;
6448 +    case NETWORK_STATUS_WAIT_FOR_EVENT:
6449 +        con->is_readable = 0;
6450 +        return NETWORK_STATUS_WAIT_FOR_EVENT;
6451 +    case NETWORK_STATUS_INTERRUPTED:
6452 +        con->is_readable = 1;
6453 +        return NETWORK_STATUS_WAIT_FOR_EVENT;
6454 +    case NETWORK_STATUS_CONNECTION_CLOSE:
6455 +        /* pipelining */
6456 +        con->is_readable = 0;
6457 +        return NETWORK_STATUS_CONNECTION_CLOSE;
6458 +    case NETWORK_STATUS_FATAL_ERROR:
6459 +        con->is_readable = 0;
6460 +
6461 +        connection_set_state(srv, con, CON_STATE_ERROR);
6462 +        return NETWORK_STATUS_FATAL_ERROR;
6463 +    default:
6464 +        SEGFAULT();
6465 +        break;
6466 +    }
6467  
6468 -                               switch(errno) {
6469 -                               default:
6470 -                                       log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:", 
6471 -                                                       len, r, errno,
6472 -                                                       strerror(errno));
6473 -                                       break;
6474 -                               }
6475 -                               
6476 -                               break;
6477 -                       case SSL_ERROR_ZERO_RETURN:
6478 -                               /* clean shutdown on the remote side */
6479 -                               
6480 -                               if (r == 0) {
6481 -                                       /* FIXME: later */
6482 -                               }
6483 -                               
6484 -                               /* fall thourgh */
6485 -                       default:
6486 -                               while((ssl_err = ERR_get_error())) {
6487 -                                       /* get all errors from the error-queue */
6488 -                                       log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:", 
6489 -                                                       r, ERR_error_string(ssl_err, NULL));
6490 -                               }
6491 -                               break;
6492 -                       }
6493 -               } else {
6494 -                       if (errno == EAGAIN) return 0;
6495 -                       if (errno == EINTR) {
6496 -                               /* we have been interrupted before we could read */
6497 -                               con->is_readable = 1;
6498 -                               return 0;
6499 -                       }
6500 -               
6501 -                       if (errno != ECONNRESET) {
6502 -                               /* expected for keep-alive */
6503 -                               log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
6504 -                       }
6505 -               }
6506 -#else
6507 -               if (errno == EAGAIN) return 0;
6508 -               if (errno == EINTR) {
6509 -                       /* we have been interrupted before we could read */
6510 -                       con->is_readable = 1;
6511 -                       return 0;
6512 -               }
6513 -               
6514 -               if (errno != ECONNRESET) {
6515 -                       /* expected for keep-alive */
6516 -                       log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
6517 -               }
6518 -#endif
6519 -               connection_set_state(srv, con, CON_STATE_ERROR);
6520 -               
6521 -               return -1;
6522 -       } else if (len == 0) {
6523 -               con->is_readable = 0;
6524 -               /* the other end close the connection -> KEEP-ALIVE */
6525 -
6526 -               /* pipelining */
6527 -
6528 -               return -2;
6529 -       } else if ((size_t)len < b->size - 1) {
6530 -               /* we got less then expected, wait for the next fd-event */
6531 -               
6532 -               con->is_readable = 0;
6533 -       }
6534 -       
6535 -       b->used = len;
6536 -       b->ptr[b->used++] = '\0';
6537 -       
6538 -       con->bytes_read += len;
6539 -#if 0
6540 -       dump_packet(b->ptr, len);
6541 -#endif
6542 -       
6543 -       return 0;
6544 +    newlen = chunkqueue_length(con->read_queue);
6545 +
6546 +       con->bytes_read += (newlen - oldlen);
6547 +
6548 +       return NETWORK_STATUS_SUCCESS;
6549  }
6550  
6551  static int connection_handle_write_prepare(server *srv, connection *con) {
6552 @@ -343,6 +230,7 @@
6553                 case HTTP_METHOD_GET:
6554                 case HTTP_METHOD_POST:
6555                 case HTTP_METHOD_HEAD:
6556 +                       /* webdav */
6557                 case HTTP_METHOD_PUT:
6558                 case HTTP_METHOD_MKCOL:
6559                 case HTTP_METHOD_DELETE:
6560 @@ -350,12 +238,14 @@
6561                 case HTTP_METHOD_MOVE:
6562                 case HTTP_METHOD_PROPFIND:
6563                 case HTTP_METHOD_PROPPATCH:
6564 +               case HTTP_METHOD_LOCK:
6565 +               case HTTP_METHOD_UNLOCK:
6566                         break;
6567                 case HTTP_METHOD_OPTIONS:
6568                         /*
6569                          * 400 is coming from the request-parser BEFORE uri.path is set
6570 -                        * 403 is from the response handler when noone else catched it 
6571 -                        * 
6572 +                        * 403 is from the response handler when noone else catched it
6573 +                        *
6574                          * */
6575                         if (con->uri.path->used &&
6576                             con->uri.path->ptr[0] != '*') {
6577 @@ -381,55 +271,58 @@
6578                         break;
6579                 }
6580         }
6581 -       
6582 +
6583         if (con->http_status == 0) {
6584                 con->http_status = 403;
6585         }
6586 -       
6587 +
6588         switch(con->http_status) {
6589         case 400: /* class: header + custom body */
6590         case 401:
6591         case 403:
6592         case 404:
6593         case 408:
6594 +       case 409:
6595 +       case 410:
6596         case 411:
6597         case 416:
6598         case 423:
6599         case 500:
6600         case 501:
6601         case 503:
6602 -       case 505: 
6603 +       case 505:
6604 +       case 509:
6605                 if (con->mode != DIRECT) break;
6606 -               
6607 +
6608                 con->file_finished = 0;
6609 -               
6610 +
6611                 buffer_reset(con->physical.path);
6612 -                               
6613 +
6614                 /* try to send static errorfile */
6615                 if (!buffer_is_empty(con->conf.errorfile_prefix)) {
6616                         stat_cache_entry *sce = NULL;
6617 -                       
6618 +
6619                         buffer_copy_string_buffer(con->physical.path, con->conf.errorfile_prefix);
6620                         buffer_append_string(con->physical.path, get_http_status_body_name(con->http_status));
6621 -                       
6622 +
6623                         if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
6624                                 con->file_finished = 1;
6625 -                               
6626 +
6627                                 http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
6628                                 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
6629                         }
6630                 }
6631 -               
6632 -               if (!con->file_finished) {                      
6633 +
6634 +               if (!con->file_finished) {
6635                         buffer *b;
6636 -                       
6637 +
6638                         buffer_reset(con->physical.path);
6639 -                       
6640 +
6641                         con->file_finished = 1;
6642                         b = chunkqueue_get_append_buffer(con->write_queue);
6643 -                               
6644 +
6645                         /* build default error-page */
6646 -                       buffer_copy_string(b, 
6647 +                       buffer_copy_string(b,
6648                                            "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
6649                                            "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
6650                                            "         \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
6651 @@ -439,7 +332,7 @@
6652                         buffer_append_long(b, con->http_status);
6653                         buffer_append_string(b, " - ");
6654                         buffer_append_string(b, get_http_status_name(con->http_status));
6655 -                       
6656 +
6657                         buffer_append_string(b,
6658                                              "</title>\n"
6659                                              " </head>\n"
6660 @@ -448,12 +341,12 @@
6661                         buffer_append_long(b, con->http_status);
6662                         buffer_append_string(b, " - ");
6663                         buffer_append_string(b, get_http_status_name(con->http_status));
6664 -                       
6665 -                       buffer_append_string(b,"</h1>\n" 
6666 +
6667 +                       buffer_append_string(b,"</h1>\n"
6668                                              " </body>\n"
6669                                              "</html>\n"
6670                                              );
6671 -                       
6672 +
6673                         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
6674                 }
6675                 /* fall through */
6676 @@ -463,10 +356,10 @@
6677         case 301:
6678         case 302:
6679                 break;
6680 -               
6681 +
6682         case 206: /* write_queue is already prepared */
6683                 con->file_finished = 1;
6684 -               
6685 +
6686                 break;
6687         case 205: /* class: header only */
6688         case 304:
6689 @@ -474,19 +367,19 @@
6690                 /* disable chunked encoding again as we have no body */
6691                 con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
6692                 chunkqueue_reset(con->write_queue);
6693 -               
6694 +
6695                 con->file_finished = 1;
6696                 break;
6697         }
6698 -       
6699 +
6700  
6701         if (con->file_finished) {
6702 -               /* we have all the content and chunked encoding is not used, set a content-length */ 
6703 -               
6704 -               if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) && 
6705 +               /* we have all the content and chunked encoding is not used, set a content-length */
6706 +
6707 +               if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) &&
6708                     (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) {
6709                         buffer_copy_off_t(srv->tmp_buf, chunkqueue_length(con->write_queue));
6710 -               
6711 +
6712                         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf));
6713                 }
6714         } else {
6715 @@ -495,74 +388,77 @@
6716                     ((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0)) {
6717                         con->keep_alive = 0;
6718                 }
6719 -               
6720 +
6721                 if (0 == (con->parsed_response & HTTP_CONNECTION)) {
6722                         /* (f)cgi did'nt send Connection: header
6723 -                        *                          
6724 +                        *
6725                          * shall we ?
6726                          */
6727                         if (((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) &&
6728                             (con->parsed_response & HTTP_CONTENT_LENGTH) == 0) {
6729                                 /* without content_length, no keep-alive */
6730 -                               
6731 +
6732                                 con->keep_alive = 0;
6733                         }
6734                 } else {
6735                         /* a subrequest disable keep-alive although the client wanted it */
6736                         if (con->keep_alive && !con->response.keep_alive) {
6737                                 con->keep_alive = 0;
6738 -                               
6739 +
6740                                 /* FIXME: we have to drop the Connection: Header from the subrequest */
6741                         }
6742                 }
6743         }
6744 -       
6745 +
6746         if (con->request.http_method == HTTP_METHOD_HEAD) {
6747                 chunkqueue_reset(con->write_queue);
6748         }
6749  
6750         http_response_write_header(srv, con);
6751 -               
6752 +
6753         return 0;
6754  }
6755  
6756  static int connection_handle_write(server *srv, connection *con) {
6757 -       switch(network_write_chunkqueue(srv, con, con->write_queue)) {
6758 -       case 0:
6759 +    switch(network_write_chunkqueue(srv, con, con->write_queue)) {
6760 +       case NETWORK_STATUS_SUCCESS:
6761                 if (con->file_finished) {
6762                         connection_set_state(srv, con, CON_STATE_RESPONSE_END);
6763                         joblist_append(srv, con);
6764                 }
6765                 break;
6766 -       case -1: /* error on our side */
6767 +       case NETWORK_STATUS_FATAL_ERROR: /* error on our side */
6768                 log_error_write(srv, __FILE__, __LINE__, "sd",
6769                                 "connection closed: write failed on fd", con->fd);
6770                 connection_set_state(srv, con, CON_STATE_ERROR);
6771                 joblist_append(srv, con);
6772                 break;
6773 -       case -2: /* remote close */
6774 +       case NETWORK_STATUS_CONNECTION_CLOSE: /* remote close */
6775                 connection_set_state(srv, con, CON_STATE_ERROR);
6776                 joblist_append(srv, con);
6777                 break;
6778 -       case 1:
6779 +       case NETWORK_STATUS_WAIT_FOR_EVENT:
6780                 con->is_writable = 0;
6781 -               
6782 +
6783                 /* not finished yet -> WRITE */
6784                 break;
6785 +       case NETWORK_STATUS_INTERRUPTED:
6786 +               con->is_writable = 1;
6787 +               break;
6788 +       case NETWORK_STATUS_UNSET:
6789 +               break;
6790         }
6791 -       
6792 +
6793         return 0;
6794  }
6795  
6796 -
6797 -
6798  connection *connection_init(server *srv) {
6799         connection *con;
6800 -       
6801 +
6802         UNUSED(srv);
6803  
6804         con = calloc(1, sizeof(*con));
6805 -               
6806 +
6807         con->fd = 0;
6808         con->ndx = -1;
6809         con->fde_ndx = -1;
6810 @@ -573,32 +469,32 @@
6811  
6812  #define CLEAN(x) \
6813         con->x = buffer_init();
6814 -       
6815 +
6816         CLEAN(request.uri);
6817         CLEAN(request.request_line);
6818         CLEAN(request.request);
6819         CLEAN(request.pathinfo);
6820 -       
6821 +
6822         CLEAN(request.orig_uri);
6823 -       
6824 +
6825         CLEAN(uri.scheme);
6826         CLEAN(uri.authority);
6827         CLEAN(uri.path);
6828         CLEAN(uri.path_raw);
6829         CLEAN(uri.query);
6830 -       
6831 +
6832         CLEAN(physical.doc_root);
6833         CLEAN(physical.path);
6834         CLEAN(physical.basedir);
6835         CLEAN(physical.rel_path);
6836         CLEAN(physical.etag);
6837         CLEAN(parse_request);
6838 -       
6839 +
6840         CLEAN(authed_user);
6841         CLEAN(server_name);
6842         CLEAN(error_handler);
6843         CLEAN(dst_addr_buf);
6844 -       
6845 +
6846  #undef CLEAN
6847         con->write_queue = chunkqueue_init();
6848         con->read_queue = chunkqueue_init();
6849 @@ -608,26 +504,26 @@
6850         con->request.headers      = array_init();
6851         con->response.headers     = array_init();
6852         con->environment     = array_init();
6853 -       
6854 +
6855         /* init plugin specific connection structures */
6856 -       
6857 +
6858         con->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *));
6859 -       
6860 +
6861         con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t));
6862         config_setup_connection(srv, con);
6863 -       
6864 +
6865         return con;
6866  }
6867  
6868  void connections_free(server *srv) {
6869         connections *conns = srv->conns;
6870 -       size_t i;       
6871 -       
6872 +       size_t i;
6873 +
6874         for (i = 0; i < conns->size; i++) {
6875                 connection *con = conns->ptr[i];
6876 -               
6877 +
6878                 connection_reset(srv, con);
6879 -               
6880 +
6881                 chunkqueue_free(con->write_queue);
6882                 chunkqueue_free(con->read_queue);
6883                 chunkqueue_free(con->request_content_queue);
6884 @@ -637,27 +533,27 @@
6885  
6886  #define CLEAN(x) \
6887         buffer_free(con->x);
6888 -               
6889 +
6890                 CLEAN(request.uri);
6891                 CLEAN(request.request_line);
6892                 CLEAN(request.request);
6893                 CLEAN(request.pathinfo);
6894 -               
6895 +
6896                 CLEAN(request.orig_uri);
6897 -               
6898 +
6899                 CLEAN(uri.scheme);
6900                 CLEAN(uri.authority);
6901                 CLEAN(uri.path);
6902                 CLEAN(uri.path_raw);
6903                 CLEAN(uri.query);
6904 -               
6905 +
6906                 CLEAN(physical.doc_root);
6907                 CLEAN(physical.path);
6908                 CLEAN(physical.basedir);
6909                 CLEAN(physical.etag);
6910                 CLEAN(physical.rel_path);
6911                 CLEAN(parse_request);
6912 -               
6913 +
6914                 CLEAN(authed_user);
6915                 CLEAN(server_name);
6916                 CLEAN(error_handler);
6917 @@ -665,97 +561,97 @@
6918  #undef CLEAN
6919                 free(con->plugin_ctx);
6920                 free(con->cond_cache);
6921 -               
6922 +
6923                 free(con);
6924         }
6925 -       
6926 +
6927         free(conns->ptr);
6928  }
6929  
6930  
6931  int connection_reset(server *srv, connection *con) {
6932         size_t i;
6933 -       
6934 +
6935         plugins_call_connection_reset(srv, con);
6936 -       
6937 +
6938         con->is_readable = 1;
6939         con->is_writable = 1;
6940         con->http_status = 0;
6941         con->file_finished = 0;
6942         con->file_started = 0;
6943         con->got_response = 0;
6944 -       
6945 +
6946         con->parsed_response = 0;
6947 -       
6948 +
6949         con->bytes_written = 0;
6950         con->bytes_written_cur_second = 0;
6951         con->bytes_read = 0;
6952         con->bytes_header = 0;
6953         con->loops_per_request = 0;
6954 -       
6955 +
6956         con->request.http_method = HTTP_METHOD_UNSET;
6957         con->request.http_version = HTTP_VERSION_UNSET;
6958 -       
6959 +
6960         con->request.http_if_modified_since = NULL;
6961         con->request.http_if_none_match = NULL;
6962 -       
6963 +
6964         con->response.keep_alive = 0;
6965         con->response.content_length = -1;
6966         con->response.transfer_encoding = 0;
6967 -       
6968 +
6969         con->mode = DIRECT;
6970 -       
6971 +
6972  #define CLEAN(x) \
6973         if (con->x) buffer_reset(con->x);
6974 -       
6975 +
6976         CLEAN(request.uri);
6977         CLEAN(request.request_line);
6978         CLEAN(request.pathinfo);
6979         CLEAN(request.request);
6980 -       
6981 +
6982         CLEAN(request.orig_uri);
6983 -       
6984 +
6985         CLEAN(uri.scheme);
6986         CLEAN(uri.authority);
6987         CLEAN(uri.path);
6988         CLEAN(uri.path_raw);
6989         CLEAN(uri.query);
6990 -       
6991 +
6992         CLEAN(physical.doc_root);
6993         CLEAN(physical.path);
6994         CLEAN(physical.basedir);
6995         CLEAN(physical.rel_path);
6996         CLEAN(physical.etag);
6997 -       
6998 +
6999         CLEAN(parse_request);
7000 -       
7001 +
7002         CLEAN(authed_user);
7003         CLEAN(server_name);
7004         CLEAN(error_handler);
7005 -#undef CLEAN   
7006 -       
7007 +#undef CLEAN
7008 +
7009  #define CLEAN(x) \
7010 -       if (con->x) con->x->used = 0;   
7011 -       
7012 +       if (con->x) con->x->used = 0;
7013 +
7014  #undef CLEAN
7015 -       
7016 +
7017  #define CLEAN(x) \
7018                 con->request.x = NULL;
7019 -       
7020 +
7021         CLEAN(http_host);
7022         CLEAN(http_range);
7023         CLEAN(http_content_type);
7024  #undef CLEAN
7025         con->request.content_length = 0;
7026 -       
7027 +
7028         array_reset(con->request.headers);
7029         array_reset(con->response.headers);
7030         array_reset(con->environment);
7031 -       
7032 +
7033         chunkqueue_reset(con->write_queue);
7034         chunkqueue_reset(con->request_content_queue);
7035  
7036 -       /* the plugins should cleanup themself */       
7037 +       /* the plugins should cleanup themself */
7038         for (i = 0; i < srv->plugins.used; i++) {
7039                 plugin *p = ((plugin **)(srv->plugins.ptr))[i];
7040                 plugin_data *pd = p->data;
7041 @@ -768,7 +664,7 @@
7042  
7043                 con->plugin_ctx[pd->id] = NULL;
7044         }
7045 -       
7046 +
7047  #if COND_RESULT_UNSET
7048         for (i = srv->config_context->used - 1; i >= 0; i --) {
7049                 con->cond_cache[i].result = COND_RESULT_UNSET;
7050 @@ -777,56 +673,56 @@
7051  #else
7052         memset(con->cond_cache, 0, sizeof(cond_cache_t) * srv->config_context->used);
7053  #endif
7054 -       
7055 +
7056         con->header_len = 0;
7057         con->in_error_handler = 0;
7058 -       
7059 +
7060         config_setup_connection(srv, con);
7061 -       
7062 +
7063         return 0;
7064  }
7065  
7066  /**
7067 - * 
7068 - * search for \r\n\r\n 
7069 - * 
7070 + *
7071 + * search for \r\n\r\n
7072 + *
7073   * this is a special 32bit version which is using a sliding window for
7074 - * the comparisions 
7075 - * 
7076 + * the comparisions
7077 + *
7078   * how it works:
7079 - * 
7080 + *
7081   * b:      'abcdefg'
7082   * rnrn:   'cdef'
7083 - * 
7084 + *
7085   * cmpbuf: abcd != cdef
7086   * cmpbuf: bcde != cdef
7087   * cmpbuf: cdef == cdef -> return &c
7088 - * 
7089 - * cmpbuf and rnrn are treated as 32bit uint and bit-ops are used to 
7090 + *
7091 + * cmpbuf and rnrn are treated as 32bit uint and bit-ops are used to
7092   * maintain cmpbuf and rnrn
7093 - * 
7094 + *
7095   */
7096  
7097  char *buffer_search_rnrn(buffer *b) {
7098         uint32_t cmpbuf, rnrn;
7099         char *cp;
7100         size_t i;
7101 -       
7102 +
7103         if (b->used < 4) return NULL;
7104 -       
7105 +
7106         rnrn = ('\r' << 24) | ('\n' << 16) |
7107                 ('\r' << 8) | ('\n' << 0);
7108 -       
7109 +
7110         cmpbuf = (b->ptr[0] << 24) | (b->ptr[1] << 16) |
7111                 (b->ptr[2] << 8) | (b->ptr[3] << 0);
7112 -               
7113 +
7114         cp = b->ptr + 4;
7115         for (i = 0; i < b->used - 4; i++) {
7116                 if (cmpbuf == rnrn) return cp - 4;
7117 -                       
7118 +
7119                 cmpbuf = (cmpbuf << 8 | *(cp++)) & 0xffffffff;
7120         }
7121 -       
7122 +
7123         return NULL;
7124  }
7125  /**
7126 @@ -840,22 +736,25 @@
7127         chunk *c;
7128         chunkqueue *cq = con->read_queue;
7129         chunkqueue *dst_cq = con->request_content_queue;
7130 -       
7131 +
7132         if (con->is_readable) {
7133                 con->read_idle_ts = srv->cur_ts;
7134 -       
7135 +
7136                 switch(connection_handle_read(srv, con)) {
7137 -               case -1:
7138 +               case NETWORK_STATUS_FATAL_ERROR:
7139                         return -1;
7140 -               case -2:
7141 +               case NETWORK_STATUS_CONNECTION_CLOSE:
7142                         /* remote side closed the connection
7143                          * if we still have content, handle it, if not leave here */
7144  
7145                         if (cq->first == cq->last &&
7146 -                           cq->first->mem->used == 0) {
7147 +                (NULL == cq->first ||
7148 +                           cq->first->mem->used == 0)) {
7149  
7150                                 /* conn-closed, leave here */
7151                                 connection_set_state(srv, con, CON_STATE_ERROR);
7152 +
7153 +                return 0;
7154                         }
7155                 default:
7156                         break;
7157 @@ -891,14 +790,14 @@
7158                         /* the last node was empty */
7159                         if (c->next == NULL) {
7160                                 cq->last = c;
7161 -                       } 
7162 +                       }
7163  
7164                         c = c->next;
7165                 } else {
7166                         c = c->next;
7167                 }
7168         }
7169 -       
7170 +
7171         /* nothing to handle */
7172         if (cq->first == NULL) return 0;
7173  
7174 @@ -906,25 +805,26 @@
7175         case CON_STATE_READ:
7176                 /* prepare con->request.request */
7177                 c = cq->first;
7178 -               
7179 +
7180                 /* check if we need the full package */
7181                 if (con->request.request->used == 0) {
7182                         buffer b;
7183 -                       
7184 +
7185                         b.ptr = c->mem->ptr + c->offset;
7186                         b.used = c->mem->used - c->offset;
7187 -                       
7188 +
7189                         if (NULL != (h_term = buffer_search_rnrn(&b))) {
7190                                 /* \r\n\r\n found
7191                                  * - copy everything incl. the terminator to request.request
7192                                  */
7193 -                               
7194 -                               buffer_copy_string_len(con->request.request, 
7195 -                                                      b.ptr, 
7196 +
7197 +                               buffer_copy_string_len(con->request.request,
7198 +                                                      b.ptr,
7199                                                        h_term - b.ptr + 4);
7200 -                               
7201 +
7202                                 /* the buffer has been read up to the terminator */
7203                                 c->offset += h_term - b.ptr + 4;
7204 +
7205                         } else {
7206                                 /* not found, copy everything */
7207                                 buffer_copy_string_len(con->request.request, c->mem->ptr + c->offset, c->mem->used - c->offset - 1);
7208 @@ -932,14 +832,14 @@
7209                         }
7210                 } else {
7211                         /* have to take care of overlapping header terminators */
7212 -                       
7213 +
7214                         size_t l = con->request.request->used - 2;
7215                         char *s  = con->request.request->ptr;
7216                         buffer b;
7217 -                       
7218 +
7219                         b.ptr = c->mem->ptr + c->offset;
7220                         b.used = c->mem->used - c->offset;
7221 -                       
7222 +
7223                         if (con->request.request->used - 1 > 3 &&
7224                             c->mem->used > 1 &&
7225                             s[l-2] == '\r' &&
7226 @@ -948,7 +848,7 @@
7227                             c->mem->ptr[0] == '\n') {
7228                                 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 1);
7229                                 c->offset += 1;
7230 -                               
7231 +
7232                                 h_term = con->request.request->ptr;
7233                         } else if (con->request.request->used - 1 > 2 &&
7234                                    c->mem->used > 2 &&
7235 @@ -958,7 +858,7 @@
7236                                    c->mem->ptr[1] == '\n') {
7237                                 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 2);
7238                                 c->offset += 2;
7239 -                               
7240 +
7241                                 h_term = con->request.request->ptr;
7242                         } else if (con->request.request->used - 1 > 1 &&
7243                                    c->mem->used > 3 &&
7244 @@ -968,17 +868,17 @@
7245                                    c->mem->ptr[2] == '\n') {
7246                                 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 3);
7247                                 c->offset += 3;
7248 -                               
7249 +
7250                                 h_term = con->request.request->ptr;
7251                         } else if (NULL != (h_term = buffer_search_string_len(&b, "\r\n\r\n", 4))) {
7252                                 /* \r\n\r\n found
7253                                  * - copy everything incl. the terminator to request.request
7254                                  */
7255 -                               
7256 -                               buffer_append_string_len(con->request.request, 
7257 -                                                      c->mem->ptr + c->offset, 
7258 +
7259 +                               buffer_append_string_len(con->request.request,
7260 +                                                      c->mem->ptr + c->offset,
7261                                                        c->offset + h_term - b.ptr + 4);
7262 -                               
7263 +
7264                                 /* the buffer has been read up to the terminator */
7265                                 c->offset += h_term - b.ptr + 4;
7266                         } else {
7267 @@ -999,16 +899,16 @@
7268                         connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7269                 }
7270                 break;
7271 -       case CON_STATE_READ_POST: 
7272 +       case CON_STATE_READ_POST:
7273                 for (c = cq->first; c && (dst_cq->bytes_in != (off_t)con->request.content_length); c = c->next) {
7274                         off_t weWant, weHave, toRead;
7275 -                       
7276 +
7277                         weWant = con->request.content_length - dst_cq->bytes_in;
7278 -                       
7279 +
7280                         assert(c->mem->used);
7281 -                       
7282 +
7283                         weHave = c->mem->used - c->offset - 1;
7284 -                               
7285 +
7286                         toRead = weHave > weWant ? weWant : weHave;
7287  
7288                         /* the new way, copy everything into a chunkqueue whcih might use tempfiles */
7289 @@ -1017,13 +917,13 @@
7290                                 /* copy everything to max 1Mb sized tempfiles */
7291  
7292                                 /*
7293 -                                * if the last chunk is 
7294 +                                * if the last chunk is
7295                                  * - smaller than 1Mb (size < 1Mb)
7296                                  * - not read yet (offset == 0)
7297                                  * -> append to it
7298                                  * otherwise
7299 -                                * -> create a new chunk 
7300 -                                * 
7301 +                                * -> create a new chunk
7302 +                                *
7303                                  * */
7304  
7305                                 if (dst_cq->last &&
7306 @@ -1056,14 +956,14 @@
7307                                 /* we have a chunk, let's write to it */
7308  
7309                                 if (dst_c->file.fd == -1) {
7310 -                                       /* we don't have file to write to, 
7311 +                                       /* we don't have file to write to,
7312                                          * EACCES might be one reason.
7313                                          *
7314                                          * Instead of sending 500 we send 413 and say the request is too large
7315                                          *  */
7316  
7317                                         log_error_write(srv, __FILE__, __LINE__, "sbs",
7318 -                                                       "denying upload as opening to temp-file for upload failed:", 
7319 +                                                       "denying upload as opening to temp-file for upload failed:",
7320                                                         dst_c->file.name, strerror(errno));
7321  
7322                                         con->http_status = 413; /* Request-Entity too large */
7323 @@ -1074,15 +974,15 @@
7324                                 }
7325  
7326                                 if (toRead != write(dst_c->file.fd, c->mem->ptr + c->offset, toRead)) {
7327 -                                       /* write failed for some reason ... disk full ? */ 
7328 +                                       /* write failed for some reason ... disk full ? */
7329                                         log_error_write(srv, __FILE__, __LINE__, "sbs",
7330 -                                                       "denying upload as writing to file failed:", 
7331 +                                                       "denying upload as writing to file failed:",
7332                                                         dst_c->file.name, strerror(errno));
7333 -                                       
7334 +
7335                                         con->http_status = 413; /* Request-Entity too large */
7336                                         con->keep_alive = 0;
7337                                         connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7338 -                               
7339 +
7340                                         close(dst_c->file.fd);
7341                                         dst_c->file.fd = -1;
7342  
7343 @@ -1090,7 +990,7 @@
7344                                 }
7345  
7346                                 dst_c->file.length += toRead;
7347 -                                       
7348 +
7349                                 if (dst_cq->bytes_in + toRead == (off_t)con->request.content_length) {
7350                                         /* we read everything, close the chunk */
7351                                         close(dst_c->file.fd);
7352 @@ -1102,7 +1002,7 @@
7353                                 b = chunkqueue_get_append_buffer(dst_cq);
7354                                 buffer_copy_string_len(b, c->mem->ptr + c->offset, toRead);
7355                         }
7356 -                       
7357 +
7358                         c->offset += toRead;
7359                         dst_cq->bytes_in += toRead;
7360                 }
7361 @@ -1111,7 +1011,7 @@
7362                 if (dst_cq->bytes_in == (off_t)con->request.content_length) {
7363                         connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7364                 }
7365 -                       
7366 +
7367                 break;
7368         }
7369  
7370 @@ -1123,9 +1023,9 @@
7371  handler_t connection_handle_fdevent(void *s, void *context, int revents) {
7372         server     *srv = (server *)s;
7373         connection *con = context;
7374 -       
7375 +
7376         joblist_append(srv, con);
7377 -       
7378 +
7379         if (revents & FDEVENT_IN) {
7380                 con->is_readable = 1;
7381  #if 0
7382 @@ -1136,19 +1036,19 @@
7383                 con->is_writable = 1;
7384                 /* we don't need the event twice */
7385         }
7386 -       
7387 -       
7388 +
7389 +
7390         if (revents & ~(FDEVENT_IN | FDEVENT_OUT)) {
7391                 /* looks like an error */
7392 -                                               
7393 +
7394                 /* FIXME: revents = 0x19 still means that we should read from the queue */
7395                 if (revents & FDEVENT_HUP) {
7396                         if (con->state == CON_STATE_CLOSE) {
7397                                 con->close_timeout_ts = 0;
7398                         } else {
7399                                 /* sigio reports the wrong event here
7400 -                                * 
7401 -                                * there was no HUP at all 
7402 +                                *
7403 +                                * there was no HUP at all
7404                                  */
7405  #ifdef USE_LINUX_SIGIO
7406                                 if (srv->ev->in_sigio == 1) {
7407 @@ -1160,32 +1060,39 @@
7408  #else
7409                                 connection_set_state(srv, con, CON_STATE_ERROR);
7410  #endif
7411 -                               
7412 +
7413                         }
7414                 } else if (revents & FDEVENT_ERR) {
7415  #ifndef USE_LINUX_SIGIO
7416                         log_error_write(srv, __FILE__, __LINE__, "sd",
7417                                         "connection closed: poll() -> ERR", con->fd);
7418 -#endif 
7419 +#endif
7420                         connection_set_state(srv, con, CON_STATE_ERROR);
7421                 } else {
7422                         log_error_write(srv, __FILE__, __LINE__, "sd",
7423                                         "connection closed: poll() -> ???", revents);
7424 -               } 
7425 +               }
7426         }
7427 -       
7428 +
7429         if (con->state == CON_STATE_READ ||
7430             con->state == CON_STATE_READ_POST) {
7431                 connection_handle_read_state(srv, con);
7432 +               /**
7433 +                * if SSL_read() is not readin in the full packet we won't get
7434 +                * a fdevent as the low-level has already fetched everything.
7435 +                *
7436 +                * we have to call the state-engine to read the rest of the packet
7437 +                */
7438 +               if (con->is_readable) joblist_append(srv, con);
7439         }
7440 -       
7441 +
7442         if (con->state == CON_STATE_WRITE &&
7443             !chunkqueue_is_empty(con->write_queue) &&
7444             con->is_writable) {
7445 -               
7446 +
7447                 if (-1 == connection_handle_write(srv, con)) {
7448                         connection_set_state(srv, con, CON_STATE_ERROR);
7449 -                       
7450 +
7451                         log_error_write(srv, __FILE__, __LINE__, "ds",
7452                                         con->fd,
7453                                         "handle write failed.");
7454 @@ -1193,30 +1100,30 @@
7455                         con->write_request_ts = srv->cur_ts;
7456                 }
7457         }
7458 -       
7459 +
7460         if (con->state == CON_STATE_CLOSE) {
7461                 /* flush the read buffers */
7462                 int b;
7463 -               
7464 +
7465                 if (ioctl(con->fd, FIONREAD, &b)) {
7466                         log_error_write(srv, __FILE__, __LINE__, "ss",
7467                                         "ioctl() failed", strerror(errno));
7468                 }
7469 -               
7470 +
7471                 if (b > 0) {
7472                         char buf[1024];
7473                         log_error_write(srv, __FILE__, __LINE__, "sdd",
7474                                         "CLOSE-read()", con->fd, b);
7475 -                       
7476 +
7477                         /* */
7478                         read(con->fd, buf, sizeof(buf));
7479                 } else {
7480                         /* nothing to read */
7481 -                       
7482 +
7483                         con->close_timeout_ts = 0;
7484                 }
7485         }
7486 -       
7487 +
7488         return HANDLER_FINISHED;
7489  }
7490  
7491 @@ -1229,63 +1136,68 @@
7492         sock_addr cnt_addr;
7493         socklen_t cnt_len;
7494         /* accept it and register the fd */
7495 -       
7496 +
7497         cnt_len = sizeof(cnt_addr);
7498  
7499         if (-1 == (cnt = accept(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) {
7500 +#ifdef _WIN32
7501 +        errno = WSAGetLastError();
7502 +#endif
7503                 if ((errno != EAGAIN) &&
7504 +            (errno != EWOULDBLOCK) &&
7505                     (errno != EINTR)) {
7506 -                       log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), errno);
7507 +                       log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), srv_socket->fd);
7508                 }
7509                 return NULL;
7510         } else {
7511                 connection *con;
7512 -               
7513 +
7514                 srv->cur_fds++;
7515 -               
7516 +
7517                 /* ok, we have the connection, register it */
7518  #if 0
7519                 log_error_write(srv, __FILE__, __LINE__, "sd",
7520                                 "appected()", cnt);
7521  #endif
7522                 srv->con_opened++;
7523 -               
7524 +
7525                 con = connections_get_new_connection(srv);
7526 -               
7527                 con->fd = cnt;
7528                 con->fde_ndx = -1;
7529 -#if 0          
7530 +#if 0
7531                 gettimeofday(&(con->start_tv), NULL);
7532 -#endif         
7533 +#endif
7534                 fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con);
7535 -               
7536 +
7537                 connection_set_state(srv, con, CON_STATE_REQUEST_START);
7538 -               
7539 +
7540                 con->connection_start = srv->cur_ts;
7541                 con->dst_addr = cnt_addr;
7542                 buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
7543                 con->srv_socket = srv_socket;
7544 -               
7545 +
7546                 if (-1 == (fdevent_fcntl_set(srv->ev, con->fd))) {
7547                         log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
7548 +                       connection_close(srv, con);
7549                         return NULL;
7550                 }
7551  #ifdef USE_OPENSSL
7552                 /* connect FD to SSL */
7553                 if (srv_socket->is_ssl) {
7554                         if (NULL == (con->ssl = SSL_new(srv_socket->ssl_ctx))) {
7555 -                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", 
7556 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7557                                                 ERR_error_string(ERR_get_error(), NULL));
7558 -                               
7559 +                               connection_close(srv, con);
7560                                 return NULL;
7561                         }
7562 -                       
7563 +
7564                         SSL_set_accept_state(con->ssl);
7565                         con->conf.is_ssl=1;
7566 -                       
7567 +
7568                         if (1 != (SSL_set_fd(con->ssl, cnt))) {
7569 -                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", 
7570 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7571                                                 ERR_error_string(ERR_get_error(), NULL));
7572 +                               connection_close(srv, con);
7573                                 return NULL;
7574                         }
7575                 }
7576 @@ -1300,10 +1212,10 @@
7577  #ifdef USE_OPENSSL
7578         server_socket *srv_sock = con->srv_socket;
7579  #endif
7580 -       
7581 +
7582         if (srv->srvconf.log_state_handling) {
7583 -               log_error_write(srv, __FILE__, __LINE__, "sds", 
7584 -                               "state at start", 
7585 +               log_error_write(srv, __FILE__, __LINE__, "sds",
7586 +                               "state at start",
7587                                 con->fd,
7588                                 connection_get_state(con->state));
7589         }
7590 @@ -1311,91 +1223,91 @@
7591         while (done == 0) {
7592                 size_t ostate = con->state;
7593                 int b;
7594 -               
7595 +
7596                 switch (con->state) {
7597                 case CON_STATE_REQUEST_START: /* transient */
7598                         if (srv->srvconf.log_state_handling) {
7599 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7600 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7601                                                 "state for fd", con->fd, connection_get_state(con->state));
7602                         }
7603 -                       
7604 +
7605                         con->request_start = srv->cur_ts;
7606                         con->read_idle_ts = srv->cur_ts;
7607 -                       
7608 +
7609                         con->request_count++;
7610                         con->loops_per_request = 0;
7611 -                       
7612 +
7613                         connection_set_state(srv, con, CON_STATE_READ);
7614 -                       
7615 +
7616                         break;
7617                 case CON_STATE_REQUEST_END: /* transient */
7618                         if (srv->srvconf.log_state_handling) {
7619 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7620 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7621                                                 "state for fd", con->fd, connection_get_state(con->state));
7622                         }
7623 -                       
7624 +
7625                         if (http_request_parse(srv, con)) {
7626                                 /* we have to read some data from the POST request */
7627 -                               
7628 +
7629                                 connection_set_state(srv, con, CON_STATE_READ_POST);
7630  
7631                                 break;
7632                         }
7633 -                       
7634 +
7635                         connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7636 -                       
7637 +
7638                         break;
7639                 case CON_STATE_HANDLE_REQUEST:
7640 -                       /* 
7641 +                       /*
7642                          * the request is parsed
7643 -                        * 
7644 +                        *
7645                          * decided what to do with the request
7646 -                        * - 
7647 -                        * 
7648 -                        * 
7649 +                        * -
7650 +                        *
7651 +                        *
7652                          */
7653 -                       
7654 +
7655                         if (srv->srvconf.log_state_handling) {
7656 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7657 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7658                                                 "state for fd", con->fd, connection_get_state(con->state));
7659                         }
7660 -                       
7661 +
7662                         switch (r = http_response_prepare(srv, con)) {
7663                         case HANDLER_FINISHED:
7664                                 if (con->http_status == 404 ||
7665                                     con->http_status == 403) {
7666                                         /* 404 error-handler */
7667 -                                       
7668 -                                       if (con->in_error_handler == 0 && 
7669 +
7670 +                                       if (con->in_error_handler == 0 &&
7671                                             (!buffer_is_empty(con->conf.error_handler) ||
7672                                              !buffer_is_empty(con->error_handler))) {
7673                                                 /* call error-handler */
7674 -                                               
7675 +
7676                                                 con->error_handler_saved_status = con->http_status;
7677                                                 con->http_status = 0;
7678 -                                               
7679 +
7680                                                 if (buffer_is_empty(con->error_handler)) {
7681                                                         buffer_copy_string_buffer(con->request.uri, con->conf.error_handler);
7682                                                 } else {
7683                                                         buffer_copy_string_buffer(con->request.uri, con->error_handler);
7684                                                 }
7685                                                 buffer_reset(con->physical.path);
7686 -                                               
7687 +
7688                                                 con->in_error_handler = 1;
7689 -                                               
7690 +
7691                                                 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7692 -                                               
7693 +
7694                                                 done = -1;
7695                                                 break;
7696                                         } else if (con->in_error_handler) {
7697                                                 /* error-handler is a 404 */
7698 -                                               
7699 +
7700                                                 /* continue as normal, status is the same */
7701 -                                               log_error_write(srv, __FILE__, __LINE__, "sb", 
7702 +                                               log_error_write(srv, __FILE__, __LINE__, "sb",
7703                                                                 "Warning: Either the error-handler returned status 404 or the error-handler itself was not found:", con->request.uri);
7704 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
7705 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
7706                                                                 "returning the original status", con->error_handler_saved_status);
7707 -                                               log_error_write(srv, __FILE__, __LINE__, "s", 
7708 +                                               log_error_write(srv, __FILE__, __LINE__, "s",
7709                                                                 "If this is a rails app: check your production.log");
7710                                                 con->http_status = con->error_handler_saved_status;
7711                                         }
7712 @@ -1403,26 +1315,26 @@
7713                                         /* error-handler is back and has generated content */
7714                                         /* if Status: was set, take it otherwise use 200 */
7715                                 }
7716 -                               
7717 +
7718                                 if (con->http_status == 0) con->http_status = 200;
7719 -                               
7720 +
7721                                 /* we have something to send, go on */
7722                                 connection_set_state(srv, con, CON_STATE_RESPONSE_START);
7723                                 break;
7724                         case HANDLER_WAIT_FOR_FD:
7725                                 srv->want_fds++;
7726 -                               
7727 +
7728                                 fdwaitqueue_append(srv, con);
7729 -                               
7730 +
7731                                 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7732 -                               
7733 +
7734                                 break;
7735                         case HANDLER_COMEBACK:
7736                                 done = -1;
7737                         case HANDLER_WAIT_FOR_EVENT:
7738                                 /* come back here */
7739                                 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7740 -                               
7741 +
7742                                 break;
7743                         case HANDLER_ERROR:
7744                                 /* something went wrong */
7745 @@ -1432,44 +1344,44 @@
7746                                 log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r);
7747                                 break;
7748                         }
7749 -                       
7750 +
7751                         break;
7752                 case CON_STATE_RESPONSE_START:
7753 -                       /* 
7754 +                       /*
7755                          * the decision is done
7756                          * - create the HTTP-Response-Header
7757 -                        * 
7758 +                        *
7759                          */
7760 -                       
7761 +
7762                         if (srv->srvconf.log_state_handling) {
7763 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7764 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7765                                                 "state for fd", con->fd, connection_get_state(con->state));
7766                         }
7767 -                       
7768 +
7769                         if (-1 == connection_handle_write_prepare(srv, con)) {
7770                                 connection_set_state(srv, con, CON_STATE_ERROR);
7771 -                               
7772 +
7773                                 break;
7774                         }
7775 -                       
7776 +
7777                         connection_set_state(srv, con, CON_STATE_WRITE);
7778                         break;
7779                 case CON_STATE_RESPONSE_END: /* transient */
7780                         /* log the request */
7781 -                       
7782 +
7783                         if (srv->srvconf.log_state_handling) {
7784 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7785 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7786                                                 "state for fd", con->fd, connection_get_state(con->state));
7787                         }
7788 -                       
7789 +
7790                         plugins_call_handle_request_done(srv, con);
7791 -                       
7792 +
7793                         srv->con_written++;
7794 -                       
7795 +
7796                         if (con->keep_alive) {
7797                                 connection_set_state(srv, con, CON_STATE_REQUEST_START);
7798 -                               
7799 -#if 0                                  
7800 +
7801 +#if 0
7802                                 con->request_start = srv->cur_ts;
7803                                 con->read_idle_ts = srv->cur_ts;
7804  #endif
7805 @@ -1482,7 +1394,7 @@
7806                                         log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r);
7807                                         break;
7808                                 }
7809 -                               
7810 +
7811  #ifdef USE_OPENSSL
7812                                 if (srv_sock->is_ssl) {
7813                                         switch (SSL_shutdown(con->ssl)) {
7814 @@ -1490,44 +1402,44 @@
7815                                                 /* done */
7816                                                 break;
7817                                         case 0:
7818 -                                               /* wait for fd-event 
7819 -                                                * 
7820 +                                               /* wait for fd-event
7821 +                                                *
7822                                                  * FIXME: wait for fdevent and call SSL_shutdown again
7823 -                                                * 
7824 +                                                *
7825                                                  */
7826 -                                               
7827 +
7828                                                 break;
7829                                         default:
7830 -                                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", 
7831 +                                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7832                                                                 ERR_error_string(ERR_get_error(), NULL));
7833                                         }
7834                                 }
7835  #endif
7836                                 connection_close(srv, con);
7837 -                               
7838 +
7839                                 srv->con_closed++;
7840                         }
7841 -                       
7842 +
7843                         connection_reset(srv, con);
7844 -                       
7845 +
7846                         break;
7847                 case CON_STATE_CONNECT:
7848                         if (srv->srvconf.log_state_handling) {
7849 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7850 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7851                                                 "state for fd", con->fd, connection_get_state(con->state));
7852                         }
7853 -                       
7854 +
7855                         chunkqueue_reset(con->read_queue);
7856 -                       
7857 +
7858                         con->request_count = 0;
7859 -                       
7860 +
7861                         break;
7862                 case CON_STATE_CLOSE:
7863                         if (srv->srvconf.log_state_handling) {
7864 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7865 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7866                                                 "state for fd", con->fd, connection_get_state(con->state));
7867                         }
7868 -                       
7869 +
7870                         if (con->keep_alive) {
7871                                 if (ioctl(con->fd, FIONREAD, &b)) {
7872                                         log_error_write(srv, __FILE__, __LINE__, "ss",
7873 @@ -1537,43 +1449,43 @@
7874                                         char buf[1024];
7875                                         log_error_write(srv, __FILE__, __LINE__, "sdd",
7876                                                         "CLOSE-read()", con->fd, b);
7877 -                                       
7878 +
7879                                         /* */
7880                                         read(con->fd, buf, sizeof(buf));
7881                                 } else {
7882                                         /* nothing to read */
7883 -                                       
7884 +
7885                                         con->close_timeout_ts = 0;
7886                                 }
7887                         } else {
7888                                 con->close_timeout_ts = 0;
7889                         }
7890 -                       
7891 +
7892                         if (srv->cur_ts - con->close_timeout_ts > 1) {
7893                                 connection_close(srv, con);
7894 -                               
7895 +
7896                                 if (srv->srvconf.log_state_handling) {
7897 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
7898 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
7899                                                         "connection closed for fd", con->fd);
7900                                 }
7901                         }
7902 -                       
7903 +
7904                         break;
7905                 case CON_STATE_READ_POST:
7906                 case CON_STATE_READ:
7907                         if (srv->srvconf.log_state_handling) {
7908 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7909 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7910                                                 "state for fd", con->fd, connection_get_state(con->state));
7911                         }
7912 -                       
7913 +
7914                         connection_handle_read_state(srv, con);
7915                         break;
7916                 case CON_STATE_WRITE:
7917                         if (srv->srvconf.log_state_handling) {
7918 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7919 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7920                                                 "state for fd", con->fd, connection_get_state(con->state));
7921                         }
7922 -                       
7923 +
7924                         /* only try to write if we have something in the queue */
7925                         if (!chunkqueue_is_empty(con->write_queue)) {
7926  #if 0
7927 @@ -1593,10 +1505,10 @@
7928                                         con->write_request_ts = srv->cur_ts;
7929                                 }
7930                         }
7931 -                       
7932 +
7933                         break;
7934                 case CON_STATE_ERROR: /* transient */
7935 -                       
7936 +
7937                         /* even if the connection was drop we still have to write it to the access log */
7938                         if (con->http_status) {
7939                                 plugins_call_handle_request_done(srv, con);
7940 @@ -1612,19 +1524,19 @@
7941                                         SSL_shutdown(con->ssl);
7942                                         break;
7943                                 default:
7944 -                                       log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:", 
7945 -                                                       SSL_get_error(con->ssl, ret), 
7946 +                                       log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
7947 +                                                       SSL_get_error(con->ssl, ret),
7948                                                         ERR_error_string(ERR_get_error(), NULL));
7949                                         return -1;
7950                                 }
7951                         }
7952  #endif
7953 -                       
7954 +
7955                         switch(con->mode) {
7956                         case DIRECT:
7957  #if 0
7958 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
7959 -                                               "emergency exit: direct", 
7960 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
7961 +                                               "emergency exit: direct",
7962                                                 con->fd);
7963  #endif
7964                                 break;
7965 @@ -1639,35 +1551,35 @@
7966                                 }
7967                                 break;
7968                         }
7969 -                       
7970 +
7971                         connection_reset(srv, con);
7972 -                       
7973 +
7974                         /* close the connection */
7975                         if ((con->keep_alive == 1) &&
7976                             (0 == shutdown(con->fd, SHUT_WR))) {
7977                                 con->close_timeout_ts = srv->cur_ts;
7978                                 connection_set_state(srv, con, CON_STATE_CLOSE);
7979 -                               
7980 +
7981                                 if (srv->srvconf.log_state_handling) {
7982 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
7983 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
7984                                                         "shutdown for fd", con->fd);
7985                                 }
7986                         } else {
7987                                 connection_close(srv, con);
7988                         }
7989 -                       
7990 +
7991                         con->keep_alive = 0;
7992 -                       
7993 +
7994                         srv->con_closed++;
7995 -                       
7996 +
7997                         break;
7998                 default:
7999 -                       log_error_write(srv, __FILE__, __LINE__, "sdd", 
8000 +                       log_error_write(srv, __FILE__, __LINE__, "sdd",
8001                                         "unknown state:", con->fd, con->state);
8002 -                       
8003 +
8004                         break;
8005                 }
8006 -               
8007 +
8008                 if (done == -1) {
8009                         done = 0;
8010                 } else if (ostate == con->state) {
8011 @@ -1676,12 +1588,12 @@
8012         }
8013  
8014         if (srv->srvconf.log_state_handling) {
8015 -               log_error_write(srv, __FILE__, __LINE__, "sds", 
8016 -                               "state at exit:", 
8017 +               log_error_write(srv, __FILE__, __LINE__, "sds",
8018 +                               "state at exit:",
8019                                 con->fd,
8020                                 connection_get_state(con->state));
8021         }
8022 -       
8023 +
8024         switch(con->state) {
8025         case CON_STATE_READ_POST:
8026         case CON_STATE_READ:
8027 @@ -1689,11 +1601,11 @@
8028                 fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_IN);
8029                 break;
8030         case CON_STATE_WRITE:
8031 -               /* request write-fdevent only if we really need it 
8032 +               /* request write-fdevent only if we really need it
8033                  * - if we have data to write
8034 -                * - if the socket is not writable yet 
8035 +                * - if the socket is not writable yet
8036                  */
8037 -               if (!chunkqueue_is_empty(con->write_queue) && 
8038 +               if (!chunkqueue_is_empty(con->write_queue) &&
8039                     (con->is_writable == 0) &&
8040                     (con->traffic_limit_reached == 0)) {
8041                         fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT);
8042 --- lighttpd-1.4.11/src/crc32.h 2005-09-30 20:18:59.000000000 +0300
8043 +++ lighttpd-1.4.12/src/crc32.h 2006-07-11 22:07:53.000000000 +0300
8044 @@ -6,6 +6,7 @@
8045  #endif
8046  
8047  #include <sys/types.h>
8048 +#include <stdlib.h>
8049  
8050  #if defined HAVE_STDINT_H
8051  #include <stdint.h>
8052 @@ -13,6 +14,10 @@
8053  #include <inttypes.h>
8054  #endif
8055  
8056 +#ifdef _WIN32
8057 +#define uint32_t unsigned __int32
8058 +#endif
8059 +
8060  uint32_t generate_crc32c(char *string, size_t length);
8061  
8062  #endif
8063 --- lighttpd-1.4.11/src/data_array.c    2005-08-23 17:36:12.000000000 +0300
8064 +++ lighttpd-1.4.12/src/data_array.c    2006-07-11 22:07:52.000000000 +0300
8065 @@ -17,16 +17,16 @@
8066  
8067  static void data_array_free(data_unset *d) {
8068         data_array *ds = (data_array *)d;
8069 -       
8070 +
8071         buffer_free(ds->key);
8072         array_free(ds->value);
8073 -       
8074 +
8075         free(d);
8076  }
8077  
8078  static void data_array_reset(data_unset *d) {
8079         data_array *ds = (data_array *)d;
8080 -       
8081 +
8082         /* reused array elements */
8083         buffer_reset(ds->key);
8084         array_reset(ds->value);
8085 @@ -36,7 +36,7 @@
8086         UNUSED(dst);
8087  
8088         src->free(src);
8089 -       
8090 +
8091         return 0;
8092  }
8093  
8094 @@ -48,18 +48,18 @@
8095  
8096  data_array *data_array_init(void) {
8097         data_array *ds;
8098 -       
8099 +
8100         ds = calloc(1, sizeof(*ds));
8101 -       
8102 +
8103         ds->key = buffer_init();
8104         ds->value = array_init();
8105 -       
8106 +
8107         ds->copy = data_array_copy;
8108         ds->free = data_array_free;
8109         ds->reset = data_array_reset;
8110         ds->insert_dup = data_array_insert_dup;
8111         ds->print = data_array_print;
8112         ds->type = TYPE_ARRAY;
8113 -       
8114 +
8115         return ds;
8116  }
8117 --- lighttpd-1.4.11/src/data_config.c   2005-08-17 12:53:19.000000000 +0300
8118 +++ lighttpd-1.4.12/src/data_config.c   2006-07-11 22:07:51.000000000 +0300
8119 @@ -17,26 +17,26 @@
8120  
8121  static void data_config_free(data_unset *d) {
8122         data_config *ds = (data_config *)d;
8123 -       
8124 +
8125         buffer_free(ds->key);
8126         buffer_free(ds->op);
8127         buffer_free(ds->comp_key);
8128 -       
8129 +
8130         array_free(ds->value);
8131         array_free(ds->childs);
8132 -       
8133 +
8134         if (ds->string) buffer_free(ds->string);
8135  #ifdef HAVE_PCRE_H
8136         if (ds->regex) pcre_free(ds->regex);
8137         if (ds->regex_study) pcre_free(ds->regex_study);
8138  #endif
8139 -       
8140 +
8141         free(d);
8142  }
8143  
8144  static void data_config_reset(data_unset *d) {
8145         data_config *ds = (data_config *)d;
8146 -       
8147 +
8148         /* reused array elements */
8149         buffer_reset(ds->key);
8150         buffer_reset(ds->comp_key);
8151 @@ -45,9 +45,9 @@
8152  
8153  static int data_config_insert_dup(data_unset *dst, data_unset *src) {
8154         UNUSED(dst);
8155 -       
8156 +
8157         src->free(src);
8158 -       
8159 +
8160         return 0;
8161  }
8162  
8163 @@ -56,7 +56,7 @@
8164         array *a = (array *)ds->value;
8165         size_t i;
8166         size_t maxlen;
8167 -       
8168 +
8169         if (0 == ds->context_ndx) {
8170                 fprintf(stderr, "config {\n");
8171         }
8172 @@ -117,22 +117,22 @@
8173  
8174  data_config *data_config_init(void) {
8175         data_config *ds;
8176 -       
8177 +
8178         ds = calloc(1, sizeof(*ds));
8179 -       
8180 +
8181         ds->key = buffer_init();
8182         ds->op = buffer_init();
8183         ds->comp_key = buffer_init();
8184         ds->value = array_init();
8185         ds->childs = array_init();
8186         ds->childs->is_weakref = 1;
8187 -       
8188 +
8189         ds->copy = data_config_copy;
8190         ds->free = data_config_free;
8191         ds->reset = data_config_reset;
8192         ds->insert_dup = data_config_insert_dup;
8193         ds->print = data_config_print;
8194         ds->type = TYPE_CONFIG;
8195 -       
8196 +
8197         return ds;
8198  }
8199 --- lighttpd-1.4.11/src/data_count.c    2005-08-23 17:36:12.000000000 +0300
8200 +++ lighttpd-1.4.12/src/data_count.c    2006-07-11 22:07:51.000000000 +0300
8201 @@ -16,53 +16,53 @@
8202  
8203  static void data_count_free(data_unset *d) {
8204         data_count *ds = (data_count *)d;
8205 -       
8206 +
8207         buffer_free(ds->key);
8208 -       
8209 +
8210         free(d);
8211  }
8212  
8213  static void data_count_reset(data_unset *d) {
8214         data_count *ds = (data_count *)d;
8215 -       
8216 +
8217         buffer_reset(ds->key);
8218 -       
8219 +
8220         ds->count = 0;
8221  }
8222  
8223  static int data_count_insert_dup(data_unset *dst, data_unset *src) {
8224         data_count *ds_dst = (data_count *)dst;
8225         data_count *ds_src = (data_count *)src;
8226 -       
8227 +
8228         ds_dst->count += ds_src->count;
8229 -       
8230 +
8231         src->free(src);
8232 -       
8233 +
8234         return 0;
8235  }
8236  
8237  static void data_count_print(const data_unset *d, int depth) {
8238         data_count *ds = (data_count *)d;
8239         UNUSED(depth);
8240 -       
8241 +
8242         fprintf(stderr, "count(%d)", ds->count);
8243  }
8244  
8245  
8246  data_count *data_count_init(void) {
8247         data_count *ds;
8248 -       
8249 +
8250         ds = calloc(1, sizeof(*ds));
8251 -       
8252 +
8253         ds->key = buffer_init();
8254         ds->count = 1;
8255 -       
8256 +
8257         ds->copy = data_count_copy;
8258         ds->free = data_count_free;
8259         ds->reset = data_count_reset;
8260         ds->insert_dup = data_count_insert_dup;
8261         ds->print = data_count_print;
8262         ds->type = TYPE_COUNT;
8263 -       
8264 +
8265         return ds;
8266  }
8267 --- lighttpd-1.4.11/src/data_fastcgi.c  2005-08-23 17:36:12.000000000 +0300
8268 +++ lighttpd-1.4.12/src/data_fastcgi.c  2006-07-11 22:07:53.000000000 +0300
8269 @@ -17,53 +17,53 @@
8270  
8271  static void data_fastcgi_free(data_unset *d) {
8272         data_fastcgi *ds = (data_fastcgi *)d;
8273 -       
8274 +
8275         buffer_free(ds->key);
8276         buffer_free(ds->host);
8277 -       
8278 +
8279         free(d);
8280  }
8281  
8282  static void data_fastcgi_reset(data_unset *d) {
8283         data_fastcgi *ds = (data_fastcgi *)d;
8284 -       
8285 +
8286         buffer_reset(ds->key);
8287         buffer_reset(ds->host);
8288 -       
8289 +
8290  }
8291  
8292  static int data_fastcgi_insert_dup(data_unset *dst, data_unset *src) {
8293         UNUSED(dst);
8294  
8295         src->free(src);
8296 -       
8297 +
8298         return 0;
8299  }
8300  
8301  static void data_fastcgi_print(const data_unset *d, int depth) {
8302         data_fastcgi *ds = (data_fastcgi *)d;
8303         UNUSED(depth);
8304 -       
8305 +
8306         fprintf(stderr, "fastcgi(%s)", ds->host->ptr);
8307  }
8308  
8309  
8310  data_fastcgi *data_fastcgi_init(void) {
8311         data_fastcgi *ds;
8312 -       
8313 +
8314         ds = calloc(1, sizeof(*ds));
8315 -       
8316 +
8317         ds->key = buffer_init();
8318         ds->host = buffer_init();
8319         ds->port = 0;
8320         ds->is_disabled = 0;
8321 -       
8322 +
8323         ds->copy = data_fastcgi_copy;
8324         ds->free = data_fastcgi_free;
8325         ds->reset = data_fastcgi_reset;
8326         ds->insert_dup = data_fastcgi_insert_dup;
8327         ds->print = data_fastcgi_print;
8328         ds->type = TYPE_FASTCGI;
8329 -       
8330 +
8331         return ds;
8332  }
8333 --- lighttpd-1.4.11/src/data_integer.c  2005-08-23 17:36:12.000000000 +0300
8334 +++ lighttpd-1.4.12/src/data_integer.c  2006-07-11 22:07:51.000000000 +0300
8335 @@ -16,15 +16,15 @@
8336  
8337  static void data_integer_free(data_unset *d) {
8338         data_integer *ds = (data_integer *)d;
8339 -       
8340 +
8341         buffer_free(ds->key);
8342 -       
8343 +
8344         free(d);
8345  }
8346  
8347  static void data_integer_reset(data_unset *d) {
8348         data_integer *ds = (data_integer *)d;
8349 -       
8350 +
8351         /* reused integer elements */
8352         buffer_reset(ds->key);
8353         ds->value = 0;
8354 @@ -32,9 +32,9 @@
8355  
8356  static int data_integer_insert_dup(data_unset *dst, data_unset *src) {
8357         UNUSED(dst);
8358 -       
8359 +
8360         src->free(src);
8361 -       
8362 +
8363         return 0;
8364  }
8365  
8366 @@ -48,18 +48,18 @@
8367  
8368  data_integer *data_integer_init(void) {
8369         data_integer *ds;
8370 -       
8371 +
8372         ds = calloc(1, sizeof(*ds));
8373 -       
8374 +
8375         ds->key = buffer_init();
8376         ds->value = 0;
8377 -       
8378 +
8379         ds->copy = data_integer_copy;
8380         ds->free = data_integer_free;
8381         ds->reset = data_integer_reset;
8382         ds->insert_dup = data_integer_insert_dup;
8383         ds->print = data_integer_print;
8384         ds->type = TYPE_INTEGER;
8385 -       
8386 +
8387         return ds;
8388  }
8389 --- lighttpd-1.4.11/src/data_string.c   2005-08-23 17:36:12.000000000 +0300
8390 +++ lighttpd-1.4.12/src/data_string.c   2006-07-11 22:07:53.000000000 +0300
8391 @@ -17,16 +17,16 @@
8392  
8393  static void data_string_free(data_unset *d) {
8394         data_string *ds = (data_string *)d;
8395 -       
8396 +
8397         buffer_free(ds->key);
8398         buffer_free(ds->value);
8399 -       
8400 +
8401         free(d);
8402  }
8403  
8404  static void data_string_reset(data_unset *d) {
8405         data_string *ds = (data_string *)d;
8406 -       
8407 +
8408         /* reused array elements */
8409         buffer_reset(ds->key);
8410         buffer_reset(ds->value);
8411 @@ -35,23 +35,23 @@
8412  static int data_string_insert_dup(data_unset *dst, data_unset *src) {
8413         data_string *ds_dst = (data_string *)dst;
8414         data_string *ds_src = (data_string *)src;
8415 -       
8416 +
8417         if (ds_dst->value->used) {
8418                 buffer_append_string(ds_dst->value, ", ");
8419                 buffer_append_string_buffer(ds_dst->value, ds_src->value);
8420         } else {
8421                 buffer_copy_string_buffer(ds_dst->value, ds_src->value);
8422         }
8423 -       
8424 +
8425         src->free(src);
8426 -       
8427 +
8428         return 0;
8429  }
8430  
8431  static int data_response_insert_dup(data_unset *dst, data_unset *src) {
8432         data_string *ds_dst = (data_string *)dst;
8433         data_string *ds_src = (data_string *)src;
8434 -       
8435 +
8436         if (ds_dst->value->used) {
8437                 buffer_append_string(ds_dst->value, "\r\n");
8438                 buffer_append_string_buffer(ds_dst->value, ds_dst->key);
8439 @@ -60,9 +60,9 @@
8440         } else {
8441                 buffer_copy_string_buffer(ds_dst->value, ds_src->value);
8442         }
8443 -       
8444 +
8445         src->free(src);
8446 -       
8447 +
8448         return 0;
8449  }
8450  
8451 @@ -77,28 +77,28 @@
8452  
8453  data_string *data_string_init(void) {
8454         data_string *ds;
8455 -       
8456 +
8457         ds = calloc(1, sizeof(*ds));
8458         assert(ds);
8459 -       
8460 +
8461         ds->key = buffer_init();
8462         ds->value = buffer_init();
8463 -       
8464 +
8465         ds->copy = data_string_copy;
8466         ds->free = data_string_free;
8467         ds->reset = data_string_reset;
8468         ds->insert_dup = data_string_insert_dup;
8469         ds->print = data_string_print;
8470         ds->type = TYPE_STRING;
8471 -       
8472 +
8473         return ds;
8474  }
8475  
8476  data_string *data_response_init(void) {
8477         data_string *ds;
8478 -       
8479 +
8480         ds = data_string_init();
8481         ds->insert_dup = data_response_insert_dup;
8482 -       
8483 +
8484         return ds;
8485  }
8486 --- lighttpd-1.4.11/src/etag.c  2005-08-11 01:26:40.000000000 +0300
8487 +++ lighttpd-1.4.12/src/etag.c  2006-07-11 22:07:51.000000000 +0300
8488 @@ -14,19 +14,19 @@
8489         buffer_append_off_t(etag, st->st_size);
8490         buffer_append_string_len(etag, CONST_STR_LEN("-"));
8491         buffer_append_long(etag, st->st_mtime);
8492 -       
8493 +
8494         return 0;
8495  }
8496  
8497  int etag_mutate(buffer *mut, buffer *etag) {
8498         size_t h, i;
8499 -       
8500 +
8501         for (h=0, i=0; i < etag->used; ++i) h = (h<<5)^(h>>27)^(etag->ptr[i]);
8502 -       
8503 +
8504         buffer_reset(mut);
8505         buffer_copy_string_len(mut, CONST_STR_LEN("\""));
8506         buffer_append_long(mut, h);
8507         buffer_append_string_len(mut, CONST_STR_LEN("\""));
8508 -       
8509 +
8510         return 0;
8511  }
8512 --- lighttpd-1.4.11/src/etag.h  2005-08-11 01:26:40.000000000 +0300
8513 +++ lighttpd-1.4.12/src/etag.h  2006-07-11 22:07:51.000000000 +0300
8514 @@ -3,13 +3,12 @@
8515  
8516  #include <sys/types.h>
8517  #include <sys/stat.h>
8518 -#include <unistd.h>
8519  
8520  #include "buffer.h"
8521  
8522  int etag_is_equal(buffer *etag, const char *matches);
8523  int etag_create(buffer *etag, struct stat *st);
8524  int etag_mutate(buffer *mut, buffer *etag);
8525 -       
8526 +
8527  
8528  #endif
8529 --- lighttpd-1.4.11/src/fastcgi.h       2005-08-11 01:26:40.000000000 +0300
8530 +++ lighttpd-1.4.12/src/fastcgi.h       2006-07-11 22:07:51.000000000 +0300
8531 @@ -1,4 +1,4 @@
8532 -/* 
8533 +/*
8534   * fastcgi.h --
8535   *
8536   *     Defines for the FastCGI protocol.
8537 @@ -123,7 +123,7 @@
8538  
8539  
8540  typedef struct {
8541 -    unsigned char type;    
8542 +    unsigned char type;
8543      unsigned char reserved[7];
8544  } FCGI_UnknownTypeBody;
8545  
8546 --- lighttpd-1.4.11/src/fdevent.c       2005-11-15 10:51:05.000000000 +0200
8547 +++ lighttpd-1.4.12/src/fdevent.c       2006-07-11 22:07:53.000000000 +0300
8548 @@ -2,7 +2,6 @@
8549  
8550  #include "settings.h"
8551  
8552 -#include <unistd.h>
8553  #include <stdlib.h>
8554  #include <string.h>
8555  #include <errno.h>
8556 @@ -12,59 +11,61 @@
8557  #include "fdevent.h"
8558  #include "buffer.h"
8559  
8560 +#include "sys-socket.h"
8561 +
8562  fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type) {
8563         fdevents *ev;
8564 -       
8565 +
8566         ev = calloc(1, sizeof(*ev));
8567         ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray));
8568         ev->maxfds = maxfds;
8569 -       
8570 +
8571         switch(type) {
8572         case FDEVENT_HANDLER_POLL:
8573                 if (0 != fdevent_poll_init(ev)) {
8574 -                       fprintf(stderr, "%s.%d: event-handler poll failed\n", 
8575 +                       fprintf(stderr, "%s.%d: event-handler poll failed\n",
8576                                 __FILE__, __LINE__);
8577 -                       
8578 +
8579                         return NULL;
8580                 }
8581                 break;
8582         case FDEVENT_HANDLER_SELECT:
8583                 if (0 != fdevent_select_init(ev)) {
8584 -                       fprintf(stderr, "%s.%d: event-handler select failed\n", 
8585 +                       fprintf(stderr, "%s.%d: event-handler select failed\n",
8586                                 __FILE__, __LINE__);
8587                         return NULL;
8588                 }
8589                 break;
8590         case FDEVENT_HANDLER_LINUX_RTSIG:
8591                 if (0 != fdevent_linux_rtsig_init(ev)) {
8592 -                       fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n", 
8593 +                       fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8594                                 __FILE__, __LINE__);
8595                         return NULL;
8596                 }
8597                 break;
8598         case FDEVENT_HANDLER_LINUX_SYSEPOLL:
8599                 if (0 != fdevent_linux_sysepoll_init(ev)) {
8600 -                       fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n", 
8601 +                       fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8602                                 __FILE__, __LINE__);
8603                         return NULL;
8604                 }
8605                 break;
8606         case FDEVENT_HANDLER_SOLARIS_DEVPOLL:
8607                 if (0 != fdevent_solaris_devpoll_init(ev)) {
8608 -                       fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n", 
8609 +                       fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8610                                 __FILE__, __LINE__);
8611                         return NULL;
8612                 }
8613                 break;
8614         case FDEVENT_HANDLER_FREEBSD_KQUEUE:
8615                 if (0 != fdevent_freebsd_kqueue_init(ev)) {
8616 -                       fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n", 
8617 +                       fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8618                                 __FILE__, __LINE__);
8619                         return NULL;
8620                 }
8621                 break;
8622         default:
8623 -               fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n", 
8624 +               fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n",
8625                         __FILE__, __LINE__);
8626                 return NULL;
8627         }
8628 @@ -75,26 +76,26 @@
8629  void fdevent_free(fdevents *ev) {
8630         size_t i;
8631         if (!ev) return;
8632 -       
8633 +
8634         if (ev->free) ev->free(ev);
8635 -       
8636 +
8637         for (i = 0; i < ev->maxfds; i++) {
8638                 if (ev->fdarray[i]) free(ev->fdarray[i]);
8639         }
8640 -       
8641 +
8642         free(ev->fdarray);
8643         free(ev);
8644  }
8645  
8646  int fdevent_reset(fdevents *ev) {
8647         if (ev->reset) return ev->reset(ev);
8648 -       
8649 +
8650         return 0;
8651  }
8652  
8653  fdnode *fdnode_init() {
8654         fdnode *fdn;
8655 -       
8656 +
8657         fdn = calloc(1, sizeof(*fdn));
8658         fdn->fd = -1;
8659         return fdn;
8660 @@ -106,12 +107,12 @@
8661  
8662  int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) {
8663         fdnode *fdn;
8664 -       
8665 +
8666         fdn = fdnode_init();
8667         fdn->handler = handler;
8668         fdn->fd      = fd;
8669         fdn->ctx     = ctx;
8670 -       
8671 +
8672         ev->fdarray[fd] = fdn;
8673  
8674         return 0;
8675 @@ -121,31 +122,31 @@
8676         fdnode *fdn;
8677          if (!ev) return 0;
8678         fdn = ev->fdarray[fd];
8679 -       
8680 +
8681         fdnode_free(fdn);
8682 -       
8683 +
8684         ev->fdarray[fd] = NULL;
8685 -       
8686 +
8687         return 0;
8688  }
8689  
8690  int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) {
8691         int fde = fde_ndx ? *fde_ndx : -1;
8692 -       
8693 +
8694         if (ev->event_del) fde = ev->event_del(ev, fde, fd);
8695 -       
8696 +
8697         if (fde_ndx) *fde_ndx = fde;
8698 -       
8699 +
8700         return 0;
8701  }
8702  
8703  int fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int events) {
8704         int fde = fde_ndx ? *fde_ndx : -1;
8705 -       
8706 +
8707         if (ev->event_add) fde = ev->event_add(ev, fde, fd, events);
8708 -       
8709 +
8710         if (fde_ndx) *fde_ndx = fde;
8711 -       
8712 +
8713         return 0;
8714  }
8715  
8716 @@ -156,38 +157,43 @@
8717  
8718  int fdevent_event_get_revent(fdevents *ev, size_t ndx) {
8719         if (ev->event_get_revent == NULL) SEGFAULT();
8720 -       
8721 +
8722         return ev->event_get_revent(ev, ndx);
8723  }
8724  
8725  int fdevent_event_get_fd(fdevents *ev, size_t ndx) {
8726         if (ev->event_get_fd == NULL) SEGFAULT();
8727 -       
8728 +
8729         return ev->event_get_fd(ev, ndx);
8730  }
8731  
8732  fdevent_handler fdevent_get_handler(fdevents *ev, int fd) {
8733         if (ev->fdarray[fd] == NULL) SEGFAULT();
8734         if (ev->fdarray[fd]->fd != fd) SEGFAULT();
8735 -       
8736 +
8737         return ev->fdarray[fd]->handler;
8738  }
8739  
8740  void * fdevent_get_context(fdevents *ev, int fd) {
8741         if (ev->fdarray[fd] == NULL) SEGFAULT();
8742         if (ev->fdarray[fd]->fd != fd) SEGFAULT();
8743 -       
8744 +
8745         return ev->fdarray[fd]->ctx;
8746  }
8747  
8748  int fdevent_fcntl_set(fdevents *ev, int fd) {
8749 +#ifdef _WIN32
8750 +    int i = 1;
8751 +#endif
8752  #ifdef FD_CLOEXEC
8753         /* close fd on exec (cgi) */
8754         fcntl(fd, F_SETFD, FD_CLOEXEC);
8755  #endif
8756         if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, fd);
8757 -#ifdef O_NONBLOCK      
8758 +#ifdef O_NONBLOCK
8759         return fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR);
8760 +#elif defined _WIN32
8761 +    return ioctlsocket(fd, FIONBIO, &i);
8762  #else
8763         return 0;
8764  #endif
8765 @@ -196,7 +202,7 @@
8766  
8767  int fdevent_event_next_fdndx(fdevents *ev, int ndx) {
8768         if (ev->event_next_fdndx) return ev->event_next_fdndx(ev, ndx);
8769 -       
8770 +
8771         return -1;
8772  }
8773  
8774 --- lighttpd-1.4.11/src/fdevent.h       2005-09-27 11:26:33.000000000 +0300
8775 +++ lighttpd-1.4.12/src/fdevent.h       2006-07-11 22:07:51.000000000 +0300
8776 @@ -17,13 +17,13 @@
8777  # include <sys/epoll.h>
8778  #endif
8779  
8780 -/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes 
8781 +/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes
8782   * under /usr/include/sys/ */
8783  #if defined HAVE_POLL && (defined(HAVE_SYS_POLL_H) || defined(HAVE_POLL_H))
8784  # define USE_POLL
8785  # ifdef HAVE_POLL_H
8786  #  include <poll.h>
8787 -# else 
8788 +# else
8789  #  include <sys/poll.h>
8790  # endif
8791  # if defined HAVE_SIGTIMEDWAIT && defined(__linux__)
8792 @@ -31,9 +31,11 @@
8793  #  include <signal.h>
8794  # endif
8795  #endif
8796 -
8797 +#ifdef _WIN32
8798 +# define HAVE_SELECT
8799 +#endif
8800  #if defined HAVE_SELECT
8801 -# ifdef __WIN32
8802 +# ifdef _WIN32
8803  #  include <winsock2.h>
8804  # endif
8805  # define USE_SELECT
8806 @@ -67,14 +69,14 @@
8807  #define FDEVENT_HUP    BV(4)
8808  #define FDEVENT_NVAL   BV(5)
8809  
8810 -typedef enum { FD_EVENT_TYPE_UNSET = -1, 
8811 -               FD_EVENT_TYPE_CONNECTION, 
8812 -               FD_EVENT_TYPE_FCGI_CONNECTION, 
8813 -               FD_EVENT_TYPE_DIRWATCH, 
8814 -               FD_EVENT_TYPE_CGI_CONNECTION 
8815 +typedef enum { FD_EVENT_TYPE_UNSET = -1,
8816 +               FD_EVENT_TYPE_CONNECTION,
8817 +               FD_EVENT_TYPE_FCGI_CONNECTION,
8818 +               FD_EVENT_TYPE_DIRWATCH,
8819 +               FD_EVENT_TYPE_CGI_CONNECTION
8820  } fd_event_t;
8821  
8822 -typedef enum { FDEVENT_HANDLER_UNSET, 
8823 +typedef enum { FDEVENT_HANDLER_UNSET,
8824                 FDEVENT_HANDLER_SELECT,
8825                 FDEVENT_HANDLER_POLL,
8826                 FDEVENT_HANDLER_LINUX_RTSIG,
8827 @@ -86,7 +88,7 @@
8828  
8829  /**
8830   * a mapping from fd to connection structure
8831 - * 
8832 + *
8833   */
8834  typedef struct {
8835         int fd;                  /**< the fd */
8836 @@ -98,41 +100,41 @@
8837  
8838  typedef struct {
8839         fd_conn *ptr;
8840 -       
8841 +
8842         size_t size;
8843         size_t used;
8844  } fd_conn_buffer;
8845  
8846  /**
8847   * array of unused fd's
8848 - * 
8849 + *
8850   */
8851  
8852  typedef struct _fdnode {
8853         fdevent_handler handler;
8854         void *ctx;
8855         int fd;
8856 -       
8857 +
8858         struct _fdnode *prev, *next;
8859  } fdnode;
8860  
8861  typedef struct {
8862         int *ptr;
8863 -       
8864 +
8865         size_t used;
8866         size_t size;
8867  } buffer_int;
8868  
8869  /**
8870   * fd-event handler for select(), poll() and rt-signals on Linux 2.4
8871 - * 
8872 + *
8873   */
8874  typedef struct fdevents {
8875         fdevent_handler_t type;
8876 -       
8877 +
8878         fdnode **fdarray;
8879         size_t maxfds;
8880 -       
8881 +
8882  #ifdef USE_LINUX_SIGIO
8883         int in_sigio;
8884         int signum;
8885 @@ -146,21 +148,21 @@
8886  #endif
8887  #ifdef USE_POLL
8888         struct pollfd *pollfds;
8889 -       
8890 +
8891         size_t size;
8892         size_t used;
8893 -       
8894 +
8895         buffer_int unused;
8896  #endif
8897  #ifdef USE_SELECT
8898         fd_set select_read;
8899         fd_set select_write;
8900         fd_set select_error;
8901 -       
8902 +
8903         fd_set select_set_read;
8904         fd_set select_set_write;
8905         fd_set select_set_error;
8906 -       
8907 +
8908         int select_max_fd;
8909  #endif
8910  #ifdef USE_SOLARIS_DEVPOLL
8911 @@ -177,16 +179,16 @@
8912  #endif
8913         int (*reset)(struct fdevents *ev);
8914         void (*free)(struct fdevents *ev);
8915 -       
8916 +
8917         int (*event_add)(struct fdevents *ev, int fde_ndx, int fd, int events);
8918         int (*event_del)(struct fdevents *ev, int fde_ndx, int fd);
8919         int (*event_get_revent)(struct fdevents *ev, size_t ndx);
8920         int (*event_get_fd)(struct fdevents *ev, size_t ndx);
8921 -       
8922 +
8923         int (*event_next_fdndx)(struct fdevents *ev, int ndx);
8924 -       
8925 +
8926         int (*poll)(struct fdevents *ev, int timeout_ms);
8927 -       
8928 +
8929         int (*fcntl_set)(struct fdevents *ev, int fd);
8930  } fdevents;
8931  
8932 --- lighttpd-1.4.11/src/fdevent_freebsd_kqueue.c        2005-09-01 10:46:24.000000000 +0300
8933 +++ lighttpd-1.4.12/src/fdevent_freebsd_kqueue.c        2006-07-11 22:07:51.000000000 +0300
8934 @@ -1,6 +1,5 @@
8935  #include <sys/types.h>
8936  
8937 -#include <unistd.h>
8938  #include <stdlib.h>
8939  #include <stdio.h>
8940  #include <string.h>
8941 @@ -48,7 +47,7 @@
8942  
8943                 return -1;
8944         }
8945 -       
8946 +
8947         return -1;
8948  }
8949  
8950 @@ -65,7 +64,7 @@
8951  
8952         ts.tv_sec  = 0;
8953         ts.tv_nsec = 0;
8954 -       
8955 +
8956         ret = kevent(ev->kq_fd,
8957                      &kev, 1,
8958                      NULL, 0,
8959 @@ -77,7 +76,7 @@
8960  
8961                 return -1;
8962         }
8963 -       
8964 +
8965         if (filter == EVFILT_READ) {
8966                 bitset_set_bit(ev->kq_bevents, fd);
8967         } else {
8968 @@ -124,7 +123,7 @@
8969         } else if (e == EVFILT_WRITE) {
8970                 events |= FDEVENT_OUT;
8971         }
8972 -       
8973 +
8974         e = ev->kq_results[ndx].flags;
8975  
8976         if (e & EV_EOF) {
8977 @@ -152,10 +151,10 @@
8978         if (-1 == (ev->kq_fd = kqueue())) {
8979                 fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
8980                         __FILE__, __LINE__, strerror(errno));
8981 -               
8982 +
8983                 return -1;
8984         }
8985 -       
8986 +
8987         return 0;
8988  }
8989  
8990 @@ -186,7 +185,7 @@
8991         if (-1 == (ev->kq_fd = kqueue())) {
8992                 fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
8993                         __FILE__, __LINE__, strerror(errno));
8994 -               
8995 +
8996                 return -1;
8997         }
8998  
8999 --- lighttpd-1.4.11/src/fdevent_linux_rtsig.c   2005-11-21 19:56:11.000000000 +0200
9000 +++ lighttpd-1.4.12/src/fdevent_linux_rtsig.c   2006-07-11 22:07:53.000000000 +0300
9001 @@ -1,6 +1,5 @@
9002  #include <sys/types.h>
9003  
9004 -#include <unistd.h>
9005  #include <stdlib.h>
9006  #include <stdio.h>
9007  #include <string.h>
9008 @@ -26,19 +25,19 @@
9009  
9010  static int fdevent_linux_rtsig_event_del(fdevents *ev, int fde_ndx, int fd) {
9011         if (fde_ndx < 0) return -1;
9012 -       
9013 +
9014         if ((size_t)fde_ndx >= ev->used) {
9015                 fprintf(stderr, "%s.%d: del! out of range %d %zu\n", __FILE__, __LINE__, fde_ndx, ev->used);
9016                 SEGFAULT();
9017         }
9018 -       
9019 +
9020         if (ev->pollfds[fde_ndx].fd == fd) {
9021                 size_t k = fde_ndx;
9022 -               
9023 +
9024                 ev->pollfds[k].fd = -1;
9025  
9026                 bitset_clear_bit(ev->sigbset, fd);
9027 -               
9028 +
9029                 if (ev->unused.size == 0) {
9030                         ev->unused.size = 16;
9031                         ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
9032 @@ -46,29 +45,29 @@
9033                         ev->unused.size += 16;
9034                         ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
9035                 }
9036 -               
9037 +
9038                 ev->unused.ptr[ev->unused.used++] = k;
9039         } else {
9040                 fprintf(stderr, "%s.%d: del! %d %d\n", __FILE__, __LINE__, ev->pollfds[fde_ndx].fd, fd);
9041 -               
9042 +
9043                 SEGFAULT();
9044         }
9045 -       
9046 +
9047         return -1;
9048  }
9049  
9050  #if 0
9051  static int fdevent_linux_rtsig_event_compress(fdevents *ev) {
9052         size_t j;
9053 -       
9054 +
9055         if (ev->used == 0) return 0;
9056         if (ev->unused.used != 0) return 0;
9057 -       
9058 +
9059         for (j = ev->used - 1; j + 1 > 0; j--) {
9060                 if (ev->pollfds[j].fd == -1) ev->used--;
9061         }
9062 -       
9063 -       
9064 +
9065 +
9066         return 0;
9067  }
9068  #endif
9069 @@ -78,21 +77,21 @@
9070         if (fde_ndx != -1) {
9071                 if (ev->pollfds[fde_ndx].fd == fd) {
9072                         ev->pollfds[fde_ndx].events = events;
9073 -                       
9074 +
9075                         return fde_ndx;
9076                 }
9077                 fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd);
9078                 SEGFAULT();
9079         }
9080 -       
9081 +
9082         if (ev->unused.used > 0) {
9083                 int k = ev->unused.ptr[--ev->unused.used];
9084 -               
9085 +
9086                 ev->pollfds[k].fd = fd;
9087                 ev->pollfds[k].events = events;
9088  
9089                 bitset_set_bit(ev->sigbset, fd);
9090 -               
9091 +
9092                 return k;
9093         } else {
9094                 if (ev->size == 0) {
9095 @@ -102,12 +101,12 @@
9096                         ev->size += 16;
9097                         ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
9098                 }
9099 -               
9100 +
9101                 ev->pollfds[ev->used].fd = fd;
9102                 ev->pollfds[ev->used].events = events;
9103  
9104                 bitset_set_bit(ev->sigbset, fd);
9105 -       
9106 +
9107                 return ev->used++;
9108         }
9109  }
9110 @@ -115,20 +114,20 @@
9111  static int fdevent_linux_rtsig_poll(fdevents *ev, int timeout_ms) {
9112         struct timespec ts;
9113         int r;
9114 -       
9115 +
9116  #if 0
9117         fdevent_linux_rtsig_event_compress(ev);
9118  #endif
9119 -       
9120 +
9121         ev->in_sigio = 1;
9122 -               
9123 +
9124         ts.tv_sec =  timeout_ms / 1000;
9125         ts.tv_nsec = (timeout_ms % 1000) * 1000000;
9126         r = sigtimedwait(&(ev->sigset), &(ev->siginfo), &(ts));
9127 -               
9128 -       if (r == -1) { 
9129 +
9130 +       if (r == -1) {
9131                 if (errno == EAGAIN) return 0;
9132 -               return r; 
9133 +               return r;
9134         } else if (r == SIGIO) {
9135                 struct sigaction act;
9136  
9137 @@ -140,7 +139,7 @@
9138                 /* re-enable the signal queue */
9139                 act.sa_handler = SIG_DFL;
9140                 sigaction(ev->signum, &act, NULL);
9141 -               
9142 +
9143                 ev->in_sigio = 0;
9144                 r = poll(ev->pollfds, ev->used, timeout_ms);
9145  
9146 @@ -162,12 +161,12 @@
9147                 if (ev->siginfo.si_band == POLLERR) {
9148                         fprintf(stderr, "event: %d %02lx %02x %s\n", ev->siginfo.si_fd, ev->siginfo.si_band, errno, strerror(errno));
9149                 }
9150 -#  endif               
9151 +#  endif
9152                 if (ndx != 0) {
9153                         fprintf(stderr, "+\n");
9154                         return 0;
9155                 }
9156 -               
9157 +
9158                 return ev->siginfo.si_band & 0x3f;
9159         } else {
9160                 if (ndx >= ev->used) {
9161 @@ -188,13 +187,13 @@
9162  
9163  static int fdevent_linux_rtsig_fcntl_set(fdevents *ev, int fd) {
9164         static pid_t pid = 0;
9165 -       
9166 +
9167         if (pid == 0) pid = getpid();
9168 -       
9169 +
9170         if (-1 == fcntl(fd, F_SETSIG, ev->signum)) return -1;
9171 -       
9172 +
9173         if (-1 == fcntl(fd, F_SETOWN, (int) pid)) return -1;
9174 -       
9175 +
9176         return fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK | O_RDWR);
9177  }
9178  
9179 @@ -205,12 +204,12 @@
9180                 return -1;
9181         } else {
9182                 size_t i;
9183 -               
9184 +
9185                 i = (ndx < 0) ? 0 : ndx + 1;
9186                 for (; i < ev->used; i++) {
9187                         if (ev->pollfds[i].revents) break;
9188                 }
9189 -               
9190 +
9191                 return i;
9192         }
9193  }
9194 @@ -219,34 +218,34 @@
9195         ev->type = FDEVENT_HANDLER_LINUX_RTSIG;
9196  #define SET(x) \
9197         ev->x = fdevent_linux_rtsig_##x;
9198 -       
9199 +
9200         SET(free);
9201         SET(poll);
9202 -       
9203 +
9204         SET(event_del);
9205         SET(event_add);
9206 -       
9207 +
9208         SET(event_next_fdndx);
9209         SET(fcntl_set);
9210         SET(event_get_fd);
9211         SET(event_get_revent);
9212 -       
9213 +
9214         ev->signum = SIGRTMIN + 1;
9215 -       
9216 +
9217         sigemptyset(&(ev->sigset));
9218         sigaddset(&(ev->sigset), ev->signum);
9219         sigaddset(&(ev->sigset), SIGIO);
9220         if (-1 == sigprocmask(SIG_BLOCK, &(ev->sigset), NULL)) {
9221                 fprintf(stderr, "%s.%d: sigprocmask failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
9222                         __FILE__, __LINE__, strerror(errno));
9223 -               
9224 +
9225                 return -1;
9226         }
9227 -       
9228 +
9229         ev->in_sigio = 1;
9230  
9231         ev->sigbset = bitset_init(ev->maxfds);
9232 -       
9233 +
9234         return 0;
9235  }
9236  #else
9237 --- lighttpd-1.4.11/src/fdevent_linux_sysepoll.c        2005-09-30 20:29:27.000000000 +0300
9238 +++ lighttpd-1.4.12/src/fdevent_linux_sysepoll.c        2006-07-11 22:07:53.000000000 +0300
9239 @@ -1,6 +1,5 @@
9240  #include <sys/types.h>
9241  
9242 -#include <unistd.h>
9243  #include <stdlib.h>
9244  #include <stdio.h>
9245  #include <string.h>
9246 @@ -12,6 +11,8 @@
9247  #include "settings.h"
9248  #include "buffer.h"
9249  
9250 +#include "sys-files.h"
9251 +
9252  #ifdef USE_LINUX_EPOLL
9253  static void fdevent_linux_sysepoll_free(fdevents *ev) {
9254         close(ev->epoll_fd);
9255 @@ -20,36 +21,36 @@
9256  
9257  static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) {
9258         struct epoll_event ep;
9259 -       
9260 +
9261         if (fde_ndx < 0) return -1;
9262 -       
9263 +
9264         memset(&ep, 0, sizeof(ep));
9265 -       
9266 +
9267         ep.data.fd = fd;
9268         ep.data.ptr = NULL;
9269 -       
9270 +
9271         if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, &ep)) {
9272                 fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno));
9273 -               
9274 +
9275                 SEGFAULT();
9276 -               
9277 +
9278                 return 0;
9279         }
9280 -       
9281 -       
9282 +
9283 +
9284         return -1;
9285  }
9286  
9287  static int fdevent_linux_sysepoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9288         struct epoll_event ep;
9289         int add = 0;
9290 -       
9291 +
9292         if (fde_ndx == -1) add = 1;
9293 -       
9294 +
9295         memset(&ep, 0, sizeof(ep));
9296 -       
9297 +
9298         ep.events = 0;
9299 -       
9300 +
9301         if (events & FDEVENT_IN)  ep.events |= EPOLLIN;
9302         if (events & FDEVENT_OUT) ep.events |= EPOLLOUT;
9303  
9304 @@ -60,20 +61,20 @@
9305          * sent.
9306          *
9307          */
9308 -       
9309 +
9310         ep.events |= EPOLLERR | EPOLLHUP /* | EPOLLET */;
9311 -       
9312 +
9313         ep.data.ptr = NULL;
9314         ep.data.fd = fd;
9315 -       
9316 +
9317         if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) {
9318                 fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno));
9319 -               
9320 +
9321                 SEGFAULT();
9322 -               
9323 +
9324                 return 0;
9325         }
9326 -       
9327 +
9328         return fd;
9329  }
9330  
9331 @@ -83,14 +84,14 @@
9332  
9333  static int fdevent_linux_sysepoll_event_get_revent(fdevents *ev, size_t ndx) {
9334         int events = 0, e;
9335 -       
9336 +
9337         e = ev->epoll_events[ndx].events;
9338         if (e & EPOLLIN) events |= FDEVENT_IN;
9339         if (e & EPOLLOUT) events |= FDEVENT_OUT;
9340         if (e & EPOLLERR) events |= FDEVENT_ERR;
9341         if (e & EPOLLHUP) events |= FDEVENT_HUP;
9342         if (e & EPOLLPRI) events |= FDEVENT_PRI;
9343 -       
9344 +
9345         return e;
9346  }
9347  
9348 @@ -98,17 +99,17 @@
9349  # if 0
9350         fprintf(stderr, "%s.%d: %d, %d\n", __FILE__, __LINE__, ndx, ev->epoll_events[ndx].data.fd);
9351  # endif
9352 -       
9353 +
9354         return ev->epoll_events[ndx].data.fd;
9355  }
9356  
9357  static int fdevent_linux_sysepoll_event_next_fdndx(fdevents *ev, int ndx) {
9358         size_t i;
9359 -       
9360 +
9361         UNUSED(ev);
9362  
9363         i = (ndx < 0) ? 0 : ndx + 1;
9364 -       
9365 +
9366         return i;
9367  }
9368  
9369 @@ -116,17 +117,17 @@
9370         ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL;
9371  #define SET(x) \
9372         ev->x = fdevent_linux_sysepoll_##x;
9373 -       
9374 +
9375         SET(free);
9376         SET(poll);
9377 -       
9378 +
9379         SET(event_del);
9380         SET(event_add);
9381 -       
9382 +
9383         SET(event_next_fdndx);
9384         SET(event_get_fd);
9385         SET(event_get_revent);
9386 -       
9387 +
9388         if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) {
9389                 fprintf(stderr, "%s.%d: epoll_create failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
9390                         __FILE__, __LINE__, strerror(errno));
9391 @@ -154,7 +155,7 @@
9392  
9393         fprintf(stderr, "%s.%d: linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
9394                 __FILE__, __LINE__);
9395 -       
9396 +
9397         return -1;
9398  }
9399  #endif
9400 --- lighttpd-1.4.11/src/fdevent_poll.c  2005-11-18 13:59:16.000000000 +0200
9401 +++ lighttpd-1.4.12/src/fdevent_poll.c  2006-07-11 22:07:53.000000000 +0300
9402 @@ -1,6 +1,5 @@
9403  #include <sys/types.h>
9404  
9405 -#include <unistd.h>
9406  #include <stdlib.h>
9407  #include <stdio.h>
9408  #include <string.h>
9409 @@ -20,19 +19,19 @@
9410  
9411  static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) {
9412         if (fde_ndx < 0) return -1;
9413 -       
9414 +
9415         if ((size_t)fde_ndx >= ev->used) {
9416                 fprintf(stderr, "%s.%d: del! out of range %d %zd\n", __FILE__, __LINE__, fde_ndx, ev->used);
9417                 SEGFAULT();
9418         }
9419 -       
9420 +
9421         if (ev->pollfds[fde_ndx].fd == fd) {
9422                 size_t k = fde_ndx;
9423 -               
9424 +
9425                 ev->pollfds[k].fd = -1;
9426                 /* ev->pollfds[k].events = 0; */
9427                 /* ev->pollfds[k].revents = 0; */
9428 -               
9429 +
9430                 if (ev->unused.size == 0) {
9431                         ev->unused.size = 16;
9432                         ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
9433 @@ -40,47 +39,47 @@
9434                         ev->unused.size += 16;
9435                         ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
9436                 }
9437 -               
9438 +
9439                 ev->unused.ptr[ev->unused.used++] = k;
9440         } else {
9441                 SEGFAULT();
9442         }
9443 -       
9444 +
9445         return -1;
9446  }
9447  
9448  #if 0
9449  static int fdevent_poll_event_compress(fdevents *ev) {
9450         size_t j;
9451 -       
9452 +
9453         if (ev->used == 0) return 0;
9454         if (ev->unused.used != 0) return 0;
9455 -       
9456 +
9457         for (j = ev->used - 1; j + 1 > 0 && ev->pollfds[j].fd == -1; j--) ev->used--;
9458 -       
9459 +
9460         return 0;
9461  }
9462  #endif
9463  
9464  static int fdevent_poll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9465         /* known index */
9466 -       
9467 +
9468         if (fde_ndx != -1) {
9469                 if (ev->pollfds[fde_ndx].fd == fd) {
9470                         ev->pollfds[fde_ndx].events = events;
9471 -                       
9472 +
9473                         return fde_ndx;
9474                 }
9475                 fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd);
9476                 SEGFAULT();
9477         }
9478 -       
9479 +
9480         if (ev->unused.used > 0) {
9481                 int k = ev->unused.ptr[--ev->unused.used];
9482 -               
9483 +
9484                 ev->pollfds[k].fd = fd;
9485                 ev->pollfds[k].events = events;
9486 -               
9487 +
9488                 return k;
9489         } else {
9490                 if (ev->size == 0) {
9491 @@ -90,10 +89,10 @@
9492                         ev->size += 16;
9493                         ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
9494                 }
9495 -               
9496 +
9497                 ev->pollfds[ev->used].fd = fd;
9498                 ev->pollfds[ev->used].events = events;
9499 -               
9500 +
9501                 return ev->used++;
9502         }
9503  }
9504 @@ -109,12 +108,12 @@
9505         int r, poll_r;
9506         if (ndx >= ev->used) {
9507                 fprintf(stderr, "%s.%d: dying because: event: %zd >= %zd\n", __FILE__, __LINE__, ndx, ev->used);
9508 -               
9509 +
9510                 SEGFAULT();
9511 -               
9512 +
9513                 return 0;
9514         }
9515 -       
9516 +
9517         if (ev->pollfds[ndx].revents & POLLNVAL) {
9518                 /* should never happen */
9519                 SEGFAULT();
9520 @@ -131,7 +130,7 @@
9521         if (poll_r & POLLHUP) r |= FDEVENT_HUP;
9522         if (poll_r & POLLNVAL) r |= FDEVENT_NVAL;
9523         if (poll_r & POLLPRI) r |= FDEVENT_PRI;
9524 -       
9525 +
9526         return ev->pollfds[ndx].revents;
9527  }
9528  
9529 @@ -141,12 +140,12 @@
9530  
9531  static int fdevent_poll_event_next_fdndx(fdevents *ev, int ndx) {
9532         size_t i;
9533 -       
9534 +
9535         i = (ndx < 0) ? 0 : ndx + 1;
9536         for (; i < ev->used; i++) {
9537                 if (ev->pollfds[i].revents) break;
9538         }
9539 -       
9540 +
9541         return i;
9542  }
9543  
9544 @@ -154,17 +153,17 @@
9545         ev->type = FDEVENT_HANDLER_POLL;
9546  #define SET(x) \
9547         ev->x = fdevent_poll_##x;
9548 -       
9549 +
9550         SET(free);
9551         SET(poll);
9552 -       
9553 +
9554         SET(event_del);
9555         SET(event_add);
9556 -       
9557 +
9558         SET(event_next_fdndx);
9559         SET(event_get_fd);
9560         SET(event_get_revent);
9561 -       
9562 +
9563         return 0;
9564  }
9565  
9566 --- lighttpd-1.4.11/src/fdevent_select.c        2005-08-31 11:12:46.000000000 +0300
9567 +++ lighttpd-1.4.12/src/fdevent_select.c        2006-07-11 22:07:53.000000000 +0300
9568 @@ -1,18 +1,19 @@
9569 -#include <sys/time.h>
9570  #include <sys/types.h>
9571  
9572 -#include <unistd.h>
9573  #include <stdlib.h>
9574  #include <string.h>
9575  #include <errno.h>
9576  #include <signal.h>
9577  #include <fcntl.h>
9578  #include <assert.h>
9579 +#include <stdio.h>
9580  
9581  #include "fdevent.h"
9582  #include "settings.h"
9583  #include "buffer.h"
9584  
9585 +#include "sys-socket.h"
9586 +
9587  #ifdef USE_SELECT
9588  
9589  static int fdevent_select_reset(fdevents *ev) {
9590 @@ -38,7 +39,9 @@
9591         UNUSED(fde_ndx);
9592  
9593         /* we should be protected by max-fds, but you never know */
9594 +#ifndef _WIN32
9595         assert(fd < FD_SETSIZE);
9596 +#endif
9597  
9598         if (events & FDEVENT_IN) {
9599                 FD_SET(fd, &(ev->select_set_read));
9600 @@ -49,28 +52,28 @@
9601                 FD_SET(fd, &(ev->select_set_write));
9602         }
9603         FD_SET(fd, &(ev->select_set_error));
9604 -       
9605 +
9606         if (fd > ev->select_max_fd) ev->select_max_fd = fd;
9607 -       
9608 +
9609         return fd;
9610  }
9611  
9612  static int fdevent_select_poll(fdevents *ev, int timeout_ms) {
9613         struct timeval tv;
9614 -       
9615 +
9616         tv.tv_sec =  timeout_ms / 1000;
9617         tv.tv_usec = (timeout_ms % 1000) * 1000;
9618 -       
9619 +
9620         ev->select_read = ev->select_set_read;
9621         ev->select_write = ev->select_set_write;
9622         ev->select_error = ev->select_set_error;
9623 -       
9624 +
9625         return select(ev->select_max_fd + 1, &(ev->select_read), &(ev->select_write), &(ev->select_error), &tv);
9626  }
9627  
9628  static int fdevent_select_event_get_revent(fdevents *ev, size_t ndx) {
9629         int revents = 0;
9630 -       
9631 +
9632         if (FD_ISSET(ndx, &(ev->select_read))) {
9633                 revents |= FDEVENT_IN;
9634         }
9635 @@ -80,7 +83,7 @@
9636         if (FD_ISSET(ndx, &(ev->select_error))) {
9637                 revents |= FDEVENT_ERR;
9638         }
9639 -       
9640 +
9641         return revents;
9642  }
9643  
9644 @@ -92,15 +95,15 @@
9645  
9646  static int fdevent_select_event_next_fdndx(fdevents *ev, int ndx) {
9647         int i;
9648 -       
9649 +
9650         i = (ndx < 0) ? 0 : ndx + 1;
9651 -       
9652 +
9653         for (; i < ev->select_max_fd + 1; i++) {
9654                 if (FD_ISSET(i, &(ev->select_read))) break;
9655                 if (FD_ISSET(i, &(ev->select_write))) break;
9656                 if (FD_ISSET(i, &(ev->select_error))) break;
9657         }
9658 -       
9659 +
9660         return i;
9661  }
9662  
9663 @@ -108,17 +111,17 @@
9664         ev->type = FDEVENT_HANDLER_SELECT;
9665  #define SET(x) \
9666         ev->x = fdevent_select_##x;
9667 -       
9668 +
9669         SET(reset);
9670         SET(poll);
9671 -       
9672 +
9673         SET(event_del);
9674         SET(event_add);
9675 -       
9676 +
9677         SET(event_next_fdndx);
9678         SET(event_get_fd);
9679         SET(event_get_revent);
9680 -       
9681 +
9682         return 0;
9683  }
9684  
9685 --- lighttpd-1.4.11/src/fdevent_solaris_devpoll.c       2005-09-01 10:45:26.000000000 +0300
9686 +++ lighttpd-1.4.12/src/fdevent_solaris_devpoll.c       2006-07-11 22:07:51.000000000 +0300
9687 @@ -1,6 +1,5 @@
9688  #include <sys/types.h>
9689  
9690 -#include <unistd.h>
9691  #include <stdlib.h>
9692  #include <stdio.h>
9693  #include <string.h>
9694 @@ -23,55 +22,55 @@
9695  
9696  static int fdevent_solaris_devpoll_event_del(fdevents *ev, int fde_ndx, int fd) {
9697         struct pollfd pfd;
9698 -               
9699 +
9700         if (fde_ndx < 0) return -1;
9701 -       
9702 +
9703         pfd.fd = fd;
9704         pfd.events = POLLREMOVE;
9705         pfd.revents = 0;
9706 -       
9707 +
9708         if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
9709 -               fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n", 
9710 -                       __FILE__, __LINE__, 
9711 +               fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
9712 +                       __FILE__, __LINE__,
9713                         fd, strerror(errno));
9714 -               
9715 +
9716                 return -1;
9717         }
9718 -       
9719 +
9720         return -1;
9721  }
9722  
9723  static int fdevent_solaris_devpoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9724         struct pollfd pfd;
9725         int add = 0;
9726 -               
9727 +
9728         if (fde_ndx == -1) add = 1;
9729 -       
9730 +
9731         pfd.fd = fd;
9732         pfd.events = events;
9733         pfd.revents = 0;
9734 -       
9735 +
9736         if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
9737 -               fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n", 
9738 -                       __FILE__, __LINE__, 
9739 +               fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
9740 +                       __FILE__, __LINE__,
9741                         fd, strerror(errno));
9742 -               
9743 +
9744                 return -1;
9745         }
9746 -       
9747 +
9748         return fd;
9749  }
9750  
9751  static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) {
9752         struct dvpoll dopoll;
9753         int ret;
9754 -       
9755 +
9756         dopoll.dp_timeout = timeout_ms;
9757         dopoll.dp_nfds = ev->maxfds;
9758         dopoll.dp_fds = ev->devpollfds;
9759 -       
9760 +
9761         ret = ioctl(ev->devpoll_fd, DP_POLL, &dopoll);
9762 -       
9763 +
9764         return ret;
9765  }
9766  
9767 @@ -85,11 +84,11 @@
9768  
9769  static int fdevent_solaris_devpoll_event_next_fdndx(fdevents *ev, int last_ndx) {
9770         size_t i;
9771 -       
9772 +
9773         UNUSED(ev);
9774  
9775         i = (last_ndx < 0) ? 0 : last_ndx + 1;
9776 -       
9777 +
9778         return i;
9779  }
9780  
9781 @@ -117,20 +116,20 @@
9782         ev->type = FDEVENT_HANDLER_SOLARIS_DEVPOLL;
9783  #define SET(x) \
9784         ev->x = fdevent_solaris_devpoll_##x;
9785 -       
9786 +
9787         SET(free);
9788         SET(poll);
9789         SET(reset);
9790 -       
9791 +
9792         SET(event_del);
9793         SET(event_add);
9794 -       
9795 +
9796         SET(event_next_fdndx);
9797         SET(event_get_fd);
9798         SET(event_get_revent);
9799 -       
9800 +
9801         ev->devpollfds = malloc(sizeof(*ev->devpollfds) * ev->maxfds);
9802 -       
9803 +
9804         if ((ev->devpoll_fd = open("/dev/poll", O_RDWR)) < 0) {
9805                 fprintf(stderr, "%s.%d: opening /dev/poll failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
9806                         __FILE__, __LINE__, strerror(errno));
9807 @@ -152,7 +151,7 @@
9808  
9809         fprintf(stderr, "%s.%d: solaris-devpoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
9810                         __FILE__, __LINE__);
9811 -       
9812 +
9813         return -1;
9814  }
9815  #endif
9816 --- lighttpd-1.4.11/src/http-header-glue.c      2006-02-08 15:31:36.000000000 +0200
9817 +++ lighttpd-1.4.12/src/http-header-glue.c      2006-07-11 22:07:53.000000000 +0300
9818 @@ -45,20 +45,20 @@
9819  #   ifdef HAVE_STRUCT_SOCKADDR_STORAGE
9820  static size_t get_sa_len(const struct sockaddr *addr) {
9821         switch (addr->sa_family) {
9822 -               
9823 +
9824  #    ifdef AF_INET
9825         case AF_INET:
9826                 return (sizeof (struct sockaddr_in));
9827  #    endif
9828 -               
9829 +
9830  #    ifdef AF_INET6
9831         case AF_INET6:
9832                 return (sizeof (struct sockaddr_in6));
9833  #    endif
9834 -               
9835 +
9836         default:
9837                 return (sizeof (struct sockaddr));
9838 -               
9839 +
9840         }
9841  }
9842  #    define SA_LEN(addr)   (get_sa_len(addr))
9843 @@ -74,7 +74,7 @@
9844  
9845  int response_header_insert(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
9846         data_string *ds;
9847 -       
9848 +
9849         UNUSED(srv);
9850  
9851         if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
9852 @@ -82,32 +82,32 @@
9853         }
9854         buffer_copy_string_len(ds->key, key, keylen);
9855         buffer_copy_string_len(ds->value, value, vallen);
9856 -       
9857 +
9858         array_insert_unique(con->response.headers, (data_unset *)ds);
9859 -       
9860 +
9861         return 0;
9862  }
9863  
9864  int response_header_overwrite(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
9865         data_string *ds;
9866 -       
9867 +
9868         UNUSED(srv);
9869  
9870         /* if there already is a key by this name overwrite the value */
9871         if (NULL != (ds = (data_string *)array_get_element(con->response.headers, key))) {
9872                 buffer_copy_string(ds->value, value);
9873 -               
9874 +
9875                 return 0;
9876         }
9877 -       
9878 +
9879         return response_header_insert(srv, con, key, keylen, value, vallen);
9880  }
9881  
9882  int http_response_redirect_to_directory(server *srv, connection *con) {
9883         buffer *o;
9884 -       
9885 +
9886         o = buffer_init();
9887 -       
9888 +
9889         if (con->conf.is_ssl) {
9890                 buffer_copy_string(o, "https://");
9891         } else {
9892 @@ -123,36 +123,36 @@
9893  #endif
9894                 sock_addr our_addr;
9895                 socklen_t our_addr_len;
9896 -               
9897 +
9898                 our_addr_len = sizeof(our_addr);
9899 -               
9900 +
9901                 if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
9902                         con->http_status = 500;
9903 -                       
9904 +
9905                         log_error_write(srv, __FILE__, __LINE__, "ss",
9906                                         "can't get sockname", strerror(errno));
9907 -                       
9908 +
9909                         buffer_free(o);
9910                         return 0;
9911                 }
9912 -               
9913 -               
9914 +
9915 +
9916                 /* Lookup name: secondly try to get hostname for bind address */
9917                 switch(our_addr.plain.sa_family) {
9918  #ifdef HAVE_IPV6
9919                 case AF_INET6:
9920 -                       if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6), 
9921 -                                            SA_LEN((const struct sockaddr *)&our_addr.ipv6), 
9922 +                       if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6),
9923 +                                            SA_LEN((const struct sockaddr *)&our_addr.ipv6),
9924                                              hbuf, sizeof(hbuf), NULL, 0, 0)) {
9925 -                               
9926 +
9927                                 char dst[INET6_ADDRSTRLEN];
9928 -                               
9929 +
9930                                 log_error_write(srv, __FILE__, __LINE__,
9931                                                 "SSSS", "NOTICE: getnameinfo failed: ",
9932                                                 strerror(errno), ", using ip-address instead");
9933 -                               
9934 -                               buffer_append_string(o, 
9935 -                                                    inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr, 
9936 +
9937 +                               buffer_append_string(o,
9938 +                                                    inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr,
9939                                                                dst, sizeof(dst)));
9940                         } else {
9941                                 buffer_append_string(o, hbuf);
9942 @@ -164,7 +164,7 @@
9943                                 log_error_write(srv, __FILE__, __LINE__,
9944                                                 "SdSS", "NOTICE: gethostbyaddr failed: ",
9945                                                 h_errno, ", using ip-address instead");
9946 -                               
9947 +
9948                                 buffer_append_string(o, inet_ntoa(our_addr.ipv4.sin_addr));
9949                         } else {
9950                                 buffer_append_string(o, he->h_name);
9951 @@ -173,12 +173,12 @@
9952                 default:
9953                         log_error_write(srv, __FILE__, __LINE__,
9954                                         "S", "ERROR: unsupported address-type");
9955 -                       
9956 +
9957                         buffer_free(o);
9958                         return -1;
9959                 }
9960 -               
9961 -               if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) || 
9962 +
9963 +               if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) ||
9964                       (con->conf.is_ssl == 1 && srv->srvconf.port == 443))) {
9965                         buffer_append_string(o, ":");
9966                         buffer_append_long(o, srv->srvconf.port);
9967 @@ -190,41 +190,41 @@
9968                 buffer_append_string(o, "?");
9969                 buffer_append_string_buffer(o, con->uri.query);
9970         }
9971 -       
9972 +
9973         response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(o));
9974 -       
9975 +
9976         con->http_status = 301;
9977         con->file_finished = 1;
9978 -       
9979 +
9980         buffer_free(o);
9981 -       
9982 +
9983         return 0;
9984  }
9985  
9986  buffer * strftime_cache_get(server *srv, time_t last_mod) {
9987         struct tm *tm;
9988         size_t i;
9989 -               
9990 +
9991         for (i = 0; i < FILE_CACHE_MAX; i++) {
9992                 /* found cache-entry */
9993                 if (srv->mtime_cache[i].mtime == last_mod) return srv->mtime_cache[i].str;
9994 -                               
9995 +
9996                 /* found empty slot */
9997                 if (srv->mtime_cache[i].mtime == 0) break;
9998         }
9999 -       
10000 +
10001         if (i == FILE_CACHE_MAX) {
10002                 i = 0;
10003         }
10004 -               
10005 +
10006         srv->mtime_cache[i].mtime = last_mod;
10007         buffer_prepare_copy(srv->mtime_cache[i].str, 1024);
10008         tm = gmtime(&(srv->mtime_cache[i].mtime));
10009 -       srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr, 
10010 +       srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr,
10011                                                  srv->mtime_cache[i].str->size - 1,
10012                                                  "%a, %d %b %Y %H:%M:%S GMT", tm);
10013         srv->mtime_cache[i].str->used++;
10014 -       
10015 +
10016         return srv->mtime_cache[i].str;
10017  }
10018  
10019 @@ -239,56 +239,60 @@
10020          *    request. That is, if no entity tags match, then the server MUST NOT
10021          *    return a 304 (Not Modified) response.
10022          */
10023 -       
10024 +
10025         /* last-modified handling */
10026         if (con->request.http_if_none_match) {
10027                 if (etag_is_equal(con->physical.etag, con->request.http_if_none_match)) {
10028 -                       if (con->request.http_method == HTTP_METHOD_GET || 
10029 +                       if (con->request.http_method == HTTP_METHOD_GET ||
10030                             con->request.http_method == HTTP_METHOD_HEAD) {
10031 -                               
10032 +
10033                                 /* check if etag + last-modified */
10034                                 if (con->request.http_if_modified_since) {
10035                                         size_t used_len;
10036                                         char *semicolon;
10037 -                                       
10038 +
10039                                         if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
10040                                                 used_len = strlen(con->request.http_if_modified_since);
10041                                         } else {
10042                                                 used_len = semicolon - con->request.http_if_modified_since;
10043                                         }
10044 -                                       
10045 +
10046                                         if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
10047                                                 con->http_status = 304;
10048                                                 return HANDLER_FINISHED;
10049                                         } else {
10050 +#ifdef HAVE_STRPTIME
10051                                                 char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
10052 +                                               time_t t_header, t_file;
10053 +                                               struct tm tm;
10054  
10055 -                                               /* convert to timestamp */
10056 -                                               if (used_len < sizeof(buf)) {
10057 -                                                       time_t t_header, t_file;
10058 -                                                       struct tm tm;
10059 -                                                       
10060 -                                                       strncpy(buf, con->request.http_if_modified_since, used_len);
10061 -                                                       buf[used_len] = '\0';
10062 -                                                       
10063 -                                                       strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10064 -                                                       t_header = mktime(&tm);
10065 -                                                       
10066 -                                                       strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10067 -                                                       t_file = mktime(&tm);
10068 -
10069 -                                                       if (t_file > t_header) {
10070 -                                                               con->http_status = 304;
10071 -                                                               return HANDLER_FINISHED;
10072 -                                                       }
10073 -                                               } else {
10074 -                                                       log_error_write(srv, __FILE__, __LINE__, "ssdd", 
10075 -                                                                       "DEBUG: Last-Modified check failed as the received timestamp was too long:", 
10076 +                                               /* check if we can safely copy the string */
10077 +                                               if (used_len >= sizeof(buf)) {
10078 +                                                       log_error_write(srv, __FILE__, __LINE__, "ssdd",
10079 +                                                                       "DEBUG: Last-Modified check failed as the received timestamp was too long:",
10080                                                                         con->request.http_if_modified_since, used_len, sizeof(buf) - 1);
10081 -                                                       
10082 +
10083                                                         con->http_status = 412;
10084                                                         return HANDLER_FINISHED;
10085                                                 }
10086 +
10087 +
10088 +                                               strncpy(buf, con->request.http_if_modified_since, used_len);
10089 +                                               buf[used_len] = '\0';
10090 +
10091 +                                               strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10092 +                                               t_header = mktime(&tm);
10093 +
10094 +                                               strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10095 +                                               t_file = mktime(&tm);
10096 +
10097 +                                               if (t_file > t_header) return HANDLER_GO_ON;
10098 +
10099 +                                               con->http_status = 304;
10100 +                                               return HANDLER_FINISHED;
10101 +#else
10102 +                        return HANDLER_GO_ON;
10103 +#endif
10104                                         }
10105                                 } else {
10106                                         con->http_status = 304;
10107 @@ -302,16 +306,41 @@
10108         } else if (con->request.http_if_modified_since) {
10109                 size_t used_len;
10110                 char *semicolon;
10111 -               
10112 +
10113                 if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
10114                         used_len = strlen(con->request.http_if_modified_since);
10115                 } else {
10116                         used_len = semicolon - con->request.http_if_modified_since;
10117                 }
10118 -               
10119 +
10120                 if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
10121                         con->http_status = 304;
10122                         return HANDLER_FINISHED;
10123 +               } else {
10124 +#ifdef HAVE_STRPTIME
10125 +                       char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
10126 +                       time_t t_header, t_file;
10127 +                       struct tm tm;
10128 +
10129 +                       /* convert to timestamp */
10130 +                       if (used_len >= sizeof(buf)) return HANDLER_GO_ON;
10131 +
10132 +                       strncpy(buf, con->request.http_if_modified_since, used_len);
10133 +                       buf[used_len] = '\0';
10134 +
10135 +                       strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10136 +                       t_header = mktime(&tm);
10137 +
10138 +                       strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10139 +                       t_file = mktime(&tm);
10140 +
10141 +                       if (t_file > t_header) return HANDLER_GO_ON;
10142 +
10143 +                       con->http_status = 304;
10144 +                       return HANDLER_FINISHED;
10145 +#else
10146 +            return HANDLER_GO_ON;
10147 +#endif
10148                 }
10149         }
10150  
10151 --- lighttpd-1.4.11/src/http_auth.c     2006-02-01 13:02:52.000000000 +0200
10152 +++ lighttpd-1.4.12/src/http_auth.c     2006-07-11 22:07:53.000000000 +0300
10153 @@ -22,7 +22,6 @@
10154  #include <string.h>
10155  #include <time.h>
10156  #include <errno.h>
10157 -#include <unistd.h>
10158  #include <ctype.h>
10159  
10160  #include "server.h"
10161 @@ -31,23 +30,14 @@
10162  #include "http_auth_digest.h"
10163  #include "stream.h"
10164  
10165 +#include "sys-strings.h"
10166 +
10167  #ifdef USE_OPENSSL
10168  # include <openssl/md5.h>
10169  #else
10170  # include "md5.h"
10171  #endif
10172  
10173 -
10174 -#ifdef USE_PAM
10175 -#include <security/pam_appl.h>
10176 -#include <security/pam_misc.h>
10177 -
10178 -static struct pam_conv conv = {
10179 -       misc_conv,
10180 -               NULL
10181 -};
10182 -#endif
10183 -
10184  handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
10185  
10186  static const char base64_pad = '=';
10187 @@ -75,25 +65,25 @@
10188         unsigned char *result;
10189         int ch, j = 0, k;
10190         size_t i;
10191 -       
10192 +
10193         size_t in_len = strlen(in);
10194 -       
10195 +
10196         buffer_prepare_copy(out, in_len);
10197 -       
10198 +
10199         result = (unsigned char *)out->ptr;
10200 -       
10201 +
10202         ch = in[0];
10203         /* run through the whole string, converting as we go */
10204         for (i = 0; i < in_len; i++) {
10205                 ch = in[i];
10206 -               
10207 +
10208                 if (ch == '\0') break;
10209 -               
10210 +
10211                 if (ch == base64_pad) break;
10212 -               
10213 +
10214                 ch = base64_reverse_table[ch];
10215                 if (ch < 0) continue;
10216 -               
10217 +
10218                 switch(i % 4) {
10219                 case 0:
10220                         result[j] = ch << 2;
10221 @@ -125,168 +115,168 @@
10222                 }
10223         }
10224         result[k] = '\0';
10225 -       
10226 +
10227         out->used = k;
10228 -       
10229 +
10230         return result;
10231  }
10232  
10233  static int http_auth_get_password(server *srv, mod_auth_plugin_data *p, buffer *username, buffer *realm, buffer *password) {
10234         int ret = -1;
10235 -       
10236 +
10237         if (!username->used|| !realm->used) return -1;
10238 -       
10239 +
10240         if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
10241                 stream f;
10242                 char * f_line;
10243 -               
10244 +
10245                 if (buffer_is_empty(p->conf.auth_htdigest_userfile)) return -1;
10246 -               
10247 +
10248                 if (0 != stream_open(&f, p->conf.auth_htdigest_userfile)) {
10249                         log_error_write(srv, __FILE__, __LINE__, "sbss", "opening digest-userfile", p->conf.auth_htdigest_userfile, "failed:", strerror(errno));
10250 -                       
10251 +
10252                         return -1;
10253                 }
10254 -               
10255 +
10256                 f_line = f.start;
10257 -               
10258 +
10259                 while (f_line - f.start != f.size) {
10260                         char *f_user, *f_pwd, *e, *f_realm;
10261                         size_t u_len, pwd_len, r_len;
10262 -                       
10263 +
10264                         f_user = f_line;
10265 -                       
10266 -                       /* 
10267 +
10268 +                       /*
10269                          * htdigest format
10270 -                        * 
10271 -                        * user:realm:md5(user:realm:password) 
10272 +                        *
10273 +                        * user:realm:md5(user:realm:password)
10274                          */
10275 -                       
10276 +
10277                         if (NULL == (f_realm = memchr(f_user, ':', f.size - (f_user - f.start) ))) {
10278 -                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
10279 -                                               "parsed error in", p->conf.auth_htdigest_userfile, 
10280 +                               log_error_write(srv, __FILE__, __LINE__, "sbs",
10281 +                                               "parsed error in", p->conf.auth_htdigest_userfile,
10282                                                 "expected 'username:realm:hashed password'");
10283 -                               
10284 +
10285                                 stream_close(&f);
10286 -                               
10287 +
10288                                 return -1;
10289                         }
10290 -                       
10291 +
10292                         if (NULL == (f_pwd = memchr(f_realm + 1, ':', f.size - (f_realm + 1 - f.start)))) {
10293 -                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
10294 -                                               "parsed error in", p->conf.auth_plain_userfile, 
10295 +                               log_error_write(srv, __FILE__, __LINE__, "sbs",
10296 +                                               "parsed error in", p->conf.auth_plain_userfile,
10297                                                 "expected 'username:realm:hashed password'");
10298 -                               
10299 +
10300                                 stream_close(&f);
10301 -                               
10302 +
10303                                 return -1;
10304                         }
10305 -                       
10306 +
10307                         /* get pointers to the fields */
10308 -                       u_len = f_realm - f_user; 
10309 +                       u_len = f_realm - f_user;
10310                         f_realm++;
10311                         r_len = f_pwd - f_realm;
10312                         f_pwd++;
10313 -                       
10314 +
10315                         if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
10316                                 pwd_len = e - f_pwd;
10317                         } else {
10318                                 pwd_len = f.size - (f_pwd - f.start);
10319                         }
10320 -                       
10321 +
10322                         if (username->used - 1 == u_len &&
10323                             (realm->used - 1 == r_len) &&
10324                             (0 == strncmp(username->ptr, f_user, u_len)) &&
10325                             (0 == strncmp(realm->ptr, f_realm, r_len))) {
10326                                 /* found */
10327 -                               
10328 +
10329                                 buffer_copy_string_len(password, f_pwd, pwd_len);
10330 -                               
10331 +
10332                                 ret = 0;
10333                                 break;
10334                         }
10335 -                       
10336 +
10337                         /* EOL */
10338                         if (!e) break;
10339 -                       
10340 +
10341                         f_line = e + 1;
10342                 }
10343 -               
10344 +
10345                 stream_close(&f);
10346         } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD ||
10347                    p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
10348                 stream f;
10349                 char * f_line;
10350                 buffer *auth_fn;
10351 -               
10352 +
10353                 auth_fn = (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) ? p->conf.auth_htpasswd_userfile : p->conf.auth_plain_userfile;
10354 -               
10355 +
10356                 if (buffer_is_empty(auth_fn)) return -1;
10357 -               
10358 +
10359                 if (0 != stream_open(&f, auth_fn)) {
10360 -                       log_error_write(srv, __FILE__, __LINE__, "sbss", 
10361 +                       log_error_write(srv, __FILE__, __LINE__, "sbss",
10362                                         "opening plain-userfile", auth_fn, "failed:", strerror(errno));
10363 -                       
10364 +
10365                         return -1;
10366                 }
10367 -               
10368 +
10369                 f_line = f.start;
10370 -               
10371 +
10372                 while (f_line - f.start != f.size) {
10373                         char *f_user, *f_pwd, *e;
10374                         size_t u_len, pwd_len;
10375 -                       
10376 +
10377                         f_user = f_line;
10378 -                       
10379 -                       /* 
10380 +
10381 +                       /*
10382                          * htpasswd format
10383 -                        * 
10384 +                        *
10385                          * user:crypted passwd
10386                          */
10387 -                       
10388 +
10389                         if (NULL == (f_pwd = memchr(f_user, ':', f.size - (f_user - f.start) ))) {
10390 -                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
10391 -                                               "parsed error in", auth_fn, 
10392 +                               log_error_write(srv, __FILE__, __LINE__, "sbs",
10393 +                                               "parsed error in", auth_fn,
10394                                                 "expected 'username:hashed password'");
10395 -                               
10396 +
10397                                 stream_close(&f);
10398 -                               
10399 +
10400                                 return -1;
10401                         }
10402 -                       
10403 +
10404                         /* get pointers to the fields */
10405 -                       u_len = f_pwd - f_user; 
10406 +                       u_len = f_pwd - f_user;
10407                         f_pwd++;
10408 -                       
10409 +
10410                         if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
10411                                 pwd_len = e - f_pwd;
10412                         } else {
10413                                 pwd_len = f.size - (f_pwd - f.start);
10414                         }
10415 -                       
10416 +
10417                         if (username->used - 1 == u_len &&
10418                             (0 == strncmp(username->ptr, f_user, u_len))) {
10419                                 /* found */
10420 -                               
10421 +
10422                                 buffer_copy_string_len(password, f_pwd, pwd_len);
10423 -                               
10424 +
10425                                 ret = 0;
10426                                 break;
10427                         }
10428 -                       
10429 +
10430                         /* EOL */
10431                         if (!e) break;
10432 -                       
10433 +
10434                         f_line = e + 1;
10435                 }
10436 -               
10437 +
10438                 stream_close(&f);
10439         } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
10440                 ret = 0;
10441         } else {
10442                 return -1;
10443         }
10444 -       
10445 +
10446         return ret;
10447  }
10448  
10449 @@ -296,7 +286,7 @@
10450         int username_len;
10451         data_string *require;
10452         array *req;
10453 -       
10454 +
10455         UNUSED(group);
10456         UNUSED(host);
10457  
10458 @@ -304,12 +294,12 @@
10459         /* search auth-directives for path */
10460         for (i = 0; i < p->conf.auth_require->used; i++) {
10461                 if (p->conf.auth_require->data[i]->key->used == 0) continue;
10462 -               
10463 +
10464                 if (0 == strncmp(url, p->conf.auth_require->data[i]->key->ptr, p->conf.auth_require->data[i]->key->used - 1)) {
10465                         break;
10466                 }
10467         }
10468 -       
10469 +
10470         if (i == p->conf.auth_require->used) {
10471                 return -1;
10472         }
10473 @@ -317,72 +307,72 @@
10474         req = ((data_array *)(p->conf.auth_require->data[i]))->value;
10475  
10476         require = (data_string *)array_get_element(req, "require");
10477 -       
10478 +
10479         /* if we get here, the user we got a authed user */
10480         if (0 == strcmp(require->value->ptr, "valid-user")) {
10481                 return 0;
10482         }
10483 -       
10484 +
10485         /* user=name1|group=name3|host=name4 */
10486 -       
10487 +
10488         /* seperate the string by | */
10489  #if 0
10490         log_error_write(srv, __FILE__, __LINE__, "sb", "rules", require->value);
10491 -#endif 
10492 -       
10493 +#endif
10494 +
10495         username_len = username ? strlen(username) : 0;
10496 -       
10497 +
10498         r = rules = require->value->ptr;
10499 -       
10500 +
10501         while (1) {
10502                 const char *eq;
10503                 const char *k, *v, *e;
10504                 int k_len, v_len, r_len;
10505 -               
10506 +
10507                 e = strchr(r, '|');
10508 -               
10509 +
10510                 if (e) {
10511                         r_len = e - r;
10512                 } else {
10513                         r_len = strlen(rules) - (r - rules);
10514                 }
10515 -               
10516 +
10517                 /* from r to r + r_len is a rule */
10518 -               
10519 +
10520                 if (0 == strncmp(r, "valid-user", r_len)) {
10521 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
10522 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
10523                                         "parsing the 'require' section in 'auth.require' failed: valid-user cannot be combined with other require rules",
10524                                         require->value);
10525                         return -1;
10526                 }
10527 -               
10528 +
10529                 /* search for = in the rules */
10530                 if (NULL == (eq = strchr(r, '='))) {
10531 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
10532 -                                       "parsing the 'require' section in 'auth.require' failed: a = is missing", 
10533 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
10534 +                                       "parsing the 'require' section in 'auth.require' failed: a = is missing",
10535                                         require->value);
10536                         return -1;
10537                 }
10538 -               
10539 +
10540                 /* = out of range */
10541                 if (eq > r + r_len) {
10542 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
10543 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
10544                                         "parsing the 'require' section in 'auth.require' failed: = out of range",
10545                                         require->value);
10546 -                       
10547 +
10548                         return -1;
10549                 }
10550 -               
10551 +
10552                 /* the part before the = is user|group|host */
10553 -               
10554 +
10555                 k = r;
10556                 k_len = eq - r;
10557                 v = eq + 1;
10558                 v_len = r_len - k_len - 1;
10559 -               
10560 +
10561                 if (k_len == 4) {
10562                         if (0 == strncmp(k, "user", k_len)) {
10563 -                               if (username && 
10564 +                               if (username &&
10565                                     username_len == v_len &&
10566                                     0 == strncmp(username, v, v_len)) {
10567                                         return 0;
10568 @@ -404,19 +394,19 @@
10569                         log_error_write(srv, __FILE__, __LINE__, "s", "unknown  key");
10570                         return -1;
10571                 }
10572 -               
10573 +
10574                 if (!e) break;
10575                 r = e + 1;
10576         }
10577 -       
10578 +
10579         log_error_write(srv, __FILE__, __LINE__, "s", "nothing matched");
10580 -       
10581 +
10582         return -1;
10583  }
10584  
10585  /**
10586 - * 
10587 - * 
10588 + *
10589 + *
10590   * @param password password-string from the auth-backend
10591   * @param pw       password-string from the client
10592   */
10593 @@ -426,16 +416,16 @@
10594         UNUSED(req);
10595  
10596         if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
10597 -               /* 
10598 +               /*
10599                  * htdigest format
10600 -                * 
10601 -                * user:realm:md5(user:realm:password) 
10602 +                *
10603 +                * user:realm:md5(user:realm:password)
10604                  */
10605 -               
10606 +
10607                 MD5_CTX Md5Ctx;
10608                 HASH HA1;
10609                 char a1[256];
10610 -               
10611 +
10612                 MD5_Init(&Md5Ctx);
10613                 MD5_Update(&Md5Ctx, (unsigned char *)username->ptr, username->used - 1);
10614                 MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
10615 @@ -443,24 +433,24 @@
10616                 MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
10617                 MD5_Update(&Md5Ctx, (unsigned char *)pw, strlen(pw));
10618                 MD5_Final(HA1, &Md5Ctx);
10619 -               
10620 +
10621                 CvtHex(HA1, a1);
10622 -               
10623 +
10624                 if (0 == strcmp(password->ptr, a1)) {
10625                         return 0;
10626                 }
10627 -       } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) { 
10628 -#ifdef HAVE_CRYPT      
10629 +       } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) {
10630 +#ifdef HAVE_CRYPT
10631                 char salt[32];
10632                 char *crypted;
10633                 size_t salt_len = 0;
10634 -               /* 
10635 +               /*
10636                  * htpasswd format
10637 -                * 
10638 +                *
10639                  * user:crypted password
10640                  */
10641  
10642 -               /* 
10643 +               /*
10644                  *  Algorithm      Salt
10645                  *  CRYPT_STD_DES   2-character (Default)
10646                  *  CRYPT_EXT_DES   9-character
10647 @@ -478,7 +468,7 @@
10648                         salt_len = 2;
10649                 } else if (password->ptr[0] == '$' && password->ptr[2] == '$') {
10650                         char *dollar = NULL;
10651 -               
10652 +
10653                         if (NULL == (dollar = strchr(password->ptr + 3, '$'))) {
10654                                 fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
10655                                 return -1;
10656 @@ -495,7 +485,7 @@
10657                 strncpy(salt, password->ptr, salt_len);
10658  
10659                 salt[salt_len] = '\0';
10660 -               
10661 +
10662                 crypted = crypt(pw, salt);
10663  
10664                 if (0 == strcmp(password->ptr, crypted)) {
10665 @@ -503,40 +493,13 @@
10666                 } else {
10667                         fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
10668                 }
10669 -       
10670 -#endif 
10671 -       } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) { 
10672 +
10673 +#endif
10674 +       } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
10675                 if (0 == strcmp(password->ptr, pw)) {
10676                         return 0;
10677                 }
10678 -       } else if (p->conf.auth_backend == AUTH_BACKEND_PAM) { 
10679 -#ifdef USE_PAM
10680 -               pam_handle_t *pamh=NULL;
10681 -               int retval;
10682 -               
10683 -               retval = pam_start("lighttpd", username->ptr, &conv, &pamh);
10684 -               
10685 -               if (retval == PAM_SUCCESS)
10686 -                       retval = pam_authenticate(pamh, 0);    /* is user really user? */
10687 -               
10688 -               if (retval == PAM_SUCCESS)
10689 -                       retval = pam_acct_mgmt(pamh, 0);       /* permitted access? */
10690 -               
10691 -               /* This is where we have been authorized or not. */
10692 -               
10693 -               if (pam_end(pamh,retval) != PAM_SUCCESS) {     /* close Linux-PAM */
10694 -                       pamh = NULL;
10695 -                       log_error_write(srv, __FILE__, __LINE__, "s", "failed to release authenticator");
10696 -               }
10697 -               
10698 -               if (retval == PAM_SUCCESS) {
10699 -                       log_error_write(srv, __FILE__, __LINE__, "s", "Authenticated");
10700 -                       return 0;
10701 -               } else {
10702 -                       log_error_write(srv, __FILE__, __LINE__, "s", "Not Authenticated");
10703 -               }
10704 -#endif
10705 -       } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) { 
10706 +       } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
10707  #ifdef USE_LDAP
10708                 LDAP *ldap;
10709                 LDAPMessage *lm, *first;
10710 @@ -544,45 +507,45 @@
10711                 int ret;
10712                 char *attrs[] = { LDAP_NO_ATTRS, NULL };
10713                 size_t i;
10714 -               
10715 +
10716                 /* for now we stay synchronous */
10717 -               
10718 -               /* 
10719 +
10720 +               /*
10721                  * 1. connect anonymously (done in plugin init)
10722                  * 2. get DN for uid = username
10723                  * 3. auth against ldap server
10724                  * 4. (optional) check a field
10725                  * 5. disconnect
10726 -                * 
10727 +                *
10728                  */
10729 -               
10730 +
10731                 /* check username
10732 -                * 
10733 +                *
10734                  * we have to protect us againt username which modifies out filter in
10735                  * a unpleasant way
10736                  */
10737 -               
10738 +
10739                 for (i = 0; i < username->used - 1; i++) {
10740                         char c = username->ptr[i];
10741 -                       
10742 +
10743                         if (!isalpha(c) &&
10744                             !isdigit(c)) {
10745 -                               
10746 -                               log_error_write(srv, __FILE__, __LINE__, "sbd", 
10747 +
10748 +                               log_error_write(srv, __FILE__, __LINE__, "sbd",
10749                                         "ldap: invalid character (a-zA-Z0-9 allowed) in username:", username, i);
10750 -                               
10751 +
10752                                 return -1;
10753                         }
10754                 }
10755 -               
10756 -               
10757 -               
10758 +
10759 +
10760 +
10761                 /* build filter */
10762                 buffer_copy_string_buffer(p->ldap_filter, p->conf.ldap_filter_pre);
10763                 buffer_append_string_buffer(p->ldap_filter, username);
10764                 buffer_append_string_buffer(p->ldap_filter, p->conf.ldap_filter_post);
10765 -               
10766 -               
10767 +
10768 +
10769                 /* 2. */
10770                 if (p->conf.ldap == NULL ||
10771                     LDAP_SUCCESS != (ret = ldap_search_s(p->conf.ldap, p->conf.auth_ldap_basedn->ptr, LDAP_SCOPE_SUBTREE, p->ldap_filter->ptr, attrs, 0, &lm))) {
10772 @@ -590,71 +553,71 @@
10773                                 return -1;
10774                         if (LDAP_SUCCESS != (ret = ldap_search_s(p->conf.ldap, p->conf.auth_ldap_basedn->ptr, LDAP_SCOPE_SUBTREE, p->ldap_filter->ptr, attrs, 0, &lm))) {
10775  
10776 -                       log_error_write(srv, __FILE__, __LINE__, "sssb", 
10777 +                       log_error_write(srv, __FILE__, __LINE__, "sssb",
10778                                         "ldap:", ldap_err2string(ret), "filter:", p->ldap_filter);
10779 -                       
10780 +
10781                         return -1;
10782                         }
10783                 }
10784 -               
10785 +
10786                 if (NULL == (first = ldap_first_entry(p->conf.ldap, lm))) {
10787                         log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
10788 -                       
10789 +
10790                         ldap_msgfree(lm);
10791 -                       
10792 +
10793                         return -1;
10794                 }
10795 -               
10796 +
10797                 if (NULL == (dn = ldap_get_dn(p->conf.ldap, first))) {
10798                         log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
10799 -                       
10800 +
10801                         ldap_msgfree(lm);
10802 -                       
10803 +
10804                         return -1;
10805                 }
10806 -               
10807 +
10808                 ldap_msgfree(lm);
10809 -               
10810 -               
10811 +
10812 +
10813                 /* 3. */
10814                 if (NULL == (ldap = ldap_init(p->conf.auth_ldap_hostname->ptr, LDAP_PORT))) {
10815                         log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
10816                         return -1;
10817                 }
10818 -               
10819 +
10820                 ret = LDAP_VERSION3;
10821                 if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
10822                         log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
10823 -                       
10824 +
10825                         ldap_unbind_s(ldap);
10826 -                       
10827 +
10828                         return -1;
10829                 }
10830 -               
10831 +
10832                 if (p->conf.auth_ldap_starttls == 1) {
10833                         if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(ldap, NULL,  NULL))) {
10834                                 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
10835 -               
10836 +
10837                                 ldap_unbind_s(ldap);
10838 -                               
10839 +
10840                                 return -1;
10841                         }
10842                 }
10843  
10844 -               
10845 +
10846                 if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(ldap, dn, pw))) {
10847                         log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
10848 -                       
10849 +
10850                         ldap_unbind_s(ldap);
10851 -                       
10852 +
10853                         return -1;
10854                 }
10855 -               
10856 +
10857                 /* 5. */
10858                 ldap_unbind_s(ldap);
10859 -               
10860 +
10861                 /* everything worked, good, access granted */
10862 -               
10863 +
10864                 return 0;
10865  #endif
10866         }
10867 @@ -664,65 +627,65 @@
10868  int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
10869         buffer *username, *password;
10870         char *pw;
10871 -       
10872 +
10873         data_string *realm;
10874 -       
10875 +
10876         realm = (data_string *)array_get_element(req, "realm");
10877 -       
10878 +
10879         username = buffer_init();
10880         password = buffer_init();
10881 -       
10882 +
10883         base64_decode(username, realm_str);
10884 -       
10885 +
10886         /* r2 == user:password */
10887         if (NULL == (pw = strchr(username->ptr, ':'))) {
10888                 buffer_free(username);
10889 -               
10890 +
10891                 log_error_write(srv, __FILE__, __LINE__, "sb", ": is missing in", username);
10892 -               
10893 +
10894                 return 0;
10895         }
10896 -       
10897 +
10898         *pw++ = '\0';
10899 -       
10900 +
10901         username->used = pw - username->ptr;
10902 -       
10903 +
10904         /* copy password to r1 */
10905         if (http_auth_get_password(srv, p, username, realm->value, password)) {
10906                 buffer_free(username);
10907                 buffer_free(password);
10908 -               
10909 +
10910                 log_error_write(srv, __FILE__, __LINE__, "s", "get_password failed");
10911 -               
10912 +
10913                 return 0;
10914         }
10915 -       
10916 +
10917         /* password doesn't match */
10918         if (http_auth_basic_password_compare(srv, p, req, username, realm->value, password, pw)) {
10919                 log_error_write(srv, __FILE__, __LINE__, "sbb", "password doesn't match for", con->uri.path, username);
10920 -               
10921 +
10922                 buffer_free(username);
10923                 buffer_free(password);
10924 -               
10925 +
10926                 return 0;
10927         }
10928 -       
10929 +
10930         /* value is our allow-rules */
10931         if (http_auth_match_rules(srv, p, url->ptr, username->ptr, NULL, NULL)) {
10932                 buffer_free(username);
10933                 buffer_free(password);
10934 -               
10935 +
10936                 log_error_write(srv, __FILE__, __LINE__, "s", "rules didn't match");
10937 -               
10938 +
10939                 return 0;
10940         }
10941 -       
10942 +
10943         /* remember the username */
10944         buffer_copy_string_buffer(p->auth_user, username);
10945 -       
10946 +
10947         buffer_free(username);
10948         buffer_free(password);
10949 -       
10950 +
10951         return 1;
10952  }
10953  
10954 @@ -735,7 +698,7 @@
10955  int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
10956         char a1[256];
10957         char a2[256];
10958 -       
10959 +
10960         char *username;
10961         char *realm;
10962         char *nonce;
10963 @@ -745,18 +708,18 @@
10964         char *cnonce;
10965         char *nc;
10966         char *respons;
10967 -       
10968 +
10969         char *e, *c;
10970         const char *m = NULL;
10971         int i;
10972         buffer *password, *b, *username_buf, *realm_buf;
10973 -       
10974 +
10975         MD5_CTX Md5Ctx;
10976         HASH HA1;
10977         HASH HA2;
10978         HASH RespHash;
10979         HASHHEX HA2Hex;
10980 -       
10981 +
10982  
10983         /* init pointers */
10984  #define S(x) \
10985 @@ -771,11 +734,11 @@
10986                 { S("cnonce=") },
10987                 { S("nc=") },
10988                 { S("response=") },
10989 -               
10990 +
10991                 { NULL, 0, NULL }
10992         };
10993  #undef S
10994 -       
10995 +
10996         dkv[0].ptr = &username;
10997         dkv[1].ptr = &realm;
10998         dkv[2].ptr = &nonce;
10999 @@ -786,24 +749,24 @@
11000         dkv[7].ptr = &nc;
11001         dkv[8].ptr = &respons;
11002         dkv[9].ptr = NULL;
11003 -       
11004 +
11005         UNUSED(req);
11006 -       
11007 +
11008         for (i = 0; dkv[i].key; i++) {
11009                 *(dkv[i].ptr) = NULL;
11010         }
11011 -       
11012 -       
11013 +
11014 +
11015         if (p->conf.auth_backend != AUTH_BACKEND_HTDIGEST &&
11016             p->conf.auth_backend != AUTH_BACKEND_PLAIN) {
11017 -               log_error_write(srv, __FILE__, __LINE__, "s", 
11018 +               log_error_write(srv, __FILE__, __LINE__, "s",
11019                                 "digest: unsupported backend (only htdigest or plain)");
11020 -               
11021 +
11022                 return -1;
11023         }
11024 -       
11025 +
11026         b = buffer_init_string(realm_str);
11027 -       
11028 +
11029         /* parse credentials from client */
11030         for (c = b->ptr; *c; c++) {
11031                 /* skip whitespaces */
11032 @@ -812,18 +775,18 @@
11033  
11034                 for (i = 0; dkv[i].key; i++) {
11035                         if ((0 == strncmp(c, dkv[i].key, dkv[i].key_len))) {
11036 -                               if ((c[dkv[i].key_len] == '"') && 
11037 +                               if ((c[dkv[i].key_len] == '"') &&
11038                                     (NULL != (e = strchr(c + dkv[i].key_len + 1, '"')))) {
11039                                         /* value with "..." */
11040                                         *(dkv[i].ptr) = c + dkv[i].key_len + 1;
11041                                         c = e;
11042 -       
11043 +
11044                                         *e = '\0';
11045                                 } else if (NULL != (e = strchr(c + dkv[i].key_len, ','))) {
11046                                         /* value without "...", terminated by ',' */
11047                                         *(dkv[i].ptr) = c + dkv[i].key_len;
11048                                         c = e;
11049 -                                       
11050 +
11051                                         *e = '\0';
11052                                 } else {
11053                                         /* value without "...", terminated by EOL */
11054 @@ -833,7 +796,7 @@
11055                         }
11056                 }
11057         }
11058 -       
11059 +
11060         if (p->conf.auth_debug > 1) {
11061                 log_error_write(srv, __FILE__, __LINE__, "ss", "username", username);
11062                 log_error_write(srv, __FILE__, __LINE__, "ss", "realm", realm);
11063 @@ -845,22 +808,22 @@
11064                 log_error_write(srv, __FILE__, __LINE__, "ss", "nc", nc);
11065                 log_error_write(srv, __FILE__, __LINE__, "ss", "response", respons);
11066         }
11067 -       
11068 +
11069         /* check if everything is transmitted */
11070 -       if (!username || 
11071 +       if (!username ||
11072             !realm ||
11073             !nonce ||
11074             !uri ||
11075             (qop && (!nc || !cnonce)) ||
11076             !respons ) {
11077                 /* missing field */
11078 -               
11079 -               log_error_write(srv, __FILE__, __LINE__, "s", 
11080 +
11081 +               log_error_write(srv, __FILE__, __LINE__, "s",
11082                                 "digest: missing field");
11083                 return -1;
11084         }
11085  
11086 -       m = get_http_method_name(con->request.http_method);     
11087 +       m = get_http_method_name(con->request.http_method);
11088  
11089         /* password-string == HA1 */
11090         password = buffer_init();
11091 @@ -873,10 +836,10 @@
11092                 buffer_free(realm_buf);
11093                 return 0;
11094         }
11095 -       
11096 +
11097         buffer_free(username_buf);
11098         buffer_free(realm_buf);
11099 -       
11100 +
11101         if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
11102                 /* generate password from plain-text */
11103                 MD5_Init(&Md5Ctx);
11104 @@ -890,16 +853,16 @@
11105                 /* HA1 */
11106                 /* transform the 32-byte-hex-md5 to a 16-byte-md5 */
11107                 for (i = 0; i < HASHLEN; i++) {
11108 -                       HA1[i] = hex2int(password->ptr[i*2]) << 4; 
11109 -                       HA1[i] |= hex2int(password->ptr[i*2+1]); 
11110 +                       HA1[i] = hex2int(password->ptr[i*2]) << 4;
11111 +                       HA1[i] |= hex2int(password->ptr[i*2+1]);
11112                 }
11113         } else {
11114                 /* we already check that above */
11115                 SEGFAULT();
11116         }
11117 -       
11118 +
11119         buffer_free(password);
11120 -       
11121 +
11122         if (algorithm &&
11123             strcasecmp(algorithm, "md5-sess") == 0) {
11124                 MD5_Init(&Md5Ctx);
11125 @@ -910,9 +873,9 @@
11126                 MD5_Update(&Md5Ctx, (unsigned char *)cnonce, strlen(cnonce));
11127                 MD5_Final(HA1, &Md5Ctx);
11128         }
11129 -       
11130 +
11131         CvtHex(HA1, a1);
11132 -       
11133 +
11134         /* calculate H(A2) */
11135         MD5_Init(&Md5Ctx);
11136         MD5_Update(&Md5Ctx, (unsigned char *)m, strlen(m));
11137 @@ -924,7 +887,7 @@
11138         }
11139         MD5_Final(HA2, &Md5Ctx);
11140         CvtHex(HA2, HA2Hex);
11141 -       
11142 +
11143         /* calculate response */
11144         MD5_Init(&Md5Ctx);
11145         MD5_Update(&Md5Ctx, (unsigned char *)a1, HASHHEXLEN);
11146 @@ -942,39 +905,39 @@
11147         MD5_Update(&Md5Ctx, (unsigned char *)HA2Hex, HASHHEXLEN);
11148         MD5_Final(RespHash, &Md5Ctx);
11149         CvtHex(RespHash, a2);
11150 -       
11151 +
11152         if (0 != strcmp(a2, respons)) {
11153                 /* digest not ok */
11154 -               
11155 +
11156                 if (p->conf.auth_debug) {
11157 -                       log_error_write(srv, __FILE__, __LINE__, "sss", 
11158 +                       log_error_write(srv, __FILE__, __LINE__, "sss",
11159                                 "digest: digest mismatch", a2, respons);
11160                 }
11161 -               
11162 -               log_error_write(srv, __FILE__, __LINE__, "sss", 
11163 +
11164 +               log_error_write(srv, __FILE__, __LINE__, "sss",
11165                                 "digest: auth failed for", username, "wrong password");
11166 -               
11167 +
11168                 buffer_free(b);
11169                 return 0;
11170         }
11171 -       
11172 +
11173         /* value is our allow-rules */
11174         if (http_auth_match_rules(srv, p, url->ptr, username, NULL, NULL)) {
11175                 buffer_free(b);
11176 -               
11177 -               log_error_write(srv, __FILE__, __LINE__, "s", 
11178 +
11179 +               log_error_write(srv, __FILE__, __LINE__, "s",
11180                                 "digest: rules did match");
11181 -               
11182 +
11183                 return 0;
11184         }
11185 -       
11186 +
11187         /* remember the username */
11188         buffer_copy_string(p->auth_user, username);
11189 -       
11190 +
11191         buffer_free(b);
11192 -       
11193 +
11194         if (p->conf.auth_debug) {
11195 -               log_error_write(srv, __FILE__, __LINE__, "s", 
11196 +               log_error_write(srv, __FILE__, __LINE__, "s",
11197                                 "digest: auth ok");
11198         }
11199         return 1;
11200 @@ -985,23 +948,23 @@
11201         HASH h;
11202         MD5_CTX Md5Ctx;
11203         char hh[32];
11204 -       
11205 +
11206         UNUSED(p);
11207  
11208         /* generate shared-secret */
11209         MD5_Init(&Md5Ctx);
11210         MD5_Update(&Md5Ctx, (unsigned char *)fn->ptr, fn->used - 1);
11211         MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
11212 -       
11213 +
11214         /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
11215         ltostr(hh, srv->cur_ts);
11216         MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
11217         ltostr(hh, rand());
11218         MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
11219 -       
11220 +
11221         MD5_Final(h, &Md5Ctx);
11222 -       
11223 +
11224         CvtHex(h, out);
11225 -       
11226 +
11227         return 0;
11228  }
11229 --- lighttpd-1.4.11/src/http_auth.h     2005-08-14 17:12:31.000000000 +0300
11230 +++ lighttpd-1.4.12/src/http_auth.h     2006-07-11 22:07:53.000000000 +0300
11231 @@ -9,22 +9,26 @@
11232  # include <ldap.h>
11233  #endif
11234  
11235 -typedef enum { AUTH_BACKEND_UNSET, AUTH_BACKEND_PLAIN, 
11236 -               AUTH_BACKEND_LDAP, AUTH_BACKEND_HTPASSWD, 
11237 -               AUTH_BACKEND_HTDIGEST, AUTH_BACKEND_PAM } auth_backend_t;
11238 +typedef enum {
11239 +       AUTH_BACKEND_UNSET,
11240 +       AUTH_BACKEND_PLAIN,
11241 +       AUTH_BACKEND_LDAP,
11242 +       AUTH_BACKEND_HTPASSWD,
11243 +       AUTH_BACKEND_HTDIGEST
11244 +} auth_backend_t;
11245  
11246  typedef struct {
11247         /* auth */
11248         array  *auth_require;
11249 -       
11250 +
11251         buffer *auth_plain_groupfile;
11252         buffer *auth_plain_userfile;
11253 -       
11254 +
11255         buffer *auth_htdigest_userfile;
11256         buffer *auth_htpasswd_userfile;
11257 -       
11258 +
11259         buffer *auth_backend_conf;
11260 -       
11261 +
11262         buffer *auth_ldap_hostname;
11263         buffer *auth_ldap_basedn;
11264         buffer *auth_ldap_binddn;
11265 @@ -32,15 +36,15 @@
11266         buffer *auth_ldap_filter;
11267         buffer *auth_ldap_cafile;
11268         unsigned short auth_ldap_starttls;
11269 -       
11270 +
11271         unsigned short auth_debug;
11272 -       
11273 +
11274         /* generated */
11275         auth_backend_t auth_backend;
11276 -       
11277 +
11278  #ifdef USE_LDAP
11279         LDAP *ldap;
11280 -       
11281 +
11282         buffer *ldap_filter_pre;
11283         buffer *ldap_filter_post;
11284  #endif
11285 @@ -49,15 +53,15 @@
11286  typedef struct {
11287         PLUGIN_DATA;
11288         buffer *tmp_buf;
11289 -       
11290 +
11291         buffer *auth_user;
11292  
11293  #ifdef USE_LDAP
11294         buffer *ldap_filter;
11295  #endif
11296 -       
11297 +
11298         mod_auth_plugin_config **config_storage;
11299 -       
11300 +
11301         mod_auth_plugin_config conf; /* this is only used as long as no handler_ctx is setup */
11302  } mod_auth_plugin_data;
11303  
11304 --- lighttpd-1.4.11/src/http_auth_digest.h      2006-01-05 00:54:01.000000000 +0200
11305 +++ lighttpd-1.4.12/src/http_auth_digest.h      2006-07-11 22:07:53.000000000 +0300
11306 @@ -12,7 +12,7 @@
11307  #ifdef USE_OPENSSL
11308  #define IN const
11309  #else
11310 -#define IN 
11311 +#define IN
11312  #endif
11313  #define OUT
11314  
11315 --- lighttpd-1.4.11/src/http_chunk.c    2005-08-11 01:26:50.000000000 +0300
11316 +++ lighttpd-1.4.12/src/http_chunk.c    2006-07-11 22:07:53.000000000 +0300
11317 @@ -1,7 +1,7 @@
11318  /**
11319   * the HTTP chunk-API
11320 - * 
11321 - * 
11322 + *
11323 + *
11324   */
11325  
11326  #include <sys/types.h>
11327 @@ -9,7 +9,6 @@
11328  
11329  #include <stdlib.h>
11330  #include <fcntl.h>
11331 -#include <unistd.h>
11332  
11333  #include <stdio.h>
11334  #include <errno.h>
11335 @@ -23,19 +22,19 @@
11336  static int http_chunk_append_len(server *srv, connection *con, size_t len) {
11337         size_t i, olen = len, j;
11338         buffer *b;
11339 -       
11340 +
11341         b = srv->tmp_chunk_len;
11342 -       
11343 +
11344         if (len == 0) {
11345                 buffer_copy_string(b, "0");
11346         } else {
11347                 for (i = 0; i < 8 && len; i++) {
11348                         len >>= 4;
11349                 }
11350 -               
11351 +
11352                 /* i is the number of hex digits we have */
11353                 buffer_prepare_copy(b, i + 1);
11354 -               
11355 +
11356                 for (j = i-1, len = olen; j+1 > 0; j--) {
11357                         b->ptr[j] = (len & 0xf) + (((len & 0xf) <= 9) ? '0' : 'a' - 10);
11358                         len >>= 4;
11359 @@ -43,61 +42,61 @@
11360                 b->used = i;
11361                 b->ptr[b->used++] = '\0';
11362         }
11363 -               
11364 +
11365         buffer_append_string(b, "\r\n");
11366         chunkqueue_append_buffer(con->write_queue, b);
11367 -       
11368 +
11369         return 0;
11370  }
11371  
11372  
11373  int http_chunk_append_file(server *srv, connection *con, buffer *fn, off_t offset, off_t len) {
11374         chunkqueue *cq;
11375 -       
11376 +
11377         if (!con) return -1;
11378 -       
11379 +
11380         cq = con->write_queue;
11381 -       
11382 +
11383         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11384                 http_chunk_append_len(srv, con, len);
11385         }
11386 -       
11387 +
11388         chunkqueue_append_file(cq, fn, offset, len);
11389 -       
11390 +
11391         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && len > 0) {
11392                 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11393         }
11394 -       
11395 +
11396         return 0;
11397  }
11398  
11399  int http_chunk_append_buffer(server *srv, connection *con, buffer *mem) {
11400         chunkqueue *cq;
11401 -       
11402 +
11403         if (!con) return -1;
11404 -       
11405 +
11406         cq = con->write_queue;
11407 -       
11408 +
11409         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11410                 http_chunk_append_len(srv, con, mem->used - 1);
11411         }
11412 -       
11413 +
11414         chunkqueue_append_buffer(cq, mem);
11415 -       
11416 +
11417         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && mem->used > 0) {
11418                 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11419         }
11420 -       
11421 +
11422         return 0;
11423  }
11424  
11425  int http_chunk_append_mem(server *srv, connection *con, const char * mem, size_t len) {
11426         chunkqueue *cq;
11427 -       
11428 +
11429         if (!con) return -1;
11430 -       
11431 +
11432         cq = con->write_queue;
11433 -       
11434 +
11435         if (len == 0) {
11436                 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11437                         http_chunk_append_len(srv, con, 0);
11438 @@ -107,17 +106,17 @@
11439                 }
11440                 return 0;
11441         }
11442 -       
11443 +
11444         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11445                 http_chunk_append_len(srv, con, len - 1);
11446         }
11447 -       
11448 +
11449         chunkqueue_append_mem(cq, mem, len);
11450 -       
11451 +
11452         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11453                 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11454         }
11455 -       
11456 +
11457         return 0;
11458  }
11459  
11460 @@ -125,9 +124,9 @@
11461  off_t http_chunkqueue_length(server *srv, connection *con) {
11462         if (!con) {
11463                 log_error_write(srv, __FILE__, __LINE__, "s", "connection is NULL!!");
11464 -               
11465 +
11466                 return 0;
11467         }
11468 -       
11469 +
11470         return chunkqueue_length(con->write_queue);
11471  }
11472 --- lighttpd-1.4.11/src/http_resp.c     1970-01-01 03:00:00.000000000 +0300
11473 +++ lighttpd-1.4.12/src/http_resp.c     2006-07-11 22:07:53.000000000 +0300
11474 @@ -0,0 +1,261 @@
11475 +#include <string.h>
11476 +#include <stdlib.h>
11477 +#include <stdio.h>
11478 +#include <assert.h>
11479 +
11480 +#include "http_resp.h"
11481 +#include "http_resp_parser.h"
11482 +
11483 +/* declare prototypes for the parser */
11484 +void *http_resp_parserAlloc(void *(*mallocProc)(size_t));
11485 +void http_resp_parserFree(void *p,  void (*freeProc)(void*));
11486 +void http_resp_parserTrace(FILE *TraceFILE, char *zTracePrompt);
11487 +void http_resp_parser(void *, int, buffer *, http_resp_ctx_t *);
11488 +
11489 +typedef struct {
11490 +       chunkqueue *cq;
11491 +
11492 +       chunk *c; /* current chunk in the chunkqueue */
11493 +    size_t offset; /* current offset in current chunk */
11494 +
11495 +    chunk *lookup_c;
11496 +    size_t lookup_offset;
11497 +
11498 +    int is_key;
11499 +    int is_statusline;
11500 +} http_resp_tokenizer_t;
11501 +
11502 +http_resp *http_response_init(void) {
11503 +    http_resp *resp = calloc(1, sizeof(*resp));
11504 +
11505 +    resp->reason = buffer_init();
11506 +    resp->headers = array_init();
11507 +
11508 +    return resp;
11509 +}
11510 +
11511 +void http_response_reset(http_resp *resp) {
11512 +    if (!resp) return;
11513 +
11514 +    buffer_reset(resp->reason);
11515 +    array_reset(resp->headers);
11516 +
11517 +}
11518 +
11519 +void http_response_free(http_resp *resp) {
11520 +    if (!resp) return;
11521 +
11522 +    buffer_free(resp->reason);
11523 +    array_free(resp->headers);
11524 +
11525 +    free(resp);
11526 +}
11527 +
11528 +static int http_resp_get_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
11529 +    if (t->offset == t->c->mem->used - 1) {
11530 +        /* end of chunk, open next chunk */
11531 +
11532 +        if (!t->c->next) return -1;
11533 +
11534 +        t->c = t->c->next;
11535 +        t->offset = 0;
11536 +    }
11537 +
11538 +    *c = t->c->mem->ptr[t->offset++];
11539 +
11540 +    t->lookup_offset = t->offset;
11541 +    t->lookup_c = t->c;
11542 +
11543 +    //fprintf(stderr, "%s.%d: get: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->offset - 1);
11544 +
11545 +    return 0;
11546 +}
11547 +
11548 +static int http_resp_lookup_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
11549 +    if (t->lookup_offset == t->lookup_c->mem->used - 1) {
11550 +        /* end of chunk, open next chunk */
11551 +
11552 +        if (!t->lookup_c->next) return -1;
11553 +
11554 +        t->lookup_c = t->lookup_c->next;
11555 +        t->lookup_offset = 0;
11556 +    }
11557 +
11558 +    *c = t->lookup_c->mem->ptr[t->lookup_offset++];
11559 +
11560 +    //fprintf(stderr, "%s.%d: lookup: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->lookup_offset - 1);
11561 +
11562 +
11563 +    return 0;
11564 +}
11565 +
11566 +
11567 +static int http_resp_tokenizer(
11568 +    http_resp_tokenizer_t *t,
11569 +    int *token_id,
11570 +    buffer *token
11571 +) {
11572 +    unsigned char c;
11573 +    int tid = 0;
11574 +
11575 +    /* push the token to the parser */
11576 +
11577 +    while (tid == 0 && 0 == http_resp_get_next_char(t, &c)) {
11578 +        switch (c) {
11579 +        case ':':
11580 +            tid = TK_COLON;
11581 +
11582 +            t->is_key = 0;
11583 +
11584 +            break;
11585 +        case ' ':
11586 +        case '\t':
11587 +            /* ignore WS */
11588 +
11589 +            break;
11590 +        case '\r':
11591 +            if (0 != http_resp_lookup_next_char(t, &c)) return -1;
11592 +
11593 +            if (c == '\n') {
11594 +                tid = TK_CRLF;
11595 +
11596 +                t->c = t->lookup_c;
11597 +                t->offset = t->lookup_offset;
11598 +
11599 +                t->is_statusline = 0;
11600 +                t->is_key = 1;
11601 +            } else {
11602 +                fprintf(stderr, "%s.%d: CR with out LF\r\n", __FILE__, __LINE__);
11603 +                return -1;
11604 +            }
11605 +            break;
11606 +        case '\n':
11607 +            tid = TK_CRLF;
11608 +
11609 +            t->is_statusline = 0;
11610 +            t->is_key = 1;
11611 +
11612 +            break;
11613 +        default:
11614 +            while (c >= 32 && c != 127 && c != 255) {
11615 +                if (t->is_statusline) {
11616 +                       if (c == ':') {t->is_statusline = 0; break; } /* this is not a status line by a real header */
11617 +                    if (c == 32) break; /* the space is a splitter in the statusline */
11618 +                } else {
11619 +                    if (t->is_key) {
11620 +                        if (c == ':') break; /* the : is the splitter between key and value */
11621 +                    }
11622 +                }
11623 +                if (0 != http_resp_lookup_next_char(t, &c)) return -1;
11624 +            }
11625 +
11626 +            if (t->c == t->lookup_c &&
11627 +                t->offset == t->lookup_offset + 1) {
11628 +
11629 +                fprintf(stderr, "%s.%d: invalid char in string\n", __FILE__, __LINE__);
11630 +                return -1;
11631 +            }
11632 +
11633 +            tid = TK_STRING;
11634 +
11635 +            /* the lookup points to the first invalid char */
11636 +            t->lookup_offset--;
11637 +
11638 +            /* no overlapping string */
11639 +            if (t->c == t->lookup_c) {
11640 +                buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->lookup_offset - t->offset + 1);
11641 +            } else {
11642 +                /* first chunk */
11643 +                buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->c->mem->used - t->offset);
11644 +
11645 +                /* chunks in the middle */
11646 +                for (t->c = t->c->next; t->c != t->lookup_c; t->c = t->c->next) {
11647 +                    buffer_append_string_buffer(token, t->c->mem);
11648 +                    t->offset = t->c->mem->used - 1;
11649 +                }
11650 +
11651 +                /* last chunk */
11652 +                buffer_append_string_len(token, t->c->mem->ptr, t->lookup_offset);
11653 +            }
11654 +
11655 +            t->offset = t->lookup_offset;
11656 +
11657 +            break;
11658 +        }
11659 +       }
11660 +
11661 +    if (tid) {
11662 +               *token_id = tid;
11663 +
11664 +        return 1;
11665 +    }
11666 +
11667 +    return -1;
11668 +}
11669 +
11670 +parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *resp) {
11671 +    http_resp_tokenizer_t t;
11672 +       void *pParser = NULL;
11673 +       int token_id = 0;
11674 +       buffer *token = NULL;
11675 +       http_resp_ctx_t context;
11676 +    parse_status_t ret = PARSE_UNSET;
11677 +    int last_token_id = 0;
11678 +
11679 +       t.cq = cq;
11680 +    t.c = cq->first;
11681 +    t.offset = t.c->offset;
11682 +    t.is_key = 0;
11683 +    t.is_statusline = 1;
11684 +
11685 +       context.ok = 1;
11686 +    context.errmsg = buffer_init();
11687 +    context.resp = resp;
11688 +
11689 +       pParser = http_resp_parserAlloc( malloc );
11690 +       token = buffer_init();
11691 +    /* http_resp_parserTrace(stderr, "http-response: "); */
11692 +
11693 +       while((1 == http_resp_tokenizer(&t, &token_id, token)) && context.ok) {
11694 +               http_resp_parser(pParser, token_id, token, &context);
11695 +
11696 +               token = buffer_init();
11697 +
11698 +        if (last_token_id == TK_CRLF &&
11699 +            token_id == TK_CRLF) break;
11700 +
11701 +        last_token_id = token_id;
11702 +       }
11703 +
11704 +    /* oops, the parser failed */
11705 +    if (context.ok == 0) {
11706 +        ret = PARSE_ERROR;
11707 +
11708 +        fprintf(stderr, "%s.%d: parsing failed at: ...%20s\r\n",
11709 +            __FILE__, __LINE__, t.c->mem->ptr + t.offset);
11710 +    }
11711 +
11712 +       http_resp_parser(pParser, 0, token, &context);
11713 +       http_resp_parserFree(pParser, free );
11714 +
11715 +    if (context.ok == 0) {
11716 +        /* we are missing the some tokens */
11717 +
11718 +        if (ret == PARSE_UNSET) ret = PARSE_NEED_MORE;
11719 +    } else {
11720 +        chunk *c;
11721 +
11722 +        for (c = cq->first; c != t.c; c = c->next) {
11723 +            c->offset = c->mem->used - 1;
11724 +        }
11725 +
11726 +        c->offset = t.offset;
11727 +
11728 +        ret = PARSE_SUCCESS;
11729 +    }
11730 +
11731 +    buffer_free(token);
11732 +
11733 +    return ret;
11734 +}
11735 +
11736 --- lighttpd-1.4.11/src/http_resp.h     1970-01-01 03:00:00.000000000 +0300
11737 +++ lighttpd-1.4.12/src/http_resp.h     2006-07-11 22:07:53.000000000 +0300
11738 @@ -0,0 +1,34 @@
11739 +#ifndef _HTTP_RESP_H_
11740 +#define _HTTP_RESP_H_
11741 +
11742 +#include "array.h"
11743 +#include "chunk.h"
11744 +
11745 +typedef enum {
11746 +    PARSE_UNSET,
11747 +    PARSE_SUCCESS,
11748 +    PARSE_ERROR,
11749 +    PARSE_NEED_MORE
11750 +} parse_status_t;
11751 +
11752 +typedef struct {
11753 +    int protocol;   /* http/1.0, http/1.1 */
11754 +    int status;     /* e.g. 200 */
11755 +    buffer *reason; /* e.g. Ok */
11756 +    array *headers;
11757 +} http_resp;
11758 +
11759 +typedef struct {
11760 +       int     ok;
11761 +    buffer *errmsg;
11762 +
11763 +    http_resp *resp;
11764 +} http_resp_ctx_t;
11765 +
11766 +http_resp *http_response_init(void);
11767 +void http_response_free(http_resp *resp);
11768 +void http_response_reset(http_resp *resp);
11769 +
11770 +parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *http_response);
11771 +
11772 +#endif
11773 --- lighttpd-1.4.11/src/http_resp_parser.c      1970-01-01 03:00:00.000000000 +0300
11774 +++ lighttpd-1.4.12/src/http_resp_parser.c      2006-07-11 22:08:02.000000000 +0300
11775 @@ -0,0 +1,894 @@
11776 +/* Driver template for the LEMON parser generator.
11777 +** The author disclaims copyright to this source code.
11778 +*/
11779 +/* First off, code is include which follows the "include" declaration
11780 +** in the input file. */
11781 +#include <stdio.h>
11782 +#line 6 "./http_resp_parser.y"
11783 +
11784 +#include <assert.h>
11785 +#include <string.h>
11786 +#include "http_resp.h"
11787 +#include "keyvalue.h"
11788 +#include "array.h"
11789 +
11790 +#line 16 "http_resp_parser.c"
11791 +/* Next is all token values, in a form suitable for use by makeheaders.
11792 +** This section will be null unless lemon is run with the -m switch.
11793 +*/
11794 +/*
11795 +** These constants (all generated automatically by the parser generator)
11796 +** specify the various kinds of tokens (terminals) that the parser
11797 +** understands.
11798 +**
11799 +** Each symbol here is a terminal symbol in the grammar.
11800 +*/
11801 +/* Make sure the INTERFACE macro is defined.
11802 +*/
11803 +#ifndef INTERFACE
11804 +# define INTERFACE 1
11805 +#endif
11806 +/* The next thing included is series of defines which control
11807 +** various aspects of the generated parser.
11808 +**    YYCODETYPE         is the data type used for storing terminal
11809 +**                       and nonterminal numbers.  "unsigned char" is
11810 +**                       used if there are fewer than 250 terminals
11811 +**                       and nonterminals.  "int" is used otherwise.
11812 +**    YYNOCODE           is a number of type YYCODETYPE which corresponds
11813 +**                       to no legal terminal or nonterminal number.  This
11814 +**                       number is used to fill in empty slots of the hash
11815 +**                       table.
11816 +**    YYFALLBACK         If defined, this indicates that one or more tokens
11817 +**                       have fall-back values which should be used if the
11818 +**                       original value of the token will not parse.
11819 +**    YYACTIONTYPE       is the data type used for storing terminal
11820 +**                       and nonterminal numbers.  "unsigned char" is
11821 +**                       used if there are fewer than 250 rules and
11822 +**                       states combined.  "int" is used otherwise.
11823 +**    http_resp_parserTOKENTYPE     is the data type used for minor tokens given
11824 +**                       directly to the parser from the tokenizer.
11825 +**    YYMINORTYPE        is the data type used for all minor tokens.
11826 +**                       This is typically a union of many types, one of
11827 +**                       which is http_resp_parserTOKENTYPE.  The entry in the union
11828 +**                       for base tokens is called "yy0".
11829 +**    YYSTACKDEPTH       is the maximum depth of the parser's stack.
11830 +**    http_resp_parserARG_SDECL     A static variable declaration for the %extra_argument
11831 +**    http_resp_parserARG_PDECL     A parameter declaration for the %extra_argument
11832 +**    http_resp_parserARG_STORE     Code to store %extra_argument into yypParser
11833 +**    http_resp_parserARG_FETCH     Code to extract %extra_argument from yypParser
11834 +**    YYNSTATE           the combined number of states.
11835 +**    YYNRULE            the number of rules in the grammar
11836 +**    YYERRORSYMBOL      is the code number of the error symbol.  If not
11837 +**                       defined, then do no error processing.
11838 +*/
11839 +/* \ 1 */
11840 +#define YYCODETYPE unsigned char
11841 +#define YYNOCODE 12
11842 +#define YYACTIONTYPE unsigned char
11843 +#define http_resp_parserTOKENTYPE buffer *
11844 +typedef union {
11845 +  http_resp_parserTOKENTYPE yy0;
11846 +  http_resp * yy2;
11847 +  data_string * yy9;
11848 +  array * yy12;
11849 +  int yy20;
11850 +  int yy23;
11851 +} YYMINORTYPE;
11852 +#define YYSTACKDEPTH 100
11853 +#define http_resp_parserARG_SDECL http_resp_ctx_t *ctx;
11854 +#define http_resp_parserARG_PDECL ,http_resp_ctx_t *ctx
11855 +#define http_resp_parserARG_FETCH http_resp_ctx_t *ctx = yypParser->ctx
11856 +#define http_resp_parserARG_STORE yypParser->ctx = ctx
11857 +#define YYNSTATE 19
11858 +#define YYNRULE 9
11859 +#define YYERRORSYMBOL 4
11860 +#define YYERRSYMDT yy23
11861 +#define YY_NO_ACTION      (YYNSTATE+YYNRULE+2)
11862 +#define YY_ACCEPT_ACTION  (YYNSTATE+YYNRULE+1)
11863 +#define YY_ERROR_ACTION   (YYNSTATE+YYNRULE)
11864 +
11865 +/* Next are that tables used to determine what action to take based on the
11866 +** current state and lookahead token.  These tables are used to implement
11867 +** functions that take a state number and lookahead value and return an
11868 +** action integer.
11869 +**
11870 +** Suppose the action integer is N.  Then the action is determined as
11871 +** follows
11872 +**
11873 +**   0 <= N < YYNSTATE                  Shift N.  That is, push the lookahead
11874 +**                                      token onto the stack and goto state N.
11875 +**
11876 +**   YYNSTATE <= N < YYNSTATE+YYNRULE   Reduce by rule N-YYNSTATE.
11877 +**
11878 +**   N == YYNSTATE+YYNRULE              A syntax error has occurred.
11879 +**
11880 +**   N == YYNSTATE+YYNRULE+1            The parser accepts its input.
11881 +**
11882 +**   N == YYNSTATE+YYNRULE+2            No such action.  Denotes unused
11883 +**                                      slots in the yy_action[] table.
11884 +**
11885 +** The action table is constructed as a single large table named yy_action[].
11886 +** Given state S and lookahead X, the action is computed as
11887 +**
11888 +**      yy_action[ yy_shift_ofst[S] + X ]
11889 +**
11890 +** If the index value yy_shift_ofst[S]+X is out of range or if the value
11891 +** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
11892 +** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
11893 +** and that yy_default[S] should be used instead.
11894 +**
11895 +** The formula above is for computing the action when the lookahead is
11896 +** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
11897 +** a reduce action) then the yy_reduce_ofst[] array is used in place of
11898 +** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
11899 +** YY_SHIFT_USE_DFLT.
11900 +**
11901 +** The following are the tables generated in this section:
11902 +**
11903 +**  yy_action[]        A single table containing all actions.
11904 +**  yy_lookahead[]     A table containing the lookahead for each entry in
11905 +**                     yy_action.  Used to detect hash collisions.
11906 +**  yy_shift_ofst[]    For each state, the offset into yy_action for
11907 +**                     shifting terminals.
11908 +**  yy_reduce_ofst[]   For each state, the offset into yy_action for
11909 +**                     shifting non-terminals after a reduce.
11910 +**  yy_default[]       Default action for each state.
11911 +*/
11912 +static YYACTIONTYPE yy_action[] = {
11913 + /*     0 */     8,   29,   18,    1,   14,    2,    4,   11,   15,   12,
11914 + /*    10 */    14,   13,    4,   21,    5,   19,    3,    5,    6,    7,
11915 + /*    20 */     9,   17,   16,    4,   20,   22,   22,   10,
11916 +};
11917 +static YYCODETYPE yy_lookahead[] = {
11918 + /*     0 */     5,    6,    2,    8,    9,    1,    2,    1,    2,    8,
11919 + /*    10 */     9,    1,    2,    2,    3,    0,    9,    3,    2,    1,
11920 + /*    20 */     7,    2,    2,    2,    0,    2,   11,   10,
11921 +};
11922 +#define YY_SHIFT_USE_DFLT (-1)
11923 +static signed char yy_shift_ofst[] = {
11924 + /*     0 */     0,    4,   15,   -1,   14,   16,   18,   -1,   19,   20,
11925 + /*    10 */     6,   21,   10,   24,   -1,   -1,   -1,   23,   11,
11926 +};
11927 +#define YY_REDUCE_USE_DFLT (-6)
11928 +static signed char yy_reduce_ofst[] = {
11929 + /*     0 */    -5,    7,   -6,   -6,   -6,   -6,   -6,   -6,   13,   17,
11930 + /*    10 */    -6,    1,    7,   -6,   -6,   -6,   -6,   -6,   -6,
11931 +};
11932 +static YYACTIONTYPE yy_default[] = {
11933 + /*     0 */    28,   28,   28,   25,   28,   28,   28,   27,   28,   28,
11934 + /*    10 */    28,   28,   28,   28,   26,   24,   23,   28,   28,
11935 +};
11936 +#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
11937 +
11938 +/* The next table maps tokens into fallback tokens.  If a construct
11939 +** like the following:
11940 +**
11941 +**      %fallback ID X Y Z.
11942 +**
11943 +** appears in the grammer, then ID becomes a fallback token for X, Y,
11944 +** and Z.  Whenever one of the tokens X, Y, or Z is input to the parser
11945 +** but it does not parse, the type of the token is changed to ID and
11946 +** the parse is retried before an error is thrown.
11947 +*/
11948 +#ifdef YYFALLBACK
11949 +static const YYCODETYPE yyFallback[] = {
11950 +};
11951 +#endif /* YYFALLBACK */
11952 +
11953 +/* The following structure represents a single element of the
11954 +** parser's stack.  Information stored includes:
11955 +**
11956 +**   +  The state number for the parser at this level of the stack.
11957 +**
11958 +**   +  The value of the token stored at this level of the stack.
11959 +**      (In other words, the "major" token.)
11960 +**
11961 +**   +  The semantic value stored at this level of the stack.  This is
11962 +**      the information used by the action routines in the grammar.
11963 +**      It is sometimes called the "minor" token.
11964 +*/
11965 +struct yyStackEntry {
11966 +  int stateno;       /* The state-number */
11967 +  int major;         /* The major token value.  This is the code
11968 +                     ** number for the token at this stack level */
11969 +  YYMINORTYPE minor; /* The user-supplied minor token value.  This
11970 +                     ** is the value of the token  */
11971 +};
11972 +typedef struct yyStackEntry yyStackEntry;
11973 +
11974 +/* The state of the parser is completely contained in an instance of
11975 +** the following structure */
11976 +struct yyParser {
11977 +  int yyidx;                    /* Index of top element in stack */
11978 +  int yyerrcnt;                 /* Shifts left before out of the error */
11979 +  http_resp_parserARG_SDECL                /* A place to hold %extra_argument */
11980 +  yyStackEntry yystack[YYSTACKDEPTH];  /* The parser's stack */
11981 +};
11982 +typedef struct yyParser yyParser;
11983 +
11984 +#ifndef NDEBUG
11985 +#include <stdio.h>
11986 +static FILE *yyTraceFILE = 0;
11987 +static char *yyTracePrompt = 0;
11988 +#endif /* NDEBUG */
11989 +
11990 +#ifndef NDEBUG
11991 +/*
11992 +** Turn parser tracing on by giving a stream to which to write the trace
11993 +** and a prompt to preface each trace message.  Tracing is turned off
11994 +** by making either argument NULL
11995 +**
11996 +** Inputs:
11997 +** <ul>
11998 +** <li> A FILE* to which trace output should be written.
11999 +**      If NULL, then tracing is turned off.
12000 +** <li> A prefix string written at the beginning of every
12001 +**      line of trace output.  If NULL, then tracing is
12002 +**      turned off.
12003 +** </ul>
12004 +**
12005 +** Outputs:
12006 +** None.
12007 +*/
12008 +void http_resp_parserTrace(FILE *TraceFILE, char *zTracePrompt){
12009 +  yyTraceFILE = TraceFILE;
12010 +  yyTracePrompt = zTracePrompt;
12011 +  if( yyTraceFILE==0 ) yyTracePrompt = 0;
12012 +  else if( yyTracePrompt==0 ) yyTraceFILE = 0;
12013 +}
12014 +#endif /* NDEBUG */
12015 +
12016 +#ifndef NDEBUG
12017 +/* For tracing shifts, the names of all terminals and nonterminals
12018 +** are required.  The following table supplies these names */
12019 +static const char *yyTokenName[] = {
12020 +  "$",             "CRLF",          "STRING",        "COLON",       
12021 +  "error",         "protocol",      "response_hdr",  "number",      
12022 +  "headers",       "header",        "reason",      
12023 +};
12024 +#endif /* NDEBUG */
12025 +
12026 +#ifndef NDEBUG
12027 +/* For tracing reduce actions, the names of all rules are required.
12028 +*/
12029 +static const char *yyRuleName[] = {
12030 + /*   0 */ "response_hdr ::= headers CRLF",
12031 + /*   1 */ "response_hdr ::= protocol number reason CRLF headers CRLF",
12032 + /*   2 */ "protocol ::= STRING",
12033 + /*   3 */ "number ::= STRING",
12034 + /*   4 */ "reason ::= STRING",
12035 + /*   5 */ "reason ::= reason STRING",
12036 + /*   6 */ "headers ::= headers header",
12037 + /*   7 */ "headers ::= header",
12038 + /*   8 */ "header ::= STRING COLON STRING CRLF",
12039 +};
12040 +#endif /* NDEBUG */
12041 +
12042 +/*
12043 +** This function returns the symbolic name associated with a token
12044 +** value.
12045 +*/
12046 +const char *http_resp_parserTokenName(int tokenType){
12047 +#ifndef NDEBUG
12048 +  if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){
12049 +    return yyTokenName[tokenType];
12050 +  }else{
12051 +    return "Unknown";
12052 +  }
12053 +#else
12054 +  return "";
12055 +#endif
12056 +}
12057 +
12058 +/*
12059 +** This function allocates a new parser.
12060 +** The only argument is a pointer to a function which works like
12061 +** malloc.
12062 +**
12063 +** Inputs:
12064 +** A pointer to the function used to allocate memory.
12065 +**
12066 +** Outputs:
12067 +** A pointer to a parser.  This pointer is used in subsequent calls
12068 +** to http_resp_parser and http_resp_parserFree.
12069 +*/
12070 +void *http_resp_parserAlloc(void *(*mallocProc)(size_t)){
12071 +  yyParser *pParser;
12072 +  pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
12073 +  if( pParser ){
12074 +    pParser->yyidx = -1;
12075 +  }
12076 +  return pParser;
12077 +}
12078 +
12079 +/* The following function deletes the value associated with a
12080 +** symbol.  The symbol can be either a terminal or nonterminal.
12081 +** "yymajor" is the symbol code, and "yypminor" is a pointer to
12082 +** the value.
12083 +*/
12084 +static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){
12085 +  switch( yymajor ){
12086 +    /* Here is inserted the actions which take place when a
12087 +    ** terminal or non-terminal is destroyed.  This can happen
12088 +    ** when the symbol is popped from the stack during a
12089 +    ** reduce or during error processing or when a parser is
12090 +    ** being destroyed before it is finished parsing.
12091 +    **
12092 +    ** Note: during a reduce, the only symbols destroyed are those
12093 +    ** which appear on the RHS of the rule, but which are not used
12094 +    ** inside the C code.
12095 +    */
12096 +    case 1:
12097 +    case 2:
12098 +    case 3:
12099 +#line 23 "./http_resp_parser.y"
12100 +{ buffer_free((yypminor->yy0)); }
12101 +#line 326 "http_resp_parser.c"
12102 +      break;
12103 +    default:  break;   /* If no destructor action specified: do nothing */
12104 +  }
12105 +}
12106 +
12107 +/*
12108 +** Pop the parser's stack once.
12109 +**
12110 +** If there is a destructor routine associated with the token which
12111 +** is popped from the stack, then call it.
12112 +**
12113 +** Return the major token number for the symbol popped.
12114 +*/
12115 +static int yy_pop_parser_stack(yyParser *pParser){
12116 +  YYCODETYPE yymajor;
12117 +  yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
12118 +
12119 +  if( pParser->yyidx<0 ) return 0;
12120 +#ifndef NDEBUG
12121 +  if( yyTraceFILE && pParser->yyidx>=0 ){
12122 +    fprintf(yyTraceFILE,"%sPopping %s\n",
12123 +      yyTracePrompt,
12124 +      yyTokenName[yytos->major]);
12125 +  }
12126 +#endif
12127 +  yymajor = yytos->major;
12128 +  yy_destructor( yymajor, &yytos->minor);
12129 +  pParser->yyidx--;
12130 +  return yymajor;
12131 +}
12132 +
12133 +/*
12134 +** Deallocate and destroy a parser.  Destructors are all called for
12135 +** all stack elements before shutting the parser down.
12136 +**
12137 +** Inputs:
12138 +** <ul>
12139 +** <li>  A pointer to the parser.  This should be a pointer
12140 +**       obtained from http_resp_parserAlloc.
12141 +** <li>  A pointer to a function used to reclaim memory obtained
12142 +**       from malloc.
12143 +** </ul>
12144 +*/
12145 +void http_resp_parserFree(
12146 +  void *p,                    /* The parser to be deleted */
12147 +  void (*freeProc)(void*)     /* Function used to reclaim memory */
12148 +){
12149 +  yyParser *pParser = (yyParser*)p;
12150 +  if( pParser==0 ) return;
12151 +  while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
12152 +  (*freeProc)((void*)pParser);
12153 +}
12154 +
12155 +/*
12156 +** Find the appropriate action for a parser given the terminal
12157 +** look-ahead token iLookAhead.
12158 +**
12159 +** If the look-ahead token is YYNOCODE, then check to see if the action is
12160 +** independent of the look-ahead.  If it is, return the action, otherwise
12161 +** return YY_NO_ACTION.
12162 +*/
12163 +static int yy_find_shift_action(
12164 +  yyParser *pParser,        /* The parser */
12165 +  int iLookAhead            /* The look-ahead token */
12166 +){
12167 +  int i;
12168 +  int stateno = pParser->yystack[pParser->yyidx].stateno;
12169 +
12170 +  /* if( pParser->yyidx<0 ) return YY_NO_ACTION;  */
12171 +  i = yy_shift_ofst[stateno];
12172 +  if( i==YY_SHIFT_USE_DFLT ){
12173 +    return yy_default[stateno];
12174 +  }
12175 +  if( iLookAhead==YYNOCODE ){
12176 +    return YY_NO_ACTION;
12177 +  }
12178 +  i += iLookAhead;
12179 +  if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
12180 +#ifdef YYFALLBACK
12181 +    int iFallback;            /* Fallback token */
12182 +    if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
12183 +           && (iFallback = yyFallback[iLookAhead])!=0 ){
12184 +#ifndef NDEBUG
12185 +      if( yyTraceFILE ){
12186 +        fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
12187 +           yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
12188 +      }
12189 +#endif
12190 +      return yy_find_shift_action(pParser, iFallback);
12191 +    }
12192 +#endif
12193 +    return yy_default[stateno];
12194 +  }else{
12195 +    return yy_action[i];
12196 +  }
12197 +}
12198 +
12199 +/*
12200 +** Find the appropriate action for a parser given the non-terminal
12201 +** look-ahead token iLookAhead.
12202 +**
12203 +** If the look-ahead token is YYNOCODE, then check to see if the action is
12204 +** independent of the look-ahead.  If it is, return the action, otherwise
12205 +** return YY_NO_ACTION.
12206 +*/
12207 +static int yy_find_reduce_action(
12208 +  yyParser *pParser,        /* The parser */
12209 +  int iLookAhead            /* The look-ahead token */
12210 +){
12211 +  int i;
12212 +  int stateno = pParser->yystack[pParser->yyidx].stateno;
12213 +
12214 +  i = yy_reduce_ofst[stateno];
12215 +  if( i==YY_REDUCE_USE_DFLT ){
12216 +    return yy_default[stateno];
12217 +  }
12218 +  if( iLookAhead==YYNOCODE ){
12219 +    return YY_NO_ACTION;
12220 +  }
12221 +  i += iLookAhead;
12222 +  if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
12223 +    return yy_default[stateno];
12224 +  }else{
12225 +    return yy_action[i];
12226 +  }
12227 +}
12228 +
12229 +/*
12230 +** Perform a shift action.
12231 +*/
12232 +static void yy_shift(
12233 +  yyParser *yypParser,          /* The parser to be shifted */
12234 +  int yyNewState,               /* The new state to shift in */
12235 +  int yyMajor,                  /* The major token to shift in */
12236 +  YYMINORTYPE *yypMinor         /* Pointer ot the minor token to shift in */
12237 +){
12238 +  yyStackEntry *yytos;
12239 +  yypParser->yyidx++;
12240 +  if( yypParser->yyidx>=YYSTACKDEPTH ){
12241 +     http_resp_parserARG_FETCH;
12242 +     yypParser->yyidx--;
12243 +#ifndef NDEBUG
12244 +     if( yyTraceFILE ){
12245 +       fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
12246 +     }
12247 +#endif
12248 +     while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
12249 +     /* Here code is inserted which will execute if the parser
12250 +     ** stack every overflows */
12251 +     http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument var */
12252 +     return;
12253 +  }
12254 +  yytos = &yypParser->yystack[yypParser->yyidx];
12255 +  yytos->stateno = yyNewState;
12256 +  yytos->major = yyMajor;
12257 +  yytos->minor = *yypMinor;
12258 +#ifndef NDEBUG
12259 +  if( yyTraceFILE && yypParser->yyidx>0 ){
12260 +    int i;
12261 +    fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
12262 +    fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
12263 +    for(i=1; i<=yypParser->yyidx; i++)
12264 +      fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
12265 +    fprintf(yyTraceFILE,"\n");
12266 +  }
12267 +#endif
12268 +}
12269 +
12270 +/* The following table contains information about every rule that
12271 +** is used during the reduce.
12272 +*/
12273 +static struct {
12274 +  YYCODETYPE lhs;         /* Symbol on the left-hand side of the rule */
12275 +  unsigned char nrhs;     /* Number of right-hand side symbols in the rule */
12276 +} yyRuleInfo[] = {
12277 +  { 6, 2 },
12278 +  { 6, 6 },
12279 +  { 5, 1 },
12280 +  { 7, 1 },
12281 +  { 10, 1 },
12282 +  { 10, 2 },
12283 +  { 8, 2 },
12284 +  { 8, 1 },
12285 +  { 9, 4 },
12286 +};
12287 +
12288 +static void yy_accept(yyParser*);  /* Forward Declaration */
12289 +
12290 +/*
12291 +** Perform a reduce action and the shift that must immediately
12292 +** follow the reduce.
12293 +*/
12294 +static void yy_reduce(
12295 +  yyParser *yypParser,         /* The parser */
12296 +  int yyruleno                 /* Number of the rule by which to reduce */
12297 +){
12298 +  int yygoto;                     /* The next state */
12299 +  int yyact;                      /* The next action */
12300 +  YYMINORTYPE yygotominor;        /* The LHS of the rule reduced */
12301 +  yyStackEntry *yymsp;            /* The top of the parser's stack */
12302 +  int yysize;                     /* Amount to pop the stack */
12303 +  http_resp_parserARG_FETCH;
12304 +  yymsp = &yypParser->yystack[yypParser->yyidx];
12305 +#ifndef NDEBUG
12306 +  if( yyTraceFILE && yyruleno>=0
12307 +        && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
12308 +    fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
12309 +      yyRuleName[yyruleno]);
12310 +  }
12311 +#endif /* NDEBUG */
12312 +
12313 +  switch( yyruleno ){
12314 +  /* Beginning here are the reduction cases.  A typical example
12315 +  ** follows:
12316 +  **   case 0:
12317 +  **  #line <lineno> <grammarfile>
12318 +  **     { ... }           // User supplied code
12319 +  **  #line <lineno> <thisfile>
12320 +  **     break;
12321 +  */
12322 +      case 0:
12323 +#line 26 "./http_resp_parser.y"
12324 +{
12325 +    http_resp *resp = ctx->resp;
12326 +    data_string *ds;
12327
12328 +    resp->protocol = HTTP_VERSION_UNSET;
12329 +
12330 +    buffer_copy_string(resp->reason, ""); /* no reason */
12331 +    array_free(resp->headers);
12332 +    resp->headers = yymsp[-1].minor.yy12;
12333 +
12334 +    if (NULL == (ds = (data_string *)array_get_element(yymsp[-1].minor.yy12, "Status"))) { 
12335 +        resp->status = 0;
12336 +    } else {
12337 +        char *err;
12338 +        resp->status = strtol(ds->value->ptr, &err, 10);
12339 +    
12340 +        if (*err != '\0') {
12341 +            buffer_copy_string(ctx->errmsg, "expected a number: ");
12342 +            buffer_append_string_buffer(ctx->errmsg, ds->value);
12343 +        
12344 +            ctx->ok = 0;
12345 +        }
12346 +
12347 +    }
12348 +
12349 +    yymsp[-1].minor.yy12 = NULL;
12350 +}
12351 +#line 576 "http_resp_parser.c"
12352 +  yy_destructor(1,&yymsp[0].minor);
12353 +        break;
12354 +      case 1:
12355 +#line 54 "./http_resp_parser.y"
12356 +{
12357 +    http_resp *resp = ctx->resp;
12358 +    
12359 +    resp->status = yymsp[-4].minor.yy20;
12360 +    resp->protocol = yymsp[-5].minor.yy20;
12361 +    buffer_copy_string_buffer(resp->reason, yymsp[-3].minor.yy0);
12362 +    
12363 +    array_free(resp->headers);
12364 +    
12365 +    resp->headers = yymsp[-1].minor.yy12;
12366 +    
12367 +    yymsp[-1].minor.yy12 = NULL;
12368 +}
12369 +#line 594 "http_resp_parser.c"
12370 +  yy_destructor(1,&yymsp[-2].minor);
12371 +  yy_destructor(1,&yymsp[0].minor);
12372 +        break;
12373 +      case 2:
12374 +#line 68 "./http_resp_parser.y"
12375 +{
12376 +    if (buffer_is_equal_string(yymsp[0].minor.yy0, CONST_STR_LEN("HTTP/1.0"))) {
12377 +        yygotominor.yy20 = HTTP_VERSION_1_0;
12378 +    } else if (buffer_is_equal_string(yymsp[0].minor.yy0, CONST_STR_LEN("HTTP/1.1"))) {
12379 +        yygotominor.yy20 = HTTP_VERSION_1_1;
12380 +    } else {
12381 +        buffer_copy_string(ctx->errmsg, "unknown protocol: ");
12382 +        buffer_append_string_buffer(ctx->errmsg, yymsp[0].minor.yy0);
12383 +        
12384 +        ctx->ok = 0;
12385 +    }
12386 +}
12387 +#line 612 "http_resp_parser.c"
12388 +        break;
12389 +      case 3:
12390 +#line 81 "./http_resp_parser.y"
12391 +{
12392 +    char *err;
12393 +    yygotominor.yy20 = strtol(yymsp[0].minor.yy0->ptr, &err, 10);
12394 +    
12395 +    if (*err != '\0') {
12396 +        buffer_copy_string(ctx->errmsg, "expected a number: ");
12397 +        buffer_append_string_buffer(ctx->errmsg, yymsp[0].minor.yy0);
12398 +        
12399 +        ctx->ok = 0;
12400 +    }
12401 +}
12402 +#line 627 "http_resp_parser.c"
12403 +        break;
12404 +      case 4:
12405 +#line 93 "./http_resp_parser.y"
12406 +{
12407 +    buffer_copy_string_buffer(yygotominor.yy0, yymsp[0].minor.yy0);
12408 +}
12409 +#line 634 "http_resp_parser.c"
12410 +        break;
12411 +      case 5:
12412 +#line 97 "./http_resp_parser.y"
12413 +{
12414 +    yygotominor.yy0 = yymsp[-1].minor.yy0;
12415 +    
12416 +    buffer_append_string(yygotominor.yy0, " ");
12417 +    buffer_append_string_buffer(yygotominor.yy0, yymsp[0].minor.yy0);
12418 +    
12419 +    yymsp[-1].minor.yy0 = NULL;
12420 +}
12421 +#line 646 "http_resp_parser.c"
12422 +        break;
12423 +      case 6:
12424 +#line 106 "./http_resp_parser.y"
12425 +{
12426 +    yygotominor.yy12 = yymsp[-1].minor.yy12;
12427 +    
12428 +    array_insert_unique(yygotominor.yy12, (data_unset *)yymsp[0].minor.yy9);
12429 +    
12430 +    yymsp[-1].minor.yy12 = NULL;
12431 +}
12432 +#line 657 "http_resp_parser.c"
12433 +        break;
12434 +      case 7:
12435 +#line 114 "./http_resp_parser.y"
12436 +{
12437 +    yygotominor.yy12 = array_init();
12438 +
12439 +    array_insert_unique(yygotominor.yy12, (data_unset *)yymsp[0].minor.yy9);
12440 +}
12441 +#line 666 "http_resp_parser.c"
12442 +        break;
12443 +      case 8:
12444 +#line 119 "./http_resp_parser.y"
12445 +{
12446 +    yygotominor.yy9 = data_string_init();
12447 +    
12448 +    buffer_copy_string_buffer(yygotominor.yy9->key, yymsp[-3].minor.yy0);
12449 +    buffer_copy_string_buffer(yygotominor.yy9->value, yymsp[-1].minor.yy0);    
12450 +}
12451 +#line 676 "http_resp_parser.c"
12452 +  yy_destructor(3,&yymsp[-2].minor);
12453 +  yy_destructor(1,&yymsp[0].minor);
12454 +        break;
12455 +  };
12456 +  yygoto = yyRuleInfo[yyruleno].lhs;
12457 +  yysize = yyRuleInfo[yyruleno].nrhs;
12458 +  yypParser->yyidx -= yysize;
12459 +  yyact = yy_find_reduce_action(yypParser,yygoto);
12460 +  if( yyact < YYNSTATE ){
12461 +    yy_shift(yypParser,yyact,yygoto,&yygotominor);
12462 +  }else if( yyact == YYNSTATE + YYNRULE + 1 ){
12463 +    yy_accept(yypParser);
12464 +  }
12465 +}
12466 +
12467 +/*
12468 +** The following code executes when the parse fails
12469 +*/
12470 +static void yy_parse_failed(
12471 +  yyParser *yypParser           /* The parser */
12472 +){
12473 +  http_resp_parserARG_FETCH;
12474 +#ifndef NDEBUG
12475 +  if( yyTraceFILE ){
12476 +    fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
12477 +  }
12478 +#endif
12479 +  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
12480 +  /* Here code is inserted which will be executed whenever the
12481 +  ** parser fails */
12482 +#line 14 "./http_resp_parser.y"
12483 +
12484 +  ctx->ok = 0;
12485 +
12486 +#line 711 "http_resp_parser.c"
12487 +  http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12488 +}
12489 +
12490 +/*
12491 +** The following code executes when a syntax error first occurs.
12492 +*/
12493 +static void yy_syntax_error(
12494 +  yyParser *yypParser,           /* The parser */
12495 +  int yymajor,                   /* The major type of the error token */
12496 +  YYMINORTYPE yyminor            /* The minor type of the error token */
12497 +){
12498 +  http_resp_parserARG_FETCH;
12499 +#define TOKEN (yyminor.yy0)
12500 +  http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12501 +}
12502 +
12503 +/*
12504 +** The following is executed when the parser accepts
12505 +*/
12506 +static void yy_accept(
12507 +  yyParser *yypParser           /* The parser */
12508 +){
12509 +  http_resp_parserARG_FETCH;
12510 +#ifndef NDEBUG
12511 +  if( yyTraceFILE ){
12512 +    fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
12513 +  }
12514 +#endif
12515 +  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
12516 +  /* Here code is inserted which will be executed whenever the
12517 +  ** parser accepts */
12518 +  http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12519 +}
12520 +
12521 +/* The main parser program.
12522 +** The first argument is a pointer to a structure obtained from
12523 +** "http_resp_parserAlloc" which describes the current state of the parser.
12524 +** The second argument is the major token number.  The third is
12525 +** the minor token.  The fourth optional argument is whatever the
12526 +** user wants (and specified in the grammar) and is available for
12527 +** use by the action routines.
12528 +**
12529 +** Inputs:
12530 +** <ul>
12531 +** <li> A pointer to the parser (an opaque structure.)
12532 +** <li> The major token number.
12533 +** <li> The minor token number.
12534 +** <li> An option argument of a grammar-specified type.
12535 +** </ul>
12536 +**
12537 +** Outputs:
12538 +** None.
12539 +*/
12540 +void http_resp_parser(
12541 +  void *yyp,                   /* The parser */
12542 +  int yymajor,                 /* The major token code number */
12543 +  http_resp_parserTOKENTYPE yyminor       /* The value for the token */
12544 +  http_resp_parserARG_PDECL               /* Optional %extra_argument parameter */
12545 +){
12546 +  YYMINORTYPE yyminorunion;
12547 +  int yyact;            /* The parser action. */
12548 +  int yyendofinput;     /* True if we are at the end of input */
12549 +  int yyerrorhit = 0;   /* True if yymajor has invoked an error */
12550 +  yyParser *yypParser;  /* The parser */
12551 +
12552 +  /* (re)initialize the parser, if necessary */
12553 +  yypParser = (yyParser*)yyp;
12554 +  if( yypParser->yyidx<0 ){
12555 +    if( yymajor==0 ) return;
12556 +    yypParser->yyidx = 0;
12557 +    yypParser->yyerrcnt = -1;
12558 +    yypParser->yystack[0].stateno = 0;
12559 +    yypParser->yystack[0].major = 0;
12560 +  }
12561 +  yyminorunion.yy0 = yyminor;
12562 +  yyendofinput = (yymajor==0);
12563 +  http_resp_parserARG_STORE;
12564 +
12565 +#ifndef NDEBUG
12566 +  if( yyTraceFILE ){
12567 +    fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
12568 +  }
12569 +#endif
12570 +
12571 +  do{
12572 +    yyact = yy_find_shift_action(yypParser,yymajor);
12573 +    if( yyact<YYNSTATE ){
12574 +      yy_shift(yypParser,yyact,yymajor,&yyminorunion);
12575 +      yypParser->yyerrcnt--;
12576 +      if( yyendofinput && yypParser->yyidx>=0 ){
12577 +        yymajor = 0;
12578 +      }else{
12579 +        yymajor = YYNOCODE;
12580 +      }
12581 +    }else if( yyact < YYNSTATE + YYNRULE ){
12582 +      yy_reduce(yypParser,yyact-YYNSTATE);
12583 +    }else if( yyact == YY_ERROR_ACTION ){
12584 +      int yymx;
12585 +#ifndef NDEBUG
12586 +      if( yyTraceFILE ){
12587 +        fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
12588 +      }
12589 +#endif
12590 +#ifdef YYERRORSYMBOL
12591 +      /* A syntax error has occurred.
12592 +      ** The response to an error depends upon whether or not the
12593 +      ** grammar defines an error token "ERROR".
12594 +      **
12595 +      ** This is what we do if the grammar does define ERROR:
12596 +      **
12597 +      **  * Call the %syntax_error function.
12598 +      **
12599 +      **  * Begin popping the stack until we enter a state where
12600 +      **    it is legal to shift the error symbol, then shift
12601 +      **    the error symbol.
12602 +      **
12603 +      **  * Set the error count to three.
12604 +      **
12605 +      **  * Begin accepting and shifting new tokens.  No new error
12606 +      **    processing will occur until three tokens have been
12607 +      **    shifted successfully.
12608 +      **
12609 +      */
12610 +      if( yypParser->yyerrcnt<0 ){
12611 +        yy_syntax_error(yypParser,yymajor,yyminorunion);
12612 +      }
12613 +      yymx = yypParser->yystack[yypParser->yyidx].major;
12614 +      if( yymx==YYERRORSYMBOL || yyerrorhit ){
12615 +#ifndef NDEBUG
12616 +        if( yyTraceFILE ){
12617 +          fprintf(yyTraceFILE,"%sDiscard input token %s\n",
12618 +             yyTracePrompt,yyTokenName[yymajor]);
12619 +        }
12620 +#endif
12621 +        yy_destructor(yymajor,&yyminorunion);
12622 +        yymajor = YYNOCODE;
12623 +      }else{
12624 +         while(
12625 +          yypParser->yyidx >= 0 &&
12626 +          yymx != YYERRORSYMBOL &&
12627 +          (yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE
12628 +        ){
12629 +          yy_pop_parser_stack(yypParser);
12630 +        }
12631 +        if( yypParser->yyidx < 0 || yymajor==0 ){
12632 +          yy_destructor(yymajor,&yyminorunion);
12633 +          yy_parse_failed(yypParser);
12634 +          yymajor = YYNOCODE;
12635 +        }else if( yymx!=YYERRORSYMBOL ){
12636 +          YYMINORTYPE u2;
12637 +          u2.YYERRSYMDT = 0;
12638 +          yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
12639 +        }
12640 +      }
12641 +      yypParser->yyerrcnt = 3;
12642 +      yyerrorhit = 1;
12643 +#else  /* YYERRORSYMBOL is not defined */
12644 +      /* This is what we do if the grammar does not define ERROR:
12645 +      **
12646 +      **  * Report an error message, and throw away the input token.
12647 +      **
12648 +      **  * If the input token is $, then fail the parse.
12649 +      **
12650 +      ** As before, subsequent error messages are suppressed until
12651 +      ** three input tokens have been successfully shifted.
12652 +      */
12653 +      if( yypParser->yyerrcnt<=0 ){
12654 +        yy_syntax_error(yypParser,yymajor,yyminorunion);
12655 +      }
12656 +      yypParser->yyerrcnt = 3;
12657 +      yy_destructor(yymajor,&yyminorunion);
12658 +      if( yyendofinput ){
12659 +        yy_parse_failed(yypParser);
12660 +      }
12661 +      yymajor = YYNOCODE;
12662 +#endif
12663 +    }else{
12664 +      yy_accept(yypParser);
12665 +      yymajor = YYNOCODE;
12666 +    }
12667 +  }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
12668 +  return;
12669 +}
12670 --- lighttpd-1.4.11/src/inet_ntop_cache.c       2005-08-11 01:26:38.000000000 +0300
12671 +++ lighttpd-1.4.12/src/inet_ntop_cache.c       2006-07-11 22:07:52.000000000 +0300
12672 @@ -8,7 +8,7 @@
12673  #include "sys-socket.h"
12674  
12675  const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr) {
12676 -#ifdef HAVE_IPV6       
12677 +#ifdef HAVE_IPV6
12678         size_t ndx = 0, i;
12679         for (i = 0; i < INET_NTOP_CACHE_MAX; i++) {
12680                 if (srv->inet_ntop_cache[i].ts != 0) {
12681 @@ -20,31 +20,31 @@
12682                                    srv->inet_ntop_cache[i].addr.ipv4.s_addr == addr->ipv4.sin_addr.s_addr) {
12683                                 /* IPv4 found in cache */
12684                                 break;
12685 -                               
12686 +
12687                         }
12688                 }
12689         }
12690 -       
12691 +
12692         if (i == INET_NTOP_CACHE_MAX) {
12693                 /* not found in cache */
12694 -               
12695 +
12696                 i = ndx;
12697 -               inet_ntop(addr->plain.sa_family, 
12698 -                         addr->plain.sa_family == AF_INET6 ? 
12699 +               inet_ntop(addr->plain.sa_family,
12700 +                         addr->plain.sa_family == AF_INET6 ?
12701                           (const void *) &(addr->ipv6.sin6_addr) :
12702                           (const void *) &(addr->ipv4.sin_addr),
12703                           srv->inet_ntop_cache[i].b2, INET6_ADDRSTRLEN);
12704 -               
12705 +
12706                 srv->inet_ntop_cache[i].ts = srv->cur_ts;
12707                 srv->inet_ntop_cache[i].family = addr->plain.sa_family;
12708 -               
12709 +
12710                 if (srv->inet_ntop_cache[i].family == AF_INET) {
12711                         srv->inet_ntop_cache[i].addr.ipv4.s_addr = addr->ipv4.sin_addr.s_addr;
12712                 } else if (srv->inet_ntop_cache[i].family == AF_INET6) {
12713                         memcpy(srv->inet_ntop_cache[i].addr.ipv6.s6_addr, addr->ipv6.sin6_addr.s6_addr, 16);
12714                 }
12715         }
12716 -       
12717 +
12718         return srv->inet_ntop_cache[i].b2;
12719  #else
12720         UNUSED(srv);
12721 --- lighttpd-1.4.11/src/joblist.c       2005-08-11 01:26:41.000000000 +0300
12722 +++ lighttpd-1.4.12/src/joblist.c       2006-07-11 22:07:51.000000000 +0300
12723 @@ -7,7 +7,7 @@
12724  
12725  int joblist_append(server *srv, connection *con) {
12726         if (con->in_joblist) return 0;
12727 -       
12728 +
12729         if (srv->joblist->size == 0) {
12730                 srv->joblist->size  = 16;
12731                 srv->joblist->ptr   = malloc(sizeof(*srv->joblist->ptr) * srv->joblist->size);
12732 @@ -15,15 +15,15 @@
12733                 srv->joblist->size += 16;
12734                 srv->joblist->ptr   = realloc(srv->joblist->ptr, sizeof(*srv->joblist->ptr) * srv->joblist->size);
12735         }
12736 -       
12737 +
12738         srv->joblist->ptr[srv->joblist->used++] = con;
12739 -       
12740 +
12741         return 0;
12742  }
12743  
12744  void joblist_free(server *srv, connections *joblist) {
12745         UNUSED(srv);
12746 -               
12747 +
12748         free(joblist->ptr);
12749         free(joblist);
12750  }
12751 @@ -31,14 +31,14 @@
12752  connection *fdwaitqueue_unshift(server *srv, connections *fdwaitqueue) {
12753         connection *con;
12754         UNUSED(srv);
12755 -               
12756 -       
12757 +
12758 +
12759         if (fdwaitqueue->used == 0) return NULL;
12760 -       
12761 +
12762         con = fdwaitqueue->ptr[0];
12763 -       
12764 +
12765         memmove(fdwaitqueue->ptr, &(fdwaitqueue->ptr[1]), --fdwaitqueue->used * sizeof(*(fdwaitqueue->ptr)));
12766 -       
12767 +
12768         return con;
12769  }
12770  
12771 @@ -50,9 +50,9 @@
12772                 srv->fdwaitqueue->size += 16;
12773                 srv->fdwaitqueue->ptr   = realloc(srv->fdwaitqueue->ptr, sizeof(*(srv->fdwaitqueue->ptr)) * srv->fdwaitqueue->size);
12774         }
12775 -       
12776 +
12777         srv->fdwaitqueue->ptr[srv->fdwaitqueue->used++] = con;
12778 -       
12779 +
12780         return 0;
12781  }
12782  
12783 --- lighttpd-1.4.11/src/keyvalue.c      2006-03-02 16:08:06.000000000 +0200
12784 +++ lighttpd-1.4.12/src/keyvalue.c      2006-07-11 22:07:51.000000000 +0300
12785 @@ -87,7 +87,8 @@
12786         { 504, "Gateway Timeout" },
12787         { 505, "HTTP Version Not Supported" },
12788         { 507, "Insufficient Storage" }, /* WebDAV */
12789 -       
12790 +       { 509, "Bandwidth Limit exceeded" },
12791 +
12792         { -1, NULL }
12793  };
12794  
12795 @@ -102,12 +103,12 @@
12796         { 501, "501.html" },
12797         { 503, "503.html" },
12798         { 505, "505.html" },
12799 -       
12800 +
12801         { -1, NULL }
12802  };
12803  
12804  
12805 -const char *keyvalue_get_value(keyvalue *kv, int k) { 
12806 +const char *keyvalue_get_value(keyvalue *kv, int k) {
12807         int i;
12808         for (i = 0; kv[i].value; i++) {
12809                 if (kv[i].key == k) return kv[i].value;
12810 @@ -115,7 +116,7 @@
12811         return NULL;
12812  }
12813  
12814 -int keyvalue_get_key(keyvalue *kv, const char *s) { 
12815 +int keyvalue_get_key(keyvalue *kv, const char *s) {
12816         int i;
12817         for (i = 0; kv[i].value; i++) {
12818                 if (0 == strcmp(kv[i].value, s)) return kv[i].key;
12819 @@ -125,9 +126,9 @@
12820  
12821  keyvalue_buffer *keyvalue_buffer_init(void) {
12822         keyvalue_buffer *kvb;
12823 -       
12824 +
12825         kvb = calloc(1, sizeof(*kvb));
12826 -       
12827 +
12828         return kvb;
12829  }
12830  
12831 @@ -135,49 +136,49 @@
12832         size_t i;
12833         if (kvb->size == 0) {
12834                 kvb->size = 4;
12835 -               
12836 +
12837                 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12838 -               
12839 +
12840                 for(i = 0; i < kvb->size; i++) {
12841                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12842                 }
12843         } else if (kvb->used == kvb->size) {
12844                 kvb->size += 4;
12845 -               
12846 +
12847                 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12848 -               
12849 +
12850                 for(i = kvb->used; i < kvb->size; i++) {
12851                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12852                 }
12853         }
12854 -       
12855 +
12856         kvb->kv[kvb->used]->key = key;
12857         kvb->kv[kvb->used]->value = strdup(value);
12858 -       
12859 +
12860         kvb->used++;
12861 -       
12862 +
12863         return 0;
12864  }
12865  
12866  void keyvalue_buffer_free(keyvalue_buffer *kvb) {
12867         size_t i;
12868 -       
12869 +
12870         for (i = 0; i < kvb->size; i++) {
12871                 if (kvb->kv[i]->value) free(kvb->kv[i]->value);
12872                 free(kvb->kv[i]);
12873         }
12874 -       
12875 +
12876         if (kvb->kv) free(kvb->kv);
12877 -       
12878 +
12879         free(kvb);
12880  }
12881  
12882  
12883  s_keyvalue_buffer *s_keyvalue_buffer_init(void) {
12884         s_keyvalue_buffer *kvb;
12885 -       
12886 +
12887         kvb = calloc(1, sizeof(*kvb));
12888 -       
12889 +
12890         return kvb;
12891  }
12892  
12893 @@ -186,50 +187,50 @@
12894         if (kvb->size == 0) {
12895                 kvb->size = 4;
12896                 kvb->used = 0;
12897 -               
12898 +
12899                 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12900 -               
12901 +
12902                 for(i = 0; i < kvb->size; i++) {
12903                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12904                 }
12905         } else if (kvb->used == kvb->size) {
12906                 kvb->size += 4;
12907 -               
12908 +
12909                 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12910 -               
12911 +
12912                 for(i = kvb->used; i < kvb->size; i++) {
12913                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12914                 }
12915         }
12916 -       
12917 +
12918         kvb->kv[kvb->used]->key = key ? strdup(key) : NULL;
12919         kvb->kv[kvb->used]->value = strdup(value);
12920 -       
12921 +
12922         kvb->used++;
12923 -       
12924 +
12925         return 0;
12926  }
12927  
12928  void s_keyvalue_buffer_free(s_keyvalue_buffer *kvb) {
12929         size_t i;
12930 -       
12931 +
12932         for (i = 0; i < kvb->size; i++) {
12933                 if (kvb->kv[i]->key) free(kvb->kv[i]->key);
12934                 if (kvb->kv[i]->value) free(kvb->kv[i]->value);
12935                 free(kvb->kv[i]);
12936         }
12937 -       
12938 +
12939         if (kvb->kv) free(kvb->kv);
12940 -       
12941 +
12942         free(kvb);
12943  }
12944  
12945  
12946  httpauth_keyvalue_buffer *httpauth_keyvalue_buffer_init(void) {
12947         httpauth_keyvalue_buffer *kvb;
12948 -       
12949 +
12950         kvb = calloc(1, sizeof(*kvb));
12951 -       
12952 +
12953         return kvb;
12954  }
12955  
12956 @@ -237,42 +238,42 @@
12957         size_t i;
12958         if (kvb->size == 0) {
12959                 kvb->size = 4;
12960 -               
12961 +
12962                 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12963 -               
12964 +
12965                 for(i = 0; i < kvb->size; i++) {
12966                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12967                 }
12968         } else if (kvb->used == kvb->size) {
12969                 kvb->size += 4;
12970 -               
12971 +
12972                 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
12973 -               
12974 +
12975                 for(i = kvb->used; i < kvb->size; i++) {
12976                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12977                 }
12978         }
12979 -       
12980 +
12981         kvb->kv[kvb->used]->key = strdup(key);
12982         kvb->kv[kvb->used]->realm = strdup(realm);
12983         kvb->kv[kvb->used]->type = type;
12984 -       
12985 +
12986         kvb->used++;
12987 -       
12988 +
12989         return 0;
12990  }
12991  
12992  void httpauth_keyvalue_buffer_free(httpauth_keyvalue_buffer *kvb) {
12993         size_t i;
12994 -       
12995 +
12996         for (i = 0; i < kvb->size; i++) {
12997                 if (kvb->kv[i]->key) free(kvb->kv[i]->key);
12998                 if (kvb->kv[i]->realm) free(kvb->kv[i]->realm);
12999                 free(kvb->kv[i]);
13000         }
13001 -       
13002 +
13003         if (kvb->kv) free(kvb->kv);
13004 -       
13005 +
13006         free(kvb);
13007  }
13008  
13009 @@ -306,9 +307,9 @@
13010  
13011  pcre_keyvalue_buffer *pcre_keyvalue_buffer_init(void) {
13012         pcre_keyvalue_buffer *kvb;
13013 -       
13014 +
13015         kvb = calloc(1, sizeof(*kvb));
13016 -       
13017 +
13018         return kvb;
13019  }
13020  
13021 @@ -319,46 +320,46 @@
13022         int erroff;
13023         pcre_keyvalue *kv;
13024  #endif
13025 -       
13026 +
13027         if (!key) return -1;
13028  
13029  #ifdef HAVE_PCRE_H
13030         if (kvb->size == 0) {
13031                 kvb->size = 4;
13032                 kvb->used = 0;
13033 -               
13034 +
13035                 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
13036 -               
13037 +
13038                 for(i = 0; i < kvb->size; i++) {
13039                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
13040                 }
13041         } else if (kvb->used == kvb->size) {
13042                 kvb->size += 4;
13043 -               
13044 +
13045                 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
13046 -               
13047 +
13048                 for(i = kvb->used; i < kvb->size; i++) {
13049                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
13050                 }
13051         }
13052 -       
13053 +
13054         kv = kvb->kv[kvb->used];
13055         if (NULL == (kv->key = pcre_compile(key,
13056                                           0, &errptr, &erroff, NULL))) {
13057 -               
13058 +
13059                 fprintf(stderr, "%s.%d: rexexp compilation error at %s\n", __FILE__, __LINE__, errptr);
13060                 return -1;
13061         }
13062  
13063 -       if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&  
13064 +       if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
13065                         errptr != NULL) {
13066                 return -1;
13067         }
13068 -       
13069 +
13070         kv->value = buffer_init_string(value);
13071 -       
13072 +
13073         kvb->used++;
13074 -       
13075 +
13076         return 0;
13077  #else
13078         UNUSED(kvb);
13079 @@ -380,9 +381,9 @@
13080                 if (kv->value) buffer_free(kv->value);
13081                 free(kv);
13082         }
13083 -       
13084 +
13085         if (kvb->kv) free(kvb->kv);
13086  #endif
13087 -       
13088 +
13089         free(kvb);
13090  }
13091 --- lighttpd-1.4.11/src/keyvalue.h      2006-03-02 16:08:06.000000000 +0200
13092 +++ lighttpd-1.4.12/src/keyvalue.h      2006-07-11 22:07:52.000000000 +0300
13093 @@ -9,19 +9,19 @@
13094  # include <pcre.h>
13095  #endif
13096  
13097 -typedef enum { 
13098 -       HTTP_METHOD_UNSET = -1, 
13099 -       HTTP_METHOD_GET, 
13100 -       HTTP_METHOD_POST, 
13101 -       HTTP_METHOD_HEAD, 
13102 -       HTTP_METHOD_OPTIONS, 
13103 +typedef enum {
13104 +       HTTP_METHOD_UNSET = -1,
13105 +       HTTP_METHOD_GET,
13106 +       HTTP_METHOD_POST,
13107 +       HTTP_METHOD_HEAD,
13108 +       HTTP_METHOD_OPTIONS,
13109         HTTP_METHOD_PROPFIND,  /* WebDAV */
13110 -       HTTP_METHOD_MKCOL, 
13111 -       HTTP_METHOD_PUT, 
13112 -       HTTP_METHOD_DELETE, 
13113 -       HTTP_METHOD_COPY, 
13114 -       HTTP_METHOD_MOVE, 
13115 -       HTTP_METHOD_PROPPATCH, 
13116 +       HTTP_METHOD_MKCOL,
13117 +       HTTP_METHOD_PUT,
13118 +       HTTP_METHOD_DELETE,
13119 +       HTTP_METHOD_COPY,
13120 +       HTTP_METHOD_MOVE,
13121 +       HTTP_METHOD_PROPPATCH,
13122         HTTP_METHOD_REPORT, /* DeltaV */
13123         HTTP_METHOD_CHECKOUT,
13124         HTTP_METHOD_CHECKIN,
13125 @@ -39,13 +39,13 @@
13126  
13127  typedef struct {
13128         int key;
13129 -       
13130 +
13131         char *value;
13132  } keyvalue;
13133  
13134  typedef struct {
13135         char *key;
13136 -       
13137 +
13138         char *value;
13139  } s_keyvalue;
13140  
13141 @@ -54,7 +54,7 @@
13142         pcre *key;
13143         pcre_extra *key_extra;
13144  #endif
13145 -       
13146 +
13147         buffer *value;
13148  } pcre_keyvalue;
13149  
13150 @@ -62,7 +62,7 @@
13151  
13152  typedef struct {
13153         char *key;
13154 -       
13155 +
13156         char *realm;
13157         httpauth_type type;
13158  } httpauth_keyvalue;
13159 --- lighttpd-1.4.11/src/lemon.c 2005-09-01 00:21:34.000000000 +0300
13160 +++ lighttpd-1.4.12/src/lemon.c 2006-07-11 22:07:51.000000000 +0300
13161 @@ -579,7 +579,7 @@
13162  */
13163  
13164  /* Find a precedence symbol of every rule in the grammar.
13165 -** 
13166 +**
13167  ** Those rules which have a precedence symbol coded in the input
13168  ** grammar using the "[symbol]" construct will already have the
13169  ** rp->precsym field filled.  Other rules take as their precedence
13170 @@ -869,7 +869,7 @@
13171        cfp->status = INCOMPLETE;
13172      }
13173    }
13174 -  
13175 +
13176    do{
13177      progress = 0;
13178      for(i=0; i<lemp->nstate; i++){
13179 @@ -900,7 +900,7 @@
13180    struct symbol *sp;
13181    struct rule *rp;
13182  
13183 -  /* Add all of the reduce actions 
13184 +  /* Add all of the reduce actions
13185    ** A reduce action is added for each element of the followset of
13186    ** a configuration which has its dot at the extreme right.
13187    */
13188 @@ -1017,7 +1017,7 @@
13189        apx->type = RD_RESOLVED;
13190      }
13191    }else{
13192 -    assert( 
13193 +    assert(
13194        apx->type==SH_RESOLVED ||
13195        apx->type==RD_RESOLVED ||
13196        apx->type==CONFLICT ||
13197 @@ -1350,7 +1350,7 @@
13198    OptInit(argv,options,stderr);
13199    if( version ){
13200       printf("Lemon version 1.0\n");
13201 -     exit(0); 
13202 +     exit(0);
13203    }
13204    if( OptNArgs() < 1 ){
13205      fprintf(stderr,"Exactly one filename argument is required.\n");
13206 @@ -2031,7 +2031,7 @@
13207      case IN_RHS:
13208        if( x[0]=='.' ){
13209          struct rule *rp;
13210 -        rp = (struct rule *)malloc( sizeof(struct rule) + 
13211 +        rp = (struct rule *)malloc( sizeof(struct rule) +
13212               sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs );
13213          if( rp==0 ){
13214            ErrorMsg(psp->filename,psp->tokenlineno,
13215 @@ -2546,7 +2546,7 @@
13216    return fp;
13217  }
13218  
13219 -/* Duplicate the input file without comments and without actions 
13220 +/* Duplicate the input file without comments and without actions
13221  ** on rules */
13222  void Reprint(lemp)
13223  struct lemon *lemp;
13224 @@ -2822,7 +2822,7 @@
13225  PRIVATE FILE *tplt_open(lemp)
13226  struct lemon *lemp;
13227  {
13228 -  
13229 +
13230    char buf[1000];
13231    FILE *in;
13232    char *tpltname;
13233 @@ -2930,7 +2930,7 @@
13234    return ret;
13235  }
13236  
13237 -/* 
13238 +/*
13239  ** Generate code which executes when the rule "rp" is reduced.  Write
13240  ** the code to "out".  Make sure lineno stays up-to-date.
13241  */
13242 @@ -3384,7 +3384,7 @@
13243  
13244    /* Output the yy_shift_ofst[] table */
13245    fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
13246 -  fprintf(out, "static %s yy_shift_ofst[] = {\n", 
13247 +  fprintf(out, "static %s yy_shift_ofst[] = {\n",
13248            minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++;
13249    n = lemp->nstate;
13250    for(i=j=0; i<n; i++){
13251 @@ -3405,7 +3405,7 @@
13252  
13253    /* Output the yy_reduce_ofst[] table */
13254    fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
13255 -  fprintf(out, "static %s yy_reduce_ofst[] = {\n", 
13256 +  fprintf(out, "static %s yy_reduce_ofst[] = {\n",
13257            minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++;
13258    n = lemp->nstate;
13259    for(i=j=0; i<n; i++){
13260 @@ -3480,7 +3480,7 @@
13261    tplt_xfer(lemp->name,in,out,&lineno);
13262  
13263    /* Generate code which executes every time a symbol is popped from
13264 -  ** the stack while processing errors or while destroying the parser. 
13265 +  ** the stack while processing errors or while destroying the parser.
13266    ** (In other words, generate the %destructor actions)
13267    */
13268    if( lemp->tokendest ){
13269 @@ -3522,7 +3522,7 @@
13270    tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno);
13271    tplt_xfer(lemp->name,in,out,&lineno);
13272  
13273 -  /* Generate the table of rule information 
13274 +  /* Generate the table of rule information
13275    **
13276    ** Note: This code depends on the fact that rules are number
13277    ** sequentually beginning with 0.
13278 @@ -3589,7 +3589,7 @@
13279      for(i=1; i<lemp->nterminal; i++){
13280        fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
13281      }
13282 -    fclose(out);  
13283 +    fclose(out);
13284    }
13285    return;
13286  }
13287 @@ -3630,7 +3630,7 @@
13288          rbest = rp;
13289        }
13290      }
13291
13292 +
13293      /* Do not make a default if the number of rules to default
13294      ** is not at least 2 */
13295      if( nbest<2 ) continue;
13296 @@ -3781,7 +3781,7 @@
13297    if( x1a ){
13298      x1a->size = 1024;
13299      x1a->count = 0;
13300 -    x1a->tbl = (x1node*)malloc( 
13301 +    x1a->tbl = (x1node*)malloc(
13302        (sizeof(x1node) + sizeof(x1node*))*1024 );
13303      if( x1a->tbl==0 ){
13304        free(x1a);
13305 @@ -3943,7 +3943,7 @@
13306    if( x2a ){
13307      x2a->size = 128;
13308      x2a->count = 0;
13309 -    x2a->tbl = (x2node*)malloc( 
13310 +    x2a->tbl = (x2node*)malloc(
13311        (sizeof(x2node) + sizeof(x2node*))*128 );
13312      if( x2a->tbl==0 ){
13313        free(x2a);
13314 @@ -4149,7 +4149,7 @@
13315    if( x3a ){
13316      x3a->size = 128;
13317      x3a->count = 0;
13318 -    x3a->tbl = (x3node*)malloc( 
13319 +    x3a->tbl = (x3node*)malloc(
13320        (sizeof(x3node) + sizeof(x3node*))*128 );
13321      if( x3a->tbl==0 ){
13322        free(x3a);
13323 @@ -4295,7 +4295,7 @@
13324    if( x4a ){
13325      x4a->size = 64;
13326      x4a->count = 0;
13327 -    x4a->tbl = (x4node*)malloc( 
13328 +    x4a->tbl = (x4node*)malloc(
13329        (sizeof(x4node) + sizeof(x4node*))*64 );
13330      if( x4a->tbl==0 ){
13331        free(x4a);
13332 --- lighttpd-1.4.11/src/lempar.c        2005-08-11 01:26:40.000000000 +0300
13333 +++ lighttpd-1.4.12/src/lempar.c        2006-07-11 22:07:51.000000000 +0300
13334 @@ -8,10 +8,10 @@
13335  /* Next is all token values, in a form suitable for use by makeheaders.
13336  ** This section will be null unless lemon is run with the -m switch.
13337  */
13338 -/* 
13339 +/*
13340  ** These constants (all generated automatically by the parser generator)
13341  ** specify the various kinds of tokens (terminals) that the parser
13342 -** understands. 
13343 +** understands.
13344  **
13345  ** Each symbol here is a terminal symbol in the grammar.
13346  */
13347 @@ -29,7 +29,7 @@
13348  **                       and nonterminals.  "int" is used otherwise.
13349  **    YYNOCODE           is a number of type YYCODETYPE which corresponds
13350  **                       to no legal terminal or nonterminal number.  This
13351 -**                       number is used to fill in empty slots of the hash 
13352 +**                       number is used to fill in empty slots of the hash
13353  **                       table.
13354  **    YYFALLBACK         If defined, this indicates that one or more tokens
13355  **                       have fall-back values which should be used if the
13356 @@ -38,7 +38,7 @@
13357  **                       and nonterminal numbers.  "unsigned char" is
13358  **                       used if there are fewer than 250 rules and
13359  **                       states combined.  "int" is used otherwise.
13360 -**    ParseTOKENTYPE     is the data type used for minor tokens given 
13361 +**    ParseTOKENTYPE     is the data type used for minor tokens given
13362  **                       directly to the parser from the tokenizer.
13363  **    YYMINORTYPE        is the data type used for all minor tokens.
13364  **                       This is typically a union of many types, one of
13365 @@ -62,7 +62,7 @@
13366  /* Next are that tables used to determine what action to take based on the
13367  ** current state and lookahead token.  These tables are used to implement
13368  ** functions that take a state number and lookahead value and return an
13369 -** action integer.  
13370 +** action integer.
13371  **
13372  ** Suppose the action integer is N.  Then the action is determined as
13373  ** follows
13374 @@ -87,7 +87,7 @@
13375  ** If the index value yy_shift_ofst[S]+X is out of range or if the value
13376  ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
13377  ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
13378 -** and that yy_default[S] should be used instead.  
13379 +** and that yy_default[S] should be used instead.
13380  **
13381  ** The formula above is for computing the action when the lookahead is
13382  ** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
13383 @@ -111,7 +111,7 @@
13384  
13385  /* The next table maps tokens into fallback tokens.  If a construct
13386  ** like the following:
13387 -** 
13388 +**
13389  **      %fallback ID X Y Z.
13390  **
13391  ** appears in the grammer, then ID becomes a fallback token for X, Y,
13392 @@ -163,10 +163,10 @@
13393  #endif /* NDEBUG */
13394  
13395  #ifndef NDEBUG
13396 -/* 
13397 +/*
13398  ** Turn parser tracing on by giving a stream to which to write the trace
13399  ** and a prompt to preface each trace message.  Tracing is turned off
13400 -** by making either argument NULL 
13401 +** by making either argument NULL
13402  **
13403  ** Inputs:
13404  ** <ul>
13405 @@ -191,7 +191,7 @@
13406  #ifndef NDEBUG
13407  /* For tracing shifts, the names of all terminals and nonterminals
13408  ** are required.  The following table supplies these names */
13409 -static const char *yyTokenName[] = { 
13410 +static const char *yyTokenName[] = {
13411  %%
13412  };
13413  #endif /* NDEBUG */
13414 @@ -220,7 +220,7 @@
13415  #endif
13416  }
13417  
13418 -/* 
13419 +/*
13420  ** This function allocates a new parser.
13421  ** The only argument is a pointer to a function which works like
13422  ** malloc.
13423 @@ -251,7 +251,7 @@
13424      /* Here is inserted the actions which take place when a
13425      ** terminal or non-terminal is destroyed.  This can happen
13426      ** when the symbol is popped from the stack during a
13427 -    ** reduce or during error processing or when a parser is 
13428 +    ** reduce or during error processing or when a parser is
13429      ** being destroyed before it is finished parsing.
13430      **
13431      ** Note: during a reduce, the only symbols destroyed are those
13432 @@ -289,7 +289,7 @@
13433    return yymajor;
13434  }
13435  
13436 -/* 
13437 +/*
13438  ** Deallocate and destroy a parser.  Destructors are all called for
13439  ** all stack elements before shutting the parser down.
13440  **
13441 @@ -325,7 +325,7 @@
13442  ){
13443    int i;
13444    int stateno = pParser->yystack[pParser->yyidx].stateno;
13445
13446 +
13447    /* if( pParser->yyidx<0 ) return YY_NO_ACTION;  */
13448    i = yy_shift_ofst[stateno];
13449    if( i==YY_SHIFT_USE_DFLT ){
13450 @@ -369,7 +369,7 @@
13451  ){
13452    int i;
13453    int stateno = pParser->yystack[pParser->yyidx].stateno;
13454
13455 +
13456    i = yy_reduce_ofst[stateno];
13457    if( i==YY_REDUCE_USE_DFLT ){
13458      return yy_default[stateno];
13459 @@ -455,7 +455,7 @@
13460    ParseARG_FETCH;
13461    yymsp = &yypParser->yystack[yypParser->yyidx];
13462  #ifndef NDEBUG
13463 -  if( yyTraceFILE && yyruleno>=0 
13464 +  if( yyTraceFILE && yyruleno>=0
13465          && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
13466      fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
13467        yyRuleName[yyruleno]);
13468 @@ -608,7 +608,7 @@
13469  #ifdef YYERRORSYMBOL
13470        /* A syntax error has occurred.
13471        ** The response to an error depends upon whether or not the
13472 -      ** grammar defines an error token "ERROR".  
13473 +      ** grammar defines an error token "ERROR".
13474        **
13475        ** This is what we do if the grammar does define ERROR:
13476        **
13477 --- lighttpd-1.4.11/src/log.c   2005-11-07 15:01:35.000000000 +0200
13478 +++ lighttpd-1.4.12/src/log.c   2006-07-11 22:07:53.000000000 +0300
13479 @@ -5,7 +5,7 @@
13480  #include <errno.h>
13481  #include <fcntl.h>
13482  #include <time.h>
13483 -#include <unistd.h>
13484 +//#include <unistd.h>
13485  #include <string.h>
13486  #include <stdlib.h>
13487  
13488 @@ -16,6 +16,10 @@
13489  #include "config.h"
13490  #endif
13491  
13492 +#ifdef _WIN32
13493 +#undef HAVE_SYSLOG_H
13494 +#endif
13495 +
13496  #ifdef HAVE_SYSLOG_H
13497  #include <syslog.h>
13498  #endif
13499 @@ -23,6 +27,8 @@
13500  #include "log.h"
13501  #include "array.h"
13502  
13503 +#include "sys-files.h"
13504 +
13505  #ifdef HAVE_VALGRIND_VALGRIND_H
13506  #include <valgrind/valgrind.h>
13507  #endif
13508 @@ -31,38 +37,38 @@
13509  # define O_LARGEFILE 0
13510  #endif
13511  
13512 -/** 
13513 +/**
13514   * open the errorlog
13515 - * 
13516 + *
13517   * we have 3 possibilities:
13518   * - stderr (default)
13519 - * - syslog 
13520 + * - syslog
13521   * - logfile
13522 - * 
13523 + *
13524   * if the open failed, report to the user and die
13525 - * 
13526 + *
13527   */
13528  
13529  int log_error_open(server *srv) {
13530         int fd;
13531         int close_stderr = 1;
13532 -       
13533 +
13534  #ifdef HAVE_SYSLOG_H
13535         /* perhaps someone wants to use syslog() */
13536         openlog("lighttpd", LOG_CONS | LOG_PID, LOG_DAEMON);
13537  #endif
13538         srv->errorlog_mode = ERRORLOG_STDERR;
13539 -       
13540 +
13541         if (srv->srvconf.errorlog_use_syslog) {
13542                 srv->errorlog_mode = ERRORLOG_SYSLOG;
13543         } else if (!buffer_is_empty(srv->srvconf.errorlog_file)) {
13544                 const char *logfile = srv->srvconf.errorlog_file->ptr;
13545 -               
13546 +
13547                 if (-1 == (srv->errorlog_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
13548 -                       log_error_write(srv, __FILE__, __LINE__, "SSSS", 
13549 +                       log_error_write(srv, __FILE__, __LINE__, "SSSS",
13550                                         "opening errorlog '", logfile,
13551                                         "' failed: ", strerror(errno));
13552 -                       
13553 +
13554                         return -1;
13555                 }
13556  #ifdef FD_CLOEXEC
13557 @@ -71,15 +77,15 @@
13558  #endif
13559                 srv->errorlog_mode = ERRORLOG_FILE;
13560         }
13561 -       
13562 +
13563         log_error_write(srv, __FILE__, __LINE__, "s", "server started");
13564 -       
13565 +
13566  #ifdef HAVE_VALGRIND_VALGRIND_H
13567         /* don't close stderr for debugging purposes if run in valgrind */
13568         if (RUNNING_ON_VALGRIND) close_stderr = 0;
13569  #endif
13570         if (srv->errorlog_mode == ERRORLOG_STDERR) close_stderr = 0;
13571 -       
13572 +
13573         /* move stderr to /dev/null */
13574         if (close_stderr &&
13575             -1 != (fd = open("/dev/null", O_WRONLY))) {
13576 @@ -90,33 +96,33 @@
13577         return 0;
13578  }
13579  
13580 -/** 
13581 +/**
13582   * open the errorlog
13583 - * 
13584 + *
13585   * if the open failed, report to the user and die
13586   * if no filename is given, use syslog instead
13587 - * 
13588 + *
13589   */
13590  
13591  int log_error_cycle(server *srv) {
13592         /* only cycle if we are not in syslog-mode */
13593 -       
13594 +
13595         if (srv->errorlog_mode == ERRORLOG_FILE) {
13596                 const char *logfile = srv->srvconf.errorlog_file->ptr;
13597                 /* already check of opening time */
13598 -               
13599 +
13600                 int new_fd;
13601 -               
13602 +
13603                 if (-1 == (new_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
13604                         /* write to old log */
13605 -                       log_error_write(srv, __FILE__, __LINE__, "SSSSS", 
13606 +                       log_error_write(srv, __FILE__, __LINE__, "SSSSS",
13607                                         "cycling errorlog '", logfile,
13608                                         "' failed: ", strerror(errno),
13609                                         ", falling back to syslog()");
13610 -                       
13611 +
13612                         close(srv->errorlog_fd);
13613                         srv->errorlog_fd = -1;
13614 -#ifdef HAVE_SYSLOG_H   
13615 +#ifdef HAVE_SYSLOG_H
13616                         srv->errorlog_mode = ERRORLOG_SYSLOG;
13617  #endif
13618                 } else {
13619 @@ -125,15 +131,15 @@
13620                         srv->errorlog_fd = new_fd;
13621                 }
13622         }
13623 -       
13624 +
13625         log_error_write(srv, __FILE__, __LINE__, "s", "logfiles cycled");
13626 -       
13627 +
13628         return 0;
13629  }
13630  
13631  int log_error_close(server *srv) {
13632         log_error_write(srv, __FILE__, __LINE__, "s", "server stopped");
13633 -       
13634 +
13635         switch(srv->errorlog_mode) {
13636         case ERRORLOG_FILE:
13637                 close(srv->errorlog_fd);
13638 @@ -146,13 +152,13 @@
13639         case ERRORLOG_STDERR:
13640                 break;
13641         }
13642 -       
13643 +
13644         return 0;
13645  }
13646  
13647  int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) {
13648         va_list ap;
13649 -       
13650 +
13651         switch(srv->errorlog_mode) {
13652         case ERRORLOG_FILE:
13653         case ERRORLOG_STDERR:
13654 @@ -161,7 +167,7 @@
13655                         buffer_prepare_copy(srv->ts_debug_str, 255);
13656                         strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts)));
13657                         srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1;
13658 -                       
13659 +
13660                         srv->last_generated_debug_ts = srv->cur_ts;
13661                 }
13662  
13663 @@ -173,19 +179,19 @@
13664                 BUFFER_COPY_STRING_CONST(srv->errorlog_buf, "(");
13665                 break;
13666         }
13667 -       
13668 +
13669         buffer_append_string(srv->errorlog_buf, filename);
13670         BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ".");
13671         buffer_append_long(srv->errorlog_buf, line);
13672         BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ") ");
13673 -       
13674 -       
13675 +
13676 +
13677         for(va_start(ap, fmt); *fmt; fmt++) {
13678                 int d;
13679                 char *s;
13680                 buffer *b;
13681                 off_t o;
13682 -               
13683 +
13684                 switch(*fmt) {
13685                 case 's':           /* string */
13686                         s = va_arg(ap, char *);
13687 @@ -227,7 +233,7 @@
13688                         break;
13689                 case '(':
13690                 case ')':
13691 -               case '<':       
13692 +               case '<':
13693                 case '>':
13694                 case ',':
13695                 case ' ':
13696 @@ -236,7 +242,7 @@
13697                 }
13698         }
13699         va_end(ap);
13700 -       
13701 +
13702         switch(srv->errorlog_mode) {
13703         case ERRORLOG_FILE:
13704                 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
13705 @@ -246,11 +252,13 @@
13706                 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
13707                 write(STDERR_FILENO, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1);
13708                 break;
13709 +#ifdef HAVE_SYSLOG_H
13710         case ERRORLOG_SYSLOG:
13711                 syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr);
13712                 break;
13713 +#endif
13714         }
13715 -       
13716 +
13717         return 0;
13718  }
13719  
13720 --- lighttpd-1.4.11/src/log.h   2005-08-11 01:26:36.000000000 +0300
13721 +++ lighttpd-1.4.12/src/log.h   2006-07-11 22:07:53.000000000 +0300
13722 @@ -9,5 +9,5 @@
13723  int log_error_close(server *srv);
13724  int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...);
13725  int log_error_cycle(server *srv);
13726 -       
13727 +
13728  #endif
13729 --- lighttpd-1.4.11/src/md5.h   2005-11-17 16:20:40.000000000 +0200
13730 +++ lighttpd-1.4.12/src/md5.h   2006-07-11 22:07:53.000000000 +0300
13731 @@ -30,9 +30,15 @@
13732  # include <inttypes.h>
13733  #endif
13734  
13735 +#ifdef _WIN32
13736 +#define UINT4 unsigned __int32
13737 +#define UINT2 unsigned __int16
13738 +#define POINTER unsigned char *
13739 +#else
13740  #define UINT4 uint32_t
13741  #define UINT2 uint16_t
13742  #define POINTER unsigned char *
13743 +#endif
13744  
13745  /* MD5 context. */
13746  typedef struct {
13747 --- lighttpd-1.4.11/src/mod_access.c    2006-01-14 19:44:54.000000000 +0200
13748 +++ lighttpd-1.4.12/src/mod_access.c    2006-07-11 22:07:53.000000000 +0300
13749 @@ -8,126 +8,125 @@
13750  
13751  #include "plugin.h"
13752  
13753 +#include "sys-strings.h"
13754 +
13755  typedef struct {
13756         array *access_deny;
13757  } plugin_config;
13758  
13759  typedef struct {
13760         PLUGIN_DATA;
13761 -       
13762 +
13763         plugin_config **config_storage;
13764 -       
13765 -       plugin_config conf; 
13766 +
13767 +       plugin_config conf;
13768  } plugin_data;
13769  
13770  INIT_FUNC(mod_access_init) {
13771         plugin_data *p;
13772 -       
13773 +
13774         p = calloc(1, sizeof(*p));
13775 -       
13776 +
13777         return p;
13778  }
13779  
13780  FREE_FUNC(mod_access_free) {
13781         plugin_data *p = p_d;
13782 -       
13783 +
13784         UNUSED(srv);
13785  
13786         if (!p) return HANDLER_GO_ON;
13787 -       
13788 +
13789         if (p->config_storage) {
13790                 size_t i;
13791                 for (i = 0; i < srv->config_context->used; i++) {
13792                         plugin_config *s = p->config_storage[i];
13793 -                       
13794 +
13795                         array_free(s->access_deny);
13796 -                       
13797 +
13798                         free(s);
13799                 }
13800                 free(p->config_storage);
13801         }
13802 -       
13803 +
13804         free(p);
13805 -       
13806 +
13807         return HANDLER_GO_ON;
13808  }
13809  
13810  SETDEFAULTS_FUNC(mod_access_set_defaults) {
13811         plugin_data *p = p_d;
13812         size_t i = 0;
13813 -       
13814 -       config_values_t cv[] = { 
13815 +
13816 +       config_values_t cv[] = {
13817                 { "url.access-deny",             NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
13818                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
13819         };
13820 -       
13821 +
13822         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
13823 -       
13824 +
13825         for (i = 0; i < srv->config_context->used; i++) {
13826                 plugin_config *s;
13827 -               
13828 +
13829                 s = calloc(1, sizeof(plugin_config));
13830                 s->access_deny    = array_init();
13831 -               
13832 +
13833                 cv[0].destination = s->access_deny;
13834 -               
13835 +
13836                 p->config_storage[i] = s;
13837 -       
13838 +
13839                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
13840                         return HANDLER_ERROR;
13841                 }
13842         }
13843 -       
13844 +
13845         return HANDLER_GO_ON;
13846  }
13847  
13848 -#define PATCH(x) \
13849 -       p->conf.x = s->x;
13850  static int mod_access_patch_connection(server *srv, connection *con, plugin_data *p) {
13851         size_t i, j;
13852         plugin_config *s = p->config_storage[0];
13853  
13854 -       PATCH(access_deny);
13855 -       
13856 +       PATCH_OPTION(access_deny);
13857 +
13858         /* skip the first, the global context */
13859         for (i = 1; i < srv->config_context->used; i++) {
13860                 data_config *dc = (data_config *)srv->config_context->data[i];
13861                 s = p->config_storage[i];
13862 -               
13863 +
13864                 /* condition didn't match */
13865                 if (!config_check_cond(srv, con, dc)) continue;
13866 -               
13867 +
13868                 /* merge config */
13869                 for (j = 0; j < dc->value->used; j++) {
13870                         data_unset *du = dc->value->data[j];
13871 -                       
13872 +
13873                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.access-deny"))) {
13874 -                               PATCH(access_deny);
13875 +                               PATCH_OPTION(access_deny);
13876                         }
13877                 }
13878         }
13879 -       
13880 +
13881         return 0;
13882  }
13883 -#undef PATCH
13884  
13885  URIHANDLER_FUNC(mod_access_uri_handler) {
13886         plugin_data *p = p_d;
13887         int s_len;
13888         size_t k;
13889 -       
13890 +
13891         if (con->uri.path->used == 0) return HANDLER_GO_ON;
13892 -       
13893 +
13894         mod_access_patch_connection(srv, con, p);
13895 -       
13896 +
13897         s_len = con->uri.path->used - 1;
13898 -       
13899 +
13900         for (k = 0; k < p->conf.access_deny->used; k++) {
13901                 data_string *ds = (data_string *)p->conf.access_deny->data[k];
13902                 int ct_len = ds->value->used - 1;
13903 -               
13904 +
13905                 if (ct_len > s_len) continue;
13906 -               
13907 +
13908                 if (ds->value->used == 0) continue;
13909  
13910                 /* if we have a case-insensitive FS we have to lower-case the URI here too */
13911 @@ -135,18 +134,18 @@
13912                 if (con->conf.force_lowercase_filenames) {
13913                         if (0 == strncasecmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
13914                                 con->http_status = 403;
13915 -                       
13916 +
13917                                 return HANDLER_FINISHED;
13918                         }
13919                 } else {
13920                         if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
13921                                 con->http_status = 403;
13922 -                       
13923 +
13924                                 return HANDLER_FINISHED;
13925                         }
13926                 }
13927         }
13928 -       
13929 +
13930         /* not found */
13931         return HANDLER_GO_ON;
13932  }
13933 @@ -155,13 +154,13 @@
13934  int mod_access_plugin_init(plugin *p) {
13935         p->version     = LIGHTTPD_VERSION_ID;
13936         p->name        = buffer_init_string("access");
13937 -       
13938 +
13939         p->init        = mod_access_init;
13940         p->set_defaults = mod_access_set_defaults;
13941         p->handle_uri_clean  = mod_access_uri_handler;
13942         p->cleanup     = mod_access_free;
13943 -       
13944 +
13945         p->data        = NULL;
13946 -       
13947 +
13948         return 0;
13949  }
13950 --- lighttpd-1.4.11/src/mod_accesslog.c 2006-01-31 14:01:43.000000000 +0200
13951 +++ lighttpd-1.4.12/src/mod_accesslog.c 2006-07-11 22:07:53.000000000 +0300
13952 @@ -6,8 +6,7 @@
13953  #include <ctype.h>
13954  #include <stdlib.h>
13955  #include <string.h>
13956 -#include <fcntl.h>
13957 -#include <unistd.h>
13958 +#include <fcntl.h> /* only the defines on windows */
13959  #include <errno.h>
13960  #include <time.h>
13961  
13962 @@ -22,6 +21,7 @@
13963  #include "inet_ntop_cache.h"
13964  
13965  #include "sys-socket.h"
13966 +#include "sys-files.h"
13967  
13968  #ifdef HAVE_SYSLOG_H
13969  # include <syslog.h>
13970 @@ -29,7 +29,7 @@
13971  
13972  typedef struct {
13973         char key;
13974 -       enum { 
13975 +       enum {
13976                 FORMAT_UNSET,
13977                         FORMAT_UNSUPPORTED,
13978                         FORMAT_PERCENT,
13979 @@ -41,7 +41,7 @@
13980                         FORMAT_STATUS,
13981                         FORMAT_BYTES_OUT_NO_HEADER,
13982                         FORMAT_HEADER,
13983 -                       
13984 +
13985                         FORMAT_REMOTE_ADDR,
13986                         FORMAT_LOCAL_ADDR,
13987                         FORMAT_COOKIE,
13988 @@ -59,20 +59,20 @@
13989                         FORMAT_CONNECTION_STATUS,
13990                         FORMAT_BYTES_IN,
13991                         FORMAT_BYTES_OUT,
13992 -                       
13993 +
13994                         FORMAT_RESPONSE_HEADER
13995         } type;
13996  } format_mapping;
13997  
13998  /**
13999 - * 
14000 - * 
14001 + *
14002 + *
14003   * "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
14004 - * 
14005 + *
14006   */
14007  
14008 -const format_mapping fmap[] = 
14009 -{ 
14010 +const format_mapping fmap[] =
14011 +{
14012         { '%', FORMAT_PERCENT },
14013         { 'h', FORMAT_REMOTE_HOST },
14014         { 'l', FORMAT_REMOTE_IDENT },
14015 @@ -82,7 +82,7 @@
14016         { 's', FORMAT_STATUS },
14017         { 'b', FORMAT_BYTES_OUT_NO_HEADER },
14018         { 'i', FORMAT_HEADER },
14019 -       
14020 +
14021         { 'a', FORMAT_REMOTE_ADDR },
14022         { 'A', FORMAT_LOCAL_ADDR },
14023         { 'B', FORMAT_BYTES_OUT_NO_HEADER },
14024 @@ -103,23 +103,23 @@
14025         { 'X', FORMAT_CONNECTION_STATUS },
14026         { 'I', FORMAT_BYTES_IN },
14027         { 'O', FORMAT_BYTES_OUT },
14028 -       
14029 +
14030         { 'o', FORMAT_RESPONSE_HEADER },
14031 -       
14032 +
14033         { '\0', FORMAT_UNSET }
14034  };
14035  
14036  
14037  typedef struct {
14038         enum { FIELD_UNSET, FIELD_STRING, FIELD_FORMAT } type;
14039 -       
14040 +
14041         buffer *string;
14042         int field;
14043  } format_field;
14044  
14045  typedef struct {
14046         format_field **ptr;
14047 -       
14048 +
14049         size_t used;
14050         size_t size;
14051  } format_fields;
14052 @@ -128,39 +128,39 @@
14053         buffer *access_logfile;
14054         buffer *format;
14055         unsigned short use_syslog;
14056 -       
14057 -       
14058 +
14059 +
14060         int    log_access_fd;
14061         time_t last_generated_accesslog_ts;
14062         time_t *last_generated_accesslog_ts_ptr;
14063 -       
14064 -       
14065 +
14066 +
14067         buffer *access_logbuffer;
14068         buffer *ts_accesslog_str;
14069 -       
14070 +
14071         format_fields *parsed_format;
14072  } plugin_config;
14073  
14074  typedef struct {
14075         PLUGIN_DATA;
14076 -       
14077 +
14078         plugin_config **config_storage;
14079 -       plugin_config conf; 
14080 +       plugin_config conf;
14081  } plugin_data;
14082  
14083  INIT_FUNC(mod_accesslog_init) {
14084         plugin_data *p;
14085 -       
14086 +
14087         p = calloc(1, sizeof(*p));
14088 -       
14089 +
14090         return p;
14091  }
14092  
14093  int accesslog_parse_format(server *srv, format_fields *fields, buffer *format) {
14094         size_t i, j, k = 0, start = 0;
14095 -       
14096 +
14097         for (i = 0; i < format->used - 1; i++) {
14098 -               
14099 +
14100                 switch(format->ptr[i]) {
14101                 case '%':
14102                         if (start != i) {
14103 @@ -173,19 +173,19 @@
14104                                         fields->size += 16;
14105                                         fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
14106                                 }
14107 -                               
14108 +
14109                                 fields->ptr[fields->used] = malloc(sizeof(format_fields));
14110                                 fields->ptr[fields->used]->type = FIELD_STRING;
14111                                 fields->ptr[fields->used]->string = buffer_init();
14112 -                               
14113 +
14114                                 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
14115 -                               
14116 +
14117                                 fields->used++;
14118                         }
14119 -                       
14120 -                       
14121 +
14122 +
14123                         /* we need a new field */
14124 -                       
14125 +
14126                         if (fields->size == 0) {
14127                                 fields->size = 16;
14128                                 fields->used = 0;
14129 @@ -194,43 +194,43 @@
14130                                 fields->size += 16;
14131                                 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
14132                         }
14133 -                       
14134 +
14135                         /* search for the terminating command */
14136                         switch (format->ptr[i+1]) {
14137                         case '>':
14138                         case '<':
14139                                 /* only for s */
14140 -                               
14141 +
14142                                 for (j = 0; fmap[j].key != '\0'; j++) {
14143                                         if (fmap[j].key != format->ptr[i+2]) continue;
14144 -                                       
14145 +
14146                                         /* found key */
14147 -                                               
14148 +
14149                                         fields->ptr[fields->used] = malloc(sizeof(format_fields));
14150                                         fields->ptr[fields->used]->type = FIELD_FORMAT;
14151                                         fields->ptr[fields->used]->field = fmap[j].type;
14152                                         fields->ptr[fields->used]->string = NULL;
14153 -                                       
14154 +
14155                                         fields->used++;
14156 -                                       
14157 +
14158                                         break;
14159                                 }
14160 -                               
14161 +
14162                                 if (fmap[j].key == '\0') {
14163                                         log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14164                                         return -1;
14165                                 }
14166 -                               
14167 +
14168                                 start = i + 3;
14169 -                               
14170 +
14171                                 break;
14172                         case '{':
14173                                 /* go forward to } */
14174 -                               
14175 +
14176                                 for (k = i+2; k < format->used - 1; k++) {
14177                                         if (format->ptr[k] == '}') break;
14178                                 }
14179 -                               
14180 +
14181                                 if (k == format->used - 1) {
14182                                         log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14183                                         return -1;
14184 @@ -239,62 +239,62 @@
14185                                         log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14186                                         return -1;
14187                                 }
14188 -                               
14189 +
14190                                 for (j = 0; fmap[j].key != '\0'; j++) {
14191                                         if (fmap[j].key != format->ptr[k+1]) continue;
14192 -                                       
14193 +
14194                                         /* found key */
14195 -                                               
14196 +
14197                                         fields->ptr[fields->used] = malloc(sizeof(format_fields));
14198                                         fields->ptr[fields->used]->type = FIELD_FORMAT;
14199                                         fields->ptr[fields->used]->field = fmap[j].type;
14200                                         fields->ptr[fields->used]->string = buffer_init();
14201 -                                       
14202 +
14203                                         buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + i + 2, k - (i + 2));
14204 -                                       
14205 +
14206                                         fields->used++;
14207 -                                       
14208 +
14209                                         break;
14210                                 }
14211 -                               
14212 +
14213                                 if (fmap[j].key == '\0') {
14214                                         log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14215                                         return -1;
14216                                 }
14217 -                               
14218 +
14219                                 start = k + 2;
14220 -                               
14221 +
14222                                 break;
14223                         default:
14224                                 for (j = 0; fmap[j].key != '\0'; j++) {
14225                                         if (fmap[j].key != format->ptr[i+1]) continue;
14226 -                                       
14227 +
14228                                         /* found key */
14229 -                                               
14230 +
14231                                         fields->ptr[fields->used] = malloc(sizeof(format_fields));
14232                                         fields->ptr[fields->used]->type = FIELD_FORMAT;
14233                                         fields->ptr[fields->used]->field = fmap[j].type;
14234                                         fields->ptr[fields->used]->string = NULL;
14235 -                                       
14236 +
14237                                         fields->used++;
14238 -                                       
14239 +
14240                                         break;
14241                                 }
14242 -                               
14243 +
14244                                 if (fmap[j].key == '\0') {
14245                                         log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14246                                         return -1;
14247                                 }
14248 -                               
14249 +
14250                                 start = i + 2;
14251 -                               
14252 +
14253                                 break;
14254                         }
14255 -                       
14256 +
14257                         break;
14258                 }
14259         }
14260 -       
14261 +
14262         if (start < i) {
14263                 /* copy the string */
14264                 if (fields->size == 0) {
14265 @@ -305,32 +305,32 @@
14266                         fields->size += 16;
14267                         fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
14268                 }
14269 -               
14270 +
14271                 fields->ptr[fields->used] = malloc(sizeof(format_fields));
14272                 fields->ptr[fields->used]->type = FIELD_STRING;
14273                 fields->ptr[fields->used]->string = buffer_init();
14274 -               
14275 +
14276                 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
14277 -               
14278 +
14279                 fields->used++;
14280         }
14281 -       
14282 +
14283         return 0;
14284  }
14285  
14286  FREE_FUNC(mod_accesslog_free) {
14287         plugin_data *p = p_d;
14288         size_t i;
14289 -       
14290 +
14291         if (!p) return HANDLER_GO_ON;
14292 -       
14293 +
14294         if (p->config_storage) {
14295 -               
14296 +
14297                 for (i = 0; i < srv->config_context->used; i++) {
14298                         plugin_config *s = p->config_storage[i];
14299  
14300                         if (!s) continue;
14301 -                       
14302 +
14303                         if (s->access_logbuffer->used) {
14304                                 if (s->use_syslog) {
14305  # ifdef HAVE_SYSLOG_H
14306 @@ -342,14 +342,14 @@
14307                                         write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
14308                                 }
14309                         }
14310 -                       
14311 +
14312                         if (s->log_access_fd != -1) close(s->log_access_fd);
14313 -                       
14314 +
14315                         buffer_free(s->ts_accesslog_str);
14316                         buffer_free(s->access_logbuffer);
14317                         buffer_free(s->format);
14318                         buffer_free(s->access_logfile);
14319 -                       
14320 +
14321                         if (s->parsed_format) {
14322                                 size_t j;
14323                                 for (j = 0; j < s->parsed_format->used; j++) {
14324 @@ -359,36 +359,36 @@
14325                                 free(s->parsed_format->ptr);
14326                                 free(s->parsed_format);
14327                         }
14328 -                       
14329 +
14330                         free(s);
14331                 }
14332 -       
14333 +
14334                 free(p->config_storage);
14335         }
14336 -       
14337 +
14338         free(p);
14339 -       
14340 +
14341         return HANDLER_GO_ON;
14342  }
14343  
14344  SETDEFAULTS_FUNC(log_access_open) {
14345         plugin_data *p = p_d;
14346         size_t i = 0;
14347 -       
14348 -       config_values_t cv[] = { 
14349 +
14350 +       config_values_t cv[] = {
14351                 { "accesslog.filename",             NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
14352                 { "accesslog.use-syslog",           NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
14353                 { "accesslog.format",               NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
14354                 { NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
14355         };
14356 -       
14357 +
14358         if (!p) return HANDLER_ERROR;
14359 -       
14360 +
14361         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
14362 -       
14363 +
14364         for (i = 0; i < srv->config_context->used; i++) {
14365                 plugin_config *s;
14366 -               
14367 +
14368                 s = calloc(1, sizeof(plugin_config));
14369                 s->access_logfile = buffer_init();
14370                 s->format = buffer_init();
14371 @@ -397,44 +397,44 @@
14372                 s->log_access_fd = -1;
14373                 s->last_generated_accesslog_ts = 0;
14374                 s->last_generated_accesslog_ts_ptr = &(s->last_generated_accesslog_ts);
14375 -               
14376 -       
14377 +
14378 +
14379                 cv[0].destination = s->access_logfile;
14380                 cv[1].destination = &(s->use_syslog);
14381                 cv[2].destination = s->format;
14382 -       
14383 +
14384                 p->config_storage[i] = s;
14385 -               
14386 +
14387                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
14388                         return HANDLER_ERROR;
14389                 }
14390 -               
14391 +
14392                 if (i == 0 && buffer_is_empty(s->format)) {
14393                         /* set a default logfile string */
14394 -                       
14395 +
14396                         buffer_copy_string(s->format, "%h %V %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"");
14397                 }
14398 -               
14399 +
14400                 /* parse */
14401 -               
14402 +
14403                 if (s->format->used) {
14404                         s->parsed_format = calloc(1, sizeof(*(s->parsed_format)));
14405 -                       
14406 +
14407                         if (-1 == accesslog_parse_format(srv, s->parsed_format, s->format)) {
14408  
14409 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
14410 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
14411                                                 "parsing accesslog-definition failed:", s->format);
14412  
14413                                 return HANDLER_ERROR;
14414                         }
14415  #if 0
14416 -                       /* debugging */                 
14417 +                       /* debugging */
14418                         for (j = 0; j < s->parsed_format->used; j++) {
14419                                 switch (s->parsed_format->ptr[j]->type) {
14420                                 case FIELD_FORMAT:
14421 -                                       log_error_write(srv, __FILE__, __LINE__, "ssds", 
14422 +                                       log_error_write(srv, __FILE__, __LINE__, "ssds",
14423                                                         "config:", "format", s->parsed_format->ptr[j]->field,
14424 -                                                       s->parsed_format->ptr[j]->string ? 
14425 +                                                       s->parsed_format->ptr[j]->string ?
14426                                                         s->parsed_format->ptr[j]->string->ptr : "" );
14427                                         break;
14428                                 case FIELD_STRING:
14429 @@ -446,52 +446,52 @@
14430                         }
14431  #endif
14432                 }
14433 -               
14434 +
14435                 if (s->use_syslog) {
14436                         /* ignore the next checks */
14437                         continue;
14438                 }
14439 -               
14440 +
14441                 if (buffer_is_empty(s->access_logfile)) continue;
14442 -               
14443 +
14444                 if (s->access_logfile->ptr[0] == '|') {
14445  #ifdef HAVE_FORK
14446                         /* create write pipe and spawn process */
14447 -                       
14448 +
14449                         int to_log_fds[2];
14450                         pid_t pid;
14451 -                       
14452 +
14453                         if (pipe(to_log_fds)) {
14454                                 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno));
14455                                 return HANDLER_ERROR;
14456                         }
14457 -                       
14458 +
14459                         /* fork, execve */
14460                         switch (pid = fork()) {
14461 -                       case 0: 
14462 +                       case 0:
14463                                 /* child */
14464 -                               
14465 +
14466                                 close(STDIN_FILENO);
14467                                 dup2(to_log_fds[0], STDIN_FILENO);
14468                                 close(to_log_fds[0]);
14469                                 /* not needed */
14470                                 close(to_log_fds[1]);
14471 -                               
14472 +
14473                                 /* we don't need the client socket */
14474                                 for (i = 3; i < 256; i++) {
14475                                         close(i);
14476                                 }
14477 -                               
14478 -                               /* exec the log-process (skip the | ) 
14479 -                                * 
14480 +
14481 +                               /* exec the log-process (skip the | )
14482 +                                *
14483                                  */
14484 -                               
14485 +
14486                                 execl("/bin/sh", "sh", "-c", s->access_logfile->ptr + 1, NULL);
14487  
14488 -                               log_error_write(srv, __FILE__, __LINE__, "sss", 
14489 -                                               "spawning log-process failed: ", strerror(errno), 
14490 +                               log_error_write(srv, __FILE__, __LINE__, "sss",
14491 +                                               "spawning log-process failed: ", strerror(errno),
14492                                                 s->access_logfile->ptr + 1);
14493 -                               
14494 +
14495                                 exit(-1);
14496                                 break;
14497                         case -1:
14498 @@ -500,27 +500,28 @@
14499                                 break;
14500                         default:
14501                                 close(to_log_fds[0]);
14502 -                               
14503 +
14504                                 s->log_access_fd = to_log_fds[1];
14505 -                               
14506 +
14507                                 break;
14508                         }
14509  #else
14510                         return -1;
14511  #endif
14512 -               } else if (-1 == (s->log_access_fd = 
14513 +               } else if (-1 == (s->log_access_fd =
14514                                   open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
14515 -                       
14516 -                       log_error_write(srv, __FILE__, __LINE__, "ssb", 
14517 -                                       "opening access-log failed:", 
14518 +
14519 +                       log_error_write(srv, __FILE__, __LINE__, "ssb",
14520 +                                       "opening access-log failed:",
14521                                         strerror(errno), s->access_logfile);
14522 -                       
14523 +
14524                         return HANDLER_ERROR;
14525                 }
14526 +#ifndef _WIN32
14527                 fcntl(s->log_access_fd, F_SETFD, FD_CLOEXEC);
14528 -       
14529 +#endif
14530         }
14531 -       
14532 +
14533         return HANDLER_GO_ON;
14534  }
14535  
14536 @@ -529,7 +530,7 @@
14537         size_t i;
14538  
14539         if (!p->config_storage) return HANDLER_GO_ON;
14540 -               
14541 +
14542         for (i = 0; i < srv->config_context->used; i++) {
14543                 plugin_config *s = p->config_storage[i];
14544  
14545 @@ -544,90 +545,87 @@
14546                         } else if (s->log_access_fd != -1) {
14547                                 write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
14548                         }
14549 -                       
14550 +
14551                         buffer_reset(s->access_logbuffer);
14552                 }
14553 -               
14554 +
14555                 if (s->use_syslog == 0 &&
14556                     !buffer_is_empty(s->access_logfile) &&
14557                     s->access_logfile->ptr[0] != '|') {
14558 -                       
14559 +
14560                         close(s->log_access_fd);
14561 -                       
14562 -                       if (-1 == (s->log_access_fd = 
14563 +
14564 +                       if (-1 == (s->log_access_fd =
14565                                    open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
14566 -                               
14567 +
14568                                 log_error_write(srv, __FILE__, __LINE__, "ss", "cycling access-log failed:", strerror(errno));
14569 -                               
14570 +
14571                                 return HANDLER_ERROR;
14572                         }
14573                 }
14574         }
14575 -       
14576 +
14577         return HANDLER_GO_ON;
14578  }
14579  
14580 -#define PATCH(x) \
14581 -       p->conf.x = s->x;
14582  static int mod_accesslog_patch_connection(server *srv, connection *con, plugin_data *p) {
14583         size_t i, j;
14584         plugin_config *s = p->config_storage[0];
14585 -       
14586 -       PATCH(access_logfile);
14587 -       PATCH(format);
14588 -       PATCH(log_access_fd);
14589 -       PATCH(last_generated_accesslog_ts_ptr);
14590 -       PATCH(access_logbuffer);
14591 -       PATCH(ts_accesslog_str);
14592 -       PATCH(parsed_format);
14593 -       PATCH(use_syslog);
14594 -       
14595 +
14596 +       PATCH_OPTION(access_logfile);
14597 +       PATCH_OPTION(format);
14598 +       PATCH_OPTION(log_access_fd);
14599 +       PATCH_OPTION(last_generated_accesslog_ts_ptr);
14600 +       PATCH_OPTION(access_logbuffer);
14601 +       PATCH_OPTION(ts_accesslog_str);
14602 +       PATCH_OPTION(parsed_format);
14603 +       PATCH_OPTION(use_syslog);
14604 +
14605         /* skip the first, the global context */
14606         for (i = 1; i < srv->config_context->used; i++) {
14607                 data_config *dc = (data_config *)srv->config_context->data[i];
14608                 s = p->config_storage[i];
14609 -               
14610 +
14611                 /* condition didn't match */
14612                 if (!config_check_cond(srv, con, dc)) continue;
14613 -               
14614 +
14615                 /* merge config */
14616                 for (j = 0; j < dc->value->used; j++) {
14617                         data_unset *du = dc->value->data[j];
14618 -                       
14619 +
14620                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.filename"))) {
14621 -                               PATCH(access_logfile);
14622 -                               PATCH(log_access_fd);
14623 -                               PATCH(last_generated_accesslog_ts_ptr);
14624 -                               PATCH(access_logbuffer);
14625 -                               PATCH(ts_accesslog_str);
14626 +                               PATCH_OPTION(access_logfile);
14627 +                               PATCH_OPTION(log_access_fd);
14628 +                               PATCH_OPTION(last_generated_accesslog_ts_ptr);
14629 +                               PATCH_OPTION(access_logbuffer);
14630 +                               PATCH_OPTION(ts_accesslog_str);
14631                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.format"))) {
14632 -                               PATCH(format);
14633 -                               PATCH(parsed_format);
14634 +                               PATCH_OPTION(format);
14635 +                               PATCH_OPTION(parsed_format);
14636                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.use-syslog"))) {
14637 -                               PATCH(use_syslog);
14638 +                               PATCH_OPTION(use_syslog);
14639                         }
14640                 }
14641         }
14642 -       
14643 +
14644         return 0;
14645  }
14646 -#undef PATCH
14647  
14648  REQUESTDONE_FUNC(log_access_write) {
14649         plugin_data *p = p_d;
14650         buffer *b;
14651         size_t j;
14652 -       
14653 +
14654         int newts = 0;
14655         data_string *ds;
14656 -       
14657 +
14658         mod_accesslog_patch_connection(srv, con, p);
14659 -       
14660 +
14661         b = p->conf.access_logbuffer;
14662         if (b->used == 0) {
14663                 buffer_copy_string(b, "");
14664         }
14665 -       
14666 +
14667         for (j = 0; j < p->conf.parsed_format->used; j++) {
14668                 switch(p->conf.parsed_format->ptr[j]->type) {
14669                 case FIELD_STRING:
14670 @@ -636,14 +634,14 @@
14671                 case FIELD_FORMAT:
14672                         switch(p->conf.parsed_format->ptr[j]->field) {
14673                         case FORMAT_TIMESTAMP:
14674 -                               
14675 +
14676                                 /* cache the generated timestamp */
14677                                 if (srv->cur_ts != *(p->conf.last_generated_accesslog_ts_ptr)) {
14678                                         struct tm tm;
14679  #if defined(HAVE_STRUCT_TM_GMTOFF)
14680                                         long scd, hrs, min;
14681  #endif
14682 -               
14683 +
14684                                         buffer_prepare_copy(p->conf.ts_accesslog_str, 255);
14685  #if defined(HAVE_STRUCT_TM_GMTOFF)
14686  # ifdef HAVE_LOCALTIME_R
14687 @@ -653,17 +651,17 @@
14688                                         strftime(p->conf.ts_accesslog_str->ptr, p->conf.ts_accesslog_str->size - 1, "[%d/%b/%Y:%H:%M:%S ", localtime_r(&(srv->cur_ts)));
14689  # endif
14690                                         p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
14691 -                                       
14692 +
14693                                         buffer_append_string(p->conf.ts_accesslog_str, tm.tm_gmtoff >= 0 ? "+" : "-");
14694 -                                       
14695 +
14696                                         scd = abs(tm.tm_gmtoff);
14697                                         hrs = scd / 3600;
14698                                         min = (scd % 3600) / 60;
14699 -                                       
14700 +
14701                                         /* hours */
14702                                         if (hrs < 10) buffer_append_string(p->conf.ts_accesslog_str, "0");
14703                                         buffer_append_long(p->conf.ts_accesslog_str, hrs);
14704 -                                       
14705 +
14706                                         if (min < 10) buffer_append_string(p->conf.ts_accesslog_str, "0");
14707                                         buffer_append_long(p->conf.ts_accesslog_str, min);
14708                                         BUFFER_APPEND_STRING_CONST(p->conf.ts_accesslog_str, "]");
14709 @@ -676,20 +674,20 @@
14710  #endif
14711                                         p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
14712  #endif
14713 -                                       
14714 +
14715                                         *(p->conf.last_generated_accesslog_ts_ptr) = srv->cur_ts;
14716                                         newts = 1;
14717                                 }
14718 -                               
14719 +
14720                                 buffer_append_string_buffer(b, p->conf.ts_accesslog_str);
14721 -                               
14722 +
14723                                 break;
14724                         case FORMAT_REMOTE_HOST:
14725 -       
14726 +
14727                                 /* handle inet_ntop cache */
14728 -       
14729 +
14730                                 buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
14731 -                               
14732 +
14733                                 break;
14734                         case FORMAT_REMOTE_IDENT:
14735                                 /* ident */
14736 @@ -710,10 +708,10 @@
14737                         case FORMAT_STATUS:
14738                                 buffer_append_long(b, con->http_status);
14739                                 break;
14740 -       
14741 +
14742                         case FORMAT_BYTES_OUT_NO_HEADER:
14743                                 if (con->bytes_written > 0) {
14744 -                                       buffer_append_off_t(b, 
14745 +                                       buffer_append_off_t(b,
14746                                                             con->bytes_written - con->bytes_header <= 0 ? 0 : con->bytes_written - con->bytes_header);
14747                                 } else {
14748                                         BUFFER_APPEND_STRING_CONST(b, "-");
14749 @@ -772,7 +770,7 @@
14750                                 }
14751                                 break;
14752                         case FORMAT_REQUEST_PROTOCOL:
14753 -                               buffer_append_string(b, 
14754 +                               buffer_append_string(b,
14755                                                      con->request.http_version == HTTP_VERSION_1_1 ? "HTTP/1.1" : "HTTP/1.0");
14756                                 break;
14757                         case FORMAT_REQUEST_METHOD:
14758 @@ -801,7 +799,7 @@
14759                                  { 'D', FORMAT_TIME_USED_MS },
14760                                  { 'e', FORMAT_ENV },
14761                                  */
14762 -                               
14763 +
14764                                 break;
14765                         }
14766                         break;
14767 @@ -809,7 +807,7 @@
14768                         break;
14769                 }
14770         }
14771 -       
14772 +
14773         BUFFER_APPEND_STRING_CONST(b, "\n");
14774  
14775         if (p->conf.use_syslog ||  /* syslog doesn't cache */
14776 @@ -828,7 +826,7 @@
14777                 }
14778                 buffer_reset(b);
14779         }
14780 -       
14781 +
14782         return HANDLER_GO_ON;
14783  }
14784  
14785 @@ -836,15 +834,15 @@
14786  int mod_accesslog_plugin_init(plugin *p) {
14787         p->version     = LIGHTTPD_VERSION_ID;
14788         p->name        = buffer_init_string("accesslog");
14789 -       
14790 +
14791         p->init        = mod_accesslog_init;
14792         p->set_defaults= log_access_open;
14793         p->cleanup     = mod_accesslog_free;
14794 -       
14795 +
14796         p->handle_request_done  = log_access_write;
14797         p->handle_sighup        = log_access_cycle;
14798 -       
14799 +
14800         p->data        = NULL;
14801 -       
14802 +
14803         return 0;
14804  }
14805 --- lighttpd-1.4.11/src/mod_alias.c     2006-03-01 23:18:51.000000000 +0200
14806 +++ lighttpd-1.4.12/src/mod_alias.c     2006-07-11 22:07:51.000000000 +0300
14807 @@ -8,6 +8,7 @@
14808  #include "buffer.h"
14809  
14810  #include "plugin.h"
14811 +#include "sys-strings.h"
14812  
14813  /* plugin config for all request/connections */
14814  typedef struct {
14815 @@ -16,44 +17,44 @@
14816  
14817  typedef struct {
14818         PLUGIN_DATA;
14819 -       
14820 +
14821         plugin_config **config_storage;
14822 -       
14823 -       plugin_config conf; 
14824 +
14825 +       plugin_config conf;
14826  } plugin_data;
14827  
14828  /* init the plugin data */
14829  INIT_FUNC(mod_alias_init) {
14830         plugin_data *p;
14831 -       
14832 +
14833         p = calloc(1, sizeof(*p));
14834 -       
14835 -       
14836 -       
14837 +
14838 +
14839 +
14840         return p;
14841  }
14842  
14843  /* detroy the plugin data */
14844  FREE_FUNC(mod_alias_free) {
14845         plugin_data *p = p_d;
14846 -       
14847 +
14848         if (!p) return HANDLER_GO_ON;
14849 -       
14850 +
14851         if (p->config_storage) {
14852                 size_t i;
14853 -               
14854 +
14855                 for (i = 0; i < srv->config_context->used; i++) {
14856                         plugin_config *s = p->config_storage[i];
14857 -                       
14858 +
14859                         array_free(s->alias);
14860 -                       
14861 +
14862                         free(s);
14863                 }
14864                 free(p->config_storage);
14865         }
14866 -       
14867 +
14868         free(p);
14869 -       
14870 +
14871         return HANDLER_GO_ON;
14872  }
14873  
14874 @@ -62,25 +63,25 @@
14875  SETDEFAULTS_FUNC(mod_alias_set_defaults) {
14876         plugin_data *p = p_d;
14877         size_t i = 0;
14878 -       
14879 -       config_values_t cv[] = { 
14880 +
14881 +       config_values_t cv[] = {
14882                 { "alias.url",                  NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
14883                 { NULL,                         NULL, T_CONFIG_UNSET,  T_CONFIG_SCOPE_UNSET }
14884         };
14885 -       
14886 +
14887         if (!p) return HANDLER_ERROR;
14888 -       
14889 +
14890         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
14891 -       
14892 +
14893         for (i = 0; i < srv->config_context->used; i++) {
14894                 plugin_config *s;
14895 -               
14896 +
14897                 s = calloc(1, sizeof(plugin_config));
14898 -               s->alias = array_init();        
14899 +               s->alias = array_init();
14900                 cv[0].destination = s->alias;
14901 -               
14902 +
14903                 p->config_storage[i] = s;
14904 -               
14905 +
14906                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
14907                         return HANDLER_ERROR;
14908                 }
14909 @@ -110,76 +111,73 @@
14910                         }
14911                 }
14912         }
14913 -       
14914 +
14915         return HANDLER_GO_ON;
14916  }
14917  
14918 -#define PATCH(x) \
14919 -       p->conf.x = s->x;
14920  static int mod_alias_patch_connection(server *srv, connection *con, plugin_data *p) {
14921         size_t i, j;
14922         plugin_config *s = p->config_storage[0];
14923 -       
14924 -       PATCH(alias);
14925 -       
14926 +
14927 +       PATCH_OPTION(alias);
14928 +
14929         /* skip the first, the global context */
14930         for (i = 1; i < srv->config_context->used; i++) {
14931                 data_config *dc = (data_config *)srv->config_context->data[i];
14932                 s = p->config_storage[i];
14933 -               
14934 +
14935                 /* condition didn't match */
14936                 if (!config_check_cond(srv, con, dc)) continue;
14937 -               
14938 +
14939                 /* merge config */
14940                 for (j = 0; j < dc->value->used; j++) {
14941                         data_unset *du = dc->value->data[j];
14942 -                       
14943 +
14944                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("alias.url"))) {
14945 -                               PATCH(alias);
14946 +                               PATCH_OPTION(alias);
14947                         }
14948                 }
14949         }
14950 -       
14951 +
14952         return 0;
14953  }
14954 -#undef PATCH
14955  
14956  PHYSICALPATH_FUNC(mod_alias_physical_handler) {
14957         plugin_data *p = p_d;
14958         int uri_len, basedir_len;
14959         char *uri_ptr;
14960         size_t k;
14961 -       
14962 +
14963         if (con->physical.path->used == 0) return HANDLER_GO_ON;
14964 -       
14965 +
14966         mod_alias_patch_connection(srv, con, p);
14967 -       
14968 +
14969         /* not to include the tailing slash */
14970         basedir_len = (con->physical.basedir->used - 1) - 1;
14971         uri_len = con->physical.path->used - 1 - basedir_len;
14972         uri_ptr = con->physical.path->ptr + basedir_len;
14973 -       
14974 +
14975         for (k = 0; k < p->conf.alias->used; k++) {
14976                 data_string *ds = (data_string *)p->conf.alias->data[k];
14977                 int alias_len = ds->key->used - 1;
14978 -               
14979 +
14980                 if (alias_len > uri_len) continue;
14981                 if (ds->key->used == 0) continue;
14982 -               
14983 +
14984                 if (0 == (con->conf.force_lowercase_filenames ?
14985                                         strncasecmp(uri_ptr, ds->key->ptr, alias_len) :
14986                                         strncmp(uri_ptr, ds->key->ptr, alias_len))) {
14987                         /* matched */
14988 -                       
14989 +
14990                         buffer_copy_string_buffer(con->physical.basedir, ds->value);
14991                         buffer_copy_string_buffer(srv->tmp_buf, ds->value);
14992                         buffer_append_string(srv->tmp_buf, uri_ptr + alias_len);
14993                         buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
14994 -                       
14995 +
14996                         return HANDLER_GO_ON;
14997                 }
14998         }
14999 -       
15000 +
15001         /* not found */
15002         return HANDLER_GO_ON;
15003  }
15004 @@ -189,13 +187,13 @@
15005  int mod_alias_plugin_init(plugin *p) {
15006         p->version     = LIGHTTPD_VERSION_ID;
15007         p->name        = buffer_init_string("alias");
15008 -       
15009 +
15010         p->init           = mod_alias_init;
15011         p->handle_physical= mod_alias_physical_handler;
15012         p->set_defaults   = mod_alias_set_defaults;
15013         p->cleanup        = mod_alias_free;
15014 -       
15015 +
15016         p->data        = NULL;
15017 -       
15018 +
15019         return 0;
15020  }
15021 --- lighttpd-1.4.11/src/mod_auth.c      2006-02-15 20:01:31.000000000 +0200
15022 +++ lighttpd-1.4.12/src/mod_auth.c      2006-07-11 22:07:53.000000000 +0300
15023 @@ -5,168 +5,167 @@
15024  #include <string.h>
15025  #include <errno.h>
15026  #include <fcntl.h>
15027 -#include <unistd.h>
15028  
15029  #include "plugin.h"
15030  #include "http_auth.h"
15031  #include "log.h"
15032  #include "response.h"
15033  
15034 +#include "sys-strings.h"
15035 +#include "sys-files.h"
15036 +
15037  handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
15038  
15039  
15040  /**
15041   * the basic and digest auth framework
15042 - * 
15043 + *
15044   * - config handling
15045   * - protocol handling
15046 - * 
15047 - * http_auth.c 
15048 - * http_auth_digest.c 
15049 - * 
15050 + *
15051 + * http_auth.c
15052 + * http_auth_digest.c
15053 + *
15054   * do the real work
15055   */
15056  
15057  INIT_FUNC(mod_auth_init) {
15058         mod_auth_plugin_data *p;
15059 -       
15060 +
15061         p = calloc(1, sizeof(*p));
15062 -       
15063 +
15064         p->tmp_buf = buffer_init();
15065 -       
15066 +
15067         p->auth_user = buffer_init();
15068  #ifdef USE_LDAP
15069         p->ldap_filter = buffer_init();
15070  #endif
15071 -       
15072 +
15073         return p;
15074  }
15075  
15076  FREE_FUNC(mod_auth_free) {
15077         mod_auth_plugin_data *p = p_d;
15078 -       
15079 +
15080         UNUSED(srv);
15081  
15082         if (!p) return HANDLER_GO_ON;
15083 -       
15084 +
15085         buffer_free(p->tmp_buf);
15086         buffer_free(p->auth_user);
15087  #ifdef USE_LDAP
15088         buffer_free(p->ldap_filter);
15089  #endif
15090 -       
15091 +
15092         if (p->config_storage) {
15093                 size_t i;
15094                 for (i = 0; i < srv->config_context->used; i++) {
15095                         mod_auth_plugin_config *s = p->config_storage[i];
15096 -                       
15097 +
15098                         if (!s) continue;
15099 -                       
15100 +
15101                         array_free(s->auth_require);
15102                         buffer_free(s->auth_plain_groupfile);
15103                         buffer_free(s->auth_plain_userfile);
15104                         buffer_free(s->auth_htdigest_userfile);
15105                         buffer_free(s->auth_htpasswd_userfile);
15106                         buffer_free(s->auth_backend_conf);
15107 -                       
15108 +
15109                         buffer_free(s->auth_ldap_hostname);
15110                         buffer_free(s->auth_ldap_basedn);
15111                         buffer_free(s->auth_ldap_binddn);
15112                         buffer_free(s->auth_ldap_bindpw);
15113                         buffer_free(s->auth_ldap_filter);
15114                         buffer_free(s->auth_ldap_cafile);
15115 -                       
15116 +
15117  #ifdef USE_LDAP
15118                         buffer_free(s->ldap_filter_pre);
15119                         buffer_free(s->ldap_filter_post);
15120 -                       
15121 +
15122                         if (s->ldap) ldap_unbind_s(s->ldap);
15123  #endif
15124 -                       
15125 +
15126                         free(s);
15127                 }
15128                 free(p->config_storage);
15129         }
15130 -       
15131 +
15132         free(p);
15133 -       
15134 +
15135         return HANDLER_GO_ON;
15136  }
15137  
15138 -#define PATCH(x) \
15139 -       p->conf.x = s->x;
15140  static int mod_auth_patch_connection(server *srv, connection *con, mod_auth_plugin_data *p) {
15141         size_t i, j;
15142         mod_auth_plugin_config *s = p->config_storage[0];
15143  
15144 -       PATCH(auth_backend);
15145 -       PATCH(auth_plain_groupfile);
15146 -       PATCH(auth_plain_userfile);
15147 -       PATCH(auth_htdigest_userfile);
15148 -       PATCH(auth_htpasswd_userfile);
15149 -       PATCH(auth_require);
15150 -       PATCH(auth_debug);
15151 -       PATCH(auth_ldap_hostname);
15152 -       PATCH(auth_ldap_basedn);
15153 -       PATCH(auth_ldap_binddn);
15154 -       PATCH(auth_ldap_bindpw);
15155 -       PATCH(auth_ldap_filter);
15156 -       PATCH(auth_ldap_cafile);
15157 -       PATCH(auth_ldap_starttls);
15158 +       PATCH_OPTION(auth_backend);
15159 +       PATCH_OPTION(auth_plain_groupfile);
15160 +       PATCH_OPTION(auth_plain_userfile);
15161 +       PATCH_OPTION(auth_htdigest_userfile);
15162 +       PATCH_OPTION(auth_htpasswd_userfile);
15163 +       PATCH_OPTION(auth_require);
15164 +       PATCH_OPTION(auth_debug);
15165 +       PATCH_OPTION(auth_ldap_hostname);
15166 +       PATCH_OPTION(auth_ldap_basedn);
15167 +       PATCH_OPTION(auth_ldap_binddn);
15168 +       PATCH_OPTION(auth_ldap_bindpw);
15169 +       PATCH_OPTION(auth_ldap_filter);
15170 +       PATCH_OPTION(auth_ldap_cafile);
15171 +       PATCH_OPTION(auth_ldap_starttls);
15172  #ifdef USE_LDAP
15173 -       PATCH(ldap);
15174 -       PATCH(ldap_filter_pre);
15175 -       PATCH(ldap_filter_post);
15176 +       PATCH_OPTION(ldap);
15177 +       PATCH_OPTION(ldap_filter_pre);
15178 +       PATCH_OPTION(ldap_filter_post);
15179  #endif
15180 -       
15181 +
15182         /* skip the first, the global context */
15183         for (i = 1; i < srv->config_context->used; i++) {
15184                 data_config *dc = (data_config *)srv->config_context->data[i];
15185                 s = p->config_storage[i];
15186 -               
15187 +
15188                 /* condition didn't match */
15189                 if (!config_check_cond(srv, con, dc)) continue;
15190 -               
15191 +
15192                 /* merge config */
15193                 for (j = 0; j < dc->value->used; j++) {
15194                         data_unset *du = dc->value->data[j];
15195 -                       
15196 +
15197                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend"))) {
15198 -                               PATCH(auth_backend);
15199 +                               PATCH_OPTION(auth_backend);
15200                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.groupfile"))) {
15201 -                               PATCH(auth_plain_groupfile);
15202 +                               PATCH_OPTION(auth_plain_groupfile);
15203                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.userfile"))) {
15204 -                               PATCH(auth_plain_userfile);
15205 +                               PATCH_OPTION(auth_plain_userfile);
15206                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htdigest.userfile"))) {
15207 -                               PATCH(auth_htdigest_userfile);
15208 +                               PATCH_OPTION(auth_htdigest_userfile);
15209                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htpasswd.userfile"))) {
15210 -                               PATCH(auth_htpasswd_userfile);
15211 +                               PATCH_OPTION(auth_htpasswd_userfile);
15212                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.require"))) {
15213 -                               PATCH(auth_require);
15214 +                               PATCH_OPTION(auth_require);
15215                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.debug"))) {
15216 -                               PATCH(auth_debug);
15217 +                               PATCH_OPTION(auth_debug);
15218                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.hostname"))) {
15219 -                               PATCH(auth_ldap_hostname);
15220 +                               PATCH_OPTION(auth_ldap_hostname);
15221  #ifdef USE_LDAP
15222 -                               PATCH(ldap);
15223 -                               PATCH(ldap_filter_pre);
15224 -                               PATCH(ldap_filter_post);
15225 +                               PATCH_OPTION(ldap);
15226 +                               PATCH_OPTION(ldap_filter_pre);
15227 +                               PATCH_OPTION(ldap_filter_post);
15228  #endif
15229                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.base-dn"))) {
15230 -                               PATCH(auth_ldap_basedn);
15231 +                               PATCH_OPTION(auth_ldap_basedn);
15232                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.filter"))) {
15233 -                               PATCH(auth_ldap_filter);
15234 +                               PATCH_OPTION(auth_ldap_filter);
15235                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.ca-file"))) {
15236 -                               PATCH(auth_ldap_cafile);
15237 +                               PATCH_OPTION(auth_ldap_cafile);
15238                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.starttls"))) {
15239 -                               PATCH(auth_ldap_starttls);
15240 +                               PATCH_OPTION(auth_ldap_starttls);
15241                         }
15242                 }
15243         }
15244 -       
15245 +
15246         return 0;
15247  }
15248 -#undef PATCH
15249  
15250  static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
15251         size_t k;
15252 @@ -175,22 +174,22 @@
15253         data_string *ds;
15254         mod_auth_plugin_data *p = p_d;
15255         array *req;
15256 -       
15257 +
15258         /* select the right config */
15259         mod_auth_patch_connection(srv, con, p);
15260 -       
15261 +
15262         if (p->conf.auth_require == NULL) return HANDLER_GO_ON;
15263 -       
15264 +
15265         /*
15266          * AUTH
15267 -        *  
15268 +        *
15269          */
15270 -       
15271 +
15272         /* do we have to ask for auth ? */
15273 -       
15274 +
15275         auth_required = 0;
15276         auth_satisfied = 0;
15277 -       
15278 +
15279         /* search auth-directives for path */
15280         for (k = 0; k < p->conf.auth_require->used; k++) {
15281                 buffer *req = p->conf.auth_require->data[k]->key;
15282 @@ -212,31 +211,31 @@
15283                         }
15284                 }
15285         }
15286 -       
15287 +
15288         /* nothing to do for us */
15289         if (auth_required == 0) return HANDLER_GO_ON;
15290 -       
15291 +
15292         req = ((data_array *)(p->conf.auth_require->data[k]))->value;
15293 -       
15294 +
15295         /* try to get Authorization-header */
15296 -               
15297 +
15298         if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization"))) {
15299                 http_authorization = ds->value->ptr;
15300         }
15301 -       
15302 +
15303         if (ds && ds->value && ds->value->used) {
15304                 char *auth_realm;
15305                 data_string *method;
15306 -               
15307 +
15308                 method = (data_string *)array_get_element(req, "method");
15309 -               
15310 +
15311                 /* parse auth-header */
15312                 if (NULL != (auth_realm = strchr(http_authorization, ' '))) {
15313                         int auth_type_len = auth_realm - http_authorization;
15314 -                       
15315 +
15316                         if ((auth_type_len == 5) &&
15317                             (0 == strncmp(http_authorization, "Basic", auth_type_len))) {
15318 -                               
15319 +
15320                                 if (0 == strcmp(method->value->ptr, "basic")) {
15321                                         auth_satisfied = http_auth_basic_check(srv, con, p, req, con->uri.path, auth_realm+1);
15322                                 }
15323 @@ -245,43 +244,43 @@
15324                                 if (0 == strcmp(method->value->ptr, "digest")) {
15325                                         if (-1 == (auth_satisfied = http_auth_digest_check(srv, con, p, req, con->uri.path, auth_realm+1))) {
15326                                                 con->http_status = 400;
15327 -                                               
15328 +
15329                                                 /* a field was missing */
15330 -                                               
15331 +
15332                                                 return HANDLER_FINISHED;
15333                                         }
15334                                 }
15335                         } else {
15336 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
15337 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
15338                                                 "unknown authentification type:",
15339                                                 http_authorization);
15340                         }
15341                 }
15342         }
15343 -       
15344 +
15345         if (!auth_satisfied) {
15346                 data_string *method, *realm;
15347                 method = (data_string *)array_get_element(req, "method");
15348                 realm = (data_string *)array_get_element(req, "realm");
15349 -               
15350 +
15351                 con->http_status = 401;
15352 -                       
15353 +
15354                 if (0 == strcmp(method->value->ptr, "basic")) {
15355                         buffer_copy_string(p->tmp_buf, "Basic realm=\"");
15356                         buffer_append_string_buffer(p->tmp_buf, realm->value);
15357                         buffer_append_string(p->tmp_buf, "\"");
15358 -                       
15359 +
15360                         response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
15361                 } else if (0 == strcmp(method->value->ptr, "digest")) {
15362                         char hh[33];
15363                         http_auth_digest_generate_nonce(srv, p, srv->tmp_buf, hh);
15364 -                       
15365 +
15366                         buffer_copy_string(p->tmp_buf, "Digest realm=\"");
15367                         buffer_append_string_buffer(p->tmp_buf, realm->value);
15368                         buffer_append_string(p->tmp_buf, "\", nonce=\"");
15369                         buffer_append_string(p->tmp_buf, hh);
15370                         buffer_append_string(p->tmp_buf, "\", qop=\"auth\"");
15371 -                       
15372 +
15373                         response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
15374                 } else {
15375                         /* evil */
15376 @@ -289,18 +288,18 @@
15377                 return HANDLER_FINISHED;
15378         } else {
15379                 /* the REMOTE_USER header */
15380 -               
15381 +
15382                 buffer_copy_string_buffer(con->authed_user, p->auth_user);
15383         }
15384 -       
15385 +
15386         return HANDLER_GO_ON;
15387  }
15388  
15389  SETDEFAULTS_FUNC(mod_auth_set_defaults) {
15390         mod_auth_plugin_data *p = p_d;
15391         size_t i;
15392 -       
15393 -       config_values_t cv[] = { 
15394 +
15395 +       config_values_t cv[] = {
15396                 { "auth.backend",                   NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
15397                 { "auth.backend.plain.groupfile",   NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
15398                 { "auth.backend.plain.userfile",    NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
15399 @@ -317,7 +316,7 @@
15400                 { "auth.debug",                     NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },  /* 13 */
15401                 { NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
15402         };
15403 -       
15404 +
15405         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
15406  
15407         for (i = 0; i < srv->config_context->used; i++) {
15408 @@ -325,14 +324,14 @@
15409                 size_t n;
15410                 data_array *da;
15411                 array *ca;
15412 -               
15413 +
15414                 s = calloc(1, sizeof(mod_auth_plugin_config));
15415                 s->auth_plain_groupfile = buffer_init();
15416                 s->auth_plain_userfile = buffer_init();
15417                 s->auth_htdigest_userfile = buffer_init();
15418                 s->auth_htpasswd_userfile = buffer_init();
15419                 s->auth_backend_conf = buffer_init();
15420 -               
15421 +
15422                 s->auth_ldap_hostname = buffer_init();
15423                 s->auth_ldap_basedn = buffer_init();
15424                 s->auth_ldap_binddn = buffer_init();
15425 @@ -341,15 +340,15 @@
15426                 s->auth_ldap_cafile = buffer_init();
15427                 s->auth_ldap_starttls = 0;
15428                 s->auth_debug = 0;
15429 -               
15430 +
15431                 s->auth_require = array_init();
15432 -               
15433 +
15434  #ifdef USE_LDAP
15435                 s->ldap_filter_pre = buffer_init();
15436                 s->ldap_filter_post = buffer_init();
15437                 s->ldap = NULL;
15438  #endif
15439 -       
15440 +
15441                 cv[0].destination = s->auth_backend_conf;
15442                 cv[1].destination = s->auth_plain_groupfile;
15443                 cv[2].destination = s->auth_plain_userfile;
15444 @@ -364,14 +363,14 @@
15445                 cv[11].destination = s->auth_htdigest_userfile;
15446                 cv[12].destination = s->auth_htpasswd_userfile;
15447                 cv[13].destination = &(s->auth_debug);
15448 -               
15449 +
15450                 p->config_storage[i] = s;
15451                 ca = ((data_config *)srv->config_context->data[i])->value;
15452 -               
15453 +
15454                 if (0 != config_insert_values_global(srv, ca, cv)) {
15455                         return HANDLER_ERROR;
15456                 }
15457 -               
15458 +
15459                 if (s->auth_backend_conf->used) {
15460                         if (0 == strcmp(s->auth_backend_conf->ptr, "htpasswd")) {
15461                                 s->auth_backend = AUTH_BACKEND_HTPASSWD;
15462 @@ -383,31 +382,31 @@
15463                                 s->auth_backend = AUTH_BACKEND_LDAP;
15464                         } else {
15465                                 log_error_write(srv, __FILE__, __LINE__, "sb", "auth.backend not supported:", s->auth_backend_conf);
15466 -                               
15467 +
15468                                 return HANDLER_ERROR;
15469                         }
15470                 }
15471  
15472                 /* no auth.require for this section */
15473                 if (NULL == (da = (data_array *)array_get_element(ca, "auth.require"))) continue;
15474 -               
15475 +
15476                 if (da->type != TYPE_ARRAY) continue;
15477 -               
15478 +
15479                 for (n = 0; n < da->value->used; n++) {
15480                         size_t m;
15481                         data_array *da_file = (data_array *)da->value->data[n];
15482                         const char *method, *realm, *require;
15483 -                       
15484 +
15485                         if (da->value->data[n]->type != TYPE_ARRAY) {
15486 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
15487 -                                               "auth.require should contain an array as in:", 
15488 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
15489 +                                               "auth.require should contain an array as in:",
15490                                                 "auth.require = ( \"...\" => ( ..., ...) )");
15491  
15492                                 return HANDLER_ERROR;
15493                         }
15494 -                                       
15495 +
15496                         method = realm = require = NULL;
15497 -                                       
15498 +
15499                         for (m = 0; m < da_file->value->used; m++) {
15500                                 if (da_file->value->data[m]->type == TYPE_STRING) {
15501                                         if (0 == strcmp(da_file->value->data[m]->key->ptr, "method")) {
15502 @@ -417,8 +416,8 @@
15503                                         } else if (0 == strcmp(da_file->value->data[m]->key->ptr, "require")) {
15504                                                 require = ((data_string *)(da_file->value->data[m]))->value->ptr;
15505                                         } else {
15506 -                                               log_error_write(srv, __FILE__, __LINE__, "ssbs", 
15507 -                                                       "the field is unknown in:", 
15508 +                                               log_error_write(srv, __FILE__, __LINE__, "ssbs",
15509 +                                                       "the field is unknown in:",
15510                                                         "auth.require = ( \"...\" => ( ..., -> \"",
15511                                                         da_file->value->data[m]->key,
15512                                                         "\" <- => \"...\" ) )");
15513 @@ -426,19 +425,19 @@
15514                                                 return HANDLER_ERROR;
15515                                         }
15516                                 } else {
15517 -                                       log_error_write(srv, __FILE__, __LINE__, "ssbs", 
15518 -                                               "a string was expected for:", 
15519 +                                       log_error_write(srv, __FILE__, __LINE__, "ssbs",
15520 +                                               "a string was expected for:",
15521                                                 "auth.require = ( \"...\" => ( ..., -> \"",
15522                                                 da_file->value->data[m]->key,
15523                                                 "\" <- => \"...\" ) )");
15524 -                                       
15525 +
15526                                         return HANDLER_ERROR;
15527                                 }
15528                         }
15529 -                                       
15530 +
15531                         if (method == NULL) {
15532 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
15533 -                                               "the require field is missing in:", 
15534 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
15535 +                                               "the require field is missing in:",
15536                                                 "auth.require = ( \"...\" => ( ..., \"method\" => \"...\" ) )");
15537                                 return HANDLER_ERROR;
15538                         } else {
15539 @@ -450,60 +449,60 @@
15540                                         return HANDLER_ERROR;
15541                                 }
15542                         }
15543 -                       
15544 +
15545                         if (realm == NULL) {
15546 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
15547 -                                               "the require field is missing in:", 
15548 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
15549 +                                               "the require field is missing in:",
15550                                                 "auth.require = ( \"...\" => ( ..., \"realm\" => \"...\" ) )");
15551                                 return HANDLER_ERROR;
15552                         }
15553 -                       
15554 +
15555                         if (require == NULL) {
15556 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
15557 -                                               "the require field is missing in:", 
15558 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
15559 +                                               "the require field is missing in:",
15560                                                 "auth.require = ( \"...\" => ( ..., \"require\" => \"...\" ) )");
15561                                 return HANDLER_ERROR;
15562                         }
15563 -                       
15564 +
15565                         if (method && realm && require) {
15566                                 data_string *ds;
15567                                 data_array *a;
15568 -                               
15569 +
15570                                 a = data_array_init();
15571                                 buffer_copy_string_buffer(a->key, da_file->key);
15572 -                               
15573 +
15574                                 ds = data_string_init();
15575 -                               
15576 +
15577                                 buffer_copy_string(ds->key, "method");
15578                                 buffer_copy_string(ds->value, method);
15579 -                               
15580 +
15581                                 array_insert_unique(a->value, (data_unset *)ds);
15582 -                               
15583 +
15584                                 ds = data_string_init();
15585 -                               
15586 +
15587                                 buffer_copy_string(ds->key, "realm");
15588                                 buffer_copy_string(ds->value, realm);
15589 -                               
15590 +
15591                                 array_insert_unique(a->value, (data_unset *)ds);
15592 -                               
15593 +
15594                                 ds = data_string_init();
15595 -                               
15596 +
15597                                 buffer_copy_string(ds->key, "require");
15598                                 buffer_copy_string(ds->value, require);
15599 -                               
15600 +
15601                                 array_insert_unique(a->value, (data_unset *)ds);
15602 -                               
15603 +
15604                                 array_insert_unique(s->auth_require, (data_unset *)a);
15605                         }
15606                 }
15607 -       
15608 +
15609                 switch(s->auth_backend) {
15610                 case AUTH_BACKEND_PLAIN:
15611                         if (s->auth_plain_userfile->used) {
15612                                 int fd;
15613                                 /* try to read */
15614                                 if (-1 == (fd = open(s->auth_plain_userfile->ptr, O_RDONLY))) {
15615 -                                       log_error_write(srv, __FILE__, __LINE__, "sbss", 
15616 +                                       log_error_write(srv, __FILE__, __LINE__, "sbss",
15617                                                         "opening auth.backend.plain.userfile:", s->auth_plain_userfile,
15618                                                         "failed:", strerror(errno));
15619                                         return HANDLER_ERROR;
15620 @@ -516,7 +515,7 @@
15621                                 int fd;
15622                                 /* try to read */
15623                                 if (-1 == (fd = open(s->auth_htpasswd_userfile->ptr, O_RDONLY))) {
15624 -                                       log_error_write(srv, __FILE__, __LINE__, "sbss", 
15625 +                                       log_error_write(srv, __FILE__, __LINE__, "sbss",
15626                                                         "opening auth.backend.htpasswd.userfile:", s->auth_htpasswd_userfile,
15627                                                         "failed:", strerror(errno));
15628                                         return HANDLER_ERROR;
15629 @@ -529,7 +528,7 @@
15630                                 int fd;
15631                                 /* try to read */
15632                                 if (-1 == (fd = open(s->auth_htdigest_userfile->ptr, O_RDONLY))) {
15633 -                                       log_error_write(srv, __FILE__, __LINE__, "sbss", 
15634 +                                       log_error_write(srv, __FILE__, __LINE__, "sbss",
15635                                                         "opening auth.backend.htdigest.userfile:", s->auth_htdigest_userfile,
15636                                                         "failed:", strerror(errno));
15637                                         return HANDLER_ERROR;
15638 @@ -554,75 +553,75 @@
15639  handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s) {
15640  #ifdef USE_LDAP
15641                         int ret;
15642 -#if 0                  
15643 +#if 0
15644                         if (s->auth_ldap_basedn->used == 0) {
15645                                 log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.base-dn has to be set");
15646 -                               
15647 +
15648                                 return HANDLER_ERROR;
15649                         }
15650  #endif
15651 -                       
15652 +
15653                         if (s->auth_ldap_filter->used) {
15654                                 char *dollar;
15655 -                               
15656 +
15657                                 /* parse filter */
15658 -                       
15659 +
15660                                 if (NULL == (dollar = strchr(s->auth_ldap_filter->ptr, '$'))) {
15661                                         log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.filter is missing a replace-operator '$'");
15662 -                                       
15663 +
15664                                         return HANDLER_ERROR;
15665                                 }
15666 -                               
15667 +
15668                                 buffer_copy_string_len(s->ldap_filter_pre, s->auth_ldap_filter->ptr, dollar - s->auth_ldap_filter->ptr);
15669                                 buffer_copy_string(s->ldap_filter_post, dollar+1);
15670                         }
15671 -                       
15672 +
15673                         if (s->auth_ldap_hostname->used) {
15674                                 if (NULL == (s->ldap = ldap_init(s->auth_ldap_hostname->ptr, LDAP_PORT))) {
15675                                         log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
15676 -                                       
15677 +
15678                                         return HANDLER_ERROR;
15679                                 }
15680 -                               
15681 +
15682                                 ret = LDAP_VERSION3;
15683                                 if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(s->ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
15684                                         log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
15685 -                               
15686 +
15687                                         return HANDLER_ERROR;
15688                                 }
15689  
15690                                 if (s->auth_ldap_starttls) {
15691 -                                       /* if no CA file is given, it is ok, as we will use encryption 
15692 +                                       /* if no CA file is given, it is ok, as we will use encryption
15693                                          * if the server requires a CAfile it will tell us */
15694                                         if (!buffer_is_empty(s->auth_ldap_cafile)) {
15695 -                                               if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, 
15696 +                                               if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
15697                                                                                 s->auth_ldap_cafile->ptr))) {
15698 -                                                       log_error_write(srv, __FILE__, __LINE__, "ss", 
15699 +                                                       log_error_write(srv, __FILE__, __LINE__, "ss",
15700                                                                         "Loading CA certificate failed:", ldap_err2string(ret));
15701 -                                               
15702 +
15703                                                         return HANDLER_ERROR;
15704                                                 }
15705                                         }
15706 -       
15707 +
15708                                         if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(s->ldap, NULL,  NULL))) {
15709                                                 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
15710 -                                               
15711 +
15712                                                 return HANDLER_ERROR;
15713                                         }
15714                                 }
15715 -                               
15716 -                               
15717 +
15718 +
15719                                 /* 1. */
15720                                 if (s->auth_ldap_binddn->used) {
15721                                         if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, s->auth_ldap_binddn->ptr, s->auth_ldap_bindpw->ptr))) {
15722                                                 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
15723 -                                               
15724 +
15725                                                 return HANDLER_ERROR;
15726                                         }
15727                                 } else {
15728                                         if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, NULL, NULL))) {
15729                                                 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
15730 -                                               
15731 +
15732                                                 return HANDLER_ERROR;
15733                                         }
15734                                 }
15735 @@ -641,8 +640,8 @@
15736         p->set_defaults = mod_auth_set_defaults;
15737         p->handle_uri_clean = mod_auth_uri_handler;
15738         p->cleanup     = mod_auth_free;
15739 -       
15740 +
15741         p->data        = NULL;
15742 -       
15743 +
15744         return 0;
15745  }
15746 --- lighttpd-1.4.11/src/mod_cgi.c       2006-02-22 15:15:10.000000000 +0200
15747 +++ lighttpd-1.4.12/src/mod_cgi.c       2006-07-11 22:07:51.000000000 +0300
15748 @@ -1,21 +1,8 @@
15749  #include <sys/types.h>
15750 -#ifdef __WIN32
15751 -#include <winsock2.h>
15752 -#else
15753 -#include <sys/socket.h>
15754 -#include <sys/wait.h>
15755 -#include <sys/mman.h>
15756 -
15757 -#include <netinet/in.h>
15758 -
15759 -#include <arpa/inet.h>
15760 -#endif
15761  
15762 -#include <unistd.h>
15763  #include <errno.h>
15764  #include <stdlib.h>
15765  #include <string.h>
15766 -#include <fdevent.h>
15767  #include <signal.h>
15768  #include <ctype.h>
15769  #include <assert.h>
15770 @@ -29,9 +16,16 @@
15771  #include "connections.h"
15772  #include "joblist.h"
15773  #include "http_chunk.h"
15774 +#include "fdevent.h"
15775  
15776  #include "plugin.h"
15777  
15778 +#include "sys-files.h"
15779 +#include "sys-mmap.h"
15780 +#include "sys-socket.h"
15781 +#include "sys-strings.h"
15782 +#include "sys-process.h"
15783 +
15784  #ifdef HAVE_SYS_FILIO_H
15785  # include <sys/filio.h>
15786  #endif
15787 @@ -40,11 +34,12 @@
15788  
15789  typedef struct {
15790         char **ptr;
15791 -       
15792 +
15793         size_t size;
15794         size_t used;
15795  } char_array;
15796  
15797 +#define pid_t int
15798  typedef struct {
15799         pid_t *ptr;
15800         size_t used;
15801 @@ -58,23 +53,23 @@
15802  typedef struct {
15803         PLUGIN_DATA;
15804         buffer_pid_t cgi_pid;
15805 -       
15806 +
15807         buffer *tmp_buf;
15808         buffer *parse_response;
15809 -       
15810 +
15811         plugin_config **config_storage;
15812 -       
15813 -       plugin_config conf; 
15814 +
15815 +       plugin_config conf;
15816  } plugin_data;
15817  
15818  typedef struct {
15819         pid_t pid;
15820         int fd;
15821         int fde_ndx; /* index into the fd-event buffer */
15822 -       
15823 +
15824         connection *remote_conn;  /* dumb pointer */
15825         plugin_data *plugin_data; /* dumb pointer */
15826 -       
15827 +
15828         buffer *response;
15829         buffer *response_header;
15830  } handler_ctx;
15831 @@ -83,17 +78,17 @@
15832         handler_ctx *hctx = calloc(1, sizeof(*hctx));
15833  
15834         assert(hctx);
15835 -       
15836 +
15837         hctx->response = buffer_init();
15838         hctx->response_header = buffer_init();
15839 -       
15840 +
15841         return hctx;
15842  }
15843  
15844  static void cgi_handler_ctx_free(handler_ctx *hctx) {
15845         buffer_free(hctx->response);
15846         buffer_free(hctx->response_header);
15847 -       
15848 +
15849         free(hctx);
15850  }
15851  
15852 @@ -101,14 +96,14 @@
15853  
15854  INIT_FUNC(mod_cgi_init) {
15855         plugin_data *p;
15856 -       
15857 +
15858         p = calloc(1, sizeof(*p));
15859  
15860         assert(p);
15861 -       
15862 +
15863         p->tmp_buf = buffer_init();
15864         p->parse_response = buffer_init();
15865 -       
15866 +
15867         return p;
15868  }
15869  
15870 @@ -116,62 +111,62 @@
15871  FREE_FUNC(mod_cgi_free) {
15872         plugin_data *p = p_d;
15873         buffer_pid_t *r = &(p->cgi_pid);
15874 -       
15875 +
15876         UNUSED(srv);
15877 -       
15878 +
15879         if (p->config_storage) {
15880                 size_t i;
15881                 for (i = 0; i < srv->config_context->used; i++) {
15882                         plugin_config *s = p->config_storage[i];
15883 -                       
15884 +
15885                         array_free(s->cgi);
15886 -                       
15887 +
15888                         free(s);
15889                 }
15890                 free(p->config_storage);
15891         }
15892 -       
15893 +
15894  
15895         if (r->ptr) free(r->ptr);
15896 -       
15897 +
15898         buffer_free(p->tmp_buf);
15899         buffer_free(p->parse_response);
15900 -       
15901 +
15902         free(p);
15903 -       
15904 +
15905         return HANDLER_GO_ON;
15906  }
15907  
15908  SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
15909         plugin_data *p = p_d;
15910         size_t i = 0;
15911 -       
15912 -       config_values_t cv[] = { 
15913 +
15914 +       config_values_t cv[] = {
15915                 { "cgi.assign",                  NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
15916                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET}
15917         };
15918  
15919         if (!p) return HANDLER_ERROR;
15920 -       
15921 +
15922         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
15923 -       
15924 +
15925         for (i = 0; i < srv->config_context->used; i++) {
15926                 plugin_config *s;
15927 -               
15928 +
15929                 s = calloc(1, sizeof(plugin_config));
15930                 assert(s);
15931 -               
15932 +
15933                 s->cgi    = array_init();
15934 -               
15935 +
15936                 cv[0].destination = s->cgi;
15937 -               
15938 +
15939                 p->config_storage[i] = s;
15940 -       
15941 +
15942                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
15943                         return HANDLER_ERROR;
15944                 }
15945         }
15946 -       
15947 +
15948         return HANDLER_GO_ON;
15949  }
15950  
15951 @@ -180,13 +175,13 @@
15952         int m = -1;
15953         size_t i;
15954         buffer_pid_t *r = &(p->cgi_pid);
15955 -       
15956 +
15957         UNUSED(srv);
15958  
15959         for (i = 0; i < r->used; i++) {
15960                 if (r->ptr[i] > m) m = r->ptr[i];
15961         }
15962 -       
15963 +
15964         if (r->size == 0) {
15965                 r->size = 16;
15966                 r->ptr = malloc(sizeof(*r->ptr) * r->size);
15967 @@ -194,31 +189,31 @@
15968                 r->size += 16;
15969                 r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
15970         }
15971 -       
15972 +
15973         r->ptr[r->used++] = pid;
15974 -       
15975 +
15976         return m;
15977  }
15978  
15979  static int cgi_pid_del(server *srv, plugin_data *p, pid_t pid) {
15980         size_t i;
15981         buffer_pid_t *r = &(p->cgi_pid);
15982 -       
15983 +
15984         UNUSED(srv);
15985  
15986         for (i = 0; i < r->used; i++) {
15987                 if (r->ptr[i] == pid) break;
15988         }
15989 -       
15990 +
15991         if (i != r->used) {
15992                 /* found */
15993 -               
15994 +
15995                 if (i != r->used - 1) {
15996                         r->ptr[i] = r->ptr[r->used - 1];
15997                 }
15998                 r->used--;
15999         }
16000 -       
16001 +
16002         return 0;
16003  }
16004  
16005 @@ -226,32 +221,32 @@
16006         char *ns;
16007         const char *s;
16008         int line = 0;
16009 -       
16010 +
16011         UNUSED(srv);
16012 -       
16013 +
16014         buffer_copy_string_buffer(p->parse_response, in);
16015 -       
16016 -       for (s = p->parse_response->ptr; 
16017 -            NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n'))); 
16018 +
16019 +       for (s = p->parse_response->ptr;
16020 +            NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
16021              s = ns + (eol == EOL_RN ? 2 : 1), line++) {
16022                 const char *key, *value;
16023                 int key_len;
16024                 data_string *ds;
16025 -               
16026 +
16027                 ns[0] = '\0';
16028 -               
16029 -               if (line == 0 && 
16030 +
16031 +               if (line == 0 &&
16032                     0 == strncmp(s, "HTTP/1.", 7)) {
16033                         /* non-parsed header ... we parse them anyway */
16034 -                       
16035 +
16036                         if ((s[7] == '1' ||
16037                              s[7] == '0') &&
16038                             s[8] == ' ') {
16039                                 int status;
16040                                 /* after the space should be a status code for us */
16041 -                               
16042 +
16043                                 status = strtol(s+9, NULL, 10);
16044 -                               
16045 +
16046                                 if (con->http_status >= 100 &&
16047                                     con->http_status < 1000) {
16048                                         /* we expected 3 digits and didn't got them */
16049 @@ -260,27 +255,27 @@
16050                                 }
16051                         }
16052                 } else {
16053 -               
16054 +
16055                         key = s;
16056                         if (NULL == (value = strchr(s, ':'))) {
16057                                 /* we expect: "<key>: <value>\r\n" */
16058                                 continue;
16059                         }
16060 -                       
16061 +
16062                         key_len = value - key;
16063                         value += 1;
16064 -                       
16065 +
16066                         /* skip LWS */
16067                         while (*value == ' ' || *value == '\t') value++;
16068 -                       
16069 +
16070                         if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
16071                                 ds = data_response_init();
16072                         }
16073                         buffer_copy_string_len(ds->key, key, key_len);
16074                         buffer_copy_string(ds->value, value);
16075 -                       
16076 +
16077                         array_insert_unique(con->response.headers, (data_unset *)ds);
16078 -                       
16079 +
16080                         switch(key_len) {
16081                         case 4:
16082                                 if (0 == strncasecmp(key, "Date", key_len)) {
16083 @@ -315,13 +310,13 @@
16084                         }
16085                 }
16086         }
16087 -       
16088 +
16089         /* CGI/1.1 rev 03 - 7.2.1.2 */
16090         if ((con->parsed_response & HTTP_LOCATION) &&
16091             !(con->parsed_response & HTTP_STATUS)) {
16092                 con->http_status = 302;
16093         }
16094 -       
16095 +
16096         return 0;
16097  }
16098  
16099 @@ -329,10 +324,10 @@
16100  static int cgi_demux_response(server *srv, handler_ctx *hctx) {
16101         plugin_data *p    = hctx->plugin_data;
16102         connection  *con  = hctx->remote_conn;
16103 -       
16104 +
16105         while(1) {
16106                 int n;
16107 -               
16108 +
16109                 buffer_prepare_copy(hctx->response, 1024);
16110                 if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
16111                         if (errno == EAGAIN || errno == EINTR) {
16112 @@ -343,125 +338,125 @@
16113                         log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
16114                         return FDEVENT_HANDLED_ERROR;
16115                 }
16116 -               
16117 +
16118                 if (n == 0) {
16119                         /* read finished */
16120 -                       
16121 +
16122                         con->file_finished = 1;
16123 -                       
16124 +
16125                         /* send final chunk */
16126                         http_chunk_append_mem(srv, con, NULL, 0);
16127                         joblist_append(srv, con);
16128 -                       
16129 +
16130                         return FDEVENT_HANDLED_FINISHED;
16131                 }
16132 -               
16133 +
16134                 hctx->response->ptr[n] = '\0';
16135                 hctx->response->used = n+1;
16136 -               
16137 +
16138                 /* split header from body */
16139 -               
16140 +
16141                 if (con->file_started == 0) {
16142                         char *c;
16143                         int in_header = 0;
16144                         int header_end = 0;
16145                         int cp, eol = EOL_UNSET;
16146                         size_t used = 0;
16147 -                       
16148 +
16149                         buffer_append_string_buffer(hctx->response_header, hctx->response);
16150 -                       
16151 +
16152                         /* nph (non-parsed headers) */
16153                         if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
16154 -                       
16155 +
16156                         /* search for the \r\n\r\n or \n\n in the string */
16157                         for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
16158                                 if (*c == ':') in_header = 1;
16159                                 else if (*c == '\n') {
16160                                         if (in_header == 0) {
16161                                                 /* got a response without a response header */
16162 -                                               
16163 +
16164                                                 c = NULL;
16165                                                 header_end = 1;
16166                                                 break;
16167                                         }
16168 -                                       
16169 +
16170                                         if (eol == EOL_UNSET) eol = EOL_N;
16171 -                                       
16172 +
16173                                         if (*(c+1) == '\n') {
16174                                                 header_end = 1;
16175                                                 break;
16176                                         }
16177 -                                       
16178 +
16179                                 } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
16180                                         if (in_header == 0) {
16181                                                 /* got a response without a response header */
16182 -                                               
16183 +
16184                                                 c = NULL;
16185                                                 header_end = 1;
16186                                                 break;
16187                                         }
16188 -                                       
16189 +
16190                                         if (eol == EOL_UNSET) eol = EOL_RN;
16191 -                                       
16192 +
16193                                         if (used > 3 &&
16194 -                                           *(c+2) == '\r' && 
16195 +                                           *(c+2) == '\r' &&
16196                                             *(c+3) == '\n') {
16197                                                 header_end = 1;
16198                                                 break;
16199                                         }
16200 -                                       
16201 +
16202                                         /* skip the \n */
16203                                         c++;
16204                                         cp++;
16205                                         used--;
16206                                 }
16207                         }
16208 -                       
16209 +
16210                         if (header_end) {
16211                                 if (c == NULL) {
16212                                         /* no header, but a body */
16213 -                                       
16214 +
16215                                         if (con->request.http_version == HTTP_VERSION_1_1) {
16216                                                 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
16217                                         }
16218 -                                       
16219 +
16220                                         http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
16221                                         joblist_append(srv, con);
16222                                 } else {
16223                                         size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
16224                                         size_t blen = hctx->response_header->used - hlen - 1;
16225 -                               
16226 +
16227                                         /* a small hack: terminate after at the second \r */
16228                                         hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
16229                                         hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';
16230 -                               
16231 +
16232                                         /* parse the response header */
16233                                         cgi_response_parse(srv, con, p, hctx->response_header, eol);
16234 -                                       
16235 +
16236                                         /* enable chunked-transfer-encoding */
16237                                         if (con->request.http_version == HTTP_VERSION_1_1 &&
16238                                             !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
16239                                                 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
16240                                         }
16241 -                                       
16242 +
16243                                         if ((hctx->response->used != hlen) && blen > 0) {
16244                                                 http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
16245                                                 joblist_append(srv, con);
16246                                         }
16247                                 }
16248 -                               
16249 +
16250                                 con->file_started = 1;
16251                         }
16252                 } else {
16253                         http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
16254                         joblist_append(srv, con);
16255                 }
16256 -               
16257 -#if 0          
16258 +
16259 +#if 0
16260                 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
16261  #endif
16262         }
16263 -       
16264 +
16265         return FDEVENT_HANDLED_NOT_FINISHED;
16266  }
16267  
16268 @@ -470,45 +465,46 @@
16269         pid_t pid;
16270         plugin_data *p;
16271         connection  *con;
16272 -       
16273 +
16274         if (NULL == hctx) return HANDLER_GO_ON;
16275 -       
16276 +
16277         p    = hctx->plugin_data;
16278         con  = hctx->remote_conn;
16279 -       
16280 +
16281         if (con->mode != p->id) return HANDLER_GO_ON;
16282  
16283 -#ifndef __WIN32
16284 -       
16285 +#ifndef _WIN32
16286 +
16287         /* the connection to the browser went away, but we still have a connection
16288 -        * to the CGI script 
16289 +        * to the CGI script
16290          *
16291          * close cgi-connection
16292          */
16293 -       
16294 +
16295         if (hctx->fd != -1) {
16296                 /* close connection to the cgi-script */
16297                 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
16298                 fdevent_unregister(srv->ev, hctx->fd);
16299 -               
16300 +
16301                 if (close(hctx->fd)) {
16302                         log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
16303                 }
16304 -               
16305 +
16306                 hctx->fd = -1;
16307                 hctx->fde_ndx = -1;
16308         }
16309 -       
16310 +
16311         pid = hctx->pid;
16312 -       
16313 +
16314         con->plugin_ctx[p->id] = NULL;
16315 -       
16316 +
16317         /* is this a good idea ? */
16318         cgi_handler_ctx_free(hctx);
16319 -       
16320 +
16321         /* if waitpid hasn't been called by response.c yet, do it here */
16322         if (pid) {
16323                 /* check if the CGI-script is already gone */
16324 +#ifndef _WIN32
16325                 switch(waitpid(pid, &status, WNOHANG)) {
16326                 case 0:
16327                         /* not finished yet */
16328 @@ -519,19 +515,19 @@
16329                 case -1:
16330                         /* */
16331                         if (errno == EINTR) break;
16332 -                       
16333 -                       /* 
16334 -                        * errno == ECHILD happens if _subrequest catches the process-status before 
16335 +
16336 +                       /*
16337 +                        * errno == ECHILD happens if _subrequest catches the process-status before
16338                          * we have read the response of the cgi process
16339 -                        * 
16340 +                        *
16341                          * -> catch status
16342                          * -> WAIT_FOR_EVENT
16343                          * -> read response
16344                          * -> we get here with waitpid == ECHILD
16345 -                        * 
16346 +                        *
16347                          */
16348                         if (errno == ECHILD) return HANDLER_GO_ON;
16349 -                       
16350 +
16351                         log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
16352                         return HANDLER_ERROR;
16353                 default:
16354 @@ -541,13 +537,13 @@
16355                                 con->http_status = 500;
16356                                 con->mode = DIRECT;
16357                         }
16358 -                               
16359 +
16360                         if (WIFEXITED(status)) {
16361  #if 0
16362                                 log_error_write(srv, __FILE__, __LINE__, "sd", "(debug) cgi exited fine, pid:", pid);
16363  #endif
16364                                 pid = 0;
16365 -                               
16366 +
16367                                 return HANDLER_GO_ON;
16368                         } else {
16369                                 log_error_write(srv, __FILE__, __LINE__, "sd", "cgi died, pid:", pid);
16370 @@ -555,20 +551,20 @@
16371                                 return HANDLER_GO_ON;
16372                         }
16373                 }
16374 -               
16375 -       
16376 +
16377 +
16378                 kill(pid, SIGTERM);
16379 -               
16380 +#endif
16381                 /* cgi-script is still alive, queue the PID for removal */
16382                 cgi_pid_add(srv, p, pid);
16383         }
16384 -#endif 
16385 +#endif
16386         return HANDLER_GO_ON;
16387  }
16388  
16389  static handler_t cgi_connection_close_callback(server *srv, connection *con, void *p_d) {
16390         plugin_data *p = p_d;
16391 -       
16392 +
16393         return cgi_connection_close(srv, con->plugin_ctx[p->id]);
16394  }
16395  
16396 @@ -577,43 +573,43 @@
16397         server      *srv  = (server *)s;
16398         handler_ctx *hctx = ctx;
16399         connection  *con  = hctx->remote_conn;
16400 -       
16401 +
16402         joblist_append(srv, con);
16403 -       
16404 +
16405         if (hctx->fd == -1) {
16406                 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "invalid cgi-fd");
16407 -               
16408 +
16409                 return HANDLER_ERROR;
16410         }
16411 -       
16412 +
16413         if (revents & FDEVENT_IN) {
16414                 switch (cgi_demux_response(srv, hctx)) {
16415                 case FDEVENT_HANDLED_NOT_FINISHED:
16416                         break;
16417                 case FDEVENT_HANDLED_FINISHED:
16418                         /* we are done */
16419 -                       
16420 +
16421  #if 0
16422                         log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "finished");
16423  #endif
16424                         cgi_connection_close(srv, hctx);
16425 -                       
16426 -                       /* if we get a IN|HUP and have read everything don't exec the close twice */ 
16427 +
16428 +                       /* if we get a IN|HUP and have read everything don't exec the close twice */
16429                         return HANDLER_FINISHED;
16430                 case FDEVENT_HANDLED_ERROR:
16431                         connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
16432                         con->http_status = 500;
16433                         con->mode = DIRECT;
16434 -                       
16435 +
16436                         log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: ");
16437                         break;
16438                 }
16439         }
16440 -       
16441 +
16442         if (revents & FDEVENT_OUT) {
16443                 /* nothing to do */
16444         }
16445 -       
16446 +
16447         /* perhaps this issue is already handled */
16448         if (revents & FDEVENT_HUP) {
16449                 /* check if we still have a unfinished header package which is a body in reality */
16450 @@ -623,54 +619,54 @@
16451                         http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
16452                         joblist_append(srv, con);
16453                 }
16454 -               
16455 +
16456                 if (con->file_finished == 0) {
16457                         http_chunk_append_mem(srv, con, NULL, 0);
16458                         joblist_append(srv, con);
16459                 }
16460 -               
16461 +
16462                 con->file_finished = 1;
16463 -               
16464 +
16465                 if (chunkqueue_is_empty(con->write_queue)) {
16466                         /* there is nothing left to write */
16467                         connection_set_state(srv, con, CON_STATE_RESPONSE_END);
16468                 } else {
16469                         /* used the write-handler to finish the request on demand */
16470 -                       
16471 +
16472                 }
16473 -               
16474 +
16475  # if 0
16476                 log_error_write(srv, __FILE__, __LINE__, "sddd", "got HUP from cgi", con->fd, hctx->fd, revents);
16477  # endif
16478 -               
16479 +
16480                 /* rtsigs didn't liked the close */
16481                 cgi_connection_close(srv, hctx);
16482         } else if (revents & FDEVENT_ERR) {
16483                 con->file_finished = 1;
16484 -               
16485 +
16486                 /* kill all connections to the cgi process */
16487                 cgi_connection_close(srv, hctx);
16488  #if 1
16489                 log_error_write(srv, __FILE__, __LINE__, "s", "cgi-FDEVENT_ERR");
16490 -#endif                 
16491 +#endif
16492                 return HANDLER_ERROR;
16493         }
16494 -       
16495 +
16496         return HANDLER_FINISHED;
16497  }
16498  
16499  
16500  static int cgi_env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
16501         char *dst;
16502 -       
16503 +
16504         if (!key || !val) return -1;
16505 -       
16506 +
16507         dst = malloc(key_len + val_len + 3);
16508         memcpy(dst, key, key_len);
16509         dst[key_len] = '=';
16510         /* add the \0 from the value */
16511         memcpy(dst + key_len + 1, val, val_len + 1);
16512 -       
16513 +
16514         if (env->size == 0) {
16515                 env->size = 16;
16516                 env->ptr = malloc(env->size * sizeof(*env->ptr));
16517 @@ -678,45 +674,45 @@
16518                 env->size += 16;
16519                 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
16520         }
16521 -       
16522 +
16523         env->ptr[env->used++] = dst;
16524 -       
16525 +
16526         return 0;
16527  }
16528  
16529  static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *cgi_handler) {
16530         pid_t pid;
16531 -       
16532 +
16533  #ifdef HAVE_IPV6
16534         char b2[INET6_ADDRSTRLEN + 1];
16535  #endif
16536 -       
16537 +
16538         int to_cgi_fds[2];
16539         int from_cgi_fds[2];
16540         struct stat st;
16541 -       
16542 -#ifndef __WIN32        
16543 -       
16544 +
16545 +#ifndef _WIN32
16546 +
16547         if (cgi_handler->used > 1) {
16548                 /* stat the exec file */
16549                 if (-1 == (stat(cgi_handler->ptr, &st))) {
16550 -                       log_error_write(srv, __FILE__, __LINE__, "sbss", 
16551 +                       log_error_write(srv, __FILE__, __LINE__, "sbss",
16552                                         "stat for cgi-handler", cgi_handler,
16553                                         "failed:", strerror(errno));
16554                         return -1;
16555                 }
16556         }
16557 -       
16558 +
16559         if (pipe(to_cgi_fds)) {
16560                 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
16561                 return -1;
16562         }
16563 -       
16564 +
16565         if (pipe(from_cgi_fds)) {
16566                 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
16567                 return -1;
16568         }
16569 -       
16570 +
16571         /* fork, execve */
16572         switch (pid = fork()) {
16573         case 0: {
16574 @@ -730,22 +726,22 @@
16575                 char *c;
16576                 const char *s;
16577                 server_socket *srv_sock = con->srv_socket;
16578 -               
16579 +
16580                 /* move stdout to from_cgi_fd[1] */
16581                 close(STDOUT_FILENO);
16582                 dup2(from_cgi_fds[1], STDOUT_FILENO);
16583                 close(from_cgi_fds[1]);
16584                 /* not needed */
16585                 close(from_cgi_fds[0]);
16586 -               
16587 +
16588                 /* move the stdin to to_cgi_fd[0] */
16589                 close(STDIN_FILENO);
16590                 dup2(to_cgi_fds[0], STDIN_FILENO);
16591                 close(to_cgi_fds[0]);
16592                 /* not needed */
16593                 close(to_cgi_fds[1]);
16594 -               
16595 -               /* HACK: 
16596 +
16597 +               /* HACK:
16598                  * this is not nice, but it works
16599                  *
16600                  * we feed the stderr of the CGI to our errorlog, if possible
16601 @@ -754,20 +750,20 @@
16602                         close(STDERR_FILENO);
16603                         dup2(srv->errorlog_fd, STDERR_FILENO);
16604                 }
16605 -               
16606 +
16607                 /* create environment */
16608                 env.ptr = NULL;
16609                 env.size = 0;
16610                 env.used = 0;
16611 -               
16612 +
16613                 cgi_env_add(&env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
16614  
16615                 if (!buffer_is_empty(con->server_name)) {
16616                         cgi_env_add(&env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
16617                 } else {
16618  #ifdef HAVE_IPV6
16619 -                       s = inet_ntop(srv_sock->addr.plain.sa_family, 
16620 -                                     srv_sock->addr.plain.sa_family == AF_INET6 ? 
16621 +                       s = inet_ntop(srv_sock->addr.plain.sa_family,
16622 +                                     srv_sock->addr.plain.sa_family == AF_INET6 ?
16623                                       (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
16624                                       (const void *) &(srv_sock->addr.ipv4.sin_addr),
16625                                       b2, sizeof(b2)-1);
16626 @@ -779,10 +775,10 @@
16627                 cgi_env_add(&env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
16628  
16629                 s = get_http_version_name(con->request.http_version);
16630 -               
16631 +
16632                 cgi_env_add(&env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
16633 -               
16634 -               ltostr(buf, 
16635 +
16636 +               ltostr(buf,
16637  #ifdef HAVE_IPV6
16638                         ntohs(srv_sock->addr.plain.sa_family == AF_INET6 ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
16639  #else
16640 @@ -790,10 +786,10 @@
16641  #endif
16642                         );
16643                 cgi_env_add(&env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
16644 -               
16645 +
16646  #ifdef HAVE_IPV6
16647 -               s = inet_ntop(srv_sock->addr.plain.sa_family, 
16648 -                             srv_sock->addr.plain.sa_family == AF_INET6 ? 
16649 +               s = inet_ntop(srv_sock->addr.plain.sa_family,
16650 +                             srv_sock->addr.plain.sa_family == AF_INET6 ?
16651                               (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
16652                               (const void *) &(srv_sock->addr.ipv4.sin_addr),
16653                               b2, sizeof(b2)-1);
16654 @@ -811,15 +807,18 @@
16655                 cgi_env_add(&env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200"));
16656                 if (!buffer_is_empty(con->uri.query)) {
16657                         cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query));
16658 +               } else {
16659 +                       /* set a empty QUERY_STRING */
16660 +                       cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
16661                 }
16662                 if (!buffer_is_empty(con->request.orig_uri)) {
16663                         cgi_env_add(&env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
16664                 }
16665 -               
16666 -               
16667 +
16668 +
16669  #ifdef HAVE_IPV6
16670 -               s = inet_ntop(con->dst_addr.plain.sa_family, 
16671 -                             con->dst_addr.plain.sa_family == AF_INET6 ? 
16672 +               s = inet_ntop(con->dst_addr.plain.sa_family,
16673 +                             con->dst_addr.plain.sa_family == AF_INET6 ?
16674                               (const void *) &(con->dst_addr.ipv6.sin6_addr) :
16675                               (const void *) &(con->dst_addr.ipv4.sin_addr),
16676                               b2, sizeof(b2)-1);
16677 @@ -828,7 +827,7 @@
16678  #endif
16679                 cgi_env_add(&env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
16680  
16681 -               ltostr(buf, 
16682 +               ltostr(buf,
16683  #ifdef HAVE_IPV6
16684                         ntohs(con->dst_addr.plain.sa_family == AF_INET6 ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
16685  #else
16686 @@ -836,19 +835,19 @@
16687  #endif
16688                         );
16689                 cgi_env_add(&env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
16690 -               
16691 +
16692                 if (!buffer_is_empty(con->authed_user)) {
16693                         cgi_env_add(&env, CONST_STR_LEN("REMOTE_USER"),
16694                                     CONST_BUF_LEN(con->authed_user));
16695                 }
16696 -               
16697 +
16698                 /* request.content_length < SSIZE_MAX, see request.c */
16699                 ltostr(buf, con->request.content_length);
16700                 cgi_env_add(&env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
16701                 cgi_env_add(&env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
16702                 cgi_env_add(&env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
16703                 cgi_env_add(&env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
16704 -               
16705 +
16706                 /* for valgrind */
16707                 if (NULL != (s = getenv("LD_PRELOAD"))) {
16708                         cgi_env_add(&env, CONST_STR_LEN("LD_PRELOAD"), s, strlen(s));
16709 @@ -863,24 +862,24 @@
16710                         cgi_env_add(&env, CONST_STR_LEN("SYSTEMROOT"), s, strlen(s));
16711                 }
16712  #endif
16713 -               
16714 +
16715                 for (n = 0; n < con->request.headers->used; n++) {
16716                         data_string *ds;
16717 -                       
16718 +
16719                         ds = (data_string *)con->request.headers->data[n];
16720 -                       
16721 +
16722                         if (ds->value->used && ds->key->used) {
16723                                 size_t j;
16724 -                               
16725 +
16726                                 buffer_reset(p->tmp_buf);
16727 -                               
16728 +
16729                                 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
16730                                         buffer_copy_string(p->tmp_buf, "HTTP_");
16731                                         p->tmp_buf->used--; /* strip \0 after HTTP_ */
16732                                 }
16733 -                               
16734 +
16735                                 buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
16736 -                               
16737 +
16738                                 for (j = 0; j < ds->key->used - 1; j++) {
16739                                         char cr = '_';
16740                                         if (light_isalpha(ds->key->ptr[j])) {
16741 @@ -893,46 +892,46 @@
16742                                         p->tmp_buf->ptr[p->tmp_buf->used++] = cr;
16743                                 }
16744                                 p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
16745 -                               
16746 +
16747                                 cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
16748                         }
16749                 }
16750 -               
16751 +
16752                 for (n = 0; n < con->environment->used; n++) {
16753                         data_string *ds;
16754 -                       
16755 +
16756                         ds = (data_string *)con->environment->data[n];
16757 -                       
16758 +
16759                         if (ds->value->used && ds->key->used) {
16760                                 size_t j;
16761 -                               
16762 +
16763                                 buffer_reset(p->tmp_buf);
16764 -                               
16765 +
16766                                 buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
16767 -                               
16768 +
16769                                 for (j = 0; j < ds->key->used - 1; j++) {
16770 -                                       p->tmp_buf->ptr[p->tmp_buf->used++] = 
16771 -                                               isalpha((unsigned char)ds->key->ptr[j]) ? 
16772 +                                       p->tmp_buf->ptr[p->tmp_buf->used++] =
16773 +                                               isalpha((unsigned char)ds->key->ptr[j]) ?
16774                                                 toupper((unsigned char)ds->key->ptr[j]) : '_';
16775                                 }
16776                                 p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
16777 -                               
16778 +
16779                                 cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
16780                         }
16781                 }
16782 -               
16783 +
16784                 if (env.size == env.used) {
16785                         env.size += 16;
16786                         env.ptr = realloc(env.ptr, env.size * sizeof(*env.ptr));
16787                 }
16788 -               
16789 +
16790                 env.ptr[env.used] = NULL;
16791 -               
16792 +
16793                 /* set up args */
16794                 argc = 3;
16795                 args = malloc(sizeof(*args) * argc);
16796                 i = 0;
16797 -               
16798 +
16799                 if (cgi_handler->used > 1) {
16800                         args[i++] = cgi_handler->ptr;
16801                 }
16802 @@ -942,7 +941,7 @@
16803                 /* search for the last / */
16804                 if (NULL != (c = strrchr(con->physical.path->ptr, '/'))) {
16805                         *c = '\0';
16806 -                       
16807 +
16808                         /* change to the physical directory */
16809                         if (-1 == chdir(con->physical.path->ptr)) {
16810                                 log_error_write(srv, __FILE__, __LINE__, "ssb", "chdir failed:", strerror(errno), con->physical.path);
16811 @@ -954,12 +953,12 @@
16812                 for (i = 3; i < 256; i++) {
16813                         if (i != srv->errorlog_fd) close(i);
16814                 }
16815 -               
16816 +
16817                 /* exec the cgi */
16818                 execve(args[0], args, env.ptr);
16819 -               
16820 +
16821                 log_error_write(srv, __FILE__, __LINE__, "sss", "CGI failed:", strerror(errno), args[0]);
16822 -               
16823 +
16824                 /* */
16825                 SEGFAULT();
16826                 break;
16827 @@ -974,11 +973,11 @@
16828  
16829                 close(from_cgi_fds[1]);
16830                 close(to_cgi_fds[0]);
16831 -               
16832 +
16833                 if (con->request.content_length) {
16834                         chunkqueue *cq = con->request_content_queue;
16835                         chunk *c;
16836 -               
16837 +
16838                         assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
16839  
16840                         /* there is content to send */
16841 @@ -993,16 +992,16 @@
16842                                                 if (-1 == c->file.fd &&  /* open the file if not already open */
16843                                                     -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
16844                                                         log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
16845 -                                       
16846 +
16847                                                         close(from_cgi_fds[0]);
16848                                                         close(to_cgi_fds[1]);
16849                                                         return -1;
16850                                                 }
16851  
16852                                                 c->file.mmap.length = c->file.length;
16853 -                               
16854 +
16855                                                 if (MAP_FAILED == (c->file.mmap.start = mmap(0,  c->file.mmap.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
16856 -                                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ", 
16857 +                                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
16858                                                                         strerror(errno), c->file.name,  c->file.fd);
16859  
16860                                                         close(from_cgi_fds[0]);
16861 @@ -1012,7 +1011,7 @@
16862  
16863                                                 close(c->file.fd);
16864                                                 c->file.fd = -1;
16865 -       
16866 +
16867                                                 /* chunk_reset() or chunk_free() will cleanup for us */
16868                                         }
16869  
16870 @@ -1020,7 +1019,7 @@
16871                                                 switch(errno) {
16872                                                 case ENOSPC:
16873                                                         con->http_status = 507;
16874 -               
16875 +
16876                                                         break;
16877                                                 default:
16878                                                         con->http_status = 403;
16879 @@ -1033,7 +1032,7 @@
16880                                                 switch(errno) {
16881                                                 case ENOSPC:
16882                                                         con->http_status = 507;
16883 -               
16884 +
16885                                                         break;
16886                                                 default:
16887                                                         con->http_status = 403;
16888 @@ -1056,103 +1055,100 @@
16889                 }
16890  
16891                 close(to_cgi_fds[1]);
16892 -                               
16893 +
16894                 /* register PID and wait for them asyncronously */
16895                 con->mode = p->id;
16896                 buffer_reset(con->physical.path);
16897 -               
16898 +
16899                 hctx = cgi_handler_ctx_init();
16900 -               
16901 +
16902                 hctx->remote_conn = con;
16903                 hctx->plugin_data = p;
16904                 hctx->pid = pid;
16905                 hctx->fd = from_cgi_fds[0];
16906                 hctx->fde_ndx = -1;
16907 -               
16908 +
16909                 con->plugin_ctx[p->id] = hctx;
16910 -               
16911 +
16912                 fdevent_register(srv->ev, hctx->fd, cgi_handle_fdevent, hctx);
16913                 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
16914 -               
16915 +
16916                 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
16917                         log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
16918 -                       
16919 +
16920                         fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
16921                         fdevent_unregister(srv->ev, hctx->fd);
16922 -                       
16923 +
16924                         log_error_write(srv, __FILE__, __LINE__, "sd", "cgi close:", hctx->fd);
16925 -                       
16926 +
16927                         close(hctx->fd);
16928 -                       
16929 +
16930                         cgi_handler_ctx_free(hctx);
16931 -                       
16932 +
16933                         con->plugin_ctx[p->id] = NULL;
16934 -                       
16935 +
16936                         return -1;
16937                 }
16938 -               
16939 +
16940                 break;
16941         }
16942         }
16943 -       
16944 +
16945         return 0;
16946  #else
16947         return -1;
16948  #endif
16949  }
16950  
16951 -#define PATCH(x) \
16952 -       p->conf.x = s->x;
16953  static int mod_cgi_patch_connection(server *srv, connection *con, plugin_data *p) {
16954         size_t i, j;
16955         plugin_config *s = p->config_storage[0];
16956 -       
16957 -       PATCH(cgi);
16958 -       
16959 +
16960 +       PATCH_OPTION(cgi);
16961 +
16962         /* skip the first, the global context */
16963         for (i = 1; i < srv->config_context->used; i++) {
16964                 data_config *dc = (data_config *)srv->config_context->data[i];
16965                 s = p->config_storage[i];
16966 -               
16967 +
16968                 /* condition didn't match */
16969                 if (!config_check_cond(srv, con, dc)) continue;
16970 -               
16971 +
16972                 /* merge config */
16973                 for (j = 0; j < dc->value->used; j++) {
16974                         data_unset *du = dc->value->data[j];
16975 -                       
16976 +
16977                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.assign"))) {
16978 -                               PATCH(cgi);
16979 +                               PATCH_OPTION(cgi);
16980                         }
16981                 }
16982         }
16983 -       
16984 +
16985         return 0;
16986  }
16987 -#undef PATCH
16988  
16989  URIHANDLER_FUNC(cgi_is_handled) {
16990         size_t k, s_len;
16991         plugin_data *p = p_d;
16992         buffer *fn = con->physical.path;
16993 -       
16994 +
16995         if (fn->used == 0) return HANDLER_GO_ON;
16996 -       
16997 +
16998         mod_cgi_patch_connection(srv, con, p);
16999 -       
17000 +
17001         s_len = fn->used - 1;
17002 -       
17003 +
17004         for (k = 0; k < p->conf.cgi->used; k++) {
17005                 data_string *ds = (data_string *)p->conf.cgi->data[k];
17006                 size_t ct_len = ds->key->used - 1;
17007 -               
17008 +
17009                 if (ds->key->used == 0) continue;
17010                 if (s_len < ct_len) continue;
17011 -               
17012 +
17013                 if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
17014                         if (cgi_create_env(srv, con, p, ds->value)) {
17015                                 con->http_status = 500;
17016 -                               
17017 +
17018                                 buffer_reset(con->physical.path);
17019                                 return HANDLER_FINISHED;
17020                         }
17021 @@ -1160,7 +1156,7 @@
17022                         break;
17023                 }
17024         }
17025 -       
17026 +
17027         return HANDLER_GO_ON;
17028  }
17029  
17030 @@ -1168,11 +1164,11 @@
17031         plugin_data *p = p_d;
17032         size_t ndx;
17033         /* the trigger handle only cares about lonely PID which we have to wait for */
17034 -#ifndef __WIN32
17035 +#ifndef _WIN32
17036  
17037         for (ndx = 0; ndx < p->cgi_pid.used; ndx++) {
17038                 int status;
17039 -               
17040 +
17041                 switch(waitpid(p->cgi_pid.ptr[ndx], &status, WNOHANG)) {
17042                 case 0:
17043                         /* not finished yet */
17044 @@ -1182,7 +1178,7 @@
17045                         break;
17046                 case -1:
17047                         log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
17048 -                       
17049 +
17050                         return HANDLER_ERROR;
17051                 default:
17052  
17053 @@ -1193,16 +1189,16 @@
17054                         } else {
17055                                 log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
17056                         }
17057 -                       
17058 +
17059                         cgi_pid_del(srv, p, p->cgi_pid.ptr[ndx]);
17060 -                       /* del modified the buffer structure 
17061 +                       /* del modified the buffer structure
17062                          * and copies the last entry to the current one
17063                          * -> recheck the current index
17064                          */
17065                         ndx--;
17066                 }
17067         }
17068 -#endif 
17069 +#endif
17070         return HANDLER_GO_ON;
17071  }
17072  
17073 @@ -1210,15 +1206,15 @@
17074         int status;
17075         plugin_data *p = p_d;
17076         handler_ctx *hctx = con->plugin_ctx[p->id];
17077 -       
17078 +
17079         if (con->mode != p->id) return HANDLER_GO_ON;
17080         if (NULL == hctx) return HANDLER_GO_ON;
17081 -       
17082 +
17083  #if 0
17084         log_error_write(srv, __FILE__, __LINE__, "sdd", "subrequest, pid =", hctx, hctx->pid);
17085 -#endif 
17086 +#endif
17087         if (hctx->pid == 0) return HANDLER_FINISHED;
17088 -#ifndef __WIN32        
17089 +#ifndef _WIN32
17090         switch(waitpid(hctx->pid, &status, WNOHANG)) {
17091         case 0:
17092                 /* we only have for events here if we don't have the header yet,
17093 @@ -1228,61 +1224,61 @@
17094                 return HANDLER_WAIT_FOR_EVENT;
17095         case -1:
17096                 if (errno == EINTR) return HANDLER_WAIT_FOR_EVENT;
17097 -               
17098 +
17099                 if (errno == ECHILD && con->file_started == 0) {
17100                         /*
17101 -                        * second round but still not response 
17102 +                        * second round but still not response
17103                          */
17104 -                       return HANDLER_WAIT_FOR_EVENT; 
17105 +                       return HANDLER_WAIT_FOR_EVENT;
17106                 }
17107 -               
17108 +
17109                 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
17110                 con->mode = DIRECT;
17111                 con->http_status = 500;
17112 -               
17113 +
17114                 hctx->pid = 0;
17115 -               
17116 +
17117                 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
17118                 fdevent_unregister(srv->ev, hctx->fd);
17119 -               
17120 +
17121                 if (close(hctx->fd)) {
17122                         log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
17123                 }
17124 -               
17125 +
17126                 cgi_handler_ctx_free(hctx);
17127 -               
17128 +
17129                 con->plugin_ctx[p->id] = NULL;
17130 -               
17131 +
17132                 return HANDLER_FINISHED;
17133         default:
17134 -               /* cgi process exited cleanly 
17135 -                * 
17136 -                * check if we already got the response 
17137 +               /* cgi process exited cleanly
17138 +                *
17139 +                * check if we already got the response
17140                  */
17141 -               
17142 +
17143                 if (!con->file_started) return HANDLER_WAIT_FOR_EVENT;
17144 -               
17145 +
17146                 if (WIFEXITED(status)) {
17147                         /* nothing */
17148                 } else {
17149                         log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
17150 -                       
17151 +
17152                         con->mode = DIRECT;
17153                         con->http_status = 500;
17154 -                       
17155 +
17156                 }
17157 -               
17158 +
17159                 hctx->pid = 0;
17160 -               
17161 +
17162                 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
17163                 fdevent_unregister(srv->ev, hctx->fd);
17164 -               
17165 +
17166                 if (close(hctx->fd)) {
17167                         log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
17168                 }
17169 -               
17170 +
17171                 cgi_handler_ctx_free(hctx);
17172 -               
17173 +
17174                 con->plugin_ctx[p->id] = NULL;
17175                 return HANDLER_FINISHED;
17176         }
17177 @@ -1306,8 +1302,8 @@
17178         p->init           = mod_cgi_init;
17179         p->cleanup        = mod_cgi_free;
17180         p->set_defaults   = mod_fastcgi_set_defaults;
17181 -       
17182 +
17183         p->data        = NULL;
17184 -       
17185 +
17186         return 0;
17187  }
17188 --- lighttpd-1.4.11/src/mod_cml.c       2006-01-30 13:51:48.000000000 +0200
17189 +++ lighttpd-1.4.12/src/mod_cml.c       2006-07-11 22:07:51.000000000 +0300
17190 @@ -4,7 +4,6 @@
17191  #include <stdlib.h>
17192  #include <string.h>
17193  #include <errno.h>
17194 -#include <unistd.h>
17195  #include <stdio.h>
17196  
17197  #include "buffer.h"
17198 @@ -20,50 +19,50 @@
17199  /* init the plugin data */
17200  INIT_FUNC(mod_cml_init) {
17201         plugin_data *p;
17202 -       
17203 +
17204         p = calloc(1, sizeof(*p));
17205 -       
17206 +
17207         p->basedir         = buffer_init();
17208         p->baseurl         = buffer_init();
17209         p->trigger_handler = buffer_init();
17210 -       
17211 +
17212         return p;
17213  }
17214  
17215  /* detroy the plugin data */
17216  FREE_FUNC(mod_cml_free) {
17217         plugin_data *p = p_d;
17218 -       
17219 +
17220         UNUSED(srv);
17221  
17222         if (!p) return HANDLER_GO_ON;
17223 -       
17224 +
17225         if (p->config_storage) {
17226                 size_t i;
17227                 for (i = 0; i < srv->config_context->used; i++) {
17228                         plugin_config *s = p->config_storage[i];
17229 -                       
17230 +
17231                         buffer_free(s->ext);
17232 -                       
17233 +
17234                         buffer_free(s->mc_namespace);
17235                         buffer_free(s->power_magnet);
17236                         array_free(s->mc_hosts);
17237 -                       
17238 +
17239  #if defined(HAVE_MEMCACHE_H)
17240                         if (s->mc) mc_free(s->mc);
17241  #endif
17242 -                       
17243 +
17244                         free(s);
17245                 }
17246                 free(p->config_storage);
17247         }
17248 -       
17249 +
17250         buffer_free(p->trigger_handler);
17251         buffer_free(p->basedir);
17252         buffer_free(p->baseurl);
17253 -       
17254 +
17255         free(p);
17256 -       
17257 +
17258         return HANDLER_GO_ON;
17259  }
17260  
17261 @@ -72,22 +71,22 @@
17262  SETDEFAULTS_FUNC(mod_cml_set_defaults) {
17263         plugin_data *p = p_d;
17264         size_t i = 0;
17265 -       
17266 -       config_values_t cv[] = { 
17267 +
17268 +       config_values_t cv[] = {
17269                 { "cml.extension",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
17270                 { "cml.memcache-hosts",         NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },        /* 1 */
17271                 { "cml.memcache-namespace",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
17272                 { "cml.power-magnet",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 3 */
17273                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
17274         };
17275 -       
17276 +
17277         if (!p) return HANDLER_ERROR;
17278 -       
17279 +
17280         p->config_storage = malloc(srv->config_context->used * sizeof(specific_config *));
17281 -       
17282 +
17283         for (i = 0; i < srv->config_context->used; i++) {
17284                 plugin_config *s;
17285 -               
17286 +
17287                 s = malloc(sizeof(plugin_config));
17288                 s->ext    = buffer_init();
17289                 s->mc_hosts       = array_init();
17290 @@ -96,87 +95,84 @@
17291  #if defined(HAVE_MEMCACHE_H)
17292                 s->mc = NULL;
17293  #endif
17294 -               
17295 +
17296                 cv[0].destination = s->ext;
17297                 cv[1].destination = s->mc_hosts;
17298                 cv[2].destination = s->mc_namespace;
17299                 cv[3].destination = s->power_magnet;
17300 -               
17301 +
17302                 p->config_storage[i] = s;
17303 -       
17304 +
17305                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
17306                         return HANDLER_ERROR;
17307                 }
17308 -               
17309 +
17310                 if (s->mc_hosts->used) {
17311  #if defined(HAVE_MEMCACHE_H)
17312                         size_t k;
17313                         s->mc = mc_new();
17314 -               
17315 +
17316                         for (k = 0; k < s->mc_hosts->used; k++) {
17317                                 data_string *ds = (data_string *)s->mc_hosts->data[k];
17318 -                               
17319 +
17320                                 if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
17321 -                                       log_error_write(srv, __FILE__, __LINE__, "sb", 
17322 -                                                       "connection to host failed:", 
17323 +                                       log_error_write(srv, __FILE__, __LINE__, "sb",
17324 +                                                       "connection to host failed:",
17325                                                         ds->value);
17326 -                                       
17327 +
17328                                         return HANDLER_ERROR;
17329                                 }
17330                         }
17331  #else
17332 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
17333 +                       log_error_write(srv, __FILE__, __LINE__, "s",
17334                                         "memcache support is not compiled in but cml.memcache-hosts is set, aborting");
17335                         return HANDLER_ERROR;
17336  #endif
17337                 }
17338         }
17339 -       
17340 +
17341         return HANDLER_GO_ON;
17342  }
17343  
17344 -#define PATCH(x) \
17345 -       p->conf.x = s->x;
17346  static int mod_cml_patch_connection(server *srv, connection *con, plugin_data *p) {
17347         size_t i, j;
17348         plugin_config *s = p->config_storage[0];
17349 -       
17350 -       PATCH(ext);
17351 +
17352 +       PATCH_OPTION(ext);
17353  #if defined(HAVE_MEMCACHE_H)
17354 -       PATCH(mc);
17355 +       PATCH_OPTION(mc);
17356  #endif
17357 -       PATCH(mc_namespace);
17358 -       PATCH(power_magnet);
17359 -       
17360 +       PATCH_OPTION(mc_namespace);
17361 +       PATCH_OPTION(power_magnet);
17362 +
17363         /* skip the first, the global context */
17364         for (i = 1; i < srv->config_context->used; i++) {
17365                 data_config *dc = (data_config *)srv->config_context->data[i];
17366                 s = p->config_storage[i];
17367 -               
17368 +
17369                 /* condition didn't match */
17370                 if (!config_check_cond(srv, con, dc)) continue;
17371 -               
17372 +
17373                 /* merge config */
17374                 for (j = 0; j < dc->value->used; j++) {
17375                         data_unset *du = dc->value->data[j];
17376 -                       
17377 +
17378                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.extension"))) {
17379 -                               PATCH(ext);
17380 +                               PATCH_OPTION(ext);
17381                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-hosts"))) {
17382  #if defined(HAVE_MEMCACHE_H)
17383 -                               PATCH(mc);
17384 +                               PATCH_OPTION(mc);
17385  #endif
17386                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-namespace"))) {
17387 -                               PATCH(mc_namespace);
17388 +                               PATCH_OPTION(mc_namespace);
17389                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.power-magnet"))) {
17390 -                               PATCH(power_magnet);
17391 +                               PATCH_OPTION(power_magnet);
17392                         }
17393                 }
17394         }
17395 -       
17396 +
17397         return 0;
17398  }
17399 -#undef PATCH
17400  
17401  int cache_call_lua(server *srv, connection *con, plugin_data *p, buffer *cml_file) {
17402         buffer *b;
17403 @@ -187,57 +183,57 @@
17404         b = p->baseurl;
17405         buffer_copy_string_buffer(b, con->uri.path);
17406         for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
17407 -       
17408 +
17409         if (*c == '/') {
17410                 b->used = c - b->ptr + 2;
17411                 *(c+1) = '\0';
17412         }
17413 -       
17414 +
17415         b = p->basedir;
17416         buffer_copy_string_buffer(b, con->physical.path);
17417         for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
17418 -       
17419 +
17420         if (*c == '/') {
17421                 b->used = c - b->ptr + 2;
17422                 *(c+1) = '\0';
17423         }
17424 -       
17425 +
17426  
17427         /* prepare variables
17428          *   - cookie-based
17429          *   - get-param-based
17430          */
17431 -       
17432 +
17433         return cache_parse_lua(srv, con, p, cml_file);
17434 -       
17435 +
17436  }
17437  
17438  URIHANDLER_FUNC(mod_cml_power_magnet) {
17439         plugin_data *p = p_d;
17440 -       
17441 +
17442         mod_cml_patch_connection(srv, con, p);
17443 -       
17444 +
17445         buffer_reset(p->basedir);
17446         buffer_reset(p->baseurl);
17447         buffer_reset(p->trigger_handler);
17448  
17449         if (buffer_is_empty(p->conf.power_magnet)) return HANDLER_GO_ON;
17450 -       
17451 -       /* 
17452 +
17453 +       /*
17454          * power-magnet:
17455          * cml.power-magnet = server.docroot + "/rewrite.cml"
17456          *
17457          * is called on EACH request, take the original REQUEST_URI and modifies the
17458 -        * request header as neccesary. 
17459 +        * request header as neccesary.
17460          *
17461          * First use:
17462          * if file_exists("/maintainance.html") {
17463          *   output_include = ( "/maintainance.html" )
17464 -        *   return CACHE_HIT 
17465 +        *   return CACHE_HIT
17466          * }
17467          *
17468          * as we only want to rewrite HTML like requests we should cover it in a conditional
17469 -        * 
17470 +        *
17471          * */
17472  
17473         switch(cache_call_lua(srv, con, p, p->conf.power_magnet)) {
17474 @@ -266,20 +262,20 @@
17475  
17476  URIHANDLER_FUNC(mod_cml_is_handled) {
17477         plugin_data *p = p_d;
17478 -       
17479 +
17480         if (buffer_is_empty(con->physical.path)) return HANDLER_ERROR;
17481 -       
17482 +
17483         mod_cml_patch_connection(srv, con, p);
17484 -       
17485 +
17486         buffer_reset(p->basedir);
17487         buffer_reset(p->baseurl);
17488         buffer_reset(p->trigger_handler);
17489  
17490         if (buffer_is_empty(p->conf.ext)) return HANDLER_GO_ON;
17491 -       
17492 +
17493         if (!buffer_is_equal_right_len(con->physical.path, p->conf.ext, p->conf.ext->used - 1)) {
17494                 return HANDLER_GO_ON;
17495 -       } 
17496 +       }
17497  
17498         switch(cache_call_lua(srv, con, p, con->physical.path)) {
17499         case -1:
17500 @@ -311,15 +307,15 @@
17501  int mod_cml_plugin_init(plugin *p) {
17502         p->version     = LIGHTTPD_VERSION_ID;
17503         p->name        = buffer_init_string("cache");
17504 -       
17505 +
17506         p->init        = mod_cml_init;
17507         p->cleanup     = mod_cml_free;
17508         p->set_defaults  = mod_cml_set_defaults;
17509 -       
17510 +
17511         p->handle_subrequest_start = mod_cml_is_handled;
17512         p->handle_physical         = mod_cml_power_magnet;
17513 -       
17514 +
17515         p->data        = NULL;
17516 -       
17517 +
17518         return 0;
17519  }
17520 --- lighttpd-1.4.11/src/mod_cml.h       2006-01-30 13:51:35.000000000 +0200
17521 +++ lighttpd-1.4.12/src/mod_cml.h       2006-07-11 22:07:51.000000000 +0300
17522 @@ -16,10 +16,10 @@
17523  
17524  typedef struct {
17525         buffer *ext;
17526 -       
17527 +
17528         array  *mc_hosts;
17529         buffer *mc_namespace;
17530 -#if defined(HAVE_MEMCACHE_H) 
17531 +#if defined(HAVE_MEMCACHE_H)
17532         struct memcache *mc;
17533  #endif
17534         buffer *power_magnet;
17535 @@ -27,15 +27,15 @@
17536  
17537  typedef struct {
17538         PLUGIN_DATA;
17539 -       
17540 +
17541         buffer *basedir;
17542         buffer *baseurl;
17543 -       
17544 +
17545         buffer *trigger_handler;
17546 -       
17547 +
17548         plugin_config **config_storage;
17549 -       
17550 -       plugin_config conf; 
17551 +
17552 +       plugin_config conf;
17553  } plugin_data;
17554  
17555  int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn);
17556 --- lighttpd-1.4.11/src/mod_cml_funcs.c 2005-11-17 16:15:08.000000000 +0200
17557 +++ lighttpd-1.4.12/src/mod_cml_funcs.c 2006-07-11 22:07:52.000000000 +0300
17558 @@ -4,8 +4,7 @@
17559  #include <stdlib.h>
17560  #include <string.h>
17561  #include <errno.h>
17562 -#include <unistd.h>
17563 -#include <dirent.h>
17564 +
17565  #include <stdio.h>
17566  
17567  #include "buffer.h"
17568 @@ -13,6 +12,7 @@
17569  #include "log.h"
17570  #include "plugin.h"
17571  #include "response.h"
17572 +#include "sys-files.h"
17573  
17574  #include "mod_cml.h"
17575  #include "mod_cml_funcs.h"
17576 @@ -30,7 +30,7 @@
17577  #ifdef USE_OPENSSL
17578  #define IN const
17579  #else
17580 -#define IN 
17581 +#define IN
17582  #endif
17583  #define OUT
17584  
17585 @@ -42,29 +42,29 @@
17586         buffer b;
17587         char hex[33];
17588         int n = lua_gettop(L);
17589 -       
17590 +
17591         b.ptr = hex;
17592         b.used = 0;
17593         b.size = sizeof(hex);
17594 -       
17595 +
17596         if (n != 1) {
17597                 lua_pushstring(L, "md5: expected one argument");
17598                 lua_error(L);
17599         }
17600 -       
17601 +
17602         if (!lua_isstring(L, 1)) {
17603                 lua_pushstring(L, "md5: argument has to be a string");
17604                 lua_error(L);
17605         }
17606 -       
17607 +
17608         MD5_Init(&Md5Ctx);
17609         MD5_Update(&Md5Ctx, (unsigned char *)lua_tostring(L, 1), lua_strlen(L, 1));
17610         MD5_Final(HA1, &Md5Ctx);
17611 -       
17612 +
17613         buffer_copy_string_hex(&b, (char *)HA1, 16);
17614 -       
17615 +
17616         lua_pushstring(L, b.ptr);
17617 -       
17618 +
17619         return 1;
17620  }
17621  
17622 @@ -72,37 +72,37 @@
17623  int f_file_mtime(lua_State *L) {
17624         struct stat st;
17625         int n = lua_gettop(L);
17626 -       
17627 +
17628         if (n != 1) {
17629                 lua_pushstring(L, "file_mtime: expected one argument");
17630                 lua_error(L);
17631         }
17632 -       
17633 +
17634         if (!lua_isstring(L, 1)) {
17635                 lua_pushstring(L, "file_mtime: argument has to be a string");
17636                 lua_error(L);
17637         }
17638 -       
17639 +
17640         if (-1 == stat(lua_tostring(L, 1), &st)) {
17641                 lua_pushnil(L);
17642                 return 1;
17643         }
17644 -       
17645 +
17646         lua_pushnumber(L, st.st_mtime);
17647 -       
17648 +
17649         return 1;
17650  }
17651 -
17652 +#ifndef _WIN32
17653  int f_dir_files_iter(lua_State *L) {
17654         DIR *d;
17655         struct dirent *de;
17656 -       
17657 +
17658         d = lua_touserdata(L, lua_upvalueindex(1));
17659 -       
17660 +
17661         if (NULL == (de = readdir(d))) {
17662                 /* EOF */
17663                 closedir(d);
17664 -               
17665 +
17666                 return 0;
17667         } else {
17668                 lua_pushstring(L, de->d_name);
17669 @@ -113,75 +113,75 @@
17670  int f_dir_files(lua_State *L) {
17671         DIR *d;
17672         int n = lua_gettop(L);
17673 -       
17674 +
17675         if (n != 1) {
17676                 lua_pushstring(L, "dir_files: expected one argument");
17677                 lua_error(L);
17678         }
17679 -       
17680 +
17681         if (!lua_isstring(L, 1)) {
17682                 lua_pushstring(L, "dir_files: argument has to be a string");
17683                 lua_error(L);
17684         }
17685 -       
17686 -       /* check if there is a valid DIR handle on the stack */ 
17687 +
17688 +       /* check if there is a valid DIR handle on the stack */
17689         if (NULL == (d = opendir(lua_tostring(L, 1)))) {
17690                 lua_pushnil(L);
17691                 return 1;
17692         }
17693 -       
17694 +
17695         /* push d into registry */
17696         lua_pushlightuserdata(L, d);
17697         lua_pushcclosure(L, f_dir_files_iter, 1);
17698 -       
17699 +
17700         return 1;
17701  }
17702 -
17703 +#endif
17704  int f_file_isreg(lua_State *L) {
17705         struct stat st;
17706         int n = lua_gettop(L);
17707 -       
17708 +
17709         if (n != 1) {
17710                 lua_pushstring(L, "file_isreg: expected one argument");
17711                 lua_error(L);
17712         }
17713 -       
17714 +
17715         if (!lua_isstring(L, 1)) {
17716                 lua_pushstring(L, "file_isreg: argument has to be a string");
17717                 lua_error(L);
17718         }
17719 -       
17720 +
17721         if (-1 == stat(lua_tostring(L, 1), &st)) {
17722                 lua_pushnil(L);
17723                 return 1;
17724         }
17725 -       
17726 +
17727         lua_pushnumber(L, S_ISREG(st.st_mode));
17728 -       
17729 +
17730         return 1;
17731  }
17732  
17733  int f_file_isdir(lua_State *L) {
17734         struct stat st;
17735         int n = lua_gettop(L);
17736 -       
17737 +
17738         if (n != 1) {
17739                 lua_pushstring(L, "file_isreg: expected one argument");
17740                 lua_error(L);
17741         }
17742 -       
17743 +
17744         if (!lua_isstring(L, 1)) {
17745                 lua_pushstring(L, "file_isreg: argument has to be a string");
17746                 lua_error(L);
17747         }
17748 -       
17749 +
17750         if (-1 == stat(lua_tostring(L, 1), &st)) {
17751                 lua_pushnil(L);
17752                 return 1;
17753         }
17754 -       
17755 +
17756         lua_pushnumber(L, S_ISDIR(st.st_mode));
17757 -       
17758 +
17759         return 1;
17760  }
17761  
17762 @@ -192,33 +192,33 @@
17763         char *r;
17764         int n = lua_gettop(L);
17765         struct memcache *mc;
17766 -       
17767 +
17768         if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17769                 lua_pushstring(L, "where is my userdata ?");
17770                 lua_error(L);
17771         }
17772 -       
17773 +
17774         mc = lua_touserdata(L, lua_upvalueindex(1));
17775 -       
17776 +
17777         if (n != 1) {
17778                 lua_pushstring(L, "expected one argument");
17779                 lua_error(L);
17780         }
17781 -       
17782 +
17783         if (!lua_isstring(L, 1)) {
17784                 lua_pushstring(L, "argument has to be a string");
17785                 lua_error(L);
17786         }
17787 -       
17788 -       if (NULL == (r = mc_aget(mc, 
17789 +
17790 +       if (NULL == (r = mc_aget(mc,
17791                                  lua_tostring(L, 1), lua_strlen(L, 1)))) {
17792 -                               
17793 +
17794                 lua_pushboolean(L, 0);
17795                 return 1;
17796         }
17797 -       
17798 +
17799         free(r);
17800 -       
17801 +
17802         lua_pushboolean(L, 1);
17803         return 1;
17804  }
17805 @@ -226,74 +226,74 @@
17806  int f_memcache_get_string(lua_State *L) {
17807         char *r;
17808         int n = lua_gettop(L);
17809 -       
17810 +
17811         struct memcache *mc;
17812 -       
17813 +
17814         if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17815                 lua_pushstring(L, "where is my userdata ?");
17816                 lua_error(L);
17817         }
17818 -       
17819 +
17820         mc = lua_touserdata(L, lua_upvalueindex(1));
17821 -       
17822 -       
17823 +
17824 +
17825         if (n != 1) {
17826                 lua_pushstring(L, "expected one argument");
17827                 lua_error(L);
17828         }
17829 -       
17830 +
17831         if (!lua_isstring(L, 1)) {
17832                 lua_pushstring(L, "argument has to be a string");
17833                 lua_error(L);
17834         }
17835 -       
17836 -       if (NULL == (r = mc_aget(mc, 
17837 +
17838 +       if (NULL == (r = mc_aget(mc,
17839                                  lua_tostring(L, 1), lua_strlen(L, 1)))) {
17840                 lua_pushnil(L);
17841                 return 1;
17842         }
17843 -       
17844 +
17845         lua_pushstring(L, r);
17846 -       
17847 +
17848         free(r);
17849 -       
17850 +
17851         return 1;
17852  }
17853  
17854  int f_memcache_get_long(lua_State *L) {
17855         char *r;
17856         int n = lua_gettop(L);
17857 -       
17858 +
17859         struct memcache *mc;
17860 -       
17861 +
17862         if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17863                 lua_pushstring(L, "where is my userdata ?");
17864                 lua_error(L);
17865         }
17866 -       
17867 +
17868         mc = lua_touserdata(L, lua_upvalueindex(1));
17869 -       
17870 -       
17871 +
17872 +
17873         if (n != 1) {
17874                 lua_pushstring(L, "expected one argument");
17875                 lua_error(L);
17876         }
17877 -       
17878 +
17879         if (!lua_isstring(L, 1)) {
17880                 lua_pushstring(L, "argument has to be a string");
17881                 lua_error(L);
17882         }
17883 -       
17884 -       if (NULL == (r = mc_aget(mc, 
17885 +
17886 +       if (NULL == (r = mc_aget(mc,
17887                                  lua_tostring(L, 1), lua_strlen(L, 1)))) {
17888                 lua_pushnil(L);
17889                 return 1;
17890         }
17891 -       
17892 +
17893         lua_pushnumber(L, strtol(r, NULL, 10));
17894 -       
17895 +
17896         free(r);
17897 -       
17898 +
17899         return 1;
17900  }
17901  #endif
17902 --- lighttpd-1.4.11/src/mod_cml_lua.c   2006-01-30 13:56:40.000000000 +0200
17903 +++ lighttpd-1.4.12/src/mod_cml_lua.c   2006-07-11 22:07:53.000000000 +0300
17904 @@ -23,7 +23,7 @@
17905  #ifdef USE_OPENSSL
17906  #define IN const
17907  #else
17908 -#define IN 
17909 +#define IN
17910  #endif
17911  #define OUT
17912  
17913 @@ -31,6 +31,7 @@
17914  
17915  #include <lua.h>
17916  #include <lualib.h>
17917 +#include <lauxlib.h>
17918  
17919  typedef struct {
17920         stream st;
17921 @@ -39,11 +40,11 @@
17922  
17923  static const char * load_file(lua_State *L, void *data, size_t *size) {
17924         readme *rm = data;
17925 -       
17926 +
17927         UNUSED(L);
17928 -       
17929 +
17930         if (rm->done) return 0;
17931 -       
17932 +
17933         *size = rm->st.size;
17934         rm->done = 1;
17935         return rm->st.start;
17936 @@ -51,47 +52,47 @@
17937  
17938  static int lua_to_c_get_string(lua_State *L, const char *varname, buffer *b) {
17939         int curelem;
17940 -       
17941 +
17942         lua_pushstring(L, varname);
17943 -       
17944 +
17945         curelem = lua_gettop(L);
17946         lua_gettable(L, LUA_GLOBALSINDEX);
17947 -       
17948 +
17949         /* it should be a table */
17950         if (!lua_isstring(L, curelem)) {
17951                 lua_settop(L, curelem - 1);
17952 -               
17953 +
17954                 return -1;
17955         }
17956 -       
17957 +
17958         buffer_copy_string(b, lua_tostring(L, curelem));
17959 -       
17960 +
17961         lua_pop(L, 1);
17962 -       
17963 +
17964         assert(curelem - 1 == lua_gettop(L));
17965 -       
17966 +
17967         return 0;
17968  }
17969  
17970  static int lua_to_c_is_table(lua_State *L, const char *varname) {
17971         int curelem;
17972 -       
17973 +
17974         lua_pushstring(L, varname);
17975 -       
17976 +
17977         curelem = lua_gettop(L);
17978         lua_gettable(L, LUA_GLOBALSINDEX);
17979 -       
17980 +
17981         /* it should be a table */
17982         if (!lua_istable(L, curelem)) {
17983                 lua_settop(L, curelem - 1);
17984 -               
17985 +
17986                 return 0;
17987         }
17988 -       
17989 +
17990         lua_settop(L, curelem - 1);
17991 -       
17992 +
17993         assert(curelem - 1 == lua_gettop(L));
17994 -       
17995 +
17996         return 1;
17997  }
17998  
17999 @@ -99,7 +100,7 @@
18000         lua_pushlstring(L, key, key_len);
18001         lua_pushlstring(L, val, val_len);
18002         lua_settable(L, tbl);
18003 -       
18004 +
18005         return 0;
18006  }
18007  
18008 @@ -108,21 +109,21 @@
18009         size_t is_key = 1;
18010         size_t i;
18011         char *key = NULL, *val = NULL;
18012 -       
18013 +
18014         key = qrystr->ptr;
18015 -       
18016 +
18017         /* we need the \0 */
18018         for (i = 0; i < qrystr->used; i++) {
18019                 switch(qrystr->ptr[i]) {
18020                 case '=':
18021                         if (is_key) {
18022                                 val = qrystr->ptr + i + 1;
18023 -                               
18024 +
18025                                 qrystr->ptr[i] = '\0';
18026 -                               
18027 +
18028                                 is_key = 0;
18029                         }
18030 -                       
18031 +
18032                         break;
18033                 case '&':
18034                 case '\0': /* fin symbol */
18035 @@ -131,19 +132,19 @@
18036  
18037                                 /* terminate the value */
18038                                 qrystr->ptr[i] = '\0';
18039 -                               
18040 -                               c_to_lua_push(L, tbl, 
18041 +
18042 +                               c_to_lua_push(L, tbl,
18043                                               key, strlen(key),
18044                                               val, strlen(val));
18045                         }
18046 -                       
18047 +
18048                         key = qrystr->ptr + i + 1;
18049                         val = NULL;
18050                         is_key = 1;
18051                         break;
18052                 }
18053         }
18054 -       
18055 +
18056         return 0;
18057  }
18058  #if 0
18059 @@ -151,21 +152,21 @@
18060         data_unset *d;
18061  
18062         UNUSED(srv);
18063 -       
18064 +
18065         if (NULL != (d = array_get_element(con->request.headers, "Cookie"))) {
18066                 data_string *ds = (data_string *)d;
18067                 size_t key = 0, value = 0;
18068                 size_t is_key = 1, is_sid = 0;
18069                 size_t i;
18070 -               
18071 +
18072                 /* found COOKIE */
18073                 if (!DATA_IS_STRING(d)) return -1;
18074                 if (ds->value->used == 0) return -1;
18075 -                       
18076 +
18077                 if (ds->value->ptr[0] == '\0' ||
18078                     ds->value->ptr[0] == '=' ||
18079                     ds->value->ptr[0] == ';') return -1;
18080 -               
18081 +
18082                 buffer_reset(p->session_id);
18083                 for (i = 0; i < ds->value->used; i++) {
18084                         switch(ds->value->ptr[i]) {
18085 @@ -176,16 +177,16 @@
18086                                                 is_sid = 1;
18087                                         }
18088                                         value = i + 1;
18089 -                               
18090 +
18091                                         is_key = 0;
18092                                 }
18093 -                               
18094 +
18095                                 break;
18096                         case ';':
18097                                 if (is_sid) {
18098                                         buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);
18099                                 }
18100 -                               
18101 +
18102                                 is_sid = 0;
18103                                 key = i + 1;
18104                                 value = 0;
18105 @@ -204,48 +205,43 @@
18106                         }
18107                 }
18108         }
18109 -       
18110 +
18111         return 0;
18112  }
18113  #endif
18114  
18115  int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) {
18116 -       lua_State *L; 
18117 +       lua_State *L;
18118         readme rm;
18119         int ret = -1;
18120         buffer *b = buffer_init();
18121         int header_tbl = 0;
18122 -       
18123 +
18124         rm.done = 0;
18125         stream_open(&rm.st, fn);
18126 -       
18127 +
18128         /* push the lua file to the interpreter and see what happends */
18129 -       L = lua_open();
18130 -       
18131 -       luaopen_base(L);
18132 -       luaopen_table(L);
18133 -       luaopen_string(L);
18134 -       luaopen_math(L);
18135 -       luaopen_io(L);
18136 -       
18137 +       L = luaL_newstate();
18138 +       luaL_openlibs(L);
18139 +
18140         /* register functions */
18141         lua_register(L, "md5", f_crypto_md5);
18142         lua_register(L, "file_mtime", f_file_mtime);
18143         lua_register(L, "file_isreg", f_file_isreg);
18144         lua_register(L, "file_isdir", f_file_isreg);
18145         lua_register(L, "dir_files", f_dir_files);
18146 -       
18147 +
18148  #ifdef HAVE_MEMCACHE_H
18149         lua_pushliteral(L, "memcache_get_long");
18150         lua_pushlightuserdata(L, p->conf.mc);
18151         lua_pushcclosure(L, f_memcache_get_long, 1);
18152         lua_settable(L, LUA_GLOBALSINDEX);
18153 -       
18154 +
18155         lua_pushliteral(L, "memcache_get_string");
18156         lua_pushlightuserdata(L, p->conf.mc);
18157         lua_pushcclosure(L, f_memcache_get_string, 1);
18158         lua_settable(L, LUA_GLOBALSINDEX);
18159 -       
18160 +
18161         lua_pushliteral(L, "memcache_exists");
18162         lua_pushlightuserdata(L, p->conf.mc);
18163         lua_pushcclosure(L, f_memcache_exists, 1);
18164 @@ -255,11 +251,11 @@
18165         lua_pushliteral(L, "request");
18166         lua_newtable(L);
18167         lua_settable(L, LUA_GLOBALSINDEX);
18168 -       
18169 +
18170         lua_pushliteral(L, "request");
18171         header_tbl = lua_gettop(L);
18172         lua_gettable(L, LUA_GLOBALSINDEX);
18173 -       
18174 +
18175         c_to_lua_push(L, header_tbl, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
18176         c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
18177         c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
18178 @@ -267,84 +263,84 @@
18179         if (!buffer_is_empty(con->request.pathinfo)) {
18180                 c_to_lua_push(L, header_tbl, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
18181         }
18182 -       
18183 +
18184         c_to_lua_push(L, header_tbl, CONST_STR_LEN("CWD"), CONST_BUF_LEN(p->basedir));
18185         c_to_lua_push(L, header_tbl, CONST_STR_LEN("BASEURL"), CONST_BUF_LEN(p->baseurl));
18186 -       
18187 +
18188         /* register GET parameter */
18189         lua_pushliteral(L, "get");
18190         lua_newtable(L);
18191         lua_settable(L, LUA_GLOBALSINDEX);
18192 -       
18193 +
18194         lua_pushliteral(L, "get");
18195         header_tbl = lua_gettop(L);
18196         lua_gettable(L, LUA_GLOBALSINDEX);
18197 -       
18198 +
18199         buffer_copy_string_buffer(b, con->uri.query);
18200         cache_export_get_params(L, header_tbl, b);
18201         buffer_reset(b);
18202  
18203 -       /* 2 default constants */       
18204 +       /* 2 default constants */
18205         lua_pushliteral(L, "CACHE_HIT");
18206         lua_pushboolean(L, 0);
18207         lua_settable(L, LUA_GLOBALSINDEX);
18208 -       
18209 +
18210         lua_pushliteral(L, "CACHE_MISS");
18211         lua_pushboolean(L, 1);
18212         lua_settable(L, LUA_GLOBALSINDEX);
18213 -       
18214 +
18215         /* load lua program */
18216         if (lua_load(L, load_file, &rm, fn->ptr) || lua_pcall(L,0,1,0)) {
18217                 log_error_write(srv, __FILE__, __LINE__, "s",
18218                                 lua_tostring(L,-1));
18219 -               
18220 +
18221                 goto error;
18222         }
18223 -       
18224 +
18225         /* get return value */
18226         ret = (int)lua_tonumber(L, -1);
18227         lua_pop(L, 1);
18228 -       
18229 -       /* fetch the data from lua */ 
18230 +
18231 +       /* fetch the data from lua */
18232         lua_to_c_get_string(L, "trigger_handler", p->trigger_handler);
18233 -       
18234 +
18235         if (0 == lua_to_c_get_string(L, "output_contenttype", b)) {
18236                 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(b));
18237         }
18238 -       
18239 +
18240         if (ret == 0) {
18241                 /* up to now it is a cache-hit, check if all files exist */
18242 -               
18243 +
18244                 int curelem;
18245                 time_t mtime = 0;
18246 -       
18247 +
18248                 if (!lua_to_c_is_table(L, "output_include")) {
18249                         log_error_write(srv, __FILE__, __LINE__, "s",
18250                                 "output_include is missing or not a table");
18251                         ret = -1;
18252 -               
18253 +
18254                         goto error;
18255                 }
18256 -               
18257 +
18258                 lua_pushstring(L, "output_include");
18259 -               
18260 +
18261                 curelem = lua_gettop(L);
18262                 lua_gettable(L, LUA_GLOBALSINDEX);
18263  
18264                 /* HOW-TO build a etag ?
18265 -                * as we don't just have one file we have to take the stat() 
18266 +                * as we don't just have one file we have to take the stat()
18267                  * from all base files, merge them and build the etag from
18268                  * it later.
18269 -                * 
18270 +                *
18271                  * The mtime of the content is the mtime of the freshest base file
18272 -                * 
18273 +                *
18274                  * */
18275 -               
18276 +
18277                 lua_pushnil(L);  /* first key */
18278                 while (lua_next(L, curelem) != 0) {
18279                         stat_cache_entry *sce = NULL;
18280                         /* key' is at index -2 and value' at index -1 */
18281 -                       
18282 +
18283                         if (lua_isstring(L, -1)) {
18284                                 const char *s = lua_tostring(L, -1);
18285  
18286 @@ -364,18 +360,18 @@
18287                                                 /* a file is missing, call the handler to generate it */
18288                                                 if (!buffer_is_empty(p->trigger_handler)) {
18289                                                         ret = 1; /* cache-miss */
18290 -                                                       
18291 +
18292                                                         log_error_write(srv, __FILE__, __LINE__, "s",
18293                                                                         "a file is missing, calling handler");
18294 -                                                       
18295 +
18296                                                         break;
18297                                                 } else {
18298                                                         /* handler not set -> 500 */
18299                                                         ret = -1;
18300 -                                                       
18301 +
18302                                                         log_error_write(srv, __FILE__, __LINE__, "s",
18303                                                                         "a file missing and no handler set");
18304 -                                                       
18305 +
18306                                                         break;
18307                                                 }
18308                                                 break;
18309 @@ -393,12 +389,12 @@
18310                                                 "not a string");
18311                                 break;
18312                         }
18313 -               
18314 +
18315                         lua_pop(L, 1);  /* removes value'; keeps key' for next iteration */
18316                 }
18317 -               
18318 +
18319                 lua_settop(L, curelem - 1);
18320 -               
18321 +
18322                 if (ret == 0) {
18323                         data_string *ds;
18324                         char timebuf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
18325 @@ -410,9 +406,9 @@
18326  
18327                         /* no Last-Modified specified */
18328                         if ((mtime) && (NULL == ds)) {
18329 -               
18330 +
18331                                 strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&mtime));
18332 -                               
18333 +
18334                                 response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), timebuf, sizeof(timebuf) - 1);
18335  
18336  
18337 @@ -428,9 +424,9 @@
18338                                 tbuf.used = 0;
18339                                 tbuf.ptr = NULL;
18340                         }
18341 -                       
18342 +
18343                         if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, &tbuf)) {
18344 -                               /* ok, the client already has our content, 
18345 +                               /* ok, the client already has our content,
18346                                  * no need to send it again */
18347  
18348                                 chunkqueue_reset(con->write_queue);
18349 @@ -440,24 +436,24 @@
18350                         chunkqueue_reset(con->write_queue);
18351                 }
18352         }
18353 -       
18354 +
18355         if (ret == 1 && !buffer_is_empty(p->trigger_handler)) {
18356                 /* cache-miss */
18357                 buffer_copy_string_buffer(con->uri.path, p->baseurl);
18358                 buffer_append_string_buffer(con->uri.path, p->trigger_handler);
18359 -       
18360 +
18361                 buffer_copy_string_buffer(con->physical.path, p->basedir);
18362                 buffer_append_string_buffer(con->physical.path, p->trigger_handler);
18363 -               
18364 +
18365                 chunkqueue_reset(con->write_queue);
18366         }
18367 -       
18368 +
18369  error:
18370         lua_close(L);
18371 -       
18372 +
18373         stream_close(&rm.st);
18374         buffer_free(b);
18375 -       
18376 +
18377         return ret /* cache-error */;
18378  }
18379  #else
18380 --- lighttpd-1.4.11/src/mod_compress.c  2005-11-18 13:49:14.000000000 +0200
18381 +++ lighttpd-1.4.12/src/mod_compress.c  2006-07-11 22:07:53.000000000 +0300
18382 @@ -2,7 +2,6 @@
18383  #include <sys/stat.h>
18384  
18385  #include <fcntl.h>
18386 -#include <unistd.h>
18387  #include <ctype.h>
18388  #include <stdlib.h>
18389  #include <string.h>
18390 @@ -14,6 +13,7 @@
18391  #include "buffer.h"
18392  #include "response.h"
18393  #include "stat_cache.h"
18394 +#include "http_chunk.h"
18395  
18396  #include "plugin.h"
18397  
18398 @@ -33,6 +33,7 @@
18399  #endif
18400  
18401  #include "sys-mmap.h"
18402 +#include "sys-files.h"
18403  
18404  /* request: accept-encoding */
18405  #define HTTP_ACCEPT_ENCODING_IDENTITY BV(0)
18406 @@ -55,97 +56,127 @@
18407         PLUGIN_DATA;
18408         buffer *ofn;
18409         buffer *b;
18410 -       
18411 +
18412         plugin_config **config_storage;
18413 -       plugin_config conf; 
18414 +       plugin_config conf;
18415  } plugin_data;
18416  
18417  INIT_FUNC(mod_compress_init) {
18418         plugin_data *p;
18419 -       
18420 +
18421         p = calloc(1, sizeof(*p));
18422 -       
18423 +
18424         p->ofn = buffer_init();
18425         p->b = buffer_init();
18426 -       
18427 +
18428         return p;
18429  }
18430  
18431  FREE_FUNC(mod_compress_free) {
18432         plugin_data *p = p_d;
18433 -       
18434 +
18435         UNUSED(srv);
18436  
18437         if (!p) return HANDLER_GO_ON;
18438 -       
18439 +
18440         buffer_free(p->ofn);
18441         buffer_free(p->b);
18442 -       
18443 +
18444         if (p->config_storage) {
18445                 size_t i;
18446                 for (i = 0; i < srv->config_context->used; i++) {
18447                         plugin_config *s = p->config_storage[i];
18448  
18449                         if (!s) continue;
18450 -                       
18451 +
18452                         array_free(s->compress);
18453                         buffer_free(s->compress_cache_dir);
18454 -                       
18455 +
18456                         free(s);
18457                 }
18458                 free(p->config_storage);
18459         }
18460 -       
18461 -       
18462 +
18463 +
18464         free(p);
18465 -       
18466 +
18467         return HANDLER_GO_ON;
18468  }
18469  
18470 +void mkdir_recursive(const char *dir) {
18471 +
18472 +       char dir_copy[256];
18473 +       char *p = dir_copy;
18474 +
18475 +       if (!dir || !dir[0])
18476 +               return;
18477 +
18478 +       strncpy(dir_copy, dir, sizeof(dir_copy) / sizeof(dir_copy[0]));
18479 +
18480 +       while ((p = strchr(p + 1, '/')) != NULL) {
18481 +
18482 +               *p = '\0';
18483 +               if ((mkdir(dir_copy, 0700) != 0) && (errno != EEXIST))
18484 +                       return;
18485 +
18486 +               *p++ = '/';
18487 +       }
18488 +
18489 +       mkdir(dir, 0700);
18490 +}
18491 +
18492  SETDEFAULTS_FUNC(mod_compress_setdefaults) {
18493         plugin_data *p = p_d;
18494         size_t i = 0;
18495 -       
18496 -       config_values_t cv[] = { 
18497 +
18498 +       config_values_t cv[] = {
18499                 { "compress.cache-dir",             NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
18500                 { "compress.filetype",              NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
18501                 { "compress.max-filesize",          NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
18502                 { NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
18503         };
18504 -       
18505 +
18506         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
18507 -       
18508 +
18509         for (i = 0; i < srv->config_context->used; i++) {
18510                 plugin_config *s;
18511 -               
18512 +
18513                 s = calloc(1, sizeof(plugin_config));
18514                 s->compress_cache_dir = buffer_init();
18515                 s->compress = array_init();
18516                 s->compress_max_filesize = 0;
18517 -               
18518 +
18519                 cv[0].destination = s->compress_cache_dir;
18520                 cv[1].destination = s->compress;
18521                 cv[2].destination = &(s->compress_max_filesize);
18522 -               
18523 +
18524                 p->config_storage[i] = s;
18525 -       
18526 +
18527                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
18528                         return HANDLER_ERROR;
18529                 }
18530 -               
18531 +
18532                 if (!buffer_is_empty(s->compress_cache_dir)) {
18533                         struct stat st;
18534                         if (0 != stat(s->compress_cache_dir->ptr, &st)) {
18535 -                               log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir", 
18536 +
18537 +                               log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, attempting to create",
18538                                                 s->compress_cache_dir, strerror(errno));
18539 -                               
18540 -                               return HANDLER_ERROR;
18541 +                               mkdir_recursive(s->compress_cache_dir->ptr);
18542 +
18543 +                               if (0 != stat(s->compress_cache_dir->ptr, &st)) {
18544 +
18545 +                                       log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, create failed",
18546 +                                                                       s->compress_cache_dir, strerror(errno));
18547 +
18548 +                                       return HANDLER_ERROR;
18549 +                               }
18550                         }
18551                 }
18552         }
18553 -       
18554 +
18555         return HANDLER_GO_ON;
18556 -       
18557 +
18558  }
18559  
18560  #ifdef USE_ZLIB
18561 @@ -153,32 +184,32 @@
18562         unsigned char *c;
18563         unsigned long crc;
18564         z_stream z;
18565 -       
18566 +
18567         UNUSED(srv);
18568         UNUSED(con);
18569  
18570         z.zalloc = Z_NULL;
18571         z.zfree = Z_NULL;
18572         z.opaque = Z_NULL;
18573 -       
18574 -       if (Z_OK != deflateInit2(&z, 
18575 +
18576 +       if (Z_OK != deflateInit2(&z,
18577                                  Z_DEFAULT_COMPRESSION,
18578 -                                Z_DEFLATED, 
18579 +                                Z_DEFLATED,
18580                                  -MAX_WBITS,  /* supress zlib-header */
18581                                  8,
18582                                  Z_DEFAULT_STRATEGY)) {
18583                 return -1;
18584         }
18585 -               
18586 +
18587         z.next_in = (unsigned char *)start;
18588         z.avail_in = st_size;
18589         z.total_in = 0;
18590 -               
18591 -                       
18592 +
18593 +
18594         buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12 + 18);
18595 -               
18596 +
18597         /* write gzip header */
18598 -               
18599 +
18600         c = (unsigned char *)p->b->ptr;
18601         c[0] = 0x1f;
18602         c[1] = 0x8b;
18603 @@ -190,24 +221,24 @@
18604         c[7] = (mtime >> 24) & 0xff;
18605         c[8] = 0x00; /* extra flags */
18606         c[9] = 0x03; /* UNIX */
18607 -       
18608 +
18609         p->b->used = 10;
18610         z.next_out = (unsigned char *)p->b->ptr + p->b->used;
18611         z.avail_out = p->b->size - p->b->used - 8;
18612         z.total_out = 0;
18613 -       
18614 +
18615         if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
18616                 deflateEnd(&z);
18617                 return -1;
18618         }
18619 -       
18620 +
18621         /* trailer */
18622         p->b->used += z.total_out;
18623 -       
18624 +
18625         crc = generate_crc32c(start, st_size);
18626 -               
18627 +
18628         c = (unsigned char *)p->b->ptr + p->b->used;
18629 -               
18630 +
18631         c[0] = (crc >>  0) & 0xff;
18632         c[1] = (crc >>  8) & 0xff;
18633         c[2] = (crc >> 16) & 0xff;
18634 @@ -221,51 +252,51 @@
18635         if (Z_OK != deflateEnd(&z)) {
18636                 return -1;
18637         }
18638 -       
18639 +
18640         return 0;
18641  }
18642  
18643  static int deflate_file_to_buffer_deflate(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
18644         z_stream z;
18645 -       
18646 +
18647         UNUSED(srv);
18648         UNUSED(con);
18649  
18650         z.zalloc = Z_NULL;
18651         z.zfree = Z_NULL;
18652         z.opaque = Z_NULL;
18653 -       
18654 -       if (Z_OK != deflateInit2(&z, 
18655 +
18656 +       if (Z_OK != deflateInit2(&z,
18657                                  Z_DEFAULT_COMPRESSION,
18658 -                                Z_DEFLATED, 
18659 +                                Z_DEFLATED,
18660                                  -MAX_WBITS,  /* supress zlib-header */
18661                                  8,
18662                                  Z_DEFAULT_STRATEGY)) {
18663                 return -1;
18664         }
18665 -               
18666 +
18667         z.next_in = start;
18668         z.avail_in = st_size;
18669         z.total_in = 0;
18670 -               
18671 +
18672         buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12);
18673 -       
18674 +
18675         z.next_out = (unsigned char *)p->b->ptr;
18676         z.avail_out = p->b->size;
18677         z.total_out = 0;
18678 -       
18679 +
18680         if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
18681                 deflateEnd(&z);
18682                 return -1;
18683         }
18684 -       
18685 +
18686         /* trailer */
18687         p->b->used += z.total_out;
18688 -       
18689 +
18690         if (Z_OK != deflateEnd(&z)) {
18691                 return -1;
18692         }
18693 -       
18694 +
18695         return 0;
18696  }
18697  
18698 @@ -274,48 +305,48 @@
18699  #ifdef USE_BZ2LIB
18700  static int deflate_file_to_buffer_bzip2(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
18701         bz_stream bz;
18702 -       
18703 +
18704         UNUSED(srv);
18705         UNUSED(con);
18706  
18707         bz.bzalloc = NULL;
18708         bz.bzfree = NULL;
18709         bz.opaque = NULL;
18710 -       
18711 -       if (BZ_OK != BZ2_bzCompressInit(&bz, 
18712 +
18713 +       if (BZ_OK != BZ2_bzCompressInit(&bz,
18714                                         9, /* blocksize = 900k */
18715                                         0, /* no output */
18716                                         0)) { /* workFactor: default */
18717                 return -1;
18718         }
18719 -               
18720 +
18721         bz.next_in = (char *)start;
18722         bz.avail_in = st_size;
18723         bz.total_in_lo32 = 0;
18724         bz.total_in_hi32 = 0;
18725 -               
18726 +
18727         buffer_prepare_copy(p->b, (bz.avail_in * 1.1) + 12);
18728 -       
18729 +
18730         bz.next_out = p->b->ptr;
18731         bz.avail_out = p->b->size;
18732         bz.total_out_lo32 = 0;
18733         bz.total_out_hi32 = 0;
18734 -       
18735 +
18736         if (BZ_STREAM_END != BZ2_bzCompress(&bz, BZ_FINISH)) {
18737                 BZ2_bzCompressEnd(&bz);
18738                 return -1;
18739         }
18740 -       
18741 +
18742         /* file is too large for now */
18743         if (bz.total_out_hi32) return -1;
18744 -       
18745 +
18746         /* trailer */
18747         p->b->used = bz.total_out_lo32;
18748 -       
18749 +
18750         if (BZ_OK != BZ2_bzCompressEnd(&bz)) {
18751                 return -1;
18752         }
18753 -       
18754 +
18755         return 0;
18756  }
18757  #endif
18758 @@ -326,47 +357,50 @@
18759         void *start;
18760         const char *filename = fn->ptr;
18761         ssize_t r;
18762 -       
18763 +       stat_cache_entry *compressed_sce = NULL;
18764 +
18765 +       if (buffer_is_empty(p->conf.compress_cache_dir)) return -1;
18766 +
18767         /* overflow */
18768         if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
18769 -       
18770 -       /* don't mmap files > 128Mb 
18771 -        * 
18772 +
18773 +       /* don't mmap files > 128Mb
18774 +        *
18775          * we could use a sliding window, but currently there is no need for it
18776          */
18777 -       
18778 +
18779         if (sce->st.st_size > 128 * 1024 * 1024) return -1;
18780 -       
18781 +
18782         buffer_reset(p->ofn);
18783         buffer_copy_string_buffer(p->ofn, p->conf.compress_cache_dir);
18784 -       BUFFER_APPEND_SLASH(p->ofn);
18785 -       
18786 +       PATHNAME_APPEND_SLASH(p->ofn);
18787 +
18788         if (0 == strncmp(con->physical.path->ptr, con->physical.doc_root->ptr, con->physical.doc_root->used-1)) {
18789                 size_t offset = p->ofn->used - 1;
18790                 char *dir, *nextdir;
18791 -               
18792 +
18793                 buffer_append_string(p->ofn, con->physical.path->ptr + con->physical.doc_root->used - 1);
18794 -               
18795 +
18796                 buffer_copy_string_buffer(p->b, p->ofn);
18797 -               
18798 +
18799                 /* mkdir -p ... */
18800                 for (dir = p->b->ptr + offset; NULL != (nextdir = strchr(dir, '/')); dir = nextdir + 1) {
18801                         *nextdir = '\0';
18802 -                       
18803 +
18804                         if (-1 == mkdir(p->b->ptr, 0700)) {
18805                                 if (errno != EEXIST) {
18806                                         log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cache-directory", p->b, "failed", strerror(errno));
18807 -                                       
18808 +
18809                                         return -1;
18810                                 }
18811                         }
18812 -                       
18813 +
18814                         *nextdir = '/';
18815                 }
18816         } else {
18817                 buffer_append_string_buffer(p->ofn, con->uri.path);
18818         }
18819 -       
18820 +
18821         switch(type) {
18822         case HTTP_ACCEPT_ENCODING_GZIP:
18823                 buffer_append_string(p->ofn, "-gzip-");
18824 @@ -381,55 +415,64 @@
18825                 log_error_write(srv, __FILE__, __LINE__, "sd", "unknown compression type", type);
18826                 return -1;
18827         }
18828 -       
18829 +
18830         buffer_append_string_buffer(p->ofn, sce->etag);
18831 -       
18832 +
18833 +
18834 +       if (HANDLER_ERROR != stat_cache_get_entry(srv, con, p->ofn, &compressed_sce)) {
18835 +               /* file exists */
18836 +
18837 +               http_chunk_append_file(srv, con, p->ofn, 0, compressed_sce->st.st_size);
18838 +               con->file_finished = 1;
18839 +
18840 +               return 0;
18841 +       }
18842 +
18843         if (-1 == (ofd = open(p->ofn->ptr, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600))) {
18844                 if (errno == EEXIST) {
18845                         /* cache-entry exists */
18846 -#if 0
18847 -                       log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache hit");
18848 -#endif
18849 -                       buffer_copy_string_buffer(con->physical.path, p->ofn);
18850 -                       
18851 -                       return 0;
18852 +
18853                 }
18854 -               
18855 -               log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cachefile", p->ofn, "failed", strerror(errno));
18856 -               
18857 +
18858 +               log_error_write(srv, __FILE__, __LINE__, "sbss",
18859 +                               "creating cachefile", p->ofn,
18860 +                               "failed", strerror(errno));
18861 +
18862                 return -1;
18863         }
18864 -#if 0
18865 -       log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache miss");
18866 -#endif 
18867 +
18868         if (-1 == (ifd = open(filename, O_RDONLY | O_BINARY))) {
18869 -               log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
18870 -               
18871 +               log_error_write(srv, __FILE__, __LINE__, "sbss",
18872 +                               "opening plain-file", fn,
18873 +                               "failed", strerror(errno));
18874 +
18875                 close(ofd);
18876 -               
18877 +
18878                 return -1;
18879         }
18880 -       
18881 -       
18882 +
18883 +
18884         if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
18885 -               log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
18886 -               
18887 +               log_error_write(srv, __FILE__, __LINE__, "sbss",
18888 +                               "mmaping", fn,
18889 +                               "failed", strerror(errno));
18890 +
18891                 close(ofd);
18892                 close(ifd);
18893                 return -1;
18894         }
18895 -       
18896 +
18897         switch(type) {
18898  #ifdef USE_ZLIB
18899 -       case HTTP_ACCEPT_ENCODING_GZIP: 
18900 +       case HTTP_ACCEPT_ENCODING_GZIP:
18901                 ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
18902                 break;
18903 -       case HTTP_ACCEPT_ENCODING_DEFLATE: 
18904 +       case HTTP_ACCEPT_ENCODING_DEFLATE:
18905                 ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
18906                 break;
18907  #endif
18908  #ifdef USE_BZ2LIB
18909 -       case HTTP_ACCEPT_ENCODING_BZIP2: 
18910 +       case HTTP_ACCEPT_ENCODING_BZIP2:
18911                 ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
18912                 break;
18913  #endif
18914 @@ -437,26 +480,27 @@
18915                 ret = -1;
18916                 break;
18917         }
18918 -       
18919 +
18920         if (-1 == (r = write(ofd, p->b->ptr, p->b->used))) {
18921 -               munmap(start, sce->st.st_size); 
18922 +               munmap(start, sce->st.st_size);
18923                 close(ofd);
18924                 close(ifd);
18925                 return -1;
18926         }
18927 -       
18928 +
18929         if ((size_t)r != p->b->used) {
18930 -               
18931 +
18932         }
18933 -               
18934 +
18935         munmap(start, sce->st.st_size);
18936         close(ofd);
18937         close(ifd);
18938 -       
18939 +
18940         if (ret != 0) return -1;
18941 -       
18942 -       buffer_copy_string_buffer(con->physical.path, p->ofn);
18943 -       
18944 +
18945 +       http_chunk_append_file(srv, con, p->ofn, 0, r);
18946 +       con->file_finished = 1;
18947 +
18948         return 0;
18949  }
18950  
18951 @@ -465,43 +509,44 @@
18952         int ret = -1;
18953         void *start;
18954         buffer *b;
18955 -       
18956 +
18957         /* overflow */
18958         if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
18959 -       
18960 +
18961         /* don't mmap files > 128M
18962 -        * 
18963 +        *
18964          * we could use a sliding window, but currently there is no need for it
18965          */
18966 -       
18967 +
18968         if (sce->st.st_size > 128 * 1024 * 1024) return -1;
18969 -       
18970 -       
18971 +
18972         if (-1 == (ifd = open(fn->ptr, O_RDONLY | O_BINARY))) {
18973                 log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
18974 -               
18975 +
18976                 return -1;
18977         }
18978 -       
18979 -       
18980 -       if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
18981 +
18982 +       start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0);
18983 +
18984 +       close(ifd);
18985 +
18986 +       if (MAP_FAILED == start) {
18987                 log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
18988 -               
18989 -               close(ifd);
18990 +
18991                 return -1;
18992         }
18993 -       
18994 +
18995         switch(type) {
18996  #ifdef USE_ZLIB
18997 -       case HTTP_ACCEPT_ENCODING_GZIP: 
18998 +       case HTTP_ACCEPT_ENCODING_GZIP:
18999                 ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
19000                 break;
19001 -       case HTTP_ACCEPT_ENCODING_DEFLATE: 
19002 +       case HTTP_ACCEPT_ENCODING_DEFLATE:
19003                 ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
19004                 break;
19005  #endif
19006  #ifdef USE_BZ2LIB
19007 -       case HTTP_ACCEPT_ENCODING_BZIP2: 
19008 +       case HTTP_ACCEPT_ENCODING_BZIP2:
19009                 ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
19010                 break;
19011  #endif
19012 @@ -509,69 +554,64 @@
19013                 ret = -1;
19014                 break;
19015         }
19016 -               
19017 +
19018         munmap(start, sce->st.st_size);
19019 -       close(ifd);
19020 -       
19021 +
19022         if (ret != 0) return -1;
19023 -       
19024 +
19025         chunkqueue_reset(con->write_queue);
19026         b = chunkqueue_get_append_buffer(con->write_queue);
19027         buffer_copy_memory(b, p->b->ptr, p->b->used + 1);
19028 -       
19029 +
19030         buffer_reset(con->physical.path);
19031 -       
19032 +
19033         con->file_finished = 1;
19034         con->file_started  = 1;
19035 -       
19036 +
19037         return 0;
19038  }
19039  
19040 -
19041 -#define PATCH(x) \
19042 -       p->conf.x = s->x;
19043  static int mod_compress_patch_connection(server *srv, connection *con, plugin_data *p) {
19044         size_t i, j;
19045         plugin_config *s = p->config_storage[0];
19046  
19047 -       PATCH(compress_cache_dir);
19048 -       PATCH(compress);
19049 -       PATCH(compress_max_filesize);
19050 -       
19051 +       PATCH_OPTION(compress_cache_dir);
19052 +       PATCH_OPTION(compress);
19053 +       PATCH_OPTION(compress_max_filesize);
19054 +
19055         /* skip the first, the global context */
19056         for (i = 1; i < srv->config_context->used; i++) {
19057                 data_config *dc = (data_config *)srv->config_context->data[i];
19058                 s = p->config_storage[i];
19059 -               
19060 +
19061                 /* condition didn't match */
19062                 if (!config_check_cond(srv, con, dc)) continue;
19063 -               
19064 +
19065                 /* merge config */
19066                 for (j = 0; j < dc->value->used; j++) {
19067                         data_unset *du = dc->value->data[j];
19068 -                       
19069 +
19070                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.cache-dir"))) {
19071 -                               PATCH(compress_cache_dir);
19072 +                               PATCH_OPTION(compress_cache_dir);
19073                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.filetype"))) {
19074 -                               PATCH(compress);
19075 +                               PATCH_OPTION(compress);
19076                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.max-filesize"))) {
19077 -                               PATCH(compress_max_filesize);
19078 +                               PATCH_OPTION(compress_max_filesize);
19079                         }
19080                 }
19081         }
19082 -       
19083 +
19084         return 0;
19085  }
19086 -#undef PATCH
19087  
19088  PHYSICALPATH_FUNC(mod_compress_physical) {
19089         plugin_data *p = p_d;
19090         size_t m;
19091         off_t max_fsize;
19092         stat_cache_entry *sce = NULL;
19093 -       
19094 +
19095         /* only GET and POST can get compressed */
19096 -       if (con->request.http_method != HTTP_METHOD_GET && 
19097 +       if (con->request.http_method != HTTP_METHOD_GET &&
19098             con->request.http_method != HTTP_METHOD_POST) {
19099                 return HANDLER_GO_ON;
19100         }
19101 @@ -579,46 +619,49 @@
19102         if (buffer_is_empty(con->physical.path)) {
19103                 return HANDLER_GO_ON;
19104         }
19105 -       
19106 +
19107         mod_compress_patch_connection(srv, con, p);
19108 -       
19109 +
19110         max_fsize = p->conf.compress_max_filesize;
19111  
19112         stat_cache_get_entry(srv, con, con->physical.path, &sce);
19113  
19114         /* don't compress files that are too large as we need to much time to handle them */
19115         if (max_fsize && (sce->st.st_size >> 10) > max_fsize) return HANDLER_GO_ON;
19116 -               
19117 +
19118 +       /* compressing the file might lead to larger files instead */
19119 +       if (sce->st.st_size < 128) return HANDLER_GO_ON;
19120 +
19121         /* check if mimetype is in compress-config */
19122         for (m = 0; m < p->conf.compress->used; m++) {
19123                 data_string *compress_ds = (data_string *)p->conf.compress->data[m];
19124 -                       
19125 +
19126                 if (!compress_ds) {
19127                         log_error_write(srv, __FILE__, __LINE__, "sbb", "evil", con->physical.path, con->uri.path);
19128 -                       
19129 +
19130                         return HANDLER_GO_ON;
19131                 }
19132 -               
19133 +
19134                 if (buffer_is_equal(compress_ds->value, sce->content_type)) {
19135                         /* mimetype found */
19136                         data_string *ds;
19137 -                               
19138 +
19139                         /* the response might change according to Accept-Encoding */
19140                         response_header_insert(srv, con, CONST_STR_LEN("Vary"), CONST_STR_LEN("Accept-Encoding"));
19141 -                               
19142 +
19143                         if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Accept-Encoding"))) {
19144                                 int accept_encoding = 0;
19145                                 char *value = ds->value->ptr;
19146                                 int srv_encodings = 0;
19147                                 int matched_encodings = 0;
19148 -                               
19149 +
19150                                 /* get client side support encodings */
19151                                 if (NULL != strstr(value, "gzip")) accept_encoding |= HTTP_ACCEPT_ENCODING_GZIP;
19152                                 if (NULL != strstr(value, "deflate")) accept_encoding |= HTTP_ACCEPT_ENCODING_DEFLATE;
19153                                 if (NULL != strstr(value, "compress")) accept_encoding |= HTTP_ACCEPT_ENCODING_COMPRESS;
19154                                 if (NULL != strstr(value, "bzip2")) accept_encoding |= HTTP_ACCEPT_ENCODING_BZIP2;
19155                                 if (NULL != strstr(value, "identity")) accept_encoding |= HTTP_ACCEPT_ENCODING_IDENTITY;
19156 -                               
19157 +
19158                                 /* get server side supported ones */
19159  #ifdef USE_BZ2LIB
19160                                 srv_encodings |= HTTP_ACCEPT_ENCODING_BZIP2;
19161 @@ -627,18 +670,31 @@
19162                                 srv_encodings |= HTTP_ACCEPT_ENCODING_GZIP;
19163                                 srv_encodings |= HTTP_ACCEPT_ENCODING_DEFLATE;
19164  #endif
19165 -                               
19166 +
19167                                 /* find matching entries */
19168                                 matched_encodings = accept_encoding & srv_encodings;
19169 -                               
19170 +
19171                                 if (matched_encodings) {
19172                                         const char *dflt_gzip = "gzip";
19173                                         const char *dflt_deflate = "deflate";
19174                                         const char *dflt_bzip2 = "bzip2";
19175 -                                       
19176 +
19177                                         const char *compression_name = NULL;
19178                                         int compression_type = 0;
19179 -                                       
19180 +                                       buffer *mtime;
19181 +
19182 +                                       mtime = strftime_cache_get(srv, sce->st.st_mtime);
19183 +                                       etag_mutate(con->physical.etag, sce->etag);
19184 +
19185 +                                       response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
19186 +                                       response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
19187 +
19188 +                                       /* perhaps we don't even have to compress the file as the browser still has the
19189 +                                        * current version */
19190 +                                       if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
19191 +                                               return HANDLER_FINISHED;
19192 +                                       }
19193 +
19194                                         /* select best matching encoding */
19195                                         if (matched_encodings & HTTP_ACCEPT_ENCODING_BZIP2) {
19196                                                 compression_type = HTTP_ACCEPT_ENCODING_BZIP2;
19197 @@ -650,31 +706,21 @@
19198                                                 compression_type = HTTP_ACCEPT_ENCODING_DEFLATE;
19199                                                 compression_name = dflt_deflate;
19200                                         }
19201 -                                       
19202 -                                       /* deflate it */
19203 -                                       if (p->conf.compress_cache_dir->used) {
19204 -                                               if (0 == deflate_file_to_file(srv, con, p,
19205 -                                                                             con->physical.path, sce, compression_type)) {
19206 -                                                       buffer *mtime;
19207 -                                                       
19208 -                                                       response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
19209 -                                                       
19210 -                                                       mtime = strftime_cache_get(srv, sce->st.st_mtime);
19211 -                                                       response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
19212 -
19213 -                                                       etag_mutate(con->physical.etag, sce->etag);
19214 -                                                       response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
19215 -
19216 -                                                       response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
19217 -
19218 -                                                       return HANDLER_GO_ON;
19219 -                                               }
19220 -                                       } else if (0 == deflate_file_to_buffer(srv, con, p,
19221 -                                                                              con->physical.path, sce, compression_type)) {
19222 -                                                       
19223 -                                               response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
19224 -                                               response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
19225 -                                               
19226 +
19227 +                                       /* deflate it to file (cached) or to memory */
19228 +                                       if (0 == deflate_file_to_file(srv, con, p,
19229 +                                                       con->physical.path, sce, compression_type) ||
19230 +                                           0 == deflate_file_to_buffer(srv, con, p,
19231 +                                                       con->physical.path, sce, compression_type)) {
19232 +
19233 +                                               response_header_overwrite(srv, con,
19234 +                                                               CONST_STR_LEN("Content-Encoding"),
19235 +                                                               compression_name, strlen(compression_name));
19236 +
19237 +                                               response_header_overwrite(srv, con,
19238 +                                                               CONST_STR_LEN("Content-Type"),
19239 +                                                               CONST_BUF_LEN(sce->content_type));
19240 +
19241                                                 return HANDLER_FINISHED;
19242                                         }
19243                                         break;
19244 @@ -682,20 +728,20 @@
19245                         }
19246                 }
19247         }
19248 -       
19249 +
19250         return HANDLER_GO_ON;
19251  }
19252  
19253  int mod_compress_plugin_init(plugin *p) {
19254         p->version     = LIGHTTPD_VERSION_ID;
19255         p->name        = buffer_init_string("compress");
19256 -       
19257 +
19258         p->init        = mod_compress_init;
19259         p->set_defaults = mod_compress_setdefaults;
19260         p->handle_subrequest_start  = mod_compress_physical;
19261         p->cleanup     = mod_compress_free;
19262 -       
19263 +
19264         p->data        = NULL;
19265 -       
19266 +
19267         return 0;
19268  }
19269 --- lighttpd-1.4.11/src/mod_dirlisting.c        2006-01-13 00:00:45.000000000 +0200
19270 +++ lighttpd-1.4.12/src/mod_dirlisting.c        2006-07-11 22:07:53.000000000 +0300
19271 @@ -1,11 +1,9 @@
19272  #include <ctype.h>
19273  #include <stdlib.h>
19274  #include <string.h>
19275 -#include <dirent.h>
19276  #include <assert.h>
19277  #include <errno.h>
19278  #include <stdio.h>
19279 -#include <unistd.h>
19280  #include <time.h>
19281  
19282  #include "base.h"
19283 @@ -31,6 +29,9 @@
19284  #include <attr/attributes.h>
19285  #endif
19286  
19287 +#include "sys-files.h"
19288 +#include "sys-strings.h"
19289 +
19290  /* plugin config for all request/connections */
19291  
19292  typedef struct {
19293 @@ -54,7 +55,7 @@
19294         unsigned short hide_readme_file;
19295         unsigned short show_header;
19296         unsigned short hide_header_file;
19297 -       
19298 +
19299         excludes_buffer *excludes;
19300  
19301         buffer *external_css;
19302 @@ -63,13 +64,13 @@
19303  
19304  typedef struct {
19305         PLUGIN_DATA;
19306 -       
19307 +
19308         buffer *tmp_buf;
19309         buffer *content_charset;
19310 -       
19311 +
19312         plugin_config **config_storage;
19313 -       
19314 -       plugin_config conf; 
19315 +
19316 +       plugin_config conf;
19317  } plugin_data;
19318  
19319  excludes_buffer *excludes_buffer_init(void) {
19320 @@ -146,44 +147,44 @@
19321  /* init the plugin data */
19322  INIT_FUNC(mod_dirlisting_init) {
19323         plugin_data *p;
19324 -       
19325 +
19326         p = calloc(1, sizeof(*p));
19327  
19328         p->tmp_buf = buffer_init();
19329         p->content_charset = buffer_init();
19330 -       
19331 +
19332         return p;
19333  }
19334  
19335  /* detroy the plugin data */
19336  FREE_FUNC(mod_dirlisting_free) {
19337         plugin_data *p = p_d;
19338 -       
19339 +
19340         UNUSED(srv);
19341  
19342         if (!p) return HANDLER_GO_ON;
19343 -       
19344 +
19345         if (p->config_storage) {
19346                 size_t i;
19347                 for (i = 0; i < srv->config_context->used; i++) {
19348                         plugin_config *s = p->config_storage[i];
19349 -                       
19350 +
19351                         if (!s) continue;
19352 -                       
19353 +
19354                         excludes_buffer_free(s->excludes);
19355                         buffer_free(s->external_css);
19356                         buffer_free(s->encoding);
19357 -                       
19358 +
19359                         free(s);
19360                 }
19361                 free(p->config_storage);
19362         }
19363 -       
19364 +
19365         buffer_free(p->tmp_buf);
19366         buffer_free(p->content_charset);
19367 -       
19368 +
19369         free(p);
19370 -       
19371 +
19372         return HANDLER_GO_ON;
19373  }
19374  
19375 @@ -215,10 +216,10 @@
19376                         if (0 != excludes_buffer_append(s->excludes,
19377                                     ((data_string *)(da->value->data[j]))->value)) {
19378  #ifdef HAVE_PCRE_H
19379 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
19380 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
19381                                                 "pcre-compile failed for", ((data_string *)(da->value->data[j]))->value);
19382  #else
19383 -                               log_error_write(srv, __FILE__, __LINE__, "s", 
19384 +                               log_error_write(srv, __FILE__, __LINE__, "s",
19385                                                 "pcre support is missing, please install libpcre and the headers");
19386  #endif
19387                         }
19388 @@ -233,8 +234,8 @@
19389  SETDEFAULTS_FUNC(mod_dirlisting_set_defaults) {
19390         plugin_data *p = p_d;
19391         size_t i = 0;
19392 -       
19393 -       config_values_t cv[] = { 
19394 +
19395 +       config_values_t cv[] = {
19396                 { "dir-listing.exclude",          NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION },   /* 0 */
19397                 { "dir-listing.activate",         NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
19398                 { "dir-listing.hide-dotfiles",    NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
19399 @@ -245,18 +246,18 @@
19400                 { "dir-listing.show-header",      NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
19401                 { "dir-listing.hide-header-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
19402                 { "server.dir-listing",           NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
19403 -               
19404 +
19405                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
19406         };
19407 -       
19408 +
19409         if (!p) return HANDLER_ERROR;
19410 -       
19411 +
19412         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
19413 -       
19414 +
19415         for (i = 0; i < srv->config_context->used; i++) {
19416                 plugin_config *s;
19417                 array *ca;
19418 -               
19419 +
19420                 s = calloc(1, sizeof(plugin_config));
19421                 s->excludes = excludes_buffer_init();
19422                 s->dir_listing = 0;
19423 @@ -267,7 +268,7 @@
19424                 s->show_header = 0;
19425                 s->hide_header_file = 0;
19426                 s->encoding = buffer_init();
19427 -               
19428 +
19429                 cv[0].destination = s->excludes;
19430                 cv[1].destination = &(s->dir_listing);
19431                 cv[2].destination = &(s->hide_dot_files);
19432 @@ -292,60 +293,57 @@
19433         return HANDLER_GO_ON;
19434  }
19435  
19436 -#define PATCH(x) \
19437 -       p->conf.x = s->x;
19438  static int mod_dirlisting_patch_connection(server *srv, connection *con, plugin_data *p) {
19439         size_t i, j;
19440         plugin_config *s = p->config_storage[0];
19441  
19442 -       PATCH(dir_listing);
19443 -       PATCH(external_css);
19444 -       PATCH(hide_dot_files);
19445 -       PATCH(encoding);
19446 -       PATCH(show_readme);
19447 -       PATCH(hide_readme_file);
19448 -       PATCH(show_header);
19449 -       PATCH(hide_header_file);
19450 -       PATCH(excludes);
19451 -       
19452 +       PATCH_OPTION(dir_listing);
19453 +       PATCH_OPTION(external_css);
19454 +       PATCH_OPTION(hide_dot_files);
19455 +       PATCH_OPTION(encoding);
19456 +       PATCH_OPTION(show_readme);
19457 +       PATCH_OPTION(hide_readme_file);
19458 +       PATCH_OPTION(show_header);
19459 +       PATCH_OPTION(hide_header_file);
19460 +       PATCH_OPTION(excludes);
19461 +
19462         /* skip the first, the global context */
19463         for (i = 1; i < srv->config_context->used; i++) {
19464                 data_config *dc = (data_config *)srv->config_context->data[i];
19465                 s = p->config_storage[i];
19466 -               
19467 +
19468                 /* condition didn't match */
19469                 if (!config_check_cond(srv, con, dc)) continue;
19470 -               
19471 +
19472                 /* merge config */
19473                 for (j = 0; j < dc->value->used; j++) {
19474                         data_unset *du = dc->value->data[j];
19475 -                       
19476 +
19477                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.activate")) ||
19478                             buffer_is_equal_string(du->key, CONST_STR_LEN("server.dir-listing"))) {
19479 -                               PATCH(dir_listing);
19480 +                               PATCH_OPTION(dir_listing);
19481                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-dotfiles"))) {
19482 -                               PATCH(hide_dot_files);
19483 +                               PATCH_OPTION(hide_dot_files);
19484                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.external-css"))) {
19485 -                               PATCH(external_css);
19486 +                               PATCH_OPTION(external_css);
19487                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.encoding"))) {
19488 -                               PATCH(encoding);
19489 +                               PATCH_OPTION(encoding);
19490                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-readme"))) {
19491 -                               PATCH(show_readme);
19492 +                               PATCH_OPTION(show_readme);
19493                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-readme-file"))) {
19494 -                               PATCH(hide_readme_file);
19495 +                               PATCH_OPTION(hide_readme_file);
19496                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-header"))) {
19497 -                               PATCH(show_header);
19498 +                               PATCH_OPTION(show_header);
19499                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-header-file"))) {
19500 -                               PATCH(hide_header_file);
19501 +                               PATCH_OPTION(hide_header_file);
19502                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.excludes"))) {
19503 -                               PATCH(excludes);
19504 +                               PATCH_OPTION(excludes);
19505                         }
19506                 }
19507         }
19508 -       
19509 +
19510         return 0;
19511  }
19512 -#undef PATCH
19513  
19514  typedef struct {
19515         size_t  namelen;
19516 @@ -432,7 +430,7 @@
19517  
19518  static void http_list_directory_header(server *srv, connection *con, plugin_data *p, buffer *out) {
19519         UNUSED(srv);
19520 -       
19521 +
19522         BUFFER_APPEND_STRING_CONST(out,
19523                 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
19524                 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n"
19525 @@ -492,11 +490,11 @@
19526         if (p->conf.show_header) {
19527                 stream s;
19528                 /* if we have a HEADER file, display it in <pre class="header"></pre> */
19529 -               
19530 +
19531                 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
19532 -               BUFFER_APPEND_SLASH(p->tmp_buf);
19533 +               PATHNAME_APPEND_SLASH(p->tmp_buf);
19534                 BUFFER_APPEND_STRING_CONST(p->tmp_buf, "HEADER.txt");
19535 -               
19536 +
19537                 if (-1 != stream_open(&s, p->tmp_buf)) {
19538                         BUFFER_APPEND_STRING_CONST(out, "<pre class=\"header\">");
19539                         buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
19540 @@ -531,21 +529,21 @@
19541  
19542  static void http_list_directory_footer(server *srv, connection *con, plugin_data *p, buffer *out) {
19543         UNUSED(srv);
19544 -       
19545 +
19546         BUFFER_APPEND_STRING_CONST(out,
19547                 "</tbody>\n"
19548                 "</table>\n"
19549                 "</div>\n"
19550         );
19551 -       
19552 +
19553         if (p->conf.show_readme) {
19554                 stream s;
19555                 /* if we have a README file, display it in <pre class="readme"></pre> */
19556 -               
19557 +
19558                 buffer_copy_string_buffer(p->tmp_buf,  con->physical.path);
19559 -               BUFFER_APPEND_SLASH(p->tmp_buf);
19560 +               PATHNAME_APPEND_SLASH(p->tmp_buf);
19561                 BUFFER_APPEND_STRING_CONST(p->tmp_buf, "README.txt");
19562 -               
19563 +
19564                 if (-1 != stream_open(&s, p->tmp_buf)) {
19565                         BUFFER_APPEND_STRING_CONST(out, "<pre class=\"readme\">");
19566                         buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
19567 @@ -553,7 +551,7 @@
19568                 }
19569                 stream_close(&s);
19570         }
19571 -       
19572 +
19573         BUFFER_APPEND_STRING_CONST(out,
19574                 "<div class=\"foot\">"
19575         );
19576 @@ -595,7 +593,7 @@
19577  #endif
19578  
19579         if (dir->used == 0) return -1;
19580 -       
19581 +
19582         i = dir->used - 1;
19583  
19584  #ifdef HAVE_PATHCONF
19585 @@ -606,19 +604,24 @@
19586                 name_max = 256; /* stupid default */
19587  #endif
19588         }
19589 -#elif defined __WIN32
19590 +#elif defined _WIN32
19591         name_max = FILENAME_MAX;
19592  #else
19593         name_max = NAME_MAX;
19594  #endif
19595 -       
19596 +
19597         path = malloc(dir->used + name_max);
19598         assert(path);
19599         strcpy(path, dir->ptr);
19600 +#ifdef _WIN32
19601 +    /* append \*.* to the path and keep the \ as part of the pathname */
19602 +    strcat(path, "\\*.*");
19603 +    i++;
19604 +#endif
19605         path_file = path + i;
19606  
19607         if (NULL == (dp = opendir(path))) {
19608 -               log_error_write(srv, __FILE__, __LINE__, "sbs", 
19609 +               log_error_write(srv, __FILE__, __LINE__, "sbs",
19610                         "opendir failed:", dir, strerror(errno));
19611  
19612                 free(path);
19613 @@ -633,7 +636,7 @@
19614         assert(files.ent);
19615         files.size = DIRLIST_BLOB_SIZE;
19616         files.used = 0;
19617 -       
19618 +
19619         while ((dent = readdir(dp)) != NULL) {
19620                 unsigned short exclude_match = 0;
19621  
19622 @@ -686,15 +689,17 @@
19623  #endif
19624  
19625                 i = strlen(dent->d_name);
19626 -               
19627 +
19628                 /* NOTE: the manual says, d_name is never more than NAME_MAX
19629                  *       so this should actually not be a buffer-overflow-risk
19630                  */
19631                 if (i > (size_t)name_max) continue;
19632 -               
19633 +
19634                 memcpy(path_file, dent->d_name, i + 1);
19635 -               if (stat(path, &st) != 0)
19636 +               if (stat(path, &st) != 0) {
19637 +            fprintf(stderr, "%s.%d: %s, %s\r\n", __FILE__, __LINE__, path, strerror(errno));
19638                         continue;
19639 +        }
19640  
19641                 list = &files;
19642                 if (S_ISDIR(st.st_mode))
19643 @@ -740,7 +745,7 @@
19644  #else
19645                 strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", localtime(&(tmp->mtime)));
19646  #endif
19647 -               
19648 +
19649                 BUFFER_APPEND_STRING_CONST(out, "<tr><td class=\"n\"><a href=\"");
19650                 buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_REL_URI_PART);
19651                 BUFFER_APPEND_STRING_CONST(out, "/\">");
19652 @@ -758,7 +763,7 @@
19653  
19654                 content_type = NULL;
19655  #ifdef HAVE_XATTR
19656 -               
19657 +
19658                 if (con->conf.use_xattr) {
19659                         memcpy(path_file, DIRLIST_ENT_NAME(tmp), tmp->namelen + 1);
19660                         attrlen = sizeof(attrval) - 1;
19661 @@ -768,7 +773,7 @@
19662                         }
19663                 }
19664  #endif
19665 -               
19666 +
19667                 if (content_type == NULL) {
19668                         content_type = "application/octet-stream";
19669                         for (k = 0; k < con->conf.mimetypes->used; k++) {
19670 @@ -788,7 +793,7 @@
19671                                 }
19672                         }
19673                 }
19674 -                       
19675 +
19676  #ifdef HAVE_LOCALTIME_R
19677                 localtime_r(&(tmp->mtime), &tm);
19678                 strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", &tm);
19679 @@ -837,36 +842,36 @@
19680  URIHANDLER_FUNC(mod_dirlisting_subrequest) {
19681         plugin_data *p = p_d;
19682         stat_cache_entry *sce = NULL;
19683 -       
19684 +
19685         UNUSED(srv);
19686 -       
19687 +
19688         if (con->physical.path->used == 0) return HANDLER_GO_ON;
19689         if (con->uri.path->used == 0) return HANDLER_GO_ON;
19690         if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
19691 -       
19692 +
19693         mod_dirlisting_patch_connection(srv, con, p);
19694  
19695         if (!p->conf.dir_listing) return HANDLER_GO_ON;
19696 -       
19697 +
19698         if (con->conf.log_request_handling) {
19699                 log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling the request as Dir-Listing");
19700                 log_error_write(srv, __FILE__, __LINE__,  "sb", "URI          :", con->uri.path);
19701         }
19702 -       
19703 +
19704         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
19705                 fprintf(stderr, "%s.%d: %s\n", __FILE__, __LINE__, con->physical.path->ptr);
19706                 SEGFAULT();
19707         }
19708 -       
19709 +
19710         if (!S_ISDIR(sce->st.st_mode)) return HANDLER_GO_ON;
19711 -       
19712 +
19713         if (http_list_directory(srv, con, p, con->physical.path)) {
19714                 /* dirlisting failed */
19715                 con->http_status = 403;
19716         }
19717 -       
19718 +
19719         buffer_reset(con->physical.path);
19720 -       
19721 +
19722         /* not found */
19723         return HANDLER_FINISHED;
19724  }
19725 @@ -876,13 +881,13 @@
19726  int mod_dirlisting_plugin_init(plugin *p) {
19727         p->version     = LIGHTTPD_VERSION_ID;
19728         p->name        = buffer_init_string("dirlisting");
19729 -       
19730 +
19731         p->init        = mod_dirlisting_init;
19732         p->handle_subrequest_start  = mod_dirlisting_subrequest;
19733         p->set_defaults  = mod_dirlisting_set_defaults;
19734         p->cleanup     = mod_dirlisting_free;
19735 -       
19736 +
19737         p->data        = NULL;
19738 -       
19739 +
19740         return 0;
19741  }
19742 --- lighttpd-1.4.11/src/mod_evasive.c   2006-01-04 15:24:51.000000000 +0200
19743 +++ lighttpd-1.4.12/src/mod_evasive.c   2006-07-11 22:07:53.000000000 +0300
19744 @@ -31,100 +31,97 @@
19745  
19746  typedef struct {
19747         PLUGIN_DATA;
19748 -       
19749 +
19750         plugin_config **config_storage;
19751 -       
19752 -       plugin_config conf; 
19753 +
19754 +       plugin_config conf;
19755  } plugin_data;
19756  
19757  INIT_FUNC(mod_evasive_init) {
19758         plugin_data *p;
19759 -       
19760 +
19761         p = calloc(1, sizeof(*p));
19762 -       
19763 +
19764         return p;
19765  }
19766  
19767  FREE_FUNC(mod_evasive_free) {
19768         plugin_data *p = p_d;
19769 -       
19770 +
19771         UNUSED(srv);
19772  
19773         if (!p) return HANDLER_GO_ON;
19774 -       
19775 +
19776         if (p->config_storage) {
19777                 size_t i;
19778                 for (i = 0; i < srv->config_context->used; i++) {
19779                         plugin_config *s = p->config_storage[i];
19780 -                                               
19781 +
19782                         free(s);
19783                 }
19784                 free(p->config_storage);
19785         }
19786 -       
19787 +
19788         free(p);
19789 -       
19790 +
19791         return HANDLER_GO_ON;
19792  }
19793  
19794  SETDEFAULTS_FUNC(mod_evasive_set_defaults) {
19795         plugin_data *p = p_d;
19796         size_t i = 0;
19797 -       
19798 -       config_values_t cv[] = { 
19799 +
19800 +       config_values_t cv[] = {
19801                 { "evasive.max-conns-per-ip",    NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
19802                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
19803         };
19804 -       
19805 +
19806         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
19807 -       
19808 +
19809         for (i = 0; i < srv->config_context->used; i++) {
19810                 plugin_config *s;
19811 -               
19812 +
19813                 s = calloc(1, sizeof(plugin_config));
19814                 s->max_conns       = 0;
19815 -               
19816 +
19817                 cv[0].destination = &(s->max_conns);
19818 -               
19819 +
19820                 p->config_storage[i] = s;
19821 -       
19822 +
19823                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
19824                         return HANDLER_ERROR;
19825                 }
19826         }
19827 -       
19828 +
19829         return HANDLER_GO_ON;
19830  }
19831  
19832 -#define PATCH(x) \
19833 -       p->conf.x = s->x;
19834  static int mod_evasive_patch_connection(server *srv, connection *con, plugin_data *p) {
19835         size_t i, j;
19836         plugin_config *s = p->config_storage[0];
19837  
19838 -       PATCH(max_conns);
19839 -       
19840 +       PATCH_OPTION(max_conns);
19841 +
19842         /* skip the first, the global context */
19843         for (i = 1; i < srv->config_context->used; i++) {
19844                 data_config *dc = (data_config *)srv->config_context->data[i];
19845                 s = p->config_storage[i];
19846 -               
19847 +
19848                 /* condition didn't match */
19849                 if (!config_check_cond(srv, con, dc)) continue;
19850 -               
19851 +
19852                 /* merge config */
19853                 for (j = 0; j < dc->value->used; j++) {
19854                         data_unset *du = dc->value->data[j];
19855 -                       
19856 +
19857                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("evasive.max-conns-per-ip"))) {
19858 -                               PATCH(max_conns);
19859 +                               PATCH_OPTION(max_conns);
19860                         }
19861                 }
19862         }
19863 -       
19864 +
19865         return 0;
19866  }
19867 -#undef PATCH
19868  
19869  URIHANDLER_FUNC(mod_evasive_uri_handler) {
19870         plugin_data *p = p_d;
19871 @@ -132,10 +129,10 @@
19872         size_t j;
19873  
19874         if (con->uri.path->used == 0) return HANDLER_GO_ON;
19875 -       
19876 +
19877         mod_evasive_patch_connection(srv, con, p);
19878 -       
19879 -       /* no limit set, nothing to block */    
19880 +
19881 +       /* no limit set, nothing to block */
19882         if (p->conf.max_conns == 0) return HANDLER_GO_ON;
19883  
19884         for (j = 0; j < srv->conns->used; j++) {
19885 @@ -147,7 +144,7 @@
19886                 if (c->dst_addr.ipv4.sin_addr.s_addr == con->dst_addr.ipv4.sin_addr.s_addr &&
19887                     c->state > CON_STATE_REQUEST_END) {
19888                         conns_by_ip++;
19889 -       
19890 +
19891                         if (conns_by_ip > p->conf.max_conns) {
19892                                 log_error_write(srv, __FILE__, __LINE__, "ss",
19893                                         inet_ntop_cache_get_ip(srv, &(con->dst_addr)),
19894 @@ -158,7 +155,7 @@
19895                         }
19896                 }
19897         }
19898 -       
19899 +
19900         return HANDLER_GO_ON;
19901  }
19902  
19903 @@ -166,13 +163,13 @@
19904  int mod_evasive_plugin_init(plugin *p) {
19905         p->version     = LIGHTTPD_VERSION_ID;
19906         p->name        = buffer_init_string("evasive");
19907 -       
19908 +
19909         p->init        = mod_evasive_init;
19910         p->set_defaults = mod_evasive_set_defaults;
19911         p->handle_uri_clean  = mod_evasive_uri_handler;
19912         p->cleanup     = mod_evasive_free;
19913 -       
19914 +
19915         p->data        = NULL;
19916 -       
19917 +
19918         return 0;
19919  }
19920 --- lighttpd-1.4.11/src/mod_evhost.c    2005-08-17 10:42:03.000000000 +0300
19921 +++ lighttpd-1.4.12/src/mod_evhost.c    2006-07-11 22:07:51.000000000 +0300
19922 @@ -7,10 +7,12 @@
19923  #include "response.h"
19924  #include "stat_cache.h"
19925  
19926 +#include "sys-files.h"
19927 +
19928  typedef struct {
19929         /* unparsed pieces */
19930         buffer *path_pieces_raw;
19931 -       
19932 +
19933         /* pieces for path creation */
19934         size_t len;
19935         buffer **path_pieces;
19936 @@ -21,14 +23,14 @@
19937         buffer *tmp_buf;
19938  
19939         plugin_config **config_storage;
19940 -       plugin_config conf; 
19941 +       plugin_config conf;
19942  } plugin_data;
19943  
19944  INIT_FUNC(mod_evhost_init) {
19945         plugin_data *p;
19946 -       
19947 +
19948         p = calloc(1, sizeof(*p));
19949 -       
19950 +
19951         p->tmp_buf = buffer_init();
19952  
19953         return p;
19954 @@ -36,34 +38,34 @@
19955  
19956  FREE_FUNC(mod_evhost_free) {
19957         plugin_data *p = p_d;
19958 -       
19959 +
19960         UNUSED(srv);
19961  
19962         if (!p) return HANDLER_GO_ON;
19963 -       
19964 +
19965         if (p->config_storage) {
19966                 size_t i;
19967                 for (i = 0; i < srv->config_context->used; i++) {
19968                         plugin_config *s = p->config_storage[i];
19969  
19970                         if (!s) continue;
19971 -                       
19972 +
19973                         if(s->path_pieces) {
19974                                 size_t j;
19975                                 for (j = 0; j < s->len; j++) {
19976                                         buffer_free(s->path_pieces[j]);
19977                                 }
19978 -                               
19979 +
19980                                 free(s->path_pieces);
19981                         }
19982 -                       
19983 +
19984                         buffer_free(s->path_pieces_raw);
19985 -                       
19986 +
19987                         free(s);
19988                 }
19989                 free(p->config_storage);
19990         }
19991 -       
19992 +
19993         buffer_free(p->tmp_buf);
19994  
19995         free(p);
19996 @@ -73,30 +75,30 @@
19997  
19998  static void mod_evhost_parse_pattern(plugin_config *s) {
19999         char *ptr = s->path_pieces_raw->ptr,*pos;
20000 -       
20001 +
20002         s->path_pieces = NULL;
20003 -       
20004 +
20005         for(pos=ptr;*ptr;ptr++) {
20006                 if(*ptr == '%') {
20007                         s->path_pieces = realloc(s->path_pieces,(s->len+2) * sizeof(*s->path_pieces));
20008                         s->path_pieces[s->len] = buffer_init();
20009                         s->path_pieces[s->len+1] = buffer_init();
20010 -                       
20011 +
20012                         buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos);
20013                         pos = ptr + 2;
20014 -                       
20015 +
20016                         buffer_copy_string_len(s->path_pieces[s->len+1],ptr++,2);
20017 -                       
20018 +
20019                         s->len += 2;
20020                 }
20021         }
20022 -       
20023 +
20024         if(*pos != '\0') {
20025                 s->path_pieces = realloc(s->path_pieces,(s->len+1) * sizeof(*s->path_pieces));
20026                 s->path_pieces[s->len] = buffer_init();
20027 -               
20028 +
20029                 buffer_append_memory(s->path_pieces[s->len],pos,ptr-pos);
20030 -               
20031 +
20032                 s->len += 1;
20033         }
20034  }
20035 @@ -104,9 +106,9 @@
20036  SETDEFAULTS_FUNC(mod_evhost_set_defaults) {
20037         plugin_data *p = p_d;
20038         size_t i;
20039 -       
20040 +
20041         /**
20042 -        * 
20043 +        *
20044          * #
20045          * # define a pattern for the host url finding
20046          * # %% => % sign
20047 @@ -117,39 +119,39 @@
20048          * # %4 => subdomain 2 name
20049          * #
20050          * evhost.path-pattern = "/home/ckruse/dev/www/%3/htdocs/"
20051 -        * 
20052 +        *
20053          */
20054 -       
20055 -       config_values_t cv[] = { 
20056 +
20057 +       config_values_t cv[] = {
20058                 { "evhost.path-pattern",            NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
20059                 { NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
20060         };
20061 -       
20062 +
20063         if (!p) return HANDLER_ERROR;
20064 -       
20065 +
20066         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
20067 -       
20068 +
20069         for (i = 0; i < srv->config_context->used; i++) {
20070                 plugin_config *s;
20071 -               
20072 +
20073                 s = calloc(1, sizeof(plugin_config));
20074                 s->path_pieces_raw = buffer_init();
20075                 s->path_pieces     = NULL;
20076                 s->len             = 0;
20077 -       
20078 +
20079                 cv[0].destination = s->path_pieces_raw;
20080 -               
20081 +
20082                 p->config_storage[i] = s;
20083 -               
20084 +
20085                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value,  cv)) {
20086                         return HANDLER_ERROR;
20087                 }
20088 -               
20089 +
20090                 if (s->path_pieces_raw->used != 0) {
20091                         mod_evhost_parse_pattern(s);
20092                 }
20093         }
20094 -       
20095 +
20096         return HANDLER_GO_ON;
20097  }
20098  
20099 @@ -158,7 +160,7 @@
20100   * - %0 - full hostname (authority w/o port)
20101   * - %1 - tld
20102   * - %2 - domain.tld
20103 - * - %3 - 
20104 + * - %3 -
20105   */
20106  
20107  static int mod_evhost_parse_host(connection *con,array *host) {
20108 @@ -168,7 +170,7 @@
20109         int first = 1;
20110         data_string *ds;
20111         int i;
20112 -       
20113 +
20114         /* first, find the domain + tld */
20115         for(;ptr > con->uri.authority->ptr;ptr--) {
20116                 if(*ptr == '.') {
20117 @@ -179,18 +181,18 @@
20118                         first = 1;
20119                 }
20120         }
20121 -       
20122 +
20123         ds = data_string_init();
20124         buffer_copy_string(ds->key,"%0");
20125 -       
20126 +
20127         /* if we stopped at a dot, skip the dot */
20128         if (*ptr == '.') ptr++;
20129         buffer_copy_string_len(ds->value, ptr, colon-ptr);
20130 -       
20131 +
20132         array_insert_unique(host,(data_unset *)ds);
20133 -       
20134 +
20135         /* if the : is not the start of the authority, go on parsing the hostname */
20136 -       
20137 +
20138         if (colon != con->uri.authority->ptr) {
20139                 for(ptr = colon - 1, i = 1; ptr > con->uri.authority->ptr; ptr--) {
20140                         if(*ptr == '.') {
20141 @@ -200,59 +202,55 @@
20142                                         buffer_copy_string(ds->key,"%");
20143                                         buffer_append_long(ds->key, i++);
20144                                         buffer_copy_string_len(ds->value,ptr+1,colon-ptr-1);
20145 -                                       
20146 +
20147                                         array_insert_unique(host,(data_unset *)ds);
20148                                 }
20149                                 colon = ptr;
20150                         }
20151                 }
20152 -               
20153 +
20154                 /* if the . is not the first charactor of the hostname */
20155                 if (colon != ptr) {
20156                         ds = data_string_init();
20157                         buffer_copy_string(ds->key,"%");
20158                         buffer_append_long(ds->key, i++);
20159                         buffer_copy_string_len(ds->value,ptr,colon-ptr);
20160 -                       
20161 +
20162                         array_insert_unique(host,(data_unset *)ds);
20163                 }
20164         }
20165 -       
20166 +
20167         return 0;
20168  }
20169  
20170 -#define PATCH(x) \
20171 -       p->conf.x = s->x;
20172  static int mod_evhost_patch_connection(server *srv, connection *con, plugin_data *p) {
20173         size_t i, j;
20174         plugin_config *s = p->config_storage[0];
20175 -       
20176 -       PATCH(path_pieces);
20177 -       PATCH(len);
20178 -       
20179 +
20180 +       PATCH_OPTION(path_pieces);
20181 +       PATCH_OPTION(len);
20182 +
20183         /* skip the first, the global context */
20184         for (i = 1; i < srv->config_context->used; i++) {
20185                 data_config *dc = (data_config *)srv->config_context->data[i];
20186                 s = p->config_storage[i];
20187 -               
20188 +
20189                 /* condition didn't match */
20190                 if (!config_check_cond(srv, con, dc)) continue;
20191 -               
20192 +
20193                 /* merge config */
20194                 for (j = 0; j < dc->value->used; j++) {
20195                         data_unset *du = dc->value->data[j];
20196 -                       
20197 +
20198                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("evhost.path-pattern"))) {
20199 -                               PATCH(path_pieces);
20200 -                               PATCH(len);
20201 +                               PATCH_OPTION(path_pieces);
20202 +                               PATCH_OPTION(len);
20203                         }
20204                 }
20205         }
20206 -       
20207 +
20208         return 0;
20209  }
20210 -#undef PATCH
20211 -
20212  
20213  static handler_t mod_evhost_uri_handler(server *srv, connection *con, void *p_d) {
20214         plugin_data *p = p_d;
20215 @@ -261,29 +259,29 @@
20216         register char *ptr;
20217         int not_good = 0;
20218         stat_cache_entry *sce = NULL;
20219 -       
20220 +
20221         /* not authority set */
20222         if (con->uri.authority->used == 0) return HANDLER_GO_ON;
20223 -       
20224 +
20225         mod_evhost_patch_connection(srv, con, p);
20226 -       
20227 +
20228         /* missing even default(global) conf */
20229         if (0 == p->conf.len) {
20230                 return HANDLER_GO_ON;
20231         }
20232  
20233         parsed_host = array_init();
20234 -       
20235 +
20236         mod_evhost_parse_host(con, parsed_host);
20237 -       
20238 +
20239         /* build document-root */
20240         buffer_reset(p->tmp_buf);
20241 -       
20242 +
20243         for (i = 0; i < p->conf.len; i++) {
20244                 ptr = p->conf.path_pieces[i]->ptr;
20245                 if (*ptr == '%') {
20246                         data_string *ds;
20247 -                       
20248 +
20249                         if (*(ptr+1) == '%') {
20250                                 /* %% */
20251                                 BUFFER_APPEND_STRING_CONST(p->tmp_buf,"%");
20252 @@ -298,11 +296,11 @@
20253                         buffer_append_string_buffer(p->tmp_buf,p->conf.path_pieces[i]);
20254                 }
20255         }
20256 -       
20257 -       BUFFER_APPEND_SLASH(p->tmp_buf);
20258 -       
20259 +
20260 +       PATHNAME_APPEND_SLASH(p->tmp_buf);
20261 +
20262         array_free(parsed_host);
20263 -       
20264 +
20265         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
20266                 log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
20267                 not_good = 1;
20268 @@ -310,11 +308,11 @@
20269                 log_error_write(srv, __FILE__, __LINE__, "sb", "not a directory:", p->tmp_buf);
20270                 not_good = 1;
20271         }
20272 -       
20273 +
20274         if (!not_good) {
20275                 buffer_copy_string_buffer(con->physical.doc_root, p->tmp_buf);
20276         }
20277 -       
20278 +
20279         return HANDLER_GO_ON;
20280  }
20281  
20282 @@ -325,9 +323,9 @@
20283         p->set_defaults            = mod_evhost_set_defaults;
20284         p->handle_docroot          = mod_evhost_uri_handler;
20285         p->cleanup                 = mod_evhost_free;
20286 -       
20287 +
20288         p->data                    = NULL;
20289 -       
20290 +
20291         return 0;
20292  }
20293  
20294 --- lighttpd-1.4.11/src/mod_expire.c    2005-11-03 09:52:13.000000000 +0200
20295 +++ lighttpd-1.4.12/src/mod_expire.c    2006-07-11 22:07:52.000000000 +0300
20296 @@ -12,8 +12,8 @@
20297  #include "stat_cache.h"
20298  
20299  /**
20300 - * this is a expire module for a lighttpd 
20301 - * 
20302 + * this is a expire module for a lighttpd
20303 + *
20304   * set 'Expires:' HTTP Headers on demand
20305   */
20306  
20307 @@ -27,51 +27,51 @@
20308  
20309  typedef struct {
20310         PLUGIN_DATA;
20311 -       
20312 +
20313         buffer *expire_tstmp;
20314 -       
20315 +
20316         plugin_config **config_storage;
20317 -       
20318 -       plugin_config conf; 
20319 +
20320 +       plugin_config conf;
20321  } plugin_data;
20322  
20323  /* init the plugin data */
20324  INIT_FUNC(mod_expire_init) {
20325         plugin_data *p;
20326 -       
20327 +
20328         p = calloc(1, sizeof(*p));
20329 -       
20330 +
20331         p->expire_tstmp = buffer_init();
20332 -       
20333 +
20334         buffer_prepare_copy(p->expire_tstmp, 255);
20335 -       
20336 +
20337         return p;
20338  }
20339  
20340  /* detroy the plugin data */
20341  FREE_FUNC(mod_expire_free) {
20342         plugin_data *p = p_d;
20343 -       
20344 +
20345         UNUSED(srv);
20346  
20347         if (!p) return HANDLER_GO_ON;
20348 -       
20349 +
20350         buffer_free(p->expire_tstmp);
20351 -       
20352 +
20353         if (p->config_storage) {
20354                 size_t i;
20355                 for (i = 0; i < srv->config_context->used; i++) {
20356                         plugin_config *s = p->config_storage[i];
20357 -                       
20358 +
20359                         array_free(s->expire_url);
20360 -                       
20361 +
20362                         free(s);
20363                 }
20364                 free(p->config_storage);
20365         }
20366 -       
20367 +
20368         free(p);
20369 -       
20370 +
20371         return HANDLER_GO_ON;
20372  }
20373  
20374 @@ -79,25 +79,25 @@
20375         char *ts;
20376         int type = -1;
20377         int retts = 0;
20378 -               
20379 +
20380         UNUSED(p);
20381  
20382 -       /* 
20383 +       /*
20384          * parse
20385 -        * 
20386 +        *
20387          * '(access|modification) [plus] {<num> <type>}*'
20388 -        * 
20389 +        *
20390          * e.g. 'access 1 years'
20391          */
20392 -       
20393 +
20394         if (expire->used == 0) {
20395 -               log_error_write(srv, __FILE__, __LINE__, "s", 
20396 +               log_error_write(srv, __FILE__, __LINE__, "s",
20397                                 "empty:");
20398                 return -1;
20399         }
20400 -       
20401 +
20402         ts = expire->ptr;
20403 -       
20404 +
20405         if (0 == strncmp(ts, "access ", 7)) {
20406                 type  = 0;
20407                 ts   += 7;
20408 @@ -110,39 +110,39 @@
20409                                 "invalid <base>:", ts);
20410                 return -1;
20411         }
20412 -       
20413 +
20414         if (0 == strncmp(ts, "plus ", 5)) {
20415                 /* skip the optional plus */
20416                 ts   += 5;
20417         }
20418 -       
20419 +
20420         /* the rest is just <number> (years|months|days|hours|minutes|seconds) */
20421         while (1) {
20422                 char *space, *err;
20423                 int num;
20424 -               
20425 +
20426                 if (NULL == (space = strchr(ts, ' '))) {
20427 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
20428 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
20429                                         "missing space after <num>:", ts);
20430                         return -1;
20431                 }
20432 -               
20433 +
20434                 num = strtol(ts, &err, 10);
20435                 if (*err != ' ') {
20436 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
20437 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
20438                                         "missing <type> after <num>:", ts);
20439                         return -1;
20440                 }
20441 -               
20442 +
20443                 ts = space + 1;
20444 -               
20445 +
20446                 if (NULL != (space = strchr(ts, ' '))) {
20447                         int slen;
20448                         /* */
20449 -                       
20450 +
20451                         slen = space - ts;
20452 -                       
20453 -                       if (slen == 5 && 
20454 +
20455 +                       if (slen == 5 &&
20456                             0 == strncmp(ts, "years", slen)) {
20457                                 num *= 60 * 60 * 24 * 30 * 12;
20458                         } else if (slen == 6 &&
20459 @@ -161,13 +161,13 @@
20460                                    0 == strncmp(ts, "seconds", slen)) {
20461                                 num *= 1;
20462                         } else {
20463 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
20464 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
20465                                                 "unknown type:", ts);
20466                                 return -1;
20467                         }
20468 -                       
20469 +
20470                         retts += num;
20471 -                       
20472 +
20473                         ts = space + 1;
20474                 } else {
20475                         if (0 == strcmp(ts, "years")) {
20476 @@ -183,19 +183,19 @@
20477                         } else if (0 == strcmp(ts, "seconds")) {
20478                                 num *= 1;
20479                         } else {
20480 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
20481 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
20482                                                 "unknown type:", ts);
20483                                 return -1;
20484                         }
20485 -                       
20486 +
20487                         retts += num;
20488 -                       
20489 +
20490                         break;
20491                 }
20492         }
20493 -       
20494 +
20495         if (offset != NULL) *offset = retts;
20496 -       
20497 +
20498         return type;
20499  }
20500  
20501 @@ -205,102 +205,99 @@
20502  SETDEFAULTS_FUNC(mod_expire_set_defaults) {
20503         plugin_data *p = p_d;
20504         size_t i = 0, k;
20505 -       
20506 -       config_values_t cv[] = { 
20507 +
20508 +       config_values_t cv[] = {
20509                 { "expire.url",                 NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
20510                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
20511         };
20512 -       
20513 +
20514         if (!p) return HANDLER_ERROR;
20515 -       
20516 +
20517         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
20518 -       
20519 +
20520         for (i = 0; i < srv->config_context->used; i++) {
20521                 plugin_config *s;
20522 -               
20523 +
20524                 s = calloc(1, sizeof(plugin_config));
20525                 s->expire_url    = array_init();
20526 -               
20527 +
20528                 cv[0].destination = s->expire_url;
20529 -               
20530 +
20531                 p->config_storage[i] = s;
20532 -       
20533 +
20534                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
20535                         return HANDLER_ERROR;
20536                 }
20537 -       
20538 +
20539                 for (k = 0; k < s->expire_url->used; k++) {
20540                         data_string *ds = (data_string *)s->expire_url->data[k];
20541 -                       
20542 +
20543                         /* parse lines */
20544                         if (-1 == mod_expire_get_offset(srv, p, ds->value, NULL)) {
20545 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
20546 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
20547                                                 "parsing expire.url failed:", ds->value);
20548                                 return HANDLER_ERROR;
20549                         }
20550                 }
20551         }
20552 -       
20553 -       
20554 +
20555 +
20556         return HANDLER_GO_ON;
20557  }
20558  
20559 -#define PATCH(x) \
20560 -       p->conf.x = s->x;
20561  static int mod_expire_patch_connection(server *srv, connection *con, plugin_data *p) {
20562         size_t i, j;
20563         plugin_config *s = p->config_storage[0];
20564 -       
20565 -       PATCH(expire_url);
20566 -       
20567 +
20568 +       PATCH_OPTION(expire_url);
20569 +
20570         /* skip the first, the global context */
20571         for (i = 1; i < srv->config_context->used; i++) {
20572                 data_config *dc = (data_config *)srv->config_context->data[i];
20573                 s = p->config_storage[i];
20574 -               
20575 +
20576                 /* condition didn't match */
20577                 if (!config_check_cond(srv, con, dc)) continue;
20578 -               
20579 +
20580                 /* merge config */
20581                 for (j = 0; j < dc->value->used; j++) {
20582                         data_unset *du = dc->value->data[j];
20583 -                       
20584 +
20585                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("expire.url"))) {
20586 -                               PATCH(expire_url);
20587 +                               PATCH_OPTION(expire_url);
20588                         }
20589                 }
20590         }
20591 -       
20592 +
20593         return 0;
20594  }
20595 -#undef PATCH
20596  
20597  URIHANDLER_FUNC(mod_expire_path_handler) {
20598         plugin_data *p = p_d;
20599         int s_len;
20600         size_t k;
20601 -       
20602 +
20603         if (con->uri.path->used == 0) return HANDLER_GO_ON;
20604 -       
20605 +
20606         mod_expire_patch_connection(srv, con, p);
20607 -       
20608 +
20609         s_len = con->uri.path->used - 1;
20610 -       
20611 +
20612         for (k = 0; k < p->conf.expire_url->used; k++) {
20613                 data_string *ds = (data_string *)p->conf.expire_url->data[k];
20614                 int ct_len = ds->key->used - 1;
20615 -               
20616 +
20617                 if (ct_len > s_len) continue;
20618                 if (ds->key->used == 0) continue;
20619 -               
20620 +
20621                 if (0 == strncmp(con->uri.path->ptr, ds->key->ptr, ct_len)) {
20622                         int ts;
20623                         time_t t;
20624                         size_t len;
20625                         stat_cache_entry *sce = NULL;
20626 -               
20627 +
20628                         stat_cache_get_entry(srv, con, con->physical.path, &sce);
20629 -                       
20630 +
20631                         switch(mod_expire_get_offset(srv, p, ds->value, &ts)) {
20632                         case 0:
20633                                 /* access */
20634 @@ -308,38 +305,38 @@
20635                                 break;
20636                         case 1:
20637                                 /* modification */
20638 -                               
20639 +
20640                                 t = (ts + sce->st.st_mtime);
20641                                 break;
20642                         default:
20643                                 /* -1 is handled at parse-time */
20644                                 break;
20645                         }
20646 -                       
20647 -                       
20648 -                       if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1, 
20649 +
20650 +
20651 +                       if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1,
20652                                            "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(t))))) {
20653                                 /* could not set expire header, out of mem */
20654 -                               
20655 +
20656                                 return HANDLER_GO_ON;
20657 -                               
20658 +
20659                         }
20660 -                           
20661 +
20662                         p->expire_tstmp->used = len + 1;
20663 -               
20664 -                       /* HTTP/1.0 */  
20665 +
20666 +                       /* HTTP/1.0 */
20667                         response_header_overwrite(srv, con, CONST_STR_LEN("Expires"), CONST_BUF_LEN(p->expire_tstmp));
20668  
20669 -                       /* HTTP/1.1 */  
20670 +                       /* HTTP/1.1 */
20671                         buffer_copy_string(p->expire_tstmp, "max-age=");
20672                         buffer_append_long(p->expire_tstmp, ts);
20673 -                       
20674 +
20675                         response_header_overwrite(srv, con, CONST_STR_LEN("Cache-Control"), CONST_BUF_LEN(p->expire_tstmp));
20676 -                       
20677 +
20678                         return HANDLER_GO_ON;
20679                 }
20680         }
20681 -       
20682 +
20683         /* not found */
20684         return HANDLER_GO_ON;
20685  }
20686 @@ -349,13 +346,13 @@
20687  int mod_expire_plugin_init(plugin *p) {
20688         p->version     = LIGHTTPD_VERSION_ID;
20689         p->name        = buffer_init_string("expire");
20690 -       
20691 +
20692         p->init        = mod_expire_init;
20693         p->handle_subrequest_start = mod_expire_path_handler;
20694         p->set_defaults  = mod_expire_set_defaults;
20695         p->cleanup     = mod_expire_free;
20696 -       
20697 +
20698         p->data        = NULL;
20699 -       
20700 +
20701         return 0;
20702  }
20703 --- lighttpd-1.4.11/src/mod_fastcgi.c   2006-03-09 13:18:39.000000000 +0200
20704 +++ lighttpd-1.4.12/src/mod_fastcgi.c   2006-07-11 22:07:53.000000000 +0300
20705 @@ -1,5 +1,4 @@
20706  #include <sys/types.h>
20707 -#include <unistd.h>
20708  #include <errno.h>
20709  #include <fcntl.h>
20710  #include <string.h>
20711 @@ -24,7 +23,7 @@
20712  #include "inet_ntop_cache.h"
20713  #include "stat_cache.h"
20714  
20715 -#include <fastcgi.h>
20716 +#include "fastcgi.h"
20717  #include <stdio.h>
20718  
20719  #ifdef HAVE_SYS_FILIO_H
20720 @@ -32,7 +31,11 @@
20721  #endif
20722  
20723  #include "sys-socket.h"
20724 +#include "sys-files.h"
20725 +#include "sys-strings.h"
20726 +#include "sys-process.h"
20727  
20728 +#include "http_resp.h"
20729  
20730  #ifndef UNIX_PATH_MAX
20731  # define UNIX_PATH_MAX 108
20732 @@ -45,14 +48,13 @@
20733  #include <sys/wait.h>
20734  #endif
20735  
20736 -
20737  /*
20738 - * 
20739 + *
20740   * TODO:
20741 - * 
20742 + *
20743   * - add timeout for a connect to a non-fastcgi process
20744   *   (use state_timestamp + state)
20745 - * 
20746 + *
20747   */
20748  
20749  typedef struct fcgi_proc {
20750 @@ -61,7 +63,7 @@
20751         unsigned port;  /* config.port + pno */
20752  
20753         buffer *connection_name; /* either tcp:<host>:<port> or unix:<socket> for debuggin purposes */
20754 -       
20755 +
20756         pid_t pid;   /* PID of the spawned process (0 if not spawned locally) */
20757  
20758  
20759 @@ -70,20 +72,20 @@
20760         time_t last_used; /* see idle_timeout */
20761         size_t requests;  /* see max_requests */
20762         struct fcgi_proc *prev, *next; /* see first */
20763 -       
20764 +
20765         time_t disabled_until; /* this proc is disabled until, use something else until than */
20766 -       
20767 +
20768         int is_local;
20769  
20770 -       enum { 
20771 +       enum {
20772                 PROC_STATE_UNSET,    /* init-phase */
20773                 PROC_STATE_RUNNING,  /* alive */
20774 -               PROC_STATE_OVERLOADED, /* listen-queue is full, 
20775 +               PROC_STATE_OVERLOADED, /* listen-queue is full,
20776                                           don't send something to this proc for the next 2 seconds */
20777                 PROC_STATE_DIED_WAIT_FOR_PID, /* */
20778                 PROC_STATE_DIED,     /* marked as dead, should be restarted */
20779                 PROC_STATE_KILLED    /* was killed as we don't have the load anymore */
20780 -       } state; 
20781 +       } state;
20782  } fcgi_proc;
20783  
20784  typedef struct {
20785 @@ -94,20 +96,20 @@
20786          * sorted by lowest load
20787          *
20788          * whenever a job is done move it up in the list
20789 -        * until it is sorted, move it down as soon as the 
20790 +        * until it is sorted, move it down as soon as the
20791          * job is started
20792          */
20793 -       fcgi_proc *first; 
20794 -       fcgi_proc *unused_procs; 
20795 +       fcgi_proc *first;
20796 +       fcgi_proc *unused_procs;
20797  
20798 -       /* 
20799 +       /*
20800          * spawn at least min_procs, at max_procs.
20801          *
20802 -        * as soon as the load of the first entry 
20803 +        * as soon as the load of the first entry
20804          * is max_load_per_proc we spawn a new one
20805 -        * and add it to the first entry and give it 
20806 +        * and add it to the first entry and give it
20807          * the load
20808 -        * 
20809 +        *
20810          */
20811  
20812         unsigned short min_procs;
20813 @@ -119,44 +121,44 @@
20814  
20815         /*
20816          * kick the process from the list if it was not
20817 -        * used for idle_timeout until min_procs is 
20818 +        * used for idle_timeout until min_procs is
20819          * reached. this helps to get the processlist
20820          * small again we had a small peak load.
20821          *
20822          */
20823 -       
20824 +
20825         unsigned short idle_timeout;
20826 -       
20827 +
20828         /*
20829          * time after a disabled remote connection is tried to be re-enabled
20830 -        * 
20831 -        * 
20832 +        *
20833 +        *
20834          */
20835 -       
20836 +
20837         unsigned short disable_time;
20838  
20839         /*
20840          * same fastcgi processes get a little bit larger
20841 -        * than wanted. max_requests_per_proc kills a 
20842 +        * than wanted. max_requests_per_proc kills a
20843          * process after a number of handled requests.
20844          *
20845          */
20846         size_t max_requests_per_proc;
20847 -       
20848 +
20849  
20850         /* config */
20851  
20852 -       /* 
20853 -        * host:port 
20854 +       /*
20855 +        * host:port
20856          *
20857 -        * if host is one of the local IP adresses the 
20858 +        * if host is one of the local IP adresses the
20859          * whole connection is local
20860          *
20861          * if tcp/ip should be used host AND port have
20862 -        * to be specified 
20863 -        * 
20864 -        */ 
20865 -       buffer *host; 
20866 +        * to be specified
20867 +        *
20868 +        */
20869 +       buffer *host;
20870         unsigned short port;
20871  
20872         /*
20873 @@ -169,7 +171,7 @@
20874          */
20875         buffer *unixsocket;
20876  
20877 -       /* if socket is local we can start the fastcgi 
20878 +       /* if socket is local we can start the fastcgi
20879          * process ourself
20880          *
20881          * bin-path is the path to the binary
20882 @@ -177,19 +179,19 @@
20883          * check min_procs and max_procs for the number
20884          * of process to start-up
20885          */
20886 -       buffer *bin_path; 
20887 -       
20888 -       /* bin-path is set bin-environment is taken to 
20889 +       buffer *bin_path;
20890 +
20891 +       /* bin-path is set bin-environment is taken to
20892          * create the environement before starting the
20893          * FastCGI process
20894 -        * 
20895 +        *
20896          */
20897         array *bin_env;
20898 -       
20899 +
20900         array *bin_env_copy;
20901 -       
20902 +
20903         /*
20904 -        * docroot-translation between URL->phys and the 
20905 +        * docroot-translation between URL->phys and the
20906          * remote host
20907          *
20908          * reasons:
20909 @@ -208,7 +210,7 @@
20910         unsigned short mode;
20911  
20912         /*
20913 -        * check_local tell you if the phys file is stat()ed 
20914 +        * check_local tell you if the phys file is stat()ed
20915          * or not. FastCGI doesn't care if the service is
20916          * remote. If the web-server side doesn't contain
20917          * the fastcgi-files we should not stat() for them
20918 @@ -218,11 +220,11 @@
20919  
20920         /*
20921          * append PATH_INFO to SCRIPT_FILENAME
20922 -        * 
20923 +        *
20924          * php needs this if cgi.fix_pathinfo is provied
20925 -        * 
20926 +        *
20927          */
20928 -       
20929 +
20930         unsigned short break_scriptfilename_for_php;
20931  
20932         /*
20933 @@ -231,12 +233,12 @@
20934          *
20935          */
20936         unsigned short allow_xsendfile;
20937 -               
20938 +
20939         ssize_t load; /* replace by host->load */
20940  
20941         size_t max_id; /* corresponds most of the time to
20942         num_procs.
20943 -       
20944 +
20945         only if a process is killed max_id waits for the process itself
20946         to die and decrements its afterwards */
20947  
20948 @@ -245,17 +247,17 @@
20949  
20950  /*
20951   * one extension can have multiple hosts assigned
20952 - * one host can spawn additional processes on the same 
20953 + * one host can spawn additional processes on the same
20954   *   socket (if we control it)
20955   *
20956   * ext -> host -> procs
20957   *    1:n     1:n
20958   *
20959 - * if the fastcgi process is remote that whole goes down 
20960 + * if the fastcgi process is remote that whole goes down
20961   * to
20962   *
20963   * ext -> host -> procs
20964 - *    1:n     1:1 
20965 + *    1:n     1:1
20966   *
20967   * in case of PHP and FCGI_CHILDREN we have again a procs
20968   * but we don't control it directly.
20969 @@ -268,7 +270,7 @@
20970         int note_is_sent;
20971  
20972         fcgi_extension_host **hosts;
20973 -       
20974 +
20975         size_t used;
20976         size_t size;
20977  } fcgi_extension;
20978 @@ -282,10 +284,10 @@
20979  
20980  
20981  typedef struct {
20982 -       fcgi_exts *exts; 
20983 +       fcgi_exts *exts;
20984  
20985         array *ext_mapping;
20986 -       
20987 +
20988         int debug;
20989  } plugin_config;
20990  
20991 @@ -297,7 +299,7 @@
20992  
20993  typedef struct {
20994         char **ptr;
20995 -       
20996 +
20997         size_t size;
20998         size_t used;
20999  } char_array;
21000 @@ -306,44 +308,44 @@
21001  typedef struct {
21002         PLUGIN_DATA;
21003         buffer_uint fcgi_request_id;
21004 -       
21005 +
21006         buffer *fcgi_env;
21007 -       
21008 +
21009         buffer *path;
21010 -       buffer *parse_response;
21011  
21012         buffer *statuskey;
21013 -       
21014 +
21015 +       http_resp *resp;
21016 +
21017         plugin_config **config_storage;
21018 -       
21019 +
21020         plugin_config conf; /* this is only used as long as no handler_ctx is setup */
21021  } plugin_data;
21022  
21023  /* connection specific data */
21024 -typedef enum { 
21025 +typedef enum {
21026         FCGI_STATE_UNSET,
21027 -       FCGI_STATE_INIT, 
21028 -       FCGI_STATE_CONNECT_DELAYED, 
21029 -       FCGI_STATE_PREPARE_WRITE, 
21030 -       FCGI_STATE_WRITE, 
21031 -       FCGI_STATE_READ 
21032 +       FCGI_STATE_INIT,
21033 +       FCGI_STATE_CONNECT_DELAYED,
21034 +       FCGI_STATE_PREPARE_WRITE,
21035 +       FCGI_STATE_WRITE,
21036 +       FCGI_STATE_READ
21037  } fcgi_connection_state_t;
21038  
21039  typedef struct {
21040         fcgi_proc *proc;
21041         fcgi_extension_host *host;
21042         fcgi_extension *ext;
21043 -       
21044 +
21045         fcgi_connection_state_t state;
21046         time_t   state_timestamp;
21047 -       
21048 +
21049         int      reconnects; /* number of reconnect attempts */
21050 -       
21051 -       chunkqueue *rb; /* read queue */
21052 +
21053 +       chunkqueue *rb; /* the raw fcgi read-queue */
21054 +       chunkqueue *http_rb; /* the decoded read-queue for http-parsing */
21055         chunkqueue *wb; /* write queue */
21056 -       
21057 -       buffer   *response_header;
21058 -       
21059 +
21060         size_t    request_id;
21061         int       fd;        /* fd to the fastcgi process */
21062         int       fde_ndx;   /* index into the fd-event buffer */
21063 @@ -352,9 +354,9 @@
21064         int       got_proc;
21065  
21066         int       send_content_body;
21067 -       
21068 +
21069         plugin_config conf;
21070 -       
21071 +
21072         connection *remote_conn;  /* dumb pointer */
21073         plugin_data *plugin_data; /* dumb pointer */
21074  } handler_ctx;
21075 @@ -380,7 +382,7 @@
21076         return di;
21077  }
21078  
21079 -/* dummies of the statistic framework functions 
21080 +/* dummies of the statistic framework functions
21081   * they will be moved to a statistics.c later */
21082  int status_counter_inc(server *srv, const char *s, size_t len) {
21083         data_integer *di = status_counter_get_counter(srv, s, len);
21084 @@ -429,7 +431,7 @@
21085         CLEAN(".connected");
21086         CLEAN(".load");
21087  
21088 -#undef CLEAN   
21089 +#undef CLEAN
21090  
21091  #define CLEAN(x) \
21092         fastcgi_status_copy_procname(b, host, NULL); \
21093 @@ -438,33 +440,32 @@
21094  
21095         CLEAN(".load");
21096  
21097 -#undef CLEAN   
21098 +#undef CLEAN
21099  
21100         return 0;
21101  }
21102  
21103  static handler_ctx * handler_ctx_init() {
21104         handler_ctx * hctx;
21105 -       
21106 +
21107         hctx = calloc(1, sizeof(*hctx));
21108         assert(hctx);
21109 -       
21110 +
21111         hctx->fde_ndx = -1;
21112 -       
21113 -       hctx->response_header = buffer_init();
21114 -       
21115 +
21116         hctx->request_id = 0;
21117         hctx->state = FCGI_STATE_INIT;
21118         hctx->proc = NULL;
21119 -       
21120 +
21121         hctx->fd = -1;
21122 -       
21123 +
21124         hctx->reconnects = 0;
21125         hctx->send_content_body = 1;
21126  
21127         hctx->rb = chunkqueue_init();
21128 +       hctx->http_rb = chunkqueue_init();
21129         hctx->wb = chunkqueue_init();
21130 -       
21131 +
21132         return hctx;
21133  }
21134  
21135 @@ -473,10 +474,9 @@
21136                 hctx->host->load--;
21137                 hctx->host = NULL;
21138         }
21139 -       
21140 -       buffer_free(hctx->response_header);
21141  
21142         chunkqueue_free(hctx->rb);
21143 +       chunkqueue_free(hctx->http_rb);
21144         chunkqueue_free(hctx->wb);
21145  
21146         free(hctx);
21147 @@ -488,21 +488,21 @@
21148         f = calloc(1, sizeof(*f));
21149         f->unixsocket = buffer_init();
21150         f->connection_name = buffer_init();
21151 -       
21152 +
21153         f->prev = NULL;
21154         f->next = NULL;
21155 -       
21156 +
21157         return f;
21158  }
21159  
21160  void fastcgi_process_free(fcgi_proc *f) {
21161         if (!f) return;
21162 -       
21163 +
21164         fastcgi_process_free(f->next);
21165 -       
21166 +
21167         buffer_free(f->unixsocket);
21168         buffer_free(f->connection_name);
21169 -       
21170 +
21171         free(f);
21172  }
21173  
21174 @@ -519,13 +519,13 @@
21175         f->bin_env = array_init();
21176         f->bin_env_copy = array_init();
21177         f->strip_request_uri = buffer_init();
21178 -       
21179 +
21180         return f;
21181  }
21182  
21183  void fastcgi_host_free(fcgi_extension_host *h) {
21184         if (!h) return;
21185 -       
21186 +
21187         buffer_free(h->id);
21188         buffer_free(h->host);
21189         buffer_free(h->unixsocket);
21190 @@ -534,49 +534,49 @@
21191         buffer_free(h->strip_request_uri);
21192         array_free(h->bin_env);
21193         array_free(h->bin_env_copy);
21194 -       
21195 +
21196         fastcgi_process_free(h->first);
21197         fastcgi_process_free(h->unused_procs);
21198 -       
21199 +
21200         free(h);
21201 -       
21202 +
21203  }
21204  
21205  fcgi_exts *fastcgi_extensions_init() {
21206         fcgi_exts *f;
21207  
21208         f = calloc(1, sizeof(*f));
21209 -       
21210 +
21211         return f;
21212  }
21213  
21214  void fastcgi_extensions_free(fcgi_exts *f) {
21215         size_t i;
21216 -       
21217 +
21218         if (!f) return;
21219 -       
21220 +
21221         for (i = 0; i < f->used; i++) {
21222                 fcgi_extension *fe;
21223                 size_t j;
21224 -               
21225 +
21226                 fe = f->exts[i];
21227 -               
21228 +
21229                 for (j = 0; j < fe->used; j++) {
21230                         fcgi_extension_host *h;
21231 -                       
21232 +
21233                         h = fe->hosts[j];
21234 -                       
21235 +
21236                         fastcgi_host_free(h);
21237                 }
21238 -               
21239 +
21240                 buffer_free(fe->key);
21241                 free(fe->hosts);
21242 -               
21243 +
21244                 free(fe);
21245         }
21246 -       
21247 +
21248         free(f->exts);
21249 -       
21250 +
21251         free(f);
21252  }
21253  
21254 @@ -625,24 +625,25 @@
21255                 assert(fe->hosts);
21256         }
21257  
21258 -       fe->hosts[fe->used++] = fh; 
21259 +       fe->hosts[fe->used++] = fh;
21260  
21261         return 0;
21262 -       
21263 +
21264  }
21265  
21266  INIT_FUNC(mod_fastcgi_init) {
21267         plugin_data *p;
21268 -       
21269 +
21270         p = calloc(1, sizeof(*p));
21271 -       
21272 +
21273         p->fcgi_env = buffer_init();
21274 -       
21275 +
21276         p->path = buffer_init();
21277 -       p->parse_response = buffer_init();
21278 +
21279 +       p->resp = http_response_init();
21280  
21281         p->statuskey = buffer_init();
21282 -       
21283 +
21284         return p;
21285  }
21286  
21287 @@ -650,81 +651,82 @@
21288  FREE_FUNC(mod_fastcgi_free) {
21289         plugin_data *p = p_d;
21290         buffer_uint *r = &(p->fcgi_request_id);
21291 -       
21292 +
21293         UNUSED(srv);
21294  
21295         if (r->ptr) free(r->ptr);
21296 -       
21297 +
21298         buffer_free(p->fcgi_env);
21299         buffer_free(p->path);
21300 -       buffer_free(p->parse_response);
21301         buffer_free(p->statuskey);
21302 -       
21303 +
21304 +       http_response_free(p->resp);
21305 +
21306         if (p->config_storage) {
21307                 size_t i, j, n;
21308                 for (i = 0; i < srv->config_context->used; i++) {
21309                         plugin_config *s = p->config_storage[i];
21310                         fcgi_exts *exts;
21311 -                       
21312 +
21313                         if (!s) continue;
21314 -                       
21315 +
21316                         exts = s->exts;
21317  
21318                         for (j = 0; j < exts->used; j++) {
21319                                 fcgi_extension *ex;
21320 -                               
21321 +
21322                                 ex = exts->exts[j];
21323 -                               
21324 +
21325                                 for (n = 0; n < ex->used; n++) {
21326                                         fcgi_proc *proc;
21327                                         fcgi_extension_host *host;
21328 -                                       
21329 +
21330                                         host = ex->hosts[n];
21331 -                                       
21332 +
21333                                         for (proc = host->first; proc; proc = proc->next) {
21334                                                 if (proc->pid != 0) kill(proc->pid, SIGTERM);
21335 -                                               
21336 -                                               if (proc->is_local && 
21337 +
21338 +                                               if (proc->is_local &&
21339                                                     !buffer_is_empty(proc->unixsocket)) {
21340                                                         unlink(proc->unixsocket->ptr);
21341                                                 }
21342                                         }
21343 -                                       
21344 +
21345                                         for (proc = host->unused_procs; proc; proc = proc->next) {
21346                                                 if (proc->pid != 0) kill(proc->pid, SIGTERM);
21347 -                                               
21348 -                                               if (proc->is_local && 
21349 +
21350 +                                               if (proc->is_local &&
21351                                                     !buffer_is_empty(proc->unixsocket)) {
21352                                                         unlink(proc->unixsocket->ptr);
21353                                                 }
21354                                         }
21355                                 }
21356                         }
21357 -                       
21358 +
21359                         fastcgi_extensions_free(s->exts);
21360                         array_free(s->ext_mapping);
21361 -                       
21362 +
21363                         free(s);
21364                 }
21365                 free(p->config_storage);
21366         }
21367 -       
21368 +
21369         free(p);
21370 -       
21371 +
21372         return HANDLER_GO_ON;
21373  }
21374  
21375  static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
21376         char *dst;
21377 -       
21378 +
21379         if (!key || !val) return -1;
21380 -       
21381 +
21382         dst = malloc(key_len + val_len + 3);
21383         memcpy(dst, key, key_len);
21384         dst[key_len] = '=';
21385         /* add the \0 from the value */
21386         memcpy(dst + key_len + 1, val, val_len + 1);
21387 -       
21388 +
21389         if (env->size == 0) {
21390                 env->size = 16;
21391                 env->ptr = malloc(env->size * sizeof(*env->ptr));
21392 @@ -732,9 +734,9 @@
21393                 env->size += 16;
21394                 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
21395         }
21396 -       
21397 +
21398         env->ptr[env->used++] = dst;
21399 -       
21400 +
21401         return 0;
21402  }
21403  
21404 @@ -753,15 +755,15 @@
21405                         if (env->size == 0) {
21406                                 env->size = 16;
21407                                 env->ptr = malloc(env->size * sizeof(*env->ptr));
21408 -                       } else if (env->size == env->used) { 
21409 +                       } else if (env->size == env->used) {
21410                                 env->size += 16;
21411                                 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
21412                         }
21413 -                       
21414 +
21415                         b->ptr[i] = '\0';
21416  
21417                         env->ptr[env->used++] = start;
21418 -                       
21419 +
21420                         start = b->ptr + i + 1;
21421                         break;
21422                 default:
21423 @@ -794,7 +796,7 @@
21424         return 0;
21425  }
21426  
21427 -static int fcgi_spawn_connection(server *srv, 
21428 +static int fcgi_spawn_connection(server *srv,
21429                                  plugin_data *p,
21430                                  fcgi_extension_host *host,
21431                                  fcgi_proc *proc) {
21432 @@ -806,31 +808,27 @@
21433  #endif
21434         struct sockaddr_in fcgi_addr_in;
21435         struct sockaddr *fcgi_addr;
21436 -       
21437 +
21438         socklen_t servlen;
21439 -       
21440 +
21441  #ifndef HAVE_FORK
21442         return -1;
21443  #endif
21444 -       
21445 +
21446         if (p->conf.debug) {
21447                 log_error_write(srv, __FILE__, __LINE__, "sdb",
21448                                 "new proc, socket:", proc->port, proc->unixsocket);
21449         }
21450 -               
21451 +
21452         if (!buffer_is_empty(proc->unixsocket)) {
21453                 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
21454 -               
21455 +
21456  #ifdef HAVE_SYS_UN_H
21457                 fcgi_addr_un.sun_family = AF_UNIX;
21458                 strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
21459 -               
21460 -#ifdef SUN_LEN
21461 +
21462                 servlen = SUN_LEN(&fcgi_addr_un);
21463 -#else
21464 -               /* stevens says: */
21465 -               servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
21466 -#endif
21467 +
21468                 socket_type = AF_UNIX;
21469                 fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
21470  
21471 @@ -844,108 +842,108 @@
21472  #endif
21473         } else {
21474                 fcgi_addr_in.sin_family = AF_INET;
21475 -               
21476 +
21477                 if (buffer_is_empty(host->host)) {
21478                         fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
21479                 } else {
21480                         struct hostent *he;
21481 -                       
21482 +
21483                         /* set a usefull default */
21484                         fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
21485 -                       
21486 -                       
21487 +
21488 +
21489                         if (NULL == (he = gethostbyname(host->host->ptr))) {
21490 -                               log_error_write(srv, __FILE__, __LINE__, 
21491 -                                               "sdb", "gethostbyname failed: ", 
21492 +                               log_error_write(srv, __FILE__, __LINE__,
21493 +                                               "sdb", "gethostbyname failed: ",
21494                                                 h_errno, host->host);
21495                                 return -1;
21496                         }
21497 -                       
21498 +
21499                         if (he->h_addrtype != AF_INET) {
21500                                 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
21501                                 return -1;
21502                         }
21503 -                       
21504 +
21505                         if (he->h_length != sizeof(struct in_addr)) {
21506                                 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
21507                                 return -1;
21508                         }
21509 -                       
21510 +
21511                         memcpy(&(fcgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
21512 -                       
21513 +
21514                 }
21515                 fcgi_addr_in.sin_port = htons(proc->port);
21516                 servlen = sizeof(fcgi_addr_in);
21517 -               
21518 +
21519                 socket_type = AF_INET;
21520                 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
21521 -               
21522 +
21523                 buffer_copy_string(proc->connection_name, "tcp:");
21524                 buffer_append_string_buffer(proc->connection_name, host->host);
21525                 buffer_append_string(proc->connection_name, ":");
21526                 buffer_append_long(proc->connection_name, proc->port);
21527         }
21528 -       
21529 +
21530         if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
21531 -               log_error_write(srv, __FILE__, __LINE__, "ss", 
21532 +               log_error_write(srv, __FILE__, __LINE__, "ss",
21533                                 "failed:", strerror(errno));
21534                 return -1;
21535         }
21536 -       
21537 +
21538         if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
21539                 /* server is not up, spawn in  */
21540                 pid_t child;
21541                 int val;
21542 -               
21543 -               if (errno != ENOENT && 
21544 +
21545 +               if (errno != ENOENT &&
21546                     !buffer_is_empty(proc->unixsocket)) {
21547                         unlink(proc->unixsocket->ptr);
21548                 }
21549 -               
21550 +
21551                 close(fcgi_fd);
21552 -               
21553 +
21554                 /* reopen socket */
21555                 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
21556 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
21557 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
21558                                 "socket failed:", strerror(errno));
21559                         return -1;
21560                 }
21561 -               
21562 +
21563                 val = 1;
21564                 if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
21565 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
21566 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
21567                                         "socketsockopt failed:", strerror(errno));
21568                         return -1;
21569                 }
21570 -               
21571 +
21572                 /* create socket */
21573                 if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
21574 -                       log_error_write(srv, __FILE__, __LINE__, "sbs", 
21575 -                               "bind failed for:", 
21576 +                       log_error_write(srv, __FILE__, __LINE__, "sbs",
21577 +                               "bind failed for:",
21578                                 proc->connection_name,
21579                                 strerror(errno));
21580                         return -1;
21581                 }
21582 -               
21583 +
21584                 if (-1 == listen(fcgi_fd, 1024)) {
21585 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
21586 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
21587                                 "listen failed:", strerror(errno));
21588                         return -1;
21589                 }
21590 -               
21591 -#ifdef HAVE_FORK       
21592 +
21593 +#ifndef _WIN32
21594                 switch ((child = fork())) {
21595                 case 0: {
21596                         size_t i = 0;
21597                         char *c;
21598                         char_array env;
21599                         char_array arg;
21600 -                       
21601 +
21602                         /* create environment */
21603                         env.ptr = NULL;
21604                         env.size = 0;
21605                         env.used = 0;
21606 -                       
21607 +
21608                         arg.ptr = NULL;
21609                         arg.size = 0;
21610                         arg.used = 0;
21611 @@ -955,18 +953,18 @@
21612                                 dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
21613                                 close(fcgi_fd);
21614                         }
21615 -                       
21616 +
21617                         /* we don't need the client socket */
21618                         for (i = 3; i < 256; i++) {
21619                                 close(i);
21620                         }
21621 -                       
21622 +
21623                         /* build clean environment */
21624                         if (host->bin_env_copy->used) {
21625                                 for (i = 0; i < host->bin_env_copy->used; i++) {
21626                                         data_string *ds = (data_string *)host->bin_env_copy->data[i];
21627                                         char *ge;
21628 -                                       
21629 +
21630                                         if (NULL != (ge = getenv(ds->value->ptr))) {
21631                                                 env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
21632                                         }
21633 @@ -974,39 +972,39 @@
21634                         } else {
21635                                 for (i = 0; environ[i]; i++) {
21636                                         char *eq;
21637 -                                       
21638 +
21639                                         if (NULL != (eq = strchr(environ[i], '='))) {
21640                                                 env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
21641                                         }
21642                                 }
21643                         }
21644 -                       
21645 +
21646                         /* create environment */
21647                         for (i = 0; i < host->bin_env->used; i++) {
21648                                 data_string *ds = (data_string *)host->bin_env->data[i];
21649 -                               
21650 +
21651                                 env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
21652                         }
21653 -                       
21654 +
21655                         for (i = 0; i < env.used; i++) {
21656                                 /* search for PHP_FCGI_CHILDREN */
21657                                 if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
21658                         }
21659 -                       
21660 +
21661                         /* not found, add a default */
21662                         if (i == env.used) {
21663                                 env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
21664                         }
21665 -                       
21666 +
21667                         env.ptr[env.used] = NULL;
21668  
21669                         parse_binpath(&arg, host->bin_path);
21670 -                       
21671 +
21672                         /* chdir into the base of the bin-path,
21673                          * search for the last / */
21674                         if (NULL != (c = strrchr(arg.ptr[0], '/'))) {
21675                                 *c = '\0';
21676 -                       
21677 +
21678                                 /* change to the physical directory */
21679                                 if (-1 == chdir(arg.ptr[0])) {
21680                                         *c = '/';
21681 @@ -1018,12 +1016,12 @@
21682  
21683                         /* exec the cgi */
21684                         execve(arg.ptr[0], arg.ptr, env.ptr);
21685 -                       
21686 -                       log_error_write(srv, __FILE__, __LINE__, "sbs", 
21687 +
21688 +                       log_error_write(srv, __FILE__, __LINE__, "sbs",
21689                                         "execve failed for:", host->bin_path, strerror(errno));
21690 -                       
21691 +
21692                         exit(errno);
21693 -                       
21694 +
21695                         break;
21696                 }
21697                 case -1:
21698 @@ -1031,17 +1029,17 @@
21699                         break;
21700                 default:
21701                         /* father */
21702 -                       
21703 +
21704                         /* wait */
21705                         select(0, NULL, NULL, NULL, &tv);
21706 -                       
21707 +
21708                         switch (waitpid(child, &status, WNOHANG)) {
21709                         case 0:
21710                                 /* child still running after timeout, good */
21711                                 break;
21712                         case -1:
21713                                 /* no PID found ? should never happen */
21714 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
21715 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
21716                                                 "pid not found:", strerror(errno));
21717                                 return -1;
21718                         default:
21719 @@ -1049,10 +1047,10 @@
21720                                                 "the fastcgi-backend", host->bin_path, "failed to start:");
21721                                 /* the child should not terminate at all */
21722                                 if (WIFEXITED(status)) {
21723 -                                       log_error_write(srv, __FILE__, __LINE__, "sdb", 
21724 -                                                       "child exited with status", 
21725 +                                       log_error_write(srv, __FILE__, __LINE__, "sdb",
21726 +                                                       "child exited with status",
21727                                                         WEXITSTATUS(status), host->bin_path);
21728 -                                       log_error_write(srv, __FILE__, __LINE__, "s", 
21729 +                                       log_error_write(srv, __FILE__, __LINE__, "s",
21730                                                         "if you try do run PHP as FastCGI backend make sure you use the FastCGI enabled version.\n"
21731                                                         "You can find out if it is the right one by executing 'php -v' and it should display '(cgi-fcgi)' "
21732                                                         "in the output, NOT (cgi) NOR (cli)\n"
21733 @@ -1060,8 +1058,8 @@
21734                                         log_error_write(srv, __FILE__, __LINE__, "s",
21735                                                         "If this is PHP on Gentoo add fastcgi to the USE flags");
21736                                 } else if (WIFSIGNALED(status)) {
21737 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
21738 -                                                       "terminated by signal:", 
21739 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
21740 +                                                       "terminated by signal:",
21741                                                         WTERMSIG(status));
21742  
21743                                         if (WTERMSIG(status) == 11) {
21744 @@ -1071,8 +1069,8 @@
21745                                                                 "If this is PHP try to remove the byte-code caches for now and try again.");
21746                                         }
21747                                 } else {
21748 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
21749 -                                                       "child died somehow:", 
21750 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
21751 +                                                       "child died somehow:",
21752                                                         status);
21753                                 }
21754                                 return -1;
21755 @@ -1082,26 +1080,26 @@
21756                         proc->pid = child;
21757                         proc->last_used = srv->cur_ts;
21758                         proc->is_local = 1;
21759 -                                               
21760 +
21761                         break;
21762                 }
21763  #endif
21764         } else {
21765                 proc->is_local = 0;
21766                 proc->pid = 0;
21767 -               
21768 +
21769                 if (p->conf.debug) {
21770                         log_error_write(srv, __FILE__, __LINE__, "sb",
21771                                         "(debug) socket is already used, won't spawn:",
21772                                         proc->connection_name);
21773                 }
21774         }
21775 -       
21776 +
21777         proc->state = PROC_STATE_RUNNING;
21778         host->active_procs++;
21779 -       
21780 +
21781         close(fcgi_fd);
21782 -       
21783 +
21784         return 0;
21785  }
21786  
21787 @@ -1111,93 +1109,93 @@
21788         data_unset *du;
21789         size_t i = 0;
21790         buffer *fcgi_mode = buffer_init();
21791 -       
21792 -       config_values_t cv[] = { 
21793 +
21794 +       config_values_t cv[] = {
21795                 { "fastcgi.server",              NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
21796                 { "fastcgi.debug",               NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
21797                 { "fastcgi.map-extensions",      NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
21798                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
21799         };
21800 -       
21801 +
21802         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
21803 -       
21804 +
21805         for (i = 0; i < srv->config_context->used; i++) {
21806                 plugin_config *s;
21807                 array *ca;
21808 -               
21809 +
21810                 s = malloc(sizeof(plugin_config));
21811                 s->exts          = fastcgi_extensions_init();
21812                 s->debug         = 0;
21813                 s->ext_mapping   = array_init();
21814 -               
21815 +
21816                 cv[0].destination = s->exts;
21817                 cv[1].destination = &(s->debug);
21818                 cv[2].destination = s->ext_mapping;
21819 -               
21820 +
21821                 p->config_storage[i] = s;
21822                 ca = ((data_config *)srv->config_context->data[i])->value;
21823 -       
21824 +
21825                 if (0 != config_insert_values_global(srv, ca, cv)) {
21826                         return HANDLER_ERROR;
21827                 }
21828 -               
21829 -               /* 
21830 +
21831 +               /*
21832                  * <key> = ( ... )
21833                  */
21834 -               
21835 +
21836                 if (NULL != (du = array_get_element(ca, "fastcgi.server"))) {
21837                         size_t j;
21838                         data_array *da = (data_array *)du;
21839 -                       
21840 +
21841                         if (du->type != TYPE_ARRAY) {
21842 -                               log_error_write(srv, __FILE__, __LINE__, "sss", 
21843 +                               log_error_write(srv, __FILE__, __LINE__, "sss",
21844                                                 "unexpected type for key: ", "fastcgi.server", "array of strings");
21845 -                               
21846 +
21847                                 return HANDLER_ERROR;
21848                         }
21849 -                       
21850 -                       
21851 -                       /* 
21852 -                        * fastcgi.server = ( "<ext>" => ( ... ), 
21853 +
21854 +
21855 +                       /*
21856 +                        * fastcgi.server = ( "<ext>" => ( ... ),
21857                          *                    "<ext>" => ( ... ) )
21858                          */
21859 -                       
21860 +
21861                         for (j = 0; j < da->value->used; j++) {
21862                                 size_t n;
21863                                 data_array *da_ext = (data_array *)da->value->data[j];
21864 -                               
21865 +
21866                                 if (da->value->data[j]->type != TYPE_ARRAY) {
21867 -                                       log_error_write(srv, __FILE__, __LINE__, "sssbs", 
21868 -                                                       "unexpected type for key: ", "fastcgi.server", 
21869 +                                       log_error_write(srv, __FILE__, __LINE__, "sssbs",
21870 +                                                       "unexpected type for key: ", "fastcgi.server",
21871                                                         "[", da->value->data[j]->key, "](string)");
21872 -                                       
21873 +
21874                                         return HANDLER_ERROR;
21875                                 }
21876 -                               
21877 -                               /* 
21878 -                                * da_ext->key == name of the extension 
21879 +
21880 +                               /*
21881 +                                * da_ext->key == name of the extension
21882                                  */
21883 -                               
21884 -                               /* 
21885 -                                * fastcgi.server = ( "<ext>" => 
21886 -                                *                     ( "<host>" => ( ... ), 
21887 +
21888 +                               /*
21889 +                                * fastcgi.server = ( "<ext>" =>
21890 +                                *                     ( "<host>" => ( ... ),
21891                                  *                       "<host>" => ( ... )
21892 -                                *                     ), 
21893 +                                *                     ),
21894                                  *                    "<ext>" => ... )
21895                                  */
21896 -                                       
21897 +
21898                                 for (n = 0; n < da_ext->value->used; n++) {
21899                                         data_array *da_host = (data_array *)da_ext->value->data[n];
21900 -                                       
21901 +
21902                                         fcgi_extension_host *host;
21903 -                                       
21904 -                                       config_values_t fcv[] = { 
21905 +
21906 +                                       config_values_t fcv[] = {
21907                                                 { "host",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
21908                                                 { "docroot",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
21909                                                 { "mode",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
21910                                                 { "socket",            NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 3 */
21911                                                 { "bin-path",          NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 4 */
21912 -                                               
21913 +
21914                                                 { "check-local",       NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },      /* 5 */
21915                                                 { "port",              NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 6 */
21916                                                 { "min-procs-not-working",         NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 7 this is broken for now */
21917 @@ -1205,28 +1203,28 @@
21918                                                 { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 9 */
21919                                                 { "idle-timeout",      NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 10 */
21920                                                 { "disable-time",      NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 11 */
21921 -                                               
21922 +
21923                                                 { "bin-environment",   NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },        /* 12 */
21924                                                 { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },     /* 13 */
21925 -                                               
21926 +
21927                                                 { "broken-scriptfilename", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },  /* 14 */
21928                                                 { "allow-x-send-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },      /* 15 */
21929                                                 { "strip-request-uri",  NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },      /* 16 */
21930 -                                               
21931 +
21932                                                 { NULL,                NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
21933                                         };
21934 -                                       
21935 +
21936                                         if (da_host->type != TYPE_ARRAY) {
21937 -                                               log_error_write(srv, __FILE__, __LINE__, "ssSBS", 
21938 -                                                               "unexpected type for key:", 
21939 -                                                               "fastcgi.server", 
21940 +                                               log_error_write(srv, __FILE__, __LINE__, "ssSBS",
21941 +                                                               "unexpected type for key:",
21942 +                                                               "fastcgi.server",
21943                                                                 "[", da_host->key, "](string)");
21944 -                                               
21945 +
21946                                                 return HANDLER_ERROR;
21947                                         }
21948 -                                       
21949 +
21950                                         host = fastcgi_host_init();
21951 -                                       
21952 +
21953                                         buffer_copy_string_buffer(host->id, da_host->key);
21954  
21955                                         host->check_local  = 1;
21956 @@ -1238,13 +1236,13 @@
21957                                         host->disable_time = 60;
21958                                         host->break_scriptfilename_for_php = 0;
21959                                         host->allow_xsendfile = 0; /* handle X-LIGHTTPD-send-file */
21960 -                                       
21961 +
21962                                         fcv[0].destination = host->host;
21963                                         fcv[1].destination = host->docroot;
21964                                         fcv[2].destination = fcgi_mode;
21965                                         fcv[3].destination = host->unixsocket;
21966                                         fcv[4].destination = host->bin_path;
21967 -                                       
21968 +
21969                                         fcv[5].destination = &(host->check_local);
21970                                         fcv[6].destination = &(host->port);
21971                                         fcv[7].destination = &(host->min_procs);
21972 @@ -1252,35 +1250,35 @@
21973                                         fcv[9].destination = &(host->max_load_per_proc);
21974                                         fcv[10].destination = &(host->idle_timeout);
21975                                         fcv[11].destination = &(host->disable_time);
21976 -                                       
21977 +
21978                                         fcv[12].destination = host->bin_env;
21979                                         fcv[13].destination = host->bin_env_copy;
21980                                         fcv[14].destination = &(host->break_scriptfilename_for_php);
21981                                         fcv[15].destination = &(host->allow_xsendfile);
21982                                         fcv[16].destination = host->strip_request_uri;
21983 -                                       
21984 +
21985                                         if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
21986                                                 return HANDLER_ERROR;
21987                                         }
21988 -                                                       
21989 -                                       if ((!buffer_is_empty(host->host) || host->port) && 
21990 +
21991 +                                       if ((!buffer_is_empty(host->host) || host->port) &&
21992                                             !buffer_is_empty(host->unixsocket)) {
21993 -                                               log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", 
21994 +                                               log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
21995                                                                 "either host/port or socket have to be set in:",
21996 -                                                               da->key, "= (", 
21997 +                                                               da->key, "= (",
21998                                                                 da_ext->key, " => (",
21999                                                                 da_host->key, " ( ...");
22000  
22001                                                 return HANDLER_ERROR;
22002                                         }
22003 -                                       
22004 +
22005                                         if (!buffer_is_empty(host->unixsocket)) {
22006                                                 /* unix domain socket */
22007 -                                               
22008 +
22009                                                 if (host->unixsocket->used > UNIX_PATH_MAX - 2) {
22010 -                                                       log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", 
22011 +                                                       log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
22012                                                                         "unixsocket is too long in:",
22013 -                                                                       da->key, "= (", 
22014 +                                                                       da->key, "= (",
22015                                                                         da_ext->key, " => (",
22016                                                                         da_host->key, " ( ...");
22017  
22018 @@ -1288,37 +1286,37 @@
22019                                                 }
22020                                         } else {
22021                                                 /* tcp/ip */
22022 -                                               
22023 -                                               if (buffer_is_empty(host->host) && 
22024 +
22025 +                                               if (buffer_is_empty(host->host) &&
22026                                                     buffer_is_empty(host->bin_path)) {
22027 -                                                       log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", 
22028 +                                                       log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
22029                                                                         "host or binpath have to be set in:",
22030 -                                                                       da->key, "= (", 
22031 +                                                                       da->key, "= (",
22032                                                                         da_ext->key, " => (",
22033                                                                         da_host->key, " ( ...");
22034 -                                                       
22035 +
22036                                                         return HANDLER_ERROR;
22037                                                 } else if (host->port == 0) {
22038 -                                                       log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", 
22039 +                                                       log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
22040                                                                         "port has to be set in:",
22041 -                                                                       da->key, "= (", 
22042 +                                                                       da->key, "= (",
22043                                                                         da_ext->key, " => (",
22044                                                                         da_host->key, " ( ...");
22045  
22046                                                         return HANDLER_ERROR;
22047                                                 }
22048                                         }
22049 -                                               
22050 -                                       if (!buffer_is_empty(host->bin_path)) { 
22051 +
22052 +                                       if (!buffer_is_empty(host->bin_path)) {
22053                                                 /* a local socket + self spawning */
22054                                                 size_t pno;
22055  
22056                                                 /* HACK:  just to make sure the adaptive spawing is disabled */
22057                                                 host->min_procs = host->max_procs;
22058 -                                               
22059 +
22060                                                 if (host->min_procs > host->max_procs) host->max_procs = host->min_procs;
22061                                                 if (host->max_load_per_proc < 1) host->max_load_per_proc = 0;
22062 -                                               
22063 +
22064                                                 if (s->debug) {
22065                                                         log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd",
22066                                                                         "--- fastcgi spawning local",
22067 @@ -1328,7 +1326,7 @@
22068                                                                         "\n\tmin-procs:", host->min_procs,
22069                                                                         "\n\tmax-procs:", host->max_procs);
22070                                                 }
22071 -                                               
22072 +
22073                                                 for (pno = 0; pno < host->min_procs; pno++) {
22074                                                         fcgi_proc *proc;
22075  
22076 @@ -1343,7 +1341,7 @@
22077                                                                 buffer_append_string(proc->unixsocket, "-");
22078                                                                 buffer_append_long(proc->unixsocket, pno);
22079                                                         }
22080 -                                                       
22081 +
22082                                                         if (s->debug) {
22083                                                                 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
22084                                                                                 "--- fastcgi spawning",
22085 @@ -1351,7 +1349,7 @@
22086                                                                                 "\n\tsocket", host->unixsocket,
22087                                                                                 "\n\tcurrent:", pno, "/", host->min_procs);
22088                                                         }
22089 -                                                       
22090 +
22091                                                         if (fcgi_spawn_connection(srv, p, host, proc)) {
22092                                                                 log_error_write(srv, __FILE__, __LINE__, "s",
22093                                                                                 "[ERROR]: spawning fcgi failed.");
22094 @@ -1359,35 +1357,35 @@
22095                                                         }
22096  
22097                                                         fastcgi_status_init(srv, p->statuskey, host, proc);
22098 -                                                       
22099 +
22100                                                         proc->next = host->first;
22101                                                         if (host->first)        host->first->prev = proc;
22102 -                                                       
22103 +
22104                                                         host->first = proc;
22105                                                 }
22106                                         } else {
22107                                                 fcgi_proc *proc;
22108 -                                               
22109 +
22110                                                 proc = fastcgi_process_init();
22111                                                 proc->id = host->num_procs++;
22112                                                 host->max_id++;
22113                                                 host->active_procs++;
22114                                                 proc->state = PROC_STATE_RUNNING;
22115 -                                               
22116 +
22117                                                 if (buffer_is_empty(host->unixsocket)) {
22118                                                         proc->port = host->port;
22119                                                 } else {
22120                                                         buffer_copy_string_buffer(proc->unixsocket, host->unixsocket);
22121                                                 }
22122 -                                               
22123 +
22124                                                 fastcgi_status_init(srv, p->statuskey, host, proc);
22125  
22126                                                 host->first = proc;
22127 -                                               
22128 +
22129                                                 host->min_procs = 1;
22130                                                 host->max_procs = 1;
22131                                         }
22132 -                                       
22133 +
22134                                         if (!buffer_is_empty(fcgi_mode)) {
22135                                                 if (strcmp(fcgi_mode->ptr, "responder") == 0) {
22136                                                         host->mode = FCGI_RESPONDER;
22137 @@ -1411,16 +1409,16 @@
22138                         }
22139                 }
22140         }
22141 -       
22142 +
22143         buffer_free(fcgi_mode);
22144 -       
22145 +
22146         return HANDLER_GO_ON;
22147  }
22148  
22149  static int fcgi_set_state(server *srv, handler_ctx *hctx, fcgi_connection_state_t state) {
22150         hctx->state = state;
22151         hctx->state_timestamp = srv->cur_ts;
22152 -       
22153 +
22154         return 0;
22155  }
22156  
22157 @@ -1429,13 +1427,13 @@
22158         size_t m = 0;
22159         size_t i;
22160         buffer_uint *r = &(p->fcgi_request_id);
22161 -       
22162 +
22163         UNUSED(srv);
22164  
22165         for (i = 0; i < r->used; i++) {
22166                 if (r->ptr[i] > m) m = r->ptr[i];
22167         }
22168 -       
22169 +
22170         if (r->size == 0) {
22171                 r->size = 16;
22172                 r->ptr = malloc(sizeof(*r->ptr) * r->size);
22173 @@ -1443,54 +1441,54 @@
22174                 r->size += 16;
22175                 r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
22176         }
22177 -       
22178 +
22179         r->ptr[r->used++] = ++m;
22180 -       
22181 +
22182         return m;
22183  }
22184  
22185  static int fcgi_requestid_del(server *srv, plugin_data *p, size_t request_id) {
22186         size_t i;
22187         buffer_uint *r = &(p->fcgi_request_id);
22188 -       
22189 +
22190         UNUSED(srv);
22191  
22192         for (i = 0; i < r->used; i++) {
22193                 if (r->ptr[i] == request_id) break;
22194         }
22195 -       
22196 +
22197         if (i != r->used) {
22198                 /* found */
22199 -               
22200 +
22201                 if (i != r->used - 1) {
22202                         r->ptr[i] = r->ptr[r->used - 1];
22203                 }
22204                 r->used--;
22205         }
22206 -       
22207 +
22208         return 0;
22209  }
22210  void fcgi_connection_close(server *srv, handler_ctx *hctx) {
22211         plugin_data *p;
22212         connection  *con;
22213 -       
22214 +
22215         if (NULL == hctx) return;
22216 -       
22217 +
22218         p    = hctx->plugin_data;
22219         con  = hctx->remote_conn;
22220 -       
22221 +
22222         if (con->mode != p->id) {
22223                 WP();
22224                 return;
22225         }
22226 -       
22227 +
22228         if (hctx->fd != -1) {
22229                 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
22230                 fdevent_unregister(srv->ev, hctx->fd);
22231                 close(hctx->fd);
22232                 srv->cur_fds--;
22233         }
22234 -       
22235 +
22236         if (hctx->request_id != 0) {
22237                 fcgi_requestid_del(srv, p, hctx->request_id);
22238         }
22239 @@ -1499,7 +1497,7 @@
22240                 if (hctx->got_proc) {
22241                         /* after the connect the process gets a load */
22242                         hctx->proc->load--;
22243 -                       
22244 +
22245                         status_counter_dec(srv, CONST_STR_LEN("fastcgi.active-requests"));
22246  
22247                         fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
22248 @@ -1509,39 +1507,39 @@
22249  
22250                         if (p->conf.debug) {
22251                                 log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
22252 -                                               "released proc:", 
22253 -                                               "pid:", hctx->proc->pid, 
22254 -                                               "socket:", hctx->proc->connection_name, 
22255 +                                               "released proc:",
22256 +                                               "pid:", hctx->proc->pid,
22257 +                                               "socket:", hctx->proc->connection_name,
22258                                                 "load:", hctx->proc->load);
22259                         }
22260                 }
22261         }
22262  
22263 -       
22264 +
22265         handler_ctx_free(hctx);
22266 -       con->plugin_ctx[p->id] = NULL;  
22267 +       con->plugin_ctx[p->id] = NULL;
22268  }
22269  
22270  static int fcgi_reconnect(server *srv, handler_ctx *hctx) {
22271         plugin_data *p    = hctx->plugin_data;
22272 -       
22273 -       /* child died 
22274 -        * 
22275 -        * 1. 
22276 -        * 
22277 +
22278 +       /* child died
22279 +        *
22280 +        * 1.
22281 +        *
22282          * connect was ok, connection was accepted
22283          * but the php accept loop checks after the accept if it should die or not.
22284 -        * 
22285 -        * if yes we can only detect it at a write() 
22286 -        * 
22287 +        *
22288 +        * if yes we can only detect it at a write()
22289 +        *
22290          * next step is resetting this attemp and setup a connection again
22291 -        * 
22292 +        *
22293          * if we have more then 5 reconnects for the same request, die
22294 -        * 
22295 -        * 2. 
22296 -        * 
22297 +        *
22298 +        * 2.
22299 +        *
22300          * we have a connection but the child died by some other reason
22301 -        * 
22302 +        *
22303          */
22304  
22305         if (hctx->fd != -1) {
22306 @@ -1551,59 +1549,59 @@
22307                 srv->cur_fds--;
22308                 hctx->fd = -1;
22309         }
22310 -       
22311 +
22312         fcgi_requestid_del(srv, p, hctx->request_id);
22313 -       
22314 +
22315         fcgi_set_state(srv, hctx, FCGI_STATE_INIT);
22316 -       
22317 +
22318         hctx->request_id = 0;
22319         hctx->reconnects++;
22320 -       
22321 +
22322         if (p->conf.debug > 2) {
22323                 if (hctx->proc) {
22324                         log_error_write(srv, __FILE__, __LINE__, "sdb",
22325 -                                       "release proc for reconnect:", 
22326 +                                       "release proc for reconnect:",
22327                                         hctx->proc->pid, hctx->proc->connection_name);
22328                 } else {
22329                         log_error_write(srv, __FILE__, __LINE__, "sb",
22330 -                                       "release proc for reconnect:", 
22331 +                                       "release proc for reconnect:",
22332                                         hctx->host->unixsocket);
22333                 }
22334         }
22335  
22336 -       if (hctx->proc && hctx->got_proc) {     
22337 +       if (hctx->proc && hctx->got_proc) {
22338                 hctx->proc->load--;
22339         }
22340  
22341         /* perhaps another host gives us more luck */
22342         hctx->host->load--;
22343         hctx->host = NULL;
22344 -       
22345 +
22346         return 0;
22347  }
22348  
22349  
22350  static handler_t fcgi_connection_reset(server *srv, connection *con, void *p_d) {
22351         plugin_data *p = p_d;
22352 -       
22353 +
22354         fcgi_connection_close(srv, con->plugin_ctx[p->id]);
22355 -       
22356 +
22357         return HANDLER_GO_ON;
22358  }
22359  
22360  
22361  static int fcgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
22362         size_t len;
22363 -       
22364 +
22365         if (!key || !val) return -1;
22366 -       
22367 +
22368         len = key_len + val_len;
22369 -       
22370 +
22371         len += key_len > 127 ? 4 : 1;
22372         len += val_len > 127 ? 4 : 1;
22373 -       
22374 +
22375         buffer_prepare_append(env, len);
22376 -       
22377 +
22378         if (key_len > 127) {
22379                 env->ptr[env->used++] = ((key_len >> 24) & 0xff) | 0x80;
22380                 env->ptr[env->used++] = (key_len >> 16) & 0xff;
22381 @@ -1612,7 +1610,7 @@
22382         } else {
22383                 env->ptr[env->used++] = (key_len >> 0) & 0xff;
22384         }
22385 -       
22386 +
22387         if (val_len > 127) {
22388                 env->ptr[env->used++] = ((val_len >> 24) & 0xff) | 0x80;
22389                 env->ptr[env->used++] = (val_len >> 16) & 0xff;
22390 @@ -1621,12 +1619,12 @@
22391         } else {
22392                 env->ptr[env->used++] = (val_len >> 0) & 0xff;
22393         }
22394 -       
22395 +
22396         memcpy(env->ptr + env->used, key, key_len);
22397         env->used += key_len;
22398         memcpy(env->ptr + env->used, val, val_len);
22399         env->used += val_len;
22400 -       
22401 +
22402         return 0;
22403  }
22404  
22405 @@ -1639,11 +1637,11 @@
22406         header->contentLengthB1 = (contentLength >> 8) & 0xff;
22407         header->paddingLength = paddingLength;
22408         header->reserved = 0;
22409 -       
22410 +
22411         return 0;
22412  }
22413  /**
22414 - * 
22415 + *
22416   * returns
22417   *   -1 error
22418   *    0 connected
22419 @@ -1665,26 +1663,23 @@
22420         struct sockaddr_un fcgi_addr_un;
22421  #endif
22422         socklen_t servlen;
22423 -       
22424 +
22425         fcgi_extension_host *host = hctx->host;
22426         fcgi_proc *proc   = hctx->proc;
22427         int fcgi_fd       = hctx->fd;
22428 -       
22429 +
22430         memset(&fcgi_addr, 0, sizeof(fcgi_addr));
22431 -       
22432 +
22433         if (!buffer_is_empty(proc->unixsocket)) {
22434  #ifdef HAVE_SYS_UN_H
22435                 /* use the unix domain socket */
22436                 fcgi_addr_un.sun_family = AF_UNIX;
22437                 strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
22438 -#ifdef SUN_LEN
22439 +
22440                 servlen = SUN_LEN(&fcgi_addr_un);
22441 -#else
22442 -               /* stevens says: */
22443 -               servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
22444 -#endif
22445 +
22446                 fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
22447 -       
22448 +
22449                 if (buffer_is_empty(proc->connection_name)) {
22450                         /* on remote spawing we have to set the connection-name now */
22451                         buffer_copy_string(proc->connection_name, "unix:");
22452 @@ -1695,16 +1690,18 @@
22453  #endif
22454         } else {
22455                 fcgi_addr_in.sin_family = AF_INET;
22456 +
22457                 if (0 == inet_aton(host->host->ptr, &(fcgi_addr_in.sin_addr))) {
22458 -                       log_error_write(srv, __FILE__, __LINE__, "sbs", 
22459 -                                       "converting IP-adress failed for", host->host, 
22460 +                       log_error_write(srv, __FILE__, __LINE__, "sbs",
22461 +                                       "converting IP-adress failed for", host->host,
22462                                         "\nBe sure to specify an IP address here");
22463 -                       
22464 +
22465                         return -1;
22466                 }
22467 +
22468                 fcgi_addr_in.sin_port = htons(proc->port);
22469                 servlen = sizeof(fcgi_addr_in);
22470 -               
22471 +
22472                 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
22473  
22474                 if (buffer_is_empty(proc->connection_name)) {
22475 @@ -1715,20 +1712,20 @@
22476                         buffer_append_long(proc->connection_name, proc->port);
22477                 }
22478         }
22479 -       
22480 +
22481         if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
22482 -               if (errno == EINPROGRESS || 
22483 +               if (errno == EINPROGRESS ||
22484                     errno == EALREADY ||
22485                     errno == EINTR) {
22486                         if (hctx->conf.debug > 2) {
22487 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
22488 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
22489                                         "connect delayed, will continue later:", proc->connection_name);
22490                         }
22491 -                       
22492 +
22493                         return CONNECTION_DELAYED;
22494                 } else if (errno == EAGAIN) {
22495                         if (hctx->conf.debug) {
22496 -                               log_error_write(srv, __FILE__, __LINE__, "sbsd", 
22497 +                               log_error_write(srv, __FILE__, __LINE__, "sbsd",
22498                                         "This means that the you have more incoming requests than your fastcgi-backend can handle in parallel. "
22499                                         "Perhaps it helps to spawn more fastcgi backend or php-children, if not decrease server.max-connections."
22500                                         "The load for this fastcgi backend", proc->connection_name, "is", proc->load);
22501 @@ -1736,8 +1733,8 @@
22502  
22503                         return CONNECTION_OVERLOADED;
22504                 } else {
22505 -                       log_error_write(srv, __FILE__, __LINE__, "sssb", 
22506 -                                       "connect failed:", 
22507 +                       log_error_write(srv, __FILE__, __LINE__, "sssb",
22508 +                                       "connect failed:",
22509                                         strerror(errno), "on",
22510                                         proc->connection_name);
22511  
22512 @@ -1747,7 +1744,7 @@
22513  
22514         hctx->reconnects = 0;
22515         if (hctx->conf.debug > 1) {
22516 -               log_error_write(srv, __FILE__, __LINE__, "sd", 
22517 +               log_error_write(srv, __FILE__, __LINE__, "sd",
22518                                 "connect succeeded: ", fcgi_fd);
22519         }
22520  
22521 @@ -1756,21 +1753,21 @@
22522  
22523  static int fcgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
22524         size_t i;
22525 -       
22526 +
22527         for (i = 0; i < con->request.headers->used; i++) {
22528                 data_string *ds;
22529 -               
22530 +
22531                 ds = (data_string *)con->request.headers->data[i];
22532 -               
22533 +
22534                 if (ds->value->used && ds->key->used) {
22535                         size_t j;
22536                         buffer_reset(srv->tmp_buf);
22537 -                       
22538 +
22539                         if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
22540                                 BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
22541                                 srv->tmp_buf->used--;
22542                         }
22543 -                       
22544 +
22545                         buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
22546                         for (j = 0; j < ds->key->used - 1; j++) {
22547                                 char c = '_';
22548 @@ -1784,20 +1781,20 @@
22549                                 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
22550                         }
22551                         srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
22552 -                       
22553 +
22554                         fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
22555                 }
22556         }
22557 -       
22558 +
22559         for (i = 0; i < con->environment->used; i++) {
22560                 data_string *ds;
22561 -               
22562 +
22563                 ds = (data_string *)con->environment->data[i];
22564 -               
22565 +
22566                 if (ds->value->used && ds->key->used) {
22567                         size_t j;
22568                         buffer_reset(srv->tmp_buf);
22569 -                       
22570 +
22571                         buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
22572                         for (j = 0; j < ds->key->used - 1; j++) {
22573                                 char c = '_';
22574 @@ -1811,11 +1808,11 @@
22575                                 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
22576                         }
22577                         srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
22578 -                       
22579 +
22580                         fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
22581                 }
22582         }
22583 -       
22584 +
22585         return 0;
22586  }
22587  
22588 @@ -1824,24 +1821,24 @@
22589         FCGI_BeginRequestRecord beginRecord;
22590         FCGI_Header header;
22591         buffer *b;
22592 -       
22593 +
22594         char buf[32];
22595         const char *s;
22596  #ifdef HAVE_IPV6
22597         char b2[INET6_ADDRSTRLEN + 1];
22598  #endif
22599 -       
22600 +
22601         plugin_data *p    = hctx->plugin_data;
22602         fcgi_extension_host *host= hctx->host;
22603  
22604         connection *con   = hctx->remote_conn;
22605         server_socket *srv_sock = con->srv_socket;
22606 -       
22607 +
22608         sock_addr our_addr;
22609         socklen_t our_addr_len;
22610 -       
22611 +
22612         /* send FCGI_BEGIN_REQUEST */
22613 -       
22614 +
22615         fcgi_header(&(beginRecord.header), FCGI_BEGIN_REQUEST, request_id, sizeof(beginRecord.body), 0);
22616         beginRecord.body.roleB0 = host->mode;
22617         beginRecord.body.roleB1 = 0;
22618 @@ -1849,21 +1846,21 @@
22619         memset(beginRecord.body.reserved, 0, sizeof(beginRecord.body.reserved));
22620  
22621         b = chunkqueue_get_append_buffer(hctx->wb);
22622 -       
22623 +
22624         buffer_copy_memory(b, (const char *)&beginRecord, sizeof(beginRecord));
22625 -       
22626 +
22627         /* send FCGI_PARAMS */
22628         buffer_prepare_copy(p->fcgi_env, 1024);
22629  
22630  
22631         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
22632 -       
22633 +
22634         if (con->server_name->used) {
22635                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
22636         } else {
22637  #ifdef HAVE_IPV6
22638 -               s = inet_ntop(srv_sock->addr.plain.sa_family, 
22639 -                             srv_sock->addr.plain.sa_family == AF_INET6 ? 
22640 +               s = inet_ntop(srv_sock->addr.plain.sa_family,
22641 +                             srv_sock->addr.plain.sa_family == AF_INET6 ?
22642                               (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
22643                               (const void *) &(srv_sock->addr.ipv4.sin_addr),
22644                               b2, sizeof(b2)-1);
22645 @@ -1872,50 +1869,50 @@
22646  #endif
22647                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
22648         }
22649 -       
22650 +
22651         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
22652 -       
22653 -       ltostr(buf, 
22654 +
22655 +       ltostr(buf,
22656  #ifdef HAVE_IPV6
22657                ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
22658  #else
22659                ntohs(srv_sock->addr.ipv4.sin_port)
22660  #endif
22661                );
22662 -       
22663 +
22664         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
22665 -       
22666 +
22667         /* get the server-side of the connection to the client */
22668         our_addr_len = sizeof(our_addr);
22669 -       
22670 +
22671         if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
22672                 s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
22673         } else {
22674                 s = inet_ntop_cache_get_ip(srv, &(our_addr));
22675         }
22676         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
22677 -       
22678 -       ltostr(buf, 
22679 +
22680 +       ltostr(buf,
22681  #ifdef HAVE_IPV6
22682                ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
22683  #else
22684                ntohs(con->dst_addr.ipv4.sin_port)
22685  #endif
22686                );
22687 -       
22688 +
22689         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
22690 -       
22691 +
22692         s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
22693         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
22694 -       
22695 +
22696         if (!buffer_is_empty(con->authed_user)) {
22697                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_USER"),
22698                              CONST_BUF_LEN(con->authed_user));
22699         }
22700 -       
22701 +
22702         if (con->request.content_length > 0 && host->mode != FCGI_AUTHORIZER) {
22703                 /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
22704 -               
22705 +
22706                 /* request.content_length < SSIZE_MAX, see request.c */
22707                 ltostr(buf, con->request.content_length);
22708                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
22709 @@ -1930,12 +1927,12 @@
22710                  */
22711  
22712                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
22713 -               
22714 +
22715                 if (!buffer_is_empty(con->request.pathinfo)) {
22716                         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
22717 -                       
22718 +
22719                         /* PATH_TRANSLATED is only defined if PATH_INFO is set */
22720 -                       
22721 +
22722                         if (!buffer_is_empty(host->docroot)) {
22723                                 buffer_copy_string_buffer(p->path, host->docroot);
22724                         } else {
22725 @@ -1957,27 +1954,27 @@
22726          */
22727  
22728         if (!buffer_is_empty(host->docroot)) {
22729 -               /* 
22730 -                * rewrite SCRIPT_FILENAME 
22731 -                * 
22732 +               /*
22733 +                * rewrite SCRIPT_FILENAME
22734 +                *
22735                  */
22736 -               
22737 +
22738                 buffer_copy_string_buffer(p->path, host->docroot);
22739                 buffer_append_string_buffer(p->path, con->uri.path);
22740 -               
22741 +
22742                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
22743                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
22744         } else {
22745                 buffer_copy_string_buffer(p->path, con->physical.path);
22746 -               
22747 -               /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself 
22748 -                * 
22749 +
22750 +               /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself
22751 +                *
22752                  * see src/sapi/cgi_main.c, init_request_info()
22753                  */
22754                 if (host->break_scriptfilename_for_php) {
22755                         buffer_append_string_buffer(p->path, con->request.pathinfo);
22756                 }
22757 -               
22758 +
22759                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
22760                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
22761         }
22762 @@ -1987,7 +1984,7 @@
22763                 /**
22764                  * /app1/index/list
22765                  *
22766 -                * stripping /app1 or /app1/ should lead to 
22767 +                * stripping /app1 or /app1/ should lead to
22768                  *
22769                  * /index/list
22770                  *
22771 @@ -2001,7 +1998,7 @@
22772                     0 == strncmp(con->request.orig_uri->ptr, host->strip_request_uri->ptr, host->strip_request_uri->used - 1)) {
22773                         /* the left is the same */
22774  
22775 -                       fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"), 
22776 +                       fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"),
22777                                         con->request.orig_uri->ptr + (host->strip_request_uri->used - 2),
22778                                         con->request.orig_uri->used - (host->strip_request_uri->used - 2));
22779                 } else {
22780 @@ -2018,26 +2015,26 @@
22781         } else {
22782                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
22783         }
22784 -       
22785 +
22786         s = get_http_method_name(con->request.http_method);
22787         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
22788         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
22789         s = get_http_version_name(con->request.http_version);
22790         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
22791 -       
22792 +
22793  #ifdef USE_OPENSSL
22794         if (srv_sock->is_ssl) {
22795                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
22796         }
22797  #endif
22798 -       
22799 -       
22800 +
22801 +
22802         fcgi_env_add_request_headers(srv, con, p);
22803 -       
22804 +
22805         fcgi_header(&(header), FCGI_PARAMS, request_id, p->fcgi_env->used, 0);
22806         buffer_append_memory(b, (const char *)&header, sizeof(header));
22807         buffer_append_memory(b, (const char *)p->fcgi_env->ptr, p->fcgi_env->used);
22808 -       
22809 +
22810         fcgi_header(&(header), FCGI_PARAMS, request_id, 0, 0);
22811         buffer_append_memory(b, (const char *)&header, sizeof(header));
22812  
22813 @@ -2057,7 +2054,7 @@
22814  
22815                         /* we announce toWrite octects
22816                          * now take all the request_content chunk that we need to fill this request
22817 -                        * */   
22818 +                        * */
22819  
22820                         b = chunkqueue_get_append_buffer(hctx->wb);
22821                         fcgi_header(&(header), FCGI_STDIN, request_id, weWant, 0);
22822 @@ -2080,16 +2077,16 @@
22823                                         if (weHave > weWant - written) weHave = weWant - written;
22824  
22825                                         if (p->conf.debug > 10) {
22826 -                                               fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n", 
22827 -                                                               __FILE__, __LINE__, 
22828 -                                                               weHave, 
22829 -                                                               req_c->offset, 
22830 -                                                               req_c->file.length, 
22831 +                                               fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n",
22832 +                                                               __FILE__, __LINE__,
22833 +                                                               weHave,
22834 +                                                               req_c->offset,
22835 +                                                               req_c->file.length,
22836                                                                 req_c->file.name->ptr);
22837                                         }
22838  
22839                                         assert(weHave != 0);
22840 -                                       
22841 +
22842                                         chunkqueue_append_file(hctx->wb, req_c->file.name, req_c->offset, weHave);
22843  
22844                                         req_c->offset += weHave;
22845 @@ -2104,7 +2101,7 @@
22846                                          * - we reference the tempfile from the request-content-queue several times
22847                                          *   if the req_c is larger than FCGI_MAX_LENGTH
22848                                          * - we can't simply cleanup the request-content-queue as soon as possible
22849 -                                        *   as it would remove the tempfiles 
22850 +                                        *   as it would remove the tempfiles
22851                                          * - the idea is to 'steal' the tempfiles and attach the is_temp flag to the last
22852                                          *   referencing chunk of the fastcgi-write-queue
22853                                          *
22854 @@ -2141,7 +2138,7 @@
22855                                         req_c->offset += weHave;
22856                                         req_cq->bytes_out += weHave;
22857                                         written += weHave;
22858 -                                       
22859 +
22860                                         hctx->wb->bytes_in += weHave;
22861  
22862                                         if (req_c->offset == req_c->mem->used - 1) {
22863 @@ -2155,12 +2152,12 @@
22864                                         break;
22865                                 }
22866                         }
22867 -                       
22868 +
22869                         b->used++; /* add virtual \0 */
22870                         offset += weWant;
22871                 }
22872         }
22873 -       
22874 +
22875         b = chunkqueue_get_append_buffer(hctx->wb);
22876         /* terminate STDIN */
22877         fcgi_header(&(header), FCGI_STDIN, request_id, 0, 0);
22878 @@ -2175,118 +2172,19 @@
22879                 if ((i+1) % 16 == 0) {
22880                         size_t j;
22881                         for (j = i-15; j <= i; j++) {
22882 -                               fprintf(stderr, "%c", 
22883 +                               fprintf(stderr, "%c",
22884                                         isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.');
22885                         }
22886                         fprintf(stderr, "\n");
22887                 }
22888         }
22889  #endif
22890 -       
22891 -       return 0;
22892 -}
22893 -
22894 -static int fcgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
22895 -       char *s, *ns;
22896 -       
22897 -       handler_ctx *hctx = con->plugin_ctx[p->id];
22898 -       fcgi_extension_host *host= hctx->host;
22899 -       
22900 -       UNUSED(srv);
22901  
22902 -       buffer_copy_string_buffer(p->parse_response, in);
22903 -       
22904 -       /* search for \n */
22905 -       for (s = p->parse_response->ptr; NULL != (ns = strchr(s, '\n')); s = ns + 1) {
22906 -               char *key, *value;
22907 -               int key_len;
22908 -               data_string *ds;
22909 -               
22910 -               /* a good day. Someone has read the specs and is sending a \r\n to us */
22911 -               
22912 -               if (ns > p->parse_response->ptr &&
22913 -                   *(ns-1) == '\r') {
22914 -                       *(ns-1) = '\0';
22915 -               }
22916 -               
22917 -               ns[0] = '\0';
22918 -               
22919 -               key = s;
22920 -               if (NULL == (value = strchr(s, ':'))) {
22921 -                       /* we expect: "<key>: <value>\n" */
22922 -                       continue;
22923 -               }
22924 -               
22925 -               key_len = value - key;
22926 -               
22927 -               value++;
22928 -               /* strip WS */
22929 -               while (*value == ' ' || *value == '\t') value++;
22930 -               
22931 -               if (host->mode != FCGI_AUTHORIZER ||
22932 -                   !(con->http_status == 0 ||
22933 -                     con->http_status == 200)) {
22934 -                       /* authorizers shouldn't affect the response headers sent back to the client */
22935 -                       
22936 -                       /* don't forward Status: */
22937 -                       if (0 != strncasecmp(key, "Status", key_len)) {
22938 -                               if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
22939 -                                       ds = data_response_init();
22940 -                               }
22941 -                               buffer_copy_string_len(ds->key, key, key_len);
22942 -                               buffer_copy_string(ds->value, value);
22943 -                               
22944 -                               array_insert_unique(con->response.headers, (data_unset *)ds);
22945 -                       }
22946 -               }
22947 -               
22948 -               switch(key_len) {
22949 -               case 4:
22950 -                       if (0 == strncasecmp(key, "Date", key_len)) {
22951 -                               con->parsed_response |= HTTP_DATE;
22952 -                       }
22953 -                       break;
22954 -               case 6:
22955 -                       if (0 == strncasecmp(key, "Status", key_len)) {
22956 -                               con->http_status = strtol(value, NULL, 10);
22957 -                               con->parsed_response |= HTTP_STATUS;
22958 -                       }
22959 -                       break;
22960 -               case 8:
22961 -                       if (0 == strncasecmp(key, "Location", key_len)) {
22962 -                               con->parsed_response |= HTTP_LOCATION;
22963 -                       }
22964 -                       break;
22965 -               case 10:
22966 -                       if (0 == strncasecmp(key, "Connection", key_len)) {
22967 -                               con->response.keep_alive = (0 == strcasecmp(value, "Keep-Alive")) ? 1 : 0;
22968 -                               con->parsed_response |= HTTP_CONNECTION;
22969 -                       }
22970 -                       break;
22971 -               case 14:
22972 -                       if (0 == strncasecmp(key, "Content-Length", key_len)) {
22973 -                               con->response.content_length = strtol(value, NULL, 10);
22974 -                               con->parsed_response |= HTTP_CONTENT_LENGTH;
22975 -                               
22976 -                               if (con->response.content_length < 0) con->response.content_length = 0;
22977 -                       }
22978 -                       break;
22979 -               default:
22980 -                       break;
22981 -               }
22982 -       }
22983 -       
22984 -       /* CGI/1.1 rev 03 - 7.2.1.2 */
22985 -       if ((con->parsed_response & HTTP_LOCATION) &&
22986 -           !(con->parsed_response & HTTP_STATUS)) {
22987 -               con->http_status = 302;
22988 -       }
22989 -       
22990         return 0;
22991  }
22992  
22993  typedef struct {
22994 -       buffer  *b; 
22995 +       buffer  *b;
22996         size_t   len;
22997         int      type;
22998         int      padding;
22999 @@ -2327,9 +2225,9 @@
23000                 return -1;
23001         }
23002  
23003 -       /* we have at least a header, now check how much me have to fetch */ 
23004 +       /* we have at least a header, now check how much me have to fetch */
23005         header = (FCGI_Header *)(packet->b->ptr);
23006 -                       
23007 +
23008         packet->len = (header->contentLengthB0 | (header->contentLengthB1 << 8)) + header->paddingLength;
23009         packet->request_id = (header->requestIdB0 | (header->requestIdB1 << 8));
23010         packet->type = header->type;
23011 @@ -2348,7 +2246,7 @@
23012                         size_t weHave = c->mem->used - c->offset - offset - 1;
23013  
23014                         if (weHave > weWant) weHave = weWant;
23015 -                                               
23016 +
23017                         buffer_append_string_len(packet->b, c->mem->ptr + c->offset + offset, weHave);
23018  
23019                         /* we only skipped the first 8 bytes as they are the fcgi header */
23020 @@ -2380,65 +2278,37 @@
23021         }
23022  
23023         chunkqueue_remove_finished_chunks(hctx->rb);
23024 -       
23025 +
23026         return 0;
23027  }
23028  
23029  static int fcgi_demux_response(server *srv, handler_ctx *hctx) {
23030         int fin = 0;
23031 -       int toread;
23032 -       ssize_t r;
23033 -       
23034 +
23035         plugin_data *p    = hctx->plugin_data;
23036         connection *con   = hctx->remote_conn;
23037 -       int fcgi_fd       = hctx->fd;
23038         fcgi_extension_host *host= hctx->host;
23039         fcgi_proc *proc   = hctx->proc;
23040 -       
23041 -       /* 
23042 -        * check how much we have to read 
23043 -        */
23044 -       if (ioctl(hctx->fd, FIONREAD, &toread)) {
23045 -               log_error_write(srv, __FILE__, __LINE__, "sd", 
23046 -                               "unexpected end-of-file (perhaps the fastcgi process died):",
23047 -                               fcgi_fd);
23048 -               return -1;
23049 -       }
23050 -       
23051 -       /* init read-buffer */
23052 -       
23053 -       if (toread > 0) {
23054 -               buffer *b;
23055 -
23056 -               b = chunkqueue_get_append_buffer(hctx->rb);
23057 -               buffer_prepare_copy(b, toread + 1);
23058 -
23059 -               /* append to read-buffer */
23060 -               if (-1 == (r = read(hctx->fd, b->ptr, toread))) {
23061 -                       log_error_write(srv, __FILE__, __LINE__, "sds", 
23062 -                                       "unexpected end-of-file (perhaps the fastcgi process died):",
23063 -                                       fcgi_fd, strerror(errno));
23064 -                       return -1;
23065 -               }
23066 -               
23067 -               /* this should be catched by the b > 0 above */
23068 -               assert(r);
23069  
23070 -               b->used = r + 1; /* one extra for the fake \0 */
23071 -               b->ptr[b->used - 1] = '\0';
23072 -       } else {
23073 -               log_error_write(srv, __FILE__, __LINE__, "ssdsb", 
23074 +       switch(srv->network_backend_read(srv, con, hctx->fd, hctx->rb)) {
23075 +       case NETWORK_STATUS_WAIT_FOR_EVENT:
23076 +               /* we are only triggered when there is a event */
23077 +               log_error_write(srv, __FILE__, __LINE__, "ssdsb",
23078                                 "unexpected end-of-file (perhaps the fastcgi process died):",
23079                                 "pid:", proc->pid,
23080                                 "socket:", proc->connection_name);
23081 -               
23082 +               return -1;
23083 +       case NETWORK_STATUS_SUCCESS:
23084 +               break;
23085 +       default:
23086 +               log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi-read failed");
23087                 return -1;
23088         }
23089  
23090         /*
23091          * parse the fastcgi packets and forward the content to the write-queue
23092          *
23093 -        */     
23094 +        */
23095         while (fin == 0) {
23096                 fastcgi_response_packet packet;
23097  
23098 @@ -2454,92 +2324,135 @@
23099  
23100                         /* is the header already finished */
23101                         if (0 == con->file_started) {
23102 -                               char *c;
23103 -                               size_t blen;
23104 -                               data_string *ds;
23105 -                                       
23106 -                               /* search for header terminator 
23107 -                                * 
23108 -                                * if we start with \r\n check if last packet terminated with \r\n
23109 -                                * if we start with \n check if last packet terminated with \n
23110 -                                * search for \r\n\r\n
23111 -                                * search for \n\n
23112 -                                */
23113 -
23114 -                               if (hctx->response_header->used == 0) {
23115 -                                       buffer_copy_string_buffer(hctx->response_header, packet.b);
23116 -                               } else {
23117 -                                       buffer_append_string_buffer(hctx->response_header, packet.b);
23118 -                               }
23119 -
23120 -                               if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\r\n\r\n")))) {
23121 -                                       blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 4;
23122 -                                       hctx->response_header->used = (c - hctx->response_header->ptr) + 3;
23123 -                                       c += 4; /* point the the start of the response */
23124 -                               } else if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\n\n")))) {
23125 -                                       blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 2;
23126 -                                       hctx->response_header->used = c - hctx->response_header->ptr + 2;
23127 -                                       c += 2; /* point the the start of the response */
23128 -                               } else {
23129 -                                       /* no luck, no header found */
23130 +                               int have_content_length = 0;
23131 +                               int need_more = 0;
23132 +                               size_t i;
23133 +
23134 +                               /* append the current packet to the chunk queue */
23135 +                               chunkqueue_append_buffer(hctx->http_rb, packet.b);
23136 +                               http_response_reset(p->resp);
23137 +
23138 +                               switch(http_response_parse_cq(hctx->http_rb, p->resp)) {
23139 +                               case PARSE_ERROR:
23140 +                                       /* parsing the response header failed */
23141 +
23142 +                                       con->http_status = 502; /* Bad Gateway */
23143 +
23144 +                                       return 1;
23145 +                               case PARSE_NEED_MORE:
23146 +                                       need_more = 1;
23147 +                                       break; /* leave the loop */
23148 +                               case PARSE_SUCCESS:
23149                                         break;
23150 +                               default:
23151 +                                       /* should not happen */
23152 +                                       SEGFAULT();
23153                                 }
23154  
23155 -                               /* parse the response header */
23156 -                               fcgi_response_parse(srv, con, p, hctx->response_header);
23157 +                               if (need_more) break;
23158  
23159 -                               con->file_started = 1;
23160 +                               chunkqueue_remove_finished_chunks(hctx->http_rb);
23161  
23162 -                               if (host->mode == FCGI_AUTHORIZER &&
23163 -                                   (con->http_status == 0 ||
23164 -                                    con->http_status == 200)) {
23165 -                                       /* a authorizer with approved the static request, ignore the content here */
23166 -                                       hctx->send_content_body = 0;
23167 -                               }
23168 -
23169 -                               if (host->allow_xsendfile &&
23170 -                                   NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-LIGHTTPD-send-file"))) {
23171 -                                       stat_cache_entry *sce;
23172 -
23173 -                                       if (HANDLER_ERROR != stat_cache_get_entry(srv, con, ds->value, &sce)) {
23174 -                                               /* found */
23175 -
23176 -                                               http_chunk_append_file(srv, con, ds->value, 0, sce->st.st_size);
23177 -                                               hctx->send_content_body = 0; /* ignore the content */
23178 -                                               joblist_append(srv, con);
23179 +                               con->http_status = p->resp->status;
23180 +
23181 +                               /* handle the header fields */
23182 +                               if (host->mode == FCGI_AUTHORIZER) {
23183 +                                       /* auth mode is a bit different */
23184 +
23185 +                                       if (con->http_status == 0 ||
23186 +                                           con->http_status == 200) {
23187 +                                               /* a authorizer with approved the static request, ignore the content here */
23188 +                                               hctx->send_content_body = 0;
23189                                         }
23190                                 }
23191  
23192 +                               /* copy the http-headers */
23193 +                               for (i = 0; i < p->resp->headers->used; i++) {
23194 +                                       const char *ign[] = { "Status", NULL };
23195 +                                       size_t j;
23196 +                                       data_string *ds;
23197 +
23198 +                                       data_string *header = (data_string *)p->resp->headers->data[i];
23199 +
23200 +                                       /* ignore all headers in AUTHORIZER mode */
23201 +                                       if (host->mode == FCGI_AUTHORIZER) continue;
23202 +
23203 +                                       /* some headers are ignored by default */
23204 +                                       for (j = 0; ign[j]; j++) {
23205 +                                               if (0 == strcasecmp(ign[j], header->key->ptr)) break;
23206 +                                       }
23207 +                                       if (ign[j]) continue;
23208 +
23209 +                                       if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) {
23210 +                                               /* CGI/1.1 rev 03 - 7.2.1.2 */
23211 +                                               con->http_status = 302;
23212 +                                       } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) {
23213 +                                               have_content_length = 1;
23214 +                                       } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-Sendfile")) || 
23215 +                                                  0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-LIGHTTPD-send-file"))) {
23216 +                                               
23217 +                                               stat_cache_entry *sce;
23218                                                 
23219 -                               if (hctx->send_content_body && blen > 1) {                                              
23220 -                                       /* enable chunked-transfer-encoding */
23221 +                                               if (host->allow_xsendfile &&
23222 +                                                   HANDLER_ERROR != stat_cache_get_entry(srv, con, header->value, &sce)) {
23223 +                                                       http_chunk_append_file(srv, con, header->value, 0, sce->st.st_size);
23224 +                                                       hctx->send_content_body = 0; /* ignore the content */
23225 +                                       
23226 +                                                       joblist_append(srv, con);
23227 +                                               }
23228 +
23229 +                                               continue; /* ignore header */
23230 +                                       }
23231 +                                       
23232 +                                       if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
23233 +                                               ds = data_response_init();
23234 +                                       }
23235 +                                       buffer_copy_string_buffer(ds->key, header->key);
23236 +                                       buffer_copy_string_buffer(ds->value, header->value);
23237 +
23238 +                                       array_insert_unique(con->response.headers, (data_unset *)ds);
23239 +                               }
23240 +
23241 +                               /* header is complete ... go on with the body */
23242 +
23243 +                               con->file_started = 1;
23244 +
23245 +                               if (hctx->send_content_body) {
23246 +                                       chunk *c = hctx->http_rb->first;
23247 +
23248 +                                       /* if we don't have a content-length enable chunked encoding 
23249 +                                        * if possible
23250 +                                        * 
23251 +                                        * TODO: move this to a later stage in the filter-queue
23252 +                                        *  */
23253                                         if (con->request.http_version == HTTP_VERSION_1_1 &&
23254 -                                           !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
23255 +                                           !have_content_length) {
23256                                                 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
23257                                         }
23258  
23259 -                                       http_chunk_append_mem(srv, con, c, blen);
23260 +                                       /* copy the rest of the data */
23261 +                                       for (c = hctx->http_rb->first; c; c = c->next) {
23262 +                                               if (c->mem->used > 1) {
23263 +                                                       http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
23264 +                                                       c->offset = c->mem->used - 1;
23265 +                                               }
23266 +                                       }
23267 +                                       chunkqueue_remove_finished_chunks(hctx->http_rb);
23268                                         joblist_append(srv, con);
23269                                 }
23270                         } else if (hctx->send_content_body && packet.b->used > 1) {
23271 -                               if (con->request.http_version == HTTP_VERSION_1_1 &&
23272 -                                   !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
23273 -                                       /* enable chunked-transfer-encoding */
23274 -                                       con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
23275 -                               }
23276 -
23277                                 http_chunk_append_mem(srv, con, packet.b->ptr, packet.b->used);
23278                                 joblist_append(srv, con);
23279                         }
23280                         break;
23281                 case FCGI_STDERR:
23282 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
23283 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
23284                                         "FastCGI-stderr:", packet.b);
23285 -                       
23286 +
23287                         break;
23288                 case FCGI_END_REQUEST:
23289                         con->file_finished = 1;
23290 -                       
23291 +
23292                         if (host->mode != FCGI_AUTHORIZER ||
23293                             !(con->http_status == 0 ||
23294                               con->http_status == 200)) {
23295 @@ -2547,39 +2460,39 @@
23296                                 http_chunk_append_mem(srv, con, NULL, 0);
23297                                 joblist_append(srv, con);
23298                         }
23299 -                       
23300 +
23301                         fin = 1;
23302                         break;
23303                 default:
23304 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
23305 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
23306                                         "FastCGI: header.type not handled: ", packet.type);
23307                         break;
23308                 }
23309                 buffer_free(packet.b);
23310         }
23311 -       
23312 +
23313         return fin;
23314  }
23315  
23316  static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_host *host) {
23317         fcgi_proc *proc;
23318 -       
23319 +
23320         for (proc = host->first; proc; proc = proc->next) {
23321                 int status;
23322  
23323                 if (p->conf.debug > 2) {
23324 -                       log_error_write(srv, __FILE__, __LINE__,  "sbdddd", 
23325 -                                       "proc:", 
23326 +                       log_error_write(srv, __FILE__, __LINE__,  "sbdddd",
23327 +                                       "proc:",
23328                                         proc->connection_name,
23329                                         proc->state,
23330                                         proc->is_local,
23331                                         proc->load,
23332                                         proc->pid);
23333                 }
23334 -               
23335 -               /* 
23336 +
23337 +               /*
23338                  * if the remote side is overloaded, we check back after <n> seconds
23339 -                * 
23340 +                *
23341                  */
23342                 switch (proc->state) {
23343                 case PROC_STATE_KILLED:
23344 @@ -2592,13 +2505,13 @@
23345                         break;
23346                 case PROC_STATE_OVERLOADED:
23347                         if (srv->cur_ts <= proc->disabled_until) break;
23348 -                       
23349 +
23350                         proc->state = PROC_STATE_RUNNING;
23351                         host->active_procs++;
23352 -                       
23353 -                       log_error_write(srv, __FILE__, __LINE__,  "sbdb", 
23354 -                                       "fcgi-server re-enabled:", 
23355 -                                       host->host, host->port, 
23356 +
23357 +                       log_error_write(srv, __FILE__, __LINE__,  "sbdb",
23358 +                                       "fcgi-server re-enabled:",
23359 +                                       host->host, host->port,
23360                                         host->unixsocket);
23361                         break;
23362                 case PROC_STATE_DIED_WAIT_FOR_PID:
23363 @@ -2606,7 +2519,7 @@
23364                         if (!proc->is_local) break;
23365  
23366                         /* the child should not terminate at all */
23367 -                       
23368 +#ifndef _WIN32
23369                         switch(waitpid(proc->pid, &status, WNOHANG)) {
23370                         case 0:
23371                                 /* child is still alive */
23372 @@ -2616,45 +2529,45 @@
23373                         default:
23374                                 if (WIFEXITED(status)) {
23375  #if 0
23376 -                                       log_error_write(srv, __FILE__, __LINE__, "sdsd", 
23377 +                                       log_error_write(srv, __FILE__, __LINE__, "sdsd",
23378                                                         "child exited, pid:", proc->pid,
23379                                                         "status:", WEXITSTATUS(status));
23380  #endif
23381                                 } else if (WIFSIGNALED(status)) {
23382 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
23383 -                                                       "child signaled:", 
23384 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
23385 +                                                       "child signaled:",
23386                                                         WTERMSIG(status));
23387                                 } else {
23388 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
23389 -                                                       "child died somehow:", 
23390 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
23391 +                                                       "child died somehow:",
23392                                                         status);
23393                                 }
23394 -                               
23395 +
23396                                 proc->state = PROC_STATE_DIED;
23397                                 break;
23398                         }
23399 -
23400 +#endif
23401                         /* fall through if we have a dead proc now */
23402                         if (proc->state != PROC_STATE_DIED) break;
23403  
23404                 case PROC_STATE_DIED:
23405 -                       /* local proc get restarted by us, 
23406 +                       /* local proc get restarted by us,
23407                          * remote ones hopefully by the admin */
23408 -                       
23409 +
23410                         if (proc->is_local) {
23411                                 /* we still have connections bound to this proc,
23412                                  * let them terminate first */
23413                                 if (proc->load != 0) break;
23414 -                       
23415 +
23416                                 /* restart the child */
23417 -                               
23418 +
23419                                 if (p->conf.debug) {
23420                                         log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
23421                                                         "--- fastcgi spawning",
23422                                                         "\n\tsocket", proc->connection_name,
23423                                                         "\n\tcurrent:", 1, "/", host->min_procs);
23424                                 }
23425 -                               
23426 +
23427                                 if (fcgi_spawn_connection(srv, p, host, proc)) {
23428                                         log_error_write(srv, __FILE__, __LINE__, "s",
23429                                                         "ERROR: spawning fcgi failed.");
23430 @@ -2662,18 +2575,18 @@
23431                                 }
23432                         } else {
23433                                 if (srv->cur_ts <= proc->disabled_until) break;
23434 -                       
23435 +
23436                                 proc->state = PROC_STATE_RUNNING;
23437                                 host->active_procs++;
23438 -                       
23439 -                               log_error_write(srv, __FILE__, __LINE__,  "sb", 
23440 -                                               "fcgi-server re-enabled:", 
23441 +
23442 +                               log_error_write(srv, __FILE__, __LINE__,  "sb",
23443 +                                               "fcgi-server re-enabled:",
23444                                                 proc->connection_name);
23445                         }
23446                         break;
23447                 }
23448         }
23449 -       
23450 +
23451         return 0;
23452  }
23453  
23454 @@ -2682,19 +2595,19 @@
23455         fcgi_extension_host *host= hctx->host;
23456         connection *con   = hctx->remote_conn;
23457         fcgi_proc  *proc;
23458 -       
23459 +
23460         int ret;
23461  
23462 -       /* sanity check */      
23463 +       /* sanity check */
23464         if (!host ||
23465             ((!host->host->used || !host->port) && !host->unixsocket->used)) {
23466 -               log_error_write(srv, __FILE__, __LINE__, "sxddd", 
23467 +               log_error_write(srv, __FILE__, __LINE__, "sxddd",
23468                                 "write-req: error",
23469                                 host,
23470                                 host->host->used,
23471                                 host->port,
23472                                 host->unixsocket->used);
23473 -                       
23474 +
23475                 hctx->proc->disabled_until = srv->cur_ts + 10;
23476                 hctx->proc->state = PROC_STATE_DIED;
23477  
23478 @@ -2705,12 +2618,12 @@
23479         if (hctx->state == FCGI_STATE_CONNECT_DELAYED) {
23480                 int socket_error;
23481                 socklen_t socket_error_len = sizeof(socket_error);
23482 -                       
23483 +
23484                 /* try to finish the connect() */
23485                 if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
23486 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
23487 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
23488                                         "getsockopt failed:", strerror(errno));
23489 -                       
23490 +
23491                         hctx->proc->disabled_until = srv->cur_ts + 10;
23492                         hctx->proc->state = PROC_STATE_DIED;
23493  
23494 @@ -2719,12 +2632,12 @@
23495                 if (socket_error != 0) {
23496                         if (!hctx->proc->is_local || p->conf.debug) {
23497                                 /* local procs get restarted */
23498 -                               
23499 +
23500                                 log_error_write(srv, __FILE__, __LINE__, "sssb",
23501 -                                               "establishing connection failed:", strerror(socket_error), 
23502 +                                               "establishing connection failed:", strerror(socket_error),
23503                                                 "socket:", hctx->proc->connection_name);
23504                         }
23505 -       
23506 +
23507                         hctx->proc->disabled_until = srv->cur_ts + 5;
23508  
23509                         if (hctx->proc->is_local) {
23510 @@ -2732,17 +2645,17 @@
23511                         } else {
23512                                 hctx->proc->state = PROC_STATE_DIED;
23513                         }
23514 -       
23515 +
23516                         hctx->proc->state = PROC_STATE_DIED;
23517 -               
23518 +
23519                         fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
23520                         buffer_append_string(p->statuskey, ".died");
23521  
23522                         status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
23523 -               
23524 +
23525                         return HANDLER_ERROR;
23526                 }
23527 -               /* go on with preparing the request */ 
23528 +               /* go on with preparing the request */
23529                 hctx->state = FCGI_STATE_PREPARE_WRITE;
23530         }
23531  
23532 @@ -2755,14 +2668,14 @@
23533                 /* do we have a running process for this host (max-procs) ? */
23534                 hctx->proc = NULL;
23535  
23536 -               for (proc = hctx->host->first; 
23537 -                    proc && proc->state != PROC_STATE_RUNNING; 
23538 +               for (proc = hctx->host->first;
23539 +                    proc && proc->state != PROC_STATE_RUNNING;
23540                      proc = proc->next);
23541 -                       
23542 +
23543                 /* all childs are dead */
23544                 if (proc == NULL) {
23545                         hctx->fde_ndx = -1;
23546 -               
23547 +
23548                         return HANDLER_ERROR;
23549                 }
23550  
23551 @@ -2775,50 +2688,50 @@
23552                 }
23553  
23554                 ret = host->unixsocket->used ? AF_UNIX : AF_INET;
23555 -               
23556 +
23557                 if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
23558                         if (errno == EMFILE ||
23559                             errno == EINTR) {
23560 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
23561 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
23562                                                 "wait for fd at connection:", con->fd);
23563 -                               
23564 +
23565                                 return HANDLER_WAIT_FOR_FD;
23566                         }
23567 -                       
23568 -                       log_error_write(srv, __FILE__, __LINE__, "ssdd", 
23569 +
23570 +                       log_error_write(srv, __FILE__, __LINE__, "ssdd",
23571                                         "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
23572                         return HANDLER_ERROR;
23573                 }
23574                 hctx->fde_ndx = -1;
23575 -               
23576 +
23577                 srv->cur_fds++;
23578 -               
23579 +
23580                 fdevent_register(srv->ev, hctx->fd, fcgi_handle_fdevent, hctx);
23581 -               
23582 +
23583                 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
23584 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
23585 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
23586                                         "fcntl failed:", strerror(errno));
23587 -                       
23588 +
23589                         return HANDLER_ERROR;
23590                 }
23591 -                       
23592 +
23593                 if (hctx->proc->is_local) {
23594                         hctx->pid = hctx->proc->pid;
23595                 }
23596 -                       
23597 +
23598                 switch (fcgi_establish_connection(srv, hctx)) {
23599                 case CONNECTION_DELAYED:
23600                         /* connection is in progress, wait for an event and call getsockopt() below */
23601 -                       
23602 +
23603                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23604 -                       
23605 +
23606                         fcgi_set_state(srv, hctx, FCGI_STATE_CONNECT_DELAYED);
23607                         return HANDLER_WAIT_FOR_EVENT;
23608                 case CONNECTION_OVERLOADED:
23609                         /* cool down the backend, it is overloaded
23610                          * -> EAGAIN */
23611  
23612 -                       log_error_write(srv, __FILE__, __LINE__, "ssdsd", 
23613 +                       log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23614                                 "backend is overloaded, we disable it for a 2 seconds and send the request to another backend instead:",
23615                                 "reconnects:", hctx->reconnects,
23616                                 "load:", host->load);
23617 @@ -2831,7 +2744,7 @@
23618                         buffer_append_string(p->statuskey, ".overloaded");
23619  
23620                         status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
23621 -                       
23622 +
23623                         return HANDLER_ERROR;
23624                 case CONNECTION_DEAD:
23625                         /* we got a hard error from the backend like
23626 @@ -2840,19 +2753,19 @@
23627                          *
23628                          * for check if the host is back in 5 seconds
23629                          *  */
23630 -                       
23631 +
23632                         hctx->proc->disabled_until = srv->cur_ts + 5;
23633                         if (hctx->proc->is_local) {
23634                                 hctx->proc->state = PROC_STATE_DIED_WAIT_FOR_PID;
23635                         } else {
23636                                 hctx->proc->state = PROC_STATE_DIED;
23637                         }
23638 -       
23639 -                       log_error_write(srv, __FILE__, __LINE__, "ssdsd", 
23640 +
23641 +                       log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23642                                 "backend died, we disable it for a 5 seconds and send the request to another backend instead:",
23643                                 "reconnects:", hctx->reconnects,
23644                                 "load:", host->load);
23645 -       
23646 +
23647                         fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
23648                         buffer_append_string(p->statuskey, ".died");
23649  
23650 @@ -2863,19 +2776,19 @@
23651                         /* everything is ok, go on */
23652  
23653                         fcgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
23654 -                       
23655 +
23656                         break;
23657                 case CONNECTION_UNSET:
23658                         break;
23659                 }
23660 -               
23661 +
23662         case FCGI_STATE_PREPARE_WRITE:
23663                 /* ok, we have the connection */
23664 -               
23665 +
23666                 hctx->proc->load++;
23667                 hctx->proc->last_used = srv->cur_ts;
23668                 hctx->got_proc = 1;
23669 -       
23670 +
23671                 status_counter_inc(srv, CONST_STR_LEN("fastcgi.requests"));
23672                 status_counter_inc(srv, CONST_STR_LEN("fastcgi.active-requests"));
23673  
23674 @@ -2898,9 +2811,9 @@
23675  
23676                 if (p->conf.debug) {
23677                         log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
23678 -                                       "got proc:", 
23679 -                                       "pid:", hctx->proc->pid, 
23680 -                                       "socket:", hctx->proc->connection_name, 
23681 +                                       "got proc:",
23682 +                                       "pid:", hctx->proc->pid,
23683 +                                       "socket:", hctx->proc->connection_name,
23684                                         "load:", hctx->proc->load);
23685                 }
23686  
23687 @@ -2908,62 +2821,63 @@
23688                 if (hctx->request_id == 0) {
23689                         hctx->request_id = fcgi_requestid_new(srv, p);
23690                 } else {
23691 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
23692 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
23693                                         "fcgi-request is already in use:", hctx->request_id);
23694                 }
23695 -               
23696 +
23697                 /* fall through */
23698                 fcgi_create_env(srv, hctx, hctx->request_id);
23699 -               
23700 +
23701                 fcgi_set_state(srv, hctx, FCGI_STATE_WRITE);
23702 -               
23703 +
23704                 /* fall through */
23705         case FCGI_STATE_WRITE:
23706 -               ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); 
23707 +               ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
23708  
23709                 chunkqueue_remove_finished_chunks(hctx->wb);
23710 -               
23711 +
23712                 if (ret < 0) {
23713                         switch(errno) {
23714                         case ENOTCONN:
23715 -                               /* the connection got dropped after accept() 
23716 -                                * 
23717 -                                * this is most of the time a PHP which dies 
23718 +                               /* the connection got dropped after accept()
23719 +                                *
23720 +                                * this is most of the time a PHP which dies
23721                                  * after PHP_FCGI_MAX_REQUESTS
23722 -                                * 
23723 -                                */ 
23724 +                                *
23725 +                                */
23726                                 if (hctx->wb->bytes_out == 0 &&
23727                                     hctx->reconnects < 5) {
23728 -                                       usleep(10000); /* take away the load of the webserver 
23729 -                                                       * to let the php a chance to restart 
23730 +#ifndef _WIN32
23731 +                                       usleep(10000); /* take away the load of the webserver
23732 +                                                       * to let the php a chance to restart
23733                                                         */
23734 -                                       
23735 +#endif
23736                                         fcgi_reconnect(srv, hctx);
23737 -                               
23738 +
23739                                         return HANDLER_WAIT_FOR_FD;
23740                                 }
23741 -                               
23742 +
23743                                 /* not reconnected ... why
23744 -                                * 
23745 +                                *
23746                                  * far@#lighttpd report this for FreeBSD
23747 -                                * 
23748 +                                *
23749                                  */
23750 -                               
23751 -                               log_error_write(srv, __FILE__, __LINE__, "ssdsd", 
23752 +
23753 +                               log_error_write(srv, __FILE__, __LINE__, "ssosd",
23754                                                 "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
23755                                                 "write-offset:", hctx->wb->bytes_out,
23756                                                 "reconnect attempts:", hctx->reconnects);
23757 -                               
23758 +
23759                                 return HANDLER_ERROR;
23760                         case EAGAIN:
23761                         case EINTR:
23762                                 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23763 -                               
23764 +
23765                                 return HANDLER_WAIT_FOR_EVENT;
23766                         default:
23767 -                               log_error_write(srv, __FILE__, __LINE__, "ssd", 
23768 +                               log_error_write(srv, __FILE__, __LINE__, "ssd",
23769                                                 "write failed:", strerror(errno), errno);
23770 -                               
23771 +
23772                                 return HANDLER_ERROR;
23773                         }
23774                 }
23775 @@ -2975,7 +2889,7 @@
23776                         fcgi_set_state(srv, hctx, FCGI_STATE_READ);
23777                 } else {
23778                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23779 -                               
23780 +
23781                         return HANDLER_WAIT_FOR_EVENT;
23782                 }
23783  
23784 @@ -2987,7 +2901,7 @@
23785                 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
23786                 return HANDLER_ERROR;
23787         }
23788 -       
23789 +
23790         return HANDLER_WAIT_FOR_EVENT;
23791  }
23792  
23793 @@ -2996,18 +2910,18 @@
23794   * */
23795  SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) {
23796         plugin_data *p = p_d;
23797 -       
23798 +
23799         handler_ctx *hctx = con->plugin_ctx[p->id];
23800         fcgi_proc *proc;
23801         fcgi_extension_host *host;
23802 -       
23803 +
23804         if (NULL == hctx) return HANDLER_GO_ON;
23805 -       
23806 +
23807         /* not my job */
23808         if (con->mode != p->id) return HANDLER_GO_ON;
23809  
23810         /* we don't have a host yet, choose one
23811 -        * -> this happens in the first round 
23812 +        * -> this happens in the first round
23813          *    and when the host died and we have to select a new one */
23814         if (hctx->host == NULL) {
23815                 size_t k;
23816 @@ -3016,23 +2930,23 @@
23817                 /* get best server */
23818                 for (k = 0, ndx = -1; k < hctx->ext->used; k++) {
23819                         host = hctx->ext->hosts[k];
23820 -               
23821 +
23822                         /* we should have at least one proc that can do something */
23823                         if (host->active_procs == 0) continue;
23824  
23825                         if (used == -1 || host->load < used) {
23826                                 used = host->load;
23827 -                       
23828 +
23829                                 ndx = k;
23830                         }
23831                 }
23832 -       
23833 +
23834                 /* found a server */
23835                 if (ndx == -1) {
23836                         /* all hosts are down */
23837  
23838                         fcgi_connection_close(srv, hctx);
23839 -                       
23840 +
23841                         con->http_status = 500;
23842                         con->mode = DIRECT;
23843  
23844 @@ -3040,16 +2954,16 @@
23845                 }
23846  
23847                 host = hctx->ext->hosts[ndx];
23848 -               
23849 -               /* 
23850 -                * if check-local is disabled, use the uri.path handler 
23851 -                * 
23852 +
23853 +               /*
23854 +                * if check-local is disabled, use the uri.path handler
23855 +                *
23856                  */
23857 -               
23858 +
23859                 /* init handler-context */
23860                 hctx->host = host;
23861  
23862 -               /* we put a connection on this host, move the other new connections to other hosts 
23863 +               /* we put a connection on this host, move the other new connections to other hosts
23864                  *
23865                  * as soon as hctx->host is unassigned, decrease the load again */
23866                 hctx->host->load++;
23867 @@ -3063,7 +2977,7 @@
23868         case HANDLER_ERROR:
23869                 proc = hctx->proc;
23870                 host = hctx->host;
23871 -               
23872 +
23873                 if (hctx->state == FCGI_STATE_INIT ||
23874                     hctx->state == FCGI_STATE_CONNECT_DELAYED) {
23875                         if (proc) host->active_procs--;
23876 @@ -3078,7 +2992,7 @@
23877                                 return HANDLER_WAIT_FOR_FD;
23878                         } else {
23879                                 fcgi_connection_close(srv, hctx);
23880 -                       
23881 +
23882                                 buffer_reset(con->physical.path);
23883                                 con->mode = DIRECT;
23884                                 con->http_status = 500;
23885 @@ -3088,12 +3002,12 @@
23886                         }
23887                 } else {
23888                         fcgi_connection_close(srv, hctx);
23889 -                       
23890 +
23891                         buffer_reset(con->physical.path);
23892                         con->mode = DIRECT;
23893                         con->http_status = 503;
23894                         joblist_append(srv, con); /* really ? */
23895 -                       
23896 +
23897                         return HANDLER_FINISHED;
23898                 }
23899         case HANDLER_WAIT_FOR_EVENT:
23900 @@ -3115,7 +3029,7 @@
23901         handler_ctx *hctx = ctx;
23902         connection  *con  = hctx->remote_conn;
23903         plugin_data *p    = hctx->plugin_data;
23904 -       
23905 +
23906         fcgi_proc *proc   = hctx->proc;
23907         fcgi_extension_host *host= hctx->host;
23908  
23909 @@ -3125,8 +3039,8 @@
23910                 case 0:
23911                         break;
23912                 case 1:
23913 -                       
23914 -                       if (host->mode == FCGI_AUTHORIZER && 
23915 +
23916 +                       if (host->mode == FCGI_AUTHORIZER &&
23917                             (con->http_status == 200 ||
23918                              con->http_status == 0)) {
23919                                 /*
23920 @@ -3136,26 +3050,26 @@
23921                                  */
23922  
23923                                 buffer_copy_string_buffer(con->physical.doc_root, host->docroot);
23924 -                               
23925 +
23926                                 buffer_copy_string_buffer(con->physical.path, host->docroot);
23927                                 buffer_append_string_buffer(con->physical.path, con->uri.path);
23928                                 fcgi_connection_close(srv, hctx);
23929 -                               
23930 +
23931                                 con->mode = DIRECT;
23932                                 con->file_started = 1; /* fcgi_extension won't touch the request afterwards */
23933                         } else {
23934                                 /* we are done */
23935                                 fcgi_connection_close(srv, hctx);
23936                         }
23937 -                       
23938 +
23939                         joblist_append(srv, con);
23940                         return HANDLER_FINISHED;
23941                 case -1:
23942                         if (proc->pid && proc->state != PROC_STATE_DIED) {
23943                                 int status;
23944 -                               
23945 +
23946                                 /* only fetch the zombie if it is not already done */
23947 -                               
23948 +#ifndef _WIN32
23949                                 switch(waitpid(proc->pid, &status, WNOHANG)) {
23950                                 case 0:
23951                                         /* child is still alive */
23952 @@ -3165,60 +3079,61 @@
23953                                 default:
23954                                         /* the child should not terminate at all */
23955                                         if (WIFEXITED(status)) {
23956 -                                               log_error_write(srv, __FILE__, __LINE__, "sdsd", 
23957 +                                               log_error_write(srv, __FILE__, __LINE__, "sdsd",
23958                                                                 "child exited, pid:", proc->pid,
23959                                                                 "status:", WEXITSTATUS(status));
23960                                         } else if (WIFSIGNALED(status)) {
23961 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
23962 -                                                               "child signaled:", 
23963 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
23964 +                                                               "child signaled:",
23965                                                                 WTERMSIG(status));
23966                                         } else {
23967 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
23968 -                                                               "child died somehow:", 
23969 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
23970 +                                                               "child died somehow:",
23971                                                                 status);
23972                                         }
23973 -                                       
23974 +
23975                                         if (p->conf.debug) {
23976                                                 log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
23977                                                                 "--- fastcgi spawning",
23978                                                                 "\n\tsocket", proc->connection_name,
23979                                                                 "\n\tcurrent:", 1, "/", host->min_procs);
23980                                         }
23981 -                                       
23982 +
23983                                         if (fcgi_spawn_connection(srv, p, host, proc)) {
23984                                                 /* respawning failed, retry later */
23985                                                 proc->state = PROC_STATE_DIED;
23986  
23987 -                                               log_error_write(srv, __FILE__, __LINE__, "s", 
23988 +                                               log_error_write(srv, __FILE__, __LINE__, "s",
23989                                                                 "respawning failed, will retry later");
23990                                         }
23991 -                                       
23992 +
23993                                         break;
23994                                 }
23995 +#endif
23996                         }
23997  
23998                         if (con->file_started == 0) {
23999                                 /* nothing has been send out yet, try to use another child */
24000 -                               
24001 +
24002                                 if (hctx->wb->bytes_out == 0 &&
24003                                     hctx->reconnects < 5) {
24004                                         fcgi_reconnect(srv, hctx);
24005 -                                       
24006 -                                       log_error_write(srv, __FILE__, __LINE__, "ssbsbs", 
24007 +
24008 +                                       log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
24009                                                 "response not received, request not sent",
24010 -                                               "on socket:", proc->connection_name, 
24011 +                                               "on socket:", proc->connection_name,
24012                                                 "for", con->uri.path, ", reconnecting");
24013 -                                       
24014 +
24015                                         return HANDLER_WAIT_FOR_FD;
24016                                 }
24017 -                       
24018 -                               log_error_write(srv, __FILE__, __LINE__, "sosbsbs", 
24019 +
24020 +                               log_error_write(srv, __FILE__, __LINE__, "sosbsbs",
24021                                                 "response not received, request sent:", hctx->wb->bytes_out,
24022 -                                               "on socket:", proc->connection_name, 
24023 +                                               "on socket:", proc->connection_name,
24024                                                 "for", con->uri.path, ", closing connection");
24025 -                               
24026 +
24027                                 fcgi_connection_close(srv, hctx);
24028 -                               
24029 +
24030                                 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
24031                                 buffer_reset(con->physical.path);
24032                                 con->http_status = 500;
24033 @@ -3226,76 +3141,76 @@
24034                         } else {
24035                                 /* response might have been already started, kill the connection */
24036                                 fcgi_connection_close(srv, hctx);
24037 -                               
24038 -                               log_error_write(srv, __FILE__, __LINE__, "ssbsbs", 
24039 +
24040 +                               log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
24041                                                 "response already sent out, but backend returned error",
24042 -                                               "on socket:", proc->connection_name, 
24043 +                                               "on socket:", proc->connection_name,
24044                                                 "for", con->uri.path, ", terminating connection");
24045 -                               
24046 +
24047                                 connection_set_state(srv, con, CON_STATE_ERROR);
24048                         }
24049  
24050                         /* */
24051 -                       
24052 -                       
24053 +
24054 +
24055                         joblist_append(srv, con);
24056                         return HANDLER_FINISHED;
24057                 }
24058         }
24059 -       
24060 +
24061         if (revents & FDEVENT_OUT) {
24062                 if (hctx->state == FCGI_STATE_CONNECT_DELAYED ||
24063                     hctx->state == FCGI_STATE_WRITE) {
24064                         /* we are allowed to send something out
24065 -                        * 
24066 +                        *
24067                          * 1. in a unfinished connect() call
24068                          * 2. in a unfinished write() call (long POST request)
24069                          */
24070                         return mod_fastcgi_handle_subrequest(srv, con, p);
24071                 } else {
24072 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
24073 -                                       "got a FDEVENT_OUT and didn't know why:", 
24074 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
24075 +                                       "got a FDEVENT_OUT and didn't know why:",
24076                                         hctx->state);
24077                 }
24078         }
24079 -       
24080 +
24081         /* perhaps this issue is already handled */
24082         if (revents & FDEVENT_HUP) {
24083                 if (hctx->state == FCGI_STATE_CONNECT_DELAYED) {
24084                         /* getoptsock will catch this one (right ?)
24085 -                        * 
24086 -                        * if we are in connect we might get a EINPROGRESS 
24087 -                        * in the first call and a FDEVENT_HUP in the 
24088 +                        *
24089 +                        * if we are in connect we might get a EINPROGRESS
24090 +                        * in the first call and a FDEVENT_HUP in the
24091                          * second round
24092 -                        * 
24093 +                        *
24094                          * FIXME: as it is a bit ugly.
24095 -                        * 
24096 +                        *
24097                          */
24098                         return mod_fastcgi_handle_subrequest(srv, con, p);
24099                 } else if (hctx->state == FCGI_STATE_READ &&
24100                            hctx->proc->port == 0) {
24101                         /* FIXME:
24102 -                        * 
24103 +                        *
24104                          * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket
24105                          * even if the FCGI_FIN packet is not received yet
24106                          */
24107                 } else {
24108 -                       log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd", 
24109 -                                       "error: unexpected close of fastcgi connection for", 
24110 +                       log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
24111 +                                       "error: unexpected close of fastcgi connection for",
24112                                         con->uri.path,
24113 -                                       "(no fastcgi process on host:", 
24114 +                                       "(no fastcgi process on host:",
24115                                         host->host,
24116 -                                       ", port: ", 
24117 +                                       ", port: ",
24118                                         host->port,
24119                                         " ?)",
24120                                         hctx->state);
24121 -                       
24122 +
24123                         connection_set_state(srv, con, CON_STATE_ERROR);
24124                         fcgi_connection_close(srv, hctx);
24125                         joblist_append(srv, con);
24126                 }
24127         } else if (revents & FDEVENT_ERR) {
24128 -               log_error_write(srv, __FILE__, __LINE__, "s", 
24129 +               log_error_write(srv, __FILE__, __LINE__, "s",
24130                                 "fcgi: got a FDEVENT_ERR. Don't know why.");
24131                 /* kill all connections to the fastcgi process */
24132  
24133 @@ -3304,45 +3219,42 @@
24134                 fcgi_connection_close(srv, hctx);
24135                 joblist_append(srv, con);
24136         }
24137 -       
24138 +
24139         return HANDLER_FINISHED;
24140  }
24141 -#define PATCH(x) \
24142 -       p->conf.x = s->x;
24143 +
24144  static int fcgi_patch_connection(server *srv, connection *con, plugin_data *p) {
24145         size_t i, j;
24146         plugin_config *s = p->config_storage[0];
24147 -       
24148 -       PATCH(exts);
24149 -       PATCH(debug);
24150 -       PATCH(ext_mapping);
24151 -       
24152 +
24153 +       PATCH_OPTION(exts);
24154 +       PATCH_OPTION(debug);
24155 +       PATCH_OPTION(ext_mapping);
24156 +
24157         /* skip the first, the global context */
24158         for (i = 1; i < srv->config_context->used; i++) {
24159                 data_config *dc = (data_config *)srv->config_context->data[i];
24160                 s = p->config_storage[i];
24161 -               
24162 +
24163                 /* condition didn't match */
24164                 if (!config_check_cond(srv, con, dc)) continue;
24165 -               
24166 +
24167                 /* merge config */
24168                 for (j = 0; j < dc->value->used; j++) {
24169                         data_unset *du = dc->value->data[j];
24170 -                       
24171 +
24172                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.server"))) {
24173 -                               PATCH(exts);
24174 +                               PATCH_OPTION(exts);
24175                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.debug"))) {
24176 -                               PATCH(debug);
24177 +                               PATCH_OPTION(debug);
24178                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.map-extensions"))) {
24179 -                               PATCH(ext_mapping);
24180 +                               PATCH_OPTION(ext_mapping);
24181                         }
24182                 }
24183         }
24184 -       
24185 +
24186         return 0;
24187  }
24188 -#undef PATCH
24189 -
24190  
24191  static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
24192         plugin_data *p = p_d;
24193 @@ -3351,16 +3263,16 @@
24194         buffer *fn;
24195         fcgi_extension *extension = NULL;
24196         fcgi_extension_host *host = NULL;
24197 -       
24198 +
24199         /* Possibly, we processed already this request */
24200         if (con->file_started == 1) return HANDLER_GO_ON;
24201  
24202         fn = uri_path_handler ? con->uri.path : con->physical.path;
24203  
24204         if (buffer_is_empty(fn)) return HANDLER_GO_ON;
24205 -       
24206 +
24207         s_len = fn->used - 1;
24208 -       
24209 +
24210         fcgi_patch_connection(srv, con, p);
24211  
24212         /* fastcgi.map-extensions maps extensions to existing fastcgi.server entries
24213 @@ -3368,24 +3280,24 @@
24214          * fastcgi.map-extensions = ( ".php3" => ".php" )
24215          *
24216          * fastcgi.server = ( ".php" => ... )
24217 -        * 
24218 +        *
24219          * */
24220  
24221         /* check if extension-mapping matches */
24222         for (k = 0; k < p->conf.ext_mapping->used; k++) {
24223                 data_string *ds = (data_string *)p->conf.ext_mapping->data[k];
24224                 size_t ct_len; /* length of the config entry */
24225 -               
24226 +
24227                 if (ds->key->used == 0) continue;
24228 -               
24229 +
24230                 ct_len = ds->key->used - 1;
24231 -               
24232 +
24233                 if (s_len < ct_len) continue;
24234 -               
24235 +
24236                 /* found a mapping */
24237                 if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
24238                         /* check if we know the extension */
24239 -                       
24240 +
24241                         /* we can reuse k here */
24242                         for (k = 0; k < p->conf.exts->used; k++) {
24243                                 extension = p->conf.exts->exts[k];
24244 @@ -3407,15 +3319,15 @@
24245                 /* check if extension matches */
24246                 for (k = 0; k < p->conf.exts->used; k++) {
24247                         size_t ct_len; /* length of the config entry */
24248 -               
24249 +
24250                         extension = p->conf.exts->exts[k];
24251 -               
24252 +
24253                         if (extension->key->used == 0) continue;
24254 -               
24255 +
24256                         ct_len = extension->key->used - 1;
24257 -               
24258 +
24259                         if (s_len < ct_len) continue;
24260 -               
24261 +
24262                         /* check extension in the form "/fcgi_pattern" */
24263                         if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
24264                                 break;
24265 @@ -3441,10 +3353,10 @@
24266                         continue;
24267                 }
24268  
24269 -               /* we found one host that is alive */ 
24270 +               /* we found one host that is alive */
24271                 break;
24272         }
24273 -       
24274 +
24275         if (!host) {
24276                 /* sorry, we don't have a server alive for this ext */
24277                 buffer_reset(con->physical.path);
24278 @@ -3459,72 +3371,72 @@
24279                                         "on", extension->key,
24280                                         "are down.");
24281                 }
24282 -               
24283 +
24284                 return HANDLER_FINISHED;
24285         }
24286  
24287         /* a note about no handler is not sent yey */
24288         extension->note_is_sent = 0;
24289  
24290 -       /* 
24291 -        * if check-local is disabled, use the uri.path handler 
24292 -        * 
24293 +       /*
24294 +        * if check-local is disabled, use the uri.path handler
24295 +        *
24296          */
24297 -       
24298 +
24299         /* init handler-context */
24300         if (uri_path_handler) {
24301                 if (host->check_local == 0) {
24302                         handler_ctx *hctx;
24303                         char *pathinfo;
24304 -                       
24305 +
24306                         hctx = handler_ctx_init();
24307 -                       
24308 +
24309                         hctx->remote_conn      = con;
24310                         hctx->plugin_data      = p;
24311                         hctx->proc             = NULL;
24312                         hctx->ext              = extension;
24313 -       
24314 +
24315  
24316                         hctx->conf.exts        = p->conf.exts;
24317                         hctx->conf.debug       = p->conf.debug;
24318 -                               
24319 +
24320                         con->plugin_ctx[p->id] = hctx;
24321 -                               
24322 +
24323                         con->mode = p->id;
24324 -                               
24325 +
24326                         if (con->conf.log_request_handling) {
24327 -                               log_error_write(srv, __FILE__, __LINE__, "s", 
24328 +                               log_error_write(srv, __FILE__, __LINE__, "s",
24329                                 "handling it in mod_fastcgi");
24330                         }
24331 -                               
24332 -                       /* the prefix is the SCRIPT_NAME, 
24333 +
24334 +                       /* the prefix is the SCRIPT_NAME,
24335                          * everthing from start to the next slash
24336                          * this is important for check-local = "disable"
24337 -                        * 
24338 +                        *
24339                          * if prefix = /admin.fcgi
24340 -                        * 
24341 +                        *
24342                          * /admin.fcgi/foo/bar
24343 -                        * 
24344 +                        *
24345                          * SCRIPT_NAME = /admin.fcgi
24346                          * PATH_INFO   = /foo/bar
24347 -                        * 
24348 +                        *
24349                          * if prefix = /fcgi-bin/
24350 -                        * 
24351 +                        *
24352                          * /fcgi-bin/foo/bar
24353 -                        * 
24354 +                        *
24355                          * SCRIPT_NAME = /fcgi-bin/foo
24356                          * PATH_INFO   = /bar
24357 -                        * 
24358 +                        *
24359                          */
24360 -                       
24361 +
24362                         /* the rewrite is only done for /prefix/? matches */
24363                         if (extension->key->ptr[0] == '/' &&
24364                             con->uri.path->used > extension->key->used &&
24365                             NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) {
24366 -                               /* rewrite uri.path and pathinfo */ 
24367 -                               
24368 +                               /* rewrite uri.path and pathinfo */
24369 +
24370                                 buffer_copy_string(con->request.pathinfo, pathinfo);
24371 -                               
24372 +
24373                                 con->uri.path->used -= con->request.pathinfo->used - 1;
24374                                 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
24375                         }
24376 @@ -3532,19 +3444,19 @@
24377         } else {
24378                 handler_ctx *hctx;
24379                 hctx = handler_ctx_init();
24380 -               
24381 +
24382                 hctx->remote_conn      = con;
24383                 hctx->plugin_data      = p;
24384                 hctx->proc             = NULL;
24385                 hctx->ext              = extension;
24386 -               
24387 +
24388                 hctx->conf.exts        = p->conf.exts;
24389                 hctx->conf.debug       = p->conf.debug;
24390 -               
24391 +
24392                 con->plugin_ctx[p->id] = hctx;
24393 -               
24394 +
24395                 con->mode = p->id;
24396 -               
24397 +
24398                 if (con->conf.log_request_handling) {
24399                         log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
24400                 }
24401 @@ -3566,19 +3478,19 @@
24402  JOBLIST_FUNC(mod_fastcgi_handle_joblist) {
24403         plugin_data *p = p_d;
24404         handler_ctx *hctx = con->plugin_ctx[p->id];
24405 -       
24406 +
24407         if (hctx == NULL) return HANDLER_GO_ON;
24408  
24409         if (hctx->fd != -1) {
24410                 switch (hctx->state) {
24411                 case FCGI_STATE_READ:
24412                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
24413 -                       
24414 +
24415                         break;
24416                 case FCGI_STATE_CONNECT_DELAYED:
24417                 case FCGI_STATE_WRITE:
24418                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
24419 -                       
24420 +
24421                         break;
24422                 case FCGI_STATE_INIT:
24423                         /* at reconnect */
24424 @@ -3595,7 +3507,7 @@
24425  
24426  static handler_t fcgi_connection_close_callback(server *srv, connection *con, void *p_d) {
24427         plugin_data *p = p_d;
24428 -       
24429 +
24430         fcgi_connection_close(srv, con->plugin_ctx[p->id]);
24431  
24432         return HANDLER_GO_ON;
24433 @@ -3604,16 +3516,39 @@
24434  TRIGGER_FUNC(mod_fastcgi_handle_trigger) {
24435         plugin_data *p = p_d;
24436         size_t i, j, n;
24437 -       
24438 -       
24439 +
24440 +
24441         /* perhaps we should kill a connect attempt after 10-15 seconds
24442 -        * 
24443 +        *
24444          * currently we wait for the TCP timeout which is on Linux 180 seconds
24445 -        * 
24446 -        * 
24447 -        * 
24448 +        *
24449          */
24450  
24451 +       for (i = 0; i < srv->conns->used; i++) {
24452 +               connection *con = srv->conns->ptr[i];
24453 +               handler_ctx *hctx = con->plugin_ctx[p->id];
24454 +
24455 +               /* if a connection is ours and is in handle-req for more than max-request-time
24456 +                * kill the connection */
24457 +
24458 +               if (con->mode != p->id) continue;
24459 +               if (con->state != CON_STATE_HANDLE_REQUEST) continue;
24460 +               if (srv->cur_ts < con->request_start + 60) continue;
24461 +
24462 +               /* the request is waiting for a FCGI_STDOUT since 60 seconds */
24463 +
24464 +               /* kill the connection */
24465 +
24466 +               log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi backend didn't responded after 60 seconds");
24467 +
24468 +               fcgi_connection_close(srv, hctx);
24469 +
24470 +               con->mode = DIRECT;
24471 +               con->http_status = 500;
24472 +
24473 +               joblist_append(srv, con);
24474 +       }
24475 +
24476         /* check all childs if they are still up */
24477  
24478         for (i = 0; i < srv->config_context->used; i++) {
24479 @@ -3628,45 +3563,45 @@
24480                         fcgi_extension *ex;
24481  
24482                         ex = exts->exts[j];
24483 -                       
24484 +
24485                         for (n = 0; n < ex->used; n++) {
24486 -                               
24487 +
24488                                 fcgi_proc *proc;
24489                                 unsigned long sum_load = 0;
24490                                 fcgi_extension_host *host;
24491 -                               
24492 +
24493                                 host = ex->hosts[n];
24494 -                               
24495 +
24496                                 fcgi_restart_dead_procs(srv, p, host);
24497 -                               
24498 +
24499                                 for (proc = host->first; proc; proc = proc->next) {
24500                                         sum_load += proc->load;
24501                                 }
24502 -                               
24503 +
24504                                 if (host->num_procs &&
24505                                     host->num_procs < host->max_procs &&
24506                                     (sum_load / host->num_procs) > host->max_load_per_proc) {
24507                                         /* overload, spawn new child */
24508                                         if (p->conf.debug) {
24509 -                                               log_error_write(srv, __FILE__, __LINE__, "s", 
24510 +                                               log_error_write(srv, __FILE__, __LINE__, "s",
24511                                                                 "overload detected, spawning a new child");
24512                                         }
24513 -                                       
24514 +
24515                                         for (proc = host->unused_procs; proc && proc->pid != 0; proc = proc->next);
24516 -                                       
24517 +
24518                                         if (proc) {
24519                                                 if (proc == host->unused_procs) host->unused_procs = proc->next;
24520 -                                               
24521 +
24522                                                 if (proc->next) proc->next->prev = NULL;
24523 -                                               
24524 +
24525                                                 host->max_id++;
24526                                         } else {
24527                                                 proc = fastcgi_process_init();
24528                                                 proc->id = host->max_id++;
24529                                         }
24530 -                                       
24531 +
24532                                         host->num_procs++;
24533 -                                       
24534 +
24535                                         if (buffer_is_empty(host->unixsocket)) {
24536                                                 proc->port = host->port + proc->id;
24537                                         } else {
24538 @@ -3674,13 +3609,13 @@
24539                                                 buffer_append_string(proc->unixsocket, "-");
24540                                                 buffer_append_long(proc->unixsocket, proc->id);
24541                                         }
24542 -                                       
24543 +
24544                                         if (fcgi_spawn_connection(srv, p, host, proc)) {
24545                                                 log_error_write(srv, __FILE__, __LINE__, "s",
24546                                                                 "ERROR: spawning fcgi failed.");
24547                                                 return HANDLER_ERROR;
24548                                         }
24549 -                                       
24550 +
24551                                         proc->prev = NULL;
24552                                         proc->next = host->first;
24553                                         if (host->first) {
24554 @@ -3688,56 +3623,56 @@
24555                                         }
24556                                         host->first = proc;
24557                                 }
24558 -                               
24559 +
24560                                 for (proc = host->first; proc; proc = proc->next) {
24561                                         if (proc->load != 0) break;
24562                                         if (host->num_procs <= host->min_procs) break;
24563                                         if (proc->pid == 0) continue;
24564 -                                       
24565 +
24566                                         if (srv->cur_ts - proc->last_used > host->idle_timeout) {
24567                                                 /* a proc is idling for a long time now,
24568                                                  * terminated it */
24569 -                                               
24570 +
24571                                                 if (p->conf.debug) {
24572 -                                                       log_error_write(srv, __FILE__, __LINE__, "ssbsd", 
24573 -                                                                       "idle-timeout reached, terminating child:", 
24574 -                                                                       "socket:", proc->connection_name, 
24575 +                                                       log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24576 +                                                                       "idle-timeout reached, terminating child:",
24577 +                                                                       "socket:", proc->connection_name,
24578                                                                         "pid", proc->pid);
24579                                                 }
24580 -                                               
24581 -                                               
24582 +
24583 +
24584                                                 if (proc->next) proc->next->prev = proc->prev;
24585                                                 if (proc->prev) proc->prev->next = proc->next;
24586 -                                               
24587 +
24588                                                 if (proc->prev == NULL) host->first = proc->next;
24589 -                                               
24590 +
24591                                                 proc->prev = NULL;
24592                                                 proc->next = host->unused_procs;
24593 -                                               
24594 +
24595                                                 if (host->unused_procs) host->unused_procs->prev = proc;
24596                                                 host->unused_procs = proc;
24597 -                                               
24598 +
24599                                                 kill(proc->pid, SIGTERM);
24600 -                                               
24601 +
24602                                                 proc->state = PROC_STATE_KILLED;
24603 -                                               
24604 -                                               log_error_write(srv, __FILE__, __LINE__, "ssbsd", 
24605 -                                                                       "killed:", 
24606 -                                                                       "socket:", proc->connection_name, 
24607 +
24608 +                                               log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24609 +                                                                       "killed:",
24610 +                                                                       "socket:", proc->connection_name,
24611                                                                         "pid", proc->pid);
24612 -                                               
24613 +
24614                                                 host->num_procs--;
24615 -                                               
24616 +
24617                                                 /* proc is now in unused, let the next second handle the next process */
24618                                                 break;
24619 -                                       }       
24620 +                                       }
24621                                 }
24622 -                               
24623 +
24624                                 for (proc = host->unused_procs; proc; proc = proc->next) {
24625                                         int status;
24626 -                                       
24627 +
24628                                         if (proc->pid == 0) continue;
24629 -                                       
24630 +#ifndef _WIN32
24631                                         switch (waitpid(proc->pid, &status, WNOHANG)) {
24632                                         case 0:
24633                                                 /* child still running after timeout, good */
24634 @@ -3745,10 +3680,10 @@
24635                                         case -1:
24636                                                 if (errno != EINTR) {
24637                                                         /* no PID found ? should never happen */
24638 -                                                       log_error_write(srv, __FILE__, __LINE__, "sddss", 
24639 +                                                       log_error_write(srv, __FILE__, __LINE__, "sddss",
24640                                                                         "pid ", proc->pid, proc->state,
24641                                                                         "not found:", strerror(errno));
24642 -                                                       
24643 +
24644  #if 0
24645                                                         if (errno == ECHILD) {
24646                                                                 /* someone else has cleaned up for us */
24647 @@ -3762,25 +3697,26 @@
24648                                                 /* the child should not terminate at all */
24649                                                 if (WIFEXITED(status)) {
24650                                                         if (proc->state != PROC_STATE_KILLED) {
24651 -                                                               log_error_write(srv, __FILE__, __LINE__, "sdb", 
24652 -                                                                               "child exited:", 
24653 +                                                               log_error_write(srv, __FILE__, __LINE__, "sdb",
24654 +                                                                               "child exited:",
24655                                                                                 WEXITSTATUS(status), proc->connection_name);
24656                                                         }
24657                                                 } else if (WIFSIGNALED(status)) {
24658                                                         if (WTERMSIG(status) != SIGTERM) {
24659 -                                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
24660 -                                                                               "child signaled:", 
24661 +                                                               log_error_write(srv, __FILE__, __LINE__, "sd",
24662 +                                                                               "child signaled:",
24663                                                                                 WTERMSIG(status));
24664                                                         }
24665                                                 } else {
24666 -                                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
24667 -                                                                       "child died somehow:", 
24668 +                                                       log_error_write(srv, __FILE__, __LINE__, "sd",
24669 +                                                                       "child died somehow:",
24670                                                                         status);
24671                                                 }
24672                                                 proc->pid = 0;
24673                                                 proc->state = PROC_STATE_UNSET;
24674                                                 host->max_id--;
24675                                         }
24676 +#endif
24677                                 }
24678                         }
24679                 }
24680 @@ -3804,8 +3740,8 @@
24681         p->handle_subrequest       = mod_fastcgi_handle_subrequest;
24682         p->handle_joblist          = mod_fastcgi_handle_joblist;
24683         p->handle_trigger          = mod_fastcgi_handle_trigger;
24684 -       
24685 +
24686         p->data         = NULL;
24687 -       
24688 +
24689         return 0;
24690  }
24691 --- lighttpd-1.4.11/src/mod_flv_streaming.c     2006-03-07 14:06:26.000000000 +0200
24692 +++ lighttpd-1.4.12/src/mod_flv_streaming.c     2006-07-11 22:07:52.000000000 +0300
24693 @@ -23,35 +23,35 @@
24694  
24695  typedef struct {
24696         PLUGIN_DATA;
24697 -       
24698 +
24699         buffer *query_str;
24700         array *get_params;
24701 -       
24702 +
24703         plugin_config **config_storage;
24704 -       
24705 -       plugin_config conf; 
24706 +
24707 +       plugin_config conf;
24708  } plugin_data;
24709  
24710  /* init the plugin data */
24711  INIT_FUNC(mod_flv_streaming_init) {
24712         plugin_data *p;
24713 -       
24714 +
24715         p = calloc(1, sizeof(*p));
24716 -       
24717 +
24718         p->query_str = buffer_init();
24719         p->get_params = array_init();
24720 -       
24721 +
24722         return p;
24723  }
24724  
24725  /* detroy the plugin data */
24726  FREE_FUNC(mod_flv_streaming_free) {
24727         plugin_data *p = p_d;
24728 -       
24729 +
24730         UNUSED(srv);
24731  
24732         if (!p) return HANDLER_GO_ON;
24733 -       
24734 +
24735         if (p->config_storage) {
24736                 size_t i;
24737  
24738 @@ -59,19 +59,19 @@
24739                         plugin_config *s = p->config_storage[i];
24740  
24741                         if (!s) continue;
24742 -                       
24743 +
24744                         array_free(s->extensions);
24745 -                       
24746 +
24747                         free(s);
24748                 }
24749                 free(p->config_storage);
24750         }
24751 -       
24752 +
24753         buffer_free(p->query_str);
24754         array_free(p->get_params);
24755 -       
24756 +
24757         free(p);
24758 -       
24759 +
24760         return HANDLER_GO_ON;
24761  }
24762  
24763 @@ -80,83 +80,80 @@
24764  SETDEFAULTS_FUNC(mod_flv_streaming_set_defaults) {
24765         plugin_data *p = p_d;
24766         size_t i = 0;
24767 -       
24768 -       config_values_t cv[] = { 
24769 +
24770 +       config_values_t cv[] = {
24771                 { "flv-streaming.extensions",   NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
24772                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
24773         };
24774 -       
24775 +
24776         if (!p) return HANDLER_ERROR;
24777 -       
24778 +
24779         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
24780 -       
24781 +
24782         for (i = 0; i < srv->config_context->used; i++) {
24783                 plugin_config *s;
24784 -               
24785 +
24786                 s = calloc(1, sizeof(plugin_config));
24787                 s->extensions     = array_init();
24788 -               
24789 +
24790                 cv[0].destination = s->extensions;
24791 -               
24792 +
24793                 p->config_storage[i] = s;
24794 -       
24795 +
24796                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
24797                         return HANDLER_ERROR;
24798                 }
24799         }
24800 -       
24801 +
24802         return HANDLER_GO_ON;
24803  }
24804  
24805 -#define PATCH(x) \
24806 -       p->conf.x = s->x;
24807  static int mod_flv_streaming_patch_connection(server *srv, connection *con, plugin_data *p) {
24808         size_t i, j;
24809         plugin_config *s = p->config_storage[0];
24810 -       
24811 -       PATCH(extensions);
24812 -       
24813 +
24814 +       PATCH_OPTION(extensions);
24815 +
24816         /* skip the first, the global context */
24817         for (i = 1; i < srv->config_context->used; i++) {
24818                 data_config *dc = (data_config *)srv->config_context->data[i];
24819                 s = p->config_storage[i];
24820 -               
24821 +
24822                 /* condition didn't match */
24823                 if (!config_check_cond(srv, con, dc)) continue;
24824 -               
24825 +
24826                 /* merge config */
24827                 for (j = 0; j < dc->value->used; j++) {
24828                         data_unset *du = dc->value->data[j];
24829 -                       
24830 +
24831                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("flv-streaming.extensions"))) {
24832 -                               PATCH(extensions);
24833 +                               PATCH_OPTION(extensions);
24834                         }
24835                 }
24836         }
24837 -       
24838 +
24839         return 0;
24840  }
24841 -#undef PATCH
24842  
24843 -static int split_get_params(server *srv, connection *con, array *get_params, buffer *qrystr) {
24844 +static int split_get_params(array *get_params, buffer *qrystr) {
24845         size_t is_key = 1;
24846         size_t i;
24847         char *key = NULL, *val = NULL;
24848 -       
24849 +
24850         key = qrystr->ptr;
24851 -       
24852 +
24853         /* we need the \0 */
24854         for (i = 0; i < qrystr->used; i++) {
24855                 switch(qrystr->ptr[i]) {
24856                 case '=':
24857                         if (is_key) {
24858                                 val = qrystr->ptr + i + 1;
24859 -                               
24860 +
24861                                 qrystr->ptr[i] = '\0';
24862 -                               
24863 +
24864                                 is_key = 0;
24865                         }
24866 -                       
24867 +
24868                         break;
24869                 case '&':
24870                 case '\0': /* fin symbol */
24871 @@ -167,7 +164,7 @@
24872                                 /* terminate the value */
24873                                 qrystr->ptr[i] = '\0';
24874  
24875 -                               if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
24876 +                               if (NULL == (ds = (data_string *)array_get_unused_element(get_params, TYPE_STRING))) {
24877                                         ds = data_string_init();
24878                                 }
24879                                 buffer_copy_string_len(ds->key, key, strlen(key));
24880 @@ -175,14 +172,14 @@
24881  
24882                                 array_insert_unique(get_params, (data_unset *)ds);
24883                         }
24884 -                       
24885 +
24886                         key = qrystr->ptr + i + 1;
24887                         val = NULL;
24888                         is_key = 1;
24889                         break;
24890                 }
24891         }
24892 -       
24893 +
24894         return 0;
24895  }
24896  
24897 @@ -190,34 +187,34 @@
24898         plugin_data *p = p_d;
24899         int s_len;
24900         size_t k;
24901 -       
24902 +
24903         UNUSED(srv);
24904  
24905         if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON;
24906 -       
24907 +
24908         mod_flv_streaming_patch_connection(srv, con, p);
24909  
24910         s_len = con->physical.path->used - 1;
24911 -       
24912 +
24913         for (k = 0; k < p->conf.extensions->used; k++) {
24914                 data_string *ds = (data_string *)p->conf.extensions->data[k];
24915                 int ct_len = ds->value->used - 1;
24916 -               
24917 +
24918                 if (ct_len > s_len) continue;
24919                 if (ds->value->used == 0) continue;
24920 -               
24921 +
24922                 if (0 == strncmp(con->physical.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
24923                         data_string *get_param;
24924                         stat_cache_entry *sce = NULL;
24925                         buffer *b;
24926                         int start;
24927                         char *err = NULL;
24928 -                       /* if there is a start=[0-9]+ in the header use it as start, 
24929 +                       /* if there is a start=[0-9]+ in the header use it as start,
24930                          * otherwise send the full file */
24931  
24932                         array_reset(p->get_params);
24933                         buffer_copy_string_buffer(p->query_str, con->uri.query);
24934 -                       split_get_params(srv, con, p->get_params, p->query_str);
24935 +                       split_get_params(p->get_params, p->query_str);
24936  
24937                         if (NULL == (get_param = (data_string *)array_get_element(p->get_params, "start"))) {
24938                                 return HANDLER_GO_ON;
24939 @@ -256,7 +253,7 @@
24940                         return HANDLER_FINISHED;
24941                 }
24942         }
24943 -       
24944 +
24945         /* not found */
24946         return HANDLER_GO_ON;
24947  }
24948 @@ -266,13 +263,13 @@
24949  int mod_flv_streaming_plugin_init(plugin *p) {
24950         p->version     = LIGHTTPD_VERSION_ID;
24951         p->name        = buffer_init_string("flv_streaming");
24952 -       
24953 +
24954         p->init        = mod_flv_streaming_init;
24955         p->handle_physical = mod_flv_streaming_path_handler;
24956         p->set_defaults  = mod_flv_streaming_set_defaults;
24957         p->cleanup     = mod_flv_streaming_free;
24958 -       
24959 +
24960         p->data        = NULL;
24961 -       
24962 +
24963         return 0;
24964  }
24965 --- lighttpd-1.4.11/src/mod_indexfile.c 2005-09-30 01:08:53.000000000 +0300
24966 +++ lighttpd-1.4.12/src/mod_indexfile.c 2006-07-11 22:07:53.000000000 +0300
24967 @@ -20,51 +20,51 @@
24968  
24969  typedef struct {
24970         PLUGIN_DATA;
24971 -       
24972 +
24973         buffer *tmp_buf;
24974 -       
24975 +
24976         plugin_config **config_storage;
24977 -       
24978 -       plugin_config conf; 
24979 +
24980 +       plugin_config conf;
24981  } plugin_data;
24982  
24983  /* init the plugin data */
24984  INIT_FUNC(mod_indexfile_init) {
24985         plugin_data *p;
24986 -       
24987 +
24988         p = calloc(1, sizeof(*p));
24989 -       
24990 +
24991         p->tmp_buf = buffer_init();
24992 -       
24993 +
24994         return p;
24995  }
24996  
24997  /* detroy the plugin data */
24998  FREE_FUNC(mod_indexfile_free) {
24999         plugin_data *p = p_d;
25000 -       
25001 +
25002         UNUSED(srv);
25003  
25004         if (!p) return HANDLER_GO_ON;
25005 -       
25006 +
25007         if (p->config_storage) {
25008                 size_t i;
25009                 for (i = 0; i < srv->config_context->used; i++) {
25010                         plugin_config *s = p->config_storage[i];
25011  
25012                         if (!s) continue;
25013 -                       
25014 +
25015                         array_free(s->indexfiles);
25016 -                       
25017 +
25018                         free(s);
25019                 }
25020                 free(p->config_storage);
25021         }
25022 -       
25023 +
25024         buffer_free(p->tmp_buf);
25025 -       
25026 +
25027         free(p);
25028 -       
25029 +
25030         return HANDLER_GO_ON;
25031  }
25032  
25033 @@ -73,131 +73,128 @@
25034  SETDEFAULTS_FUNC(mod_indexfile_set_defaults) {
25035         plugin_data *p = p_d;
25036         size_t i = 0;
25037 -       
25038 -       config_values_t cv[] = { 
25039 +
25040 +       config_values_t cv[] = {
25041                 { "index-file.names",           NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
25042                 { "server.indexfiles",          NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
25043                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
25044         };
25045 -       
25046 +
25047         if (!p) return HANDLER_ERROR;
25048 -       
25049 +
25050         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
25051 -       
25052 +
25053         for (i = 0; i < srv->config_context->used; i++) {
25054                 plugin_config *s;
25055 -               
25056 +
25057                 s = calloc(1, sizeof(plugin_config));
25058                 s->indexfiles    = array_init();
25059 -               
25060 +
25061                 cv[0].destination = s->indexfiles;
25062                 cv[1].destination = s->indexfiles; /* old name for [0] */
25063 -               
25064 +
25065                 p->config_storage[i] = s;
25066 -       
25067 +
25068                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
25069                         return HANDLER_ERROR;
25070                 }
25071         }
25072 -       
25073 +
25074         return HANDLER_GO_ON;
25075  }
25076  
25077 -#define PATCH(x) \
25078 -       p->conf.x = s->x;
25079  static int mod_indexfile_patch_connection(server *srv, connection *con, plugin_data *p) {
25080         size_t i, j;
25081         plugin_config *s = p->config_storage[0];
25082 -       
25083 -       PATCH(indexfiles);
25084 -       
25085 +
25086 +       PATCH_OPTION(indexfiles);
25087 +
25088         /* skip the first, the global context */
25089         for (i = 1; i < srv->config_context->used; i++) {
25090                 data_config *dc = (data_config *)srv->config_context->data[i];
25091                 s = p->config_storage[i];
25092 -               
25093 +
25094                 /* condition didn't match */
25095                 if (!config_check_cond(srv, con, dc)) continue;
25096 -               
25097 +
25098                 /* merge config */
25099                 for (j = 0; j < dc->value->used; j++) {
25100                         data_unset *du = dc->value->data[j];
25101 -                       
25102 +
25103                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.indexfiles"))) {
25104 -                               PATCH(indexfiles);
25105 +                               PATCH_OPTION(indexfiles);
25106                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("index-file.names"))) {
25107 -                               PATCH(indexfiles);
25108 +                               PATCH_OPTION(indexfiles);
25109                         }
25110                 }
25111         }
25112 -       
25113 +
25114         return 0;
25115  }
25116 -#undef PATCH
25117  
25118  URIHANDLER_FUNC(mod_indexfile_subrequest) {
25119         plugin_data *p = p_d;
25120         size_t k;
25121         stat_cache_entry *sce = NULL;
25122 -       
25123 +
25124         if (con->uri.path->used == 0) return HANDLER_GO_ON;
25125         if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
25126 -       
25127 +
25128         mod_indexfile_patch_connection(srv, con, p);
25129 -       
25130 +
25131         if (con->conf.log_request_handling) {
25132                 log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling the request as Indexfile");
25133                 log_error_write(srv, __FILE__, __LINE__,  "sb", "URI          :", con->uri.path);
25134         }
25135 -       
25136 +
25137         /* indexfile */
25138         for (k = 0; k < p->conf.indexfiles->used; k++) {
25139                 data_string *ds = (data_string *)p->conf.indexfiles->data[k];
25140 -               
25141 +
25142                 if (ds->value && ds->value->ptr[0] == '/') {
25143 -                       /* if the index-file starts with a prefix as use this file as 
25144 +                       /* if the index-file starts with a prefix as use this file as
25145                          * index-generator */
25146                         buffer_copy_string_buffer(p->tmp_buf, con->physical.doc_root);
25147                 } else {
25148                         buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
25149                 }
25150                 buffer_append_string_buffer(p->tmp_buf, ds->value);
25151 -               
25152 +
25153                 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
25154                         if (errno == EACCES) {
25155                                 con->http_status = 403;
25156                                 buffer_reset(con->physical.path);
25157 -                               
25158 +
25159                                 return HANDLER_FINISHED;
25160                         }
25161 -                       
25162 +
25163                         if (errno != ENOENT &&
25164                             errno != ENOTDIR) {
25165                                 /* we have no idea what happend. let's tell the user so. */
25166 -                               
25167 +
25168                                 con->http_status = 500;
25169 -                               
25170 +
25171                                 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
25172                                                 "file not found ... or so: ", strerror(errno),
25173                                                 con->uri.path,
25174                                                 "->", con->physical.path);
25175 -                               
25176 +
25177                                 buffer_reset(con->physical.path);
25178 -                               
25179 +
25180                                 return HANDLER_FINISHED;
25181                         }
25182                         continue;
25183                 }
25184 -                       
25185 +
25186                 /* rewrite uri.path to the real path (/ -> /index.php) */
25187                 buffer_append_string_buffer(con->uri.path, ds->value);
25188                 buffer_copy_string_buffer(con->physical.path, p->tmp_buf);
25189 -               
25190 +
25191                 /* fce is already set up a few lines above */
25192 -               
25193 +
25194                 return HANDLER_GO_ON;
25195         }
25196 -       
25197 +
25198         /* not found */
25199         return HANDLER_GO_ON;
25200  }
25201 @@ -207,13 +204,13 @@
25202  int mod_indexfile_plugin_init(plugin *p) {
25203         p->version     = LIGHTTPD_VERSION_ID;
25204         p->name        = buffer_init_string("indexfile");
25205 -       
25206 +
25207         p->init        = mod_indexfile_init;
25208         p->handle_subrequest_start = mod_indexfile_subrequest;
25209         p->set_defaults  = mod_indexfile_set_defaults;
25210         p->cleanup     = mod_indexfile_free;
25211 -       
25212 +
25213         p->data        = NULL;
25214 -       
25215 +
25216         return 0;
25217  }
25218 --- lighttpd-1.4.11/src/mod_mysql_vhost.c       2006-01-14 20:35:10.000000000 +0200
25219 +++ lighttpd-1.4.12/src/mod_mysql_vhost.c       2006-07-11 22:07:52.000000000 +0300
25220 @@ -1,13 +1,18 @@
25221 -#include <unistd.h>
25222  #include <stdio.h>
25223  #include <errno.h>
25224  #include <fcntl.h>
25225 -#include <strings.h>
25226 +#include <string.h>
25227  
25228  #ifdef HAVE_CONFIG_H
25229  #include "config.h"
25230  #endif
25231  
25232 +#ifdef HAVE_MYSQL_H 
25233 +# ifdef HAVE_LIBMYSQL
25234 +#  define HAVE_MYSQL
25235 +# endif
25236 +#endif
25237 +
25238  #ifdef HAVE_MYSQL
25239  #include <mysql.h>
25240  #endif
25241 @@ -16,61 +21,40 @@
25242  #include "log.h"
25243  
25244  #include "stat_cache.h"
25245 -#ifdef DEBUG_MOD_MYSQL_VHOST
25246 -#define DEBUG
25247 -#endif
25248 +#include "sys-files.h"
25249  
25250 -/*
25251 - * Plugin for lighttpd to use MySQL 
25252 - *   for domain to directory lookups,
25253 - *   i.e virtual hosts (vhosts).
25254 - *   
25255 - * Optionally sets fcgi_offset and fcgi_arg 
25256 - *   in preparation for fcgi.c to handle 
25257 - *   per-user fcgi chroot jails.
25258 - *
25259 - * /ada@riksnet.se 2004-12-06
25260 - */
25261 +#include "mod_sql_vhost_core.h"
25262  
25263  #ifdef HAVE_MYSQL
25264 +
25265 +#define CORE_PLUGIN "mod_sql_vhost_core"
25266 +
25267  typedef struct {
25268         MYSQL   *mysql;
25269 -       
25270 -       buffer  *mydb;
25271 -       buffer  *myuser;
25272 -       buffer  *mypass;
25273 -       buffer  *mysock;
25274 -       
25275 -       buffer  *hostname;
25276 -       unsigned short port;
25277 -       
25278 +
25279         buffer  *mysql_pre;
25280         buffer  *mysql_post;
25281 +
25282 +       mod_sql_vhost_core_plugin_config *core;
25283  } plugin_config;
25284  
25285  /* global plugin data */
25286  typedef struct {
25287         PLUGIN_DATA;
25288 -       
25289 +
25290         buffer  *tmp_buf;
25291 -       
25292 +
25293         plugin_config **config_storage;
25294 -       
25295 -       plugin_config conf; 
25296 +
25297 +       plugin_config conf;
25298  } plugin_data;
25299  
25300 -/* per connection plugin data */
25301 -typedef struct {
25302 -       buffer  *server_name;
25303 -       buffer  *document_root;
25304 -       buffer  *fcgi_arg;
25305 -       unsigned fcgi_offset;
25306 -} plugin_connection_data;
25307 +SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost); 
25308  
25309  /* init the plugin data */
25310  INIT_FUNC(mod_mysql_vhost_init) {
25311         plugin_data *p;
25312 -       
25313 +
25314         p = calloc(1, sizeof(*p));
25315  
25316         p->tmp_buf = buffer_init();
25317 @@ -83,144 +67,77 @@
25318         plugin_data *p = p_d;
25319  
25320         UNUSED(srv);
25321 -       
25322 -#ifdef DEBUG
25323 -       log_error_write(srv, __FILE__, __LINE__, "ss", 
25324 -               "mod_mysql_vhost_cleanup", p ? "yes" : "NO");
25325 -#endif
25326 +
25327         if (!p) return HANDLER_GO_ON;
25328 -       
25329 +
25330         if (p->config_storage) {
25331                 size_t i;
25332                 for (i = 0; i < srv->config_context->used; i++) {
25333                         plugin_config *s = p->config_storage[i];
25334  
25335                         if (!s) continue;
25336 -                       
25337 +
25338                         mysql_close(s->mysql);
25339 -                       
25340 -                       buffer_free(s->mydb);
25341 -                       buffer_free(s->myuser);
25342 -                       buffer_free(s->mypass);
25343 -                       buffer_free(s->mysock);
25344 +
25345                         buffer_free(s->mysql_pre);
25346                         buffer_free(s->mysql_post);
25347 -                       
25348 +
25349                         free(s);
25350                 }
25351                 free(p->config_storage);
25352         }
25353         buffer_free(p->tmp_buf);
25354 -       
25355 -       free(p);
25356  
25357 -       return HANDLER_GO_ON;
25358 -}
25359 -
25360 -/* handle the plugin per connection data */
25361 -static void* mod_mysql_vhost_connection_data(server *srv, connection *con, void *p_d)
25362 -{
25363 -       plugin_data *p = p_d;
25364 -       plugin_connection_data *c = con->plugin_ctx[p->id];
25365 -
25366 -       UNUSED(srv);
25367 -
25368 -#ifdef DEBUG
25369 -        log_error_write(srv, __FILE__, __LINE__, "ss", 
25370 -               "mod_mysql_connection_data", c ? "old" : "NEW");
25371 -#endif
25372 -
25373 -       if (c) return c;
25374 -       c = calloc(1, sizeof(*c));
25375 -
25376 -       c->server_name = buffer_init();
25377 -       c->document_root = buffer_init();
25378 -       c->fcgi_arg = buffer_init();
25379 -       c->fcgi_offset = 0;
25380 -
25381 -       return con->plugin_ctx[p->id] = c;
25382 -}
25383 -
25384 -/* destroy the plugin per connection data */
25385 -CONNECTION_FUNC(mod_mysql_vhost_handle_connection_close) {
25386 -       plugin_data *p = p_d;
25387 -       plugin_connection_data *c = con->plugin_ctx[p->id];
25388 -
25389 -       UNUSED(srv);
25390 -
25391 -#ifdef DEBUG
25392 -       log_error_write(srv, __FILE__, __LINE__, "ss", 
25393 -               "mod_mysql_vhost_handle_connection_close", c ? "yes" : "NO");
25394 -#endif
25395 -       
25396 -       if (!c) return HANDLER_GO_ON;
25397 -
25398 -       buffer_free(c->server_name);
25399 -       buffer_free(c->document_root);
25400 -       buffer_free(c->fcgi_arg);
25401 -       c->fcgi_offset = 0;
25402 -
25403 -       free(c);
25404 +       free(p);
25405  
25406 -       con->plugin_ctx[p->id] = NULL;
25407         return HANDLER_GO_ON;
25408  }
25409  
25410  /* set configuration values */
25411  SERVER_FUNC(mod_mysql_vhost_set_defaults) {
25412         plugin_data *p = p_d;
25413 +       mod_sql_vhost_core_plugin_data *core_config;
25414  
25415 -       char *qmark;
25416         size_t i = 0;
25417  
25418 -       config_values_t cv[] = {
25419 -               { "mysql-vhost.db",     NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER },
25420 -               { "mysql-vhost.user",   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER },
25421 -               { "mysql-vhost.pass",   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER },
25422 -               { "mysql-vhost.sock",   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER },
25423 -               { "mysql-vhost.sql",    NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER },
25424 -               { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER },
25425 -               { "mysql-vhost.port",   NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_SERVER },
25426 -                { NULL,                        NULL, T_CONFIG_UNSET,   T_CONFIG_SCOPE_UNSET }
25427 -        };
25428 -       
25429 +       /* our very own plugin storage, one entry for each conditional
25430 +        * 
25431 +        * srv->config_context->used is the number of conditionals
25432 +        * */
25433         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
25434 -       
25435 +
25436 +       /* get the config of the core-plugin */
25437 +       core_config = plugin_get_config(srv, CORE_PLUGIN);
25438 +
25439 +
25440 +       /* walk through all conditionals and check for assignments */
25441         for (i = 0; i < srv->config_context->used; i++) {
25442                 plugin_config *s;
25443                 buffer *sel;
25444 -               
25445 -               
25446 +               char *qmark;
25447 +
25448 +               /* get the config from the core plugin for this conditional-context */
25449                 s = calloc(1, sizeof(plugin_config));
25450 -               s->mydb = buffer_init();
25451 -               s->myuser = buffer_init();
25452 -               s->mypass = buffer_init();
25453 -               s->mysock = buffer_init();
25454 -               s->hostname = buffer_init();
25455 -               s->port   = 0;               /* default port for mysql */
25456 -               sel = buffer_init();
25457 -               s->mysql = NULL;
25458 +
25459 +               s->core = core_config->config_storage[i];
25460                 
25461 +               s->mysql = NULL;
25462 +
25463                 s->mysql_pre = buffer_init();
25464                 s->mysql_post = buffer_init();
25465 -               
25466 -               cv[0].destination = s->mydb;
25467 -               cv[1].destination = s->myuser;
25468 -               cv[2].destination = s->mypass;
25469 -               cv[3].destination = s->mysock;
25470 -               cv[4].destination = sel;
25471 -               cv[5].destination = s->hostname;
25472 -               cv[6].destination = &(s->port);
25473 -               
25474 +
25475                 p->config_storage[i] = s;
25476 -               
25477 -               if (config_insert_values_global(srv, 
25478 -                       ((data_config *)srv->config_context->data[i])->value,
25479 -                       cv)) return HANDLER_ERROR;
25480 -               
25481 -               s->mysql_pre = buffer_init();
25482 -               s->mysql_post = buffer_init();
25483 -               
25484 +
25485 +               /* check if we are the plugin for this backend */
25486 +               if (!buffer_is_equal_string(s->core->backend, CONST_STR_LEN("mysql"))) continue;
25487 +
25488 +               /* attach us to the core-plugin */
25489 +               s->core->backend_data = p;
25490 +               s->core->get_vhost = mod_mysql_vhost_get_vhost;
25491 +
25492 +               sel = buffer_init();
25493 +               buffer_copy_string_buffer(sel, s->core->select_vhost);
25494 +
25495                 if (sel->used && (qmark = index(sel->ptr, '?'))) {
25496                         *qmark = '\0';
25497                         buffer_copy_string(s->mysql_pre, sel->ptr);
25498 @@ -228,35 +145,35 @@
25499                 } else {
25500                         buffer_copy_string_buffer(s->mysql_pre, sel);
25501                 }
25502 -               
25503 +
25504                 /* required:
25505                  * - username
25506 -                * - database 
25507 -                * 
25508 +                * - database
25509 +                *
25510                  * optional:
25511                  * - password, default: empty
25512                  * - socket, default: mysql default
25513                  * - hostname, if set overrides socket
25514                  * - port, default: 3306
25515                  */
25516 -               
25517 +
25518                 /* all have to be set */
25519 -               if (!(buffer_is_empty(s->myuser) ||
25520 -                     buffer_is_empty(s->mydb))) {
25521 +               if (!(buffer_is_empty(s->core->user) ||
25522 +                     buffer_is_empty(s->core->db))) {
25523  
25524                         int fd;
25525 -               
25526 +
25527                         if (NULL == (s->mysql = mysql_init(NULL))) {
25528                                 log_error_write(srv, __FILE__, __LINE__, "s", "mysql_init() failed, exiting...");
25529 -                               
25530 +
25531                                 return HANDLER_ERROR;
25532                         }
25533 -#define FOO(x) (s->x->used ? s->x->ptr : NULL)
25534 -                       
25535 -                       if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(myuser), FOO(mypass), 
25536 -                                               FOO(mydb), s->port, FOO(mysock), 0)) {
25537 +#define FOO(x) (s->core->x->used ? s->core->x->ptr : NULL)
25538 +
25539 +                       if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(user), FOO(pass),
25540 +                                               FOO(db), s->core->port, FOO(sock), 0)) {
25541                                 log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(s->mysql));
25542 -                               
25543 +
25544                                 return HANDLER_ERROR;
25545                         }
25546  #undef FOO
25547 @@ -265,61 +182,47 @@
25548                         /* otherwise we cannot be sure that mysql is fd i-1 */
25549                         if (-1 == (fd = open("/dev/null", 0))) {
25550                                 close(fd);
25551 -                               fcntl(fd-1, F_SETFD, FD_CLOEXEC); 
25552 +                               fcntl(fd-1, F_SETFD, FD_CLOEXEC);
25553                         }
25554                 }
25555         }
25556 -       
25557 -       
25558 +
25559 +
25560  
25561          return HANDLER_GO_ON;
25562  }
25563  
25564 -#define PATCH(x) \
25565 -       p->conf.x = s->x;
25566  static int mod_mysql_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
25567 -       size_t i, j;
25568 +       size_t i;
25569         plugin_config *s = p->config_storage[0];
25570 -       
25571 -       PATCH(mysql_pre);
25572 -       PATCH(mysql_post);
25573 -#ifdef HAVE_MYSQL
25574 -       PATCH(mysql);
25575 -#endif
25576 -       
25577 +
25578 +       PATCH_OPTION(mysql_pre);
25579 +       PATCH_OPTION(mysql_post);
25580 +       PATCH_OPTION(mysql);
25581 +
25582         /* skip the first, the global context */
25583         for (i = 1; i < srv->config_context->used; i++) {
25584                 data_config *dc = (data_config *)srv->config_context->data[i];
25585                 s = p->config_storage[i];
25586 -               
25587 +
25588                 /* condition didn't match */
25589                 if (!config_check_cond(srv, con, dc)) continue;
25590 -               
25591 -               /* merge config */
25592 -               for (j = 0; j < dc->value->used; j++) {
25593 -                       data_unset *du = dc->value->data[j];
25594 -                       
25595 -                       if (buffer_is_equal_string(du->key, CONST_STR_LEN("mysql-vhost.sql"))) {
25596 -                               PATCH(mysql_pre);
25597 -                               PATCH(mysql_post);
25598 -                       }
25599 -               }
25600 -               
25601 +
25602                 if (s->mysql) {
25603 -                       PATCH(mysql);
25604 +                       PATCH_OPTION(mysql);
25605 +                       PATCH_OPTION(mysql_pre);
25606 +                       PATCH_OPTION(mysql_post);
25607                 }
25608         }
25609 -       
25610 +
25611         return 0;
25612  }
25613 -#undef PATCH
25614  
25615 -
25616 -/* handle document root request */
25617 -CONNECTION_FUNC(mod_mysql_vhost_handle_docroot) {
25618 +/**
25619 + * get the vhost info from the database 
25620 + */
25621 +SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost) {
25622         plugin_data *p = p_d;
25623 -       plugin_connection_data *c;
25624 -       stat_cache_entry *sce;
25625  
25626         unsigned  cols;
25627         MYSQL_ROW row;
25628 @@ -332,13 +235,6 @@
25629  
25630         if (!p->conf.mysql) return HANDLER_GO_ON;
25631  
25632 -       /* sets up connection data if not done yet */
25633 -       c = mod_mysql_vhost_connection_data(srv, con, p_d);
25634 -
25635 -       /* check if cached this connection */
25636 -       if (c->server_name->used && /* con->uri.authority->used && */
25637 -            buffer_is_equal(c->server_name, con->uri.authority)) goto GO_ON;
25638 -
25639         /* build and run SQL query */
25640         buffer_copy_string_buffer(p->tmp_buf, p->conf.mysql_pre);
25641         if (p->conf.mysql_post->used) {
25642 @@ -347,77 +243,43 @@
25643         }
25644         if (mysql_query(p->conf.mysql, p->tmp_buf->ptr)) {
25645                 log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(p->conf.mysql));
25646 -               goto ERR500;
25647 +
25648 +               mysql_free_result(result);
25649 +               return HANDLER_GO_ON;
25650         }
25651         result = mysql_store_result(p->conf.mysql);
25652         cols = mysql_num_fields(result);
25653         row = mysql_fetch_row(result);
25654 +
25655         if (!row || cols < 1) {
25656                 /* no such virtual host */
25657                 mysql_free_result(result);
25658                 return HANDLER_GO_ON;
25659         }
25660  
25661 -       /* sanity check that really is a directory */
25662 -       buffer_copy_string(p->tmp_buf, row[0]);
25663 -       BUFFER_APPEND_SLASH(p->tmp_buf);
25664 -
25665 -       if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
25666 -               log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
25667 -               goto ERR500;
25668 -       }
25669 -        if (!S_ISDIR(sce->st.st_mode)) {
25670 -               log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->tmp_buf);
25671 -               goto ERR500;
25672 -       }
25673 +       buffer_copy_string(docroot, row[0]);
25674  
25675 -       /* cache the data */
25676 -       buffer_copy_string_buffer(c->server_name, con->uri.authority);
25677 -       buffer_copy_string_buffer(c->document_root, p->tmp_buf);
25678 -
25679 -       /* fcgi_offset and fcgi_arg are optional */
25680 -       if (cols > 1 && row[1]) {
25681 -               c->fcgi_offset = atoi(row[1]);
25682 -               
25683 -               if (cols > 2 && row[2]) {
25684 -                       buffer_copy_string(c->fcgi_arg, row[2]);
25685 -               } else {
25686 -                       c->fcgi_arg->used = 0;
25687 -               }
25688 -       } else {
25689 -               c->fcgi_offset = c->fcgi_arg->used = 0;
25690 -       }
25691         mysql_free_result(result);
25692  
25693 -       /* fix virtual server and docroot */
25694 -GO_ON: buffer_copy_string_buffer(con->server_name, c->server_name);
25695 -       buffer_copy_string_buffer(con->physical.doc_root, c->document_root);
25696 -
25697 -#ifdef DEBUG
25698 -       log_error_write(srv, __FILE__, __LINE__, "sbbdb", 
25699 -               result ? "NOT CACHED" : "cached", 
25700 -               con->server_name, con->physical.doc_root,
25701 -               c->fcgi_offset, c->fcgi_arg);
25702 -#endif
25703 -       return HANDLER_GO_ON;   
25704 -
25705 -ERR500:        if (result) mysql_free_result(result);
25706 -       con->http_status = 500; /* Internal Error */
25707 -       return HANDLER_FINISHED;
25708 +       return HANDLER_GO_ON;
25709  }
25710  
25711  /* this function is called at dlopen() time and inits the callbacks */
25712  int mod_mysql_vhost_plugin_init(plugin *p) {
25713 +       data_string *ds;
25714 +       
25715         p->version     = LIGHTTPD_VERSION_ID;
25716         p->name                         = buffer_init_string("mysql_vhost");
25717  
25718         p->init                         = mod_mysql_vhost_init;
25719         p->cleanup                      = mod_mysql_vhost_cleanup;
25720 -       p->handle_request_done          = mod_mysql_vhost_handle_connection_close;
25721  
25722         p->set_defaults                 = mod_mysql_vhost_set_defaults;
25723 -       p->handle_docroot               = mod_mysql_vhost_handle_docroot;
25724         
25725 +       ds = data_string_init();
25726 +       buffer_copy_string(ds->value, CORE_PLUGIN);
25727 +       array_insert_unique(p->required_plugins, (data_unset *)ds);
25728 +
25729         return 0;
25730  }
25731  #else
25732 --- lighttpd-1.4.11/src/mod_proxy.c     2006-01-31 13:01:22.000000000 +0200
25733 +++ lighttpd-1.4.12/src/mod_proxy.c     2006-07-11 22:07:52.000000000 +0300
25734 @@ -1,6 +1,5 @@
25735  #include <sys/types.h>
25736  
25737 -#include <unistd.h>
25738  #include <errno.h>
25739  #include <fcntl.h>
25740  #include <string.h>
25741 @@ -23,6 +22,9 @@
25742  
25743  #include "inet_ntop_cache.h"
25744  #include "crc32.h"
25745 +#include "network.h"
25746 +
25747 +#include "http_resp.h"
25748  
25749  #include <stdio.h>
25750  
25751 @@ -31,6 +33,8 @@
25752  #endif
25753  
25754  #include "sys-socket.h"
25755 +#include "sys-files.h"
25756 +#include "sys-strings.h"
25757  
25758  #define data_proxy data_fastcgi
25759  #define data_proxy_init data_fastcgi_init
25760 @@ -38,16 +42,16 @@
25761  #define PROXY_RETRY_TIMEOUT 60
25762  
25763  /**
25764 - * 
25765 - * the proxy module is based on the fastcgi module 
25766 - * 
25767 + *
25768 + * the proxy module is based on the fastcgi module
25769 + *
25770   * 28.06.2004 Jan Kneschke     The first release
25771   * 01.07.2004 Evgeny Rodichev  Several bugfixes and cleanups
25772   *            - co-ordinate up- and downstream flows correctly (proxy_demux_response
25773   *              and proxy_handle_fdevent)
25774   *            - correctly transfer upstream http_response_status;
25775   *            - some unused structures removed.
25776 - * 
25777 + *
25778   * TODO:      - delay upstream read if write_queue is too large
25779   *              (to prevent memory eating, like in apache). Shoud be
25780   *              configurable).
25781 @@ -66,26 +70,31 @@
25782         int debug;
25783  
25784         proxy_balance_t balance;
25785 +
25786 +       array *last_used_backends; /* "extension" : last_used_backend */
25787  } plugin_config;
25788  
25789  typedef struct {
25790         PLUGIN_DATA;
25791 -       
25792 +
25793         buffer *parse_response;
25794         buffer *balance_buf;
25795 -       
25796 +
25797 +       array *ignore_headers;
25798 +
25799         plugin_config **config_storage;
25800 -       
25801 +
25802         plugin_config conf;
25803  } plugin_data;
25804  
25805 -typedef enum { 
25806 -       PROXY_STATE_INIT, 
25807 -       PROXY_STATE_CONNECT, 
25808 -       PROXY_STATE_PREPARE_WRITE, 
25809 -       PROXY_STATE_WRITE, 
25810 -       PROXY_STATE_READ, 
25811 -       PROXY_STATE_ERROR 
25812 +typedef enum {
25813 +       PROXY_STATE_INIT,
25814 +       PROXY_STATE_CONNECT,
25815 +       PROXY_STATE_PREPARE_WRITE,
25816 +       PROXY_STATE_WRITE,
25817 +    PROXY_STATE_RESPONSE_HEADER,
25818 +    PROXY_STATE_RESPONSE_CONTENT,
25819 +       PROXY_STATE_ERROR
25820  } proxy_connection_state_t;
25821  
25822  enum { PROXY_STDOUT, PROXY_END_REQUEST };
25823 @@ -93,19 +102,20 @@
25824  typedef struct {
25825         proxy_connection_state_t state;
25826         time_t state_timestamp;
25827 -       
25828 +
25829         data_proxy *host;
25830 -       
25831 +
25832         buffer *response;
25833         buffer *response_header;
25834  
25835         chunkqueue *wb;
25836 -       
25837 +    chunkqueue *rb;
25838 +
25839         int fd; /* fd to the proxy process */
25840         int fde_ndx; /* index into the fd-event buffer */
25841  
25842         size_t path_info_offset; /* start of path_info in uri.path */
25843 -       
25844 +
25845         connection *remote_conn;  /* dump pointer */
25846         plugin_data *plugin_data; /* dump pointer */
25847  } handler_ctx;
25848 @@ -116,21 +126,22 @@
25849  
25850  static handler_ctx * handler_ctx_init() {
25851         handler_ctx * hctx;
25852 -       
25853 +
25854  
25855         hctx = calloc(1, sizeof(*hctx));
25856 -       
25857 +
25858         hctx->state = PROXY_STATE_INIT;
25859         hctx->host = NULL;
25860 -       
25861 +
25862         hctx->response = buffer_init();
25863         hctx->response_header = buffer_init();
25864  
25865         hctx->wb = chunkqueue_init();
25866 +    hctx->rb = chunkqueue_init();
25867  
25868         hctx->fd = -1;
25869         hctx->fde_ndx = -1;
25870 -       
25871 +
25872         return hctx;
25873  }
25874  
25875 @@ -138,47 +149,70 @@
25876         buffer_free(hctx->response);
25877         buffer_free(hctx->response_header);
25878         chunkqueue_free(hctx->wb);
25879 -       
25880 +    chunkqueue_free(hctx->rb);
25881 +
25882         free(hctx);
25883  }
25884  
25885  INIT_FUNC(mod_proxy_init) {
25886         plugin_data *p;
25887 -       
25888 +       size_t i;
25889 +
25890 +       char *hop2hop_headers[] = {
25891 +               "Connection",
25892 +               "Keep-Alive",
25893 +               "Host",
25894 +               NULL
25895 +       };
25896 +
25897         p = calloc(1, sizeof(*p));
25898 -       
25899 +
25900         p->parse_response = buffer_init();
25901         p->balance_buf = buffer_init();
25902 -       
25903 +       p->ignore_headers = array_init();
25904 +
25905 +       for (i = 0; hop2hop_headers[i]; i++) {
25906 +               data_string *ds;
25907 +
25908 +               if (NULL == (ds = (data_string *)array_get_unused_element(p->ignore_headers, TYPE_STRING))) {
25909 +                       ds = data_string_init();
25910 +               }
25911 +
25912 +               buffer_copy_string(ds->value, hop2hop_headers[i]);
25913 +               array_insert_unique(p->ignore_headers, (data_unset *)ds);
25914 +       }
25915 +
25916         return p;
25917  }
25918  
25919  
25920  FREE_FUNC(mod_proxy_free) {
25921         plugin_data *p = p_d;
25922 -       
25923 +
25924         UNUSED(srv);
25925  
25926         buffer_free(p->parse_response);
25927         buffer_free(p->balance_buf);
25928 -       
25929 +
25930         if (p->config_storage) {
25931                 size_t i;
25932                 for (i = 0; i < srv->config_context->used; i++) {
25933                         plugin_config *s = p->config_storage[i];
25934 -                       
25935 +
25936                         if (s) {
25937 -                       
25938                                 array_free(s->extensions);
25939 -                       
25940 +                               array_free(s->last_used_backends);
25941 +
25942                                 free(s);
25943                         }
25944                 }
25945                 free(p->config_storage);
25946         }
25947 -       
25948 +
25949 +       free(p->ignore_headers);
25950 +
25951         free(p);
25952 -       
25953 +
25954         return HANDLER_GO_ON;
25955  }
25956  
25957 @@ -186,37 +220,38 @@
25958         plugin_data *p = p_d;
25959         data_unset *du;
25960         size_t i = 0;
25961 -       
25962 -       config_values_t cv[] = { 
25963 +
25964 +       config_values_t cv[] = {
25965                 { "proxy.server",              NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
25966                 { "proxy.debug",               NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
25967                 { "proxy.balance",             NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },      /* 2 */
25968                 { NULL,                        NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
25969         };
25970 -       
25971 +
25972         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
25973 -       
25974 +
25975         for (i = 0; i < srv->config_context->used; i++) {
25976                 plugin_config *s;
25977                 array *ca;
25978 -               
25979 +
25980                 s = malloc(sizeof(plugin_config));
25981 -               s->extensions    = array_init();
25982 +               s->extensions         = array_init();
25983 +               s->last_used_backends = array_init();
25984                 s->debug         = 0;
25985 -               
25986 +
25987                 cv[0].destination = s->extensions;
25988                 cv[1].destination = &(s->debug);
25989                 cv[2].destination = p->balance_buf;
25990  
25991                 buffer_reset(p->balance_buf);
25992 -               
25993 +
25994                 p->config_storage[i] = s;
25995                 ca = ((data_config *)srv->config_context->data[i])->value;
25996 -       
25997 +
25998                 if (0 != config_insert_values_global(srv, ca, cv)) {
25999                         return HANDLER_ERROR;
26000                 }
26001 -       
26002 +
26003                 if (buffer_is_empty(p->balance_buf)) {
26004                         s->balance = PROXY_BALANCE_FAIR;
26005                 } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("fair"))) {
26006 @@ -226,7 +261,7 @@
26007                 } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("hash"))) {
26008                         s->balance = PROXY_BALANCE_HASH;
26009                 } else {
26010 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
26011 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
26012                                         "proxy.balance has to be one of: fair, round-robin, hash, but not:", p->balance_buf);
26013                         return HANDLER_ERROR;
26014                 }
26015 @@ -234,91 +269,91 @@
26016                 if (NULL != (du = array_get_element(ca, "proxy.server"))) {
26017                         size_t j;
26018                         data_array *da = (data_array *)du;
26019 -                       
26020 +
26021                         if (du->type != TYPE_ARRAY) {
26022 -                               log_error_write(srv, __FILE__, __LINE__, "sss", 
26023 +                               log_error_write(srv, __FILE__, __LINE__, "sss",
26024                                                 "unexpected type for key: ", "proxy.server", "array of strings");
26025 -                               
26026 +
26027                                 return HANDLER_ERROR;
26028                         }
26029 -                       
26030 -                       /* 
26031 +
26032 +                       /*
26033                          * proxy.server = ( "<ext>" => ...,
26034                          *                  "<ext>" => ... )
26035                          */
26036 -                       
26037 +
26038                         for (j = 0; j < da->value->used; j++) {
26039                                 data_array *da_ext = (data_array *)da->value->data[j];
26040                                 size_t n;
26041 -                               
26042 +
26043                                 if (da_ext->type != TYPE_ARRAY) {
26044 -                                       log_error_write(srv, __FILE__, __LINE__, "sssbs", 
26045 -                                                       "unexpected type for key: ", "proxy.server", 
26046 +                                       log_error_write(srv, __FILE__, __LINE__, "sssbs",
26047 +                                                       "unexpected type for key: ", "proxy.server",
26048                                                         "[", da->value->data[j]->key, "](string)");
26049 -                                       
26050 +
26051                                         return HANDLER_ERROR;
26052                                 }
26053 -                               
26054 -                               /* 
26055 -                                * proxy.server = ( "<ext>" => 
26056 -                                *                     ( "<host>" => ( ... ), 
26057 +
26058 +                               /*
26059 +                                * proxy.server = ( "<ext>" =>
26060 +                                *                     ( "<host>" => ( ... ),
26061                                  *                       "<host>" => ( ... )
26062 -                                *                     ), 
26063 +                                *                     ),
26064                                  *                    "<ext>" => ... )
26065                                  */
26066 -                               
26067 +
26068                                 for (n = 0; n < da_ext->value->used; n++) {
26069                                         data_array *da_host = (data_array *)da_ext->value->data[n];
26070 -                                       
26071 +
26072                                         data_proxy *df;
26073                                         data_array *dfa;
26074 -                                       
26075 -                                       config_values_t pcv[] = { 
26076 +
26077 +                                       config_values_t pcv[] = {
26078                                                 { "host",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },      /* 0 */
26079                                                 { "port",              NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
26080                                                 { NULL,                NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
26081                                         };
26082 -                                       
26083 +
26084                                         if (da_host->type != TYPE_ARRAY) {
26085 -                                               log_error_write(srv, __FILE__, __LINE__, "ssSBS", 
26086 -                                                               "unexpected type for key:", 
26087 -                                                               "proxy.server", 
26088 +                                               log_error_write(srv, __FILE__, __LINE__, "ssSBS",
26089 +                                                               "unexpected type for key:",
26090 +                                                               "proxy.server",
26091                                                                 "[", da_ext->value->data[n]->key, "](string)");
26092 -                                               
26093 +
26094                                                 return HANDLER_ERROR;
26095                                         }
26096 -                                       
26097 +
26098                                         df = data_proxy_init();
26099 -                                       
26100 +
26101                                         df->port = 80;
26102 -                                       
26103 +
26104                                         buffer_copy_string_buffer(df->key, da_host->key);
26105 -                                       
26106 +
26107                                         pcv[0].destination = df->host;
26108                                         pcv[1].destination = &(df->port);
26109 -                                       
26110 +
26111                                         if (0 != config_insert_values_internal(srv, da_host->value, pcv)) {
26112                                                 return HANDLER_ERROR;
26113                                         }
26114 -                                       
26115 +
26116                                         if (buffer_is_empty(df->host)) {
26117 -                                               log_error_write(srv, __FILE__, __LINE__, "sbbbs", 
26118 -                                                               "missing key (string):", 
26119 +                                               log_error_write(srv, __FILE__, __LINE__, "sbbbs",
26120 +                                                               "missing key (string):",
26121                                                                 da->key,
26122                                                                 da_ext->key,
26123                                                                 da_host->key,
26124                                                                 "host");
26125 -                                               
26126 +
26127                                                 return HANDLER_ERROR;
26128                                         }
26129 -                                       
26130 +
26131                                         /* if extension already exists, take it */
26132 -                                       
26133 +
26134                                         if (NULL == (dfa = (data_array *)array_get_element(s->extensions, da_ext->key->ptr))) {
26135                                                 dfa = data_array_init();
26136 -                                               
26137 +
26138                                                 buffer_copy_string_buffer(dfa->key, da_ext->key);
26139 -                                               
26140 +
26141                                                 array_insert_unique(dfa->value, (data_unset *)df);
26142                                                 array_insert_unique(s->extensions, (data_unset *)dfa);
26143                                         } else {
26144 @@ -328,19 +363,19 @@
26145                         }
26146                 }
26147         }
26148 -       
26149 +
26150         return HANDLER_GO_ON;
26151  }
26152  
26153  void proxy_connection_close(server *srv, handler_ctx *hctx) {
26154         plugin_data *p;
26155         connection *con;
26156 -       
26157 +
26158         if (NULL == hctx) return;
26159 -       
26160 +
26161         p    = hctx->plugin_data;
26162         con  = hctx->remote_conn;
26163 -       
26164 +
26165         if (hctx->fd != -1) {
26166                 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26167                 fdevent_unregister(srv->ev, hctx->fd);
26168 @@ -348,47 +383,56 @@
26169                 close(hctx->fd);
26170                 srv->cur_fds--;
26171         }
26172 -       
26173 +
26174         handler_ctx_free(hctx);
26175 -       con->plugin_ctx[p->id] = NULL;  
26176 +       con->plugin_ctx[p->id] = NULL;
26177  }
26178  
26179  static int proxy_establish_connection(server *srv, handler_ctx *hctx) {
26180         struct sockaddr *proxy_addr;
26181         struct sockaddr_in proxy_addr_in;
26182         socklen_t servlen;
26183 -       
26184 +
26185         plugin_data *p    = hctx->plugin_data;
26186         data_proxy *host= hctx->host;
26187         int proxy_fd       = hctx->fd;
26188 -       
26189 +
26190         memset(&proxy_addr, 0, sizeof(proxy_addr));
26191 -       
26192 +
26193         proxy_addr_in.sin_family = AF_INET;
26194         proxy_addr_in.sin_addr.s_addr = inet_addr(host->host->ptr);
26195         proxy_addr_in.sin_port = htons(host->port);
26196         servlen = sizeof(proxy_addr_in);
26197 -               
26198 +
26199         proxy_addr = (struct sockaddr *) &proxy_addr_in;
26200 -       
26201 +
26202         if (-1 == connect(proxy_fd, proxy_addr, servlen)) {
26203 -               if (errno == EINPROGRESS || errno == EALREADY) {
26204 +#ifdef _WIN32
26205 +        errno = WSAGetLastError();
26206 +#endif
26207 +        switch(errno) {
26208 +#ifdef _WIN32
26209 +        case WSAEWOULDBLOCK:
26210 +#endif
26211 +        case EINPROGRESS:
26212 +        case EALREADY:
26213                         if (p->conf.debug) {
26214 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
26215 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
26216                                                 "connect delayed:", proxy_fd);
26217                         }
26218 -                       
26219 +
26220                         return 1;
26221 -               } else {
26222 -                       
26223 -                       log_error_write(srv, __FILE__, __LINE__, "sdsd", 
26224 +               default:
26225 +
26226 +                       log_error_write(srv, __FILE__, __LINE__, "sdsd",
26227                                         "connect failed:", proxy_fd, strerror(errno), errno);
26228 -                       
26229 +
26230                         return -1;
26231                 }
26232         }
26233 +    fprintf(stderr, "%s.%d: connected fd = %d\r\n", __FILE__, __LINE__, proxy_fd);
26234         if (p->conf.debug) {
26235 -               log_error_write(srv, __FILE__, __LINE__, "sd", 
26236 +               log_error_write(srv, __FILE__, __LINE__, "sd",
26237                                 "connect succeeded: ", proxy_fd);
26238         }
26239  
26240 @@ -422,25 +466,26 @@
26241  
26242  static int proxy_create_env(server *srv, handler_ctx *hctx) {
26243         size_t i;
26244 -       
26245 +
26246         connection *con   = hctx->remote_conn;
26247 +       plugin_data *p    = hctx->plugin_data;
26248         buffer *b;
26249 -       
26250 +
26251         /* build header */
26252  
26253         b = chunkqueue_get_append_buffer(hctx->wb);
26254 -       
26255 +
26256         /* request line */
26257         buffer_copy_string(b, get_http_method_name(con->request.http_method));
26258         BUFFER_APPEND_STRING_CONST(b, " ");
26259 -       
26260 +
26261         buffer_append_string_buffer(b, con->request.uri);
26262         BUFFER_APPEND_STRING_CONST(b, " HTTP/1.0\r\n");
26263  
26264         proxy_append_header(con, "X-Forwarded-For", (char *)inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
26265 -       /* http_host is NOT is just a pointer to a buffer 
26266 +       /* http_host is NOT is just a pointer to a buffer
26267          * which is NULL if it is not set */
26268 -       if (con->request.http_host && 
26269 +       if (con->request.http_host &&
26270             !buffer_is_empty(con->request.http_host)) {
26271                 proxy_set_header(con, "X-Host", con->request.http_host->ptr);
26272         }
26273 @@ -449,24 +494,26 @@
26274         /* request header */
26275         for (i = 0; i < con->request.headers->used; i++) {
26276                 data_string *ds;
26277 -               
26278 +
26279                 ds = (data_string *)con->request.headers->data[i];
26280 -               
26281 +
26282                 if (ds->value->used && ds->key->used) {
26283 -                       if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue;
26284 -                       
26285 +
26286 +                       /* don't copy hop-to-hop headers */
26287 +                       if (array_get_element(p->ignore_headers, ds->key->ptr)) continue;
26288 +
26289                         buffer_append_string_buffer(b, ds->key);
26290                         BUFFER_APPEND_STRING_CONST(b, ": ");
26291                         buffer_append_string_buffer(b, ds->value);
26292                         BUFFER_APPEND_STRING_CONST(b, "\r\n");
26293                 }
26294         }
26295 -       
26296 +
26297         BUFFER_APPEND_STRING_CONST(b, "\r\n");
26298 -       
26299 +
26300         hctx->wb->bytes_in += b->used - 1;
26301         /* body */
26302 -       
26303 +
26304         if (con->request.content_length) {
26305                 chunkqueue *req_cq = con->request_content_queue;
26306                 chunk *req_c;
26307 @@ -479,7 +526,7 @@
26308  
26309                         /* we announce toWrite octects
26310                          * now take all the request_content chunk that we need to fill this request
26311 -                        * */   
26312 +                        * */
26313  
26314                         switch (req_c->type) {
26315                         case FILE_CHUNK:
26316 @@ -507,223 +554,125 @@
26317  
26318                                 req_c->offset += weHave;
26319                                 req_cq->bytes_out += weHave;
26320 -                               
26321 +
26322                                 hctx->wb->bytes_in += weHave;
26323  
26324                                 break;
26325                         default:
26326                                 break;
26327                         }
26328 -                       
26329 +
26330                         offset += weHave;
26331                 }
26332  
26333         }
26334 -       
26335 +
26336         return 0;
26337  }
26338  
26339  static int proxy_set_state(server *srv, handler_ctx *hctx, proxy_connection_state_t state) {
26340         hctx->state = state;
26341         hctx->state_timestamp = srv->cur_ts;
26342 -       
26343 +
26344         return 0;
26345  }
26346  
26347  
26348 -static int proxy_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
26349 -       char *s, *ns;
26350 -       int http_response_status = -1;
26351 -       
26352 -       UNUSED(srv);
26353 +static void chunkqueue_print(chunkqueue *cq) {
26354 +    chunk *c;
26355  
26356 -       /* \r\n -> \0\0 */
26357 -       
26358 -       buffer_copy_string_buffer(p->parse_response, in);
26359 -       
26360 -       for (s = p->parse_response->ptr; NULL != (ns = strstr(s, "\r\n")); s = ns + 2) {
26361 -               char *key, *value;
26362 -               int key_len;
26363 -               data_string *ds;
26364 -               int copy_header;
26365 -               
26366 -               ns[0] = '\0';
26367 -               ns[1] = '\0';
26368 -
26369 -               if (-1 == http_response_status) {
26370 -                       /* The first line of a Response message is the Status-Line */
26371 -
26372 -                       for (key=s; *key && *key != ' '; key++);
26373 -
26374 -                       if (*key) {
26375 -                               http_response_status = (int) strtol(key, NULL, 10);
26376 -                               if (http_response_status <= 0) http_response_status = 502;
26377 -                       } else {
26378 -                               http_response_status = 502;
26379 -                       }
26380 -
26381 -                       con->http_status = http_response_status;
26382 -                       con->parsed_response |= HTTP_STATUS;
26383 -                       continue;
26384 -               }
26385 -               
26386 -               if (NULL == (value = strchr(s, ':'))) {
26387 -                       /* now we expect: "<key>: <value>\n" */
26388 -
26389 -                       continue;
26390 -               }
26391 -
26392 -               key = s;
26393 -               key_len = value - key;
26394 -               
26395 -               value++;
26396 -               /* strip WS */
26397 -               while (*value == ' ' || *value == '\t') value++;
26398 -               
26399 -               copy_header = 1;
26400 -               
26401 -               switch(key_len) {
26402 -               case 4:
26403 -                       if (0 == strncasecmp(key, "Date", key_len)) {
26404 -                               con->parsed_response |= HTTP_DATE;
26405 -                       }
26406 -                       break;
26407 -               case 8:
26408 -                       if (0 == strncasecmp(key, "Location", key_len)) {
26409 -                               con->parsed_response |= HTTP_LOCATION;
26410 -                       }
26411 -                       break;
26412 -               case 10:
26413 -                       if (0 == strncasecmp(key, "Connection", key_len)) {
26414 -                               copy_header = 0;
26415 -                       }
26416 -                       break;
26417 -               case 14:
26418 -                       if (0 == strncasecmp(key, "Content-Length", key_len)) {
26419 -                               con->response.content_length = strtol(value, NULL, 10);
26420 -                               con->parsed_response |= HTTP_CONTENT_LENGTH;
26421 -                       }
26422 -                       break;
26423 -               default:
26424 -                       break;
26425 -               }
26426 -
26427 -               if (copy_header) {
26428 -                       if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
26429 -                               ds = data_response_init();
26430 -                       }
26431 -                       buffer_copy_string_len(ds->key, key, key_len);
26432 -                       buffer_copy_string(ds->value, value);
26433 -                       
26434 -                       array_insert_unique(con->response.headers, (data_unset *)ds);
26435 -               }
26436 -       }
26437 -       
26438 -       return 0;
26439 +    for (c = cq->first; c; c = c->next) {
26440 +        fprintf(stderr, "%s", c->mem->ptr + c->offset);
26441 +    }
26442 +    fprintf(stderr, "\r\n");
26443  }
26444  
26445 -
26446  static int proxy_demux_response(server *srv, handler_ctx *hctx) {
26447 -       int fin = 0;
26448 -       int b;
26449 -       ssize_t r;
26450 -       
26451         plugin_data *p    = hctx->plugin_data;
26452         connection *con   = hctx->remote_conn;
26453         int proxy_fd       = hctx->fd;
26454 -       
26455 -       /* check how much we have to read */
26456 -       if (ioctl(hctx->fd, FIONREAD, &b)) {
26457 -               log_error_write(srv, __FILE__, __LINE__, "sd", 
26458 -                               "ioctl failed: ",
26459 -                               proxy_fd);
26460 -               return -1;
26461 -       }
26462 -
26463 +    chunkqueue *next_queue = NULL;
26464 +    chunk *c = NULL;
26465  
26466 -       if (p->conf.debug) {
26467 -               log_error_write(srv, __FILE__, __LINE__, "sd",
26468 -                              "proxy - have to read:", b);
26469 -       }
26470 -
26471 -       if (b > 0) {
26472 -               if (hctx->response->used == 0) {
26473 -                       /* avoid too small buffer */
26474 -                       buffer_prepare_append(hctx->response, b + 1);
26475 -                       hctx->response->used = 1;
26476 -               } else {
26477 -                       buffer_prepare_append(hctx->response, hctx->response->used + b);
26478 -               }
26479 -               
26480 -               if (-1 == (r = read(hctx->fd, hctx->response->ptr + hctx->response->used - 1, b))) {
26481 -                       log_error_write(srv, __FILE__, __LINE__, "sds", 
26482 -                                       "unexpected end-of-file (perhaps the proxy process died):",
26483 -                                       proxy_fd, strerror(errno));
26484 -                       return -1;
26485 -               }
26486 -               
26487 -               /* this should be catched by the b > 0 above */
26488 -               assert(r);
26489 -               
26490 -               hctx->response->used += r;
26491 -               hctx->response->ptr[hctx->response->used - 1] = '\0';
26492 -
26493 -#if 0
26494 -               log_error_write(srv, __FILE__, __LINE__, "sdsbs", 
26495 -                               "demux: Response buffer len", hctx->response->used, ":", hctx->response, ":");
26496 -#endif
26497 -
26498 -               if (0 == con->got_response) {
26499 -                       con->got_response = 1;
26500 -                       buffer_prepare_copy(hctx->response_header, 128);
26501 -               }
26502 -                               
26503 -               if (0 == con->file_started) {
26504 -                       char *c;
26505 -                               
26506 -                       /* search for the \r\n\r\n in the string */
26507 -                       if (NULL != (c = buffer_search_string_len(hctx->response, "\r\n\r\n", 4))) {
26508 -                               size_t hlen = c - hctx->response->ptr + 4;
26509 -                               size_t blen = hctx->response->used - hlen - 1;
26510 -                               /* found */
26511 -                               
26512 -                               buffer_append_string_len(hctx->response_header, hctx->response->ptr, c - hctx->response->ptr + 4);
26513 -#if 0
26514 -                               log_error_write(srv, __FILE__, __LINE__, "sb", "Header:", hctx->response_header);
26515 -#endif
26516 -                               /* parse the response header */
26517 -                               proxy_response_parse(srv, con, p, hctx->response_header);
26518 -                                       
26519 -                               /* enable chunked-transfer-encoding */
26520 -                               if (con->request.http_version == HTTP_VERSION_1_1 &&
26521 -                                   !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
26522 -                                       con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
26523 -                               }
26524 -                                       
26525 -                               con->file_started = 1;
26526 -                               if (blen) {
26527 -                                       http_chunk_append_mem(srv, con, c + 4, blen + 1);
26528 -                                       joblist_append(srv, con);
26529 -                               }
26530 -                               hctx->response->used = 0;
26531 -                       }
26532 -               } else {
26533 -                       http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
26534 -                       joblist_append(srv, con);
26535 -                       hctx->response->used = 0;
26536 -               }
26537 -               
26538 -       } else {
26539 -               /* reading from upstream done */
26540 +    switch(srv->network_backend_read(srv, con, proxy_fd, hctx->rb)) {
26541 +    case NETWORK_STATUS_SUCCESS:
26542 +        /* we got content */
26543 +        break;
26544 +    case NETWORK_STATUS_CONNECTION_CLOSE:
26545 +        /* we are done, get out of here */
26546                 con->file_finished = 1;
26547 -               
26548 +
26549 +        /* close the chunk-queue with a empty chunk */
26550                 http_chunk_append_mem(srv, con, NULL, 0);
26551                 joblist_append(srv, con);
26552 -               
26553 -               fin = 1;
26554 +
26555 +        return 1;
26556 +    default:
26557 +        /* oops */
26558 +        return -1;
26559 +    }
26560 +
26561 +    /* looks like we got some content
26562 +    *
26563 +    * split off the header from the incoming stream
26564 +    */
26565 +
26566 +    if (hctx->state == PROXY_STATE_RESPONSE_HEADER) {
26567 +        http_resp *resp = http_response_init();
26568 +
26569 +        /* the response header is not fully received yet,
26570 +        *
26571 +        * extract the http-response header from the rb-cq
26572 +        */
26573 +        fprintf(stderr, "%s.%d: network-read\r\n", __FILE__, __LINE__);
26574 +        chunkqueue_print(hctx->rb);
26575 +
26576 +        switch (http_response_parse_cq(hctx->rb, resp)) {
26577 +        case PARSE_ERROR:
26578 +            /* parsing failed */
26579 +
26580 +            con->http_status = 502; /* Bad Gateway */
26581 +            return 1;
26582 +        case PARSE_NEED_MORE:
26583 +            return 0;
26584 +        case PARSE_SUCCESS:
26585 +            con->http_status = resp->status;
26586 +
26587 +            fprintf(stderr, "%s.%d: parsing done\r\n", __FILE__, __LINE__);
26588 +            chunkqueue_print(hctx->rb);
26589 +
26590 +            con->file_started = 1;
26591 +
26592 +            hctx->state = PROXY_STATE_RESPONSE_CONTENT;
26593 +            break;
26594 +        }
26595 +    }
26596 +
26597 +    /* FIXME: pass the response-header to the other plugins to
26598 +    * setup the filter-queue
26599 +    *
26600 +    * - use next-queue instead of con->write_queue
26601 +    */
26602 +
26603 +    next_queue = con->write_queue;
26604 +
26605 +    assert(hctx->state == PROXY_STATE_RESPONSE_CONTENT);
26606 +
26607 +    /* FIXME: if we have a content-length or chunked-encoding
26608 +    * handle it.
26609 +    *
26610 +    * for now we wait for EOF on the socket */
26611 +
26612 +    /* copy the content to the next cq */
26613 +    for (c = hctx->rb->first; c; c = c->next) {
26614 +        http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
26615 +
26616 +        c->offset = c->mem->used - 1;
26617         }
26618 -       
26619 -       return fin;
26620 +
26621 +    chunkqueue_remove_finished_chunks(hctx->rb);
26622 +
26623 +       return 0;
26624  }
26625  
26626  
26627 @@ -731,12 +680,12 @@
26628         data_proxy *host= hctx->host;
26629         plugin_data *p    = hctx->plugin_data;
26630         connection *con   = hctx->remote_conn;
26631 -       
26632 +
26633         int ret;
26634 -       
26635 -       if (!host || 
26636 +
26637 +       if (!host ||
26638             (!host->host->used || !host->port)) return -1;
26639 -       
26640 +
26641         switch(hctx->state) {
26642         case PROXY_STATE_INIT:
26643                 if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) {
26644 @@ -744,19 +693,19 @@
26645                         return HANDLER_ERROR;
26646                 }
26647                 hctx->fde_ndx = -1;
26648 -               
26649 +
26650                 srv->cur_fds++;
26651 -               
26652 +
26653                 fdevent_register(srv->ev, hctx->fd, proxy_handle_fdevent, hctx);
26654 -               
26655 +
26656                 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
26657                         log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
26658 -                       
26659 +
26660                         return HANDLER_ERROR;
26661                 }
26662 -               
26663 +
26664                 /* fall through */
26665 -               
26666 +
26667         case PROXY_STATE_CONNECT:
26668                 /* try to finish the connect() */
26669                 if (hctx->state == PROXY_STATE_INIT) {
26670 @@ -764,16 +713,16 @@
26671                         switch (proxy_establish_connection(srv, hctx)) {
26672                         case 1:
26673                                 proxy_set_state(srv, hctx, PROXY_STATE_CONNECT);
26674 -                               
26675 +
26676                                 /* connection is in progress, wait for an event and call getsockopt() below */
26677 -                               
26678 +
26679                                 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26680 -                               
26681 +
26682                                 return HANDLER_WAIT_FOR_EVENT;
26683                         case -1:
26684                                 /* if ECONNREFUSED choose another connection -> FIXME */
26685                                 hctx->fde_ndx = -1;
26686 -                               
26687 +
26688                                 return HANDLER_ERROR;
26689                         default:
26690                                 /* everything is ok, go on */
26691 @@ -782,152 +731,152 @@
26692                 } else {
26693                         int socket_error;
26694                         socklen_t socket_error_len = sizeof(socket_error);
26695 -               
26696 -                       /* we don't need it anymore */  
26697 +
26698 +                       /* we don't need it anymore */
26699                         fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26700  
26701                         /* try to finish the connect() */
26702                         if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
26703 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
26704 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
26705                                                 "getsockopt failed:", strerror(errno));
26706 -                               
26707 +
26708                                 return HANDLER_ERROR;
26709                         }
26710                         if (socket_error != 0) {
26711                                 log_error_write(srv, __FILE__, __LINE__, "ss",
26712 -                                               "establishing connection failed:", strerror(socket_error), 
26713 +                                               "establishing connection failed:", strerror(socket_error),
26714                                                 "port:", hctx->host->port);
26715 -                               
26716 +
26717                                 return HANDLER_ERROR;
26718                         }
26719                         if (p->conf.debug) {
26720 -                               log_error_write(srv, __FILE__, __LINE__,  "s", "proxy - connect - delayed success"); 
26721 +                               log_error_write(srv, __FILE__, __LINE__,  "s", "proxy - connect - delayed success");
26722                         }
26723 +            fprintf(stderr, "%s.%d: connected fd = %d\r\n", __FILE__, __LINE__, hctx->fd);
26724                 }
26725 -               
26726 +
26727                 proxy_set_state(srv, hctx, PROXY_STATE_PREPARE_WRITE);
26728                 /* fall through */
26729         case PROXY_STATE_PREPARE_WRITE:
26730                 proxy_create_env(srv, hctx);
26731 -               
26732 +
26733                 proxy_set_state(srv, hctx, PROXY_STATE_WRITE);
26734 -               
26735 +
26736                 /* fall through */
26737         case PROXY_STATE_WRITE:;
26738 -               ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); 
26739 +               ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
26740  
26741                 chunkqueue_remove_finished_chunks(hctx->wb);
26742  
26743 -               if (-1 == ret) {
26744 -                       if (errno != EAGAIN &&
26745 -                           errno != EINTR) {
26746 -                               log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
26747 -                               
26748 -                               return HANDLER_ERROR;
26749 -                       } else {
26750 -                               fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26751 +               switch(ret) {
26752 +        case NETWORK_STATUS_FATAL_ERROR:
26753 +                       log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
26754  
26755 -                               return HANDLER_WAIT_FOR_EVENT;
26756 -                       }
26757 +                       return HANDLER_ERROR;
26758 +        case NETWORK_STATUS_WAIT_FOR_EVENT:
26759 +
26760 +                       fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26761 +
26762 +                       return HANDLER_WAIT_FOR_EVENT;
26763                 }
26764  
26765                 if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
26766 -                       proxy_set_state(srv, hctx, PROXY_STATE_READ);
26767 +                       proxy_set_state(srv, hctx, PROXY_STATE_RESPONSE_HEADER);
26768  
26769                         fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26770                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
26771                 } else {
26772                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26773 -                               
26774 +
26775                         return HANDLER_WAIT_FOR_EVENT;
26776                 }
26777 -               
26778 +
26779                 return HANDLER_WAIT_FOR_EVENT;
26780 -       case PROXY_STATE_READ:
26781 +       case PROXY_STATE_RESPONSE_HEADER:
26782                 /* waiting for a response */
26783 +
26784                 return HANDLER_WAIT_FOR_EVENT;
26785         default:
26786                 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
26787                 return HANDLER_ERROR;
26788         }
26789 -       
26790 +
26791         return HANDLER_GO_ON;
26792  }
26793  
26794 -#define PATCH(x) \
26795 -       p->conf.x = s->x;
26796  static int mod_proxy_patch_connection(server *srv, connection *con, plugin_data *p) {
26797         size_t i, j;
26798         plugin_config *s = p->config_storage[0];
26799 -       
26800 -       PATCH(extensions);
26801 -       PATCH(debug);
26802 -       PATCH(balance);
26803 -       
26804 +
26805 +       PATCH_OPTION(extensions);
26806 +       PATCH_OPTION(debug);
26807 +       PATCH_OPTION(balance);
26808 +       PATCH_OPTION(last_used_backends);
26809 +
26810         /* skip the first, the global context */
26811         for (i = 1; i < srv->config_context->used; i++) {
26812                 data_config *dc = (data_config *)srv->config_context->data[i];
26813                 s = p->config_storage[i];
26814 -               
26815 +
26816                 /* condition didn't match */
26817                 if (!config_check_cond(srv, con, dc)) continue;
26818 -               
26819 +
26820                 /* merge config */
26821                 for (j = 0; j < dc->value->used; j++) {
26822                         data_unset *du = dc->value->data[j];
26823 -                       
26824 +
26825                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.server"))) {
26826 -                               PATCH(extensions);
26827 +                               PATCH_OPTION(extensions);
26828                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.debug"))) {
26829 -                               PATCH(debug);
26830 +                               PATCH_OPTION(debug);
26831                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.balance"))) {
26832 -                               PATCH(balance);
26833 +                               PATCH_OPTION(balance);
26834 +                               PATCH_OPTION(last_used_backends);
26835                         }
26836                 }
26837         }
26838 -       
26839 +
26840         return 0;
26841  }
26842 -#undef PATCH
26843  
26844  SUBREQUEST_FUNC(mod_proxy_handle_subrequest) {
26845         plugin_data *p = p_d;
26846 -       
26847 +
26848         handler_ctx *hctx = con->plugin_ctx[p->id];
26849         data_proxy *host;
26850 -       
26851 +
26852         if (NULL == hctx) return HANDLER_GO_ON;
26853  
26854         mod_proxy_patch_connection(srv, con, p);
26855 -       
26856 +
26857         host = hctx->host;
26858 -       
26859 +
26860         /* not my job */
26861         if (con->mode != p->id) return HANDLER_GO_ON;
26862 -       
26863 +
26864         /* ok, create the request */
26865         switch(proxy_write_request(srv, hctx)) {
26866         case HANDLER_ERROR:
26867 -               log_error_write(srv, __FILE__, __LINE__,  "sbdd", "proxy-server disabled:", 
26868 +               log_error_write(srv, __FILE__, __LINE__,  "sbdd", "proxy-server disabled:",
26869                                 host->host,
26870                                 host->port,
26871                                 hctx->fd);
26872 -               
26873 +
26874                 /* disable this server */
26875                 host->is_disabled = 1;
26876                 host->disable_ts = srv->cur_ts;
26877 -               
26878 +
26879                 proxy_connection_close(srv, hctx);
26880 -       
26881 -               /* reset the enviroment and restart the sub-request */  
26882 +
26883 +               /* reset the enviroment and restart the sub-request */
26884                 buffer_reset(con->physical.path);
26885                 con->mode = DIRECT;
26886  
26887                 joblist_append(srv, con);
26888  
26889 -               /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop 
26890 -                * and hope that the childs will be restarted 
26891 -                * 
26892 +               /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
26893 +                * and hope that the childs will be restarted
26894 +                *
26895                  */
26896  
26897                 return HANDLER_WAIT_FOR_FD;
26898 @@ -938,7 +887,7 @@
26899         default:
26900                 break;
26901         }
26902 -       
26903 +
26904         if (con->file_started == 1) {
26905                 return HANDLER_FINISHED;
26906         } else {
26907 @@ -951,13 +900,14 @@
26908         handler_ctx *hctx = ctx;
26909         connection  *con  = hctx->remote_conn;
26910         plugin_data *p    = hctx->plugin_data;
26911 -       
26912 -       
26913 +
26914 +
26915         if ((revents & FDEVENT_IN) &&
26916 -           hctx->state == PROXY_STATE_READ) {
26917 +        (hctx->state == PROXY_STATE_RESPONSE_HEADER ||
26918 +         hctx->state == PROXY_STATE_RESPONSE_CONTENT)) {
26919  
26920                 if (p->conf.debug) {
26921 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
26922 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
26923                                         "proxy: fdevent-in", hctx->state);
26924                 }
26925  
26926 @@ -966,10 +916,10 @@
26927                         break;
26928                 case 1:
26929                         hctx->host->usage--;
26930 -                       
26931 +
26932                         /* we are done */
26933                         proxy_connection_close(srv, hctx);
26934 -                       
26935 +
26936                         joblist_append(srv, con);
26937                         return HANDLER_FINISHED;
26938                 case -1:
26939 @@ -982,53 +932,53 @@
26940                                 /* response might have been already started, kill the connection */
26941                                 connection_set_state(srv, con, CON_STATE_ERROR);
26942                         }
26943 -                       
26944 +
26945                         joblist_append(srv, con);
26946                         return HANDLER_FINISHED;
26947                 }
26948         }
26949 -       
26950 +
26951         if (revents & FDEVENT_OUT) {
26952                 if (p->conf.debug) {
26953 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
26954 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
26955                                         "proxy: fdevent-out", hctx->state);
26956                 }
26957  
26958                 if (hctx->state == PROXY_STATE_CONNECT ||
26959                     hctx->state == PROXY_STATE_WRITE) {
26960                         /* we are allowed to send something out
26961 -                        * 
26962 +                        *
26963                          * 1. in a unfinished connect() call
26964                          * 2. in a unfinished write() call (long POST request)
26965                          */
26966                         return mod_proxy_handle_subrequest(srv, con, p);
26967                 } else {
26968 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
26969 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
26970                                         "proxy: out", hctx->state);
26971                 }
26972         }
26973 -       
26974 +
26975         /* perhaps this issue is already handled */
26976         if (revents & FDEVENT_HUP) {
26977                 if (p->conf.debug) {
26978 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
26979 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
26980                                         "proxy: fdevent-hup", hctx->state);
26981                 }
26982 -               
26983 +
26984                 if (hctx->state == PROXY_STATE_CONNECT) {
26985                         /* connect() -> EINPROGRESS -> HUP */
26986 -                       
26987 +
26988                         /**
26989 -                        * what is proxy is doing if it can't reach the next hop ? 
26990 -                        * 
26991 +                        * what is proxy is doing if it can't reach the next hop ?
26992 +                        *
26993                          */
26994 -                       
26995 +
26996                         proxy_connection_close(srv, hctx);
26997                         joblist_append(srv, con);
26998 -                       
26999 +
27000                         con->http_status = 503;
27001                         con->mode = DIRECT;
27002 -                       
27003 +
27004                         return HANDLER_FINISHED;
27005                 }
27006  
27007 @@ -1038,13 +988,13 @@
27008                 joblist_append(srv, con);
27009         } else if (revents & FDEVENT_ERR) {
27010                 /* kill all connections to the proxy process */
27011 -               
27012 +
27013                 log_error_write(srv, __FILE__, __LINE__, "sd", "proxy-FDEVENT_ERR, but no HUP", revents);
27014  
27015                 joblist_append(srv, con);
27016                 proxy_connection_close(srv, hctx);
27017         }
27018 -       
27019 +
27020         return HANDLER_FINISHED;
27021  }
27022  
27023 @@ -1058,44 +1008,49 @@
27024         buffer *fn;
27025         data_array *extension = NULL;
27026         size_t path_info_offset;
27027 -       
27028 +       data_integer *last_used_backend;
27029 +       data_proxy *host = NULL;
27030 +       handler_ctx *hctx = NULL;
27031 +
27032 +       array *backends = NULL;
27033 +
27034         /* Possibly, we processed already this request */
27035         if (con->file_started == 1) return HANDLER_GO_ON;
27036 -       
27037 +
27038         mod_proxy_patch_connection(srv, con, p);
27039 -       
27040 +
27041         fn = con->uri.path;
27042  
27043         if (fn->used == 0) {
27044                 return HANDLER_ERROR;
27045         }
27046 -       
27047 +
27048         s_len = fn->used - 1;
27049 -       
27050 -       
27051 +
27052 +
27053         path_info_offset = 0;
27054  
27055 -       if (p->conf.debug) {    
27056 +       if (p->conf.debug) {
27057                 log_error_write(srv, __FILE__, __LINE__,  "s", "proxy - start");
27058         }
27059  
27060         /* check if extension matches */
27061         for (k = 0; k < p->conf.extensions->used; k++) {
27062                 size_t ct_len;
27063 -               
27064 +
27065                 extension = (data_array *)p->conf.extensions->data[k];
27066 -               
27067 +
27068                 if (extension->key->used == 0) continue;
27069 -               
27070 +
27071                 ct_len = extension->key->used - 1;
27072 -               
27073 +
27074                 if (s_len < ct_len) continue;
27075 -               
27076 +
27077                 /* check extension in the form "/proxy_pattern" */
27078                 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
27079                         if (s_len > ct_len + 1) {
27080                                 char *pi_offset;
27081 -                               
27082 +
27083                                 if (0 != (pi_offset = strchr(fn->ptr + ct_len + 1, '/'))) {
27084                                         path_info_offset = pi_offset - fn->ptr;
27085                                 }
27086 @@ -1106,12 +1061,14 @@
27087                         break;
27088                 }
27089         }
27090 -       
27091 +
27092         if (k == p->conf.extensions->used) {
27093                 return HANDLER_GO_ON;
27094         }
27095  
27096 -       if (p->conf.debug) {    
27097 +       backends = extension->value;
27098 +
27099 +       if (p->conf.debug) {
27100                 log_error_write(srv, __FILE__, __LINE__,  "s", "proxy - ext found");
27101         }
27102  
27103 @@ -1120,34 +1077,34 @@
27104                 /* hash balancing */
27105  
27106                 if (p->conf.debug) {
27107 -                       log_error_write(srv, __FILE__, __LINE__,  "sd", 
27108 -                                       "proxy - used hash balancing, hosts:", extension->value->used);
27109 +                       log_error_write(srv, __FILE__, __LINE__,  "sd",
27110 +                                       "proxy - used hash balancing, hosts:", backends->used);
27111                 }
27112  
27113 -               for (k = 0, ndx = -1, last_max = ULONG_MAX; k < extension->value->used; k++) {
27114 -                       data_proxy *host = (data_proxy *)extension->value->data[k];
27115 +               for (k = 0, ndx = -1, last_max = ULONG_MAX; k < backends->used; k++) {
27116                         unsigned long cur_max;
27117  
27118 -                       if (host->is_disabled) continue;
27119 -                       
27120 +                       data_proxy *cur = (data_proxy *)backends->data[k];
27121 +
27122 +                       if (cur->is_disabled) continue;
27123 +
27124                         cur_max = generate_crc32c(CONST_BUF_LEN(con->uri.path)) +
27125 -                               generate_crc32c(CONST_BUF_LEN(host->host)) + /* we can cache this */
27126 +                               generate_crc32c(CONST_BUF_LEN(cur->host)) + /* we can cache this */
27127                                 generate_crc32c(CONST_BUF_LEN(con->uri.authority));
27128 -                       
27129 +
27130                         if (p->conf.debug) {
27131 -                               log_error_write(srv, __FILE__, __LINE__,  "sbbbd", 
27132 +                               log_error_write(srv, __FILE__, __LINE__,  "sbbbd",
27133                                                 "proxy - election:",
27134                                                 con->uri.path,
27135 -                                               host->host,
27136 +                                               cur->host,
27137                                                 con->uri.authority,
27138                                                 cur_max);
27139                         }
27140  
27141 -                       if ((last_max == ULONG_MAX) || /* first round */
27142 -                           (cur_max > last_max)) {
27143 +                       if (host == NULL || (cur_max > last_max)) {
27144                                 last_max = cur_max;
27145  
27146 -                               ndx = k;
27147 +                               host = cur;
27148                         }
27149                 }
27150  
27151 @@ -1155,19 +1112,20 @@
27152         case PROXY_BALANCE_FAIR:
27153                 /* fair balancing */
27154                 if (p->conf.debug) {
27155 -                       log_error_write(srv, __FILE__, __LINE__,  "s", 
27156 +                       log_error_write(srv, __FILE__, __LINE__,  "s",
27157                                         "proxy - used fair balancing");
27158                 }
27159  
27160 -               for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
27161 -                       data_proxy *host = (data_proxy *)extension->value->data[k];
27162 -               
27163 -                       if (host->is_disabled) continue;
27164 -
27165 -                       if (host->usage < max_usage) {
27166 -                               max_usage = host->usage;
27167 -                       
27168 -                               ndx = k;
27169 +               /* try to find the host with the lowest load */
27170 +               for (k = 0, max_usage = 0; k < backends->used; k++) {
27171 +                       data_proxy *cur = (data_proxy *)backends->data[k];
27172 +
27173 +                       if (cur->is_disabled) continue;
27174 +
27175 +                       if (NULL == host || cur->usage < max_usage) {
27176 +                               max_usage = cur->usage;
27177 +
27178 +                               host = cur;
27179                         }
27180                 }
27181  
27182 @@ -1175,89 +1133,100 @@
27183         case PROXY_BALANCE_RR:
27184                 /* round robin */
27185                 if (p->conf.debug) {
27186 -                       log_error_write(srv, __FILE__, __LINE__,  "s", 
27187 +                       log_error_write(srv, __FILE__, __LINE__,  "s",
27188                                         "proxy - used round-robin balancing");
27189                 }
27190  
27191                 /* just to be sure */
27192 -               assert(extension->value->used < INT_MAX);
27193 -               
27194 -               for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
27195 -                       data_proxy *host = (data_proxy *)extension->value->data[k];
27196 -               
27197 -                       if (host->is_disabled) continue;
27198 -
27199 -                       /* first usable ndx */
27200 -                       if (max_usage == INT_MAX) {
27201 -                               max_usage = k;
27202 -                       }
27203 +               assert(backends->used < INT_MAX);
27204  
27205 -                       /* get next ndx */
27206 -                       if ((int)k > host->last_used_ndx) {
27207 -                               ndx = k;
27208 -                               host->last_used_ndx = k;
27209 +               /* send each request to another host:
27210 +                *
27211 +                * e.g.:
27212 +                *
27213 +                * if we have three hosts it is
27214 +                *
27215 +                * 1 .. 2 .. 3 .. 1 .. 2 .. 3
27216 +                *
27217 +                **/
27218  
27219 -                               break;
27220 -                       }
27221 +               /* walk through the list */
27222 +               last_used_backend = (data_integer *)array_get_element(p->conf.last_used_backends, extension->key->ptr);
27223 +
27224 +               if (NULL == last_used_backend) {
27225 +                       last_used_backend = data_integer_init();
27226 +
27227 +                       buffer_copy_string_buffer(last_used_backend->key, extension->key);
27228 +                       last_used_backend->value = 0;
27229 +
27230 +                       array_insert_unique(p->conf.last_used_backends, (data_unset *)last_used_backend);
27231 +               }
27232 +
27233 +               /* scan all but the last host to see if they are up
27234 +                * take the first running host */
27235 +               for (k = last_used_backend->value + 1; (int)(k % backends->used) != last_used_backend->value; k++) {
27236 +                       data_proxy *cur = (data_proxy *)backends->data[k % backends->used];
27237 +
27238 +                       if (cur->is_disabled) continue;
27239 +
27240 +                       host = cur;
27241 +
27242 +                       last_used_backend->value = k;
27243 +
27244 +                       break;
27245                 }
27246 -               
27247 -               /* didn't found a higher id, wrap to the start */
27248 -               if (ndx != -1 && max_usage != INT_MAX) {
27249 -                       ndx = max_usage;
27250 +
27251 +               if (NULL == host) {
27252 +                       /* we found nothing better, fallback to the last used backend
27253 +                        * and check if it is still up */
27254 +                       host = (data_proxy *)backends->data[last_used_backend->value];
27255 +
27256 +                       if (host->is_disabled) host = NULL;
27257                 }
27258  
27259                 break;
27260         default:
27261                 break;
27262         }
27263 -       
27264 -       /* found a server */
27265 -       if (ndx != -1) {
27266 -               data_proxy *host = (data_proxy *)extension->value->data[ndx];
27267 -               
27268 -               /* 
27269 -                * if check-local is disabled, use the uri.path handler 
27270 -                * 
27271 -                */
27272 -               
27273 -               /* init handler-context */
27274 -               handler_ctx *hctx;
27275 -               hctx = handler_ctx_init();
27276 -                               
27277 -               hctx->path_info_offset = path_info_offset;
27278 -               hctx->remote_conn      = con;
27279 -               hctx->plugin_data      = p;
27280 -               hctx->host             = host;
27281 -                               
27282 -               con->plugin_ctx[p->id] = hctx;
27283 -               
27284 -               host->usage++;
27285 -               
27286 -               con->mode = p->id;
27287 -               
27288 -               if (p->conf.debug) {
27289 -                       log_error_write(srv, __FILE__, __LINE__,  "sbd", 
27290 -                                       "proxy - found a host",
27291 -                                       host->host, host->port);
27292 -               }
27293  
27294 -               return HANDLER_GO_ON;
27295 -       } else {
27296 -               /* no handler found */
27297 +       /* we havn't found a host */
27298 +       if (NULL == host) {
27299                 con->http_status = 500;
27300 -               
27301 -               log_error_write(srv, __FILE__, __LINE__,  "sb", 
27302 -                               "no proxy-handler found for:", 
27303 +
27304 +               log_error_write(srv, __FILE__, __LINE__,  "sb",
27305 +                               "no proxy-handler found for:",
27306                                 fn);
27307 -               
27308 +
27309                 return HANDLER_FINISHED;
27310         }
27311 +
27312 +       /* init handler-context */
27313 +       hctx = handler_ctx_init();
27314 +
27315 +       hctx->path_info_offset = path_info_offset;
27316 +       hctx->remote_conn      = con;
27317 +       hctx->plugin_data      = p;
27318 +       hctx->host             = host;
27319 +
27320 +       con->plugin_ctx[p->id] = hctx;
27321 +
27322 +       host->usage++;
27323 +
27324 +       /* we handle this request */
27325 +       con->mode = p->id;
27326 +
27327 +       if (p->conf.debug) {
27328 +               log_error_write(srv, __FILE__, __LINE__,  "sbd",
27329 +                               "proxy - found a host",
27330 +                               host->host, host->port);
27331 +       }
27332 +
27333         return HANDLER_GO_ON;
27334  }
27335  
27336  static handler_t mod_proxy_connection_close_callback(server *srv, connection *con, void *p_d) {
27337         plugin_data *p = p_d;
27338 -       
27339 +
27340         proxy_connection_close(srv, con->plugin_ctx[p->id]);
27341  
27342         return HANDLER_GO_ON;
27343 @@ -1276,11 +1245,11 @@
27344                 size_t i, n, k;
27345                 for (i = 0; i < srv->config_context->used; i++) {
27346                         plugin_config *s = p->config_storage[i];
27347 -                       
27348 -                       if (!s) continue; 
27349 +
27350 +                       if (!s) continue;
27351  
27352                         /* get the extensions for all configs */
27353 -                       
27354 +
27355                         for (k = 0; k < s->extensions->used; k++) {
27356                                 data_array *extension = (data_array *)s->extensions->data[k];
27357  
27358 @@ -1290,8 +1259,8 @@
27359  
27360                                         if (!host->is_disabled ||
27361                                             srv->cur_ts - host->disable_ts < 5) continue;
27362 -                       
27363 -                                       log_error_write(srv, __FILE__, __LINE__,  "sbd", 
27364 +
27365 +                                       log_error_write(srv, __FILE__, __LINE__,  "sbd",
27366                                                         "proxy - re-enabled:",
27367                                                         host->host, host->port);
27368  
27369 @@ -1317,8 +1286,8 @@
27370         p->handle_uri_clean        = mod_proxy_check_extension;
27371         p->handle_subrequest       = mod_proxy_handle_subrequest;
27372         p->handle_trigger          = mod_proxy_trigger;
27373 -       
27374 +
27375         p->data         = NULL;
27376 -       
27377 +
27378         return 0;
27379  }
27380 --- lighttpd-1.4.11/src/mod_redirect.c  2006-02-08 15:38:06.000000000 +0200
27381 +++ lighttpd-1.4.12/src/mod_redirect.c  2006-07-11 22:07:52.000000000 +0300
27382 @@ -22,35 +22,35 @@
27383         PLUGIN_DATA;
27384         buffer *match_buf;
27385         buffer *location;
27386 -       
27387 +
27388         plugin_config **config_storage;
27389 -       
27390 -       plugin_config conf; 
27391 +
27392 +       plugin_config conf;
27393  } plugin_data;
27394  
27395  INIT_FUNC(mod_redirect_init) {
27396         plugin_data *p;
27397 -       
27398 +
27399         p = calloc(1, sizeof(*p));
27400 -       
27401 +
27402         p->match_buf = buffer_init();
27403         p->location = buffer_init();
27404 -       
27405 +
27406         return p;
27407  }
27408  
27409  FREE_FUNC(mod_redirect_free) {
27410         plugin_data *p = p_d;
27411 -       
27412 +
27413         if (!p) return HANDLER_GO_ON;
27414  
27415         if (p->config_storage) {
27416                 size_t i;
27417                 for (i = 0; i < srv->config_context->used; i++) {
27418                         plugin_config *s = p->config_storage[i];
27419 -                       
27420 +
27421                         pcre_keyvalue_buffer_free(s->redirect);
27422 -                       
27423 +
27424                         free(s);
27425                 }
27426                 free(p->config_storage);
27427 @@ -59,9 +59,9 @@
27428  
27429         buffer_free(p->match_buf);
27430         buffer_free(p->location);
27431 -       
27432 +
27433         free(p);
27434 -       
27435 +
27436         return HANDLER_GO_ON;
27437  }
27438  
27439 @@ -69,195 +69,137 @@
27440         plugin_data *p = p_d;
27441         data_unset *du;
27442         size_t i = 0;
27443 -       
27444 -       config_values_t cv[] = { 
27445 +
27446 +       config_values_t cv[] = {
27447                 { "url.redirect",               NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
27448                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
27449         };
27450 -       
27451 +
27452         if (!p) return HANDLER_ERROR;
27453 -       
27454 +
27455         /* 0 */
27456         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
27457 -       
27458 +
27459         for (i = 0; i < srv->config_context->used; i++) {
27460                 plugin_config *s;
27461                 size_t j;
27462                 array *ca;
27463                 data_array *da = (data_array *)du;
27464 -               
27465 +
27466                 s = calloc(1, sizeof(plugin_config));
27467                 s->redirect   = pcre_keyvalue_buffer_init();
27468 -               
27469 +
27470                 cv[0].destination = s->redirect;
27471 -               
27472 +
27473                 p->config_storage[i] = s;
27474                 ca = ((data_config *)srv->config_context->data[i])->value;
27475 -       
27476 +
27477                 if (0 != config_insert_values_global(srv, ca, cv)) {
27478                         return HANDLER_ERROR;
27479                 }
27480 -               
27481 +
27482                 if (NULL == (du = array_get_element(ca, "url.redirect"))) {
27483                         /* no url.redirect defined */
27484                         continue;
27485                 }
27486 -               
27487 +
27488                 if (du->type != TYPE_ARRAY) {
27489 -                       log_error_write(srv, __FILE__, __LINE__, "sss", 
27490 +                       log_error_write(srv, __FILE__, __LINE__, "sss",
27491                                         "unexpected type for key: ", "url.redirect", "array of strings");
27492 -                       
27493 +
27494                         return HANDLER_ERROR;
27495                 }
27496 -               
27497 +
27498                 da = (data_array *)du;
27499 -                               
27500 +
27501                 for (j = 0; j < da->value->used; j++) {
27502                         if (da->value->data[j]->type != TYPE_STRING) {
27503 -                               log_error_write(srv, __FILE__, __LINE__, "sssbs", 
27504 -                                               "unexpected type for key: ", 
27505 -                                               "url.redirect", 
27506 +                               log_error_write(srv, __FILE__, __LINE__, "sssbs",
27507 +                                               "unexpected type for key: ",
27508 +                                               "url.redirect",
27509                                                 "[", da->value->data[j]->key, "](string)");
27510 -                               
27511 +
27512                                 return HANDLER_ERROR;
27513                         }
27514 -                               
27515 -                       if (0 != pcre_keyvalue_buffer_append(s->redirect, 
27516 +
27517 +                       if (0 != pcre_keyvalue_buffer_append(s->redirect,
27518                                                              ((data_string *)(da->value->data[j]))->key->ptr,
27519                                                              ((data_string *)(da->value->data[j]))->value->ptr)) {
27520 -                                       
27521 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
27522 +
27523 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
27524                                                 "pcre-compile failed for", da->value->data[j]->key);
27525                         }
27526                 }
27527         }
27528 -       
27529 +
27530         return HANDLER_GO_ON;
27531  }
27532  #ifdef HAVE_PCRE_H
27533  static int mod_redirect_patch_connection(server *srv, connection *con, plugin_data *p) {
27534         size_t i, j;
27535         plugin_config *s = p->config_storage[0];
27536 -       
27537 +
27538         p->conf.redirect = s->redirect;
27539 -       
27540 +
27541         /* skip the first, the global context */
27542         for (i = 1; i < srv->config_context->used; i++) {
27543                 data_config *dc = (data_config *)srv->config_context->data[i];
27544                 s = p->config_storage[i];
27545 -               
27546 +
27547                 /* condition didn't match */
27548                 if (!config_check_cond(srv, con, dc)) continue;
27549 -               
27550 +
27551                 /* merge config */
27552                 for (j = 0; j < dc->value->used; j++) {
27553                         data_unset *du = dc->value->data[j];
27554 -                       
27555 +
27556                         if (0 == strcmp(du->key->ptr, "url.redirect")) {
27557                                 p->conf.redirect = s->redirect;
27558                                 p->conf.context = dc;
27559                         }
27560                 }
27561         }
27562 -       
27563 +
27564         return 0;
27565  }
27566  #endif
27567  static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_data) {
27568  #ifdef HAVE_PCRE_H
27569         plugin_data *p = p_data;
27570 -       size_t i;
27571 +       int i;
27572  
27573 -       /* 
27574 +       /*
27575          * REWRITE URL
27576 -        * 
27577 +        *
27578          * e.g. redirect /base/ to /index.php?section=base
27579 -        * 
27580 +        *
27581          */
27582 -       
27583 +
27584         mod_redirect_patch_connection(srv, con, p);
27585 -       
27586 +
27587         buffer_copy_string_buffer(p->match_buf, con->request.uri);
27588 -       
27589 -       for (i = 0; i < p->conf.redirect->used; i++) {
27590 -               pcre *match;
27591 -               pcre_extra *extra;
27592 -               const char *pattern;
27593 -               size_t pattern_len;
27594 -               int n;
27595 -               pcre_keyvalue *kv = p->conf.redirect->kv[i];
27596 -# define N 10
27597 -               int ovec[N * 3];
27598 -               
27599 -               match       = kv->key;
27600 -               extra       = kv->key_extra;
27601 -               pattern     = kv->value->ptr;
27602 -               pattern_len = kv->value->used - 1;
27603 -               
27604 -               if ((n = pcre_exec(match, extra, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
27605 -                       if (n != PCRE_ERROR_NOMATCH) {
27606 -                               log_error_write(srv, __FILE__, __LINE__, "sd",
27607 -                                               "execution error while matching: ", n);
27608 -                               return HANDLER_ERROR;
27609 -                       }
27610 -               } else {
27611 -                       const char **list;
27612 -                       size_t start, end;
27613 -                       size_t k;
27614 -                       
27615 -                       /* it matched */
27616 -                       pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
27617 -                       
27618 -                       /* search for $[0-9] */
27619 -                       
27620 -                       buffer_reset(p->location);
27621 -                       
27622 -                       start = 0; end = pattern_len;
27623 -                       for (k = 0; k < pattern_len; k++) {
27624 -                               if ((pattern[k] == '$' || pattern[k] == '%') &&
27625 -                                   isdigit((unsigned char)pattern[k + 1])) {
27626 -                                       /* got one */
27627 -                                       
27628 -                                       size_t num = pattern[k + 1] - '0';
27629 -                                       
27630 -                                       end = k;
27631 -                                       
27632 -                                       buffer_append_string_len(p->location, pattern + start, end - start);
27633 -                                       
27634 -                                       if (pattern[k] == '$') {
27635 -                                               /* n is always > 0 */
27636 -                                               if (num < (size_t)n) {
27637 -                                                       buffer_append_string(p->location, list[num]);
27638 -                                               }
27639 -                                       } else {
27640 -                                               config_append_cond_match_buffer(con, p->conf.context, p->location, num);
27641 -                                       }
27642 -                                       
27643 -                                       k++;
27644 -                                       start = k + 1;
27645 -                               } 
27646 -                       }
27647 -                       
27648 -                       buffer_append_string_len(p->location, pattern + start, pattern_len - start);
27649 -                       
27650 -                       pcre_free(list);
27651 -                       
27652 -                       response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
27653 -                       
27654 -                       con->http_status = 301;
27655 -                       con->file_finished = 1;
27656 -                       
27657 -                       return HANDLER_FINISHED;
27658 -               }
27659 +       i = config_exec_pcre_keyvalue_buffer(con, p->conf.redirect, p->conf.context, p->match_buf, p->location);
27660 +
27661 +       if (i >= 0) {
27662 +               response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
27663 +
27664 +               con->http_status = 301;
27665 +               con->file_finished = 1;
27666 +
27667 +               return HANDLER_FINISHED;
27668 +       }
27669 +       else if (i != PCRE_ERROR_NOMATCH) {
27670 +               log_error_write(srv, __FILE__, __LINE__, "s",
27671 +                               "execution error while matching", i);
27672         }
27673  #undef N
27674 -               
27675 +
27676  #else
27677         UNUSED(srv);
27678         UNUSED(con);
27679         UNUSED(p_data);
27680  #endif
27681 -       
27682 +
27683         return HANDLER_GO_ON;
27684  }
27685  
27686 @@ -265,13 +207,13 @@
27687  int mod_redirect_plugin_init(plugin *p) {
27688         p->version     = LIGHTTPD_VERSION_ID;
27689         p->name        = buffer_init_string("redirect");
27690 -       
27691 +
27692         p->init        = mod_redirect_init;
27693         p->handle_uri_clean  = mod_redirect_uri_handler;
27694         p->set_defaults  = mod_redirect_set_defaults;
27695         p->cleanup     = mod_redirect_free;
27696 -       
27697 +
27698         p->data        = NULL;
27699 -       
27700 +
27701         return 0;
27702  }
27703 --- lighttpd-1.4.11/src/mod_rewrite.c   2005-09-29 20:59:10.000000000 +0300
27704 +++ lighttpd-1.4.12/src/mod_rewrite.c   2006-07-11 22:07:51.000000000 +0300
27705 @@ -13,24 +13,8 @@
27706  #endif
27707  
27708  typedef struct {
27709 -#ifdef HAVE_PCRE_H
27710 -       pcre *key;
27711 -#endif
27712 -       
27713 -       buffer *value;
27714 -       
27715 -       int once;
27716 -} rewrite_rule;
27717 -
27718 -typedef struct {
27719 -       rewrite_rule **ptr;
27720 -       
27721 -       size_t used;
27722 -       size_t size;
27723 -} rewrite_rule_buffer;
27724 -
27725 -typedef struct {
27726 -       rewrite_rule_buffer *rewrite;
27727 +       pcre_keyvalue_buffer *rewrite;
27728 +       buffer *once;
27729         data_config *context; /* to which apply me */
27730  } plugin_config;
27731  
27732 @@ -42,20 +26,20 @@
27733  typedef struct {
27734         PLUGIN_DATA;
27735         buffer *match_buf;
27736 -       
27737 +
27738         plugin_config **config_storage;
27739 -       
27740 -       plugin_config conf; 
27741 +
27742 +       plugin_config conf;
27743  } plugin_data;
27744  
27745  static handler_ctx * handler_ctx_init() {
27746         handler_ctx * hctx;
27747 -       
27748 +
27749         hctx = calloc(1, sizeof(*hctx));
27750 -       
27751 +
27752         hctx->state = REWRITE_STATE_UNSET;
27753         hctx->loops = 0;
27754 -       
27755 +
27756         return hctx;
27757  }
27758  
27759 @@ -63,207 +47,136 @@
27760         free(hctx);
27761  }
27762  
27763 -rewrite_rule_buffer *rewrite_rule_buffer_init(void) {
27764 -       rewrite_rule_buffer *kvb;
27765 -       
27766 -       kvb = calloc(1, sizeof(*kvb));
27767 -       
27768 -       return kvb;
27769 -}
27770 -
27771 -int rewrite_rule_buffer_append(rewrite_rule_buffer *kvb, buffer *key, buffer *value, int once) {
27772 -#ifdef HAVE_PCRE_H
27773 -       size_t i;
27774 -       const char *errptr;
27775 -       int erroff;
27776 -       
27777 -       if (!key) return -1;
27778 -
27779 -       if (kvb->size == 0) {
27780 -               kvb->size = 4;
27781 -               kvb->used = 0;
27782 -               
27783 -               kvb->ptr = malloc(kvb->size * sizeof(*kvb->ptr));
27784 -               
27785 -               for(i = 0; i < kvb->size; i++) {
27786 -                       kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
27787 -               }
27788 -       } else if (kvb->used == kvb->size) {
27789 -               kvb->size += 4;
27790 -               
27791 -               kvb->ptr = realloc(kvb->ptr, kvb->size * sizeof(*kvb->ptr));
27792 -               
27793 -               for(i = kvb->used; i < kvb->size; i++) {
27794 -                       kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
27795 -               }
27796 -       }
27797 -       
27798 -       if (NULL == (kvb->ptr[kvb->used]->key = pcre_compile(key->ptr,
27799 -                                                           0, &errptr, &erroff, NULL))) {
27800 -               
27801 -               return -1;
27802 -       }
27803 -       
27804 -       kvb->ptr[kvb->used]->value = buffer_init();
27805 -       buffer_copy_string_buffer(kvb->ptr[kvb->used]->value, value);
27806 -       kvb->ptr[kvb->used]->once = once;
27807 -       
27808 -       kvb->used++;
27809 -       
27810 -       return 0;
27811 -#else
27812 -       UNUSED(kvb);
27813 -       UNUSED(value);
27814 -       UNUSED(once);
27815 -       UNUSED(key);
27816 -
27817 -       return -1;
27818 -#endif
27819 -}
27820 -
27821 -void rewrite_rule_buffer_free(rewrite_rule_buffer *kvb) {
27822 -#ifdef HAVE_PCRE_H
27823 -       size_t i;
27824 -
27825 -       for (i = 0; i < kvb->size; i++) {
27826 -               if (kvb->ptr[i]->key) pcre_free(kvb->ptr[i]->key);
27827 -               if (kvb->ptr[i]->value) buffer_free(kvb->ptr[i]->value);
27828 -               free(kvb->ptr[i]);
27829 -       }
27830 -       
27831 -       if (kvb->ptr) free(kvb->ptr);
27832 -#endif
27833 -       
27834 -       free(kvb);
27835 -}
27836 -
27837  
27838  INIT_FUNC(mod_rewrite_init) {
27839         plugin_data *p;
27840 -       
27841 +
27842         p = calloc(1, sizeof(*p));
27843 -       
27844 +
27845         p->match_buf = buffer_init();
27846 -       
27847 +
27848         return p;
27849  }
27850  
27851  FREE_FUNC(mod_rewrite_free) {
27852         plugin_data *p = p_d;
27853 -       
27854 +
27855         UNUSED(srv);
27856  
27857         if (!p) return HANDLER_GO_ON;
27858 -       
27859 +
27860         buffer_free(p->match_buf);
27861         if (p->config_storage) {
27862                 size_t i;
27863                 for (i = 0; i < srv->config_context->used; i++) {
27864                         plugin_config *s = p->config_storage[i];
27865 -                       rewrite_rule_buffer_free(s->rewrite);
27866 -                       
27867 +                       pcre_keyvalue_buffer_free(s->rewrite);
27868 +                       buffer_free(s->once);
27869 +
27870                         free(s);
27871                 }
27872                 free(p->config_storage);
27873         }
27874 -       
27875 +
27876         free(p);
27877 -       
27878 +
27879         return HANDLER_GO_ON;
27880  }
27881  
27882  static int parse_config_entry(server *srv, plugin_config *s, array *ca, const char *option, int once) {
27883         data_unset *du;
27884 -       
27885 +
27886         if (NULL != (du = array_get_element(ca, option))) {
27887                 data_array *da = (data_array *)du;
27888                 size_t j;
27889 -               
27890 +
27891                 if (du->type != TYPE_ARRAY) {
27892 -                       log_error_write(srv, __FILE__, __LINE__, "sss", 
27893 +                       log_error_write(srv, __FILE__, __LINE__, "sss",
27894                                         "unexpected type for key: ", option, "array of strings");
27895 -                       
27896 +
27897                         return HANDLER_ERROR;
27898                 }
27899 -               
27900 +
27901                 da = (data_array *)du;
27902 -               
27903 +
27904                 for (j = 0; j < da->value->used; j++) {
27905                         if (da->value->data[j]->type != TYPE_STRING) {
27906 -                               log_error_write(srv, __FILE__, __LINE__, "sssbs", 
27907 -                                               "unexpected type for key: ", 
27908 -                                               option, 
27909 +                               log_error_write(srv, __FILE__, __LINE__, "sssbs",
27910 +                                               "unexpected type for key: ",
27911 +                                               option,
27912                                                 "[", da->value->data[j]->key, "](string)");
27913 -                               
27914 +
27915                                 return HANDLER_ERROR;
27916                         }
27917 -                       
27918 -                       if (0 != rewrite_rule_buffer_append(s->rewrite, 
27919 -                                                           ((data_string *)(da->value->data[j]))->key,
27920 -                                                           ((data_string *)(da->value->data[j]))->value,
27921 -                                                           once)) {
27922 +
27923 +                       if (0 != pcre_keyvalue_buffer_append(s->rewrite,
27924 +                                                           ((data_string *)(da->value->data[j]))->key->ptr,
27925 +                                                           ((data_string *)(da->value->data[j]))->value->ptr)) {
27926  #ifdef HAVE_PCRE_H
27927 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
27928 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
27929                                                 "pcre-compile failed for", da->value->data[j]->key);
27930  #else
27931 -                               log_error_write(srv, __FILE__, __LINE__, "s", 
27932 +                               log_error_write(srv, __FILE__, __LINE__, "s",
27933                                                 "pcre support is missing, please install libpcre and the headers");
27934  #endif
27935                         }
27936 +
27937 +                       if (once) {
27938 +                               buffer_append_string_len(s->once, CONST_STR_LEN("1"));
27939 +                       } else {
27940 +                               buffer_append_string_len(s->once, CONST_STR_LEN("0"));
27941 +                       }
27942                 }
27943         }
27944 -       
27945 +
27946         return 0;
27947  }
27948  
27949  SETDEFAULTS_FUNC(mod_rewrite_set_defaults) {
27950         plugin_data *p = p_d;
27951         size_t i = 0;
27952 -       
27953 -       config_values_t cv[] = { 
27954 +
27955 +       config_values_t cv[] = {
27956                 { "url.rewrite-repeat",        NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
27957                 { "url.rewrite-once",          NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
27958 -               
27959 -               /* old names, still supported 
27960 -                * 
27961 +
27962 +               /* old names, still supported
27963 +                *
27964                  * url.rewrite remapped to url.rewrite-once
27965                  * url.rewrite-final    is url.rewrite-once
27966 -                * 
27967 +                *
27968                  */
27969                 { "url.rewrite",               NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
27970                 { "url.rewrite-final",         NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
27971                 { NULL,                        NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
27972         };
27973 -       
27974 +
27975         if (!p) return HANDLER_ERROR;
27976 -       
27977 +
27978         /* 0 */
27979         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
27980 -       
27981 +
27982         for (i = 0; i < srv->config_context->used; i++) {
27983                 plugin_config *s;
27984                 array *ca;
27985 -               
27986 +
27987                 s = calloc(1, sizeof(plugin_config));
27988 -               s->rewrite   = rewrite_rule_buffer_init();
27989 -               
27990 -               cv[0].destination = s->rewrite;
27991 -               cv[1].destination = s->rewrite;
27992 -               cv[2].destination = s->rewrite;
27993 -               
27994 +               s->rewrite   = pcre_keyvalue_buffer_init();
27995 +               s->once      = buffer_init();
27996 +
27997                 p->config_storage[i] = s;
27998                 ca = ((data_config *)srv->config_context->data[i])->value;
27999 -       
28000 +
28001                 if (0 != config_insert_values_global(srv, ca, cv)) {
28002                         return HANDLER_ERROR;
28003                 }
28004 -               
28005 +
28006                 parse_config_entry(srv, s, ca, "url.rewrite-once",   1);
28007                 parse_config_entry(srv, s, ca, "url.rewrite-final",  1);
28008                 parse_config_entry(srv, s, ca, "url.rewrite",        1);
28009                 parse_config_entry(srv, s, ca, "url.rewrite-repeat", 0);
28010         }
28011 -       
28012 +
28013         return HANDLER_GO_ON;
28014  }
28015  #ifdef HAVE_PCRE_H
28016 @@ -271,157 +184,107 @@
28017         size_t i, j;
28018         plugin_config *s = p->config_storage[0];
28019         p->conf.rewrite = s->rewrite;
28020 -       
28021 +       p->conf.once    = s->once;
28022 +
28023         /* skip the first, the global context */
28024         for (i = 1; i < srv->config_context->used; i++) {
28025                 data_config *dc = (data_config *)srv->config_context->data[i];
28026                 s = p->config_storage[i];
28027 -               
28028 +
28029                 if (COMP_HTTP_URL == dc->comp) continue;
28030 -               
28031 +
28032                 /* condition didn't match */
28033                 if (!config_check_cond(srv, con, dc)) continue;
28034 -               
28035 +
28036                 /* merge config */
28037                 for (j = 0; j < dc->value->used; j++) {
28038                         data_unset *du = dc->value->data[j];
28039 -                       
28040 +
28041                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite"))) {
28042                                 p->conf.rewrite = s->rewrite;
28043 +                               p->conf.once    = s->once;
28044                                 p->conf.context = dc;
28045                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-once"))) {
28046                                 p->conf.rewrite = s->rewrite;
28047 +                               p->conf.once    = s->once;
28048                                 p->conf.context = dc;
28049                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-repeat"))) {
28050                                 p->conf.rewrite = s->rewrite;
28051 +                               p->conf.once    = s->once;
28052                                 p->conf.context = dc;
28053                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-final"))) {
28054                                 p->conf.rewrite = s->rewrite;
28055 +                               p->conf.once    = s->once;
28056                                 p->conf.context = dc;
28057                         }
28058                 }
28059         }
28060 -       
28061 +
28062         return 0;
28063  }
28064  #endif
28065  URIHANDLER_FUNC(mod_rewrite_con_reset) {
28066         plugin_data *p = p_d;
28067 -       
28068 +
28069         UNUSED(srv);
28070 -       
28071 +
28072         if (con->plugin_ctx[p->id]) {
28073                 handler_ctx_free(con->plugin_ctx[p->id]);
28074                 con->plugin_ctx[p->id] = NULL;
28075         }
28076 -       
28077 +
28078         return HANDLER_GO_ON;
28079  }
28080  
28081  URIHANDLER_FUNC(mod_rewrite_uri_handler) {
28082  #ifdef HAVE_PCRE_H
28083         plugin_data *p = p_d;
28084 -       size_t i;
28085 +       int i;
28086         handler_ctx *hctx;
28087  
28088 -       /* 
28089 +       /*
28090          * REWRITE URL
28091 -        * 
28092 +        *
28093          * e.g. rewrite /base/ to /index.php?section=base
28094 -        * 
28095 +        *
28096          */
28097 -       
28098 +
28099         if (con->plugin_ctx[p->id]) {
28100                 hctx = con->plugin_ctx[p->id];
28101 -               
28102 +
28103                 if (hctx->loops++ > 100) {
28104 -                       log_error_write(srv, __FILE__, __LINE__,  "s",  
28105 +                       log_error_write(srv, __FILE__, __LINE__,  "s",
28106                                         "ENDLESS LOOP IN rewrite-rule DETECTED ... aborting request, perhaps you want to use url.rewrite-once instead of url.rewrite-repeat");
28107 -                       
28108 +
28109                         return HANDLER_ERROR;
28110                 }
28111 -               
28112 +
28113                 if (hctx->state == REWRITE_STATE_FINISHED) return HANDLER_GO_ON;
28114         }
28115 -       
28116 +
28117         mod_rewrite_patch_connection(srv, con, p);
28118  
28119         if (!p->conf.rewrite) return HANDLER_GO_ON;
28120 -       
28121 +
28122         buffer_copy_string_buffer(p->match_buf, con->request.uri);
28123 -       
28124 -       for (i = 0; i < p->conf.rewrite->used; i++) {
28125 -               pcre *match;
28126 -               const char *pattern;
28127 -               size_t pattern_len;
28128 -               int n;
28129 -               rewrite_rule *rule = p->conf.rewrite->ptr[i];
28130 -# define N 10
28131 -               int ovec[N * 3];
28132 -               
28133 -               match       = rule->key;
28134 -               pattern     = rule->value->ptr;
28135 -               pattern_len = rule->value->used - 1;
28136 -               
28137 -               if ((n = pcre_exec(match, NULL, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
28138 -                       if (n != PCRE_ERROR_NOMATCH) {
28139 -                               log_error_write(srv, __FILE__, __LINE__, "sd",
28140 -                                               "execution error while matching: ", n);
28141 -                               return HANDLER_ERROR;
28142 -                       }
28143 -               } else {
28144 -                       const char **list;
28145 -                       size_t start, end;
28146 -                       size_t k;
28147 -                       
28148 -                       /* it matched */
28149 -                       pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
28150 -                       
28151 -                       /* search for $[0-9] */
28152 -                       
28153 -                       buffer_reset(con->request.uri);
28154 -                       
28155 -                       start = 0; end = pattern_len;
28156 -                       for (k = 0; k < pattern_len; k++) {
28157 -                               if ((pattern[k] == '$' || pattern[k] == '%') &&
28158 -                                   isdigit((unsigned char)pattern[k + 1])) {
28159 -                                       /* got one */
28160 -                                       
28161 -                                       size_t num = pattern[k + 1] - '0';
28162 -                                       
28163 -                                       end = k;
28164 -                                       
28165 -                                       buffer_append_string_len(con->request.uri, pattern + start, end - start);
28166 -                                       
28167 -                                       if (pattern[k] == '$') {
28168 -                                               /* n is always > 0 */
28169 -                                               if (num < (size_t)n) {
28170 -                                                       buffer_append_string(con->request.uri, list[num]);
28171 -                                               }
28172 -                                       } else {
28173 -                                               config_append_cond_match_buffer(con, p->conf.context, con->request.uri, num);
28174 -                                       }
28175 -                                       
28176 -                                       k++;
28177 -                                       start = k + 1;
28178 -                               } 
28179 -                       }
28180 -                       
28181 -                       buffer_append_string_len(con->request.uri, pattern + start, pattern_len - start);
28182 -                       
28183 -                       pcre_free(list);
28184 -                       
28185 -                       hctx = handler_ctx_init();
28186 -                               
28187 -                       con->plugin_ctx[p->id] = hctx;
28188 -                       
28189 -                       if (rule->once) hctx->state = REWRITE_STATE_FINISHED;
28190 -                       
28191 -                       return HANDLER_COMEBACK;
28192 -               }
28193 +       i = config_exec_pcre_keyvalue_buffer(con, p->conf.rewrite, p->conf.context, p->match_buf, con->request.uri);
28194 +
28195 +       if (i >= 0) {
28196 +               hctx = handler_ctx_init();
28197 +
28198 +               con->plugin_ctx[p->id] = hctx;
28199 +
28200 +               if (p->conf.once->ptr[i] == '1')
28201 +                       hctx->state = REWRITE_STATE_FINISHED;
28202 +
28203 +               return HANDLER_COMEBACK;
28204 +       }
28205 +       else if (i != PCRE_ERROR_NOMATCH) {
28206 +               log_error_write(srv, __FILE__, __LINE__, "s",
28207 +                               "execution error while matching", i);
28208         }
28209  #undef N
28210 -               
28211 +
28212  #else
28213         UNUSED(srv);
28214         UNUSED(con);
28215 @@ -434,17 +297,17 @@
28216  int mod_rewrite_plugin_init(plugin *p) {
28217         p->version     = LIGHTTPD_VERSION_ID;
28218         p->name        = buffer_init_string("rewrite");
28219 -       
28220 +
28221         p->init        = mod_rewrite_init;
28222         /* it has to stay _raw as we are matching on uri + querystring
28223          */
28224 -       
28225 +
28226         p->handle_uri_raw = mod_rewrite_uri_handler;
28227         p->set_defaults = mod_rewrite_set_defaults;
28228         p->cleanup     = mod_rewrite_free;
28229         p->connection_reset = mod_rewrite_con_reset;
28230 -       
28231 +
28232         p->data        = NULL;
28233 -       
28234 +
28235         return 0;
28236  }
28237 --- lighttpd-1.4.11/src/mod_rrdtool.c   2005-08-22 01:52:24.000000000 +0300
28238 +++ lighttpd-1.4.12/src/mod_rrdtool.c   2006-07-11 22:07:52.000000000 +0300
28239 @@ -5,7 +5,6 @@
28240  #include <stdlib.h>
28241  #include <stdio.h>
28242  #include <string.h>
28243 -#include <unistd.h>
28244  #include <errno.h>
28245  #include <time.h>
28246  
28247 @@ -20,10 +19,14 @@
28248  /* no need for waitpid if we don't have fork */
28249  #include <sys/wait.h>
28250  #endif
28251 +
28252 +#include "sys-files.h"
28253 +#include "sys-process.h"
28254 +
28255  typedef struct {
28256         buffer *path_rrdtool_bin;
28257         buffer *path_rrd;
28258 -       
28259 +
28260         double requests, *requests_ptr;
28261         double bytes_written, *bytes_written_ptr;
28262         double bytes_read, *bytes_read_ptr;
28263 @@ -31,84 +34,84 @@
28264  
28265  typedef struct {
28266         PLUGIN_DATA;
28267 -       
28268 +
28269         buffer *cmd;
28270         buffer *resp;
28271 -       
28272 +
28273         int read_fd, write_fd;
28274         pid_t rrdtool_pid;
28275 -       
28276 +
28277         int rrdtool_running;
28278 -       
28279 +
28280         plugin_config **config_storage;
28281         plugin_config conf;
28282  } plugin_data;
28283  
28284  INIT_FUNC(mod_rrd_init) {
28285         plugin_data *p;
28286 -       
28287 +
28288         p = calloc(1, sizeof(*p));
28289 -       
28290 +
28291         p->resp = buffer_init();
28292         p->cmd = buffer_init();
28293 -       
28294 +
28295         return p;
28296  }
28297  
28298  FREE_FUNC(mod_rrd_free) {
28299         plugin_data *p = p_d;
28300         size_t i;
28301 -       
28302 +
28303         if (!p) return HANDLER_GO_ON;
28304 -       
28305 +
28306         if (p->config_storage) {
28307                 for (i = 0; i < srv->config_context->used; i++) {
28308                         plugin_config *s = p->config_storage[i];
28309 -                       
28310 +
28311                         buffer_free(s->path_rrdtool_bin);
28312                         buffer_free(s->path_rrd);
28313 -                       
28314 +
28315                         free(s);
28316                 }
28317         }
28318         buffer_free(p->cmd);
28319         buffer_free(p->resp);
28320 -       
28321 +
28322         free(p->config_storage);
28323 -       
28324 +
28325         if (p->rrdtool_pid) {
28326                 int status;
28327                 close(p->read_fd);
28328                 close(p->write_fd);
28329 -#ifdef HAVE_FORK       
28330 +#ifdef HAVE_FORK
28331                 /* collect status */
28332                 waitpid(p->rrdtool_pid, &status, 0);
28333  #endif
28334         }
28335 -       
28336 +
28337         free(p);
28338 -       
28339 +
28340         return HANDLER_GO_ON;
28341  }
28342  
28343  int mod_rrd_create_pipe(server *srv, plugin_data *p) {
28344         pid_t pid;
28345 -       
28346 +
28347         int to_rrdtool_fds[2];
28348         int from_rrdtool_fds[2];
28349 -#ifdef HAVE_FORK       
28350 +#ifdef HAVE_FORK
28351         if (pipe(to_rrdtool_fds)) {
28352 -               log_error_write(srv, __FILE__, __LINE__, "ss", 
28353 +               log_error_write(srv, __FILE__, __LINE__, "ss",
28354                                 "pipe failed: ", strerror(errno));
28355                 return -1;
28356         }
28357 -       
28358 +
28359         if (pipe(from_rrdtool_fds)) {
28360 -               log_error_write(srv, __FILE__, __LINE__, "ss", 
28361 +               log_error_write(srv, __FILE__, __LINE__, "ss",
28362                                 "pipe failed: ", strerror(errno));
28363                 return -1;
28364         }
28365 -       
28366 +
28367         /* fork, execve */
28368         switch (pid = fork()) {
28369         case 0: {
28370 @@ -117,33 +120,33 @@
28371                 int argc;
28372                 int i = 0;
28373                 char *dash = "-";
28374 -               
28375 +
28376                 /* move stdout to from_rrdtool_fd[1] */
28377                 close(STDOUT_FILENO);
28378                 dup2(from_rrdtool_fds[1], STDOUT_FILENO);
28379                 close(from_rrdtool_fds[1]);
28380                 /* not needed */
28381                 close(from_rrdtool_fds[0]);
28382 -               
28383 +
28384                 /* move the stdin to to_rrdtool_fd[0] */
28385                 close(STDIN_FILENO);
28386                 dup2(to_rrdtool_fds[0], STDIN_FILENO);
28387                 close(to_rrdtool_fds[0]);
28388                 /* not needed */
28389                 close(to_rrdtool_fds[1]);
28390 -               
28391 +
28392                 close(STDERR_FILENO);
28393 -               
28394 +
28395                 if (srv->errorlog_mode == ERRORLOG_FILE) {
28396                         dup2(srv->errorlog_fd, STDERR_FILENO);
28397                         close(srv->errorlog_fd);
28398                 }
28399 -               
28400 +
28401                 /* set up args */
28402                 argc = 3;
28403                 args = malloc(sizeof(*args) * argc);
28404                 i = 0;
28405 -               
28406 +
28407                 args[i++] = p->conf.path_rrdtool_bin->ptr;
28408                 args[i++] = dash;
28409                 args[i++] = NULL;
28410 @@ -152,12 +155,12 @@
28411                 for (i = 3; i < 256; i++) {
28412                         close(i);
28413                 }
28414 -               
28415 +
28416                 /* exec the cgi */
28417                 execv(args[0], args);
28418 -               
28419 +
28420                 log_error_write(srv, __FILE__, __LINE__, "sss", "spawing rrdtool failed: ", strerror(errno), args[0]);
28421 -               
28422 +
28423                 /* */
28424                 SEGFAULT();
28425                 break;
28426 @@ -168,19 +171,19 @@
28427                 break;
28428         default: {
28429                 /* father */
28430 -               
28431 +
28432                 close(from_rrdtool_fds[1]);
28433                 close(to_rrdtool_fds[0]);
28434 -               
28435 +
28436                 /* register PID and wait for them asyncronously */
28437                 p->write_fd = to_rrdtool_fds[1];
28438                 p->read_fd = from_rrdtool_fds[0];
28439                 p->rrdtool_pid = pid;
28440 -               
28441 +
28442                 break;
28443         }
28444         }
28445 -       
28446 +
28447         return 0;
28448  #else
28449         return -1;
28450 @@ -189,19 +192,19 @@
28451  
28452  static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s) {
28453         struct stat st;
28454 -       
28455 +
28456         /* check if DB already exists */
28457         if (0 == stat(s->path_rrd->ptr, &st)) {
28458                 /* check if it is plain file */
28459                 if (!S_ISREG(st.st_mode)) {
28460 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
28461 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
28462                                         "not a regular file:", s->path_rrd);
28463                         return HANDLER_ERROR;
28464                 }
28465         } else {
28466                 int r ;
28467                 /* create a new one */
28468 -               
28469 +
28470                 BUFFER_COPY_STRING_CONST(p->cmd, "create ");
28471                 buffer_append_string_buffer(p->cmd, s->path_rrd);
28472                 buffer_append_string(p->cmd, " --step 60 ");
28473 @@ -220,158 +223,155 @@
28474                 buffer_append_string(p->cmd, "RRA:MIN:0.5:6:700 ");
28475                 buffer_append_string(p->cmd, "RRA:MIN:0.5:24:775 ");
28476                 buffer_append_string(p->cmd, "RRA:MIN:0.5:288:797\n");
28477 -               
28478 +
28479                 if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
28480 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
28481 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
28482                                 "rrdtool-write: failed", strerror(errno));
28483 -                       
28484 +
28485                         return HANDLER_ERROR;
28486                 }
28487 -               
28488 +
28489                 buffer_prepare_copy(p->resp, 4096);
28490                 if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
28491 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
28492 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
28493                                 "rrdtool-read: failed", strerror(errno));
28494 -                       
28495 +
28496                         return HANDLER_ERROR;
28497                 }
28498 -               
28499 +
28500                 p->resp->used = r;
28501 -               
28502 +
28503                 if (p->resp->ptr[0] != 'O' ||
28504                     p->resp->ptr[1] != 'K') {
28505 -                       log_error_write(srv, __FILE__, __LINE__, "sbb", 
28506 +                       log_error_write(srv, __FILE__, __LINE__, "sbb",
28507                                 "rrdtool-response:", p->cmd, p->resp);
28508 -                       
28509 +
28510                         return HANDLER_ERROR;
28511                 }
28512         }
28513 -       
28514 +
28515         return HANDLER_GO_ON;
28516  }
28517  
28518 -#define PATCH(x) \
28519 -       p->conf.x = s->x;
28520  static int mod_rrd_patch_connection(server *srv, connection *con, plugin_data *p) {
28521         size_t i, j;
28522         plugin_config *s = p->config_storage[0];
28523 -       
28524 -       PATCH(path_rrdtool_bin);
28525 -       PATCH(path_rrd);
28526 -       
28527 +
28528 +       PATCH_OPTION(path_rrdtool_bin);
28529 +       PATCH_OPTION(path_rrd);
28530 +
28531         p->conf.bytes_written_ptr = &(s->bytes_written);
28532         p->conf.bytes_read_ptr = &(s->bytes_read);
28533         p->conf.requests_ptr = &(s->requests);
28534 -       
28535 +
28536         /* skip the first, the global context */
28537         for (i = 1; i < srv->config_context->used; i++) {
28538                 data_config *dc = (data_config *)srv->config_context->data[i];
28539                 s = p->config_storage[i];
28540 -               
28541 +
28542                 /* condition didn't match */
28543                 if (!config_check_cond(srv, con, dc)) continue;
28544 -               
28545 +
28546                 /* merge config */
28547                 for (j = 0; j < dc->value->used; j++) {
28548                         data_unset *du = dc->value->data[j];
28549 -                       
28550 +
28551                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("rrdtool.db-name"))) {
28552 -                               PATCH(path_rrd);
28553 +                               PATCH_OPTION(path_rrd);
28554                                 /* get pointers to double values */
28555 -                               
28556 +
28557                                 p->conf.bytes_written_ptr = &(s->bytes_written);
28558                                 p->conf.bytes_read_ptr = &(s->bytes_read);
28559                                 p->conf.requests_ptr = &(s->requests);
28560                         }
28561                 }
28562         }
28563 -       
28564 +
28565         return 0;
28566  }
28567 -#undef PATCH
28568  
28569  SETDEFAULTS_FUNC(mod_rrd_set_defaults) {
28570         plugin_data *p = p_d;
28571         size_t i;
28572 -       
28573 -       config_values_t cv[] = { 
28574 +
28575 +       config_values_t cv[] = {
28576                 { "rrdtool.binary",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
28577                 { "rrdtool.db-name",             NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
28578                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
28579         };
28580 -       
28581 +
28582         if (!p) return HANDLER_ERROR;
28583 -       
28584 +
28585         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
28586 -       
28587 +
28588         for (i = 0; i < srv->config_context->used; i++) {
28589                 plugin_config *s;
28590 -               
28591 +
28592                 s = calloc(1, sizeof(plugin_config));
28593                 s->path_rrdtool_bin = buffer_init();
28594                 s->path_rrd = buffer_init();
28595                 s->requests = 0;
28596                 s->bytes_written = 0;
28597                 s->bytes_read = 0;
28598 -               
28599 +
28600                 cv[0].destination = s->path_rrdtool_bin;
28601                 cv[1].destination = s->path_rrd;
28602 -               
28603 +
28604                 p->config_storage[i] = s;
28605 -       
28606 +
28607                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
28608                         return HANDLER_ERROR;
28609                 }
28610 -               
28611 +
28612                 if (i > 0 && !buffer_is_empty(s->path_rrdtool_bin)) {
28613                         /* path_rrdtool_bin is a global option */
28614 -                       
28615 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
28616 +
28617 +                       log_error_write(srv, __FILE__, __LINE__, "s",
28618                                         "rrdtool.binary can only be set as a global option.");
28619 -                       
28620 +
28621                         return HANDLER_ERROR;
28622                 }
28623 -               
28624 +
28625         }
28626 -       
28627 +
28628         p->conf.path_rrdtool_bin = p->config_storage[0]->path_rrdtool_bin;
28629         p->rrdtool_running = 0;
28630 -       
28631 +
28632         /* check for dir */
28633 -       
28634 +
28635         if (buffer_is_empty(p->conf.path_rrdtool_bin)) {
28636 -               log_error_write(srv, __FILE__, __LINE__, "s", 
28637 +               log_error_write(srv, __FILE__, __LINE__, "s",
28638                                 "rrdtool.binary has to be set");
28639                 return HANDLER_ERROR;
28640         }
28641 -       
28642 +
28643         /* open the pipe to rrdtool */
28644         if (mod_rrd_create_pipe(srv, p)) {
28645                 return HANDLER_ERROR;
28646         }
28647 -       
28648 +
28649         p->rrdtool_running = 1;
28650 -               
28651 +
28652         return HANDLER_GO_ON;
28653  }
28654  
28655  TRIGGER_FUNC(mod_rrd_trigger) {
28656         plugin_data *p = p_d;
28657         size_t i;
28658 -       
28659 +
28660         if (!p->rrdtool_running) return HANDLER_GO_ON;
28661         if ((srv->cur_ts % 60) != 0) return HANDLER_GO_ON;
28662 -       
28663 +
28664         for (i = 0; i < srv->config_context->used; i++) {
28665                 plugin_config *s = p->config_storage[i];
28666                 int r;
28667 -               
28668 +
28669                 if (buffer_is_empty(s->path_rrd)) continue;
28670 -       
28671 +
28672                 /* write the data down every minute */
28673 -               
28674 +
28675                 if (HANDLER_GO_ON != mod_rrdtool_create_rrd(srv, p, s)) return HANDLER_ERROR;
28676 -               
28677 +
28678                 BUFFER_COPY_STRING_CONST(p->cmd, "update ");
28679                 buffer_append_string_buffer(p->cmd, s->path_rrd);
28680                 BUFFER_APPEND_STRING_CONST(p->cmd, " N:");
28681 @@ -381,69 +381,69 @@
28682                 BUFFER_APPEND_STRING_CONST(p->cmd, ":");
28683                 buffer_append_long(p->cmd, s->requests);
28684                 BUFFER_APPEND_STRING_CONST(p->cmd, "\n");
28685 -               
28686 +
28687                 if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
28688                         p->rrdtool_running = 0;
28689 -                       
28690 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
28691 +
28692 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
28693                                         "rrdtool-write: failed", strerror(errno));
28694 -                       
28695 +
28696                         return HANDLER_ERROR;
28697                 }
28698 -               
28699 +
28700                 buffer_prepare_copy(p->resp, 4096);
28701                 if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
28702                         p->rrdtool_running = 0;
28703 -                       
28704 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
28705 +
28706 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
28707                                         "rrdtool-read: failed", strerror(errno));
28708 -                       
28709 +
28710                         return HANDLER_ERROR;
28711                 }
28712 -               
28713 +
28714                 p->resp->used = r;
28715 -               
28716 +
28717                 if (p->resp->ptr[0] != 'O' ||
28718                     p->resp->ptr[1] != 'K') {
28719                         p->rrdtool_running = 0;
28720 -                       
28721 -                       log_error_write(srv, __FILE__, __LINE__, "sbb", 
28722 +
28723 +                       log_error_write(srv, __FILE__, __LINE__, "sbb",
28724                                         "rrdtool-response:", p->cmd, p->resp);
28725 -                       
28726 +
28727                         return HANDLER_ERROR;
28728                 }
28729                 s->requests = 0;
28730                 s->bytes_written = 0;
28731                 s->bytes_read = 0;
28732         }
28733 -       
28734 +
28735         return HANDLER_GO_ON;
28736  }
28737  
28738  REQUESTDONE_FUNC(mod_rrd_account) {
28739         plugin_data *p = p_d;
28740 -       
28741 +
28742         mod_rrd_patch_connection(srv, con, p);
28743 -       
28744 +
28745         *(p->conf.requests_ptr)      += 1;
28746         *(p->conf.bytes_written_ptr) += con->bytes_written;
28747         *(p->conf.bytes_read_ptr)    += con->bytes_read;
28748 -       
28749 +
28750         return HANDLER_GO_ON;
28751  }
28752  
28753  int mod_rrdtool_plugin_init(plugin *p) {
28754         p->version     = LIGHTTPD_VERSION_ID;
28755         p->name        = buffer_init_string("rrd");
28756 -       
28757 +
28758         p->init        = mod_rrd_init;
28759         p->cleanup     = mod_rrd_free;
28760         p->set_defaults= mod_rrd_set_defaults;
28761 -       
28762 +
28763         p->handle_trigger      = mod_rrd_trigger;
28764         p->handle_request_done = mod_rrd_account;
28765 -       
28766 +
28767         p->data        = NULL;
28768 -       
28769 +
28770         return 0;
28771  }
28772 --- lighttpd-1.4.11/src/mod_scgi.c      2006-03-04 17:15:26.000000000 +0200
28773 +++ lighttpd-1.4.12/src/mod_scgi.c      2006-07-11 22:07:51.000000000 +0300
28774 @@ -1,5 +1,4 @@
28775  #include <sys/types.h>
28776 -#include <unistd.h>
28777  #include <errno.h>
28778  #include <fcntl.h>
28779  #include <string.h>
28780 @@ -30,7 +29,9 @@
28781  #endif
28782  
28783  #include "sys-socket.h"
28784 -
28785 +#include "sys-files.h"
28786 +#include "sys-strings.h"
28787 +#include "sys-process.h"
28788  
28789  #ifndef UNIX_PATH_MAX
28790  # define UNIX_PATH_MAX 108
28791 @@ -46,30 +47,29 @@
28792  enum {EOL_UNSET, EOL_N, EOL_RN};
28793  
28794  /*
28795 - * 
28796 + *
28797   * TODO:
28798 - * 
28799 + *
28800   * - add timeout for a connect to a non-scgi process
28801   *   (use state_timestamp + state)
28802 - * 
28803 + *
28804   */
28805  
28806  typedef struct scgi_proc {
28807         size_t id; /* id will be between 1 and max_procs */
28808         buffer *socket; /* config.socket + "-" + id */
28809         unsigned port;  /* config.port + pno */
28810 -       
28811 -       pid_t pid;   /* PID of the spawned process (0 if not spawned locally) */
28812  
28813 +       pid_t pid;   /* PID of the spawned process (0 if not spawned locally) */
28814  
28815         size_t load; /* number of requests waiting on this process */
28816  
28817         time_t last_used; /* see idle_timeout */
28818         size_t requests;  /* see max_requests */
28819         struct scgi_proc *prev, *next; /* see first */
28820 -       
28821 +
28822         time_t disable_ts; /* replace by host->something */
28823 -       
28824 +
28825         int is_local;
28826  
28827         enum { PROC_STATE_UNSET,            /* init-phase */
28828 @@ -78,7 +78,7 @@
28829                         PROC_STATE_KILLED,  /* was killed as we don't have the load anymore */
28830                         PROC_STATE_DIED,    /* marked as dead, should be restarted */
28831                         PROC_STATE_DISABLED /* proc disabled as it resulted in an error */
28832 -       } state; 
28833 +       } state;
28834  } scgi_proc;
28835  
28836  typedef struct {
28837 @@ -86,20 +86,20 @@
28838          * sorted by lowest load
28839          *
28840          * whenever a job is done move it up in the list
28841 -        * until it is sorted, move it down as soon as the 
28842 +        * until it is sorted, move it down as soon as the
28843          * job is started
28844          */
28845 -       scgi_proc *first; 
28846 -       scgi_proc *unused_procs; 
28847 +       scgi_proc *first;
28848 +       scgi_proc *unused_procs;
28849  
28850 -       /* 
28851 +       /*
28852          * spawn at least min_procs, at max_procs.
28853          *
28854 -        * as soon as the load of the first entry 
28855 +        * as soon as the load of the first entry
28856          * is max_load_per_proc we spawn a new one
28857 -        * and add it to the first entry and give it 
28858 +        * and add it to the first entry and give it
28859          * the load
28860 -        * 
28861 +        *
28862          */
28863  
28864         unsigned short min_procs;
28865 @@ -111,44 +111,44 @@
28866  
28867         /*
28868          * kick the process from the list if it was not
28869 -        * used for idle_timeout until min_procs is 
28870 +        * used for idle_timeout until min_procs is
28871          * reached. this helps to get the processlist
28872          * small again we had a small peak load.
28873          *
28874          */
28875 -       
28876 +
28877         unsigned short idle_timeout;
28878 -       
28879 +
28880         /*
28881          * time after a disabled remote connection is tried to be re-enabled
28882 -        * 
28883 -        * 
28884 +        *
28885 +        *
28886          */
28887 -       
28888 +
28889         unsigned short disable_time;
28890  
28891         /*
28892          * same scgi processes get a little bit larger
28893 -        * than wanted. max_requests_per_proc kills a 
28894 +        * than wanted. max_requests_per_proc kills a
28895          * process after a number of handled requests.
28896          *
28897          */
28898         size_t max_requests_per_proc;
28899 -       
28900 +
28901  
28902         /* config */
28903  
28904 -       /* 
28905 -        * host:port 
28906 +       /*
28907 +        * host:port
28908          *
28909 -        * if host is one of the local IP adresses the 
28910 +        * if host is one of the local IP adresses the
28911          * whole connection is local
28912          *
28913          * if tcp/ip should be used host AND port have
28914 -        * to be specified 
28915 -        * 
28916 -        */ 
28917 -       buffer *host; 
28918 +        * to be specified
28919 +        *
28920 +        */
28921 +       buffer *host;
28922         unsigned short port;
28923  
28924         /*
28925 @@ -161,7 +161,7 @@
28926          */
28927         buffer *unixsocket;
28928  
28929 -       /* if socket is local we can start the scgi 
28930 +       /* if socket is local we can start the scgi
28931          * process ourself
28932          *
28933          * bin-path is the path to the binary
28934 @@ -169,19 +169,19 @@
28935          * check min_procs and max_procs for the number
28936          * of process to start-up
28937          */
28938 -       buffer *bin_path; 
28939 -       
28940 -       /* bin-path is set bin-environment is taken to 
28941 +       buffer *bin_path;
28942 +
28943 +       /* bin-path is set bin-environment is taken to
28944          * create the environement before starting the
28945          * FastCGI process
28946 -        * 
28947 +        *
28948          */
28949         array *bin_env;
28950 -       
28951 +
28952         array *bin_env_copy;
28953 -       
28954 +
28955         /*
28956 -        * docroot-translation between URL->phys and the 
28957 +        * docroot-translation between URL->phys and the
28958          * remote host
28959          *
28960          * reasons:
28961 @@ -192,7 +192,7 @@
28962         buffer *docroot;
28963  
28964         /*
28965 -        * check_local tell you if the phys file is stat()ed 
28966 +        * check_local tell you if the phys file is stat()ed
28967          * or not. FastCGI doesn't care if the service is
28968          * remote. If the web-server side doesn't contain
28969          * the scgi-files we should not stat() for them
28970 @@ -202,33 +202,33 @@
28971  
28972         /*
28973          * append PATH_INFO to SCRIPT_FILENAME
28974 -        * 
28975 +        *
28976          * php needs this if cgi.fix_pathinfo is provied
28977 -        * 
28978 +        *
28979          */
28980 -       
28981 +
28982         ssize_t load; /* replace by host->load */
28983  
28984         size_t max_id; /* corresponds most of the time to
28985         num_procs.
28986 -       
28987 +
28988         only if a process is killed max_id waits for the process itself
28989         to die and decrements its afterwards */
28990  } scgi_extension_host;
28991  
28992  /*
28993   * one extension can have multiple hosts assigned
28994 - * one host can spawn additional processes on the same 
28995 + * one host can spawn additional processes on the same
28996   *   socket (if we control it)
28997   *
28998   * ext -> host -> procs
28999   *    1:n     1:n
29000   *
29001 - * if the scgi process is remote that whole goes down 
29002 + * if the scgi process is remote that whole goes down
29003   * to
29004   *
29005   * ext -> host -> procs
29006 - *    1:n     1:1 
29007 + *    1:n     1:1
29008   *
29009   * in case of PHP and FCGI_CHILDREN we have again a procs
29010   * but we don't control it directly.
29011 @@ -239,7 +239,7 @@
29012         buffer *key; /* like .php */
29013  
29014         scgi_extension_host **hosts;
29015 -       
29016 +
29017         size_t used;
29018         size_t size;
29019  } scgi_extension;
29020 @@ -253,14 +253,14 @@
29021  
29022  
29023  typedef struct {
29024 -       scgi_exts *exts; 
29025 -       
29026 +       scgi_exts *exts;
29027 +
29028         int debug;
29029  } plugin_config;
29030  
29031  typedef struct {
29032         char **ptr;
29033 -       
29034 +
29035         size_t size;
29036         size_t used;
29037  } char_array;
29038 @@ -268,52 +268,51 @@
29039  /* generic plugin data, shared between all connections */
29040  typedef struct {
29041         PLUGIN_DATA;
29042 -       
29043 +
29044         buffer *scgi_env;
29045 -       
29046 +
29047         buffer *path;
29048         buffer *parse_response;
29049 -       
29050 +
29051         plugin_config **config_storage;
29052 -       
29053 +
29054         plugin_config conf; /* this is only used as long as no handler_ctx is setup */
29055  } plugin_data;
29056  
29057  /* connection specific data */
29058 -typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE, 
29059 -               FCGI_STATE_WRITE, FCGI_STATE_READ 
29060 +typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE,
29061 +               FCGI_STATE_WRITE, FCGI_STATE_READ
29062  } scgi_connection_state_t;
29063  
29064  typedef struct {
29065 -       buffer  *response; 
29066 +       buffer  *response;
29067         size_t   response_len;
29068         int      response_type;
29069         int      response_padding;
29070 -       
29071 +
29072         scgi_proc *proc;
29073         scgi_extension_host *host;
29074 -       
29075 +
29076         scgi_connection_state_t state;
29077         time_t   state_timestamp;
29078 -       
29079 +
29080         int      reconnects; /* number of reconnect attempts */
29081 -       
29082 +
29083         read_buffer *rb;
29084         chunkqueue *wb;
29085 -       
29086 +
29087         buffer   *response_header;
29088 -       
29089 +
29090         int       delayed;   /* flag to mark that the connect() is delayed */
29091 -       
29092 +
29093         size_t    request_id;
29094         int       fd;        /* fd to the scgi process */
29095         int       fde_ndx;   /* index into the fd-event buffer */
29096 -
29097         pid_t     pid;
29098         int       got_proc;
29099 -       
29100 +
29101         plugin_config conf;
29102 -       
29103 +
29104         connection *remote_conn;  /* dumb pointer */
29105         plugin_data *plugin_data; /* dumb pointer */
29106  } handler_ctx;
29107 @@ -328,28 +327,28 @@
29108  
29109  static handler_ctx * handler_ctx_init() {
29110         handler_ctx * hctx;
29111 -       
29112 +
29113         hctx = calloc(1, sizeof(*hctx));
29114         assert(hctx);
29115 -       
29116 +
29117         hctx->fde_ndx = -1;
29118 -       
29119 +
29120         hctx->response = buffer_init();
29121         hctx->response_header = buffer_init();
29122 -       
29123 +
29124         hctx->request_id = 0;
29125         hctx->state = FCGI_STATE_INIT;
29126         hctx->proc = NULL;
29127 -       
29128 +
29129         hctx->response_len = 0;
29130         hctx->response_type = 0;
29131         hctx->response_padding = 0;
29132         hctx->fd = -1;
29133 -       
29134 +
29135         hctx->reconnects = 0;
29136  
29137         hctx->wb = chunkqueue_init();
29138 -       
29139 +
29140         return hctx;
29141  }
29142  
29143 @@ -358,12 +357,12 @@
29144         buffer_free(hctx->response_header);
29145  
29146         chunkqueue_free(hctx->wb);
29147 -       
29148 +
29149         if (hctx->rb) {
29150                 if (hctx->rb->ptr) free(hctx->rb->ptr);
29151                 free(hctx->rb);
29152         }
29153 -       
29154 +
29155         free(hctx);
29156  }
29157  
29158 @@ -372,20 +371,20 @@
29159  
29160         f = calloc(1, sizeof(*f));
29161         f->socket = buffer_init();
29162 -       
29163 +
29164         f->prev = NULL;
29165         f->next = NULL;
29166 -       
29167 +
29168         return f;
29169  }
29170  
29171  void scgi_process_free(scgi_proc *f) {
29172         if (!f) return;
29173 -       
29174 +
29175         scgi_process_free(f->next);
29176 -       
29177 +
29178         buffer_free(f->socket);
29179 -       
29180 +
29181         free(f);
29182  }
29183  
29184 @@ -400,62 +399,62 @@
29185         f->bin_path = buffer_init();
29186         f->bin_env = array_init();
29187         f->bin_env_copy = array_init();
29188 -       
29189 +
29190         return f;
29191  }
29192  
29193  void scgi_host_free(scgi_extension_host *h) {
29194         if (!h) return;
29195 -       
29196 +
29197         buffer_free(h->host);
29198         buffer_free(h->unixsocket);
29199         buffer_free(h->docroot);
29200         buffer_free(h->bin_path);
29201         array_free(h->bin_env);
29202         array_free(h->bin_env_copy);
29203 -       
29204 +
29205         scgi_process_free(h->first);
29206         scgi_process_free(h->unused_procs);
29207 -       
29208 +
29209         free(h);
29210 -       
29211 +
29212  }
29213  
29214  scgi_exts *scgi_extensions_init() {
29215         scgi_exts *f;
29216  
29217         f = calloc(1, sizeof(*f));
29218 -       
29219 +
29220         return f;
29221  }
29222  
29223  void scgi_extensions_free(scgi_exts *f) {
29224         size_t i;
29225 -       
29226 +
29227         if (!f) return;
29228 -       
29229 +
29230         for (i = 0; i < f->used; i++) {
29231                 scgi_extension *fe;
29232                 size_t j;
29233 -               
29234 +
29235                 fe = f->exts[i];
29236 -               
29237 +
29238                 for (j = 0; j < fe->used; j++) {
29239                         scgi_extension_host *h;
29240 -                       
29241 +
29242                         h = fe->hosts[j];
29243 -                       
29244 +
29245                         scgi_host_free(h);
29246                 }
29247 -               
29248 +
29249                 buffer_free(fe->key);
29250                 free(fe->hosts);
29251 -               
29252 +
29253                 free(fe);
29254         }
29255 -       
29256 +
29257         free(f->exts);
29258 -       
29259 +
29260         free(f);
29261  }
29262  
29263 @@ -504,99 +503,103 @@
29264                 assert(fe->hosts);
29265         }
29266  
29267 -       fe->hosts[fe->used++] = fh; 
29268 +       fe->hosts[fe->used++] = fh;
29269  
29270         return 0;
29271 -       
29272 +
29273  }
29274  
29275  INIT_FUNC(mod_scgi_init) {
29276         plugin_data *p;
29277 -       
29278 +
29279         p = calloc(1, sizeof(*p));
29280 -       
29281 +
29282         p->scgi_env = buffer_init();
29283 -       
29284 +
29285         p->path = buffer_init();
29286         p->parse_response = buffer_init();
29287 -       
29288 +
29289         return p;
29290  }
29291  
29292  
29293  FREE_FUNC(mod_scgi_free) {
29294         plugin_data *p = p_d;
29295 -       
29296 +
29297         UNUSED(srv);
29298  
29299         buffer_free(p->scgi_env);
29300         buffer_free(p->path);
29301         buffer_free(p->parse_response);
29302 -       
29303 +
29304         if (p->config_storage) {
29305                 size_t i, j, n;
29306                 for (i = 0; i < srv->config_context->used; i++) {
29307                         plugin_config *s = p->config_storage[i];
29308                         scgi_exts *exts;
29309 -                       
29310 +
29311                         if (!s) continue;
29312 -                       
29313 +
29314                         exts = s->exts;
29315  
29316                         for (j = 0; j < exts->used; j++) {
29317                                 scgi_extension *ex;
29318 -                               
29319 +
29320                                 ex = exts->exts[j];
29321 -                               
29322 +
29323                                 for (n = 0; n < ex->used; n++) {
29324                                         scgi_proc *proc;
29325                                         scgi_extension_host *host;
29326 -                                       
29327 +
29328                                         host = ex->hosts[n];
29329 -                                       
29330 +
29331                                         for (proc = host->first; proc; proc = proc->next) {
29332 +#ifndef _WIN32
29333                                                 if (proc->pid != 0) kill(proc->pid, SIGTERM);
29334 -                                               
29335 -                                               if (proc->is_local && 
29336 +#endif
29337 +
29338 +                                               if (proc->is_local &&
29339                                                     !buffer_is_empty(proc->socket)) {
29340                                                         unlink(proc->socket->ptr);
29341                                                 }
29342                                         }
29343 -                                       
29344 +
29345                                         for (proc = host->unused_procs; proc; proc = proc->next) {
29346 +#ifndef _WIN32
29347                                                 if (proc->pid != 0) kill(proc->pid, SIGTERM);
29348 -                                               
29349 -                                               if (proc->is_local && 
29350 +#endif
29351 +
29352 +                                               if (proc->is_local &&
29353                                                     !buffer_is_empty(proc->socket)) {
29354                                                         unlink(proc->socket->ptr);
29355                                                 }
29356                                         }
29357                                 }
29358                         }
29359 -                       
29360 +
29361                         scgi_extensions_free(s->exts);
29362 -                       
29363 +
29364                         free(s);
29365                 }
29366                 free(p->config_storage);
29367         }
29368 -       
29369 +
29370         free(p);
29371 -       
29372 +
29373         return HANDLER_GO_ON;
29374  }
29375  
29376  static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
29377         char *dst;
29378 -       
29379 +
29380         if (!key || !val) return -1;
29381 -       
29382 +
29383         dst = malloc(key_len + val_len + 3);
29384         memcpy(dst, key, key_len);
29385         dst[key_len] = '=';
29386         /* add the \0 from the value */
29387         memcpy(dst + key_len + 1, val, val_len + 1);
29388 -       
29389 +
29390         if (env->size == 0) {
29391                 env->size = 16;
29392                 env->ptr = malloc(env->size * sizeof(*env->ptr));
29393 @@ -604,13 +607,13 @@
29394                 env->size += 16;
29395                 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
29396         }
29397 -       
29398 +
29399         env->ptr[env->used++] = dst;
29400 -       
29401 +
29402         return 0;
29403  }
29404  
29405 -static int scgi_spawn_connection(server *srv, 
29406 +static int scgi_spawn_connection(server *srv,
29407                                  plugin_data *p,
29408                                  scgi_extension_host *host,
29409                                  scgi_proc *proc) {
29410 @@ -622,31 +625,27 @@
29411  #endif
29412         struct sockaddr_in scgi_addr_in;
29413         struct sockaddr *scgi_addr;
29414 -       
29415 +
29416         socklen_t servlen;
29417 -       
29418 +
29419  #ifndef HAVE_FORK
29420         return -1;
29421  #endif
29422 -       
29423 +
29424         if (p->conf.debug) {
29425                 log_error_write(srv, __FILE__, __LINE__, "sdb",
29426                                 "new proc, socket:", proc->port, proc->socket);
29427         }
29428 -               
29429 +
29430         if (!buffer_is_empty(proc->socket)) {
29431                 memset(&scgi_addr, 0, sizeof(scgi_addr));
29432 -               
29433 +
29434  #ifdef HAVE_SYS_UN_H
29435                 scgi_addr_un.sun_family = AF_UNIX;
29436                 strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
29437 -               
29438 -#ifdef SUN_LEN
29439 +
29440                 servlen = SUN_LEN(&scgi_addr_un);
29441 -#else
29442 -               /* stevens says: */
29443 -               servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
29444 -#endif
29445 +
29446                 socket_type = AF_UNIX;
29447                 scgi_addr = (struct sockaddr *) &scgi_addr_un;
29448  #else
29449 @@ -656,115 +655,115 @@
29450  #endif
29451         } else {
29452                 scgi_addr_in.sin_family = AF_INET;
29453 -               
29454 +
29455                 if (buffer_is_empty(host->host)) {
29456                         scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
29457                 } else {
29458                         struct hostent *he;
29459 -                       
29460 +
29461                         /* set a usefull default */
29462                         scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
29463 -                       
29464 -                       
29465 +
29466 +
29467                         if (NULL == (he = gethostbyname(host->host->ptr))) {
29468 -                               log_error_write(srv, __FILE__, __LINE__, 
29469 -                                               "sdb", "gethostbyname failed: ", 
29470 +                               log_error_write(srv, __FILE__, __LINE__,
29471 +                                               "sdb", "gethostbyname failed: ",
29472                                                 h_errno, host->host);
29473                                 return -1;
29474                         }
29475 -                       
29476 +
29477                         if (he->h_addrtype != AF_INET) {
29478                                 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
29479                                 return -1;
29480                         }
29481 -                       
29482 +
29483                         if (he->h_length != sizeof(struct in_addr)) {
29484                                 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
29485                                 return -1;
29486                         }
29487 -                       
29488 +
29489                         memcpy(&(scgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
29490 -                       
29491 +
29492                 }
29493                 scgi_addr_in.sin_port = htons(proc->port);
29494                 servlen = sizeof(scgi_addr_in);
29495 -               
29496 +
29497                 socket_type = AF_INET;
29498                 scgi_addr = (struct sockaddr *) &scgi_addr_in;
29499         }
29500 -       
29501 +
29502         if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
29503 -               log_error_write(srv, __FILE__, __LINE__, "ss", 
29504 +               log_error_write(srv, __FILE__, __LINE__, "ss",
29505                                 "failed:", strerror(errno));
29506                 return -1;
29507         }
29508 -       
29509 +
29510         if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
29511                 /* server is not up, spawn in  */
29512                 pid_t child;
29513                 int val;
29514 -               
29515 +
29516                 if (!buffer_is_empty(proc->socket)) {
29517                         unlink(proc->socket->ptr);
29518                 }
29519 -               
29520 +
29521                 close(scgi_fd);
29522 -               
29523 +
29524                 /* reopen socket */
29525                 if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
29526 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
29527 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
29528                                 "socket failed:", strerror(errno));
29529                         return -1;
29530                 }
29531 -               
29532 +
29533                 val = 1;
29534                 if (setsockopt(scgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
29535 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
29536 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
29537                                         "socketsockopt failed:", strerror(errno));
29538                         return -1;
29539                 }
29540 -               
29541 +
29542                 /* create socket */
29543                 if (-1 == bind(scgi_fd, scgi_addr, servlen)) {
29544 -                       log_error_write(srv, __FILE__, __LINE__, "sbds", 
29545 -                               "bind failed for:", 
29546 -                               proc->socket, 
29547 -                               proc->port, 
29548 +                       log_error_write(srv, __FILE__, __LINE__, "sbds",
29549 +                               "bind failed for:",
29550 +                               proc->socket,
29551 +                               proc->port,
29552                                 strerror(errno));
29553                         return -1;
29554                 }
29555 -               
29556 +
29557                 if (-1 == listen(scgi_fd, 1024)) {
29558 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
29559 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
29560                                 "listen failed:", strerror(errno));
29561                         return -1;
29562                 }
29563 -               
29564 -#ifdef HAVE_FORK       
29565 +
29566 +#ifdef HAVE_FORK
29567                 switch ((child = fork())) {
29568                 case 0: {
29569                         buffer *b;
29570                         size_t i = 0;
29571                         int fd = 0;
29572                         char_array env;
29573 -                       
29574 -                       
29575 +
29576 +
29577                         /* create environment */
29578                         env.ptr = NULL;
29579                         env.size = 0;
29580                         env.used = 0;
29581 -                       
29582 +
29583                         /* we don't need the client socket */
29584                         for (fd = 3; fd < 256; fd++) {
29585                                 if (fd != 2 && fd != scgi_fd) close(fd);
29586                         }
29587 -                       
29588 +
29589                         /* build clean environment */
29590                         if (host->bin_env_copy->used) {
29591                                 for (i = 0; i < host->bin_env_copy->used; i++) {
29592                                         data_string *ds = (data_string *)host->bin_env_copy->data[i];
29593                                         char *ge;
29594 -                                       
29595 +
29596                                         if (NULL != (ge = getenv(ds->value->ptr))) {
29597                                                 env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
29598                                         }
29599 @@ -772,44 +771,44 @@
29600                         } else {
29601                                 for (i = 0; environ[i]; i++) {
29602                                         char *eq;
29603 -                                       
29604 +
29605                                         if (NULL != (eq = strchr(environ[i], '='))) {
29606                                                 env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
29607                                         }
29608                                 }
29609                         }
29610 -                       
29611 +
29612                         /* create environment */
29613                         for (i = 0; i < host->bin_env->used; i++) {
29614                                 data_string *ds = (data_string *)host->bin_env->data[i];
29615 -                               
29616 +
29617                                 env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
29618                         }
29619 -                       
29620 +
29621                         for (i = 0; i < env.used; i++) {
29622                                 /* search for PHP_FCGI_CHILDREN */
29623                                 if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
29624                         }
29625 -                       
29626 +
29627                         /* not found, add a default */
29628                         if (i == env.used) {
29629                                 env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
29630                         }
29631 -                       
29632 +
29633                         env.ptr[env.used] = NULL;
29634 -                       
29635 +
29636                         b = buffer_init();
29637                         buffer_copy_string(b, "exec ");
29638                         buffer_append_string_buffer(b, host->bin_path);
29639 -                       
29640 +
29641                         /* exec the cgi */
29642                         execle("/bin/sh", "sh", "-c", b->ptr, NULL, env.ptr);
29643 -                       
29644 -                       log_error_write(srv, __FILE__, __LINE__, "sbs", 
29645 +
29646 +                       log_error_write(srv, __FILE__, __LINE__, "sbs",
29647                                         "execl failed for:", host->bin_path, strerror(errno));
29648 -                       
29649 +
29650                         exit(errno);
29651 -                       
29652 +
29653                         break;
29654                 }
29655                 case -1:
29656 @@ -817,32 +816,32 @@
29657                         break;
29658                 default:
29659                         /* father */
29660 -                       
29661 +
29662                         /* wait */
29663                         select(0, NULL, NULL, NULL, &tv);
29664 -                       
29665 +
29666                         switch (waitpid(child, &status, WNOHANG)) {
29667                         case 0:
29668                                 /* child still running after timeout, good */
29669                                 break;
29670                         case -1:
29671                                 /* no PID found ? should never happen */
29672 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
29673 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
29674                                                 "pid not found:", strerror(errno));
29675                                 return -1;
29676                         default:
29677                                 /* the child should not terminate at all */
29678                                 if (WIFEXITED(status)) {
29679 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
29680 -                                                       "child exited (is this a SCGI binary ?):", 
29681 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
29682 +                                                       "child exited (is this a SCGI binary ?):",
29683                                                         WEXITSTATUS(status));
29684                                 } else if (WIFSIGNALED(status)) {
29685 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
29686 -                                                       "child signaled:", 
29687 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
29688 +                                                       "child signaled:",
29689                                                         WTERMSIG(status));
29690                                 } else {
29691 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
29692 -                                                       "child died somehow:", 
29693 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
29694 +                                                       "child died somehow:",
29695                                                         status);
29696                                 }
29697                                 return -1;
29698 @@ -852,26 +851,26 @@
29699                         proc->pid = child;
29700                         proc->last_used = srv->cur_ts;
29701                         proc->is_local = 1;
29702 -                                               
29703 +
29704                         break;
29705                 }
29706  #endif
29707         } else {
29708                 proc->is_local = 0;
29709                 proc->pid = 0;
29710 -               
29711 +
29712                 if (p->conf.debug) {
29713                         log_error_write(srv, __FILE__, __LINE__, "sb",
29714                                         "(debug) socket is already used, won't spawn:",
29715                                         proc->socket);
29716                 }
29717         }
29718 -       
29719 +
29720         proc->state = PROC_STATE_RUNNING;
29721         host->active_procs++;
29722 -       
29723 +
29724         close(scgi_fd);
29725 -       
29726 +
29727         return 0;
29728  }
29729  
29730 @@ -880,89 +879,89 @@
29731         plugin_data *p = p_d;
29732         data_unset *du;
29733         size_t i = 0;
29734 -       
29735 -       config_values_t cv[] = { 
29736 +
29737 +       config_values_t cv[] = {
29738                 { "scgi.server",              NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
29739                 { "scgi.debug",               NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
29740                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
29741         };
29742 -       
29743 +
29744         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
29745 -       
29746 +
29747         for (i = 0; i < srv->config_context->used; i++) {
29748                 plugin_config *s;
29749                 array *ca;
29750 -               
29751 +
29752                 s = malloc(sizeof(plugin_config));
29753                 s->exts          = scgi_extensions_init();
29754                 s->debug         = 0;
29755 -               
29756 +
29757                 cv[0].destination = s->exts;
29758                 cv[1].destination = &(s->debug);
29759 -               
29760 +
29761                 p->config_storage[i] = s;
29762                 ca = ((data_config *)srv->config_context->data[i])->value;
29763 -       
29764 +
29765                 if (0 != config_insert_values_global(srv, ca, cv)) {
29766                         return HANDLER_ERROR;
29767                 }
29768 -               
29769 -               /* 
29770 +
29771 +               /*
29772                  * <key> = ( ... )
29773                  */
29774 -               
29775 +
29776                 if (NULL != (du = array_get_element(ca, "scgi.server"))) {
29777                         size_t j;
29778                         data_array *da = (data_array *)du;
29779 -                       
29780 +
29781                         if (du->type != TYPE_ARRAY) {
29782 -                               log_error_write(srv, __FILE__, __LINE__, "sss", 
29783 +                               log_error_write(srv, __FILE__, __LINE__, "sss",
29784                                                 "unexpected type for key: ", "scgi.server", "array of strings");
29785 -                               
29786 +
29787                                 return HANDLER_ERROR;
29788                         }
29789 -                       
29790 -                       
29791 -                       /* 
29792 -                        * scgi.server = ( "<ext>" => ( ... ), 
29793 +
29794 +
29795 +                       /*
29796 +                        * scgi.server = ( "<ext>" => ( ... ),
29797                          *                    "<ext>" => ( ... ) )
29798                          */
29799 -                       
29800 +
29801                         for (j = 0; j < da->value->used; j++) {
29802                                 size_t n;
29803                                 data_array *da_ext = (data_array *)da->value->data[j];
29804 -                               
29805 +
29806                                 if (da->value->data[j]->type != TYPE_ARRAY) {
29807 -                                       log_error_write(srv, __FILE__, __LINE__, "sssbs", 
29808 -                                                       "unexpected type for key: ", "scgi.server", 
29809 +                                       log_error_write(srv, __FILE__, __LINE__, "sssbs",
29810 +                                                       "unexpected type for key: ", "scgi.server",
29811                                                         "[", da->value->data[j]->key, "](string)");
29812 -                                       
29813 +
29814                                         return HANDLER_ERROR;
29815                                 }
29816 -                               
29817 -                               /* 
29818 -                                * da_ext->key == name of the extension 
29819 +
29820 +                               /*
29821 +                                * da_ext->key == name of the extension
29822                                  */
29823 -                               
29824 -                               /* 
29825 -                                * scgi.server = ( "<ext>" => 
29826 -                                *                     ( "<host>" => ( ... ), 
29827 +
29828 +                               /*
29829 +                                * scgi.server = ( "<ext>" =>
29830 +                                *                     ( "<host>" => ( ... ),
29831                                  *                       "<host>" => ( ... )
29832 -                                *                     ), 
29833 +                                *                     ),
29834                                  *                    "<ext>" => ... )
29835                                  */
29836 -                                       
29837 +
29838                                 for (n = 0; n < da_ext->value->used; n++) {
29839                                         data_array *da_host = (data_array *)da_ext->value->data[n];
29840 -                                       
29841 +
29842                                         scgi_extension_host *df;
29843 -                                       
29844 -                                       config_values_t fcv[] = { 
29845 +
29846 +                                       config_values_t fcv[] = {
29847                                                 { "host",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
29848                                                 { "docroot",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
29849                                                 { "socket",            NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
29850                                                 { "bin-path",          NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 3 */
29851 -                                               
29852 +
29853                                                 { "check-local",       NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },      /* 4 */
29854                                                 { "port",              NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 5 */
29855                                                 { "min-procs-not-working",         NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 7 this is broken for now */
29856 @@ -970,37 +969,37 @@
29857                                                 { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 8 */
29858                                                 { "idle-timeout",      NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 9 */
29859                                                 { "disable-time",      NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 10 */
29860 -                                               
29861 +
29862                                                 { "bin-environment",   NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },        /* 11 */
29863                                                 { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },     /* 12 */
29864 -                                               
29865 -                                               
29866 +
29867 +
29868                                                 { NULL,                NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
29869                                         };
29870 -                                       
29871 +
29872                                         if (da_host->type != TYPE_ARRAY) {
29873 -                                               log_error_write(srv, __FILE__, __LINE__, "ssSBS", 
29874 -                                                               "unexpected type for key:", 
29875 -                                                               "scgi.server", 
29876 +                                               log_error_write(srv, __FILE__, __LINE__, "ssSBS",
29877 +                                                               "unexpected type for key:",
29878 +                                                               "scgi.server",
29879                                                                 "[", da_host->key, "](string)");
29880 -                                               
29881 +
29882                                                 return HANDLER_ERROR;
29883                                         }
29884 -                                       
29885 +
29886                                         df = scgi_host_init();
29887 -                                       
29888 +
29889                                         df->check_local  = 1;
29890                                         df->min_procs    = 4;
29891                                         df->max_procs    = 4;
29892                                         df->max_load_per_proc = 1;
29893                                         df->idle_timeout = 60;
29894                                         df->disable_time = 60;
29895 -                                       
29896 +
29897                                         fcv[0].destination = df->host;
29898                                         fcv[1].destination = df->docroot;
29899                                         fcv[2].destination = df->unixsocket;
29900                                         fcv[3].destination = df->bin_path;
29901 -                                       
29902 +
29903                                         fcv[4].destination = &(df->check_local);
29904                                         fcv[5].destination = &(df->port);
29905                                         fcv[6].destination = &(df->min_procs);
29906 @@ -1008,47 +1007,47 @@
29907                                         fcv[8].destination = &(df->max_load_per_proc);
29908                                         fcv[9].destination = &(df->idle_timeout);
29909                                         fcv[10].destination = &(df->disable_time);
29910 -                                       
29911 +
29912                                         fcv[11].destination = df->bin_env;
29913                                         fcv[12].destination = df->bin_env_copy;
29914 -                                       
29915 -                                       
29916 +
29917 +
29918                                         if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
29919                                                 return HANDLER_ERROR;
29920                                         }
29921 -                                                       
29922 -                                       if ((!buffer_is_empty(df->host) || df->port) && 
29923 +
29924 +                                       if ((!buffer_is_empty(df->host) || df->port) &&
29925                                             !buffer_is_empty(df->unixsocket)) {
29926 -                                               log_error_write(srv, __FILE__, __LINE__, "s", 
29927 +                                               log_error_write(srv, __FILE__, __LINE__, "s",
29928                                                                 "either host+port or socket");
29929 -                                               
29930 +
29931                                                 return HANDLER_ERROR;
29932                                         }
29933 -                                       
29934 +
29935                                         if (!buffer_is_empty(df->unixsocket)) {
29936                                                 /* unix domain socket */
29937 -                                               
29938 +
29939                                                 if (df->unixsocket->used > UNIX_PATH_MAX - 2) {
29940 -                                                       log_error_write(srv, __FILE__, __LINE__, "s", 
29941 +                                                       log_error_write(srv, __FILE__, __LINE__, "s",
29942                                                                         "path of the unixdomain socket is too large");
29943                                                         return HANDLER_ERROR;
29944                                                 }
29945                                         } else {
29946                                                 /* tcp/ip */
29947 -                                               
29948 -                                               if (buffer_is_empty(df->host) && 
29949 +
29950 +                                               if (buffer_is_empty(df->host) &&
29951                                                     buffer_is_empty(df->bin_path)) {
29952 -                                                       log_error_write(srv, __FILE__, __LINE__, "sbbbs", 
29953 -                                                                       "missing key (string):", 
29954 +                                                       log_error_write(srv, __FILE__, __LINE__, "sbbbs",
29955 +                                                                       "missing key (string):",
29956                                                                         da->key,
29957                                                                         da_ext->key,
29958                                                                         da_host->key,
29959                                                                         "host");
29960 -                                                       
29961 +
29962                                                         return HANDLER_ERROR;
29963                                                 } else if (df->port == 0) {
29964 -                                                       log_error_write(srv, __FILE__, __LINE__, "sbbbs", 
29965 -                                                                       "missing key (short):", 
29966 +                                                       log_error_write(srv, __FILE__, __LINE__, "sbbbs",
29967 +                                                                       "missing key (short):",
29968                                                                         da->key,
29969                                                                         da_ext->key,
29970                                                                         da_host->key,
29971 @@ -1056,14 +1055,14 @@
29972                                                         return HANDLER_ERROR;
29973                                                 }
29974                                         }
29975 -                                               
29976 -                                       if (!buffer_is_empty(df->bin_path)) { 
29977 +
29978 +                                       if (!buffer_is_empty(df->bin_path)) {
29979                                                 /* a local socket + self spawning */
29980                                                 size_t pno;
29981 -                                               
29982 +
29983                                                 if (df->min_procs > df->max_procs) df->max_procs = df->min_procs;
29984                                                 if (df->max_load_per_proc < 1) df->max_load_per_proc = 0;
29985 -                                               
29986 +
29987                                                 if (s->debug) {
29988                                                         log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd",
29989                                                                         "--- scgi spawning local",
29990 @@ -1073,7 +1072,7 @@
29991                                                                         "\n\tmin-procs:", df->min_procs,
29992                                                                         "\n\tmax-procs:", df->max_procs);
29993                                                 }
29994 -                                               
29995 +
29996                                                 for (pno = 0; pno < df->min_procs; pno++) {
29997                                                         scgi_proc *proc;
29998  
29999 @@ -1088,7 +1087,7 @@
30000                                                                 buffer_append_string(proc->socket, "-");
30001                                                                 buffer_append_long(proc->socket, pno);
30002                                                         }
30003 -                                                       
30004 +
30005                                                         if (s->debug) {
30006                                                                 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
30007                                                                                 "--- scgi spawning",
30008 @@ -1096,53 +1095,53 @@
30009                                                                                 "\n\tsocket", df->unixsocket,
30010                                                                                 "\n\tcurrent:", pno, "/", df->min_procs);
30011                                                         }
30012 -                                                       
30013 +
30014                                                         if (scgi_spawn_connection(srv, p, df, proc)) {
30015                                                                 log_error_write(srv, __FILE__, __LINE__, "s",
30016                                                                                 "[ERROR]: spawning fcgi failed.");
30017                                                                 return HANDLER_ERROR;
30018                                                         }
30019 -                                                       
30020 +
30021                                                         proc->next = df->first;
30022                                                         if (df->first)  df->first->prev = proc;
30023 -                                                       
30024 +
30025                                                         df->first = proc;
30026                                                 }
30027                                         } else {
30028                                                 scgi_proc *fp;
30029 -                                               
30030 +
30031                                                 fp = scgi_process_init();
30032                                                 fp->id = df->num_procs++;
30033                                                 df->max_id++;
30034                                                 df->active_procs++;
30035                                                 fp->state = PROC_STATE_RUNNING;
30036 -                                               
30037 +
30038                                                 if (buffer_is_empty(df->unixsocket)) {
30039                                                         fp->port = df->port;
30040                                                 } else {
30041                                                         buffer_copy_string_buffer(fp->socket, df->unixsocket);
30042                                                 }
30043 -                                               
30044 +
30045                                                 df->first = fp;
30046 -                                               
30047 +
30048                                                 df->min_procs = 1;
30049                                                 df->max_procs = 1;
30050                                         }
30051 -                                       
30052 +
30053                                         /* if extension already exists, take it */
30054                                         scgi_extension_insert(s->exts, da_ext->key, df);
30055                                 }
30056                         }
30057                 }
30058         }
30059 -       
30060 +
30061         return HANDLER_GO_ON;
30062  }
30063  
30064  static int scgi_set_state(server *srv, handler_ctx *hctx, scgi_connection_state_t state) {
30065         hctx->state = state;
30066         hctx->state_timestamp = srv->cur_ts;
30067 -       
30068 +
30069         return 0;
30070  }
30071  
30072 @@ -1150,34 +1149,34 @@
30073  void scgi_connection_cleanup(server *srv, handler_ctx *hctx) {
30074         plugin_data *p;
30075         connection  *con;
30076 -       
30077 +
30078         if (NULL == hctx) return;
30079 -       
30080 +
30081         p    = hctx->plugin_data;
30082         con  = hctx->remote_conn;
30083 -       
30084 +
30085         if (con->mode != p->id) {
30086                 WP();
30087                 return;
30088         }
30089 -       
30090 +
30091         if (hctx->fd != -1) {
30092                 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
30093                 fdevent_unregister(srv->ev, hctx->fd);
30094                 close(hctx->fd);
30095                 srv->cur_fds--;
30096         }
30097 -       
30098 +
30099         if (hctx->host && hctx->proc) {
30100                 hctx->host->load--;
30101 -               
30102 +
30103                 if (hctx->got_proc) {
30104                         /* after the connect the process gets a load */
30105                         hctx->proc->load--;
30106 -                       
30107 +
30108                         if (p->conf.debug) {
30109                                 log_error_write(srv, __FILE__, __LINE__, "sddb",
30110 -                                               "release proc:", 
30111 +                                               "release proc:",
30112                                                 hctx->fd,
30113                                                 hctx->proc->pid, hctx->proc->socket);
30114                         }
30115 @@ -1186,87 +1185,87 @@
30116                 scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
30117         }
30118  
30119 -       
30120 +
30121         handler_ctx_free(hctx);
30122 -       con->plugin_ctx[p->id] = NULL;  
30123 +       con->plugin_ctx[p->id] = NULL;
30124  }
30125  
30126  static int scgi_reconnect(server *srv, handler_ctx *hctx) {
30127         plugin_data *p    = hctx->plugin_data;
30128 -       
30129 -       /* child died 
30130 -        * 
30131 -        * 1. 
30132 -        * 
30133 +
30134 +       /* child died
30135 +        *
30136 +        * 1.
30137 +        *
30138          * connect was ok, connection was accepted
30139          * but the php accept loop checks after the accept if it should die or not.
30140 -        * 
30141 -        * if yes we can only detect it at a write() 
30142 -        * 
30143 +        *
30144 +        * if yes we can only detect it at a write()
30145 +        *
30146          * next step is resetting this attemp and setup a connection again
30147 -        * 
30148 +        *
30149          * if we have more then 5 reconnects for the same request, die
30150 -        * 
30151 -        * 2. 
30152 -        * 
30153 +        *
30154 +        * 2.
30155 +        *
30156          * we have a connection but the child died by some other reason
30157 -        * 
30158 +        *
30159          */
30160 -       
30161 +
30162         fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
30163         fdevent_unregister(srv->ev, hctx->fd);
30164         close(hctx->fd);
30165         srv->cur_fds--;
30166 -       
30167 +
30168         scgi_set_state(srv, hctx, FCGI_STATE_INIT);
30169 -       
30170 +
30171         hctx->request_id = 0;
30172         hctx->reconnects++;
30173 -       
30174 +
30175         if (p->conf.debug) {
30176                 log_error_write(srv, __FILE__, __LINE__, "sddb",
30177 -                               "release proc:", 
30178 +                               "release proc:",
30179                                 hctx->fd,
30180                                 hctx->proc->pid, hctx->proc->socket);
30181         }
30182 -       
30183 +
30184         hctx->proc->load--;
30185         scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
30186 -       
30187 +
30188         return 0;
30189  }
30190  
30191  
30192  static handler_t scgi_connection_reset(server *srv, connection *con, void *p_d) {
30193         plugin_data *p = p_d;
30194 -       
30195 +
30196         scgi_connection_cleanup(srv, con->plugin_ctx[p->id]);
30197 -       
30198 +
30199         return HANDLER_GO_ON;
30200  }
30201  
30202  
30203  static int scgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
30204         size_t len;
30205 -       
30206 +
30207         if (!key || !val) return -1;
30208 -       
30209 +
30210         len = key_len + val_len + 2;
30211 -       
30212 +
30213         buffer_prepare_append(env, len);
30214  
30215 -       /* include the NUL */   
30216 +       /* include the NUL */
30217         memcpy(env->ptr + env->used, key, key_len + 1);
30218         env->used += key_len + 1;
30219         memcpy(env->ptr + env->used, val, val_len + 1);
30220         env->used += val_len + 1;
30221 -       
30222 +
30223         return 0;
30224  }
30225  
30226  
30227  /**
30228 - * 
30229 + *
30230   * returns
30231   *   -1 error
30232   *    0 connected
30233 @@ -1280,24 +1279,21 @@
30234         struct sockaddr_un scgi_addr_un;
30235  #endif
30236         socklen_t servlen;
30237 -       
30238 +
30239         scgi_extension_host *host = hctx->host;
30240         scgi_proc *proc   = hctx->proc;
30241         int scgi_fd       = hctx->fd;
30242 -       
30243 +
30244         memset(&scgi_addr, 0, sizeof(scgi_addr));
30245 -       
30246 +
30247         if (!buffer_is_empty(proc->socket)) {
30248  #ifdef HAVE_SYS_UN_H
30249                 /* use the unix domain socket */
30250                 scgi_addr_un.sun_family = AF_UNIX;
30251                 strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
30252 -#ifdef SUN_LEN
30253 +               
30254                 servlen = SUN_LEN(&scgi_addr_un);
30255 -#else
30256 -               /* stevens says: */
30257 -               servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
30258 -#endif
30259 +
30260                 scgi_addr = (struct sockaddr *) &scgi_addr_un;
30261  #else
30262                 return -1;
30263 @@ -1305,105 +1301,105 @@
30264         } else {
30265                 scgi_addr_in.sin_family = AF_INET;
30266                 if (0 == inet_aton(host->host->ptr, &(scgi_addr_in.sin_addr))) {
30267 -                       log_error_write(srv, __FILE__, __LINE__, "sbs", 
30268 -                                       "converting IP-adress failed for", host->host, 
30269 +                       log_error_write(srv, __FILE__, __LINE__, "sbs",
30270 +                                       "converting IP-adress failed for", host->host,
30271                                         "\nBe sure to specify an IP address here");
30272 -                       
30273 +
30274                         return -1;
30275                 }
30276                 scgi_addr_in.sin_port = htons(proc->port);
30277                 servlen = sizeof(scgi_addr_in);
30278 -               
30279 +
30280                 scgi_addr = (struct sockaddr *) &scgi_addr_in;
30281         }
30282 -       
30283 +
30284         if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
30285 -               if (errno == EINPROGRESS || 
30286 +               if (errno == EINPROGRESS ||
30287                     errno == EALREADY ||
30288                     errno == EINTR) {
30289                         if (hctx->conf.debug) {
30290 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
30291 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
30292                                                 "connect delayed, will continue later:", scgi_fd);
30293                         }
30294 -                       
30295 +
30296                         return 1;
30297                 } else {
30298 -                       log_error_write(srv, __FILE__, __LINE__, "sdsddb", 
30299 -                                       "connect failed:", scgi_fd, 
30300 +                       log_error_write(srv, __FILE__, __LINE__, "sdsddb",
30301 +                                       "connect failed:", scgi_fd,
30302                                         strerror(errno), errno,
30303                                         proc->port, proc->socket);
30304  
30305                         if (errno == EAGAIN) {
30306                                 /* this is Linux only */
30307 -                               
30308 -                               log_error_write(srv, __FILE__, __LINE__, "s", 
30309 +
30310 +                               log_error_write(srv, __FILE__, __LINE__, "s",
30311                                                 "If this happend on Linux: You have been run out of local ports. "
30312                                                 "Check the manual, section Performance how to handle this.");
30313 -                       } 
30314 -                       
30315 +                       }
30316 +
30317                         return -1;
30318                 }
30319         }
30320         if (hctx->conf.debug > 1) {
30321 -               log_error_write(srv, __FILE__, __LINE__, "sd", 
30322 +               log_error_write(srv, __FILE__, __LINE__, "sd",
30323                                 "connect succeeded: ", scgi_fd);
30324         }
30325  
30326  
30327 -       
30328 +
30329         return 0;
30330  }
30331  
30332  static int scgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
30333         size_t i;
30334 -       
30335 +
30336         for (i = 0; i < con->request.headers->used; i++) {
30337                 data_string *ds;
30338 -               
30339 +
30340                 ds = (data_string *)con->request.headers->data[i];
30341 -               
30342 +
30343                 if (ds->value->used && ds->key->used) {
30344                         size_t j;
30345                         buffer_reset(srv->tmp_buf);
30346 -                       
30347 +
30348                         if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
30349                                 BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
30350                                 srv->tmp_buf->used--;
30351                         }
30352 -                       
30353 +
30354                         buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
30355                         for (j = 0; j < ds->key->used - 1; j++) {
30356 -                               srv->tmp_buf->ptr[srv->tmp_buf->used++] = 
30357 -                                       light_isalpha(ds->key->ptr[j]) ? 
30358 +                               srv->tmp_buf->ptr[srv->tmp_buf->used++] =
30359 +                                       light_isalpha(ds->key->ptr[j]) ?
30360                                         ds->key->ptr[j] & ~32 : '_';
30361                         }
30362                         srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
30363 -                       
30364 +
30365                         scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
30366                 }
30367         }
30368 -       
30369 +
30370         for (i = 0; i < con->environment->used; i++) {
30371                 data_string *ds;
30372 -               
30373 +
30374                 ds = (data_string *)con->environment->data[i];
30375 -               
30376 +
30377                 if (ds->value->used && ds->key->used) {
30378                         size_t j;
30379                         buffer_reset(srv->tmp_buf);
30380 -                       
30381 +
30382                         buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
30383                         for (j = 0; j < ds->key->used - 1; j++) {
30384 -                               srv->tmp_buf->ptr[srv->tmp_buf->used++] = 
30385 -                                       isalpha((unsigned char)ds->key->ptr[j]) ? 
30386 +                               srv->tmp_buf->ptr[srv->tmp_buf->used++] =
30387 +                                       isalpha((unsigned char)ds->key->ptr[j]) ?
30388                                         toupper((unsigned char)ds->key->ptr[j]) : '_';
30389                         }
30390                         srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
30391 -                       
30392 +
30393                         scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
30394                 }
30395         }
30396 -       
30397 +
30398         return 0;
30399  }
30400  
30401 @@ -1415,20 +1411,20 @@
30402         char b2[INET6_ADDRSTRLEN + 1];
30403  #endif
30404         buffer *b;
30405 -       
30406 +
30407         plugin_data *p    = hctx->plugin_data;
30408         scgi_extension_host *host= hctx->host;
30409  
30410         connection *con   = hctx->remote_conn;
30411         server_socket *srv_sock = con->srv_socket;
30412 -       
30413 +
30414         sock_addr our_addr;
30415         socklen_t our_addr_len;
30416 -       
30417 +
30418         buffer_prepare_copy(p->scgi_env, 1024);
30419  
30420         /* CGI-SPEC 6.1.2, FastCGI spec 6.3 and SCGI spec */
30421 -               
30422 +
30423         /* request.content_length < SSIZE_MAX, see request.c */
30424         ltostr(buf, con->request.content_length);
30425         scgi_env_add(p->scgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
30426 @@ -1436,13 +1432,13 @@
30427  
30428  
30429         scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
30430 -       
30431 +
30432         if (con->server_name->used) {
30433                 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
30434         } else {
30435  #ifdef HAVE_IPV6
30436 -               s = inet_ntop(srv_sock->addr.plain.sa_family, 
30437 -                             srv_sock->addr.plain.sa_family == AF_INET6 ? 
30438 +               s = inet_ntop(srv_sock->addr.plain.sa_family,
30439 +                             srv_sock->addr.plain.sa_family == AF_INET6 ?
30440                               (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
30441                               (const void *) &(srv_sock->addr.ipv4.sin_addr),
30442                               b2, sizeof(b2)-1);
30443 @@ -1451,47 +1447,47 @@
30444  #endif
30445                 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
30446         }
30447 -       
30448 +
30449         scgi_env_add(p->scgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
30450 -       
30451 -       ltostr(buf, 
30452 +
30453 +       ltostr(buf,
30454  #ifdef HAVE_IPV6
30455                ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
30456  #else
30457                ntohs(srv_sock->addr.ipv4.sin_port)
30458  #endif
30459                );
30460 -       
30461 +
30462         scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
30463 -       
30464 +
30465         /* get the server-side of the connection to the client */
30466         our_addr_len = sizeof(our_addr);
30467 -       
30468 +
30469         if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
30470                 s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
30471         } else {
30472                 s = inet_ntop_cache_get_ip(srv, &(our_addr));
30473         }
30474         scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
30475 -       
30476 -       ltostr(buf, 
30477 +
30478 +       ltostr(buf,
30479  #ifdef HAVE_IPV6
30480                ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
30481  #else
30482                ntohs(con->dst_addr.ipv4.sin_port)
30483  #endif
30484                );
30485 -       
30486 +
30487         scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
30488 -       
30489 +
30490         s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
30491         scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
30492 -       
30493 +
30494         if (!buffer_is_empty(con->authed_user)) {
30495                 scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_USER"),
30496                              CONST_BUF_LEN(con->authed_user));
30497         }
30498 -       
30499 +
30500  
30501         /*
30502          * SCRIPT_NAME, PATH_INFO and PATH_TRANSLATED according to
30503 @@ -1500,12 +1496,12 @@
30504          */
30505  
30506         scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
30507 -               
30508 +
30509         if (!buffer_is_empty(con->request.pathinfo)) {
30510                 scgi_env_add(p->scgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
30511 -               
30512 +
30513                 /* PATH_TRANSLATED is only defined if PATH_INFO is set */
30514 -               
30515 +
30516                 if (!buffer_is_empty(host->docroot)) {
30517                         buffer_copy_string_buffer(p->path, host->docroot);
30518                 } else {
30519 @@ -1526,19 +1522,19 @@
30520          */
30521  
30522         if (!buffer_is_empty(host->docroot)) {
30523 -               /* 
30524 -                * rewrite SCRIPT_FILENAME 
30525 -                * 
30526 +               /*
30527 +                * rewrite SCRIPT_FILENAME
30528 +                *
30529                  */
30530 -               
30531 +
30532                 buffer_copy_string_buffer(p->path, host->docroot);
30533                 buffer_append_string_buffer(p->path, con->uri.path);
30534 -               
30535 +
30536                 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
30537                 scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
30538         } else {
30539                 buffer_copy_string_buffer(p->path, con->physical.path);
30540 -               
30541 +
30542                 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
30543                 scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
30544         }
30545 @@ -1551,30 +1547,30 @@
30546         } else {
30547                 scgi_env_add(p->scgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
30548         }
30549 -       
30550 +
30551         s = get_http_method_name(con->request.http_method);
30552         scgi_env_add(p->scgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
30553         scgi_env_add(p->scgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
30554         s = get_http_version_name(con->request.http_version);
30555         scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
30556 -       
30557 +
30558  #ifdef USE_OPENSSL
30559         if (srv_sock->is_ssl) {
30560                 scgi_env_add(p->scgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
30561         }
30562  #endif
30563 -       
30564 +
30565         scgi_env_add_request_headers(srv, con, p);
30566  
30567         b = chunkqueue_get_append_buffer(hctx->wb);
30568 -       
30569 +
30570         buffer_append_long(b, p->scgi_env->used);
30571         buffer_append_string_len(b, CONST_STR_LEN(":"));
30572         buffer_append_string_len(b, (const char *)p->scgi_env->ptr, p->scgi_env->used);
30573         buffer_append_string_len(b, CONST_STR_LEN(","));
30574  
30575         hctx->wb->bytes_in += b->used - 1;
30576 -       
30577 +
30578         if (con->request.content_length) {
30579                 chunkqueue *req_cq = con->request_content_queue;
30580                 chunk *req_c;
30581 @@ -1587,7 +1583,7 @@
30582  
30583                         /* we announce toWrite octects
30584                          * now take all the request_content chunk that we need to fill this request
30585 -                        * */   
30586 +                        * */
30587  
30588                         switch (req_c->type) {
30589                         case FILE_CHUNK:
30590 @@ -1615,32 +1611,32 @@
30591  
30592                                 req_c->offset += weHave;
30593                                 req_cq->bytes_out += weHave;
30594 -                               
30595 +
30596                                 hctx->wb->bytes_in += weHave;
30597  
30598                                 break;
30599                         default:
30600                                 break;
30601                         }
30602 -                       
30603 +
30604                         offset += weHave;
30605                 }
30606         }
30607 -       
30608 +
30609  #if 0
30610         for (i = 0; i < hctx->write_buffer->used; i++) {
30611                 fprintf(stderr, "%02x ", hctx->write_buffer->ptr[i]);
30612                 if ((i+1) % 16 == 0) {
30613                         size_t j;
30614                         for (j = i-15; j <= i; j++) {
30615 -                               fprintf(stderr, "%c", 
30616 +                               fprintf(stderr, "%c",
30617                                         isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.');
30618                         }
30619                         fprintf(stderr, "\n");
30620                 }
30621         }
30622  #endif
30623 -       
30624 +
30625         return 0;
30626  }
30627  
30628 @@ -1648,32 +1644,32 @@
30629         char *ns;
30630         const char *s;
30631         int line = 0;
30632 -       
30633 +
30634         UNUSED(srv);
30635 -       
30636 +
30637         buffer_copy_string_buffer(p->parse_response, in);
30638 -       
30639 -       for (s = p->parse_response->ptr; 
30640 -            NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n'))); 
30641 +
30642 +       for (s = p->parse_response->ptr;
30643 +            NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
30644              s = ns + (eol == EOL_RN ? 2 : 1), line++) {
30645                 const char *key, *value;
30646                 int key_len;
30647                 data_string *ds;
30648 -               
30649 +
30650                 ns[0] = '\0';
30651 -               
30652 -               if (line == 0 && 
30653 +
30654 +               if (line == 0 &&
30655                     0 == strncmp(s, "HTTP/1.", 7)) {
30656                         /* non-parsed header ... we parse them anyway */
30657 -                       
30658 +
30659                         if ((s[7] == '1' ||
30660                              s[7] == '0') &&
30661                             s[8] == ' ') {
30662                                 int status;
30663                                 /* after the space should be a status code for us */
30664 -                               
30665 +
30666                                 status = strtol(s+9, NULL, 10);
30667 -                               
30668 +
30669                                 if (con->http_status >= 100 &&
30670                                     con->http_status < 1000) {
30671                                         /* we expected 3 digits and didn't got them */
30672 @@ -1682,27 +1678,27 @@
30673                                 }
30674                         }
30675                 } else {
30676 -               
30677 +
30678                         key = s;
30679                         if (NULL == (value = strchr(s, ':'))) {
30680                                 /* we expect: "<key>: <value>\r\n" */
30681                                 continue;
30682                         }
30683 -                       
30684 +
30685                         key_len = value - key;
30686                         value += 1;
30687 -                       
30688 +
30689                         /* skip LWS */
30690                         while (*value == ' ' || *value == '\t') value++;
30691 -                       
30692 +
30693                         if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
30694                                 ds = data_response_init();
30695                         }
30696                         buffer_copy_string_len(ds->key, key, key_len);
30697                         buffer_copy_string(ds->value, value);
30698 -                       
30699 +
30700                         array_insert_unique(con->response.headers, (data_unset *)ds);
30701 -                       
30702 +
30703                         switch(key_len) {
30704                         case 4:
30705                                 if (0 == strncasecmp(key, "Date", key_len)) {
30706 @@ -1737,13 +1733,13 @@
30707                         }
30708                 }
30709         }
30710 -       
30711 +
30712         /* CGI/1.1 rev 03 - 7.2.1.2 */
30713         if ((con->parsed_response & HTTP_LOCATION) &&
30714             !(con->parsed_response & HTTP_STATUS)) {
30715                 con->http_status = 302;
30716         }
30717 -       
30718 +
30719         return 0;
30720  }
30721  
30722 @@ -1751,10 +1747,10 @@
30723  static int scgi_demux_response(server *srv, handler_ctx *hctx) {
30724         plugin_data *p    = hctx->plugin_data;
30725         connection  *con  = hctx->remote_conn;
30726 -       
30727 +
30728         while(1) {
30729                 int n;
30730 -               
30731 +
30732                 buffer_prepare_copy(hctx->response, 1024);
30733                 if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
30734                         if (errno == EAGAIN || errno == EINTR) {
30735 @@ -1765,143 +1761,143 @@
30736                         log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
30737                         return -1;
30738                 }
30739 -               
30740 +
30741                 if (n == 0) {
30742                         /* read finished */
30743 -                       
30744 +
30745                         con->file_finished = 1;
30746 -                       
30747 +
30748                         /* send final chunk */
30749                         http_chunk_append_mem(srv, con, NULL, 0);
30750                         joblist_append(srv, con);
30751 -                       
30752 +
30753                         return 1;
30754                 }
30755 -               
30756 +
30757                 hctx->response->ptr[n] = '\0';
30758                 hctx->response->used = n+1;
30759 -               
30760 +
30761                 /* split header from body */
30762 -               
30763 +
30764                 if (con->file_started == 0) {
30765                         char *c;
30766                         int in_header = 0;
30767                         int header_end = 0;
30768                         int cp, eol = EOL_UNSET;
30769                         size_t used = 0;
30770 -                       
30771 +
30772                         buffer_append_string_buffer(hctx->response_header, hctx->response);
30773 -                       
30774 +
30775                         /* nph (non-parsed headers) */
30776                         if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
30777 -                       
30778 +
30779                         /* search for the \r\n\r\n or \n\n in the string */
30780                         for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
30781                                 if (*c == ':') in_header = 1;
30782                                 else if (*c == '\n') {
30783                                         if (in_header == 0) {
30784                                                 /* got a response without a response header */
30785 -                                               
30786 +
30787                                                 c = NULL;
30788                                                 header_end = 1;
30789                                                 break;
30790                                         }
30791 -                                       
30792 +
30793                                         if (eol == EOL_UNSET) eol = EOL_N;
30794 -                                       
30795 +
30796                                         if (*(c+1) == '\n') {
30797                                                 header_end = 1;
30798                                                 break;
30799                                         }
30800 -                                       
30801 +
30802                                 } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
30803                                         if (in_header == 0) {
30804                                                 /* got a response without a response header */
30805 -                                               
30806 +
30807                                                 c = NULL;
30808                                                 header_end = 1;
30809                                                 break;
30810                                         }
30811 -                                       
30812 +
30813                                         if (eol == EOL_UNSET) eol = EOL_RN;
30814 -                                       
30815 +
30816                                         if (used > 3 &&
30817 -                                           *(c+2) == '\r' && 
30818 +                                           *(c+2) == '\r' &&
30819                                             *(c+3) == '\n') {
30820                                                 header_end = 1;
30821                                                 break;
30822                                         }
30823 -                                       
30824 +
30825                                         /* skip the \n */
30826                                         c++;
30827                                         cp++;
30828                                         used--;
30829                                 }
30830                         }
30831 -                       
30832 +
30833                         if (header_end) {
30834                                 if (c == NULL) {
30835                                         /* no header, but a body */
30836 -                                       
30837 +
30838                                         if (con->request.http_version == HTTP_VERSION_1_1) {
30839                                                 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
30840                                         }
30841 -                                       
30842 +
30843                                         http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
30844                                         joblist_append(srv, con);
30845                                 } else {
30846                                         size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
30847                                         size_t blen = hctx->response_header->used - hlen - 1;
30848 -                               
30849 +
30850                                         /* a small hack: terminate after at the second \r */
30851                                         hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
30852                                         hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';
30853 -                               
30854 +
30855                                         /* parse the response header */
30856                                         scgi_response_parse(srv, con, p, hctx->response_header, eol);
30857 -                                       
30858 +
30859                                         /* enable chunked-transfer-encoding */
30860                                         if (con->request.http_version == HTTP_VERSION_1_1 &&
30861                                             !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
30862                                                 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
30863                                         }
30864 -                                       
30865 +
30866                                         if ((hctx->response->used != hlen) && blen > 0) {
30867                                                 http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
30868                                                 joblist_append(srv, con);
30869                                         }
30870                                 }
30871 -                               
30872 +
30873                                 con->file_started = 1;
30874                         }
30875                 } else {
30876                         http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
30877                         joblist_append(srv, con);
30878                 }
30879 -               
30880 -#if 0          
30881 +
30882 +#if 0
30883                 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
30884  #endif
30885         }
30886 -       
30887 +
30888         return 0;
30889  }
30890  
30891  
30892  int scgi_proclist_sort_up(server *srv, scgi_extension_host *host, scgi_proc *proc) {
30893         scgi_proc *p;
30894 -       
30895 +
30896         UNUSED(srv);
30897 -       
30898 -       /* we have been the smallest of the current list 
30899 -        * and we want to insert the node sorted as soon 
30900 +
30901 +       /* we have been the smallest of the current list
30902 +        * and we want to insert the node sorted as soon
30903          * possible
30904          *
30905 -        * 1 0 0 0 1 1 1 
30906 -        * |      ^ 
30907 +        * 1 0 0 0 1 1 1
30908 +        * |      ^
30909          * |      |
30910          * +------+
30911 -        * 
30912 +        *
30913          */
30914  
30915         /* nothing to sort, only one element */
30916 @@ -1909,9 +1905,9 @@
30917  
30918         for (p = proc; p->next && p->next->load < proc->load; p = p->next);
30919  
30920 -       /* no need to move something 
30921 +       /* no need to move something
30922          *
30923 -        * 1 2 2 2 3 3 3 
30924 +        * 1 2 2 2 3 3 3
30925          * ^
30926          * |
30927          * +
30928 @@ -1930,16 +1926,16 @@
30929  
30930         if (proc->prev) proc->prev->next = proc->next;
30931         if (proc->next) proc->next->prev = proc->prev;
30932 -       
30933 +
30934         /* proc should be right of p */
30935 -       
30936 +
30937         proc->next = p->next;
30938         proc->prev = p;
30939         if (p->next) p->next->prev = proc;
30940         p->next = proc;
30941  #if 0
30942         for(p = host->first; p; p = p->next) {
30943 -               log_error_write(srv, __FILE__, __LINE__, "dd", 
30944 +               log_error_write(srv, __FILE__, __LINE__, "dd",
30945                                 p->pid, p->load);
30946         }
30947  #else
30948 @@ -1951,21 +1947,21 @@
30949  
30950  int scgi_proclist_sort_down(server *srv, scgi_extension_host *host, scgi_proc *proc) {
30951         scgi_proc *p;
30952 -       
30953 +
30954         UNUSED(srv);
30955 -       
30956 -       /* we have been the smallest of the current list 
30957 -        * and we want to insert the node sorted as soon 
30958 +
30959 +       /* we have been the smallest of the current list
30960 +        * and we want to insert the node sorted as soon
30961          * possible
30962          *
30963 -        *  0 0 0 0 1 0 1 
30964 +        *  0 0 0 0 1 0 1
30965          * ^          |
30966          * |          |
30967          * +----------+
30968          *
30969          *
30970          * the basic is idea is:
30971 -        * - the last active scgi process should be still 
30972 +        * - the last active scgi process should be still
30973          *   in ram and is not swapped out yet
30974          * - processes that are not reused will be killed
30975          *   after some time by the trigger-handler
30976 @@ -1975,7 +1971,7 @@
30977          *   ice-cold processes are propably unused since more
30978          *   than 'unused-timeout', are swaped out and won't be
30979          *   reused in the next seconds anyway.
30980 -        * 
30981 +        *
30982          */
30983  
30984         /* nothing to sort, only one element */
30985 @@ -1984,16 +1980,16 @@
30986         for (p = host->first; p != proc && p->load < proc->load; p = p->next);
30987  
30988  
30989 -       /* no need to move something 
30990 +       /* no need to move something
30991          *
30992 -        * 1 2 2 2 3 3 3 
30993 +        * 1 2 2 2 3 3 3
30994          * ^
30995          * |
30996          * +
30997          *
30998          */
30999         if (p == proc) return 0;
31000 -       
31001 +
31002         /* we have to move left. If we are already the first element
31003          * we are done */
31004         if (host->first == proc) return 0;
31005 @@ -2009,9 +2005,9 @@
31006         p->prev = proc;
31007  
31008         if (proc->prev == NULL) host->first = proc;
31009 -#if 0  
31010 +#if 0
31011         for(p = host->first; p; p = p->next) {
31012 -               log_error_write(srv, __FILE__, __LINE__, "dd", 
31013 +               log_error_write(srv, __FILE__, __LINE__, "dd",
31014                                 p->pid, p->load);
31015         }
31016  #else
31017 @@ -2023,41 +2019,42 @@
31018  
31019  static int scgi_restart_dead_procs(server *srv, plugin_data *p, scgi_extension_host *host) {
31020         scgi_proc *proc;
31021 -       
31022 +
31023         for (proc = host->first; proc; proc = proc->next) {
31024                 if (p->conf.debug) {
31025 -                       log_error_write(srv, __FILE__, __LINE__,  "sbdbdddd", 
31026 -                                       "proc:", 
31027 -                                       host->host, proc->port, 
31028 +                       log_error_write(srv, __FILE__, __LINE__,  "sbdbdddd",
31029 +                                       "proc:",
31030 +                                       host->host, proc->port,
31031                                         proc->socket,
31032                                         proc->state,
31033                                         proc->is_local,
31034                                         proc->load,
31035                                         proc->pid);
31036                 }
31037 -               
31038 +
31039                 if (0 == proc->is_local) {
31040 -                       /* 
31041 -                        * external servers might get disabled 
31042 -                        * 
31043 -                        * enable the server again, perhaps it is back again 
31044 +                       /*
31045 +                        * external servers might get disabled
31046 +                        *
31047 +                        * enable the server again, perhaps it is back again
31048                          */
31049 -                       
31050 +
31051                         if ((proc->state == PROC_STATE_DISABLED) &&
31052                             (srv->cur_ts - proc->disable_ts > host->disable_time)) {
31053                                 proc->state = PROC_STATE_RUNNING;
31054                                 host->active_procs++;
31055 -                               
31056 -                               log_error_write(srv, __FILE__, __LINE__,  "sbdb", 
31057 -                                               "fcgi-server re-enabled:", 
31058 -                                               host->host, host->port, 
31059 +
31060 +                               log_error_write(srv, __FILE__, __LINE__,  "sbdb",
31061 +                                               "fcgi-server re-enabled:",
31062 +                                               host->host, host->port,
31063                                                 host->unixsocket);
31064                         }
31065                 } else {
31066                         /* the child should not terminate at all */
31067                         int status;
31068 -                       
31069 +
31070                         if (proc->state == PROC_STATE_DIED_WAIT_FOR_PID) {
31071 +#ifndef _WIN32
31072                                 switch(waitpid(proc->pid, &status, WNOHANG)) {
31073                                 case 0:
31074                                         /* child is still alive */
31075 @@ -2067,33 +2064,34 @@
31076                                 default:
31077                                         if (WIFEXITED(status)) {
31078  #if 0
31079 -                                               log_error_write(srv, __FILE__, __LINE__, "sdsd", 
31080 +                                               log_error_write(srv, __FILE__, __LINE__, "sdsd",
31081                                                                 "child exited, pid:", proc->pid,
31082                                                                 "status:", WEXITSTATUS(status));
31083  #endif
31084                                         } else if (WIFSIGNALED(status)) {
31085 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
31086 -                                                               "child signaled:", 
31087 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
31088 +                                                               "child signaled:",
31089                                                                 WTERMSIG(status));
31090                                         } else {
31091 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
31092 -                                                               "child died somehow:", 
31093 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
31094 +                                                               "child died somehow:",
31095                                                                 status);
31096                                         }
31097 -                                       
31098 +
31099                                         proc->state = PROC_STATE_DIED;
31100                                         break;
31101                                 }
31102 +#endif
31103                         }
31104 -                       
31105 -                       /* 
31106 +
31107 +                       /*
31108                          * local servers might died, but we restart them
31109 -                        * 
31110 +                        *
31111                          */
31112                         if (proc->state == PROC_STATE_DIED &&
31113                             proc->load == 0) {
31114                                 /* restart the child */
31115 -                               
31116 +
31117                                 if (p->conf.debug) {
31118                                         log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
31119                                                         "--- scgi spawning",
31120 @@ -2101,18 +2099,18 @@
31121                                                         "\n\tsocket", host->unixsocket,
31122                                                         "\n\tcurrent:", 1, "/", host->min_procs);
31123                                 }
31124 -                               
31125 +
31126                                 if (scgi_spawn_connection(srv, p, host, proc)) {
31127                                         log_error_write(srv, __FILE__, __LINE__, "s",
31128                                                         "ERROR: spawning fcgi failed.");
31129                                         return HANDLER_ERROR;
31130                                 }
31131 -                               
31132 +
31133                                 scgi_proclist_sort_down(srv, host, proc);
31134                         }
31135                 }
31136         }
31137 -       
31138 +
31139         return 0;
31140  }
31141  
31142 @@ -2121,13 +2119,13 @@
31143         plugin_data *p    = hctx->plugin_data;
31144         scgi_extension_host *host= hctx->host;
31145         connection *con   = hctx->remote_conn;
31146 -       
31147 +
31148         int ret;
31149  
31150 -       /* sanity check */      
31151 +       /* sanity check */
31152         if (!host ||
31153             ((!host->host->used || !host->port) && !host->unixsocket->used)) {
31154 -               log_error_write(srv, __FILE__, __LINE__, "sxddd", 
31155 +               log_error_write(srv, __FILE__, __LINE__, "sxddd",
31156                                 "write-req: error",
31157                                 host,
31158                                 host->host->used,
31159 @@ -2135,179 +2133,180 @@
31160                                 host->unixsocket->used);
31161                 return HANDLER_ERROR;
31162         }
31163 -       
31164 +
31165  
31166         switch(hctx->state) {
31167         case FCGI_STATE_INIT:
31168                 ret = host->unixsocket->used ? AF_UNIX : AF_INET;
31169 -               
31170 +
31171                 if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
31172                         if (errno == EMFILE ||
31173                             errno == EINTR) {
31174 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
31175 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
31176                                                 "wait for fd at connection:", con->fd);
31177 -                               
31178 +
31179                                 return HANDLER_WAIT_FOR_FD;
31180                         }
31181 -                       
31182 -                       log_error_write(srv, __FILE__, __LINE__, "ssdd", 
31183 +
31184 +                       log_error_write(srv, __FILE__, __LINE__, "ssdd",
31185                                         "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
31186                         return HANDLER_ERROR;
31187                 }
31188                 hctx->fde_ndx = -1;
31189 -               
31190 +
31191                 srv->cur_fds++;
31192 -               
31193 +
31194                 fdevent_register(srv->ev, hctx->fd, scgi_handle_fdevent, hctx);
31195 -               
31196 +
31197                 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
31198 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
31199 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
31200                                         "fcntl failed: ", strerror(errno));
31201 -                       
31202 +
31203                         return HANDLER_ERROR;
31204                 }
31205 -               
31206 +
31207                 /* fall through */
31208         case FCGI_STATE_CONNECT:
31209                 if (hctx->state == FCGI_STATE_INIT) {
31210 -                       for (hctx->proc = hctx->host->first; 
31211 -                            hctx->proc && hctx->proc->state != PROC_STATE_RUNNING; 
31212 +                       for (hctx->proc = hctx->host->first;
31213 +                            hctx->proc && hctx->proc->state != PROC_STATE_RUNNING;
31214                              hctx->proc = hctx->proc->next);
31215 -                       
31216 +
31217                         /* all childs are dead */
31218                         if (hctx->proc == NULL) {
31219                                 hctx->fde_ndx = -1;
31220 -                               
31221 +
31222                                 return HANDLER_ERROR;
31223                         }
31224 -                       
31225 +
31226                         if (hctx->proc->is_local) {
31227                                 hctx->pid = hctx->proc->pid;
31228                         }
31229 -                       
31230 +
31231                         switch (scgi_establish_connection(srv, hctx)) {
31232                         case 1:
31233                                 scgi_set_state(srv, hctx, FCGI_STATE_CONNECT);
31234 -                               
31235 +
31236                                 /* connection is in progress, wait for an event and call getsockopt() below */
31237 -                               
31238 +
31239                                 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31240 -                               
31241 +
31242                                 return HANDLER_WAIT_FOR_EVENT;
31243                         case -1:
31244                                 /* if ECONNREFUSED choose another connection -> FIXME */
31245                                 hctx->fde_ndx = -1;
31246 -                               
31247 +
31248                                 return HANDLER_ERROR;
31249                         default:
31250                                 /* everything is ok, go on */
31251                                 break;
31252                         }
31253  
31254 -                       
31255 +
31256                 } else {
31257                         int socket_error;
31258                         socklen_t socket_error_len = sizeof(socket_error);
31259 -                       
31260 +
31261                         /* try to finish the connect() */
31262                         if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
31263 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
31264 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
31265                                                 "getsockopt failed:", strerror(errno));
31266 -                               
31267 +
31268                                 return HANDLER_ERROR;
31269                         }
31270                         if (socket_error != 0) {
31271                                 if (!hctx->proc->is_local || p->conf.debug) {
31272                                         /* local procs get restarted */
31273 -                                       
31274 +
31275                                         log_error_write(srv, __FILE__, __LINE__, "ss",
31276 -                                                       "establishing connection failed:", strerror(socket_error), 
31277 +                                                       "establishing connection failed:", strerror(socket_error),
31278                                                         "port:", hctx->proc->port);
31279                                 }
31280 -                               
31281 +
31282                                 return HANDLER_ERROR;
31283                         }
31284                 }
31285 -               
31286 +
31287                 /* ok, we have the connection */
31288 -               
31289 +
31290                 hctx->proc->load++;
31291                 hctx->proc->last_used = srv->cur_ts;
31292                 hctx->got_proc = 1;
31293 -               
31294 +
31295                 if (p->conf.debug) {
31296                         log_error_write(srv, __FILE__, __LINE__, "sddbdd",
31297 -                                       "got proc:", 
31298 +                                       "got proc:",
31299                                         hctx->fd,
31300 -                                       hctx->proc->pid, 
31301 -                                       hctx->proc->socket, 
31302 +                                       hctx->proc->pid,
31303 +                                       hctx->proc->socket,
31304                                         hctx->proc->port,
31305                                         hctx->proc->load);
31306                 }
31307  
31308                 /* move the proc-list entry down the list */
31309                 scgi_proclist_sort_up(srv, hctx->host, hctx->proc);
31310 -               
31311 +
31312                 scgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
31313                 /* fall through */
31314         case FCGI_STATE_PREPARE_WRITE:
31315                 scgi_create_env(srv, hctx);
31316 -               
31317 +
31318                 scgi_set_state(srv, hctx, FCGI_STATE_WRITE);
31319 -               
31320 +
31321                 /* fall through */
31322         case FCGI_STATE_WRITE:
31323 -               ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); 
31324 +               ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
31325  
31326                 chunkqueue_remove_finished_chunks(hctx->wb);
31327 -       
31328 +
31329                 if (-1 == ret) {
31330                         if (errno == ENOTCONN) {
31331 -                               /* the connection got dropped after accept() 
31332 -                                * 
31333 -                                * this is most of the time a PHP which dies 
31334 +                               /* the connection got dropped after accept()
31335 +                                *
31336 +                                * this is most of the time a PHP which dies
31337                                  * after PHP_FCGI_MAX_REQUESTS
31338 -                                * 
31339 -                                */ 
31340 +                                *
31341 +                                */
31342                                 if (hctx->wb->bytes_out == 0 &&
31343                                     hctx->reconnects < 5) {
31344 -                                       usleep(10000); /* take away the load of the webserver 
31345 -                                                       * to let the php a chance to restart 
31346 +#ifndef _WIN32
31347 +                                       usleep(10000); /* take away the load of the webserver
31348 +                                                       * to let the php a chance to restart
31349                                                         */
31350 -                                       
31351 +#endif
31352                                         scgi_reconnect(srv, hctx);
31353 -                               
31354 +
31355                                         return HANDLER_WAIT_FOR_FD;
31356                                 }
31357 -                               
31358 +
31359                                 /* not reconnected ... why
31360 -                                * 
31361 +                                *
31362                                  * far@#lighttpd report this for FreeBSD
31363 -                                * 
31364 +                                *
31365                                  */
31366 -                               
31367 -                               log_error_write(srv, __FILE__, __LINE__, "ssdsd", 
31368 +
31369 +                               log_error_write(srv, __FILE__, __LINE__, "ssosd",
31370                                                 "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
31371                                                 "write-offset:", hctx->wb->bytes_out,
31372                                                 "reconnect attempts:", hctx->reconnects);
31373 -                               
31374 +
31375                                 return HANDLER_ERROR;
31376                         }
31377 -                       
31378 +
31379                         if ((errno != EAGAIN) &&
31380                             (errno != EINTR)) {
31381 -                               
31382 -                               log_error_write(srv, __FILE__, __LINE__, "ssd", 
31383 +
31384 +                               log_error_write(srv, __FILE__, __LINE__, "ssd",
31385                                                 "write failed:", strerror(errno), errno);
31386 -                               
31387 +
31388                                 return HANDLER_ERROR;
31389                         } else {
31390                                 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31391 -                               
31392 +
31393                                 return HANDLER_WAIT_FOR_EVENT;
31394                         }
31395                 }
31396 -               
31397 +
31398                 if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
31399                         /* we don't need the out event anymore */
31400                         fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
31401 @@ -2315,10 +2314,10 @@
31402                         scgi_set_state(srv, hctx, FCGI_STATE_READ);
31403                 } else {
31404                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31405 -                       
31406 +
31407                         return HANDLER_WAIT_FOR_EVENT;
31408                 }
31409 -               
31410 +
31411                 break;
31412         case FCGI_STATE_READ:
31413                 /* waiting for a response */
31414 @@ -2327,67 +2326,67 @@
31415                 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
31416                 return HANDLER_ERROR;
31417         }
31418 -       
31419 +
31420         return HANDLER_WAIT_FOR_EVENT;
31421  }
31422  
31423  SUBREQUEST_FUNC(mod_scgi_handle_subrequest) {
31424         plugin_data *p = p_d;
31425 -       
31426 +
31427         handler_ctx *hctx = con->plugin_ctx[p->id];
31428         scgi_proc *proc;
31429         scgi_extension_host *host;
31430 -       
31431 +
31432         if (NULL == hctx) return HANDLER_GO_ON;
31433 -       
31434 +
31435         /* not my job */
31436         if (con->mode != p->id) return HANDLER_GO_ON;
31437 -       
31438 +
31439         /* ok, create the request */
31440         switch(scgi_write_request(srv, hctx)) {
31441         case HANDLER_ERROR:
31442                 proc = hctx->proc;
31443                 host = hctx->host;
31444 -               
31445 -               if (proc && 
31446 +
31447 +               if (proc &&
31448                     0 == proc->is_local &&
31449                     proc->state != PROC_STATE_DISABLED) {
31450                         /* only disable remote servers as we don't manage them*/
31451 -                       
31452 -                       log_error_write(srv, __FILE__, __LINE__,  "sbdb", "fcgi-server disabled:", 
31453 +
31454 +                       log_error_write(srv, __FILE__, __LINE__,  "sbdb", "fcgi-server disabled:",
31455                                         host->host,
31456                                         proc->port,
31457                                         proc->socket);
31458 -                       
31459 +
31460                         /* disable this server */
31461                         proc->disable_ts = srv->cur_ts;
31462                         proc->state = PROC_STATE_DISABLED;
31463                         host->active_procs--;
31464                 }
31465 -               
31466 +
31467                 if (hctx->state == FCGI_STATE_INIT ||
31468                     hctx->state == FCGI_STATE_CONNECT) {
31469 -                       /* connect() or getsockopt() failed, 
31470 -                        * restart the request-handling 
31471 +                       /* connect() or getsockopt() failed,
31472 +                        * restart the request-handling
31473                          */
31474                         if (proc && proc->is_local) {
31475  
31476                                 if (p->conf.debug) {
31477 -                                       log_error_write(srv, __FILE__, __LINE__,  "sbdb", "connect() to scgi failed, restarting the request-handling:", 
31478 +                                       log_error_write(srv, __FILE__, __LINE__,  "sbdb", "connect() to scgi failed, restarting the request-handling:",
31479                                                         host->host,
31480                                                         proc->port,
31481                                                         proc->socket);
31482                                 }
31483  
31484 -                               /* 
31485 +                               /*
31486                                  * several hctx might reference the same proc
31487 -                                * 
31488 +                                *
31489                                  * Only one of them should mark the proc as dead all the other
31490                                  * ones should just take a new one.
31491 -                                * 
31492 +                                *
31493                                  * If a new proc was started with the old struct this might lead
31494                                  * the mark a perfect proc as dead otherwise
31495 -                                * 
31496 +                                *
31497                                  */
31498                                 if (proc->state == PROC_STATE_RUNNING &&
31499                                     hctx->pid == proc->pid) {
31500 @@ -2395,25 +2394,25 @@
31501                                 }
31502                         }
31503                         scgi_restart_dead_procs(srv, p, host);
31504 -                       
31505 +
31506                         scgi_connection_cleanup(srv, hctx);
31507 -                       
31508 +
31509                         buffer_reset(con->physical.path);
31510                         con->mode = DIRECT;
31511                         joblist_append(srv, con);
31512 -                       
31513 -                       /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop 
31514 -                        * and hope that the childs will be restarted 
31515 -                        * 
31516 +
31517 +                       /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
31518 +                        * and hope that the childs will be restarted
31519 +                        *
31520                          */
31521                         return HANDLER_WAIT_FOR_FD;
31522                 } else {
31523                         scgi_connection_cleanup(srv, hctx);
31524 -                       
31525 +
31526                         buffer_reset(con->physical.path);
31527                         con->mode = DIRECT;
31528                         con->http_status = 503;
31529 -                       
31530 +
31531                         return HANDLER_FINISHED;
31532                 }
31533         case HANDLER_WAIT_FOR_EVENT:
31534 @@ -2433,23 +2432,23 @@
31535  static handler_t scgi_connection_close(server *srv, handler_ctx *hctx) {
31536         plugin_data *p;
31537         connection  *con;
31538 -       
31539 +
31540         if (NULL == hctx) return HANDLER_GO_ON;
31541 -       
31542 +
31543         p    = hctx->plugin_data;
31544         con  = hctx->remote_conn;
31545 -       
31546 +
31547         if (con->mode != p->id) return HANDLER_GO_ON;
31548 -       
31549 -       log_error_write(srv, __FILE__, __LINE__, "ssdsd", 
31550 -                       "emergency exit: scgi:", 
31551 +
31552 +       log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31553 +                       "emergency exit: scgi:",
31554                         "connection-fd:", con->fd,
31555                         "fcgi-fd:", hctx->fd);
31556 -       
31557 -       
31558 -       
31559 +
31560 +
31561 +
31562         scgi_connection_cleanup(srv, hctx);
31563 -       
31564 +
31565         return HANDLER_FINISHED;
31566  }
31567  
31568 @@ -2459,7 +2458,7 @@
31569         handler_ctx *hctx = ctx;
31570         connection  *con  = hctx->remote_conn;
31571         plugin_data *p    = hctx->plugin_data;
31572 -       
31573 +
31574         scgi_proc *proc   = hctx->proc;
31575         scgi_extension_host *host= hctx->host;
31576  
31577 @@ -2471,15 +2470,15 @@
31578                 case 1:
31579                         /* we are done */
31580                         scgi_connection_cleanup(srv, hctx);
31581 -                       
31582 +
31583                         joblist_append(srv, con);
31584                         return HANDLER_FINISHED;
31585                 case -1:
31586                         if (proc->pid && proc->state != PROC_STATE_DIED) {
31587                                 int status;
31588 -                               
31589 +
31590                                 /* only fetch the zombie if it is not already done */
31591 -                               
31592 +#ifndef _WIN32
31593                                 switch(waitpid(proc->pid, &status, WNOHANG)) {
31594                                 case 0:
31595                                         /* child is still alive */
31596 @@ -2489,19 +2488,19 @@
31597                                 default:
31598                                         /* the child should not terminate at all */
31599                                         if (WIFEXITED(status)) {
31600 -                                               log_error_write(srv, __FILE__, __LINE__, "sdsd", 
31601 +                                               log_error_write(srv, __FILE__, __LINE__, "sdsd",
31602                                                                 "child exited, pid:", proc->pid,
31603                                                                 "status:", WEXITSTATUS(status));
31604                                         } else if (WIFSIGNALED(status)) {
31605 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
31606 -                                                               "child signaled:", 
31607 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
31608 +                                                               "child signaled:",
31609                                                                 WTERMSIG(status));
31610                                         } else {
31611 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
31612 -                                                               "child died somehow:", 
31613 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
31614 +                                                               "child died somehow:",
31615                                                                 status);
31616                                         }
31617 -                                       
31618 +
31619                                         if (p->conf.debug) {
31620                                                 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
31621                                                                 "--- scgi spawning",
31622 @@ -2509,40 +2508,41 @@
31623                                                                 "\n\tsocket", host->unixsocket,
31624                                                                 "\n\tcurrent:", 1, "/", host->min_procs);
31625                                         }
31626 -                                       
31627 +
31628                                         if (scgi_spawn_connection(srv, p, host, proc)) {
31629                                                 /* child died */
31630                                                 proc->state = PROC_STATE_DIED;
31631                                         } else {
31632                                                 scgi_proclist_sort_down(srv, host, proc);
31633                                         }
31634 -                                       
31635 +
31636                                         break;
31637                                 }
31638 +#endif
31639                         }
31640  
31641                         if (con->file_started == 0) {
31642                                 /* nothing has been send out yet, try to use another child */
31643 -                               
31644 +
31645                                 if (hctx->wb->bytes_out == 0 &&
31646                                     hctx->reconnects < 5) {
31647                                         scgi_reconnect(srv, hctx);
31648 -                                       
31649 -                                       log_error_write(srv, __FILE__, __LINE__, "sdsdsd", 
31650 +
31651 +                                       log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
31652                                                 "response not sent, request not sent, reconnection.",
31653                                                 "connection-fd:", con->fd,
31654                                                 "fcgi-fd:", hctx->fd);
31655 -                                       
31656 +
31657                                         return HANDLER_WAIT_FOR_FD;
31658                                 }
31659 -                               
31660 -                               log_error_write(srv, __FILE__, __LINE__, "sdsdsd", 
31661 +
31662 +                               log_error_write(srv, __FILE__, __LINE__, "sosdsd",
31663                                                 "response not sent, request sent:", hctx->wb->bytes_out,
31664                                                 "connection-fd:", con->fd,
31665                                                 "fcgi-fd:", hctx->fd);
31666 -                               
31667 +
31668                                 scgi_connection_cleanup(srv, hctx);
31669 -                               
31670 +
31671                                 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
31672                                 buffer_reset(con->physical.path);
31673                                 con->http_status = 500;
31674 @@ -2550,76 +2550,76 @@
31675                         } else {
31676                                 /* response might have been already started, kill the connection */
31677                                 scgi_connection_cleanup(srv, hctx);
31678 -                               
31679 -                               log_error_write(srv, __FILE__, __LINE__, "ssdsd", 
31680 +
31681 +                               log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31682                                                 "response already sent out, termination connection",
31683                                                 "connection-fd:", con->fd,
31684                                                 "fcgi-fd:", hctx->fd);
31685 -                               
31686 +
31687                                 connection_set_state(srv, con, CON_STATE_ERROR);
31688                         }
31689  
31690                         /* */
31691 -                       
31692 -                       
31693 +
31694 +
31695                         joblist_append(srv, con);
31696                         return HANDLER_FINISHED;
31697                 }
31698         }
31699 -       
31700 +
31701         if (revents & FDEVENT_OUT) {
31702                 if (hctx->state == FCGI_STATE_CONNECT ||
31703                     hctx->state == FCGI_STATE_WRITE) {
31704                         /* we are allowed to send something out
31705 -                        * 
31706 +                        *
31707                          * 1. in a unfinished connect() call
31708                          * 2. in a unfinished write() call (long POST request)
31709                          */
31710                         return mod_scgi_handle_subrequest(srv, con, p);
31711                 } else {
31712 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
31713 -                                       "got a FDEVENT_OUT and didn't know why:", 
31714 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
31715 +                                       "got a FDEVENT_OUT and didn't know why:",
31716                                         hctx->state);
31717                 }
31718         }
31719 -       
31720 +
31721         /* perhaps this issue is already handled */
31722         if (revents & FDEVENT_HUP) {
31723                 if (hctx->state == FCGI_STATE_CONNECT) {
31724                         /* getoptsock will catch this one (right ?)
31725 -                        * 
31726 -                        * if we are in connect we might get a EINPROGRESS 
31727 -                        * in the first call and a FDEVENT_HUP in the 
31728 +                        *
31729 +                        * if we are in connect we might get a EINPROGRESS
31730 +                        * in the first call and a FDEVENT_HUP in the
31731                          * second round
31732 -                        * 
31733 +                        *
31734                          * FIXME: as it is a bit ugly.
31735 -                        * 
31736 +                        *
31737                          */
31738                         return mod_scgi_handle_subrequest(srv, con, p);
31739                 } else if (hctx->state == FCGI_STATE_READ &&
31740                            hctx->proc->port == 0) {
31741                         /* FIXME:
31742 -                        * 
31743 +                        *
31744                          * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket
31745                          * even if the FCGI_FIN packet is not received yet
31746                          */
31747                 } else {
31748 -                       log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd", 
31749 -                                       "error: unexpected close of scgi connection for", 
31750 +                       log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
31751 +                                       "error: unexpected close of scgi connection for",
31752                                         con->uri.path,
31753 -                                       "(no scgi process on host: ", 
31754 +                                       "(no scgi process on host: ",
31755                                         host->host,
31756 -                                       ", port: ", 
31757 +                                       ", port: ",
31758                                         host->port,
31759                                         " ?)",
31760                                         hctx->state);
31761 -                       
31762 +
31763                         connection_set_state(srv, con, CON_STATE_ERROR);
31764                         scgi_connection_close(srv, hctx);
31765                         joblist_append(srv, con);
31766                 }
31767         } else if (revents & FDEVENT_ERR) {
31768 -               log_error_write(srv, __FILE__, __LINE__, "s", 
31769 +               log_error_write(srv, __FILE__, __LINE__, "s",
31770                                 "fcgi: got a FDEVENT_ERR. Don't know why.");
31771                 /* kill all connections to the scgi process */
31772  
31773 @@ -2628,42 +2628,39 @@
31774                 scgi_connection_close(srv, hctx);
31775                 joblist_append(srv, con);
31776         }
31777 -       
31778 +
31779         return HANDLER_FINISHED;
31780  }
31781 -#define PATCH(x) \
31782 -       p->conf.x = s->x;
31783 +
31784  static int scgi_patch_connection(server *srv, connection *con, plugin_data *p) {
31785         size_t i, j;
31786         plugin_config *s = p->config_storage[0];
31787 -       
31788 -       PATCH(exts);
31789 -       PATCH(debug);
31790 -       
31791 +
31792 +       PATCH_OPTION(exts);
31793 +       PATCH_OPTION(debug);
31794 +
31795         /* skip the first, the global context */
31796         for (i = 1; i < srv->config_context->used; i++) {
31797                 data_config *dc = (data_config *)srv->config_context->data[i];
31798                 s = p->config_storage[i];
31799 -               
31800 +
31801                 /* condition didn't match */
31802                 if (!config_check_cond(srv, con, dc)) continue;
31803 -               
31804 +
31805                 /* merge config */
31806                 for (j = 0; j < dc->value->used; j++) {
31807                         data_unset *du = dc->value->data[j];
31808 -                       
31809 +
31810                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.server"))) {
31811 -                               PATCH(exts);
31812 +                               PATCH_OPTION(exts);
31813                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.debug"))) {
31814 -                               PATCH(debug);
31815 +                               PATCH_OPTION(debug);
31816                         }
31817                 }
31818         }
31819 -       
31820 +
31821         return 0;
31822  }
31823 -#undef PATCH
31824 -
31825  
31826  static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
31827         plugin_data *p = p_d;
31828 @@ -2673,30 +2670,30 @@
31829         size_t k;
31830         buffer *fn;
31831         scgi_extension *extension = NULL;
31832 -       
31833 +
31834         /* Possibly, we processed already this request */
31835         if (con->file_started == 1) return HANDLER_GO_ON;
31836 -       
31837 +
31838         fn = uri_path_handler ? con->uri.path : con->physical.path;
31839  
31840         if (buffer_is_empty(fn)) return HANDLER_GO_ON;
31841  
31842         s_len = fn->used - 1;
31843 -       
31844 +
31845         scgi_patch_connection(srv, con, p);
31846  
31847         /* check if extension matches */
31848         for (k = 0; k < p->conf.exts->used; k++) {
31849                 size_t ct_len;
31850 -               
31851 +
31852                 extension = p->conf.exts->exts[k];
31853 -               
31854 +
31855                 if (extension->key->used == 0) continue;
31856 -               
31857 +
31858                 ct_len = extension->key->used - 1;
31859 -               
31860 +
31861                 if (s_len < ct_len) continue;
31862 -               
31863 +
31864                 /* check extension in the form "/scgi_pattern" */
31865                 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
31866                         break;
31867 @@ -2710,17 +2707,17 @@
31868         if (k == p->conf.exts->used) {
31869                 return HANDLER_GO_ON;
31870         }
31871 -       
31872 +
31873         /* get best server */
31874         for (k = 0, ndx = -1; k < extension->used; k++) {
31875                 scgi_extension_host *host = extension->hosts[k];
31876 -               
31877 +
31878                 /* we should have at least one proc that can do somthing */
31879                 if (host->active_procs == 0) continue;
31880  
31881                 if (used == -1 || host->load < used) {
31882                         used = host->load;
31883 -                       
31884 +
31885                         ndx = k;
31886                 }
31887         }
31888 @@ -2728,12 +2725,12 @@
31889         /* found a server */
31890         if (ndx != -1) {
31891                 scgi_extension_host *host = extension->hosts[ndx];
31892 -               
31893 -               /* 
31894 -                * if check-local is disabled, use the uri.path handler 
31895 -                * 
31896 +
31897 +               /*
31898 +                * if check-local is disabled, use the uri.path handler
31899 +                *
31900                  */
31901 -               
31902 +
31903                 /* init handler-context */
31904                 if (uri_path_handler) {
31905                         if (host->check_local == 0) {
31906 @@ -2741,7 +2738,7 @@
31907                                 char *pathinfo;
31908  
31909                                 hctx = handler_ctx_init();
31910 -                               
31911 +
31912                                 hctx->remote_conn      = con;
31913                                 hctx->plugin_data      = p;
31914                                 hctx->host             = host;
31915 @@ -2749,45 +2746,45 @@
31916  
31917                                 hctx->conf.exts        = p->conf.exts;
31918                                 hctx->conf.debug       = p->conf.debug;
31919 -                               
31920 +
31921                                 con->plugin_ctx[p->id] = hctx;
31922 -                               
31923 +
31924                                 host->load++;
31925 -                               
31926 +
31927                                 con->mode = p->id;
31928  
31929                                 if (con->conf.log_request_handling) {
31930                                         log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_scgi");
31931                                 }
31932  
31933 -                               /* the prefix is the SCRIPT_NAME, 
31934 +                               /* the prefix is the SCRIPT_NAME,
31935                                  * everthing from start to the next slash
31936                                  * this is important for check-local = "disable"
31937 -                                * 
31938 +                                *
31939                                  * if prefix = /admin.fcgi
31940 -                                * 
31941 +                                *
31942                                  * /admin.fcgi/foo/bar
31943 -                                * 
31944 +                                *
31945                                  * SCRIPT_NAME = /admin.fcgi
31946                                  * PATH_INFO   = /foo/bar
31947 -                                * 
31948 +                                *
31949                                  * if prefix = /fcgi-bin/
31950 -                                * 
31951 +                                *
31952                                  * /fcgi-bin/foo/bar
31953 -                                * 
31954 +                                *
31955                                  * SCRIPT_NAME = /fcgi-bin/foo
31956                                  * PATH_INFO   = /bar
31957 -                                * 
31958 +                                *
31959                                  */
31960 -                               
31961 +
31962                                 /* the rewrite is only done for /prefix/? matches */
31963                                 if (extension->key->ptr[0] == '/' &&
31964                                     con->uri.path->used > extension->key->used &&
31965                                     NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) {
31966 -                                       /* rewrite uri.path and pathinfo */ 
31967 -                                       
31968 +                                       /* rewrite uri.path and pathinfo */
31969 +
31970                                         buffer_copy_string(con->request.pathinfo, pathinfo);
31971 -                                       
31972 +
31973                                         con->uri.path->used -= con->request.pathinfo->used - 1;
31974                                         con->uri.path->ptr[con->uri.path->used - 1] = '\0';
31975                                 }
31976 @@ -2796,21 +2793,21 @@
31977                 } else {
31978                         handler_ctx *hctx;
31979                         hctx = handler_ctx_init();
31980 -                       
31981 +
31982                         hctx->remote_conn      = con;
31983                         hctx->plugin_data      = p;
31984                         hctx->host             = host;
31985                         hctx->proc             = NULL;
31986 -                       
31987 +
31988                         hctx->conf.exts        = p->conf.exts;
31989                         hctx->conf.debug       = p->conf.debug;
31990 -                       
31991 +
31992                         con->plugin_ctx[p->id] = hctx;
31993 -                       
31994 +
31995                         host->load++;
31996 -                       
31997 +
31998                         con->mode = p->id;
31999 -                       
32000 +
32001                         if (con->conf.log_request_handling) {
32002                                 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
32003                         }
32004 @@ -2821,11 +2818,11 @@
32005                 /* no handler found */
32006                 buffer_reset(con->physical.path);
32007                 con->http_status = 500;
32008 -               
32009 -               log_error_write(srv, __FILE__, __LINE__,  "sb", 
32010 -                               "no fcgi-handler found for:", 
32011 +
32012 +               log_error_write(srv, __FILE__, __LINE__,  "sb",
32013 +                               "no fcgi-handler found for:",
32014                                 fn);
32015 -               
32016 +
32017                 return HANDLER_FINISHED;
32018         }
32019         return HANDLER_GO_ON;
32020 @@ -2844,19 +2841,19 @@
32021  JOBLIST_FUNC(mod_scgi_handle_joblist) {
32022         plugin_data *p = p_d;
32023         handler_ctx *hctx = con->plugin_ctx[p->id];
32024 -       
32025 +
32026         if (hctx == NULL) return HANDLER_GO_ON;
32027  
32028         if (hctx->fd != -1) {
32029                 switch (hctx->state) {
32030                 case FCGI_STATE_READ:
32031                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
32032 -                       
32033 +
32034                         break;
32035                 case FCGI_STATE_CONNECT:
32036                 case FCGI_STATE_WRITE:
32037                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
32038 -                       
32039 +
32040                         break;
32041                 case FCGI_STATE_INIT:
32042                         /* at reconnect */
32043 @@ -2873,21 +2870,21 @@
32044  
32045  static handler_t scgi_connection_close_callback(server *srv, connection *con, void *p_d) {
32046         plugin_data *p = p_d;
32047 -       
32048 +
32049         return scgi_connection_close(srv, con->plugin_ctx[p->id]);
32050  }
32051  
32052  TRIGGER_FUNC(mod_scgi_handle_trigger) {
32053         plugin_data *p = p_d;
32054         size_t i, j, n;
32055 -       
32056 -       
32057 +
32058 +
32059         /* perhaps we should kill a connect attempt after 10-15 seconds
32060 -        * 
32061 +        *
32062          * currently we wait for the TCP timeout which is on Linux 180 seconds
32063 -        * 
32064 -        * 
32065 -        * 
32066 +        *
32067 +        *
32068 +        *
32069          */
32070  
32071         /* check all childs if they are still up */
32072 @@ -2904,47 +2901,47 @@
32073                         scgi_extension *ex;
32074  
32075                         ex = exts->exts[j];
32076 -                       
32077 +
32078                         for (n = 0; n < ex->used; n++) {
32079 -                               
32080 +
32081                                 scgi_proc *proc;
32082                                 unsigned long sum_load = 0;
32083                                 scgi_extension_host *host;
32084 -                               
32085 +
32086                                 host = ex->hosts[n];
32087 -                               
32088 +
32089                                 scgi_restart_dead_procs(srv, p, host);
32090 -                               
32091 +
32092                                 for (proc = host->first; proc; proc = proc->next) {
32093                                         sum_load += proc->load;
32094                                 }
32095 -                               
32096 +
32097                                 if (host->num_procs &&
32098                                     host->num_procs < host->max_procs &&
32099                                     (sum_load / host->num_procs) > host->max_load_per_proc) {
32100                                         /* overload, spawn new child */
32101                                         scgi_proc *fp = NULL;
32102 -                                       
32103 +
32104                                         if (p->conf.debug) {
32105 -                                               log_error_write(srv, __FILE__, __LINE__, "s", 
32106 +                                               log_error_write(srv, __FILE__, __LINE__, "s",
32107                                                                 "overload detected, spawning a new child");
32108                                         }
32109 -                                       
32110 +
32111                                         for (fp = host->unused_procs; fp && fp->pid != 0; fp = fp->next);
32112 -                                       
32113 +
32114                                         if (fp) {
32115                                                 if (fp == host->unused_procs) host->unused_procs = fp->next;
32116 -                                               
32117 +
32118                                                 if (fp->next) fp->next->prev = NULL;
32119 -                                               
32120 +
32121                                                 host->max_id++;
32122                                         } else {
32123                                                 fp = scgi_process_init();
32124                                                 fp->id = host->max_id++;
32125                                         }
32126 -                                       
32127 +
32128                                         host->num_procs++;
32129 -                                       
32130 +
32131                                         if (buffer_is_empty(host->unixsocket)) {
32132                                                 fp->port = host->port + fp->id;
32133                                         } else {
32134 @@ -2952,13 +2949,13 @@
32135                                                 buffer_append_string(fp->socket, "-");
32136                                                 buffer_append_long(fp->socket, fp->id);
32137                                         }
32138 -                                       
32139 +
32140                                         if (scgi_spawn_connection(srv, p, host, fp)) {
32141                                                 log_error_write(srv, __FILE__, __LINE__, "s",
32142                                                                 "ERROR: spawning fcgi failed.");
32143                                                 return HANDLER_ERROR;
32144                                         }
32145 -                                       
32146 +
32147                                         fp->prev = NULL;
32148                                         fp->next = host->first;
32149                                         if (host->first) {
32150 @@ -2966,56 +2963,57 @@
32151                                         }
32152                                         host->first = fp;
32153                                 }
32154 -                               
32155 +
32156                                 for (proc = host->first; proc; proc = proc->next) {
32157                                         if (proc->load != 0) break;
32158                                         if (host->num_procs <= host->min_procs) break;
32159                                         if (proc->pid == 0) continue;
32160 -                                       
32161 +#ifndef _WIN32
32162                                         if (srv->cur_ts - proc->last_used > host->idle_timeout) {
32163                                                 /* a proc is idling for a long time now,
32164                                                  * terminated it */
32165 -                                               
32166 +
32167                                                 if (p->conf.debug) {
32168 -                                                       log_error_write(srv, __FILE__, __LINE__, "ssbsd", 
32169 -                                                                       "idle-timeout reached, terminating child:", 
32170 -                                                                       "socket:", proc->socket, 
32171 +                                                       log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32172 +                                                                       "idle-timeout reached, terminating child:",
32173 +                                                                       "socket:", proc->socket,
32174                                                                         "pid", proc->pid);
32175                                                 }
32176 -                                               
32177 -                                               
32178 +
32179 +
32180                                                 if (proc->next) proc->next->prev = proc->prev;
32181                                                 if (proc->prev) proc->prev->next = proc->next;
32182 -                                               
32183 +
32184                                                 if (proc->prev == NULL) host->first = proc->next;
32185 -                                               
32186 +
32187                                                 proc->prev = NULL;
32188                                                 proc->next = host->unused_procs;
32189 -                                               
32190 +
32191                                                 if (host->unused_procs) host->unused_procs->prev = proc;
32192                                                 host->unused_procs = proc;
32193 -                                               
32194 +
32195                                                 kill(proc->pid, SIGTERM);
32196 -                                               
32197 +
32198                                                 proc->state = PROC_STATE_KILLED;
32199 -                                               
32200 -                                               log_error_write(srv, __FILE__, __LINE__, "ssbsd", 
32201 -                                                                       "killed:", 
32202 -                                                                       "socket:", proc->socket, 
32203 +
32204 +                                               log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32205 +                                                                       "killed:",
32206 +                                                                       "socket:", proc->socket,
32207                                                                         "pid", proc->pid);
32208 -                                               
32209 +
32210                                                 host->num_procs--;
32211 -                                               
32212 +
32213                                                 /* proc is now in unused, let the next second handle the next process */
32214                                                 break;
32215 -                                       }       
32216 +                                       }
32217 +#endif
32218                                 }
32219 -                               
32220 +
32221                                 for (proc = host->unused_procs; proc; proc = proc->next) {
32222                                         int status;
32223 -                                       
32224 +
32225                                         if (proc->pid == 0) continue;
32226 -                                       
32227 +#ifndef _WIN32
32228                                         switch (waitpid(proc->pid, &status, WNOHANG)) {
32229                                         case 0:
32230                                                 /* child still running after timeout, good */
32231 @@ -3023,10 +3021,10 @@
32232                                         case -1:
32233                                                 if (errno != EINTR) {
32234                                                         /* no PID found ? should never happen */
32235 -                                                       log_error_write(srv, __FILE__, __LINE__, "sddss", 
32236 +                                                       log_error_write(srv, __FILE__, __LINE__, "sddss",
32237                                                                         "pid ", proc->pid, proc->state,
32238                                                                         "not found:", strerror(errno));
32239 -                                                       
32240 +
32241  #if 0
32242                                                         if (errno == ECHILD) {
32243                                                                 /* someone else has cleaned up for us */
32244 @@ -3040,25 +3038,26 @@
32245                                                 /* the child should not terminate at all */
32246                                                 if (WIFEXITED(status)) {
32247                                                         if (proc->state != PROC_STATE_KILLED) {
32248 -                                                               log_error_write(srv, __FILE__, __LINE__, "sdb", 
32249 -                                                                               "child exited:", 
32250 +                                                               log_error_write(srv, __FILE__, __LINE__, "sdb",
32251 +                                                                               "child exited:",
32252                                                                                 WEXITSTATUS(status), proc->socket);
32253                                                         }
32254                                                 } else if (WIFSIGNALED(status)) {
32255                                                         if (WTERMSIG(status) != SIGTERM) {
32256 -                                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
32257 -                                                                               "child signaled:", 
32258 +                                                               log_error_write(srv, __FILE__, __LINE__, "sd",
32259 +                                                                               "child signaled:",
32260                                                                                 WTERMSIG(status));
32261                                                         }
32262                                                 } else {
32263 -                                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
32264 -                                                                       "child died somehow:", 
32265 +                                                       log_error_write(srv, __FILE__, __LINE__, "sd",
32266 +                                                                       "child died somehow:",
32267                                                                         status);
32268                                                 }
32269                                                 proc->pid = 0;
32270                                                 proc->state = PROC_STATE_UNSET;
32271                                                 host->max_id--;
32272                                         }
32273 +#endif
32274                                 }
32275                         }
32276                 }
32277 @@ -3082,8 +3081,8 @@
32278         p->handle_subrequest       = mod_scgi_handle_subrequest;
32279         p->handle_joblist          = mod_scgi_handle_joblist;
32280         p->handle_trigger          = mod_scgi_handle_trigger;
32281 -       
32282 +
32283         p->data         = NULL;
32284 -       
32285 +
32286         return 0;
32287  }
32288 --- lighttpd-1.4.11/src/mod_secure_download.c   2005-12-14 14:37:29.000000000 +0200
32289 +++ lighttpd-1.4.12/src/mod_secure_download.c   2006-07-11 22:07:51.000000000 +0300
32290 @@ -25,7 +25,7 @@
32291  #ifdef USE_OPENSSL
32292  #define IN const
32293  #else
32294 -#define IN 
32295 +#define IN
32296  #endif
32297  #define OUT
32298  
32299 @@ -36,28 +36,28 @@
32300         buffer *doc_root;
32301         buffer *secret;
32302         buffer *uri_prefix;
32303 -       
32304 +
32305         unsigned short timeout;
32306  } plugin_config;
32307  
32308  typedef struct {
32309         PLUGIN_DATA;
32310 -       
32311 +
32312         buffer *md5;
32313 -       
32314 +
32315         plugin_config **config_storage;
32316 -       
32317 -       plugin_config conf; 
32318 +
32319 +       plugin_config conf;
32320  } plugin_data;
32321  
32322  /* init the plugin data */
32323  INIT_FUNC(mod_secdownload_init) {
32324         plugin_data *p;
32325 -       
32326 +
32327         p = calloc(1, sizeof(*p));
32328 -       
32329 +
32330         p->md5 = buffer_init();
32331 -       
32332 +
32333         return p;
32334  }
32335  
32336 @@ -65,27 +65,27 @@
32337  FREE_FUNC(mod_secdownload_free) {
32338         plugin_data *p = p_d;
32339         UNUSED(srv);
32340 -       
32341 +
32342         if (!p) return HANDLER_GO_ON;
32343 -       
32344 +
32345         if (p->config_storage) {
32346                 size_t i;
32347                 for (i = 0; i < srv->config_context->used; i++) {
32348                         plugin_config *s = p->config_storage[i];
32349 -                       
32350 +
32351                         buffer_free(s->secret);
32352                         buffer_free(s->doc_root);
32353                         buffer_free(s->uri_prefix);
32354 -                       
32355 +
32356                         free(s);
32357                 }
32358                 free(p->config_storage);
32359         }
32360 -       
32361 +
32362         buffer_free(p->md5);
32363 -       
32364 +
32365         free(p);
32366 -       
32367 +
32368         return HANDLER_GO_ON;
32369  }
32370  
32371 @@ -94,107 +94,103 @@
32372  SETDEFAULTS_FUNC(mod_secdownload_set_defaults) {
32373         plugin_data *p = p_d;
32374         size_t i = 0;
32375 -       
32376 -       config_values_t cv[] = { 
32377 +
32378 +       config_values_t cv[] = {
32379                 { "secdownload.secret",            NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
32380                 { "secdownload.document-root",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
32381                 { "secdownload.uri-prefix",        NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
32382                 { "secdownload.timeout",           NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 3 */
32383                 { NULL,                            NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
32384         };
32385 -       
32386 +
32387         if (!p) return HANDLER_ERROR;
32388 -       
32389 +
32390         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32391 -       
32392 +
32393         for (i = 0; i < srv->config_context->used; i++) {
32394                 plugin_config *s;
32395 -               
32396 +
32397                 s = calloc(1, sizeof(plugin_config));
32398                 s->secret        = buffer_init();
32399                 s->doc_root      = buffer_init();
32400                 s->uri_prefix    = buffer_init();
32401                 s->timeout       = 60;
32402 -               
32403 +
32404                 cv[0].destination = s->secret;
32405                 cv[1].destination = s->doc_root;
32406                 cv[2].destination = s->uri_prefix;
32407                 cv[3].destination = &(s->timeout);
32408 -               
32409 +
32410                 p->config_storage[i] = s;
32411 -       
32412 +
32413                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
32414                         return HANDLER_ERROR;
32415                 }
32416         }
32417 -       
32418 +
32419         return HANDLER_GO_ON;
32420  }
32421  
32422  /**
32423   * checks if the supplied string is a MD5 string
32424 - * 
32425 + *
32426   * @param str a possible MD5 string
32427   * @return if the supplied string is a valid MD5 string 1 is returned otherwise 0
32428   */
32429  
32430  int is_hex_len(const char *str, size_t len) {
32431         size_t i;
32432 -       
32433 +
32434         if (NULL == str) return 0;
32435 -       
32436 +
32437         for (i = 0; i < len && *str; i++, str++) {
32438                 /* illegal characters */
32439                 if (!((*str >= '0' && *str <= '9') ||
32440                       (*str >= 'a' && *str <= 'f') ||
32441 -                     (*str >= 'A' && *str <= 'F')) 
32442 +                     (*str >= 'A' && *str <= 'F'))
32443                     ) {
32444                         return 0;
32445                 }
32446         }
32447 -       
32448 +
32449         return i == len;
32450  }
32451  
32452 -#define PATCH(x) \
32453 -       p->conf.x = s->x;
32454  static int mod_secdownload_patch_connection(server *srv, connection *con, plugin_data *p) {
32455         size_t i, j;
32456         plugin_config *s = p->config_storage[0];
32457 -       
32458 -       PATCH(secret);
32459 -       PATCH(doc_root);
32460 -       PATCH(uri_prefix);
32461 -       PATCH(timeout);
32462 -       
32463 +
32464 +       PATCH_OPTION(secret);
32465 +       PATCH_OPTION(doc_root);
32466 +       PATCH_OPTION(uri_prefix);
32467 +       PATCH_OPTION(timeout);
32468 +
32469         /* skip the first, the global context */
32470         for (i = 1; i < srv->config_context->used; i++) {
32471                 data_config *dc = (data_config *)srv->config_context->data[i];
32472                 s = p->config_storage[i];
32473 -               
32474 +
32475                 /* condition didn't match */
32476                 if (!config_check_cond(srv, con, dc)) continue;
32477 -               
32478 +
32479                 /* merge config */
32480                 for (j = 0; j < dc->value->used; j++) {
32481                         data_unset *du = dc->value->data[j];
32482 -                       
32483 +
32484                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.secret"))) {
32485 -                               PATCH(secret);
32486 +                               PATCH_OPTION(secret);
32487                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.document-root"))) {
32488 -                               PATCH(doc_root);
32489 +                               PATCH_OPTION(doc_root);
32490                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.uri-prefix"))) {
32491 -                               PATCH(uri_prefix);
32492 +                               PATCH_OPTION(uri_prefix);
32493                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.timeout"))) {
32494 -                               PATCH(timeout);
32495 +                               PATCH_OPTION(timeout);
32496                         }
32497                 }
32498         }
32499 -       
32500 +
32501         return 0;
32502  }
32503 -#undef PATCH
32504 -
32505  
32506  URIHANDLER_FUNC(mod_secdownload_uri_handler) {
32507         plugin_data *p = p_d;
32508 @@ -203,88 +199,88 @@
32509         const char *rel_uri, *ts_str, *md5_str;
32510         time_t ts = 0;
32511         size_t i;
32512 -       
32513 +
32514         if (con->uri.path->used == 0) return HANDLER_GO_ON;
32515 -       
32516 +
32517         mod_secdownload_patch_connection(srv, con, p);
32518  
32519         if (buffer_is_empty(p->conf.uri_prefix)) return HANDLER_GO_ON;
32520 -       
32521 +
32522         if (buffer_is_empty(p->conf.secret)) {
32523                 log_error_write(srv, __FILE__, __LINE__, "s",
32524                                 "secdownload.secret has to be set");
32525                 return HANDLER_ERROR;
32526         }
32527 -       
32528 +
32529         if (buffer_is_empty(p->conf.doc_root)) {
32530                 log_error_write(srv, __FILE__, __LINE__, "s",
32531                                 "secdownload.document-root has to be set");
32532                 return HANDLER_ERROR;
32533         }
32534 -       
32535 -       /* 
32536 +
32537 +       /*
32538          *  /<uri-prefix>[a-f0-9]{32}/[a-f0-9]{8}/<rel-path>
32539          */
32540 -       
32541 +
32542         if (0 != strncmp(con->uri.path->ptr, p->conf.uri_prefix->ptr, p->conf.uri_prefix->used - 1)) return HANDLER_GO_ON;
32543 -       
32544 +
32545         md5_str = con->uri.path->ptr + p->conf.uri_prefix->used - 1;
32546 -       
32547 +
32548         if (!is_hex_len(md5_str, 32)) return HANDLER_GO_ON;
32549         if (*(md5_str + 32) != '/') return HANDLER_GO_ON;
32550 -       
32551 +
32552         ts_str = md5_str + 32 + 1;
32553 -       
32554 +
32555         if (!is_hex_len(ts_str, 8)) return HANDLER_GO_ON;
32556         if (*(ts_str + 8) != '/') return HANDLER_GO_ON;
32557 -       
32558 +
32559         for (i = 0; i < 8; i++) {
32560                 ts = (ts << 4) + hex2int(*(ts_str + i));
32561         }
32562 -       
32563 +
32564         /* timed-out */
32565 -       if (srv->cur_ts - ts > p->conf.timeout || 
32566 +       if (srv->cur_ts - ts > p->conf.timeout ||
32567             srv->cur_ts - ts < -p->conf.timeout) {
32568                 con->http_status = 408;
32569 -               
32570 +
32571                 return HANDLER_FINISHED;
32572         }
32573 -       
32574 +
32575         rel_uri = ts_str + 8;
32576 -       
32577 -       /* checking MD5 
32578 -        * 
32579 +
32580 +       /* checking MD5
32581 +        *
32582          * <secret><rel-path><timestamp-hex>
32583          */
32584 -       
32585 +
32586         buffer_copy_string_buffer(p->md5, p->conf.secret);
32587         buffer_append_string(p->md5, rel_uri);
32588         buffer_append_string_len(p->md5, ts_str, 8);
32589 -       
32590 +
32591         MD5_Init(&Md5Ctx);
32592         MD5_Update(&Md5Ctx, (unsigned char *)p->md5->ptr, p->md5->used - 1);
32593         MD5_Final(HA1, &Md5Ctx);
32594 -       
32595 +
32596         buffer_copy_string_hex(p->md5, (char *)HA1, 16);
32597 -       
32598 +
32599         if (0 != strncmp(md5_str, p->md5->ptr, 32)) {
32600                 con->http_status = 403;
32601 -               
32602 -               log_error_write(srv, __FILE__, __LINE__, "sss", 
32603 +
32604 +               log_error_write(srv, __FILE__, __LINE__, "sss",
32605                                 "md5 invalid:",
32606                                 md5_str, p->md5->ptr);
32607 -               
32608 +
32609                 return HANDLER_FINISHED;
32610         }
32611 -       
32612 +
32613         /* starting with the last / we should have relative-path to the docroot
32614          */
32615 -       
32616 +
32617         buffer_copy_string_buffer(con->physical.doc_root, p->conf.doc_root);
32618         buffer_copy_string(con->physical.rel_path, rel_uri);
32619         buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
32620         buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
32621 -       
32622 +
32623         return HANDLER_GO_ON;
32624  }
32625  
32626 @@ -293,13 +289,13 @@
32627  int mod_secdownload_plugin_init(plugin *p) {
32628         p->version     = LIGHTTPD_VERSION_ID;
32629         p->name        = buffer_init_string("secdownload");
32630 -       
32631 +
32632         p->init        = mod_secdownload_init;
32633         p->handle_physical  = mod_secdownload_uri_handler;
32634         p->set_defaults  = mod_secdownload_set_defaults;
32635         p->cleanup     = mod_secdownload_free;
32636 -       
32637 +
32638         p->data        = NULL;
32639 -       
32640 +
32641         return 0;
32642  }
32643 --- lighttpd-1.4.11/src/mod_setenv.c    2006-01-14 20:33:12.000000000 +0200
32644 +++ lighttpd-1.4.12/src/mod_setenv.c    2006-07-11 22:07:53.000000000 +0300
32645 @@ -18,25 +18,25 @@
32646  typedef struct {
32647         array *request_header;
32648         array *response_header;
32649 -       
32650 +
32651         array *environment;
32652  } plugin_config;
32653  
32654  typedef struct {
32655         PLUGIN_DATA;
32656 -       
32657 +
32658         plugin_config **config_storage;
32659 -       
32660 -       plugin_config conf; 
32661 +
32662 +       plugin_config conf;
32663  } plugin_data;
32664  
32665  static handler_ctx * handler_ctx_init() {
32666         handler_ctx * hctx;
32667 -       
32668 +
32669         hctx = calloc(1, sizeof(*hctx));
32670 -       
32671 +
32672         hctx->handled = 0;
32673 -       
32674 +
32675         return hctx;
32676  }
32677  
32678 @@ -48,36 +48,36 @@
32679  /* init the plugin data */
32680  INIT_FUNC(mod_setenv_init) {
32681         plugin_data *p;
32682 -       
32683 +
32684         p = calloc(1, sizeof(*p));
32685 -       
32686 +
32687         return p;
32688  }
32689  
32690  /* detroy the plugin data */
32691  FREE_FUNC(mod_setenv_free) {
32692         plugin_data *p = p_d;
32693 -       
32694 +
32695         UNUSED(srv);
32696  
32697         if (!p) return HANDLER_GO_ON;
32698 -       
32699 +
32700         if (p->config_storage) {
32701                 size_t i;
32702                 for (i = 0; i < srv->config_context->used; i++) {
32703                         plugin_config *s = p->config_storage[i];
32704 -                       
32705 +
32706                         array_free(s->request_header);
32707                         array_free(s->response_header);
32708                         array_free(s->environment);
32709 -                       
32710 +
32711                         free(s);
32712                 }
32713                 free(p->config_storage);
32714         }
32715 -       
32716 +
32717         free(p);
32718 -       
32719 +
32720         return HANDLER_GO_ON;
32721  }
32722  
32723 @@ -86,86 +86,83 @@
32724  SETDEFAULTS_FUNC(mod_setenv_set_defaults) {
32725         plugin_data *p = p_d;
32726         size_t i = 0;
32727 -       
32728 -       config_values_t cv[] = { 
32729 +
32730 +       config_values_t cv[] = {
32731                 { "setenv.add-request-header",  NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
32732                 { "setenv.add-response-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
32733                 { "setenv.add-environment",     NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
32734                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
32735         };
32736 -       
32737 +
32738         if (!p) return HANDLER_ERROR;
32739 -       
32740 +
32741         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32742 -       
32743 +
32744         for (i = 0; i < srv->config_context->used; i++) {
32745                 plugin_config *s;
32746 -               
32747 +
32748                 s = calloc(1, sizeof(plugin_config));
32749                 s->request_header   = array_init();
32750                 s->response_header  = array_init();
32751                 s->environment      = array_init();
32752 -               
32753 +
32754                 cv[0].destination = s->request_header;
32755                 cv[1].destination = s->response_header;
32756                 cv[2].destination = s->environment;
32757 -               
32758 +
32759                 p->config_storage[i] = s;
32760 -       
32761 +
32762                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
32763                         return HANDLER_ERROR;
32764                 }
32765         }
32766 -       
32767 +
32768         return HANDLER_GO_ON;
32769  }
32770  
32771 -#define PATCH(x) \
32772 -       p->conf.x = s->x;
32773  static int mod_setenv_patch_connection(server *srv, connection *con, plugin_data *p) {
32774         size_t i, j;
32775         plugin_config *s = p->config_storage[0];
32776 -       
32777 -       PATCH(request_header);
32778 -       PATCH(response_header);
32779 -       PATCH(environment);
32780 -       
32781 +
32782 +       PATCH_OPTION(request_header);
32783 +       PATCH_OPTION(response_header);
32784 +       PATCH_OPTION(environment);
32785 +
32786         /* skip the first, the global context */
32787         for (i = 1; i < srv->config_context->used; i++) {
32788                 data_config *dc = (data_config *)srv->config_context->data[i];
32789                 s = p->config_storage[i];
32790 -               
32791 +
32792                 /* condition didn't match */
32793                 if (!config_check_cond(srv, con, dc)) continue;
32794 -               
32795 +
32796                 /* merge config */
32797                 for (j = 0; j < dc->value->used; j++) {
32798                         data_unset *du = dc->value->data[j];
32799 -                       
32800 +
32801                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-request-header"))) {
32802 -                               PATCH(request_header);
32803 +                               PATCH_OPTION(request_header);
32804                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-response-header"))) {
32805 -                               PATCH(response_header);
32806 +                               PATCH_OPTION(response_header);
32807                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-environment"))) {
32808 -                               PATCH(environment);
32809 +                               PATCH_OPTION(environment);
32810                         }
32811                 }
32812         }
32813 -       
32814 +
32815         return 0;
32816  }
32817 -#undef PATCH
32818  
32819  URIHANDLER_FUNC(mod_setenv_uri_handler) {
32820         plugin_data *p = p_d;
32821         size_t k;
32822         handler_ctx *hctx;
32823 -       
32824 +
32825         if (con->plugin_ctx[p->id]) {
32826                 hctx = con->plugin_ctx[p->id];
32827         } else {
32828                 hctx = handler_ctx_init();
32829 -                               
32830 +
32831                 con->plugin_ctx[p->id] = hctx;
32832         }
32833  
32834 @@ -180,52 +177,52 @@
32835         for (k = 0; k < p->conf.request_header->used; k++) {
32836                 data_string *ds = (data_string *)p->conf.request_header->data[k];
32837                 data_string *ds_dst;
32838 -               
32839 +
32840                 if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
32841                         ds_dst = data_string_init();
32842                 }
32843 -               
32844 +
32845                 buffer_copy_string_buffer(ds_dst->key, ds->key);
32846                 buffer_copy_string_buffer(ds_dst->value, ds->value);
32847 -               
32848 +
32849                 array_insert_unique(con->request.headers, (data_unset *)ds_dst);
32850         }
32851 -       
32852 +
32853         for (k = 0; k < p->conf.environment->used; k++) {
32854                 data_string *ds = (data_string *)p->conf.environment->data[k];
32855                 data_string *ds_dst;
32856 -               
32857 +
32858                 if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
32859                         ds_dst = data_string_init();
32860                 }
32861 -               
32862 +
32863                 buffer_copy_string_buffer(ds_dst->key, ds->key);
32864                 buffer_copy_string_buffer(ds_dst->value, ds->value);
32865 -               
32866 +
32867                 array_insert_unique(con->environment, (data_unset *)ds_dst);
32868         }
32869 -       
32870 +
32871         for (k = 0; k < p->conf.response_header->used; k++) {
32872                 data_string *ds = (data_string *)p->conf.response_header->data[k];
32873 -               
32874 +
32875                 response_header_insert(srv, con, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
32876         }
32877 -       
32878 +
32879         /* not found */
32880         return HANDLER_GO_ON;
32881  }
32882  
32883  REQUESTDONE_FUNC(mod_setenv_reset) {
32884         plugin_data *p = p_d;
32885 -       
32886 +
32887         UNUSED(srv);
32888 -       
32889 +
32890         if (con->plugin_ctx[p->id]) {
32891                 handler_ctx_free(con->plugin_ctx[p->id]);
32892                 con->plugin_ctx[p->id] = NULL;
32893         }
32894  
32895 -       return HANDLER_GO_ON;   
32896 +       return HANDLER_GO_ON;
32897  }
32898  
32899  /* this function is called at dlopen() time and inits the callbacks */
32900 @@ -233,15 +230,15 @@
32901  int mod_setenv_plugin_init(plugin *p) {
32902         p->version     = LIGHTTPD_VERSION_ID;
32903         p->name        = buffer_init_string("setenv");
32904 -       
32905 +
32906         p->init        = mod_setenv_init;
32907         p->handle_uri_clean  = mod_setenv_uri_handler;
32908         p->set_defaults  = mod_setenv_set_defaults;
32909         p->cleanup     = mod_setenv_free;
32910 -       
32911 +
32912         p->handle_request_done  = mod_setenv_reset;
32913  
32914         p->data        = NULL;
32915 -       
32916 +
32917         return 0;
32918  }
32919 --- lighttpd-1.4.11/src/mod_simple_vhost.c      2005-11-18 15:16:13.000000000 +0200
32920 +++ lighttpd-1.4.12/src/mod_simple_vhost.c      2006-07-11 22:07:52.000000000 +0300
32921 @@ -10,6 +10,8 @@
32922  
32923  #include "plugin.h"
32924  
32925 +#include "sys-files.h"
32926 +
32927  #ifdef HAVE_CONFIG_H
32928  #include "config.h"
32929  #endif
32930 @@ -18,7 +20,7 @@
32931         buffer *server_root;
32932         buffer *default_host;
32933         buffer *document_root;
32934 -       
32935 +
32936         buffer *docroot_cache_key;
32937         buffer *docroot_cache_value;
32938         buffer *docroot_cache_servername;
32939 @@ -28,138 +30,138 @@
32940  
32941  typedef struct {
32942         PLUGIN_DATA;
32943 -       
32944 +
32945         buffer *doc_root;
32946 -       
32947 +
32948         plugin_config **config_storage;
32949 -       plugin_config conf; 
32950 +       plugin_config conf;
32951  } plugin_data;
32952  
32953  INIT_FUNC(mod_simple_vhost_init) {
32954         plugin_data *p;
32955 -       
32956 +
32957         p = calloc(1, sizeof(*p));
32958 -       
32959 +
32960         p->doc_root = buffer_init();
32961 -       
32962 +
32963         return p;
32964  }
32965  
32966  FREE_FUNC(mod_simple_vhost_free) {
32967         plugin_data *p = p_d;
32968 -       
32969 +
32970         UNUSED(srv);
32971  
32972         if (!p) return HANDLER_GO_ON;
32973 -       
32974 +
32975         if (p->config_storage) {
32976                 size_t i;
32977                 for (i = 0; i < srv->config_context->used; i++) {
32978                         plugin_config *s = p->config_storage[i];
32979 -                       
32980 +
32981                         buffer_free(s->document_root);
32982                         buffer_free(s->default_host);
32983                         buffer_free(s->server_root);
32984 -                       
32985 +
32986                         buffer_free(s->docroot_cache_key);
32987                         buffer_free(s->docroot_cache_value);
32988                         buffer_free(s->docroot_cache_servername);
32989 -                       
32990 +
32991                         free(s);
32992                 }
32993 -       
32994 +
32995                 free(p->config_storage);
32996         }
32997 -       
32998 +
32999         buffer_free(p->doc_root);
33000 -       
33001 +
33002         free(p);
33003 -       
33004 +
33005         return HANDLER_GO_ON;
33006  }
33007  
33008  SETDEFAULTS_FUNC(mod_simple_vhost_set_defaults) {
33009         plugin_data *p = p_d;
33010         size_t i;
33011 -       
33012 -       config_values_t cv[] = { 
33013 +
33014 +       config_values_t cv[] = {
33015                 { "simple-vhost.server-root",       NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
33016                 { "simple-vhost.default-host",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
33017                 { "simple-vhost.document-root",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
33018                 { "simple-vhost.debug",             NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
33019                 { NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33020         };
33021 -       
33022 +
33023         if (!p) return HANDLER_ERROR;
33024 -       
33025 +
33026         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33027 -       
33028 +
33029         for (i = 0; i < srv->config_context->used; i++) {
33030                 plugin_config *s;
33031 -               
33032 +
33033                 s = calloc(1, sizeof(plugin_config));
33034 -               
33035 +
33036                 s->server_root = buffer_init();
33037                 s->default_host = buffer_init();
33038                 s->document_root = buffer_init();
33039 -               
33040 +
33041                 s->docroot_cache_key = buffer_init();
33042                 s->docroot_cache_value = buffer_init();
33043                 s->docroot_cache_servername = buffer_init();
33044  
33045                 s->debug = 0;
33046 -               
33047 +
33048                 cv[0].destination = s->server_root;
33049                 cv[1].destination = s->default_host;
33050                 cv[2].destination = s->document_root;
33051                 cv[3].destination = &(s->debug);
33052 -               
33053 -               
33054 +
33055 +
33056                 p->config_storage[i] = s;
33057 -               
33058 +
33059                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
33060                         return HANDLER_ERROR;
33061                 }
33062         }
33063 -       
33064 +
33065         return HANDLER_GO_ON;
33066  }
33067  
33068  static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer *out, buffer *host) {
33069         stat_cache_entry *sce = NULL;
33070 -       
33071 +
33072         buffer_prepare_copy(out, 128);
33073  
33074         if (p->conf.server_root->used) {
33075                 buffer_copy_string_buffer(out, p->conf.server_root);
33076 -               
33077 +
33078                 if (host->used) {
33079                         /* a hostname has to start with a alpha-numerical character
33080                          * and must not contain a slash "/"
33081                          */
33082                         char *dp;
33083 -                       
33084 -                       BUFFER_APPEND_SLASH(out);
33085 -                       
33086 +
33087 +                       PATHNAME_APPEND_SLASH(out);
33088 +
33089                         if (NULL == (dp = strchr(host->ptr, ':'))) {
33090                                 buffer_append_string_buffer(out, host);
33091                         } else {
33092                                 buffer_append_string_len(out, host->ptr, dp - host->ptr);
33093                         }
33094                 }
33095 -               BUFFER_APPEND_SLASH(out);
33096 -               
33097 +               PATHNAME_APPEND_SLASH(out);
33098 +
33099                 if (p->conf.document_root->used > 2 && p->conf.document_root->ptr[0] == '/') {
33100                         buffer_append_string_len(out, p->conf.document_root->ptr + 1, p->conf.document_root->used - 2);
33101                 } else {
33102                         buffer_append_string_buffer(out, p->conf.document_root);
33103 -                       BUFFER_APPEND_SLASH(out);
33104 +                       PATHNAME_APPEND_SLASH(out);
33105                 }
33106         } else {
33107                 buffer_copy_string_buffer(out, con->conf.document_root);
33108 -               BUFFER_APPEND_SLASH(out);
33109 +               PATHNAME_APPEND_SLASH(out);
33110         }
33111 -       
33112 +
33113         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, out, &sce)) {
33114                 if (p->conf.debug) {
33115                         log_error_write(srv, __FILE__, __LINE__, "sb",
33116 @@ -169,57 +171,53 @@
33117         } else if (!S_ISDIR(sce->st.st_mode)) {
33118                 return -1;
33119         }
33120 -       
33121 +
33122         return 0;
33123  }
33124  
33125 -
33126 -#define PATCH(x) \
33127 -       p->conf.x = s->x;
33128  static int mod_simple_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
33129         size_t i, j;
33130         plugin_config *s = p->config_storage[0];
33131 -       
33132 -       PATCH(server_root);
33133 -       PATCH(default_host);
33134 -       PATCH(document_root);
33135 -       
33136 -       PATCH(docroot_cache_key);
33137 -       PATCH(docroot_cache_value);
33138 -       PATCH(docroot_cache_servername);
33139  
33140 -       PATCH(debug);
33141 -       
33142 +       PATCH_OPTION(server_root);
33143 +       PATCH_OPTION(default_host);
33144 +       PATCH_OPTION(document_root);
33145 +
33146 +       PATCH_OPTION(docroot_cache_key);
33147 +       PATCH_OPTION(docroot_cache_value);
33148 +       PATCH_OPTION(docroot_cache_servername);
33149 +
33150 +       PATCH_OPTION(debug);
33151 +
33152         /* skip the first, the global context */
33153         for (i = 1; i < srv->config_context->used; i++) {
33154                 data_config *dc = (data_config *)srv->config_context->data[i];
33155                 s = p->config_storage[i];
33156 -               
33157 +
33158                 /* condition didn't match */
33159                 if (!config_check_cond(srv, con, dc)) continue;
33160 -               
33161 +
33162                 /* merge config */
33163                 for (j = 0; j < dc->value->used; j++) {
33164                         data_unset *du = dc->value->data[j];
33165 -                       
33166 +
33167                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.server-root"))) {
33168 -                               PATCH(server_root);
33169 -                               PATCH(docroot_cache_key);
33170 -                               PATCH(docroot_cache_value);
33171 -                               PATCH(docroot_cache_servername);
33172 +                               PATCH_OPTION(server_root);
33173 +                               PATCH_OPTION(docroot_cache_key);
33174 +                               PATCH_OPTION(docroot_cache_value);
33175 +                               PATCH_OPTION(docroot_cache_servername);
33176                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.default-host"))) {
33177 -                               PATCH(default_host);
33178 +                               PATCH_OPTION(default_host);
33179                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.document-root"))) {
33180 -                               PATCH(document_root);
33181 +                               PATCH_OPTION(document_root);
33182                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.debug"))) {
33183 -                               PATCH(debug);
33184 +                               PATCH_OPTION(debug);
33185                         }
33186                 }
33187         }
33188 -       
33189 +
33190         return 0;
33191  }
33192 -#undef PATCH
33193  
33194  static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_data) {
33195         plugin_data *p = p_data;
33196 @@ -227,12 +225,12 @@
33197         /*
33198          * cache the last successfull translation from hostname (authority) to docroot
33199          * - this saves us a stat() call
33200 -        * 
33201 +        *
33202          */
33203 -       
33204 +
33205         mod_simple_vhost_patch_connection(srv, con, p);
33206 -       
33207 -       if (p->conf.docroot_cache_key->used && 
33208 +
33209 +       if (p->conf.docroot_cache_key->used &&
33210             con->uri.authority->used &&
33211             buffer_is_equal(p->conf.docroot_cache_key, con->uri.authority)) {
33212                 /* cache hit */
33213 @@ -243,8 +241,8 @@
33214                 if ((con->uri.authority->used == 0) ||
33215                     build_doc_root(srv, con, p, p->doc_root, con->uri.authority)) {
33216                         /* not found, fallback the default-host */
33217 -                       if (build_doc_root(srv, con, p, 
33218 -                                          p->doc_root, 
33219 +                       if (build_doc_root(srv, con, p,
33220 +                                          p->doc_root,
33221                                            p->conf.default_host)) {
33222                                 return HANDLER_GO_ON;
33223                         } else {
33224 @@ -253,15 +251,15 @@
33225                 } else {
33226                         buffer_copy_string_buffer(con->server_name, con->uri.authority);
33227                 }
33228 -               
33229 +
33230                 /* copy to cache */
33231                 buffer_copy_string_buffer(p->conf.docroot_cache_key,        con->uri.authority);
33232                 buffer_copy_string_buffer(p->conf.docroot_cache_value,      p->doc_root);
33233                 buffer_copy_string_buffer(p->conf.docroot_cache_servername, con->server_name);
33234 -               
33235 +
33236                 buffer_copy_string_buffer(con->physical.doc_root, p->doc_root);
33237         }
33238 -       
33239 +
33240         return HANDLER_GO_ON;
33241  }
33242  
33243 @@ -269,13 +267,13 @@
33244  int mod_simple_vhost_plugin_init(plugin *p) {
33245         p->version     = LIGHTTPD_VERSION_ID;
33246         p->name        = buffer_init_string("simple_vhost");
33247 -       
33248 +
33249         p->init        = mod_simple_vhost_init;
33250         p->set_defaults = mod_simple_vhost_set_defaults;
33251         p->handle_docroot  = mod_simple_vhost_docroot;
33252         p->cleanup     = mod_simple_vhost_free;
33253 -       
33254 +
33255         p->data        = NULL;
33256 -       
33257 +
33258         return 0;
33259  }
33260 --- lighttpd-1.4.11/src/mod_skeleton.c  2005-10-02 18:30:51.000000000 +0300
33261 +++ lighttpd-1.4.12/src/mod_skeleton.c  2006-07-11 22:07:51.000000000 +0300
33262 @@ -14,13 +14,13 @@
33263  
33264  /**
33265   * this is a skeleton for a lighttpd plugin
33266 - * 
33267 + *
33268   * just replaces every occurance of 'skeleton' by your plugin name
33269 - * 
33270 + *
33271   * e.g. in vim:
33272 - * 
33273 + *
33274   *   :%s/skeleton/myhandler/
33275 - * 
33276 + *
33277   */
33278  
33279  
33280 @@ -33,12 +33,12 @@
33281  
33282  typedef struct {
33283         PLUGIN_DATA;
33284 -       
33285 +
33286         buffer *match_buf;
33287 -       
33288 +
33289         plugin_config **config_storage;
33290 -       
33291 -       plugin_config conf; 
33292 +
33293 +       plugin_config conf;
33294  } plugin_data;
33295  
33296  typedef struct {
33297 @@ -47,36 +47,36 @@
33298  
33299  static handler_ctx * handler_ctx_init() {
33300         handler_ctx * hctx;
33301 -       
33302 +
33303         hctx = calloc(1, sizeof(*hctx));
33304 -       
33305 +
33306         return hctx;
33307  }
33308  
33309  static void handler_ctx_free(handler_ctx *hctx) {
33310 -       
33311 +
33312         free(hctx);
33313  }
33314  
33315  /* init the plugin data */
33316  INIT_FUNC(mod_skeleton_init) {
33317         plugin_data *p;
33318 -       
33319 +
33320         p = calloc(1, sizeof(*p));
33321 -       
33322 +
33323         p->match_buf = buffer_init();
33324 -       
33325 +
33326         return p;
33327  }
33328  
33329  /* detroy the plugin data */
33330  FREE_FUNC(mod_skeleton_free) {
33331         plugin_data *p = p_d;
33332 -       
33333 +
33334         UNUSED(srv);
33335  
33336         if (!p) return HANDLER_GO_ON;
33337 -       
33338 +
33339         if (p->config_storage) {
33340                 size_t i;
33341  
33342 @@ -84,18 +84,18 @@
33343                         plugin_config *s = p->config_storage[i];
33344  
33345                         if (!s) continue;
33346 -                       
33347 +
33348                         array_free(s->match);
33349 -                       
33350 +
33351                         free(s);
33352                 }
33353                 free(p->config_storage);
33354         }
33355 -       
33356 +
33357         buffer_free(p->match_buf);
33358 -       
33359 +
33360         free(p);
33361 -       
33362 +
33363         return HANDLER_GO_ON;
33364  }
33365  
33366 @@ -104,91 +104,88 @@
33367  SETDEFAULTS_FUNC(mod_skeleton_set_defaults) {
33368         plugin_data *p = p_d;
33369         size_t i = 0;
33370 -       
33371 -       config_values_t cv[] = { 
33372 +
33373 +       config_values_t cv[] = {
33374                 { "skeleton.array",             NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
33375                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33376         };
33377 -       
33378 +
33379         if (!p) return HANDLER_ERROR;
33380 -       
33381 +
33382         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33383 -       
33384 +
33385         for (i = 0; i < srv->config_context->used; i++) {
33386                 plugin_config *s;
33387 -               
33388 +
33389                 s = calloc(1, sizeof(plugin_config));
33390                 s->match    = array_init();
33391 -               
33392 +
33393                 cv[0].destination = s->match;
33394 -               
33395 +
33396                 p->config_storage[i] = s;
33397 -       
33398 +
33399                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
33400                         return HANDLER_ERROR;
33401                 }
33402         }
33403 -       
33404 +
33405         return HANDLER_GO_ON;
33406  }
33407  
33408 -#define PATCH(x) \
33409 -       p->conf.x = s->x;
33410  static int mod_skeleton_patch_connection(server *srv, connection *con, plugin_data *p) {
33411         size_t i, j;
33412         plugin_config *s = p->config_storage[0];
33413 -       
33414 -       PATCH(match);
33415 -       
33416 +
33417 +       PATCH_OPTION(match);
33418 +
33419         /* skip the first, the global context */
33420         for (i = 1; i < srv->config_context->used; i++) {
33421                 data_config *dc = (data_config *)srv->config_context->data[i];
33422                 s = p->config_storage[i];
33423 -               
33424 +
33425                 /* condition didn't match */
33426                 if (!config_check_cond(srv, con, dc)) continue;
33427 -               
33428 +
33429                 /* merge config */
33430                 for (j = 0; j < dc->value->used; j++) {
33431                         data_unset *du = dc->value->data[j];
33432 -                       
33433 +
33434                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("skeleton.array"))) {
33435 -                               PATCH(match);
33436 +                               PATCH_OPTION(match);
33437                         }
33438                 }
33439         }
33440 -       
33441 +
33442         return 0;
33443  }
33444 -#undef PATCH
33445  
33446  URIHANDLER_FUNC(mod_skeleton_uri_handler) {
33447         plugin_data *p = p_d;
33448         int s_len;
33449         size_t k, i;
33450 -       
33451 +
33452         UNUSED(srv);
33453  
33454         if (con->uri.path->used == 0) return HANDLER_GO_ON;
33455 -       
33456 +
33457         mod_skeleton_patch_connection(srv, con, p);
33458  
33459         s_len = con->uri.path->used - 1;
33460 -       
33461 +
33462         for (k = 0; k < p->conf.match->used; k++) {
33463                 data_string *ds = (data_string *)p->conf.match->data[k];
33464                 int ct_len = ds->value->used - 1;
33465 -               
33466 +
33467                 if (ct_len > s_len) continue;
33468                 if (ds->value->used == 0) continue;
33469 -               
33470 +
33471                 if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
33472                         con->http_status = 403;
33473 -       
33474 +
33475                         return HANDLER_FINISHED;
33476                 }
33477         }
33478 -       
33479 +
33480         /* not found */
33481         return HANDLER_GO_ON;
33482  }
33483 @@ -198,13 +195,13 @@
33484  int mod_skeleton_plugin_init(plugin *p) {
33485         p->version     = LIGHTTPD_VERSION_ID;
33486         p->name        = buffer_init_string("skeleton");
33487 -       
33488 +
33489         p->init        = mod_skeleton_init;
33490         p->handle_uri_clean  = mod_skeleton_uri_handler;
33491         p->set_defaults  = mod_skeleton_set_defaults;
33492         p->cleanup     = mod_skeleton_free;
33493 -       
33494 +
33495         p->data        = NULL;
33496 -       
33497 +
33498         return 0;
33499  }
33500 --- lighttpd-1.4.11/src/mod_sql_vhost_core.c    1970-01-01 03:00:00.000000000 +0300
33501 +++ lighttpd-1.4.12/src/mod_sql_vhost_core.c    2006-07-11 22:07:53.000000000 +0300
33502 @@ -0,0 +1,209 @@
33503 +#include <stdio.h>
33504 +#include <errno.h>
33505 +#include <fcntl.h>
33506 +#include <string.h>
33507 +
33508 +#ifdef HAVE_CONFIG_H
33509 +#include "config.h"
33510 +#endif
33511 +
33512 +#include "plugin.h"
33513 +#include "log.h"
33514 +
33515 +#include "stat_cache.h"
33516 +
33517 +#include "mod_sql_vhost_core.h"
33518 +
33519 +#define plugin_data mod_sql_vhost_core_plugin_data
33520 +#define plugin_config mod_sql_vhost_core_plugin_config
33521 +
33522 +/* init the plugin data */
33523 +INIT_FUNC(mod_sql_vhost_core_init) {
33524 +       plugin_data *p;
33525 +
33526 +       p = calloc(1, sizeof(*p));
33527 +
33528 +       p->docroot = buffer_init();
33529 +       p->host = buffer_init();
33530 +
33531 +       return p;
33532 +}
33533 +
33534 +/* cleanup the plugin data */
33535 +SERVER_FUNC(mod_sql_vhost_core_cleanup) {
33536 +       plugin_data *p = p_d;
33537 +
33538 +       UNUSED(srv);
33539 +
33540 +       if (!p) return HANDLER_GO_ON;
33541 +
33542 +       if (p->config_storage) {
33543 +               size_t i;
33544 +               for (i = 0; i < srv->config_context->used; i++) {
33545 +                       plugin_config *s = p->config_storage[i];
33546 +
33547 +                       if (!s) continue;
33548 +
33549 +                       buffer_free(s->db);
33550 +                       buffer_free(s->user);
33551 +                       buffer_free(s->pass);
33552 +                       buffer_free(s->sock);
33553 +                       buffer_free(s->backend);
33554 +
33555 +                       free(s);
33556 +               }
33557 +               free(p->config_storage);
33558 +       }
33559 +       buffer_free(p->docroot);
33560 +       buffer_free(p->host);
33561 +
33562 +       free(p);
33563 +
33564 +       return HANDLER_GO_ON;
33565 +}
33566 +
33567 +/* set configuration values */
33568 +SERVER_FUNC(mod_sql_vhost_core_set_defaults) {
33569 +       plugin_data *p = p_d;
33570 +
33571 +       size_t i = 0;
33572 +
33573 +       config_values_t cv[] = {
33574 +               { "sql-vhost.db",       NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 0 * e.g. vhost */
33575 +               { "sql-vhost.user",     NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 1 * lighty */
33576 +               { "sql-vhost.pass",     NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 2 * secrect */
33577 +               { "sql-vhost.sock",     NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 3 * /tmp/mysql.sock */
33578 +               { "sql-vhost.select-vhost", NULL, T_CONFIG_STRING,      T_CONFIG_SCOPE_SERVER }, /* 4 * SELECT ... FROM hosts WHERE hostname = ? */
33579 +               { "sql-vhost.hostname", NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 5 * 127.0.0.1 */
33580 +               { "sql-vhost.port",     NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_SERVER }, /* 6 * 3306 */
33581 +               { "sql-vhost.backend",  NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 7 * mysql */
33582 +
33583 +               /* backward compat */
33584 +               { "mysql-vhost.db",     NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 8 == 0 */
33585 +               { "mysql-vhost.user",   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 9 == 1 */
33586 +               { "mysql-vhost.pass",   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 10 == 2 */
33587 +               { "mysql-vhost.sock",   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 11 == 3 */
33588 +               { "mysql-vhost.sql",    NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 12 == 4 */
33589 +               { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER }, /* 13 == 5 */
33590 +               { "mysql-vhost.port",   NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_SERVER }, /* 14 == 6 */
33591 +
33592 +                { NULL,                        NULL, T_CONFIG_UNSET,   T_CONFIG_SCOPE_UNSET }
33593 +        };
33594 +
33595 +       p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33596 +
33597 +       for (i = 0; i < srv->config_context->used; i++) {
33598 +               plugin_config *s;
33599 +
33600 +               s = calloc(1, sizeof(plugin_config));
33601 +               s->db = buffer_init();
33602 +               s->user = buffer_init();
33603 +               s->pass = buffer_init();
33604 +               s->sock = buffer_init();
33605 +               s->hostname = buffer_init();
33606 +               s->backend = buffer_init();
33607 +               s->port   = 0;               /* default port for mysql */
33608 +               s->select_vhost = buffer_init();
33609 +               s->backend_data = NULL;
33610 +
33611 +               cv[0].destination = s->db;
33612 +               cv[1].destination = s->user;
33613 +               cv[2].destination = s->pass;
33614 +               cv[3].destination = s->sock;
33615 +               cv[4].destination = s->select_vhost;
33616 +               cv[5].destination = s->hostname;
33617 +               cv[6].destination = &(s->port);
33618 +               cv[7].destination = s->backend;
33619 +
33620 +               /* backend compat */
33621 +               cv[8].destination = cv[0].destination;
33622 +               cv[9].destination = cv[1].destination;
33623 +               cv[10].destination = cv[2].destination;
33624 +               cv[11].destination = cv[3].destination;
33625 +               cv[12].destination = cv[4].destination;
33626 +               cv[13].destination = cv[5].destination;
33627 +               cv[14].destination = cv[6].destination;
33628 +
33629 +               p->config_storage[i] = s;
33630 +
33631 +               if (config_insert_values_global(srv,
33632 +                       ((data_config *)srv->config_context->data[i])->value,
33633 +                       cv)) return HANDLER_ERROR;
33634 +
33635 +               /* we only parse the config, the backend plugin will patch itself into the plugin-struct */
33636 +       }
33637 +
33638 +        return HANDLER_GO_ON;
33639 +}
33640 +
33641 +static int mod_sql_vhost_core_patch_connection(server *srv, connection *con, plugin_data *p) {
33642 +       size_t i;
33643 +       plugin_config *s = p->config_storage[0];
33644 +
33645 +       PATCH_OPTION(backend_data);
33646 +       PATCH_OPTION(get_vhost);
33647 +
33648 +       /* skip the first, the global context */
33649 +       for (i = 1; i < srv->config_context->used; i++) {
33650 +               data_config *dc = (data_config *)srv->config_context->data[i];
33651 +               s = p->config_storage[i];
33652 +
33653 +               /* condition didn't match */
33654 +               if (!config_check_cond(srv, con, dc)) continue;
33655 +
33656 +               if (s->backend_data) {
33657 +                       PATCH_OPTION(backend_data);
33658 +                       PATCH_OPTION(get_vhost);
33659 +               }
33660 +       }
33661 +
33662 +       return 0;
33663 +}
33664 +
33665 +/* handle document root request */
33666 +CONNECTION_FUNC(mod_sql_vhost_core_handle_docroot) {
33667 +       plugin_data *p = p_d;
33668 +       stat_cache_entry *sce;
33669 +
33670 +       /* no host specified? */
33671 +       if (!con->uri.authority->used) return HANDLER_GO_ON;
33672 +
33673 +       mod_sql_vhost_core_patch_connection(srv, con, p);
33674 +
33675 +       /* do we have backend ? */
33676 +       if (!p->conf.get_vhost) return HANDLER_GO_ON;
33677 +
33678 +       /* ask the backend for the data */
33679 +       if (0 != p->conf.get_vhost(srv, con, p->conf.backend_data, p->docroot, p->host)) {
33680 +               return HANDLER_GO_ON;
33681 +       }
33682 +
33683 +       if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->docroot, &sce)) {
33684 +               log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->docroot);
33685 +               return HANDLER_GO_ON;
33686 +       }
33687 +        if (!S_ISDIR(sce->st.st_mode)) {
33688 +               log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->docroot);
33689 +               return HANDLER_GO_ON;
33690 +       }
33691 +
33692 +       buffer_copy_string_buffer(con->server_name, p->host);
33693 +       buffer_copy_string_buffer(con->physical.doc_root, p->docroot);
33694 +
33695 +       return HANDLER_GO_ON;
33696 +}
33697 +
33698 +/* this function is called at dlopen() time and inits the callbacks */
33699 +int mod_sql_vhost_core_plugin_init(plugin *p) {
33700 +       p->version     = LIGHTTPD_VERSION_ID;
33701 +       p->name                         = buffer_init_string("mod_sql_vhost_core");
33702 +
33703 +       p->init                         = mod_sql_vhost_core_init;
33704 +       p->cleanup                      = mod_sql_vhost_core_cleanup;
33705 +
33706 +       p->set_defaults                 = mod_sql_vhost_core_set_defaults;
33707 +       p->handle_docroot               = mod_sql_vhost_core_handle_docroot;
33708 +
33709 +       return 0;
33710 +}
33711 +
33712 --- lighttpd-1.4.11/src/mod_sql_vhost_core.h    1970-01-01 03:00:00.000000000 +0300
33713 +++ lighttpd-1.4.12/src/mod_sql_vhost_core.h    2006-07-11 22:07:53.000000000 +0300
33714 @@ -0,0 +1,49 @@
33715 +#ifndef _MOD_SQL_VHOST_CORE_H_
33716 +#define _MOD_SQL_VHOST_CORE_H_
33717 +
33718 +#include "buffer.h"
33719 +#include "plugin.h"
33720 +
33721 +#define SQLVHOST_BACKEND_GETVHOST_PARAMS \
33722 +       (server *srv, connection *con, void *p_d, buffer *docroot, buffer *host)
33723 +
33724 +#define SQLVHOST_BACKEND_GETVHOST_RETVAL handler_t
33725 +
33726 +#define SQLVHOST_BACKEND_GETVHOST(name) \
33727 +       SQLVHOST_BACKEND_GETVHOST_RETVAL name SQLVHOST_BACKEND_GETVHOST_PARAMS
33728 +
33729 +#define SQLVHOST_BACKEND_GETVHOST_PTR(name) \
33730 +       SQLVHOST_BACKEND_GETVHOST_RETVAL (* name)SQLVHOST_BACKEND_GETVHOST_PARAMS
33731 +
33732 +typedef struct {
33733 +       buffer  *db;
33734 +       buffer  *user;
33735 +       buffer  *pass;
33736 +       buffer  *sock;
33737 +
33738 +       buffer  *hostname;
33739 +       unsigned short port;
33740 +
33741 +       buffer  *backend;
33742 +       void *backend_data;
33743 +
33744 +       buffer *select_vhost;
33745 +
33746 +       SQLVHOST_BACKEND_GETVHOST_PTR(get_vhost);
33747 +} mod_sql_vhost_core_plugin_config;
33748 +
33749 +/* global plugin data */
33750 +typedef struct {
33751 +       PLUGIN_DATA;
33752 +
33753 +       buffer  *docroot;
33754 +       buffer  *host;
33755 +
33756 +       mod_sql_vhost_core_plugin_config **config_storage;
33757 +
33758 +       mod_sql_vhost_core_plugin_config conf;
33759 +} mod_sql_vhost_core_plugin_data;
33760 +
33761 +
33762 +
33763 +#endif
33764 --- lighttpd-1.4.11/src/mod_ssi.c       2006-03-04 17:09:48.000000000 +0200
33765 +++ lighttpd-1.4.12/src/mod_ssi.c       2006-07-11 22:07:53.000000000 +0300
33766 @@ -6,7 +6,6 @@
33767  #include <string.h>
33768  #include <errno.h>
33769  #include <time.h>
33770 -#include <unistd.h>
33771  
33772  #include "base.h"
33773  #include "log.h"
33774 @@ -23,6 +22,8 @@
33775  #include "inet_ntop_cache.h"
33776  
33777  #include "sys-socket.h"
33778 +#include "sys-strings.h"
33779 +#include "sys-files.h"
33780  
33781  #ifdef HAVE_PWD_H
33782  #include <pwd.h>
33783 @@ -39,15 +40,15 @@
33784  /* init the plugin data */
33785  INIT_FUNC(mod_ssi_init) {
33786         plugin_data *p;
33787 -       
33788 +
33789         p = calloc(1, sizeof(*p));
33790 -       
33791 +
33792         p->timefmt = buffer_init();
33793         p->stat_fn = buffer_init();
33794 -       
33795 +
33796         p->ssi_vars = array_init();
33797         p->ssi_cgi_env = array_init();
33798 -       
33799 +
33800         return p;
33801  }
33802  
33803 @@ -55,21 +56,21 @@
33804  FREE_FUNC(mod_ssi_free) {
33805         plugin_data *p = p_d;
33806         UNUSED(srv);
33807 -       
33808 +
33809         if (!p) return HANDLER_GO_ON;
33810 -       
33811 +
33812         if (p->config_storage) {
33813                 size_t i;
33814                 for (i = 0; i < srv->config_context->used; i++) {
33815                         plugin_config *s = p->config_storage[i];
33816 -                       
33817 +
33818                         array_free(s->ssi_extension);
33819 -                       
33820 +
33821                         free(s);
33822                 }
33823                 free(p->config_storage);
33824         }
33825 -       
33826 +
33827         array_free(p->ssi_vars);
33828         array_free(p->ssi_cgi_env);
33829  #ifdef HAVE_PCRE_H
33830 @@ -77,9 +78,9 @@
33831  #endif
33832         buffer_free(p->timefmt);
33833         buffer_free(p->stat_fn);
33834 -       
33835 +
33836         free(p);
33837 -       
33838 +
33839         return HANDLER_GO_ON;
33840  }
33841  
33842 @@ -92,36 +93,36 @@
33843         const char *errptr;
33844         int erroff;
33845  #endif
33846 -       
33847 -       config_values_t cv[] = { 
33848 +
33849 +       config_values_t cv[] = {
33850                 { "ssi.extension",              NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
33851                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33852         };
33853 -       
33854 +
33855         if (!p) return HANDLER_ERROR;
33856 -       
33857 +
33858         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33859 -       
33860 +
33861         for (i = 0; i < srv->config_context->used; i++) {
33862                 plugin_config *s;
33863 -               
33864 +
33865                 s = calloc(1, sizeof(plugin_config));
33866                 s->ssi_extension  = array_init();
33867 -               
33868 +
33869                 cv[0].destination = s->ssi_extension;
33870 -               
33871 +
33872                 p->config_storage[i] = s;
33873 -       
33874 +
33875                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
33876                         return HANDLER_ERROR;
33877                 }
33878         }
33879 -       
33880 +
33881  #ifdef HAVE_PCRE_H
33882         /* allow 2 params */
33883         if (NULL == (p->ssi_regex = pcre_compile("<!--#([a-z]+)\\s+(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?-->", 0, &errptr, &erroff, NULL))) {
33884                 log_error_write(srv, __FILE__, __LINE__, "sds",
33885 -                               "ssi: pcre ", 
33886 +                               "ssi: pcre ",
33887                                 erroff, errptr);
33888                 return HANDLER_ERROR;
33889         }
33890 @@ -130,52 +131,52 @@
33891                         "mod_ssi: pcre support is missing, please recompile with pcre support or remove mod_ssi from the list of modules");
33892         return HANDLER_ERROR;
33893  #endif
33894 -       
33895 +
33896         return HANDLER_GO_ON;
33897  }
33898  
33899  int ssi_env_add(array *env, const char *key, const char *val) {
33900         data_string *ds;
33901 -                       
33902 +
33903         if (NULL == (ds = (data_string *)array_get_unused_element(env, TYPE_STRING))) {
33904                 ds = data_string_init();
33905         }
33906         buffer_copy_string(ds->key,   key);
33907         buffer_copy_string(ds->value, val);
33908 -       
33909 +
33910         array_insert_unique(env, (data_unset *)ds);
33911 -       
33912 +
33913         return 0;
33914  }
33915  
33916  /**
33917   *
33918   *  the next two functions are take from fcgi.c
33919 - * 
33920 + *
33921   */
33922  
33923  static int ssi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
33924         size_t i;
33925 -       
33926 +
33927         for (i = 0; i < con->request.headers->used; i++) {
33928                 data_string *ds;
33929 -               
33930 +
33931                 ds = (data_string *)con->request.headers->data[i];
33932 -               
33933 +
33934                 if (ds->value->used && ds->key->used) {
33935                         size_t j;
33936                         buffer_reset(srv->tmp_buf);
33937 -                       
33938 +
33939                         /* don't forward the Authorization: Header */
33940                         if (0 == strcasecmp(ds->key->ptr, "AUTHORIZATION")) {
33941                                 continue;
33942                         }
33943 -                       
33944 +
33945                         if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
33946                                 buffer_copy_string(srv->tmp_buf, "HTTP_");
33947                                 srv->tmp_buf->used--;
33948                         }
33949 -                       
33950 +
33951                         buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
33952                         for (j = 0; j < ds->key->used - 1; j++) {
33953                                 char c = '_';
33954 @@ -189,33 +190,33 @@
33955                                 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
33956                         }
33957                         srv->tmp_buf->ptr[srv->tmp_buf->used] = '\0';
33958 -                       
33959 +
33960                         ssi_env_add(p->ssi_cgi_env, srv->tmp_buf->ptr, ds->value->ptr);
33961                 }
33962         }
33963 -       
33964 +
33965         return 0;
33966  }
33967  
33968  static int build_ssi_cgi_vars(server *srv, connection *con, plugin_data *p) {
33969         char buf[32];
33970 -       
33971 +
33972         server_socket *srv_sock = con->srv_socket;
33973 -       
33974 +
33975  #ifdef HAVE_IPV6
33976         char b2[INET6_ADDRSTRLEN + 1];
33977  #endif
33978  
33979  #define CONST_STRING(x) \
33980                 x
33981 -       
33982 +
33983         array_reset(p->ssi_cgi_env);
33984 -       
33985 +
33986         ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_SOFTWARE"), PACKAGE_NAME"/"PACKAGE_VERSION);
33987         ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_NAME"),
33988  #ifdef HAVE_IPV6
33989 -                    inet_ntop(srv_sock->addr.plain.sa_family, 
33990 -                              srv_sock->addr.plain.sa_family == AF_INET6 ? 
33991 +                    inet_ntop(srv_sock->addr.plain.sa_family,
33992 +                              srv_sock->addr.plain.sa_family == AF_INET6 ?
33993                                (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
33994                                (const void *) &(srv_sock->addr.ipv4.sin_addr),
33995                                b2, sizeof(b2)-1)
33996 @@ -224,28 +225,28 @@
33997  #endif
33998                      );
33999         ssi_env_add(p->ssi_cgi_env, CONST_STRING("GATEWAY_INTERFACE"), "CGI/1.1");
34000 -               
34001 -       ltostr(buf, 
34002 +
34003 +       ltostr(buf,
34004  #ifdef HAVE_IPV6
34005                ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
34006  #else
34007                ntohs(srv_sock->addr.ipv4.sin_port)
34008  #endif
34009                );
34010 -       
34011 +
34012         ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PORT"), buf);
34013 -       
34014 +
34015         ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_ADDR"),
34016                     inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
34017 -       
34018 +
34019         if (con->authed_user->used) {
34020                 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_USER"),
34021                              con->authed_user->ptr);
34022         }
34023 -       
34024 +
34025         if (con->request.content_length > 0) {
34026                 /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
34027 -               
34028 +
34029                 /* request.content_length < SSIZE_MAX, see request.c */
34030                 ltostr(buf, con->request.content_length);
34031                 ssi_env_add(p->ssi_cgi_env, CONST_STRING("CONTENT_LENGTH"), buf);
34032 @@ -271,30 +272,30 @@
34033         if (con->request.pathinfo->used) {
34034                 ssi_env_add(p->ssi_cgi_env, CONST_STRING("PATH_INFO"), con->request.pathinfo->ptr);
34035         }
34036 -               
34037 +
34038         ssi_env_add(p->ssi_cgi_env, CONST_STRING("SCRIPT_FILENAME"), con->physical.path->ptr);
34039         ssi_env_add(p->ssi_cgi_env, CONST_STRING("DOCUMENT_ROOT"), con->physical.doc_root->ptr);
34040 -       
34041 +
34042         ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_URI"), con->request.uri->ptr);
34043         ssi_env_add(p->ssi_cgi_env, CONST_STRING("QUERY_STRING"), con->uri.query->used ? con->uri.query->ptr : "");
34044         ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_METHOD"), get_http_method_name(con->request.http_method));
34045         ssi_env_add(p->ssi_cgi_env, CONST_STRING("REDIRECT_STATUS"), "200");
34046         ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PROTOCOL"), get_http_version_name(con->request.http_version));
34047 -       
34048 +
34049         ssi_env_add_request_headers(srv, con, p);
34050 -       
34051 +
34052         return 0;
34053  }
34054  
34055 -static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, 
34056 +static int process_ssi_stmt(server *srv, connection *con, plugin_data *p,
34057                             const char **l, size_t n) {
34058         size_t i, ssicmd = 0;
34059         char buf[255];
34060         buffer *b = NULL;
34061 -       
34062 -       struct { 
34063 +
34064 +       struct {
34065                 const char *var;
34066 -               enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD, 
34067 +               enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD,
34068                                 SSI_CONFIG, SSI_PRINTENV, SSI_SET, SSI_IF, SSI_ELIF,
34069                                 SSI_ELSE, SSI_ENDIF, SSI_EXEC } type;
34070         } ssicmds[] = {
34071 @@ -310,27 +311,27 @@
34072                 { "endif",    SSI_ENDIF },
34073                 { "else",     SSI_ELSE },
34074                 { "exec",     SSI_EXEC },
34075 -               
34076 +
34077                 { NULL, SSI_UNSET }
34078         };
34079 -       
34080 +
34081         for (i = 0; ssicmds[i].var; i++) {
34082                 if (0 == strcmp(l[1], ssicmds[i].var)) {
34083                         ssicmd = ssicmds[i].type;
34084                         break;
34085                 }
34086         }
34087 -       
34088 +
34089         switch(ssicmd) {
34090         case SSI_ECHO: {
34091                 /* echo */
34092                 int var = 0, enc = 0;
34093                 const char *var_val = NULL;
34094                 stat_cache_entry *sce = NULL;
34095 -               
34096 -               struct { 
34097 +
34098 +               struct {
34099                         const char *var;
34100 -                       enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI, 
34101 +                       enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI,
34102                                         SSI_ECHO_LAST_MODIFIED, SSI_ECHO_USER_NAME } type;
34103                 } echovars[] = {
34104                         { "DATE_GMT",      SSI_ECHO_DATE_GMT },
34105 @@ -339,27 +340,27 @@
34106                         { "DOCUMENT_URI",  SSI_ECHO_DOCUMENT_URI },
34107                         { "LAST_MODIFIED", SSI_ECHO_LAST_MODIFIED },
34108                         { "USER_NAME",     SSI_ECHO_USER_NAME },
34109 -                       
34110 +
34111                         { NULL, SSI_ECHO_UNSET }
34112                 };
34113 -               
34114 -               struct { 
34115 +
34116 +               struct {
34117                         const char *var;
34118                         enum { SSI_ENC_UNSET, SSI_ENC_URL, SSI_ENC_NONE, SSI_ENC_ENTITY } type;
34119                 } encvars[] = {
34120                         { "url",          SSI_ENC_URL },
34121                         { "none",         SSI_ENC_NONE },
34122                         { "entity",       SSI_ENC_ENTITY },
34123 -                       
34124 +
34125                         { NULL, SSI_ENC_UNSET }
34126                 };
34127 -               
34128 +
34129                 for (i = 2; i < n; i += 2) {
34130                         if (0 == strcmp(l[i], "var")) {
34131                                 int j;
34132 -                               
34133 +
34134                                 var_val = l[i+1];
34135 -                               
34136 +
34137                                 for (j = 0; echovars[j].var; j++) {
34138                                         if (0 == strcmp(l[i+1], echovars[j].var)) {
34139                                                 var = echovars[j].type;
34140 @@ -368,7 +369,7 @@
34141                                 }
34142                         } else if (0 == strcmp(l[i], "encoding")) {
34143                                 int j;
34144 -                               
34145 +
34146                                 for (j = 0; encvars[j].var; j++) {
34147                                         if (0 == strcmp(l[i+1], encvars[j].var)) {
34148                                                 enc = encvars[j].type;
34149 @@ -377,26 +378,26 @@
34150                                 }
34151                         } else {
34152                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34153 -                                               "ssi: unknow attribute for ", 
34154 +                                               "ssi: unknow attribute for ",
34155                                                 l[1], l[i]);
34156                         }
34157                 }
34158 -               
34159 +
34160                 if (p->if_is_false) break;
34161 -               
34162 +
34163                 if (!var_val) {
34164                         log_error_write(srv, __FILE__, __LINE__, "sss",
34165 -                                       "ssi: ", 
34166 +                                       "ssi: ",
34167                                         l[1], "var is missing");
34168                         break;
34169                 }
34170  
34171                 stat_cache_get_entry(srv, con, con->physical.path, &sce);
34172 -               
34173 +
34174                 switch(var) {
34175                 case SSI_ECHO_USER_NAME: {
34176                         struct passwd *pw;
34177 -                       
34178 +
34179                         b = chunkqueue_get_append_buffer(con->write_queue);
34180  #ifdef HAVE_PWD_H
34181                         if (NULL == (pw = getpwuid(sce->st.st_uid))) {
34182 @@ -411,7 +412,7 @@
34183                 }
34184                 case SSI_ECHO_LAST_MODIFIED:    {
34185                         time_t t = sce->st.st_mtime;
34186 -                       
34187 +
34188                         b = chunkqueue_get_append_buffer(con->write_queue);
34189                         if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
34190                                 buffer_copy_string(b, "(none)");
34191 @@ -422,7 +423,7 @@
34192                 }
34193                 case SSI_ECHO_DATE_LOCAL: {
34194                         time_t t = time(NULL);
34195 -                       
34196 +
34197                         b = chunkqueue_get_append_buffer(con->write_queue);
34198                         if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
34199                                 buffer_copy_string(b, "(none)");
34200 @@ -433,7 +434,7 @@
34201                 }
34202                 case SSI_ECHO_DATE_GMT: {
34203                         time_t t = time(NULL);
34204 -                       
34205 +
34206                         b = chunkqueue_get_append_buffer(con->write_queue);
34207                         if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, gmtime(&t))) {
34208                                 buffer_copy_string(b, "(none)");
34209 @@ -444,7 +445,7 @@
34210                 }
34211                 case SSI_ECHO_DOCUMENT_NAME: {
34212                         char *sl;
34213 -                       
34214 +
34215                         b = chunkqueue_get_append_buffer(con->write_queue);
34216                         if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
34217                                 buffer_copy_string_buffer(b, con->physical.path);
34218 @@ -461,15 +462,15 @@
34219                 default: {
34220                         data_string *ds;
34221                         /* check if it is a cgi-var */
34222 -                       
34223 +
34224                         b = chunkqueue_get_append_buffer(con->write_queue);
34225 -                       
34226 +
34227                         if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, var_val))) {
34228                                 buffer_copy_string_buffer(b, ds->value);
34229                         } else {
34230                                 buffer_copy_string(b, "(none)");
34231                         }
34232 -                       
34233 +
34234                         break;
34235                 }
34236                 }
34237 @@ -481,7 +482,7 @@
34238                 const char * file_path = NULL, *virt_path = NULL;
34239                 struct stat st;
34240                 char *sl;
34241 -               
34242 +
34243                 for (i = 2; i < n; i += 2) {
34244                         if (0 == strcmp(l[i], "file")) {
34245                                 file_path = l[i+1];
34246 @@ -489,28 +490,28 @@
34247                                 virt_path = l[i+1];
34248                         } else {
34249                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34250 -                                               "ssi: unknow attribute for ", 
34251 +                                               "ssi: unknow attribute for ",
34252                                                 l[1], l[i]);
34253                         }
34254                 }
34255 -               
34256 +
34257                 if (!file_path && !virt_path) {
34258                         log_error_write(srv, __FILE__, __LINE__, "sss",
34259 -                                       "ssi: ", 
34260 +                                       "ssi: ",
34261                                         l[1], "file or virtual are missing");
34262                         break;
34263                 }
34264 -               
34265 +
34266                 if (file_path && virt_path) {
34267                         log_error_write(srv, __FILE__, __LINE__, "sss",
34268 -                                       "ssi: ", 
34269 +                                       "ssi: ",
34270                                         l[1], "only one of file and virtual is allowed here");
34271                         break;
34272                 }
34273 -               
34274 -               
34275 +
34276 +
34277                 if (p->if_is_false) break;
34278 -               
34279 +
34280                 if (file_path) {
34281                         /* current doc-root */
34282                         if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
34283 @@ -519,46 +520,46 @@
34284                                 buffer_copy_string_len(p->stat_fn, con->physical.path->ptr, sl - con->physical.path->ptr + 1);
34285                         }
34286  
34287 -                       buffer_copy_string(srv->tmp_buf, file_path); 
34288 +                       buffer_copy_string(srv->tmp_buf, file_path);
34289                         buffer_urldecode_path(srv->tmp_buf);
34290 -                       buffer_path_simplify(srv->tmp_buf, srv->tmp_buf); 
34291 -                       buffer_append_string_buffer(p->stat_fn, srv->tmp_buf); 
34292 +                       buffer_path_simplify(srv->tmp_buf, srv->tmp_buf);
34293 +                       buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
34294                 } else {
34295                         /* virtual */
34296 -                       
34297 +
34298                         if (virt_path[0] == '/') {
34299                                 buffer_copy_string(p->stat_fn, virt_path);
34300                         } else {
34301                                 /* there is always a / */
34302                                 sl = strrchr(con->uri.path->ptr, '/');
34303 -                               
34304 +
34305                                 buffer_copy_string_len(p->stat_fn, con->uri.path->ptr, sl - con->uri.path->ptr + 1);
34306                                 buffer_append_string(p->stat_fn, virt_path);
34307                         }
34308 -                       
34309 +
34310                         buffer_urldecode_path(p->stat_fn);
34311                         buffer_path_simplify(srv->tmp_buf, p->stat_fn);
34312 -                       
34313 +
34314                         /* we have an uri */
34315 -                       
34316 +
34317                         buffer_copy_string_buffer(p->stat_fn, con->physical.doc_root);
34318                         buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
34319                 }
34320 -               
34321 +
34322                 if (0 == stat(p->stat_fn->ptr, &st)) {
34323                         time_t t = st.st_mtime;
34324 -                       
34325 +
34326                         switch (ssicmd) {
34327                         case SSI_FSIZE:
34328                                 b = chunkqueue_get_append_buffer(con->write_queue);
34329                                 if (p->sizefmt) {
34330                                         int j = 0;
34331                                         const char *abr[] = { " B", " kB", " MB", " GB", " TB", NULL };
34332 -                                       
34333 +
34334                                         off_t s = st.st_size;
34335 -                                       
34336 +
34337                                         for (j = 0; s > 1024 && abr[j+1]; s /= 1024, j++);
34338 -                                       
34339 +
34340                                         buffer_copy_off_t(b, s);
34341                                         buffer_append_string(b, abr[j]);
34342                                 } else {
34343 @@ -579,7 +580,7 @@
34344                         }
34345                 } else {
34346                         log_error_write(srv, __FILE__, __LINE__, "sbs",
34347 -                                       "ssi: stating failed ", 
34348 +                                       "ssi: stating failed ",
34349                                         p->stat_fn, strerror(errno));
34350                 }
34351                 break;
34352 @@ -593,33 +594,33 @@
34353                                 val = l[i+1];
34354                         } else {
34355                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34356 -                                               "ssi: unknow attribute for ", 
34357 +                                               "ssi: unknow attribute for ",
34358                                                 l[1], l[i]);
34359                         }
34360                 }
34361 -               
34362 +
34363                 if (p->if_is_false) break;
34364 -               
34365 +
34366                 if (key && val) {
34367                         data_string *ds;
34368 -                       
34369 +
34370                         if (NULL == (ds = (data_string *)array_get_unused_element(p->ssi_vars, TYPE_STRING))) {
34371                                 ds = data_string_init();
34372                         }
34373                         buffer_copy_string(ds->key,   key);
34374                         buffer_copy_string(ds->value, val);
34375 -                       
34376 +
34377                         array_insert_unique(p->ssi_vars, (data_unset *)ds);
34378                 } else {
34379                         log_error_write(srv, __FILE__, __LINE__, "sss",
34380 -                                       "ssi: var and value have to be set in", 
34381 +                                       "ssi: var and value have to be set in",
34382                                         l[0], l[1]);
34383                 }
34384                 break;
34385         }
34386 -       case SSI_CONFIG: 
34387 +       case SSI_CONFIG:
34388                 if (p->if_is_false) break;
34389 -               
34390 +
34391                 for (i = 2; i < n; i += 2) {
34392                         if (0 == strcmp(l[i], "timefmt")) {
34393                                 buffer_copy_string(p->timefmt, l[i+1]);
34394 @@ -632,63 +633,65 @@
34395                                         log_error_write(srv, __FILE__, __LINE__, "sssss",
34396                                                         "ssi: unknow value for attribute '",
34397                                                         l[i],
34398 -                                                       "' for ", 
34399 +                                                       "' for ",
34400                                                         l[1], l[i+1]);
34401                                 }
34402                         } else {
34403                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34404 -                                               "ssi: unknow attribute for ", 
34405 +                                               "ssi: unknow attribute for ",
34406                                                 l[1], l[i]);
34407                         }
34408                 }
34409                 break;
34410         case SSI_PRINTENV:
34411                 if (p->if_is_false) break;
34412 -               
34413 +
34414                 b = chunkqueue_get_append_buffer(con->write_queue);
34415                 buffer_copy_string(b, "<pre>");
34416                 for (i = 0; i < p->ssi_vars->used; i++) {
34417                         data_string *ds = (data_string *)p->ssi_vars->data[p->ssi_vars->sorted[i]];
34418 -                       
34419 +
34420                         buffer_append_string_buffer(b, ds->key);
34421                         buffer_append_string(b, ": ");
34422                         buffer_append_string_buffer(b, ds->value);
34423                         buffer_append_string(b, "<br />");
34424 -                                       
34425 +
34426                 }
34427                 buffer_append_string(b, "</pre>");
34428 -               
34429 +
34430                 break;
34431         case SSI_EXEC: {
34432 +#ifndef _WIN32
34433 +
34434                 const char *cmd = NULL;
34435                 pid_t pid;
34436                 int from_exec_fds[2];
34437 -               
34438 +
34439                 for (i = 2; i < n; i += 2) {
34440                         if (0 == strcmp(l[i], "cmd")) {
34441                                 cmd = l[i+1];
34442                         } else {
34443                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34444 -                                               "ssi: unknow attribute for ", 
34445 +                                               "ssi: unknow attribute for ",
34446                                                 l[1], l[i]);
34447                         }
34448                 }
34449 -               
34450 +
34451                 if (p->if_is_false) break;
34452 -               
34453 +
34454                 /* create a return pipe and send output to the html-page
34455 -                * 
34456 -                * as exec is assumed evil it is implemented synchronously 
34457 +                *
34458 +                * as exec is assumed evil it is implemented synchronously
34459                  */
34460 -               
34461 +
34462                 if (!cmd) break;
34463 -#ifdef HAVE_FORK       
34464 +
34465                 if (pipe(from_exec_fds)) {
34466 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
34467 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
34468                                         "pipe failed: ", strerror(errno));
34469                         return -1;
34470                 }
34471 -       
34472 +
34473                 /* fork, execve */
34474                 switch (pid = fork()) {
34475                 case 0: {
34476 @@ -698,14 +701,14 @@
34477                         close(from_exec_fds[1]);
34478                         /* not needed */
34479                         close(from_exec_fds[0]);
34480 -                       
34481 +
34482                         /* close stdin */
34483                         close(STDIN_FILENO);
34484 -               
34485 +
34486                         execl("/bin/sh", "sh", "-c", cmd, NULL);
34487 -                       
34488 +
34489                         log_error_write(srv, __FILE__, __LINE__, "sss", "spawing exec failed:", strerror(errno), cmd);
34490 -               
34491 +
34492                         /* */
34493                         SEGFAULT();
34494                         break;
34495 @@ -718,9 +721,9 @@
34496                         /* father */
34497                         int status;
34498                         ssize_t r;
34499 -                       
34500 +
34501                         close(from_exec_fds[1]);
34502 -                       
34503 +
34504                         /* wait for the client to end */
34505                         if (-1 == waitpid(pid, &status, 0)) {
34506                                 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed:", strerror(errno));
34507 @@ -730,7 +733,7 @@
34508  
34509                                 while(1) {
34510                                         if (ioctl(from_exec_fds[0], FIONREAD, &toread)) {
34511 -                                               log_error_write(srv, __FILE__, __LINE__, "s", 
34512 +                                               log_error_write(srv, __FILE__, __LINE__, "s",
34513                                                         "unexpected end-of-file (perhaps the ssi-exec process died)");
34514                                                 return -1;
34515                                         }
34516 @@ -738,10 +741,10 @@
34517                                         if (toread > 0) {
34518                                                 b = chunkqueue_get_append_buffer(con->write_queue);
34519  
34520 -                                               buffer_prepare_copy(b, toread + 1); 
34521 +                                               buffer_prepare_copy(b, toread + 1);
34522  
34523                                                 if ((r = read(from_exec_fds[0], b->ptr, b->size - 1)) < 0) {
34524 -                                                       /* read failed */ 
34525 +                                                       /* read failed */
34526                                                         break;
34527                                                 } else {
34528                                                         b->used = r;
34529 @@ -755,59 +758,58 @@
34530                                 log_error_write(srv, __FILE__, __LINE__, "s", "process exited abnormally");
34531                         }
34532                         close(from_exec_fds[0]);
34533 -                       
34534 +
34535                         break;
34536                 }
34537                 }
34538  #else
34539 -
34540                 return -1;
34541  #endif
34542 -               
34543 +
34544                 break;
34545         }
34546         case SSI_IF: {
34547                 const char *expr = NULL;
34548 -               
34549 +
34550                 for (i = 2; i < n; i += 2) {
34551                         if (0 == strcmp(l[i], "expr")) {
34552                                 expr = l[i+1];
34553                         } else {
34554                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34555 -                                               "ssi: unknow attribute for ", 
34556 +                                               "ssi: unknow attribute for ",
34557                                                 l[1], l[i]);
34558                         }
34559                 }
34560 -               
34561 +
34562                 if (!expr) {
34563                         log_error_write(srv, __FILE__, __LINE__, "sss",
34564 -                                       "ssi: ", 
34565 +                                       "ssi: ",
34566                                         l[1], "expr missing");
34567                         break;
34568                 }
34569 -               
34570 +
34571                 if ((!p->if_is_false) &&
34572 -                   ((p->if_is_false_level == 0) || 
34573 +                   ((p->if_is_false_level == 0) ||
34574                      (p->if_level < p->if_is_false_level))) {
34575                         switch (ssi_eval_expr(srv, con, p, expr)) {
34576                         case -1:
34577 -                       case 0: 
34578 -                               p->if_is_false = 1; 
34579 +                       case 0:
34580 +                               p->if_is_false = 1;
34581                                 p->if_is_false_level = p->if_level;
34582                                 break;
34583 -                       case 1: 
34584 -                               p->if_is_false = 0; 
34585 +                       case 1:
34586 +                               p->if_is_false = 0;
34587                                 break;
34588                         }
34589                 }
34590 -               
34591 +
34592                 p->if_level++;
34593 -               
34594 +
34595                 break;
34596         }
34597         case SSI_ELSE:
34598                 p->if_level--;
34599 -               
34600 +
34601                 if (p->if_is_false) {
34602                         if ((p->if_level == p->if_is_false_level) &&
34603                             (p->if_is_false_endif == 0)) {
34604 @@ -815,11 +817,11 @@
34605                         }
34606                 } else {
34607                         p->if_is_false = 1;
34608 -                       
34609 +
34610                         p->if_is_false_level = p->if_level;
34611                 }
34612                 p->if_level++;
34613 -               
34614 +
34615                 break;
34616         case SSI_ELIF: {
34617                 const char *expr = NULL;
34618 @@ -828,52 +830,52 @@
34619                                 expr = l[i+1];
34620                         } else {
34621                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34622 -                                               "ssi: unknow attribute for ", 
34623 +                                               "ssi: unknow attribute for ",
34624                                                 l[1], l[i]);
34625                         }
34626                 }
34627 -               
34628 +
34629                 if (!expr) {
34630                         log_error_write(srv, __FILE__, __LINE__, "sss",
34631 -                                       "ssi: ", 
34632 +                                       "ssi: ",
34633                                         l[1], "expr missing");
34634                         break;
34635                 }
34636 -               
34637 +
34638                 p->if_level--;
34639 -               
34640 +
34641                 if (p->if_level == p->if_is_false_level) {
34642                         if ((p->if_is_false) &&
34643                             (p->if_is_false_endif == 0)) {
34644                                 switch (ssi_eval_expr(srv, con, p, expr)) {
34645                                 case -1:
34646 -                               case 0: 
34647 -                                       p->if_is_false = 1; 
34648 +                               case 0:
34649 +                                       p->if_is_false = 1;
34650                                         p->if_is_false_level = p->if_level;
34651                                         break;
34652 -                               case 1: 
34653 -                                       p->if_is_false = 0; 
34654 +                               case 1:
34655 +                                       p->if_is_false = 0;
34656                                         break;
34657                                 }
34658                         } else {
34659 -                               p->if_is_false = 1; 
34660 +                               p->if_is_false = 1;
34661                                 p->if_is_false_level = p->if_level;
34662                                 p->if_is_false_endif = 1;
34663                         }
34664                 }
34665 -               
34666 +
34667                 p->if_level++;
34668 -               
34669 +
34670                 break;
34671         }
34672         case SSI_ENDIF:
34673                 p->if_level--;
34674 -               
34675 +
34676                 if (p->if_level == p->if_is_false_level) {
34677                         p->if_is_false = 0;
34678                         p->if_is_false_endif = 0;
34679                 }
34680 -                       
34681 +
34682                 break;
34683         default:
34684                 log_error_write(srv, __FILE__, __LINE__, "ss",
34685 @@ -881,41 +883,41 @@
34686                                 l[1]);
34687                 break;
34688         }
34689 -       
34690 +
34691         return 0;
34692 -       
34693 +
34694  }
34695  
34696  static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p) {
34697         stream s;
34698  #ifdef  HAVE_PCRE_H
34699         int i, n;
34700 -       
34701 +
34702  #define N 10
34703         int ovec[N * 3];
34704  #endif
34705 -       
34706 +
34707         /* get a stream to the file */
34708 -       
34709 +
34710         array_reset(p->ssi_vars);
34711         array_reset(p->ssi_cgi_env);
34712         buffer_copy_string(p->timefmt, "%a, %d %b %Y %H:%M:%S %Z");
34713         p->sizefmt = 0;
34714         build_ssi_cgi_vars(srv, con, p);
34715         p->if_is_false = 0;
34716 -       
34717 +
34718         if (-1 == stream_open(&s, con->physical.path)) {
34719                 log_error_write(srv, __FILE__, __LINE__, "sb",
34720                                 "stream-open: ", con->physical.path);
34721                 return -1;
34722         }
34723 -       
34724 -       
34725 +
34726 +
34727         /**
34728 -        * <!--#element attribute=value attribute=value ... --> 
34729 -        * 
34730 +        * <!--#element attribute=value attribute=value ... -->
34731 +        *
34732          * config       DONE
34733 -        *   errmsg     -- missing 
34734 +        *   errmsg     -- missing
34735          *   sizefmt    DONE
34736          *   timefmt    DONE
34737          * echo         DONE
34738 @@ -937,13 +939,13 @@
34739          * set          DONE
34740          *   var        DONE
34741          *   value      DONE
34742 -        * 
34743 +        *
34744          * if           DONE
34745          * elif         DONE
34746          * else         DONE
34747          * endif        DONE
34748 -        * 
34749 -        * 
34750 +        *
34751 +        *
34752          * expressions
34753          * AND, OR      DONE
34754          * comp         DONE
34755 @@ -951,118 +953,115 @@
34756          * $...         DONE
34757          * '...'        DONE
34758          * ( ... )      DONE
34759 -        * 
34760 -        * 
34761 -        * 
34762 +        *
34763 +        *
34764 +        *
34765          * ** all DONE **
34766 -        * DATE_GMT 
34767 -        *   The current date in Greenwich Mean Time. 
34768 -        * DATE_LOCAL 
34769 -        *   The current date in the local time zone. 
34770 -        * DOCUMENT_NAME 
34771 -        *   The filename (excluding directories) of the document requested by the user. 
34772 -        * DOCUMENT_URI 
34773 -        *   The (%-decoded) URL path of the document requested by the user. Note that in the case of nested include files, this is not then URL for the current document. 
34774 -        * LAST_MODIFIED 
34775 -        *   The last modification date of the document requested by the user. 
34776 -        * USER_NAME 
34777 +        * DATE_GMT
34778 +        *   The current date in Greenwich Mean Time.
34779 +        * DATE_LOCAL
34780 +        *   The current date in the local time zone.
34781 +        * DOCUMENT_NAME
34782 +        *   The filename (excluding directories) of the document requested by the user.
34783 +        * DOCUMENT_URI
34784 +        *   The (%-decoded) URL path of the document requested by the user. Note that in the case of nested include files, this is not then URL for the current document.
34785 +        * LAST_MODIFIED
34786 +        *   The last modification date of the document requested by the user.
34787 +        * USER_NAME
34788          *   Contains the owner of the file which included it.
34789 -        * 
34790 +        *
34791          */
34792 -#ifdef HAVE_PCRE_H     
34793 +#ifdef HAVE_PCRE_H
34794         for (i = 0; (n = pcre_exec(p->ssi_regex, NULL, s.start, s.size, i, 0, ovec, N * 3)) > 0; i = ovec[1]) {
34795                 const char **l;
34796                 /* take everything from last offset to current match pos */
34797 -               
34798 +
34799                 if (!p->if_is_false) chunkqueue_append_file(con->write_queue, con->physical.path, i, ovec[0] - i);
34800 -               
34801 +
34802                 pcre_get_substring_list(s.start, ovec, n, &l);
34803                 process_ssi_stmt(srv, con, p, l, n);
34804                 pcre_free_substring_list(l);
34805         }
34806 -       
34807 +
34808         switch(n) {
34809         case PCRE_ERROR_NOMATCH:
34810                 /* copy everything/the rest */
34811                 chunkqueue_append_file(con->write_queue, con->physical.path, i, s.size - i);
34812 -               
34813 +
34814                 break;
34815         default:
34816                 log_error_write(srv, __FILE__, __LINE__, "sd",
34817                                 "execution error while matching: ", n);
34818                 break;
34819         }
34820 -#endif 
34821 -       
34822 -       
34823 +#endif
34824 +
34825 +
34826         stream_close(&s);
34827 -       
34828 +
34829         con->file_started  = 1;
34830         con->file_finished = 1;
34831 -       
34832 +
34833         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
34834 -       
34835 +
34836         /* reset physical.path */
34837         buffer_reset(con->physical.path);
34838 -       
34839 +
34840         return 0;
34841  }
34842  
34843 -#define PATCH(x) \
34844 -       p->conf.x = s->x;
34845  static int mod_ssi_patch_connection(server *srv, connection *con, plugin_data *p) {
34846         size_t i, j;
34847         plugin_config *s = p->config_storage[0];
34848 -       
34849 -       PATCH(ssi_extension);
34850 -       
34851 +
34852 +       PATCH_OPTION(ssi_extension);
34853 +
34854         /* skip the first, the global context */
34855         for (i = 1; i < srv->config_context->used; i++) {
34856                 data_config *dc = (data_config *)srv->config_context->data[i];
34857                 s = p->config_storage[i];
34858 -               
34859 +
34860                 /* condition didn't match */
34861                 if (!config_check_cond(srv, con, dc)) continue;
34862 -               
34863 +
34864                 /* merge config */
34865                 for (j = 0; j < dc->value->used; j++) {
34866                         data_unset *du = dc->value->data[j];
34867 -                       
34868 +
34869                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssi.extension"))) {
34870 -                               PATCH(ssi_extension);
34871 +                               PATCH_OPTION(ssi_extension);
34872                         }
34873                 }
34874         }
34875 -       
34876 +
34877         return 0;
34878  }
34879 -#undef PATCH
34880  
34881  URIHANDLER_FUNC(mod_ssi_physical_path) {
34882         plugin_data *p = p_d;
34883         size_t k;
34884 -       
34885 +
34886         if (con->physical.path->used == 0) return HANDLER_GO_ON;
34887 -       
34888 +
34889         mod_ssi_patch_connection(srv, con, p);
34890 -       
34891 +
34892         for (k = 0; k < p->conf.ssi_extension->used; k++) {
34893                 data_string *ds = (data_string *)p->conf.ssi_extension->data[k];
34894 -               
34895 +
34896                 if (ds->value->used == 0) continue;
34897 -               
34898 +
34899                 if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
34900                         /* handle ssi-request */
34901 -                       
34902 +
34903                         if (mod_ssi_handle_request(srv, con, p)) {
34904                                 /* on error */
34905                                 con->http_status = 500;
34906                         }
34907 -                       
34908 +
34909                         return HANDLER_FINISHED;
34910                 }
34911         }
34912 -       
34913 +
34914         /* not found */
34915         return HANDLER_GO_ON;
34916  }
34917 @@ -1072,13 +1071,13 @@
34918  int mod_ssi_plugin_init(plugin *p) {
34919         p->version     = LIGHTTPD_VERSION_ID;
34920         p->name        = buffer_init_string("ssi");
34921 -       
34922 +
34923         p->init        = mod_ssi_init;
34924         p->handle_subrequest_start = mod_ssi_physical_path;
34925         p->set_defaults  = mod_ssi_set_defaults;
34926         p->cleanup     = mod_ssi_free;
34927 -       
34928 +
34929         p->data        = NULL;
34930 -       
34931 +
34932         return 0;
34933  }
34934 --- lighttpd-1.4.11/src/mod_ssi.h       2005-08-11 01:26:39.000000000 +0300
34935 +++ lighttpd-1.4.12/src/mod_ssi.h       2006-07-11 22:07:53.000000000 +0300
34936 @@ -19,23 +19,23 @@
34937  
34938  typedef struct {
34939         PLUGIN_DATA;
34940 -       
34941 -#ifdef HAVE_PCRE_H     
34942 +
34943 +#ifdef HAVE_PCRE_H
34944         pcre *ssi_regex;
34945 -#endif 
34946 +#endif
34947         buffer *timefmt;
34948         int sizefmt;
34949 -       
34950 +
34951         buffer *stat_fn;
34952 -       
34953 +
34954         array *ssi_vars;
34955         array *ssi_cgi_env;
34956 -       
34957 +
34958         int if_level, if_is_false_level, if_is_false, if_is_false_endif;
34959 -       
34960 +
34961         plugin_config **config_storage;
34962 -       
34963 -       plugin_config conf; 
34964 +
34965 +       plugin_config conf;
34966  } plugin_data;
34967  
34968  int ssi_eval_expr(server *srv, connection *con, plugin_data *p, const char *expr);
34969 --- lighttpd-1.4.11/src/mod_ssi_expr.c  2005-08-11 01:26:48.000000000 +0300
34970 +++ lighttpd-1.4.12/src/mod_ssi_expr.c  2006-07-11 22:07:52.000000000 +0300
34971 @@ -11,9 +11,9 @@
34972         const char *input;
34973         size_t offset;
34974         size_t size;
34975 -       
34976 +
34977         int line_pos;
34978 -       
34979 +
34980         int in_key;
34981         int in_brace;
34982         int in_cond;
34983 @@ -21,15 +21,15 @@
34984  
34985  ssi_val_t *ssi_val_init() {
34986         ssi_val_t *s;
34987 -       
34988 +
34989         s = calloc(1, sizeof(*s));
34990 -       
34991 +
34992         return s;
34993  }
34994  
34995  void ssi_val_free(ssi_val_t *s) {
34996         if (s->str) buffer_free(s->str);
34997 -       
34998 +
34999         free(s);
35000  }
35001  
35002 @@ -45,175 +45,175 @@
35003                               ssi_tokenizer_t *t, int *token_id, buffer *token) {
35004         int tid = 0;
35005         size_t i;
35006 -       
35007 +
35008         UNUSED(con);
35009  
35010         for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
35011                 char c = t->input[t->offset];
35012                 data_string *ds;
35013 -               
35014 +
35015                 switch (c) {
35016 -               case '=': 
35017 +               case '=':
35018                         tid = TK_EQ;
35019 -                       
35020 +
35021                         t->offset++;
35022                         t->line_pos++;
35023 -                       
35024 +
35025                         buffer_copy_string(token, "(=)");
35026 -                       
35027 +
35028                         break;
35029                 case '>':
35030                         if (t->input[t->offset + 1] == '=') {
35031                                 t->offset += 2;
35032                                 t->line_pos += 2;
35033 -                               
35034 +
35035                                 tid = TK_GE;
35036 -                               
35037 +
35038                                 buffer_copy_string(token, "(>=)");
35039                         } else {
35040                                 t->offset += 1;
35041                                 t->line_pos += 1;
35042 -                               
35043 +
35044                                 tid = TK_GT;
35045 -                               
35046 +
35047                                 buffer_copy_string(token, "(>)");
35048                         }
35049 -                       
35050 +
35051                         break;
35052                 case '<':
35053                         if (t->input[t->offset + 1] == '=') {
35054                                 t->offset += 2;
35055                                 t->line_pos += 2;
35056 -                               
35057 +
35058                                 tid = TK_LE;
35059 -                               
35060 +
35061                                 buffer_copy_string(token, "(<=)");
35062                         } else {
35063                                 t->offset += 1;
35064                                 t->line_pos += 1;
35065 -                               
35066 +
35067                                 tid = TK_LT;
35068 -                               
35069 +
35070                                 buffer_copy_string(token, "(<)");
35071                         }
35072 -                       
35073 +
35074                         break;
35075 -                       
35076 +
35077                 case '!':
35078                         if (t->input[t->offset + 1] == '=') {
35079                                 t->offset += 2;
35080                                 t->line_pos += 2;
35081 -                               
35082 +
35083                                 tid = TK_NE;
35084 -                               
35085 +
35086                                 buffer_copy_string(token, "(!=)");
35087                         } else {
35088                                 t->offset += 1;
35089                                 t->line_pos += 1;
35090 -                               
35091 +
35092                                 tid = TK_NOT;
35093 -                               
35094 +
35095                                 buffer_copy_string(token, "(!)");
35096                         }
35097 -                       
35098 +
35099                         break;
35100                 case '&':
35101                         if (t->input[t->offset + 1] == '&') {
35102                                 t->offset += 2;
35103                                 t->line_pos += 2;
35104 -                               
35105 +
35106                                 tid = TK_AND;
35107 -                               
35108 +
35109                                 buffer_copy_string(token, "(&&)");
35110                         } else {
35111 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
35112 -                                               "pos:", t->line_pos, 
35113 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
35114 +                                               "pos:", t->line_pos,
35115                                                 "missing second &");
35116                                 return -1;
35117                         }
35118 -                       
35119 +
35120                         break;
35121                 case '|':
35122                         if (t->input[t->offset + 1] == '|') {
35123                                 t->offset += 2;
35124                                 t->line_pos += 2;
35125 -                               
35126 +
35127                                 tid = TK_OR;
35128 -                               
35129 +
35130                                 buffer_copy_string(token, "(||)");
35131                         } else {
35132 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
35133 -                                               "pos:", t->line_pos, 
35134 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
35135 +                                               "pos:", t->line_pos,
35136                                                 "missing second |");
35137                                 return -1;
35138                         }
35139 -                       
35140 +
35141                         break;
35142                 case '\t':
35143                 case ' ':
35144                         t->offset++;
35145                         t->line_pos++;
35146                         break;
35147 -                       
35148 +
35149                 case '\'':
35150                         /* search for the terminating " */
35151                         for (i = 1; t->input[t->offset + i] && t->input[t->offset + i] != '\'';  i++);
35152 -                       
35153 +
35154                         if (t->input[t->offset + i]) {
35155                                 tid = TK_VALUE;
35156 -                               
35157 +
35158                                 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
35159 -                               
35160 +
35161                                 t->offset += i + 1;
35162                                 t->line_pos += i + 1;
35163                         } else {
35164                                 /* ERROR */
35165 -                               
35166 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
35167 -                                               "pos:", t->line_pos, 
35168 +
35169 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
35170 +                                               "pos:", t->line_pos,
35171                                                 "missing closing quote");
35172 -                               
35173 +
35174                                 return -1;
35175                         }
35176 -                       
35177 +
35178                         break;
35179                 case '(':
35180                         t->offset++;
35181                         t->in_brace++;
35182 -                               
35183 +
35184                         tid = TK_LPARAN;
35185 -                               
35186 +
35187                         buffer_copy_string(token, "(");
35188                         break;
35189                 case ')':
35190                         t->offset++;
35191                         t->in_brace--;
35192 -                               
35193 +
35194                         tid = TK_RPARAN;
35195 -                               
35196 +
35197                         buffer_copy_string(token, ")");
35198                         break;
35199                 case '$':
35200                         if (t->input[t->offset + 1] == '{') {
35201                                 for (i = 2; t->input[t->offset + i] && t->input[t->offset + i] != '}';  i++);
35202 -                               
35203 +
35204                                 if (t->input[t->offset + i] != '}') {
35205 -                                       log_error_write(srv, __FILE__, __LINE__, "sds", 
35206 -                                                       "pos:", t->line_pos, 
35207 +                                       log_error_write(srv, __FILE__, __LINE__, "sds",
35208 +                                                       "pos:", t->line_pos,
35209                                                         "missing closing quote");
35210 -                                       
35211 +
35212                                         return -1;
35213                                 }
35214 -                               
35215 +
35216                                 buffer_copy_string_len(token, t->input + t->offset + 2, i-3);
35217                         } else {
35218                                 for (i = 1; isalpha(t->input[t->offset + i]) || t->input[t->offset + i] == '_';  i++);
35219 -                               
35220 +
35221                                 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
35222                         }
35223 -                       
35224 +
35225                         tid = TK_VALUE;
35226 -                       
35227 +
35228                         if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, token->ptr))) {
35229                                 buffer_copy_string_buffer(token, ds->value);
35230                         } else if (NULL != (ds = (data_string *)array_get_element(p->ssi_vars, token->ptr))) {
35231 @@ -221,16 +221,16 @@
35232                         } else {
35233                                 buffer_copy_string(token, "");
35234                         }
35235 -                               
35236 +
35237                         t->offset += i;
35238                         t->line_pos += i;
35239 -                       
35240 +
35241                         break;
35242                 default:
35243                         for (i = 0; isgraph(t->input[t->offset + i]);  i++) {
35244                                 char d = t->input[t->offset + i];
35245                                 switch(d) {
35246 -                               case ' ': 
35247 +                               case ' ':
35248                                 case '\t':
35249                                 case ')':
35250                                 case '(':
35251 @@ -244,25 +244,25 @@
35252                                         break;
35253                                 }
35254                         }
35255 -                       
35256 +
35257                         tid = TK_VALUE;
35258 -                               
35259 +
35260                         buffer_copy_string_len(token, t->input + t->offset, i);
35261 -                               
35262 +
35263                         t->offset += i;
35264                         t->line_pos += i;
35265 -                       
35266 +
35267                         break;
35268                 }
35269         }
35270 -                       
35271 +
35272         if (tid) {
35273                 *token_id = tid;
35274 -               
35275 +
35276                 return 1;
35277         } else if (t->offset < t->size) {
35278 -               log_error_write(srv, __FILE__, __LINE__, "sds", 
35279 -                               "pos:", t->line_pos, 
35280 +               log_error_write(srv, __FILE__, __LINE__, "sds",
35281 +                               "pos:", t->line_pos,
35282                                 "foobar");
35283         }
35284         return 0;
35285 @@ -275,50 +275,50 @@
35286         buffer *token;
35287         ssi_ctx_t context;
35288         int ret;
35289 -       
35290 +
35291         t.input = expr;
35292         t.offset = 0;
35293         t.size = strlen(expr);
35294         t.line_pos = 1;
35295 -       
35296 +
35297         t.in_key = 1;
35298         t.in_brace = 0;
35299         t.in_cond = 0;
35300 -       
35301 +
35302         context.ok = 1;
35303         context.srv = srv;
35304 -       
35305 +
35306         /* default context */
35307 -       
35308 +
35309         pParser = ssiexprparserAlloc( malloc );
35310         token = buffer_init();
35311         while((1 == (ret = ssi_expr_tokenizer(srv, con, p, &t, &token_id, token))) && context.ok) {
35312                 ssiexprparser(pParser, token_id, token, &context);
35313 -               
35314 +
35315                 token = buffer_init();
35316         }
35317         ssiexprparser(pParser, 0, token, &context);
35318         ssiexprparserFree(pParser, free );
35319 -       
35320 +
35321         buffer_free(token);
35322 -       
35323 +
35324         if (ret == -1) {
35325 -               log_error_write(srv, __FILE__, __LINE__, "s", 
35326 +               log_error_write(srv, __FILE__, __LINE__, "s",
35327                                 "expr parser failed");
35328                 return -1;
35329         }
35330 -       
35331 +
35332         if (context.ok == 0) {
35333 -               log_error_write(srv, __FILE__, __LINE__, "sds", 
35334 -                               "pos:", t.line_pos, 
35335 +               log_error_write(srv, __FILE__, __LINE__, "sds",
35336 +                               "pos:", t.line_pos,
35337                                 "parser failed somehow near here");
35338                 return -1;
35339         }
35340  #if 0
35341 -       log_error_write(srv, __FILE__, __LINE__, "ssd", 
35342 +       log_error_write(srv, __FILE__, __LINE__, "ssd",
35343                         "expr: ",
35344                         expr,
35345                         context.val.bo);
35346 -#endif 
35347 +#endif
35348         return context.val.bo;
35349  }
35350 --- lighttpd-1.4.11/src/mod_ssi_expr.h  2005-08-11 01:26:48.000000000 +0300
35351 +++ lighttpd-1.4.12/src/mod_ssi_expr.h  2006-07-11 22:07:52.000000000 +0300
35352 @@ -5,16 +5,16 @@
35353  
35354  typedef struct {
35355         enum { SSI_TYPE_UNSET, SSI_TYPE_BOOL, SSI_TYPE_STRING } type;
35356 -       
35357 +
35358         buffer *str;
35359         int     bo;
35360  } ssi_val_t;
35361  
35362  typedef struct {
35363         int     ok;
35364 -       
35365 +
35366         ssi_val_t val;
35367 -       
35368 +
35369         void   *srv;
35370  } ssi_ctx_t;
35371  
35372 --- lighttpd-1.4.11/src/mod_ssi_exprparser.c    2005-10-03 00:40:25.000000000 +0300
35373 +++ lighttpd-1.4.12/src/mod_ssi_exprparser.c    2006-07-11 22:08:02.000000000 +0300
35374 @@ -18,10 +18,10 @@
35375  /* Next is all token values, in a form suitable for use by makeheaders.
35376  ** This section will be null unless lemon is run with the -m switch.
35377  */
35378 -/* 
35379 +/*
35380  ** These constants (all generated automatically by the parser generator)
35381  ** specify the various kinds of tokens (terminals) that the parser
35382 -** understands. 
35383 +** understands.
35384  **
35385  ** Each symbol here is a terminal symbol in the grammar.
35386  */
35387 @@ -38,7 +38,7 @@
35388  **                       and nonterminals.  "int" is used otherwise.
35389  **    YYNOCODE           is a number of type YYCODETYPE which corresponds
35390  **                       to no legal terminal or nonterminal number.  This
35391 -**                       number is used to fill in empty slots of the hash 
35392 +**                       number is used to fill in empty slots of the hash
35393  **                       table.
35394  **    YYFALLBACK         If defined, this indicates that one or more tokens
35395  **                       have fall-back values which should be used if the
35396 @@ -47,7 +47,7 @@
35397  **                       and nonterminal numbers.  "unsigned char" is
35398  **                       used if there are fewer than 250 rules and
35399  **                       states combined.  "int" is used otherwise.
35400 -**    ssiexprparserTOKENTYPE     is the data type used for minor tokens given 
35401 +**    ssiexprparserTOKENTYPE     is the data type used for minor tokens given
35402  **                       directly to the parser from the tokenizer.
35403  **    YYMINORTYPE        is the data type used for all minor tokens.
35404  **                       This is typically a union of many types, one of
35405 @@ -91,7 +91,7 @@
35406  /* Next are that tables used to determine what action to take based on the
35407  ** current state and lookahead token.  These tables are used to implement
35408  ** functions that take a state number and lookahead value and return an
35409 -** action integer.  
35410 +** action integer.
35411  **
35412  ** Suppose the action integer is N.  Then the action is determined as
35413  ** follows
35414 @@ -116,7 +116,7 @@
35415  ** If the index value yy_shift_ofst[S]+X is out of range or if the value
35416  ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
35417  ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
35418 -** and that yy_default[S] should be used instead.  
35419 +** and that yy_default[S] should be used instead.
35420  **
35421  ** The formula above is for computing the action when the lookahead is
35422  ** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
35423 @@ -168,7 +168,7 @@
35424  
35425  /* The next table maps tokens into fallback tokens.  If a construct
35426  ** like the following:
35427 -** 
35428 +**
35429  **      %fallback ID X Y Z.
35430  **
35431  ** appears in the grammer, then ID becomes a fallback token for X, Y,
35432 @@ -219,10 +219,10 @@
35433  #endif /* NDEBUG */
35434  
35435  #ifndef NDEBUG
35436 -/* 
35437 +/*
35438  ** Turn parser tracing on by giving a stream to which to write the trace
35439  ** and a prompt to preface each trace message.  Tracing is turned off
35440 -** by making either argument NULL 
35441 +** by making either argument NULL
35442  **
35443  ** Inputs:
35444  ** <ul>
35445 @@ -247,7 +247,7 @@
35446  #ifndef NDEBUG
35447  /* For tracing shifts, the names of all terminals and nonterminals
35448  ** are required.  The following table supplies these names */
35449 -static const char *yyTokenName[] = { 
35450 +static const char *yyTokenName[] = {
35451    "$",             "AND",           "OR",            "EQ",          
35452    "NE",            "GT",            "GE",            "LT",          
35453    "LE",            "NOT",           "LPARAN",        "RPARAN",      
35454 @@ -295,7 +295,7 @@
35455  #endif
35456  }
35457  
35458 -/* 
35459 +/*
35460  ** This function allocates a new parser.
35461  ** The only argument is a pointer to a function which works like
35462  ** malloc.
35463 @@ -326,7 +326,7 @@
35464      /* Here is inserted the actions which take place when a
35465      ** terminal or non-terminal is destroyed.  This can happen
35466      ** when the symbol is popped from the stack during a
35467 -    ** reduce or during error processing or when a parser is 
35468 +    ** reduce or during error processing or when a parser is
35469      ** being destroyed before it is finished parsing.
35470      **
35471      ** Note: during a reduce, the only symbols destroyed are those
35472 @@ -379,7 +379,7 @@
35473    return yymajor;
35474  }
35475  
35476 -/* 
35477 +/*
35478  ** Deallocate and destroy a parser.  Destructors are all called for
35479  ** all stack elements before shutting the parser down.
35480  **
35481 @@ -415,7 +415,7 @@
35482  ){
35483    int i;
35484    int stateno = pParser->yystack[pParser->yyidx].stateno;
35485
35486 +
35487    /* if( pParser->yyidx<0 ) return YY_NO_ACTION;  */
35488    i = yy_shift_ofst[stateno];
35489    if( i==YY_SHIFT_USE_DFLT ){
35490 @@ -459,7 +459,7 @@
35491  ){
35492    int i;
35493    int stateno = pParser->yystack[pParser->yyidx].stateno;
35494
35495 +
35496    i = yy_reduce_ofst[stateno];
35497    if( i==YY_REDUCE_USE_DFLT ){
35498      return yy_default[stateno];
35499 @@ -559,7 +559,7 @@
35500    ssiexprparserARG_FETCH;
35501    yymsp = &yypParser->yystack[yypParser->yyidx];
35502  #ifndef NDEBUG
35503 -  if( yyTraceFILE && yyruleno>=0 
35504 +  if( yyTraceFILE && yyruleno>=0
35505          && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
35506      fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
35507        yyRuleName[yyruleno]);
35508 @@ -872,7 +872,7 @@
35509  #ifdef YYERRORSYMBOL
35510        /* A syntax error has occurred.
35511        ** The response to an error depends upon whether or not the
35512 -      ** grammar defines an error token "ERROR".  
35513 +      ** grammar defines an error token "ERROR".
35514        **
35515        ** This is what we do if the grammar does define ERROR:
35516        **
35517 --- lighttpd-1.4.11/src/mod_staticfile.c        2006-02-15 14:31:14.000000000 +0200
35518 +++ lighttpd-1.4.12/src/mod_staticfile.c        2006-07-11 22:07:51.000000000 +0300
35519 @@ -14,9 +14,11 @@
35520  #include "http_chunk.h"
35521  #include "response.h"
35522  
35523 +#include "sys-files.h"
35524 +#include "sys-strings.h"
35525  /**
35526   * this is a staticfile for a lighttpd plugin
35527 - * 
35528 + *
35529   */
35530  
35531  
35532 @@ -29,48 +31,48 @@
35533  
35534  typedef struct {
35535         PLUGIN_DATA;
35536 -       
35537 +
35538         buffer *range_buf;
35539 -       
35540 +
35541         plugin_config **config_storage;
35542 -       
35543 -       plugin_config conf; 
35544 +
35545 +       plugin_config conf;
35546  } plugin_data;
35547  
35548  /* init the plugin data */
35549  INIT_FUNC(mod_staticfile_init) {
35550         plugin_data *p;
35551 -       
35552 +
35553         p = calloc(1, sizeof(*p));
35554 -       
35555 +
35556         p->range_buf = buffer_init();
35557 -       
35558 +
35559         return p;
35560  }
35561  
35562 -/* detroy the plugin data */
35563 +/* destroy the plugin data */
35564  FREE_FUNC(mod_staticfile_free) {
35565         plugin_data *p = p_d;
35566 -       
35567 +
35568         UNUSED(srv);
35569  
35570         if (!p) return HANDLER_GO_ON;
35571 -       
35572 +
35573         if (p->config_storage) {
35574                 size_t i;
35575                 for (i = 0; i < srv->config_context->used; i++) {
35576                         plugin_config *s = p->config_storage[i];
35577 -                       
35578 +
35579                         array_free(s->exclude_ext);
35580 -                       
35581 +
35582                         free(s);
35583                 }
35584                 free(p->config_storage);
35585         }
35586         buffer_free(p->range_buf);
35587 -       
35588 +
35589         free(p);
35590 -       
35591 +
35592         return HANDLER_GO_ON;
35593  }
35594  
35595 @@ -79,63 +81,60 @@
35596  SETDEFAULTS_FUNC(mod_staticfile_set_defaults) {
35597         plugin_data *p = p_d;
35598         size_t i = 0;
35599 -       
35600 -       config_values_t cv[] = { 
35601 +
35602 +       config_values_t cv[] = {
35603                 { "static-file.exclude-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
35604                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
35605         };
35606 -       
35607 +
35608         if (!p) return HANDLER_ERROR;
35609 -       
35610 +
35611         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
35612 -       
35613 +
35614         for (i = 0; i < srv->config_context->used; i++) {
35615                 plugin_config *s;
35616 -               
35617 +
35618                 s = calloc(1, sizeof(plugin_config));
35619                 s->exclude_ext    = array_init();
35620 -               
35621 +
35622                 cv[0].destination = s->exclude_ext;
35623 -               
35624 +
35625                 p->config_storage[i] = s;
35626 -       
35627 +
35628                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
35629                         return HANDLER_ERROR;
35630                 }
35631         }
35632 -       
35633 +
35634         return HANDLER_GO_ON;
35635  }
35636  
35637 -#define PATCH(x) \
35638 -       p->conf.x = s->x;
35639  static int mod_staticfile_patch_connection(server *srv, connection *con, plugin_data *p) {
35640         size_t i, j;
35641         plugin_config *s = p->config_storage[0];
35642 -       
35643 -       PATCH(exclude_ext);
35644 -       
35645 +
35646 +       PATCH_OPTION(exclude_ext);
35647 +
35648         /* skip the first, the global context */
35649         for (i = 1; i < srv->config_context->used; i++) {
35650                 data_config *dc = (data_config *)srv->config_context->data[i];
35651                 s = p->config_storage[i];
35652 -               
35653 +
35654                 /* condition didn't match */
35655                 if (!config_check_cond(srv, con, dc)) continue;
35656 -               
35657 +
35658                 /* merge config */
35659                 for (j = 0; j < dc->value->used; j++) {
35660                         data_unset *du = dc->value->data[j];
35661 -                       
35662 +
35663                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("static-file.exclude-extensions"))) {
35664 -                               PATCH(exclude_ext);
35665 +                               PATCH_OPTION(exclude_ext);
35666                         }
35667                 }
35668         }
35669 -       
35670 +
35671         return 0;
35672  }
35673 -#undef PATCH
35674  
35675  static int http_response_parse_range(server *srv, connection *con, plugin_data *p) {
35676         int multipart = 0;
35677 @@ -146,69 +145,69 @@
35678         data_string *ds;
35679         stat_cache_entry *sce = NULL;
35680         buffer *content_type = NULL;
35681 -       
35682 +
35683         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
35684                 SEGFAULT();
35685         }
35686 -       
35687 +
35688         start = 0;
35689         end = sce->st.st_size - 1;
35690 -       
35691 +
35692         con->response.content_length = 0;
35693 -       
35694 +
35695         if (NULL != (ds = (data_string *)array_get_element(con->response.headers, "Content-Type"))) {
35696                 content_type = ds->value;
35697         }
35698 -       
35699 +
35700         for (s = con->request.http_range, error = 0;
35701              !error && *s && NULL != (minus = strchr(s, '-')); ) {
35702                 char *err;
35703                 off_t la, le;
35704 -               
35705 +
35706                 if (s == minus) {
35707                         /* -<stop> */
35708 -                       
35709 +
35710                         le = strtoll(s, &err, 10);
35711 -                       
35712 +
35713                         if (le == 0) {
35714                                 /* RFC 2616 - 14.35.1 */
35715 -                               
35716 +
35717                                 con->http_status = 416;
35718                                 error = 1;
35719                         } else if (*err == '\0') {
35720                                 /* end */
35721                                 s = err;
35722 -                               
35723 +
35724                                 end = sce->st.st_size - 1;
35725                                 start = sce->st.st_size + le;
35726                         } else if (*err == ',') {
35727                                 multipart = 1;
35728                                 s = err + 1;
35729 -                               
35730 +
35731                                 end = sce->st.st_size - 1;
35732                                 start = sce->st.st_size + le;
35733                         } else {
35734                                 error = 1;
35735                         }
35736 -                       
35737 +
35738                 } else if (*(minus+1) == '\0' || *(minus+1) == ',') {
35739                         /* <start>- */
35740 -                       
35741 +
35742                         la = strtoll(s, &err, 10);
35743 -                       
35744 +
35745                         if (err == minus) {
35746                                 /* ok */
35747 -                               
35748 +
35749                                 if (*(err + 1) == '\0') {
35750                                         s = err + 1;
35751 -                                       
35752 +
35753                                         end = sce->st.st_size - 1;
35754                                         start = la;
35755 -                                       
35756 +
35757                                 } else if (*(err + 1) == ',') {
35758                                         multipart = 1;
35759                                         s = err + 2;
35760 -                                       
35761 +
35762                                         end = sce->st.st_size - 1;
35763                                         start = la;
35764                                 } else {
35765 @@ -220,64 +219,64 @@
35766                         }
35767                 } else {
35768                         /* <start>-<stop> */
35769 -                       
35770 +
35771                         la = strtoll(s, &err, 10);
35772 -                       
35773 +
35774                         if (err == minus) {
35775                                 le = strtoll(minus+1, &err, 10);
35776 -                               
35777 +
35778                                 /* RFC 2616 - 14.35.1 */
35779                                 if (la > le) {
35780                                         error = 1;
35781                                 }
35782 -                                       
35783 +
35784                                 if (*err == '\0') {
35785                                         /* ok, end*/
35786                                         s = err;
35787 -                                       
35788 +
35789                                         end = le;
35790                                         start = la;
35791                                 } else if (*err == ',') {
35792                                         multipart = 1;
35793                                         s = err + 1;
35794 -                                       
35795 +
35796                                         end = le;
35797                                         start = la;
35798                                 } else {
35799                                         /* error */
35800 -                                       
35801 +
35802                                         error = 1;
35803                                 }
35804                         } else {
35805                                 /* error */
35806 -                               
35807 +
35808                                 error = 1;
35809                         }
35810                 }
35811 -               
35812 +
35813                 if (!error) {
35814                         if (start < 0) start = 0;
35815 -                       
35816 +
35817                         /* RFC 2616 - 14.35.1 */
35818                         if (end > sce->st.st_size - 1) end = sce->st.st_size - 1;
35819 -                       
35820 +
35821                         if (start > sce->st.st_size - 1) {
35822                                 error = 1;
35823 -                               
35824 +
35825                                 con->http_status = 416;
35826                         }
35827                 }
35828 -               
35829 +
35830                 if (!error) {
35831                         if (multipart) {
35832                                 /* write boundary-header */
35833                                 buffer *b;
35834 -                               
35835 +
35836                                 b = chunkqueue_get_append_buffer(con->write_queue);
35837 -                               
35838 +
35839                                 buffer_copy_string(b, "\r\n--");
35840                                 buffer_append_string(b, boundary);
35841 -                               
35842 +
35843                                 /* write Content-Range */
35844                                 buffer_append_string(b, "\r\nContent-Range: bytes ");
35845                                 buffer_append_off_t(b, start);
35846 @@ -285,54 +284,54 @@
35847                                 buffer_append_off_t(b, end);
35848                                 buffer_append_string(b, "/");
35849                                 buffer_append_off_t(b, sce->st.st_size);
35850 -                               
35851 +
35852                                 buffer_append_string(b, "\r\nContent-Type: ");
35853                                 buffer_append_string_buffer(b, content_type);
35854 -                               
35855 +
35856                                 /* write END-OF-HEADER */
35857                                 buffer_append_string(b, "\r\n\r\n");
35858 -                               
35859 +
35860                                 con->response.content_length += b->used - 1;
35861 -                               
35862 +
35863                         }
35864 -                       
35865 +
35866                         chunkqueue_append_file(con->write_queue, con->physical.path, start, end - start + 1);
35867                         con->response.content_length += end - start + 1;
35868                 }
35869         }
35870 -       
35871 +
35872         /* something went wrong */
35873         if (error) return -1;
35874 -       
35875 +
35876         if (multipart) {
35877                 /* add boundary end */
35878                 buffer *b;
35879 -               
35880 +
35881                 b = chunkqueue_get_append_buffer(con->write_queue);
35882 -               
35883 +
35884                 buffer_copy_string_len(b, "\r\n--", 4);
35885                 buffer_append_string(b, boundary);
35886                 buffer_append_string_len(b, "--\r\n", 4);
35887 -               
35888 +
35889                 con->response.content_length += b->used - 1;
35890 -               
35891 +
35892                 /* set header-fields */
35893 -               
35894 +
35895                 buffer_copy_string(p->range_buf, "multipart/byteranges; boundary=");
35896                 buffer_append_string(p->range_buf, boundary);
35897 -               
35898 +
35899                 /* overwrite content-type */
35900                 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(p->range_buf));
35901         } else {
35902                 /* add Content-Range-header */
35903 -               
35904 +
35905                 buffer_copy_string(p->range_buf, "bytes ");
35906                 buffer_append_off_t(p->range_buf, start);
35907                 buffer_append_string(p->range_buf, "-");
35908                 buffer_append_off_t(p->range_buf, end);
35909                 buffer_append_string(p->range_buf, "/");
35910                 buffer_append_off_t(p->range_buf, sce->st.st_size);
35911 -               
35912 +
35913                 response_header_insert(srv, con, CONST_STR_LEN("Content-Range"), CONST_BUF_LEN(p->range_buf));
35914         }
35915  
35916 @@ -347,12 +346,12 @@
35917         stat_cache_entry *sce = NULL;
35918         buffer *mtime;
35919         data_string *ds;
35920 -       
35921 +
35922         /* someone else has done a decision for us */
35923         if (con->http_status != 0) return HANDLER_GO_ON;
35924         if (con->uri.path->used == 0) return HANDLER_GO_ON;
35925         if (con->physical.path->used == 0) return HANDLER_GO_ON;
35926 -       
35927 +
35928         /* someone else has handled this request */
35929         if (con->mode != DIRECT) return HANDLER_GO_ON;
35930  
35931 @@ -365,52 +364,52 @@
35932         default:
35933                 return HANDLER_GO_ON;
35934         }
35935 -       
35936 +
35937         mod_staticfile_patch_connection(srv, con, p);
35938 -       
35939 +
35940         s_len = con->uri.path->used - 1;
35941 -       
35942 +
35943         /* ignore certain extensions */
35944         for (k = 0; k < p->conf.exclude_ext->used; k++) {
35945 -               ds = (data_string *)p->conf.exclude_ext->data[k]; 
35946 -               
35947 +               ds = (data_string *)p->conf.exclude_ext->data[k];
35948 +
35949                 if (ds->value->used == 0) continue;
35950  
35951                 if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
35952                         return HANDLER_GO_ON;
35953                 }
35954         }
35955 -       
35956 +
35957  
35958         if (con->conf.log_request_handling) {
35959                 log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling file as static file");
35960         }
35961 -       
35962 +
35963         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
35964                 con->http_status = 403;
35965 -               
35966 +
35967                 log_error_write(srv, __FILE__, __LINE__, "sbsb",
35968                                 "not a regular file:", con->uri.path,
35969                                 "->", con->physical.path);
35970 -               
35971 +
35972                 return HANDLER_FINISHED;
35973         }
35974 -       
35975 -       /* we only handline regular files */
35976 +
35977 +       /* we only handle regular files */
35978         if (!S_ISREG(sce->st.st_mode)) {
35979                 con->http_status = 404;
35980 -               
35981 +
35982                 if (con->conf.log_file_not_found) {
35983                         log_error_write(srv, __FILE__, __LINE__, "sbsb",
35984                                         "not a regular file:", con->uri.path,
35985                                         "->", sce->name);
35986                 }
35987 -               
35988 +
35989                 return HANDLER_FINISHED;
35990         }
35991  
35992 -       /* mod_compress might set several data directly, don't overwrite them */
35993 -       
35994 +       /* mod_compress might set several parameters directly; don't overwrite them */
35995 +
35996         /* set response content-type, if not set already */
35997  
35998         if (NULL == array_get_element(con->response.headers, "Content-Type")) {
35999 @@ -420,15 +419,15 @@
36000                         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
36001                 }
36002         }
36003 -       
36004 +
36005         if (NULL == array_get_element(con->response.headers, "ETag")) {
36006                 /* generate e-tag */
36007                 etag_mutate(con->physical.etag, sce->etag);
36008 -       
36009 +
36010                 response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
36011         }
36012         response_header_overwrite(srv, con, CONST_STR_LEN("Accept-Ranges"), CONST_STR_LEN("bytes"));
36013 -       
36014 +
36015         /* prepare header */
36016         if (NULL == (ds = (data_string *)array_get_element(con->response.headers, "Last-Modified"))) {
36017                 mtime = strftime_cache_get(srv, sce->st.st_mtime);
36018 @@ -444,34 +443,34 @@
36019                 /* check if we have a conditional GET */
36020  
36021                 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If-Range"))) {
36022 -                       /* if the value is the same as our ETag, we do a Range-request, 
36023 +                       /* if the value is the same as our ETag, we do a Range-request,
36024                          * otherwise a full 200 */
36025  
36026                         if (!buffer_is_equal(ds->value, con->physical.etag)) {
36027                                 do_range_request = 0;
36028                         }
36029                 }
36030 -       
36031 +
36032                 if (do_range_request) {
36033                         /* content prepared, I'm done */
36034                         con->file_finished = 1;
36035 -               
36036 +
36037                         if (0 == http_response_parse_range(srv, con, p)) {
36038                                 con->http_status = 206;
36039                         }
36040                         return HANDLER_FINISHED;
36041                 }
36042         }
36043 -       
36044 +
36045         /* if we are still here, prepare body */
36046 -       
36047 -       /* we add it here for all requests 
36048 -        * the HEAD request will drop it afterwards again 
36049 +
36050 +       /* we add it here for all requests
36051 +        * the HEAD request will drop it afterwards again
36052          */
36053         http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
36054 -       
36055 +
36056         con->file_finished = 1;
36057 -       
36058 +
36059         return HANDLER_FINISHED;
36060  }
36061  
36062 @@ -480,13 +479,13 @@
36063  int mod_staticfile_plugin_init(plugin *p) {
36064         p->version     = LIGHTTPD_VERSION_ID;
36065         p->name        = buffer_init_string("staticfile");
36066 -       
36067 +
36068         p->init        = mod_staticfile_init;
36069         p->handle_subrequest_start = mod_staticfile_subrequest;
36070         p->set_defaults  = mod_staticfile_set_defaults;
36071         p->cleanup     = mod_staticfile_free;
36072 -       
36073 +
36074         p->data        = NULL;
36075 -       
36076 +
36077         return 0;
36078  }
36079 --- lighttpd-1.4.11/src/mod_status.c    2006-01-10 21:45:32.000000000 +0200
36080 +++ lighttpd-1.4.12/src/mod_status.c    2006-07-11 22:07:53.000000000 +0300
36081 @@ -4,7 +4,6 @@
36082  #include <fcntl.h>
36083  #include <stdlib.h>
36084  #include <string.h>
36085 -#include <unistd.h>
36086  #include <errno.h>
36087  #include <time.h>
36088  #include <stdio.h>
36089 @@ -29,114 +28,114 @@
36090  
36091  typedef struct {
36092         PLUGIN_DATA;
36093 -       
36094 +
36095         double traffic_out;
36096         double requests;
36097 -       
36098 +
36099         double mod_5s_traffic_out[5];
36100         double mod_5s_requests[5];
36101         size_t mod_5s_ndx;
36102 -       
36103 +
36104         double rel_traffic_out;
36105         double rel_requests;
36106 -       
36107 +
36108         double abs_traffic_out;
36109         double abs_requests;
36110 -       
36111 +
36112         double bytes_written;
36113 -       
36114 +
36115         buffer *module_list;
36116 -       
36117 +
36118         plugin_config **config_storage;
36119 -       
36120 -       plugin_config conf; 
36121 +
36122 +       plugin_config conf;
36123  } plugin_data;
36124  
36125  INIT_FUNC(mod_status_init) {
36126         plugin_data *p;
36127         size_t i;
36128 -       
36129 +
36130         p = calloc(1, sizeof(*p));
36131 -       
36132 +
36133         p->traffic_out = p->requests = 0;
36134         p->rel_traffic_out = p->rel_requests = 0;
36135         p->abs_traffic_out = p->abs_requests = 0;
36136         p->bytes_written = 0;
36137         p->module_list = buffer_init();
36138 -       
36139 +
36140         for (i = 0; i < 5; i++) {
36141                 p->mod_5s_traffic_out[i] = p->mod_5s_requests[i] = 0;
36142         }
36143 -       
36144 +
36145         return p;
36146  }
36147  
36148  FREE_FUNC(mod_status_free) {
36149         plugin_data *p = p_d;
36150 -       
36151 +
36152         UNUSED(srv);
36153  
36154         if (!p) return HANDLER_GO_ON;
36155 -       
36156 +
36157         buffer_free(p->module_list);
36158 -       
36159 +
36160         if (p->config_storage) {
36161                 size_t i;
36162                 for (i = 0; i < srv->config_context->used; i++) {
36163                         plugin_config *s = p->config_storage[i];
36164 -                       
36165 +
36166                         buffer_free(s->status_url);
36167                         buffer_free(s->statistics_url);
36168                         buffer_free(s->config_url);
36169 -                       
36170 +
36171                         free(s);
36172                 }
36173                 free(p->config_storage);
36174         }
36175 -       
36176 -       
36177 +
36178 +
36179         free(p);
36180 -       
36181 +
36182         return HANDLER_GO_ON;
36183  }
36184  
36185  SETDEFAULTS_FUNC(mod_status_set_defaults) {
36186         plugin_data *p = p_d;
36187         size_t i;
36188 -       
36189 -       config_values_t cv[] = { 
36190 +
36191 +       config_values_t cv[] = {
36192                 { "status.status-url",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
36193                 { "status.config-url",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
36194                 { "status.enable-sort",          NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
36195                 { "status.statistics-url",       NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
36196                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
36197         };
36198 -       
36199 +
36200         if (!p) return HANDLER_ERROR;
36201 -       
36202 +
36203         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
36204 -       
36205 +
36206         for (i = 0; i < srv->config_context->used; i++) {
36207                 plugin_config *s;
36208 -               
36209 +
36210                 s = calloc(1, sizeof(plugin_config));
36211                 s->config_url    = buffer_init();
36212                 s->status_url    = buffer_init();
36213                 s->sort          = 1;
36214                 s->statistics_url    = buffer_init();
36215 -               
36216 +
36217                 cv[0].destination = s->status_url;
36218                 cv[1].destination = s->config_url;
36219                 cv[2].destination = &(s->sort);
36220                 cv[3].destination = s->statistics_url;
36221 -               
36222 +
36223                 p->config_storage[i] = s;
36224 -       
36225 +
36226                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
36227                         return HANDLER_ERROR;
36228                 }
36229         }
36230 -       
36231 +
36232         return HANDLER_GO_ON;
36233  }
36234  
36235 @@ -151,7 +150,7 @@
36236         buffer_append_string(b, value);
36237         BUFFER_APPEND_STRING_CONST(b, "</td>\n");
36238         BUFFER_APPEND_STRING_CONST(b, "   </tr>\n");
36239 -       
36240 +
36241         return 0;
36242  }
36243  
36244 @@ -161,13 +160,13 @@
36245         buffer_append_string(b, key);
36246         BUFFER_APPEND_STRING_CONST(b, "</th>\n");
36247         BUFFER_APPEND_STRING_CONST(b, "   </tr>\n");
36248 -       
36249 +
36250         return 0;
36251  }
36252  
36253  static int mod_status_header_append_sort(buffer *b, void *p_d, const char* key) {
36254         plugin_data *p = p_d;
36255 -       
36256 +
36257         if (p->conf.sort) {
36258                 BUFFER_APPEND_STRING_CONST(b, "<th class=\"status\"><a href=\"#\" class=\"sortheader\" onclick=\"resort(this);return false;\">");
36259                 buffer_append_string(b, key);
36260 @@ -177,13 +176,13 @@
36261                 buffer_append_string(b, key);
36262                 BUFFER_APPEND_STRING_CONST(b, "</th>\n");
36263         }
36264 -       
36265 +
36266         return 0;
36267  }
36268  
36269  static int mod_status_get_multiplier(double *avg, char *multiplier, int size) {
36270         *multiplier = ' ';
36271 -       
36272 +
36273         if (*avg > size) { *avg /= size; *multiplier = 'k'; }
36274         if (*avg > size) { *avg /= size; *multiplier = 'M'; }
36275         if (*avg > size) { *avg /= size; *multiplier = 'G'; }
36276 @@ -202,21 +201,21 @@
36277         size_t j;
36278         double avg;
36279         char multiplier = '\0';
36280 -       char buf[32];
36281 +       char buf[128];
36282         time_t ts;
36283 -       
36284 +
36285         int days, hours, mins, seconds;
36286 -       
36287 +
36288         b = chunkqueue_get_append_buffer(con->write_queue);
36289  
36290 -       BUFFER_COPY_STRING_CONST(b, 
36291 +       BUFFER_COPY_STRING_CONST(b,
36292                                  "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
36293                                  "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
36294                                  "         \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
36295                                  "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
36296                                  " <head>\n"
36297                                  "  <title>Status</title>\n");
36298 -       
36299 +
36300         BUFFER_APPEND_STRING_CONST(b,
36301                                    "  <style type=\"text/css\">\n"
36302                                    "    table.status { border: black solid thin; }\n"
36303 @@ -226,14 +225,14 @@
36304                                    "    a.sortheader { background-color: black; color: white; font-weight: bold; text-decoration: none; display: block; }\n"
36305                                    "    span.sortarrow { color: white; text-decoration: none; }\n"
36306                                    "  </style>\n");
36307 -       
36308 +
36309         if (p->conf.sort) {
36310                 BUFFER_APPEND_STRING_CONST(b,
36311                                            "<script type=\"text/javascript\">\n"
36312                                            "// <!--\n"
36313                                            "var sort_column;\n"
36314                                            "var prev_span = null;\n");
36315 -               
36316 +
36317                 BUFFER_APPEND_STRING_CONST(b,
36318                                            "function get_inner_text(el) {\n"
36319                                            " if((typeof el == 'string')||(typeof el == 'undefined'))\n"
36320 @@ -251,7 +250,7 @@
36321                                            " }\n"
36322                                            " return str;\n"
36323                                            "}\n");
36324 -               
36325 +
36326                 BUFFER_APPEND_STRING_CONST(b,
36327                                            "function sortfn(a,b) {\n"
36328                                            " var at = get_inner_text(a.cells[sort_column]);\n"
36329 @@ -266,7 +265,7 @@
36330                                            "  else return 1;\n"
36331                                            " }\n"
36332                                            "}\n");
36333 -               
36334 +
36335                 BUFFER_APPEND_STRING_CONST(b,
36336                                            "function resort(lnk) {\n"
36337                                            " var span = lnk.childNodes[1];\n"
36338 @@ -276,7 +275,7 @@
36339                                            "  rows[j-1] = table.rows[j];\n"
36340                                            " sort_column = lnk.parentNode.cellIndex;\n"
36341                                            " rows.sort(sortfn);\n");
36342 -               
36343 +
36344                 BUFFER_APPEND_STRING_CONST(b,
36345                                            " if (prev_span != null) prev_span.innerHTML = '';\n"
36346                                            " if (span.getAttribute('sortdir')=='down') {\n"
36347 @@ -294,175 +293,175 @@
36348                                            "// -->\n"
36349                                            "</script>\n");
36350         }
36351 -       
36352 -       BUFFER_APPEND_STRING_CONST(b, 
36353 +
36354 +       BUFFER_APPEND_STRING_CONST(b,
36355                                  " </head>\n"
36356                                  " <body>\n");
36357 -       
36358 -       
36359 -       
36360 +
36361 +
36362 +
36363         /* connection listing */
36364         BUFFER_APPEND_STRING_CONST(b, "<h1>Server-Status</h1>");
36365 -       
36366 -       BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">");
36367 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\">");
36368 +
36369 +       BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" id=\"status\" summary=\"Server Status\">");
36370 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\"><span id=\"host_addr\">");
36371         buffer_append_string_buffer(b, con->uri.authority);
36372 -       BUFFER_APPEND_STRING_CONST(b, " (");
36373 +       BUFFER_APPEND_STRING_CONST(b, "</span> (<span id=\"host_name\">");
36374         buffer_append_string_buffer(b, con->server_name);
36375 -       BUFFER_APPEND_STRING_CONST(b, ")</td></tr>\n");
36376 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\">");
36377 -       
36378 +       BUFFER_APPEND_STRING_CONST(b, "</span>)</td></tr>\n");
36379 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\" id=\"uptime\">");
36380 +
36381         ts = srv->cur_ts - srv->startup_ts;
36382 -       
36383 +
36384         days = ts / (60 * 60 * 24);
36385         ts %= (60 * 60 * 24);
36386 -       
36387 +
36388         hours = ts / (60 * 60);
36389         ts %= (60 * 60);
36390 -       
36391 +
36392         mins = ts / (60);
36393         ts %= (60);
36394 -       
36395 +
36396         seconds = ts;
36397 -       
36398 +
36399         if (days) {
36400                 buffer_append_long(b, days);
36401                 BUFFER_APPEND_STRING_CONST(b, " days ");
36402         }
36403 -       
36404 +
36405         if (hours) {
36406                 buffer_append_long(b, hours);
36407                 BUFFER_APPEND_STRING_CONST(b, " hours ");
36408         }
36409 -       
36410 +
36411         if (mins) {
36412                 buffer_append_long(b, mins);
36413                 BUFFER_APPEND_STRING_CONST(b, " min ");
36414         }
36415 -       
36416 +
36417         buffer_append_long(b, seconds);
36418         BUFFER_APPEND_STRING_CONST(b, " s");
36419 -       
36420 +
36421         BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36422         BUFFER_APPEND_STRING_CONST(b, "<tr><td>Started at</td><td class=\"string\">");
36423 -       
36424 +
36425         ts = srv->startup_ts;
36426 -       
36427 -       strftime(buf, sizeof(buf) - 1, "%Y-%m-%d %H:%M:%S", localtime(&ts));
36428 +
36429 +       strftime(buf, sizeof(buf) - 1, "<span id=\"start_date\">%Y-%m-%d</span> <span id=\"start_time\">%H:%M:%S</span>", localtime(&ts));
36430         buffer_append_string(b, buf);
36431         BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36432 -       
36433 -       
36434 +
36435 +
36436         BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">absolute (since start)</th></tr>\n");
36437 -       
36438 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36439 +
36440 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\" ><span id=\"requests\">");
36441         avg = p->abs_requests;
36442  
36443         mod_status_get_multiplier(&avg, &multiplier, 1000);
36444 -       
36445 +
36446         buffer_append_long(b, avg);
36447 -       BUFFER_APPEND_STRING_CONST(b, " ");
36448 +       BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_mult\">");
36449         if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36450 -       BUFFER_APPEND_STRING_CONST(b, "req</td></tr>\n");
36451 -       
36452 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36453 +       BUFFER_APPEND_STRING_CONST(b, "</span>req</td></tr>\n");
36454 +
36455 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic\">");
36456         avg = p->abs_traffic_out;
36457  
36458         mod_status_get_multiplier(&avg, &multiplier, 1024);
36459  
36460         sprintf(buf, "%.2f", avg);
36461         buffer_append_string(b, buf);
36462 -       BUFFER_APPEND_STRING_CONST(b, " ");
36463 +       BUFFER_APPEND_STRING_CONST(b, "</span>  <span id=\"traffic_mult\">");
36464         if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36465 -       BUFFER_APPEND_STRING_CONST(b, "byte</td></tr>\n");
36466 +       BUFFER_APPEND_STRING_CONST(b, "</span>byte</td></tr>\n");
36467  
36468  
36469  
36470         BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (since start)</th></tr>\n");
36471 -       
36472 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36473 +
36474 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_avg\">");
36475         avg = p->abs_requests / (srv->cur_ts - srv->startup_ts);
36476  
36477         mod_status_get_multiplier(&avg, &multiplier, 1000);
36478  
36479         buffer_append_long(b, avg);
36480 -       BUFFER_APPEND_STRING_CONST(b, " ");
36481 +       BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_avg_mult\">");
36482         if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36483 -       BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
36484 -       
36485 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36486 +       BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
36487 +
36488 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic_avg\">");
36489         avg = p->abs_traffic_out / (srv->cur_ts - srv->startup_ts);
36490  
36491         mod_status_get_multiplier(&avg, &multiplier, 1024);
36492  
36493         sprintf(buf, "%.2f", avg);
36494         buffer_append_string(b, buf);
36495 -       BUFFER_APPEND_STRING_CONST(b, " ");
36496 +       BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"traffic_avg_mult\">");
36497         if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36498 -       BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
36499 +       BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
36500 +
36501 +
36502  
36503 -       
36504 -       
36505         BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (5s sliding average)</th></tr>\n");
36506         for (j = 0, avg = 0; j < 5; j++) {
36507                 avg += p->mod_5s_requests[j];
36508         }
36509 -       
36510 +
36511         avg /= 5;
36512 -       
36513 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36514 +
36515 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_sliding_avg\">");
36516  
36517         mod_status_get_multiplier(&avg, &multiplier, 1000);
36518  
36519         buffer_append_long(b, avg);
36520 -       BUFFER_APPEND_STRING_CONST(b, " ");
36521 +       BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_avg_mult\">");
36522         if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36523 -       
36524 -       BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
36525 -       
36526 +
36527 +       BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
36528 +
36529         for (j = 0, avg = 0; j < 5; j++) {
36530                 avg += p->mod_5s_traffic_out[j];
36531         }
36532 -       
36533 +
36534         avg /= 5;
36535 -       
36536 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36537 +
36538 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"requests_sliding_traffic\">");
36539  
36540         mod_status_get_multiplier(&avg, &multiplier, 1024);
36541  
36542         sprintf(buf, "%.2f", avg);
36543         buffer_append_string(b, buf);
36544 -       BUFFER_APPEND_STRING_CONST(b, " ");
36545 +       BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_traffic_mult\">");
36546         if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36547 -       BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
36548 -       
36549 +       BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
36550 +
36551         BUFFER_APPEND_STRING_CONST(b, "</table>\n");
36552 -       
36553 -       
36554 +
36555 +
36556         BUFFER_APPEND_STRING_CONST(b, "<hr />\n<pre><b>legend</b>\n");
36557         BUFFER_APPEND_STRING_CONST(b, ". = connect, C = close, E = hard error\n");
36558         BUFFER_APPEND_STRING_CONST(b, "r = read, R = read-POST, W = write, h = handle-request\n");
36559         BUFFER_APPEND_STRING_CONST(b, "q = request-start,  Q = request-end\n");
36560         BUFFER_APPEND_STRING_CONST(b, "s = response-start, S = response-end\n");
36561 -       
36562 -       BUFFER_APPEND_STRING_CONST(b, "<b>");
36563 +
36564 +       BUFFER_APPEND_STRING_CONST(b, "<strong><span id=\"connections\">");
36565         buffer_append_long(b, srv->conns->used);
36566 -       BUFFER_APPEND_STRING_CONST(b, " connections</b>\n");
36567 -       
36568 +       BUFFER_APPEND_STRING_CONST(b, "</span> connections</strong>\n");
36569 +
36570         for (j = 0; j < srv->conns->used; j++) {
36571                 connection *c = srv->conns->ptr[j];
36572                 const char *state = connection_get_short_state(c->state);
36573 -               
36574 +
36575                 buffer_append_string_len(b, state, 1);
36576 -               
36577 +
36578                 if (((j + 1) % 50) == 0) {
36579                         BUFFER_APPEND_STRING_CONST(b, "\n");
36580                 }
36581         }
36582 -       
36583 +
36584         BUFFER_APPEND_STRING_CONST(b, "\n</pre><hr />\n<h2>Connections</h2>\n");
36585 -       
36586 -       BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">\n");
36587 +
36588 +       BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" summary=\"Current connections\" id=\"clients\">\n");
36589         BUFFER_APPEND_STRING_CONST(b, "<tr>");
36590         mod_status_header_append_sort(b, p_d, "Client IP");
36591         mod_status_header_append_sort(b, p_d, "Read");
36592 @@ -473,16 +472,16 @@
36593         mod_status_header_append_sort(b, p_d, "URI");
36594         mod_status_header_append_sort(b, p_d, "File");
36595         BUFFER_APPEND_STRING_CONST(b, "</tr>\n");
36596 -       
36597 +
36598         for (j = 0; j < srv->conns->used; j++) {
36599                 connection *c = srv->conns->ptr[j];
36600 -               
36601 -               BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string\">");
36602 -               
36603 +
36604 +               BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string ip\">");
36605 +
36606                 buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(c->dst_addr)));
36607 -               
36608 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36609 -               
36610 +
36611 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_read\">");
36612 +
36613                 if (con->request.content_length) {
36614                         buffer_append_long(b, c->request_content_queue->bytes_in);
36615                         BUFFER_APPEND_STRING_CONST(b, "/");
36616 @@ -490,55 +489,55 @@
36617                 } else {
36618                         BUFFER_APPEND_STRING_CONST(b, "0/0");
36619                 }
36620 -       
36621 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36622 -               
36623 +
36624 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_written\">");
36625 +
36626                 buffer_append_off_t(b, chunkqueue_written(c->write_queue));
36627                 BUFFER_APPEND_STRING_CONST(b, "/");
36628                 buffer_append_off_t(b, chunkqueue_length(c->write_queue));
36629 -               
36630 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36631 -               
36632 +
36633 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string state\">");
36634 +
36635                 buffer_append_string(b, connection_get_state(c->state));
36636 -               
36637 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36638 -               
36639 +
36640 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int time\">");
36641 +
36642                 buffer_append_long(b, srv->cur_ts - c->request_start);
36643 -               
36644 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36645 -               
36646 +
36647 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string host\">");
36648 +
36649                 if (buffer_is_empty(c->server_name)) {
36650                         buffer_append_string_buffer(b, c->uri.authority);
36651                 }
36652                 else {
36653                         buffer_append_string_buffer(b, c->server_name);
36654                 }
36655 -               
36656 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36657 -               
36658 +
36659 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string uri\">");
36660 +
36661                 if (!buffer_is_empty(c->uri.path)) {
36662                         buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.path), ENCODING_HTML);
36663                 }
36664 -               
36665 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36666 -               
36667 +
36668 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string file\">");
36669 +
36670                 buffer_append_string_buffer(b, c->physical.path);
36671 -               
36672 +
36673                 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36674         }
36675 -       
36676 -       
36677 -       BUFFER_APPEND_STRING_CONST(b, 
36678 +
36679 +
36680 +       BUFFER_APPEND_STRING_CONST(b,
36681                       "</table>\n");
36682 -       
36683 -       
36684 -       BUFFER_APPEND_STRING_CONST(b, 
36685 +
36686 +
36687 +       BUFFER_APPEND_STRING_CONST(b,
36688                       " </body>\n"
36689                       "</html>\n"
36690                       );
36691 -       
36692 +
36693         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
36694 -       
36695 +
36696         return 0;
36697  }
36698  
36699 @@ -548,7 +547,7 @@
36700         buffer *b;
36701         double avg;
36702         time_t ts;
36703 -       
36704 +
36705         b = chunkqueue_get_append_buffer(con->write_queue);
36706  
36707         /* output total number of requests */
36708 @@ -556,19 +555,19 @@
36709         avg = p->abs_requests;
36710         buffer_append_long(b, avg);
36711         BUFFER_APPEND_STRING_CONST(b, "\n");
36712 -       
36713 +
36714         /* output total traffic out in kbytes */
36715         BUFFER_APPEND_STRING_CONST(b, "Total kBytes: ");
36716         avg = p->abs_traffic_out / 1024;
36717         buffer_append_long(b, avg);
36718         BUFFER_APPEND_STRING_CONST(b, "\n");
36719 -       
36720 +
36721         /* output uptime */
36722         BUFFER_APPEND_STRING_CONST(b, "Uptime: ");
36723         ts = srv->cur_ts - srv->startup_ts;
36724         buffer_append_long(b, ts);
36725         BUFFER_APPEND_STRING_CONST(b, "\n");
36726 -       
36727 +
36728         /* output busy servers */
36729         BUFFER_APPEND_STRING_CONST(b, "BusyServers: ");
36730         buffer_append_long(b, srv->conns->used);
36731 @@ -577,7 +576,7 @@
36732         /* set text/plain output */
36733  
36734         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
36735 -       
36736 +
36737         return 0;
36738  }
36739  
36740 @@ -591,10 +590,10 @@
36741                 /* we have nothing to send */
36742                 con->http_status = 204;
36743                 con->file_finished = 1;
36744 -       
36745 +
36746                 return HANDLER_FINISHED;
36747         }
36748 -       
36749 +
36750         b = chunkqueue_get_append_buffer(con->write_queue);
36751  
36752         for (i = 0; i < st->used; i++) {
36753 @@ -605,27 +604,27 @@
36754                 buffer_append_long(b, ((data_integer *)(st->data[ndx]))->value);
36755                 buffer_append_string(b, "\n");
36756         }
36757 -       
36758 +
36759         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
36760 -       
36761 +
36762         con->http_status = 200;
36763         con->file_finished = 1;
36764 -       
36765 +
36766         return HANDLER_FINISHED;
36767  }
36768  
36769  
36770  static handler_t mod_status_handle_server_status(server *srv, connection *con, void *p_d) {
36771 -       
36772 +
36773         if (buffer_is_equal_string(con->uri.query, CONST_STR_LEN("auto"))) {
36774                 mod_status_handle_server_status_text(srv, con, p_d);
36775         } else {
36776                 mod_status_handle_server_status_html(srv, con, p_d);
36777         }
36778 -       
36779 +
36780         con->http_status = 200;
36781         con->file_finished = 1;
36782 -       
36783 +
36784         return HANDLER_FINISHED;
36785  }
36786  
36787 @@ -634,9 +633,9 @@
36788         plugin_data *p = p_d;
36789         buffer *b, *m = p->module_list;
36790         size_t i;
36791 -       
36792 -       struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] = 
36793 -       { 
36794 +
36795 +       struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
36796 +       {
36797                 /* - poll is most reliable
36798                  * - select works everywhere
36799                  * - linux-* are experimental
36800 @@ -661,10 +660,10 @@
36801  #endif
36802                 { FDEVENT_HANDLER_UNSET,          NULL }
36803         };
36804 -       
36805 +
36806         b = chunkqueue_get_append_buffer(con->write_queue);
36807 -       
36808 -       BUFFER_COPY_STRING_CONST(b, 
36809 +
36810 +       BUFFER_COPY_STRING_CONST(b,
36811                            "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
36812                            "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
36813                            "         \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
36814 @@ -675,7 +674,7 @@
36815                            " <body>\n"
36816                            "  <h1>" PACKAGE_NAME " " PACKAGE_VERSION "</h1>\n"
36817                            "  <table border=\"1\">\n");
36818 -       
36819 +
36820         mod_status_header_append(b, "Server-Features");
36821  #ifdef HAVE_PCRE_H
36822         mod_status_row_append(b, "RegEx Conditionals", "enabled");
36823 @@ -683,21 +682,21 @@
36824         mod_status_row_append(b, "RegEx Conditionals", "disabled - pcre missing");
36825  #endif
36826         mod_status_header_append(b, "Network Engine");
36827 -       
36828 +
36829         for (i = 0; event_handlers[i].name; i++) {
36830                 if (event_handlers[i].et == srv->event_handler) {
36831                         mod_status_row_append(b, "fd-Event-Handler", event_handlers[i].name);
36832                         break;
36833                 }
36834         }
36835 -       
36836 +
36837         mod_status_header_append(b, "Config-File-Settings");
36838 -       
36839 +
36840         for (i = 0; i < srv->plugins.used; i++) {
36841                 plugin **ps = srv->plugins.ptr;
36842 -               
36843 +
36844                 plugin *pl = ps[i];
36845 -       
36846 +
36847                 if (i == 0) {
36848                         buffer_copy_string_buffer(m, pl->name);
36849                 } else {
36850 @@ -705,137 +704,135 @@
36851                         buffer_append_string_buffer(m, pl->name);
36852                 }
36853         }
36854 -       
36855 +
36856         mod_status_row_append(b, "Loaded Modules", m->ptr);
36857 -       
36858 +
36859         BUFFER_APPEND_STRING_CONST(b, "  </table>\n");
36860 -       
36861 -       BUFFER_APPEND_STRING_CONST(b, 
36862 +
36863 +       BUFFER_APPEND_STRING_CONST(b,
36864                       " </body>\n"
36865                       "</html>\n"
36866                       );
36867 -       
36868 +
36869         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
36870 -       
36871 +
36872         con->http_status = 200;
36873         con->file_finished = 1;
36874 -       
36875 +
36876         return HANDLER_FINISHED;
36877  }
36878  
36879 -#define PATCH(x) \
36880 -       p->conf.x = s->x;
36881  static int mod_status_patch_connection(server *srv, connection *con, plugin_data *p) {
36882         size_t i, j;
36883         plugin_config *s = p->config_storage[0];
36884 -       
36885 -       PATCH(status_url);
36886 -       PATCH(config_url);
36887 -       PATCH(sort);
36888 -       PATCH(statistics_url);
36889 -       
36890 +
36891 +       PATCH_OPTION(status_url);
36892 +       PATCH_OPTION(config_url);
36893 +       PATCH_OPTION(sort);
36894 +       PATCH_OPTION(statistics_url);
36895 +
36896         /* skip the first, the global context */
36897         for (i = 1; i < srv->config_context->used; i++) {
36898                 data_config *dc = (data_config *)srv->config_context->data[i];
36899                 s = p->config_storage[i];
36900 -               
36901 +
36902                 /* condition didn't match */
36903                 if (!config_check_cond(srv, con, dc)) continue;
36904 -               
36905 +
36906                 /* merge config */
36907                 for (j = 0; j < dc->value->used; j++) {
36908                         data_unset *du = dc->value->data[j];
36909 -                       
36910 +
36911                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.status-url"))) {
36912 -                               PATCH(status_url);
36913 +                               PATCH_OPTION(status_url);
36914                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.config-url"))) {
36915 -                               PATCH(config_url);
36916 +                               PATCH_OPTION(config_url);
36917                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.enable-sort"))) {
36918 -                               PATCH(sort);
36919 +                               PATCH_OPTION(sort);
36920                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.statistics-url"))) {
36921 -                               PATCH(statistics_url);
36922 -                       } 
36923 +                               PATCH_OPTION(statistics_url);
36924 +                       }
36925                 }
36926         }
36927 -       
36928 +
36929         return 0;
36930  }
36931  
36932  static handler_t mod_status_handler(server *srv, connection *con, void *p_d) {
36933         plugin_data *p = p_d;
36934 -       
36935 +
36936         mod_status_patch_connection(srv, con, p);
36937 -       
36938 -       if (!buffer_is_empty(p->conf.status_url) && 
36939 +
36940 +       if (!buffer_is_empty(p->conf.status_url) &&
36941             buffer_is_equal(p->conf.status_url, con->uri.path)) {
36942                 return mod_status_handle_server_status(srv, con, p_d);
36943 -       } else if (!buffer_is_empty(p->conf.config_url) && 
36944 +       } else if (!buffer_is_empty(p->conf.config_url) &&
36945             buffer_is_equal(p->conf.config_url, con->uri.path)) {
36946                 return mod_status_handle_server_config(srv, con, p_d);
36947 -       } else if (!buffer_is_empty(p->conf.statistics_url) && 
36948 +       } else if (!buffer_is_empty(p->conf.statistics_url) &&
36949             buffer_is_equal(p->conf.statistics_url, con->uri.path)) {
36950                 return mod_status_handle_server_statistics(srv, con, p_d);
36951         }
36952 -       
36953 +
36954         return HANDLER_GO_ON;
36955  }
36956  
36957  TRIGGER_FUNC(mod_status_trigger) {
36958         plugin_data *p = p_d;
36959         size_t i;
36960 -       
36961 +
36962         /* check all connections */
36963         for (i = 0; i < srv->conns->used; i++) {
36964                 connection *c = srv->conns->ptr[i];
36965 -               
36966 +
36967                 p->bytes_written += c->bytes_written_cur_second;
36968         }
36969 -       
36970 +
36971         /* a sliding average */
36972         p->mod_5s_traffic_out[p->mod_5s_ndx] = p->bytes_written;
36973         p->mod_5s_requests   [p->mod_5s_ndx] = p->requests;
36974 -       
36975 +
36976         p->mod_5s_ndx = (p->mod_5s_ndx+1) % 5;
36977 -       
36978 +
36979         p->abs_traffic_out += p->bytes_written;
36980         p->rel_traffic_out += p->bytes_written;
36981 -       
36982 +
36983         p->bytes_written = 0;
36984 -       
36985 +
36986         /* reset storage - second */
36987         p->traffic_out = 0;
36988         p->requests    = 0;
36989 -       
36990 +
36991         return HANDLER_GO_ON;
36992  }
36993  
36994  REQUESTDONE_FUNC(mod_status_account) {
36995         plugin_data *p = p_d;
36996 -       
36997 +
36998         UNUSED(srv);
36999  
37000         p->requests++;
37001         p->rel_requests++;
37002         p->abs_requests++;
37003 -       
37004 +
37005         p->bytes_written += con->bytes_written_cur_second;
37006 -       
37007 +
37008         return HANDLER_GO_ON;
37009  }
37010  
37011  int mod_status_plugin_init(plugin *p) {
37012         p->version     = LIGHTTPD_VERSION_ID;
37013         p->name        = buffer_init_string("status");
37014 -       
37015 +
37016         p->init        = mod_status_init;
37017         p->cleanup     = mod_status_free;
37018         p->set_defaults= mod_status_set_defaults;
37019 -       
37020 +
37021         p->handle_uri_clean    = mod_status_handler;
37022         p->handle_trigger      = mod_status_trigger;
37023         p->handle_request_done = mod_status_account;
37024 -       
37025 +
37026         p->data        = NULL;
37027 -       
37028 +
37029         return 0;
37030  }
37031 --- lighttpd-1.4.11/src/mod_trigger_b4_dl.c     2005-09-23 22:53:55.000000000 +0300
37032 +++ lighttpd-1.4.12/src/mod_trigger_b4_dl.c     2006-07-11 22:07:51.000000000 +0300
37033 @@ -24,18 +24,18 @@
37034  
37035  /**
37036   * this is a trigger_b4_dl for a lighttpd plugin
37037 - * 
37038 + *
37039   */
37040  
37041  /* plugin config for all request/connections */
37042  
37043  typedef struct {
37044         buffer *db_filename;
37045 -       
37046 +
37047         buffer *trigger_url;
37048         buffer *download_url;
37049         buffer *deny_url;
37050 -       
37051 +
37052         array  *mc_hosts;
37053         buffer *mc_namespace;
37054  #if defined(HAVE_PCRE_H)
37055 @@ -46,58 +46,58 @@
37056         GDBM_FILE db;
37057  #endif
37058  
37059 -#if defined(HAVE_MEMCACHE_H) 
37060 +#if defined(HAVE_MEMCACHE_H)
37061         struct memcache *mc;
37062  #endif
37063 -       
37064 +
37065         unsigned short trigger_timeout;
37066         unsigned short debug;
37067  } plugin_config;
37068  
37069  typedef struct {
37070         PLUGIN_DATA;
37071 -       
37072 +
37073         buffer *tmp_buf;
37074 -       
37075 +
37076         plugin_config **config_storage;
37077 -       
37078 -       plugin_config conf; 
37079 +
37080 +       plugin_config conf;
37081  } plugin_data;
37082  
37083  /* init the plugin data */
37084  INIT_FUNC(mod_trigger_b4_dl_init) {
37085         plugin_data *p;
37086 -       
37087 +
37088         p = calloc(1, sizeof(*p));
37089 -       
37090 +
37091         p->tmp_buf = buffer_init();
37092 -       
37093 +
37094         return p;
37095  }
37096  
37097  /* detroy the plugin data */
37098  FREE_FUNC(mod_trigger_b4_dl_free) {
37099         plugin_data *p = p_d;
37100 -       
37101 +
37102         UNUSED(srv);
37103  
37104         if (!p) return HANDLER_GO_ON;
37105 -       
37106 +
37107         if (p->config_storage) {
37108                 size_t i;
37109                 for (i = 0; i < srv->config_context->used; i++) {
37110                         plugin_config *s = p->config_storage[i];
37111  
37112                         if (!s) continue;
37113 -                       
37114 +
37115                         buffer_free(s->db_filename);
37116                         buffer_free(s->download_url);
37117                         buffer_free(s->trigger_url);
37118                         buffer_free(s->deny_url);
37119 -                       
37120 +
37121                         buffer_free(s->mc_namespace);
37122                         array_free(s->mc_hosts);
37123 -                       
37124 +
37125  #if defined(HAVE_PCRE_H)
37126                         if (s->trigger_regex) pcre_free(s->trigger_regex);
37127                         if (s->download_regex) pcre_free(s->download_regex);
37128 @@ -108,16 +108,16 @@
37129  #if defined(HAVE_MEMCACHE_H)
37130                         if (s->mc) mc_free(s->mc);
37131  #endif
37132 -                       
37133 +
37134                         free(s);
37135                 }
37136                 free(p->config_storage);
37137         }
37138 -       
37139 +
37140         buffer_free(p->tmp_buf);
37141 -       
37142 +
37143         free(p);
37144 -       
37145 +
37146         return HANDLER_GO_ON;
37147  }
37148  
37149 @@ -126,9 +126,9 @@
37150  SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) {
37151         plugin_data *p = p_d;
37152         size_t i = 0;
37153 -       
37154 -       
37155 -       config_values_t cv[] = { 
37156 +
37157 +
37158 +       config_values_t cv[] = {
37159                 { "trigger-before-download.gdbm-filename",   NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
37160                 { "trigger-before-download.trigger-url",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
37161                 { "trigger-before-download.download-url",    NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
37162 @@ -139,18 +139,18 @@
37163                 { "trigger-before-download.debug",           NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },      /* 7 */
37164                 { NULL,                        NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
37165         };
37166 -       
37167 +
37168         if (!p) return HANDLER_ERROR;
37169 -       
37170 +
37171         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
37172 -       
37173 +
37174         for (i = 0; i < srv->config_context->used; i++) {
37175                 plugin_config *s;
37176  #if defined(HAVE_PCRE_H)
37177                 const char *errptr;
37178                 int erroff;
37179  #endif
37180 -               
37181 +
37182                 s = calloc(1, sizeof(plugin_config));
37183                 s->db_filename    = buffer_init();
37184                 s->download_url   = buffer_init();
37185 @@ -158,7 +158,7 @@
37186                 s->deny_url       = buffer_init();
37187                 s->mc_hosts       = array_init();
37188                 s->mc_namespace   = buffer_init();
37189 -               
37190 +
37191                 cv[0].destination = s->db_filename;
37192                 cv[1].destination = s->trigger_url;
37193                 cv[2].destination = s->download_url;
37194 @@ -167,41 +167,41 @@
37195                 cv[5].destination = s->mc_hosts;
37196                 cv[6].destination = s->mc_namespace;
37197                 cv[7].destination = &(s->debug);
37198 -               
37199 +
37200                 p->config_storage[i] = s;
37201 -       
37202 +
37203                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
37204                         return HANDLER_ERROR;
37205                 }
37206  #if defined(HAVE_GDBM_H)
37207                 if (!buffer_is_empty(s->db_filename)) {
37208                         if (NULL == (s->db = gdbm_open(s->db_filename->ptr, 4096, GDBM_WRCREAT | GDBM_NOLOCK, S_IRUSR | S_IWUSR, 0))) {
37209 -                               log_error_write(srv, __FILE__, __LINE__, "s", 
37210 +                               log_error_write(srv, __FILE__, __LINE__, "s",
37211                                                 "gdbm-open failed");
37212                                 return HANDLER_ERROR;
37213                         }
37214                 }
37215  #endif
37216 -#if defined(HAVE_PCRE_H)               
37217 +#if defined(HAVE_PCRE_H)
37218                 if (!buffer_is_empty(s->download_url)) {
37219                         if (NULL == (s->download_regex = pcre_compile(s->download_url->ptr,
37220                                                                       0, &errptr, &erroff, NULL))) {
37221 -                               
37222 -                               log_error_write(srv, __FILE__, __LINE__, "sbss", 
37223 -                                               "compiling regex for download-url failed:", 
37224 +
37225 +                               log_error_write(srv, __FILE__, __LINE__, "sbss",
37226 +                                               "compiling regex for download-url failed:",
37227                                                 s->download_url, "pos:", erroff);
37228                                 return HANDLER_ERROR;
37229                         }
37230                 }
37231 -               
37232 +
37233                 if (!buffer_is_empty(s->trigger_url)) {
37234                         if (NULL == (s->trigger_regex = pcre_compile(s->trigger_url->ptr,
37235                                                                      0, &errptr, &erroff, NULL))) {
37236 -                               
37237 -                               log_error_write(srv, __FILE__, __LINE__, "sbss", 
37238 -                                               "compiling regex for trigger-url failed:", 
37239 +
37240 +                               log_error_write(srv, __FILE__, __LINE__, "sbss",
37241 +                                               "compiling regex for trigger-url failed:",
37242                                                 s->trigger_url, "pos:", erroff);
37243 -                               
37244 +
37245                                 return HANDLER_ERROR;
37246                         }
37247                 }
37248 @@ -211,100 +211,97 @@
37249  #if defined(HAVE_MEMCACHE_H)
37250                         size_t k;
37251                         s->mc = mc_new();
37252 -               
37253 +
37254                         for (k = 0; k < s->mc_hosts->used; k++) {
37255                                 data_string *ds = (data_string *)s->mc_hosts->data[k];
37256 -                               
37257 +
37258                                 if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
37259 -                                       log_error_write(srv, __FILE__, __LINE__, "sb", 
37260 -                                                       "connection to host failed:", 
37261 +                                       log_error_write(srv, __FILE__, __LINE__, "sb",
37262 +                                                       "connection to host failed:",
37263                                                         ds->value);
37264 -                                       
37265 +
37266                                         return HANDLER_ERROR;
37267                                 }
37268                         }
37269  #else
37270 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
37271 +                       log_error_write(srv, __FILE__, __LINE__, "s",
37272                                         "memcache support is not compiled in but trigger-before-download.memcache-hosts is set, aborting");
37273                         return HANDLER_ERROR;
37274  #endif
37275                 }
37276 -               
37277 +
37278  
37279  #if (!defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)) || !defined(HAVE_PCRE_H)
37280 -               log_error_write(srv, __FILE__, __LINE__, "s", 
37281 +               log_error_write(srv, __FILE__, __LINE__, "s",
37282                                 "(either gdbm or libmemcache) and pcre are require, but were not found, aborting");
37283                 return HANDLER_ERROR;
37284  #endif
37285         }
37286 -       
37287 +
37288         return HANDLER_GO_ON;
37289  }
37290  
37291 -#define PATCH(x) \
37292 -       p->conf.x = s->x;
37293  static int mod_trigger_b4_dl_patch_connection(server *srv, connection *con, plugin_data *p) {
37294         size_t i, j;
37295         plugin_config *s = p->config_storage[0];
37296 -       
37297 +
37298  #if defined(HAVE_GDBM)
37299 -       PATCH(db);
37300 -#endif 
37301 +       PATCH_OPTION(db);
37302 +#endif
37303  #if defined(HAVE_PCRE_H)
37304 -       PATCH(download_regex);
37305 -       PATCH(trigger_regex);
37306 -#endif 
37307 -       PATCH(trigger_timeout);
37308 -       PATCH(deny_url);
37309 -       PATCH(mc_namespace);
37310 -       PATCH(debug);
37311 +       PATCH_OPTION(download_regex);
37312 +       PATCH_OPTION(trigger_regex);
37313 +#endif
37314 +       PATCH_OPTION(trigger_timeout);
37315 +       PATCH_OPTION(deny_url);
37316 +       PATCH_OPTION(mc_namespace);
37317 +       PATCH_OPTION(debug);
37318  #if defined(HAVE_MEMCACHE_H)
37319 -       PATCH(mc);
37320 +       PATCH_OPTION(mc);
37321  #endif
37322 -       
37323 +
37324         /* skip the first, the global context */
37325         for (i = 1; i < srv->config_context->used; i++) {
37326                 data_config *dc = (data_config *)srv->config_context->data[i];
37327                 s = p->config_storage[i];
37328 -               
37329 +
37330                 /* condition didn't match */
37331                 if (!config_check_cond(srv, con, dc)) continue;
37332 -               
37333 +
37334                 /* merge config */
37335                 for (j = 0; j < dc->value->used; j++) {
37336                         data_unset *du = dc->value->data[j];
37337  
37338                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.download-url"))) {
37339  #if defined(HAVE_PCRE_H)
37340 -                               PATCH(download_regex);
37341 +                               PATCH_OPTION(download_regex);
37342  #endif
37343                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-url"))) {
37344  # if defined(HAVE_PCRE_H)
37345 -                               PATCH(trigger_regex);
37346 +                               PATCH_OPTION(trigger_regex);
37347  # endif
37348                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.gdbm-filename"))) {
37349  #if defined(HAVE_GDBM_H)
37350 -                               PATCH(db);
37351 +                               PATCH_OPTION(db);
37352  #endif
37353                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-timeout"))) {
37354 -                               PATCH(trigger_timeout);
37355 +                               PATCH_OPTION(trigger_timeout);
37356                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.debug"))) {
37357 -                               PATCH(debug);
37358 +                               PATCH_OPTION(debug);
37359                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.deny-url"))) {
37360 -                               PATCH(deny_url);
37361 +                               PATCH_OPTION(deny_url);
37362                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-namespace"))) {
37363 -                               PATCH(mc_namespace);
37364 +                               PATCH_OPTION(mc_namespace);
37365                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-hosts"))) {
37366  #if defined(HAVE_MEMCACHE_H)
37367 -                               PATCH(mc);
37368 +                               PATCH_OPTION(mc);
37369  #endif
37370                         }
37371                 }
37372         }
37373 -       
37374 +
37375         return 0;
37376  }
37377 -#undef PATCH
37378  
37379  URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) {
37380         plugin_data *p = p_d;
37381 @@ -315,20 +312,20 @@
37382         int n;
37383  # define N 10
37384         int ovec[N * 3];
37385 -       
37386 +
37387         if (con->uri.path->used == 0) return HANDLER_GO_ON;
37388 -       
37389 +
37390         mod_trigger_b4_dl_patch_connection(srv, con, p);
37391 -       
37392 +
37393         if (!p->conf.trigger_regex || !p->conf.download_regex) return HANDLER_GO_ON;
37394 -       
37395 +
37396  # if !defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)
37397         return HANDLER_GO_ON;
37398  # elif defined(HAVE_GDBM_H) && defined(HAVE_MEMCACHE_H)
37399         if (!p->conf.db && !p->conf.mc) return HANDLER_GO_ON;
37400         if (p->conf.db && p->conf.mc) {
37401                 /* can't decide which one */
37402 -               
37403 +
37404                 return HANDLER_GO_ON;
37405         }
37406  # elif defined(HAVE_GDBM_H)
37407 @@ -336,12 +333,12 @@
37408  # else
37409         if (!p->conf.mc) return HANDLER_GO_ON;
37410  # endif
37411 -       
37412 +
37413         if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "X-Forwarded-For"))) {
37414                 /* X-Forwarded-For contains the ip behind the proxy */
37415 -               
37416 +
37417                 remote_ip = ds->value->ptr;
37418 -               
37419 +
37420                 /* memcache can't handle spaces */
37421         } else {
37422                 remote_ip = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
37423 @@ -350,13 +347,13 @@
37424         if (p->conf.debug) {
37425                 log_error_write(srv, __FILE__, __LINE__, "ss", "(debug) remote-ip:", remote_ip);
37426         }
37427 -               
37428 +
37429         /* check if URL is a trigger -> insert IP into DB */
37430         if ((n = pcre_exec(p->conf.trigger_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
37431                 if (n != PCRE_ERROR_NOMATCH) {
37432                         log_error_write(srv, __FILE__, __LINE__, "sd",
37433                                         "execution error while matching:", n);
37434 -                       
37435 +
37436                         return HANDLER_ERROR;
37437                 }
37438         } else {
37439 @@ -364,34 +361,34 @@
37440                 if (p->conf.db) {
37441                         /* the trigger matched */
37442                         datum key, val;
37443 -                       
37444 +
37445                         key.dptr = (char *)remote_ip;
37446                         key.dsize = strlen(remote_ip);
37447 -                       
37448 +
37449                         val.dptr = (char *)&(srv->cur_ts);
37450                         val.dsize = sizeof(srv->cur_ts);
37451 -                       
37452 +
37453                         if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
37454                                 log_error_write(srv, __FILE__, __LINE__, "s",
37455                                                 "insert failed");
37456                         }
37457                 }
37458  # endif
37459 -# if defined(HAVE_MEMCACHE_H)          
37460 +# if defined(HAVE_MEMCACHE_H)
37461                 if (p->conf.mc) {
37462                         size_t i;
37463                         buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
37464                         buffer_append_string(p->tmp_buf, remote_ip);
37465 -                       
37466 +
37467                         for (i = 0; i < p->tmp_buf->used - 1; i++) {
37468                                 if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
37469                         }
37470 -                       
37471 +
37472                         if (p->conf.debug) {
37473                                 log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) triggered IP:", p->tmp_buf);
37474                         }
37475  
37476 -                       if (0 != mc_set(p->conf.mc, 
37477 +                       if (0 != mc_set(p->conf.mc,
37478                                         CONST_BUF_LEN(p->tmp_buf),
37479                                         (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
37480                                         p->conf.trigger_timeout, 0)) {
37481 @@ -401,7 +398,7 @@
37482                 }
37483  # endif
37484         }
37485 -               
37486 +
37487         /* check if URL is a download -> check IP in DB, update timestamp */
37488         if ((n = pcre_exec(p->conf.download_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
37489                 if (n != PCRE_ERROR_NOMATCH) {
37490 @@ -411,93 +408,93 @@
37491                 }
37492         } else {
37493                 /* the download uri matched */
37494 -# if defined(HAVE_GDBM_H)              
37495 +# if defined(HAVE_GDBM_H)
37496                 if (p->conf.db) {
37497                         datum key, val;
37498                         time_t last_hit;
37499 -               
37500 +
37501                         key.dptr = (char *)remote_ip;
37502                         key.dsize = strlen(remote_ip);
37503 -                       
37504 +
37505                         val = gdbm_fetch(p->conf.db, key);
37506 -               
37507 +
37508                         if (val.dptr == NULL) {
37509                                 /* not found, redirect */
37510 -                               
37511 +
37512                                 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37513 -                               
37514 +
37515                                 con->http_status = 307;
37516 -                               
37517 +
37518                                 return HANDLER_FINISHED;
37519                         }
37520 -                       
37521 +
37522                         last_hit = *(time_t *)(val.dptr);
37523 -                       
37524 +
37525                         free(val.dptr);
37526 -                       
37527 +
37528                         if (srv->cur_ts - last_hit > p->conf.trigger_timeout) {
37529                                 /* found, but timeout, redirect */
37530 -                               
37531 +
37532                                 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37533                                 con->http_status = 307;
37534 -                               
37535 +
37536                                 if (p->conf.db) {
37537                                         if (0 != gdbm_delete(p->conf.db, key)) {
37538                                                 log_error_write(srv, __FILE__, __LINE__, "s",
37539                                                                 "delete failed");
37540                                         }
37541                                 }
37542 -                               
37543 +
37544                                 return HANDLER_FINISHED;
37545                         }
37546 -                       
37547 +
37548                         val.dptr = (char *)&(srv->cur_ts);
37549                         val.dsize = sizeof(srv->cur_ts);
37550 -                       
37551 +
37552                         if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
37553                                 log_error_write(srv, __FILE__, __LINE__, "s",
37554                                                 "insert failed");
37555                         }
37556                 }
37557  # endif
37558 -               
37559 -# if defined(HAVE_MEMCACHE_H)          
37560 +
37561 +# if defined(HAVE_MEMCACHE_H)
37562                 if (p->conf.mc) {
37563                         void *r;
37564                         size_t i;
37565 -                       
37566 +
37567                         buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
37568                         buffer_append_string(p->tmp_buf, remote_ip);
37569 -                       
37570 +
37571                         for (i = 0; i < p->tmp_buf->used - 1; i++) {
37572                                 if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
37573                         }
37574 -                       
37575 +
37576                         if (p->conf.debug) {
37577                                 log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) checking IP:", p->tmp_buf);
37578                         }
37579  
37580                         /**
37581 -                        * 
37582 +                        *
37583                          * memcached is do expiration for us, as long as we can fetch it every thing is ok
37584 -                        * and the timestamp is updated 
37585 -                        * 
37586 +                        * and the timestamp is updated
37587 +                        *
37588                          */
37589 -                       if (NULL == (r = mc_aget(p->conf.mc, 
37590 +                       if (NULL == (r = mc_aget(p->conf.mc,
37591                                                  CONST_BUF_LEN(p->tmp_buf)
37592                                                  ))) {
37593 -                               
37594 +
37595                                 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37596 -                               
37597 +
37598                                 con->http_status = 307;
37599 -                               
37600 +
37601                                 return HANDLER_FINISHED;
37602                         }
37603 -                       
37604 +
37605                         free(r);
37606 -                       
37607 +
37608                         /* set a new timeout */
37609 -                       if (0 != mc_set(p->conf.mc, 
37610 +                       if (0 != mc_set(p->conf.mc,
37611                                         CONST_BUF_LEN(p->tmp_buf),
37612                                         (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
37613                                         p->conf.trigger_timeout, 0)) {
37614 @@ -507,13 +504,13 @@
37615                 }
37616  # endif
37617         }
37618 -       
37619 +
37620  #else
37621         UNUSED(srv);
37622         UNUSED(con);
37623         UNUSED(p_d);
37624  #endif
37625 -       
37626 +
37627         return HANDLER_GO_ON;
37628  }
37629  
37630 @@ -521,21 +518,21 @@
37631  TRIGGER_FUNC(mod_trigger_b4_dl_handle_trigger) {
37632         plugin_data *p = p_d;
37633         size_t i;
37634 -       
37635 +
37636         /* check DB each minute */
37637         if (srv->cur_ts % 60 != 0) return HANDLER_GO_ON;
37638 -       
37639 +
37640         /* cleanup */
37641         for (i = 0; i < srv->config_context->used; i++) {
37642                 plugin_config *s = p->config_storage[i];
37643                 datum key, val, okey;
37644 -               
37645 +
37646                 if (!s->db) continue;
37647 -               
37648 +
37649                 okey.dptr = NULL;
37650 -               
37651 -               /* according to the manual this loop + delete does delete all entries on its way 
37652 -                * 
37653 +
37654 +               /* according to the manual this loop + delete does delete all entries on its way
37655 +                *
37656                  * we don't care as the next round will remove them. We don't have to perfect here.
37657                  */
37658                 for (key = gdbm_firstkey(s->db); key.dptr; key = gdbm_nextkey(s->db, okey)) {
37659 @@ -544,21 +541,21 @@
37660                                 free(okey.dptr);
37661                                 okey.dptr = NULL;
37662                         }
37663 -                       
37664 +
37665                         val = gdbm_fetch(s->db, key);
37666 -                       
37667 +
37668                         last_hit = *(time_t *)(val.dptr);
37669 -                       
37670 +
37671                         free(val.dptr);
37672 -                       
37673 +
37674                         if (srv->cur_ts - last_hit > s->trigger_timeout) {
37675                                 gdbm_delete(s->db, key);
37676                         }
37677 -                       
37678 +
37679                         okey = key;
37680                 }
37681                 if (okey.dptr) free(okey.dptr);
37682 -               
37683 +
37684                 /* reorg once a day */
37685                 if ((srv->cur_ts % (60 * 60 * 24) != 0)) gdbm_reorganize(s->db);
37686         }
37687 @@ -571,7 +568,7 @@
37688  int mod_trigger_b4_dl_plugin_init(plugin *p) {
37689         p->version     = LIGHTTPD_VERSION_ID;
37690         p->name        = buffer_init_string("trigger_b4_dl");
37691 -       
37692 +
37693         p->init        = mod_trigger_b4_dl_init;
37694         p->handle_uri_clean  = mod_trigger_b4_dl_uri_handler;
37695         p->set_defaults  = mod_trigger_b4_dl_set_defaults;
37696 @@ -579,8 +576,8 @@
37697         p->handle_trigger  = mod_trigger_b4_dl_handle_trigger;
37698  #endif
37699         p->cleanup     = mod_trigger_b4_dl_free;
37700 -       
37701 +
37702         p->data        = NULL;
37703 -       
37704 +
37705         return 0;
37706  }
37707 --- lighttpd-1.4.11/src/mod_userdir.c   2005-10-28 16:48:28.000000000 +0300
37708 +++ lighttpd-1.4.12/src/mod_userdir.c   2006-07-11 22:07:52.000000000 +0300
37709 @@ -10,6 +10,7 @@
37710  #include "response.h"
37711  
37712  #include "plugin.h"
37713 +#include "sys-files.h"
37714  
37715  #ifdef HAVE_PWD_H
37716  #include <pwd.h>
37717 @@ -25,54 +26,54 @@
37718  
37719  typedef struct {
37720         PLUGIN_DATA;
37721 -       
37722 +
37723         buffer *username;
37724         buffer *temp_path;
37725 -       
37726 +
37727         plugin_config **config_storage;
37728 -       
37729 -       plugin_config conf; 
37730 +
37731 +       plugin_config conf;
37732  } plugin_data;
37733  
37734  /* init the plugin data */
37735  INIT_FUNC(mod_userdir_init) {
37736         plugin_data *p;
37737 -       
37738 +
37739         p = calloc(1, sizeof(*p));
37740 -       
37741 +
37742         p->username = buffer_init();
37743         p->temp_path = buffer_init();
37744 -       
37745 +
37746         return p;
37747  }
37748  
37749  /* detroy the plugin data */
37750  FREE_FUNC(mod_userdir_free) {
37751         plugin_data *p = p_d;
37752 -       
37753 +
37754         if (!p) return HANDLER_GO_ON;
37755 -       
37756 +
37757         if (p->config_storage) {
37758                 size_t i;
37759 -               
37760 +
37761                 for (i = 0; i < srv->config_context->used; i++) {
37762                         plugin_config *s = p->config_storage[i];
37763 -                       
37764 +
37765                         array_free(s->include_user);
37766                         array_free(s->exclude_user);
37767                         buffer_free(s->path);
37768                         buffer_free(s->basepath);
37769 -                       
37770 +
37771                         free(s);
37772                 }
37773                 free(p->config_storage);
37774         }
37775 -       
37776 +
37777         buffer_free(p->username);
37778         buffer_free(p->temp_path);
37779 -       
37780 +
37781         free(p);
37782 -       
37783 +
37784         return HANDLER_GO_ON;
37785  }
37786  
37787 @@ -81,81 +82,78 @@
37788  SETDEFAULTS_FUNC(mod_userdir_set_defaults) {
37789         plugin_data *p = p_d;
37790         size_t i;
37791 -       
37792 -       config_values_t cv[] = { 
37793 +
37794 +       config_values_t cv[] = {
37795                 { "userdir.path",               NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
37796                 { "userdir.exclude-user",       NULL, T_CONFIG_ARRAY,  T_CONFIG_SCOPE_CONNECTION },       /* 1 */
37797                 { "userdir.include-user",       NULL, T_CONFIG_ARRAY,  T_CONFIG_SCOPE_CONNECTION },       /* 2 */
37798                 { "userdir.basepath",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 3 */
37799                 { NULL,                         NULL, T_CONFIG_UNSET,  T_CONFIG_SCOPE_UNSET }
37800         };
37801 -       
37802 +
37803         if (!p) return HANDLER_ERROR;
37804 -       
37805 +
37806         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
37807 -       
37808 +
37809         for (i = 0; i < srv->config_context->used; i++) {
37810                 plugin_config *s;
37811 -               
37812 +
37813                 s = calloc(1, sizeof(plugin_config));
37814                 s->exclude_user = array_init();
37815                 s->include_user = array_init();
37816                 s->path = buffer_init();
37817                 s->basepath = buffer_init();
37818 -       
37819 +
37820                 cv[0].destination = s->path;
37821                 cv[1].destination = s->exclude_user;
37822                 cv[2].destination = s->include_user;
37823                 cv[3].destination = s->basepath;
37824 -               
37825 +
37826                 p->config_storage[i] = s;
37827 -       
37828 +
37829                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
37830                         return HANDLER_ERROR;
37831                 }
37832         }
37833 -       
37834 +
37835         return HANDLER_GO_ON;
37836  }
37837  
37838 -#define PATCH(x) \
37839 -       p->conf.x = s->x;
37840  static int mod_userdir_patch_connection(server *srv, connection *con, plugin_data *p) {
37841         size_t i, j;
37842         plugin_config *s = p->config_storage[0];
37843 -       
37844 -       PATCH(path);
37845 -       PATCH(exclude_user);
37846 -       PATCH(include_user);
37847 -       PATCH(basepath);
37848 -       
37849 +
37850 +       PATCH_OPTION(path);
37851 +       PATCH_OPTION(exclude_user);
37852 +       PATCH_OPTION(include_user);
37853 +       PATCH_OPTION(basepath);
37854 +
37855         /* skip the first, the global context */
37856         for (i = 1; i < srv->config_context->used; i++) {
37857                 data_config *dc = (data_config *)srv->config_context->data[i];
37858                 s = p->config_storage[i];
37859 -               
37860 +
37861                 /* condition didn't match */
37862                 if (!config_check_cond(srv, con, dc)) continue;
37863 -               
37864 +
37865                 /* merge config */
37866                 for (j = 0; j < dc->value->used; j++) {
37867                         data_unset *du = dc->value->data[j];
37868 -                       
37869 +
37870                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.path"))) {
37871 -                               PATCH(path);
37872 +                               PATCH_OPTION(path);
37873                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.exclude-user"))) {
37874 -                               PATCH(exclude_user);
37875 +                               PATCH_OPTION(exclude_user);
37876                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.include-user"))) {
37877 -                               PATCH(include_user);
37878 +                               PATCH_OPTION(include_user);
37879                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.basepath"))) {
37880 -                               PATCH(basepath);
37881 +                               PATCH_OPTION(basepath);
37882                         }
37883                 }
37884         }
37885 -       
37886 +
37887         return 0;
37888  }
37889 -#undef PATCH
37890  
37891  URIHANDLER_FUNC(mod_userdir_docroot_handler) {
37892         plugin_data *p = p_d;
37893 @@ -169,18 +167,18 @@
37894         if (con->uri.path->used == 0) return HANDLER_GO_ON;
37895  
37896         mod_userdir_patch_connection(srv, con, p);
37897 -       
37898 +
37899         uri_len = con->uri.path->used - 1;
37900 -       
37901 +
37902         /* /~user/foo.html -> /home/user/public_html/foo.html */
37903 -       
37904 +
37905         if (con->uri.path->ptr[0] != '/' ||
37906             con->uri.path->ptr[1] != '~') return HANDLER_GO_ON;
37907 -       
37908 +
37909         if (NULL == (rel_url = strchr(con->uri.path->ptr + 2, '/'))) {
37910                 /* / is missing -> redirect to .../ as we are a user - DIRECTORY ! :) */
37911                 http_response_redirect_to_directory(srv, con);
37912 -               
37913 +
37914                 return HANDLER_FINISHED;
37915         }
37916  
37917 @@ -188,10 +186,10 @@
37918         if (0 == rel_url - (con->uri.path->ptr + 2)) {
37919                 return HANDLER_GO_ON;
37920         }
37921 -       
37922 +
37923         buffer_copy_string_len(p->username, con->uri.path->ptr + 2, rel_url - (con->uri.path->ptr + 2));
37924 -       
37925 -       if (buffer_is_empty(p->conf.basepath) 
37926 +
37927 +       if (buffer_is_empty(p->conf.basepath)
37928  #ifdef HAVE_PWD_H
37929             && NULL == (pwd = getpwnam(p->username->ptr))
37930  #endif
37931 @@ -200,31 +198,31 @@
37932                 return HANDLER_GO_ON;
37933         }
37934  
37935 -       
37936 +
37937         for (k = 0; k < p->conf.exclude_user->used; k++) {
37938                 data_string *ds = (data_string *)p->conf.exclude_user->data[k];
37939 -               
37940 +
37941                 if (buffer_is_equal(ds->value, p->username)) {
37942                         /* user in exclude list */
37943                         return HANDLER_GO_ON;
37944                 }
37945         }
37946 -       
37947 +
37948         if (p->conf.include_user->used) {
37949                 int found_user = 0;
37950                 for (k = 0; k < p->conf.include_user->used; k++) {
37951                         data_string *ds = (data_string *)p->conf.include_user->data[k];
37952 -                       
37953 +
37954                         if (buffer_is_equal(ds->value, p->username)) {
37955                                 /* user in include list */
37956                                 found_user = 1;
37957                                 break;
37958                         }
37959                 }
37960 -               
37961 +
37962                 if (!found_user) return HANDLER_GO_ON;
37963         }
37964 -       
37965 +
37966         /* we build the physical path */
37967  
37968         if (buffer_is_empty(p->conf.basepath)) {
37969 @@ -252,23 +250,23 @@
37970                 }
37971  
37972                 buffer_copy_string_buffer(p->temp_path, p->conf.basepath);
37973 -               BUFFER_APPEND_SLASH(p->temp_path);
37974 +               PATHNAME_APPEND_SLASH(p->temp_path);
37975                 buffer_append_string_buffer(p->temp_path, p->username);
37976         }
37977 -       BUFFER_APPEND_SLASH(p->temp_path);
37978 -       buffer_append_string_buffer(p->temp_path, p->conf.path); 
37979 +       PATHNAME_APPEND_SLASH(p->temp_path);
37980 +       buffer_append_string_buffer(p->temp_path, p->conf.path);
37981  
37982         if (buffer_is_empty(p->conf.basepath)) {
37983                 struct stat st;
37984                 int ret;
37985 -               
37986 +
37987                 ret = stat(p->temp_path->ptr, &st);
37988                 if (ret < 0 || S_ISDIR(st.st_mode) != 1) {
37989                         return HANDLER_GO_ON;
37990 -               } 
37991 +               }
37992         }
37993  
37994 -       BUFFER_APPEND_SLASH(p->temp_path);
37995 +       PATHNAME_APPEND_SLASH(p->temp_path);
37996         buffer_append_string(p->temp_path, rel_url + 1); /* skip the / */
37997         buffer_copy_string_buffer(con->physical.path, p->temp_path);
37998  
37999 @@ -282,13 +280,13 @@
38000  int mod_userdir_plugin_init(plugin *p) {
38001         p->version     = LIGHTTPD_VERSION_ID;
38002         p->name        = buffer_init_string("userdir");
38003 -       
38004 +
38005         p->init           = mod_userdir_init;
38006         p->handle_physical = mod_userdir_docroot_handler;
38007         p->set_defaults   = mod_userdir_set_defaults;
38008         p->cleanup        = mod_userdir_free;
38009 -       
38010 +
38011         p->data        = NULL;
38012 -       
38013 +
38014         return 0;
38015  }
38016 --- lighttpd-1.4.11/src/mod_usertrack.c 2006-01-31 15:01:20.000000000 +0200
38017 +++ lighttpd-1.4.12/src/mod_usertrack.c 2006-07-11 22:07:53.000000000 +0300
38018 @@ -24,44 +24,44 @@
38019  
38020  typedef struct {
38021         PLUGIN_DATA;
38022 -       
38023 +
38024         plugin_config **config_storage;
38025 -       
38026 -       plugin_config conf; 
38027 +
38028 +       plugin_config conf;
38029  } plugin_data;
38030  
38031  /* init the plugin data */
38032  INIT_FUNC(mod_usertrack_init) {
38033         plugin_data *p;
38034 -       
38035 +
38036         p = calloc(1, sizeof(*p));
38037 -       
38038 +
38039         return p;
38040  }
38041  
38042  /* detroy the plugin data */
38043  FREE_FUNC(mod_usertrack_free) {
38044         plugin_data *p = p_d;
38045 -       
38046 +
38047         UNUSED(srv);
38048 -       
38049 +
38050         if (!p) return HANDLER_GO_ON;
38051 -       
38052 +
38053         if (p->config_storage) {
38054                 size_t i;
38055                 for (i = 0; i < srv->config_context->used; i++) {
38056                         plugin_config *s = p->config_storage[i];
38057 -                       
38058 +
38059                         buffer_free(s->cookie_name);
38060                         buffer_free(s->cookie_domain);
38061 -                       
38062 +
38063                         free(s);
38064                 }
38065                 free(p->config_storage);
38066         }
38067 -       
38068 +
38069         free(p);
38070 -       
38071 +
38072         return HANDLER_GO_ON;
38073  }
38074  
38075 @@ -70,38 +70,38 @@
38076  SETDEFAULTS_FUNC(mod_usertrack_set_defaults) {
38077         plugin_data *p = p_d;
38078         size_t i = 0;
38079 -       
38080 -       config_values_t cv[] = { 
38081 +
38082 +       config_values_t cv[] = {
38083                 { "usertrack.cookie-name",       NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
38084                 { "usertrack.cookie-max-age",    NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 1 */
38085                 { "usertrack.cookie-domain",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
38086 -               
38087 -               { "usertrack.cookiename",        NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },   
38088 +
38089 +               { "usertrack.cookiename",        NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
38090                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
38091         };
38092 -       
38093 +
38094         if (!p) return HANDLER_ERROR;
38095 -       
38096 +
38097         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
38098 -       
38099 +
38100         for (i = 0; i < srv->config_context->used; i++) {
38101                 plugin_config *s;
38102 -               
38103 +
38104                 s = calloc(1, sizeof(plugin_config));
38105                 s->cookie_name    = buffer_init();
38106                 s->cookie_domain  = buffer_init();
38107                 s->cookie_max_age = 0;
38108 -               
38109 +
38110                 cv[0].destination = s->cookie_name;
38111                 cv[1].destination = &(s->cookie_max_age);
38112                 cv[2].destination = s->cookie_domain;
38113 -               
38114 +
38115                 p->config_storage[i] = s;
38116 -       
38117 +
38118                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
38119                         return HANDLER_ERROR;
38120                 }
38121 -       
38122 +
38123                 if (buffer_is_empty(s->cookie_name)) {
38124                         buffer_copy_string(s->cookie_name, "TRACKID");
38125                 } else {
38126 @@ -109,68 +109,65 @@
38127                         for (j = 0; j < s->cookie_name->used - 1; j++) {
38128                                 char c = s->cookie_name->ptr[j] | 32;
38129                                 if (c < 'a' || c > 'z') {
38130 -                                       log_error_write(srv, __FILE__, __LINE__, "sb", 
38131 -                                                       "invalid character in usertrack.cookie-name:", 
38132 +                                       log_error_write(srv, __FILE__, __LINE__, "sb",
38133 +                                                       "invalid character in usertrack.cookie-name:",
38134                                                         s->cookie_name);
38135 -                                       
38136 +
38137                                         return HANDLER_ERROR;
38138                                 }
38139                         }
38140                 }
38141 -               
38142 +
38143                 if (!buffer_is_empty(s->cookie_domain)) {
38144                         size_t j;
38145                         for (j = 0; j < s->cookie_domain->used - 1; j++) {
38146                                 char c = s->cookie_domain->ptr[j];
38147                                 if (c <= 32 || c >= 127 || c == '"' || c == '\\') {
38148 -                                       log_error_write(srv, __FILE__, __LINE__, "sb", 
38149 -                                                       "invalid character in usertrack.cookie-domain:", 
38150 +                                       log_error_write(srv, __FILE__, __LINE__, "sb",
38151 +                                                       "invalid character in usertrack.cookie-domain:",
38152                                                         s->cookie_domain);
38153 -                                       
38154 +
38155                                         return HANDLER_ERROR;
38156                                 }
38157                         }
38158                 }
38159         }
38160 -               
38161 +
38162         return HANDLER_GO_ON;
38163  }
38164  
38165 -#define PATCH(x) \
38166 -       p->conf.x = s->x;
38167  static int mod_usertrack_patch_connection(server *srv, connection *con, plugin_data *p) {
38168         size_t i, j;
38169         plugin_config *s = p->config_storage[0];
38170 -       
38171 -       PATCH(cookie_name);
38172 -       PATCH(cookie_domain);
38173 -       PATCH(cookie_max_age);
38174 -       
38175 +
38176 +       PATCH_OPTION(cookie_name);
38177 +       PATCH_OPTION(cookie_domain);
38178 +       PATCH_OPTION(cookie_max_age);
38179 +
38180         /* skip the first, the global context */
38181         for (i = 1; i < srv->config_context->used; i++) {
38182                 data_config *dc = (data_config *)srv->config_context->data[i];
38183                 s = p->config_storage[i];
38184 -               
38185 +
38186                 /* condition didn't match */
38187                 if (!config_check_cond(srv, con, dc)) continue;
38188 -               
38189 +
38190                 /* merge config */
38191                 for (j = 0; j < dc->value->used; j++) {
38192                         data_unset *du = dc->value->data[j];
38193 -                       
38194 +
38195                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-name"))) {
38196 -                               PATCH(cookie_name);
38197 +                               PATCH_OPTION(cookie_name);
38198                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-max-age"))) {
38199 -                               PATCH(cookie_max_age);
38200 +                               PATCH_OPTION(cookie_max_age);
38201                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-domain"))) {
38202 -                               PATCH(cookie_domain);
38203 +                               PATCH_OPTION(cookie_domain);
38204                         }
38205                 }
38206         }
38207 -       
38208 +
38209         return 0;
38210  }
38211 -#undef PATCH
38212  
38213  URIHANDLER_FUNC(mod_usertrack_uri_handler) {
38214         plugin_data *p = p_d;
38215 @@ -178,38 +175,38 @@
38216         unsigned char h[16];
38217         MD5_CTX Md5Ctx;
38218         char hh[32];
38219 -       
38220 +
38221         if (con->uri.path->used == 0) return HANDLER_GO_ON;
38222 -       
38223 +
38224         mod_usertrack_patch_connection(srv, con, p);
38225 -       
38226 +
38227         if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) {
38228                 char *g;
38229                 /* we have a cookie, does it contain a valid name ? */
38230 -               
38231 -               /* parse the cookie 
38232 -                * 
38233 +
38234 +               /* parse the cookie
38235 +                *
38236                  * check for cookiename + (WS | '=')
38237 -                * 
38238 +                *
38239                  */
38240 -               
38241 +
38242                 if (NULL != (g = strstr(ds->value->ptr, p->conf.cookie_name->ptr))) {
38243                         char *nc;
38244 -                       
38245 +
38246                         /* skip WS */
38247                         for (nc = g + p->conf.cookie_name->used-1; *nc == ' ' || *nc == '\t'; nc++);
38248 -                       
38249 +
38250                         if (*nc == '=') {
38251                                 /* ok, found the key of our own cookie */
38252 -                               
38253 +
38254                                 if (strlen(nc) > 32) {
38255                                         /* i'm lazy */
38256                                         return HANDLER_GO_ON;
38257                                 }
38258                         }
38259                 }
38260 -       } 
38261 -       
38262 +       }
38263 +
38264         /* set a cookie */
38265         if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
38266                 ds = data_response_init();
38267 @@ -217,39 +214,39 @@
38268         buffer_copy_string(ds->key, "Set-Cookie");
38269         buffer_copy_string_buffer(ds->value, p->conf.cookie_name);
38270         buffer_append_string(ds->value, "=");
38271 -       
38272 +
38273  
38274         /* taken from mod_auth.c */
38275 -       
38276 +
38277         /* generate shared-secret */
38278         MD5_Init(&Md5Ctx);
38279         MD5_Update(&Md5Ctx, (unsigned char *)con->uri.path->ptr, con->uri.path->used - 1);
38280         MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
38281 -       
38282 +
38283         /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
38284         ltostr(hh, srv->cur_ts);
38285         MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
38286         ltostr(hh, rand());
38287         MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
38288 -       
38289 +
38290         MD5_Final(h, &Md5Ctx);
38291 -       
38292 +
38293         buffer_append_string_encoded(ds->value, (char *)h, 16, ENCODING_HEX);
38294         buffer_append_string(ds->value, "; Path=/");
38295         buffer_append_string(ds->value, "; Version=1");
38296 -       
38297 +
38298         if (!buffer_is_empty(p->conf.cookie_domain)) {
38299                 buffer_append_string(ds->value, "; Domain=");
38300                 buffer_append_string_encoded(ds->value, CONST_BUF_LEN(p->conf.cookie_domain), ENCODING_REL_URI);
38301         }
38302 -       
38303 +
38304         if (p->conf.cookie_max_age) {
38305                 buffer_append_string(ds->value, "; max-age=");
38306                 buffer_append_long(ds->value, p->conf.cookie_max_age);
38307         }
38308 -       
38309 +
38310         array_insert_unique(con->response.headers, (data_unset *)ds);
38311 -       
38312 +
38313         return HANDLER_GO_ON;
38314  }
38315  
38316 @@ -258,13 +255,13 @@
38317  int mod_usertrack_plugin_init(plugin *p) {
38318         p->version     = LIGHTTPD_VERSION_ID;
38319         p->name        = buffer_init_string("usertrack");
38320 -       
38321 +
38322         p->init        = mod_usertrack_init;
38323         p->handle_uri_clean  = mod_usertrack_uri_handler;
38324         p->set_defaults  = mod_usertrack_set_defaults;
38325         p->cleanup     = mod_usertrack_free;
38326 -       
38327 +
38328         p->data        = NULL;
38329 -       
38330 +
38331         return 0;
38332  }
38333 --- lighttpd-1.4.11/src/mod_webdav.c    2006-03-03 01:28:58.000000000 +0200
38334 +++ lighttpd-1.4.12/src/mod_webdav.c    2006-07-11 22:07:53.000000000 +0300
38335 @@ -3,13 +3,10 @@
38336  #include <ctype.h>
38337  #include <stdlib.h>
38338  #include <string.h>
38339 -#include <dirent.h>
38340  #include <errno.h>
38341 -#include <unistd.h>
38342  #include <fcntl.h>
38343  #include <stdio.h>
38344  #include <assert.h>
38345 -#include <sys/mman.h>
38346  
38347  #ifdef HAVE_CONFIG_H
38348  #include "config.h"
38349 @@ -23,6 +20,11 @@
38350  #include <sqlite3.h>
38351  #endif
38352  
38353 +#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H) && defined(HAVE_UUID_H)
38354 +#define USE_LOCKS
38355 +#include <uuid/uuid.h>
38356 +#endif
38357 +
38358  #include "base.h"
38359  #include "log.h"
38360  #include "buffer.h"
38361 @@ -33,13 +35,16 @@
38362  #include "stream.h"
38363  #include "stat_cache.h"
38364  
38365 +#include "sys-files.h"
38366 +#include "sys-mmap.h"
38367 +#include "sys-strings.h"
38368  
38369  /**
38370   * this is a webdav for a lighttpd plugin
38371   *
38372 - * at least a very basic one. 
38373 + * at least a very basic one.
38374   * - for now it is read-only and we only support PROPFIND
38375 - * 
38376 + *
38377   */
38378  
38379  
38380 @@ -58,64 +63,70 @@
38381         sqlite3_stmt *stmt_delete_prop;
38382         sqlite3_stmt *stmt_select_prop;
38383         sqlite3_stmt *stmt_select_propnames;
38384 -       
38385 +
38386         sqlite3_stmt *stmt_delete_uri;
38387         sqlite3_stmt *stmt_move_uri;
38388         sqlite3_stmt *stmt_copy_uri;
38389 +
38390 +       sqlite3_stmt *stmt_remove_lock;
38391 +       sqlite3_stmt *stmt_create_lock;
38392 +       sqlite3_stmt *stmt_read_lock;
38393 +       sqlite3_stmt *stmt_read_lock_by_uri;
38394 +       sqlite3_stmt *stmt_refresh_lock;
38395  #endif
38396  } plugin_config;
38397  
38398  typedef struct {
38399         PLUGIN_DATA;
38400 -       
38401 +
38402         buffer *tmp_buf;
38403         request_uri uri;
38404         physical physical;
38405  
38406         plugin_config **config_storage;
38407 -       
38408 -       plugin_config conf; 
38409 +
38410 +       plugin_config conf;
38411  } plugin_data;
38412  
38413  /* init the plugin data */
38414  INIT_FUNC(mod_webdav_init) {
38415         plugin_data *p;
38416 -       
38417 +
38418         p = calloc(1, sizeof(*p));
38419 -       
38420 +
38421         p->tmp_buf = buffer_init();
38422  
38423         p->uri.scheme = buffer_init();
38424         p->uri.path_raw = buffer_init();
38425         p->uri.path = buffer_init();
38426         p->uri.authority = buffer_init();
38427 -       
38428 +
38429         p->physical.path = buffer_init();
38430         p->physical.rel_path = buffer_init();
38431         p->physical.doc_root = buffer_init();
38432         p->physical.basedir = buffer_init();
38433 -       
38434 +
38435         return p;
38436  }
38437  
38438  /* detroy the plugin data */
38439  FREE_FUNC(mod_webdav_free) {
38440         plugin_data *p = p_d;
38441 -       
38442 +
38443         UNUSED(srv);
38444  
38445         if (!p) return HANDLER_GO_ON;
38446 -       
38447 +
38448         if (p->config_storage) {
38449                 size_t i;
38450                 for (i = 0; i < srv->config_context->used; i++) {
38451                         plugin_config *s = p->config_storage[i];
38452  
38453                         if (!s) continue;
38454 -       
38455 +
38456                         buffer_free(s->sqlite_db_name);
38457  #ifdef USE_PROPPATCH
38458 -                       if (s->sql) {   
38459 +                       if (s->sql) {
38460                                 sqlite3_finalize(s->stmt_delete_prop);
38461                                 sqlite3_finalize(s->stmt_delete_uri);
38462                                 sqlite3_finalize(s->stmt_copy_uri);
38463 @@ -123,9 +134,15 @@
38464                                 sqlite3_finalize(s->stmt_update_prop);
38465                                 sqlite3_finalize(s->stmt_select_prop);
38466                                 sqlite3_finalize(s->stmt_select_propnames);
38467 +
38468 +                               sqlite3_finalize(s->stmt_read_lock);
38469 +                               sqlite3_finalize(s->stmt_read_lock_by_uri);
38470 +                               sqlite3_finalize(s->stmt_create_lock);
38471 +                               sqlite3_finalize(s->stmt_remove_lock);
38472 +                               sqlite3_finalize(s->stmt_refresh_lock);
38473                                 sqlite3_close(s->sql);
38474                         }
38475 -#endif 
38476 +#endif
38477                         free(s);
38478                 }
38479                 free(p->config_storage);
38480 @@ -135,16 +152,16 @@
38481         buffer_free(p->uri.path_raw);
38482         buffer_free(p->uri.path);
38483         buffer_free(p->uri.authority);
38484 -       
38485 +
38486         buffer_free(p->physical.path);
38487         buffer_free(p->physical.rel_path);
38488         buffer_free(p->physical.doc_root);
38489         buffer_free(p->physical.basedir);
38490 -       
38491 +
38492         buffer_free(p->tmp_buf);
38493 -       
38494 +
38495         free(p);
38496 -       
38497 +
38498         return HANDLER_GO_ON;
38499  }
38500  
38501 @@ -153,32 +170,32 @@
38502  SETDEFAULTS_FUNC(mod_webdav_set_defaults) {
38503         plugin_data *p = p_d;
38504         size_t i = 0;
38505 -       
38506 -       config_values_t cv[] = { 
38507 +
38508 +       config_values_t cv[] = {
38509                 { "webdav.activate",            NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
38510                 { "webdav.is-readonly",         NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
38511                 { "webdav.sqlite-db-name",      NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_CONNECTION },       /* 2 */
38512                 { "webdav.log-xml",             NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },       /* 3 */
38513                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
38514         };
38515 -       
38516 +
38517         if (!p) return HANDLER_ERROR;
38518 -       
38519 +
38520         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
38521 -       
38522 +
38523         for (i = 0; i < srv->config_context->used; i++) {
38524                 plugin_config *s;
38525 -               
38526 +
38527                 s = calloc(1, sizeof(plugin_config));
38528                 s->sqlite_db_name = buffer_init();
38529 -               
38530 +
38531                 cv[0].destination = &(s->enabled);
38532                 cv[1].destination = &(s->is_readonly);
38533                 cv[2].destination = s->sqlite_db_name;
38534                 cv[3].destination = &(s->log_xml);
38535 -               
38536 +
38537                 p->config_storage[i] = s;
38538 -       
38539 +
38540                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
38541                         return HANDLER_ERROR;
38542                 }
38543 @@ -193,8 +210,26 @@
38544                                 return HANDLER_ERROR;
38545                         }
38546  
38547 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38548 -                               CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"), 
38549 +                       if (SQLITE_OK != sqlite3_exec(s->sql,
38550 +                                       "CREATE TABLE properties ("
38551 +                                       "  resource TEXT NOT NULL,"
38552 +                                       "  prop TEXT NOT NULL,"
38553 +                                       "  ns TEXT NOT NULL,"
38554 +                                       "  value TEXT NOT NULL,"
38555 +                                       "  PRIMARY KEY(resource, prop, ns))",
38556 +                                       NULL, NULL, &err)) {
38557 +
38558 +                               if (0 != strcmp(err, "table properties already exists")) {
38559 +                                       log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
38560 +                                       sqlite3_free(err);
38561 +
38562 +                                       return HANDLER_ERROR;
38563 +                               }
38564 +                               sqlite3_free(err);
38565 +                       }
38566 +
38567 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38568 +                               CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
38569                                 &(s->stmt_select_prop), &next_stmt)) {
38570                                 /* prepare failed */
38571  
38572 @@ -202,8 +237,8 @@
38573                                 return HANDLER_ERROR;
38574                         }
38575  
38576 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38577 -                               CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"), 
38578 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38579 +                               CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"),
38580                                 &(s->stmt_select_propnames), &next_stmt)) {
38581                                 /* prepare failed */
38582  
38583 @@ -211,16 +246,67 @@
38584                                 return HANDLER_ERROR;
38585                         }
38586  
38587 -                       if (SQLITE_OK != sqlite3_exec(s->sql, 
38588 -                                       "CREATE TABLE properties ("
38589 +
38590 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38591 +                               CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"),
38592 +                               &(s->stmt_update_prop), &next_stmt)) {
38593 +                               /* prepare failed */
38594 +
38595 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
38596 +                               return HANDLER_ERROR;
38597 +                       }
38598 +
38599 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38600 +                               CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
38601 +                               &(s->stmt_delete_prop), &next_stmt)) {
38602 +                               /* prepare failed */
38603 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38604 +
38605 +                               return HANDLER_ERROR;
38606 +                       }
38607 +
38608 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38609 +                               CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"),
38610 +                               &(s->stmt_delete_uri), &next_stmt)) {
38611 +                               /* prepare failed */
38612 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38613 +
38614 +                               return HANDLER_ERROR;
38615 +                       }
38616 +
38617 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38618 +                               CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"),
38619 +                               &(s->stmt_copy_uri), &next_stmt)) {
38620 +                               /* prepare failed */
38621 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38622 +
38623 +                               return HANDLER_ERROR;
38624 +                       }
38625 +
38626 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38627 +                               CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"),
38628 +                               &(s->stmt_move_uri), &next_stmt)) {
38629 +                               /* prepare failed */
38630 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38631 +
38632 +                               return HANDLER_ERROR;
38633 +                       }
38634 +
38635 +                       /* LOCKS */
38636 +
38637 +                       if (SQLITE_OK != sqlite3_exec(s->sql,
38638 +                                       "CREATE TABLE locks ("
38639 +                                       "  locktoken TEXT NOT NULL,"
38640                                         "  resource TEXT NOT NULL,"
38641 -                                       "  prop TEXT NOT NULL,"
38642 -                                       "  ns TEXT NOT NULL,"
38643 -                                       "  value TEXT NOT NULL,"
38644 -                                       "  PRIMARY KEY(resource, prop, ns))",
38645 +                                       "  lockscope TEXT NOT NULL,"
38646 +                                       "  locktype TEXT NOT NULL,"
38647 +                                       "  owner TEXT NOT NULL,"
38648 +                                       "  depth INT NOT NULL,"
38649 +                                       "  timeout TIMESTAMP NOT NULL,"
38650 +                                       "  PRIMARY KEY(locktoken))",
38651                                         NULL, NULL, &err)) {
38652  
38653 -                               if (0 != strcmp(err, "table properties already exists")) {
38654 +                               if (0 != strcmp(err, "table locks already exists")) {
38655                                         log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
38656                                         sqlite3_free(err);
38657  
38658 @@ -228,127 +314,138 @@
38659                                 }
38660                                 sqlite3_free(err);
38661                         }
38662 -       
38663 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38664 -                               CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"), 
38665 -                               &(s->stmt_update_prop), &next_stmt)) {
38666 +
38667 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38668 +                               CONST_STR_LEN("INSERT INTO locks (locktoken, resource, lockscope, locktype, owner, depth, timeout) VALUES (?,?,?,?,?,?, CURRENT_TIME + 600)"),
38669 +                               &(s->stmt_create_lock), &next_stmt)) {
38670                                 /* prepare failed */
38671 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38672  
38673 -                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
38674                                 return HANDLER_ERROR;
38675                         }
38676  
38677 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38678 -                               CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"), 
38679 -                               &(s->stmt_delete_prop), &next_stmt)) {
38680 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38681 +                               CONST_STR_LEN("DELETE FROM locks WHERE locktoken = ?"),
38682 +                               &(s->stmt_remove_lock), &next_stmt)) {
38683                                 /* prepare failed */
38684                                 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38685  
38686                                 return HANDLER_ERROR;
38687                         }
38688  
38689 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38690 -                               CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"), 
38691 -                               &(s->stmt_delete_uri), &next_stmt)) {
38692 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38693 +                               CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE locktoken = ?"),
38694 +                               &(s->stmt_read_lock), &next_stmt)) {
38695                                 /* prepare failed */
38696                                 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38697  
38698                                 return HANDLER_ERROR;
38699                         }
38700  
38701 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38702 -                               CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"), 
38703 -                               &(s->stmt_copy_uri), &next_stmt)) {
38704 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38705 +                               CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE resource = ?"),
38706 +                               &(s->stmt_read_lock_by_uri), &next_stmt)) {
38707                                 /* prepare failed */
38708                                 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38709  
38710                                 return HANDLER_ERROR;
38711                         }
38712  
38713 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38714 -                               CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"), 
38715 -                               &(s->stmt_move_uri), &next_stmt)) {
38716 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38717 +                               CONST_STR_LEN("UPDATE locks SET timeout = CURRENT_TIME + 600 WHERE locktoken = ?"),
38718 +                               &(s->stmt_refresh_lock), &next_stmt)) {
38719                                 /* prepare failed */
38720                                 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38721  
38722                                 return HANDLER_ERROR;
38723                         }
38724 +
38725 +
38726  #else
38727                         log_error_write(srv, __FILE__, __LINE__, "s", "Sorry, no sqlite3 and libxml2 support include, compile with --with-webdav-props");
38728                         return HANDLER_ERROR;
38729  #endif
38730                 }
38731         }
38732 -       
38733 +
38734         return HANDLER_GO_ON;
38735  }
38736  
38737 -#define PATCH(x) \
38738 -       p->conf.x = s->x;
38739  static int mod_webdav_patch_connection(server *srv, connection *con, plugin_data *p) {
38740         size_t i, j;
38741         plugin_config *s = p->config_storage[0];
38742 -       
38743 -       PATCH(enabled);
38744 -       PATCH(is_readonly);
38745 -       PATCH(log_xml);
38746 -       
38747 +
38748 +       PATCH_OPTION(enabled);
38749 +       PATCH_OPTION(is_readonly);
38750 +       PATCH_OPTION(log_xml);
38751 +
38752  #ifdef USE_PROPPATCH
38753 -       PATCH(sql);
38754 -       PATCH(stmt_update_prop);
38755 -       PATCH(stmt_delete_prop);
38756 -       PATCH(stmt_select_prop);
38757 -       PATCH(stmt_select_propnames);
38758 -
38759 -       PATCH(stmt_delete_uri);
38760 -       PATCH(stmt_move_uri);
38761 -       PATCH(stmt_copy_uri);
38762 +       PATCH_OPTION(sql);
38763 +       PATCH_OPTION(stmt_update_prop);
38764 +       PATCH_OPTION(stmt_delete_prop);
38765 +       PATCH_OPTION(stmt_select_prop);
38766 +       PATCH_OPTION(stmt_select_propnames);
38767 +
38768 +       PATCH_OPTION(stmt_delete_uri);
38769 +       PATCH_OPTION(stmt_move_uri);
38770 +       PATCH_OPTION(stmt_copy_uri);
38771 +
38772 +       PATCH_OPTION(stmt_remove_lock);
38773 +       PATCH_OPTION(stmt_refresh_lock);
38774 +       PATCH_OPTION(stmt_create_lock);
38775 +       PATCH_OPTION(stmt_read_lock);
38776 +       PATCH_OPTION(stmt_read_lock_by_uri);
38777  #endif
38778         /* skip the first, the global context */
38779         for (i = 1; i < srv->config_context->used; i++) {
38780                 data_config *dc = (data_config *)srv->config_context->data[i];
38781                 s = p->config_storage[i];
38782 -               
38783 +
38784                 /* condition didn't match */
38785                 if (!config_check_cond(srv, con, dc)) continue;
38786 -               
38787 +
38788                 /* merge config */
38789                 for (j = 0; j < dc->value->used; j++) {
38790                         data_unset *du = dc->value->data[j];
38791 -                       
38792 +
38793                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.activate"))) {
38794 -                               PATCH(enabled);
38795 +                               PATCH_OPTION(enabled);
38796                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.is-readonly"))) {
38797 -                               PATCH(is_readonly);
38798 +                               PATCH_OPTION(is_readonly);
38799                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.log-xml"))) {
38800 -                               PATCH(log_xml);
38801 +                               PATCH_OPTION(log_xml);
38802                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.sqlite-db-name"))) {
38803  #ifdef USE_PROPPATCH
38804 -                               PATCH(sql);
38805 -                               PATCH(stmt_update_prop);
38806 -                               PATCH(stmt_delete_prop);
38807 -                               PATCH(stmt_select_prop);
38808 -                               PATCH(stmt_select_propnames);
38809 -                               
38810 -                               PATCH(stmt_delete_uri);
38811 -                               PATCH(stmt_move_uri);
38812 -                               PATCH(stmt_copy_uri);
38813 +                               PATCH_OPTION(sql);
38814 +                               PATCH_OPTION(stmt_update_prop);
38815 +                               PATCH_OPTION(stmt_delete_prop);
38816 +                               PATCH_OPTION(stmt_select_prop);
38817 +                               PATCH_OPTION(stmt_select_propnames);
38818 +
38819 +                               PATCH_OPTION(stmt_delete_uri);
38820 +                               PATCH_OPTION(stmt_move_uri);
38821 +                               PATCH_OPTION(stmt_copy_uri);
38822 +
38823 +                               PATCH_OPTION(stmt_remove_lock);
38824 +                               PATCH_OPTION(stmt_refresh_lock);
38825 +                               PATCH_OPTION(stmt_create_lock);
38826 +                               PATCH_OPTION(stmt_read_lock);
38827 +                               PATCH_OPTION(stmt_read_lock_by_uri);
38828  #endif
38829                         }
38830                 }
38831         }
38832 -       
38833 +
38834         return 0;
38835  }
38836 -#undef PATCH
38837  
38838  URIHANDLER_FUNC(mod_webdav_uri_handler) {
38839         plugin_data *p = p_d;
38840 -       
38841 +
38842         UNUSED(srv);
38843  
38844         if (con->uri.path->used == 0) return HANDLER_GO_ON;
38845 -       
38846 +
38847         mod_webdav_patch_connection(srv, con, p);
38848  
38849         if (!p->conf.enabled) return HANDLER_GO_ON;
38850 @@ -362,20 +459,20 @@
38851                 if (p->conf.is_readonly) {
38852                         response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND"));
38853                 } else {
38854 -                       response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH"));
38855 +                       response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH, LOCK, UNLOCK"));
38856                 }
38857                 break;
38858         default:
38859                 break;
38860         }
38861 -       
38862 +
38863         /* not found */
38864         return HANDLER_GO_ON;
38865  }
38866 -static int webdav_gen_prop_tag(server *srv, connection *con, 
38867 -               char *prop_name, 
38868 -               char *prop_ns, 
38869 -               char *value, 
38870 +static int webdav_gen_prop_tag(server *srv, connection *con,
38871 +               char *prop_name,
38872 +               char *prop_ns,
38873 +               char *value,
38874                 buffer *b) {
38875  
38876         UNUSED(srv);
38877 @@ -414,7 +511,7 @@
38878         buffer_append_string_buffer(b, dst->rel_path);
38879         buffer_append_string(b,"</D:href>\n");
38880         buffer_append_string(b,"<D:status>\n");
38881 -       
38882 +
38883         if (con->request.http_version == HTTP_VERSION_1_1) {
38884                 BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
38885         } else {
38886 @@ -458,11 +555,11 @@
38887  
38888                         /* bind the values to the insert */
38889  
38890 -                       sqlite3_bind_text(stmt, 1, 
38891 -                                         dst->rel_path->ptr, 
38892 +                       sqlite3_bind_text(stmt, 1,
38893 +                                         dst->rel_path->ptr,
38894                                           dst->rel_path->used - 1,
38895                                           SQLITE_TRANSIENT);
38896 -                                                                       
38897 +
38898                         if (SQLITE_DONE != sqlite3_step(stmt)) {
38899                                 /* */
38900                                 WP();
38901 @@ -493,14 +590,14 @@
38902                             (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
38903                                 continue;
38904                                 /* ignore the parent dir */
38905 -                       } 
38906 +                       }
38907  
38908                         buffer_copy_string_buffer(d.path, dst->path);
38909 -                       BUFFER_APPEND_SLASH(d.path);
38910 +                       PATHNAME_APPEND_SLASH(d.path);
38911                         buffer_append_string(d.path, de->d_name);
38912 -                       
38913 +
38914                         buffer_copy_string_buffer(d.rel_path, dst->rel_path);
38915 -                       BUFFER_APPEND_SLASH(d.rel_path);
38916 +                       PATHNAME_APPEND_SLASH(d.rel_path);
38917                         buffer_append_string(d.rel_path, de->d_name);
38918  
38919                         /* stat and unlink afterwards */
38920 @@ -508,7 +605,7 @@
38921                                 /* don't about it yet, rmdir will fail too */
38922                         } else if (S_ISDIR(st.st_mode)) {
38923                                 have_multi_status = webdav_delete_dir(srv, con, p, &d, b);
38924 -                                       
38925 +
38926                                 /* try to unlink it */
38927                                 if (-1 == rmdir(d.path->ptr)) {
38928                                         switch(errno) {
38929 @@ -535,11 +632,11 @@
38930  
38931                                                 /* bind the values to the insert */
38932  
38933 -                                               sqlite3_bind_text(stmt, 1, 
38934 -                                                                 d.rel_path->ptr, 
38935 +                                               sqlite3_bind_text(stmt, 1,
38936 +                                                                 d.rel_path->ptr,
38937                                                                   d.rel_path->used - 1,
38938                                                                   SQLITE_TRANSIENT);
38939 -                                                                                                       
38940 +
38941                                                 if (SQLITE_DONE != sqlite3_step(stmt)) {
38942                                                         /* */
38943                                                         WP();
38944 @@ -569,7 +666,7 @@
38945         if (stream_open(&s, src->path)) {
38946                 return 403;
38947         }
38948 -                       
38949 +
38950         if (-1 == (ofd = open(dst->path->ptr, O_WRONLY|O_TRUNC|O_CREAT|(overwrite ? 0 : O_EXCL), 0600))) {
38951                 /* opening the destination failed for some reason */
38952                 switch(errno) {
38953 @@ -601,7 +698,7 @@
38954                         break;
38955                 }
38956         }
38957 -       
38958 +
38959         stream_close(&s);
38960         close(ofd);
38961  
38962 @@ -614,16 +711,16 @@
38963                         sqlite3_reset(stmt);
38964  
38965                         /* bind the values to the insert */
38966 -                       sqlite3_bind_text(stmt, 1, 
38967 -                                         dst->rel_path->ptr, 
38968 +                       sqlite3_bind_text(stmt, 1,
38969 +                                         dst->rel_path->ptr,
38970                                           dst->rel_path->used - 1,
38971                                           SQLITE_TRANSIENT);
38972  
38973 -                       sqlite3_bind_text(stmt, 2, 
38974 -                                         src->rel_path->ptr, 
38975 +                       sqlite3_bind_text(stmt, 2,
38976 +                                         src->rel_path->ptr,
38977                                           src->rel_path->used - 1,
38978                                           SQLITE_TRANSIENT);
38979 -                                                                                                       
38980 +
38981                         if (SQLITE_DONE != sqlite3_step(stmt)) {
38982                                 /* */
38983                                 WP();
38984 @@ -655,21 +752,21 @@
38985                             (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
38986                                 continue;
38987                         }
38988 -                       
38989 +
38990                         buffer_copy_string_buffer(s.path, src->path);
38991 -                       BUFFER_APPEND_SLASH(s.path);
38992 +                       PATHNAME_APPEND_SLASH(s.path);
38993                         buffer_append_string(s.path, de->d_name);
38994  
38995                         buffer_copy_string_buffer(d.path, dst->path);
38996 -                       BUFFER_APPEND_SLASH(d.path);
38997 +                       PATHNAME_APPEND_SLASH(d.path);
38998                         buffer_append_string(d.path, de->d_name);
38999  
39000                         buffer_copy_string_buffer(s.rel_path, src->rel_path);
39001 -                       BUFFER_APPEND_SLASH(s.rel_path);
39002 +                       PATHNAME_APPEND_SLASH(s.rel_path);
39003                         buffer_append_string(s.rel_path, de->d_name);
39004  
39005                         buffer_copy_string_buffer(d.rel_path, dst->rel_path);
39006 -                       BUFFER_APPEND_SLASH(d.rel_path);
39007 +                       PATHNAME_APPEND_SLASH(d.rel_path);
39008                         buffer_append_string(d.rel_path, de->d_name);
39009  
39010                         if (-1 == stat(s.path->ptr, &st)) {
39011 @@ -692,16 +789,16 @@
39012                                                 sqlite3_reset(stmt);
39013  
39014                                                 /* bind the values to the insert */
39015 -                                               sqlite3_bind_text(stmt, 1, 
39016 -                                                         dst->rel_path->ptr, 
39017 +                                               sqlite3_bind_text(stmt, 1,
39018 +                                                         dst->rel_path->ptr,
39019                                                           dst->rel_path->used - 1,
39020                                                           SQLITE_TRANSIENT);
39021  
39022 -                                               sqlite3_bind_text(stmt, 2, 
39023 -                                                         src->rel_path->ptr, 
39024 +                                               sqlite3_bind_text(stmt, 2,
39025 +                                                         src->rel_path->ptr,
39026                                                           src->rel_path->used - 1,
39027                                                           SQLITE_TRANSIENT);
39028 -                                                                                                       
39029 +
39030                                                 if (SQLITE_DONE != sqlite3_step(stmt)) {
39031                                                         /* */
39032                                                         WP();
39033 @@ -721,7 +818,7 @@
39034                 buffer_free(s.rel_path);
39035                 buffer_free(d.path);
39036                 buffer_free(d.rel_path);
39037 -               
39038 +
39039                 closedir(srcdir);
39040         }
39041  
39042 @@ -748,12 +845,12 @@
39043                         if (S_ISDIR(sce->st.st_mode)) {
39044                                 buffer_append_string(b, "<D:getcontenttype>httpd/unix-directory</D:getcontenttype>");
39045                                 found = 1;
39046 -                       } else if(S_ISREG(sce->st.st_mode)) { 
39047 +                       } else if(S_ISREG(sce->st.st_mode)) {
39048                                 for (k = 0; k < con->conf.mimetypes->used; k++) {
39049                                         data_string *ds = (data_string *)con->conf.mimetypes->data[k];
39050 -               
39051 +
39052                                         if (ds->key->used == 0) continue;
39053 -                               
39054 +
39055                                         if (buffer_is_equal_right_len(dst->path, ds->key, ds->key->used - 1)) {
39056                                                 buffer_append_string(b,"<D:getcontenttype>");
39057                                                 buffer_append_string_buffer(b, ds->value);
39058 @@ -807,23 +904,23 @@
39059  
39060                         /* bind the values to the insert */
39061  
39062 -                       sqlite3_bind_text(stmt, 1, 
39063 -                                         dst->rel_path->ptr, 
39064 +                       sqlite3_bind_text(stmt, 1,
39065 +                                         dst->rel_path->ptr,
39066                                           dst->rel_path->used - 1,
39067                                           SQLITE_TRANSIENT);
39068 -                       sqlite3_bind_text(stmt, 2, 
39069 +                       sqlite3_bind_text(stmt, 2,
39070                                           prop_name,
39071                                           strlen(prop_name),
39072                                           SQLITE_TRANSIENT);
39073 -                       sqlite3_bind_text(stmt, 3, 
39074 +                       sqlite3_bind_text(stmt, 3,
39075                                           prop_ns,
39076                                           strlen(prop_ns),
39077                                           SQLITE_TRANSIENT);
39078  
39079                         /* it is the PK */
39080 -                       while (SQLITE_ROW == sqlite3_step(p->conf.stmt_select_prop)) {
39081 +                       while (SQLITE_ROW == sqlite3_step(stmt)) {
39082                                 /* there is a row for us, we only expect a single col 'value' */
39083 -                               webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(p->conf.stmt_select_prop, 0), b);
39084 +                               webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(stmt, 0), b);
39085                                 found = 1;
39086                         }
39087                 }
39088 @@ -840,7 +937,7 @@
39089         char *prop;
39090  } webdav_property;
39091  
39092 -webdav_property live_properties[] = { 
39093 +webdav_property live_properties[] = {
39094         { "DAV:", "creationdate" },
39095         { "DAV:", "displayname" },
39096         { "DAV:", "getcontentlanguage" },
39097 @@ -871,8 +968,8 @@
39098                         webdav_property *prop;
39099  
39100                         prop = props->ptr[i];
39101 -                       
39102 -                       if (0 != webdav_get_property(srv, con, p, 
39103 +
39104 +                       if (0 != webdav_get_property(srv, con, p,
39105                                 dst, prop->prop, prop->ns, b_200)) {
39106                                 webdav_gen_prop_tag(srv, con, prop->prop, prop->ns, NULL, b_404);
39107                         }
39108 @@ -916,12 +1013,12 @@
39109                                 if (-1 == c->file.fd &&  /* open the file if not already open */
39110                                     -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
39111                                         log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
39112 -               
39113 +
39114                                         return -1;
39115                                 }
39116 -       
39117 +
39118                                 if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
39119 -                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ", 
39120 +                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
39121                                                         strerror(errno), c->file.name,  c->file.fd);
39122  
39123                                         return -1;
39124 @@ -938,7 +1035,7 @@
39125                         if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->file.mmap.start + c->offset, weHave, 0))) {
39126                                 log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err);
39127                         }
39128 -                       
39129 +
39130                         c->offset += weHave;
39131                         cq->bytes_out += weHave;
39132  
39133 @@ -956,7 +1053,7 @@
39134                         if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->mem->ptr + c->offset, weHave, 0))) {
39135                                 log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err);
39136                         }
39137 -                       
39138 +
39139                         c->offset += weHave;
39140                         cq->bytes_out += weHave;
39141  
39142 @@ -991,6 +1088,113 @@
39143  }
39144  #endif
39145  
39146 +int webdav_lockdiscovery(server *srv, connection *con,
39147 +               buffer *locktoken, const char *lockscope, const char *locktype, int depth) {
39148 +
39149 +       buffer *b;
39150 +
39151 +       response_header_overwrite(srv, con, CONST_STR_LEN("Lock-Token"), CONST_BUF_LEN(locktoken));
39152 +
39153 +       response_header_overwrite(srv, con,
39154 +               CONST_STR_LEN("Content-Type"),
39155 +               CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39156 +
39157 +       b = chunkqueue_get_append_buffer(con->write_queue);
39158 +
39159 +       buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
39160 +
39161 +       buffer_append_string(b,"<D:prop xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
39162 +       buffer_append_string(b,"<D:lockdiscovery>\n");
39163 +       buffer_append_string(b,"<D:activelock>\n");
39164 +
39165 +       buffer_append_string(b,"<D:lockscope>");
39166 +       buffer_append_string(b,"<D:");
39167 +       buffer_append_string(b, lockscope);
39168 +       buffer_append_string(b, "/>");
39169 +       buffer_append_string(b,"</D:lockscope>\n");
39170 +
39171 +       buffer_append_string(b,"<D:locktype>");
39172 +       buffer_append_string(b,"<D:");
39173 +       buffer_append_string(b, locktype);
39174 +       buffer_append_string(b, "/>");
39175 +       buffer_append_string(b,"</D:locktype>\n");
39176 +
39177 +       buffer_append_string(b,"<D:depth>");
39178 +       buffer_append_string(b, depth == 0 ? "0" : "infinity");
39179 +       buffer_append_string(b,"</D:depth>\n");
39180 +
39181 +       buffer_append_string(b,"<D:timeout>");
39182 +       buffer_append_string(b, "Second-600");
39183 +       buffer_append_string(b,"</D:timeout>\n");
39184 +
39185 +       buffer_append_string(b,"<D:owner>");
39186 +       buffer_append_string(b,"</D:owner>\n");
39187 +
39188 +       buffer_append_string(b,"<D:locktoken>");
39189 +       buffer_append_string(b, "<D:href>");
39190 +       buffer_append_string_buffer(b, locktoken);
39191 +       buffer_append_string(b, "</D:href>");
39192 +       buffer_append_string(b,"</D:locktoken>\n");
39193 +
39194 +       buffer_append_string(b,"</D:activelock>\n");
39195 +       buffer_append_string(b,"</D:lockdiscovery>\n");
39196 +       buffer_append_string(b,"</D:prop>\n");
39197 +
39198 +       return 0;
39199 +}
39200 +/**
39201 + * check if resource is having the right locks to access to resource
39202 + *
39203 + *
39204 + *
39205 + */
39206 +int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer *uri) {
39207 +       int has_lock = 1;
39208 +
39209 +#ifdef USE_LOCKS
39210 +       data_string *ds;
39211 +
39212 +       /**
39213 +        * If can have
39214 +        * - <lock-token>
39215 +        * - [etag]
39216 +        *
39217 +        * there is NOT, AND and OR
39218 +        * and a list can be tagged
39219 +        *
39220 +        * (<lock-token>) is untagged
39221 +        * <tag> (<lock-token>) is tagged
39222 +        *
39223 +        * as long as we don't handle collections it is simple. :)
39224 +        *
39225 +        * X-Litmus: locks: 11 (owner_modify)
39226 +        * If: <http://127.0.0.1:1025/dav/litmus/lockme> (<opaquelocktoken:2165478d-0611-49c4-be92-e790d68a38f1>)
39227 +        *
39228 +        * X-Litmus: locks: 16 (fail_cond_put)
39229 +        * If: (<DAV:no-lock> ["-1622396671"])
39230 +        */
39231 +       if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
39232 +       } else {
39233 +               /* we didn't provided a lock-token -> */
39234 +               /* if the resource is locked -> 423 */
39235 +
39236 +               sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
39237 +
39238 +               sqlite3_reset(stmt);
39239 +
39240 +               sqlite3_bind_text(stmt, 1,
39241 +                         CONST_BUF_LEN(uri),
39242 +                         SQLITE_TRANSIENT);
39243 +
39244 +               while (SQLITE_ROW == sqlite3_step(stmt)) {
39245 +                       has_lock = 0;
39246 +               }
39247 +       }
39248 +#endif
39249 +
39250 +       return has_lock;
39251 +}
39252 +
39253  URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
39254         plugin_data *p = p_d;
39255         buffer *b;
39256 @@ -1001,7 +1205,8 @@
39257         buffer *prop_200;
39258         buffer *prop_404;
39259         webdav_properties *req_props;
39260 -       
39261 +       stat_cache_entry *sce = NULL;
39262 +
39263         UNUSED(srv);
39264  
39265         if (!p->conf.enabled) return HANDLER_GO_ON;
39266 @@ -1019,7 +1224,19 @@
39267                 req_props = NULL;
39268  
39269                 /* is there a content-body ? */
39270 -       
39271 +
39272 +               switch (stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
39273 +               case HANDLER_ERROR:
39274 +                       if (errno == ENOENT) {
39275 +                               con->http_status = 404;
39276 +                               return HANDLER_FINISHED;
39277 +                       }
39278 +                       break;
39279 +               default:
39280 +                       break;
39281 +               }
39282 +
39283 +
39284  #ifdef USE_PROPPATCH
39285                 /* any special requests or just allprop ? */
39286                 if (con->request.content_length) {
39287 @@ -1087,12 +1304,12 @@
39288                                                                 /* get all property names (EMPTY) */
39289                                                                 sqlite3_reset(stmt);
39290                                                                 /* bind the values to the insert */
39291 -       
39292 -                                                               sqlite3_bind_text(stmt, 1, 
39293 -                                                                                 con->uri.path->ptr, 
39294 +
39295 +                                                               sqlite3_bind_text(stmt, 1,
39296 +                                                                                 con->uri.path->ptr,
39297                                                                                   con->uri.path->used - 1,
39298                                                                                   SQLITE_TRANSIENT);
39299 -                                               
39300 +
39301                                                                 if (SQLITE_DONE != sqlite3_step(stmt)) {
39302                                                                         WP();
39303                                                                 }
39304 @@ -1115,13 +1332,13 @@
39305                 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39306  
39307                 b = chunkqueue_get_append_buffer(con->write_queue);
39308 -                               
39309 +
39310                 buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
39311  
39312                 buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
39313  
39314                 /* allprop */
39315 -               
39316 +
39317                 prop_200 = buffer_init();
39318                 prop_404 = buffer_init();
39319  
39320 @@ -1129,7 +1346,7 @@
39321                 case 0:
39322                         /* Depth: 0 */
39323                         webdav_get_props(srv, con, p, &(con->physical), req_props, prop_200, prop_404);
39324 -       
39325 +
39326                         buffer_append_string(b,"<D:response>\n");
39327                         buffer_append_string(b,"<D:href>");
39328                         buffer_append_string_buffer(b, con->uri.scheme);
39329 @@ -1145,9 +1362,9 @@
39330                                 buffer_append_string_buffer(b, prop_200);
39331  
39332                                 buffer_append_string(b,"</D:prop>\n");
39333 -       
39334 +
39335                                 buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
39336 -       
39337 +
39338                                 buffer_append_string(b,"</D:propstat>\n");
39339                         }
39340                         if (!buffer_is_empty(prop_404)) {
39341 @@ -1157,16 +1374,16 @@
39342                                 buffer_append_string_buffer(b, prop_404);
39343  
39344                                 buffer_append_string(b,"</D:prop>\n");
39345 -       
39346 +
39347                                 buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
39348 -       
39349 +
39350                                 buffer_append_string(b,"</D:propstat>\n");
39351                         }
39352  
39353                         buffer_append_string(b,"</D:response>\n");
39354  
39355                         break;
39356 -               case 1: 
39357 +               case 1:
39358                         if (NULL != (dir = opendir(con->physical.path->ptr))) {
39359                                 struct dirent *de;
39360                                 physical d;
39361 @@ -1179,16 +1396,16 @@
39362                                         if (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') {
39363                                                 continue;
39364                                                 /* ignore the parent dir */
39365 -                                       } 
39366 +                                       }
39367  
39368                                         buffer_copy_string_buffer(d.path, dst->path);
39369 -                                       BUFFER_APPEND_SLASH(d.path);
39370 +                                       PATHNAME_APPEND_SLASH(d.path);
39371  
39372                                         buffer_copy_string_buffer(d.rel_path, dst->rel_path);
39373 -                                       BUFFER_APPEND_SLASH(d.rel_path);
39374 +                                       PATHNAME_APPEND_SLASH(d.rel_path);
39375  
39376                                         if (de->d_name[0] == '.' && de->d_name[1] == '\0') {
39377 -                                               /* don't append the . */ 
39378 +                                               /* don't append the . */
39379                                         } else {
39380                                                 buffer_append_string(d.path, de->d_name);
39381                                                 buffer_append_string(d.rel_path, de->d_name);
39382 @@ -1198,7 +1415,7 @@
39383                                         buffer_reset(prop_404);
39384  
39385                                         webdav_get_props(srv, con, p, &d, req_props, prop_200, prop_404);
39386 -                                       
39387 +
39388                                         buffer_append_string(b,"<D:response>\n");
39389                                         buffer_append_string(b,"<D:href>");
39390                                         buffer_append_string_buffer(b, con->uri.scheme);
39391 @@ -1214,9 +1431,9 @@
39392                                                 buffer_append_string_buffer(b, prop_200);
39393  
39394                                                 buffer_append_string(b,"</D:prop>\n");
39395 -                       
39396 +
39397                                                 buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
39398 -                       
39399 +
39400                                                 buffer_append_string(b,"</D:propstat>\n");
39401                                         }
39402                                         if (!buffer_is_empty(prop_404)) {
39403 @@ -1226,9 +1443,9 @@
39404                                                 buffer_append_string_buffer(b, prop_404);
39405  
39406                                                 buffer_append_string(b,"</D:prop>\n");
39407 -       
39408 +
39409                                                 buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
39410 -       
39411 +
39412                                                 buffer_append_string(b,"</D:propstat>\n");
39413                                         }
39414  
39415 @@ -1275,7 +1492,7 @@
39416  
39417                         return HANDLER_FINISHED;
39418                 }
39419 -       
39420 +
39421                 /* let's create the directory */
39422  
39423                 if (-1 == mkdir(con->physical.path->ptr, 0700)) {
39424 @@ -1303,7 +1520,13 @@
39425                         con->http_status = 403;
39426                         return HANDLER_FINISHED;
39427                 }
39428 -               
39429 +
39430 +               /* does the client have a lock for this connection ? */
39431 +               if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39432 +                       con->http_status = 423;
39433 +                       return HANDLER_FINISHED;
39434 +               }
39435 +
39436                 /* stat and unlink afterwards */
39437                 if (-1 == stat(con->physical.path->ptr, &st)) {
39438                         /* don't about it yet, unlink will fail too */
39439 @@ -1323,7 +1546,7 @@
39440                                 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39441  
39442                                 b = chunkqueue_get_append_buffer(con->write_queue);
39443 -                       
39444 +
39445                                 buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
39446  
39447                                 buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\">\n");
39448 @@ -1331,7 +1554,7 @@
39449                                 buffer_append_string_buffer(b, multi_status_resp);
39450  
39451                                 buffer_append_string(b,"</D:multistatus>\n");
39452 -                       
39453 +
39454                                 if (p->conf.log_xml) {
39455                                         log_error_write(srv, __FILE__, __LINE__, "sb", "XML-response-body:", b);
39456                                 }
39457 @@ -1340,7 +1563,7 @@
39458                                 con->file_finished = 1;
39459                         } else {
39460                                 /* everything went fine, remove the directory */
39461 -       
39462 +
39463                                 if (-1 == rmdir(con->physical.path->ptr)) {
39464                                         switch(errno) {
39465                                         case ENOENT:
39466 @@ -1375,97 +1598,174 @@
39467         case HTTP_METHOD_PUT: {
39468                 int fd;
39469                 chunkqueue *cq = con->request_content_queue;
39470 +               chunk *c;
39471 +               data_string *ds_range;
39472  
39473                 if (p->conf.is_readonly) {
39474                         con->http_status = 403;
39475                         return HANDLER_FINISHED;
39476                 }
39477  
39478 +               /* is a exclusive lock set on the source */
39479 +               if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39480 +                       con->http_status = 423;
39481 +                       return HANDLER_FINISHED;
39482 +               }
39483 +
39484 +
39485                 assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
39486  
39487 -               /* taken what we have in the request-body and write it to a file */
39488 -               if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC, 0600))) {
39489 -                       /* we can't open the file */
39490 -                       con->http_status = 403;
39491 -               } else {
39492 -                       chunk *c;
39493 +               /* RFC2616 Section 9.6 PUT requires us to send 501 on all Content-* we don't support
39494 +                * - most important Content-Range
39495 +                *
39496 +                *
39497 +                * Example: Content-Range: bytes 100-1037/1038 */
39498  
39499 -                       con->http_status = 201; /* created */
39500 -                       con->file_finished = 1;
39501 +               if (NULL != (ds_range = (data_string *)array_get_element(con->request.headers, "Content-Range"))) {
39502 +                       const char *num = ds_range->value->ptr;
39503 +                       off_t offset;
39504 +                       char *err = NULL;
39505  
39506 -                       for (c = cq->first; c; c = cq->first) {
39507 -                               int r = 0; 
39508 +                       if (0 != strncmp(num, "bytes ", 6)) {
39509 +                               con->http_status = 501; /* not implemented */
39510  
39511 -                               /* copy all chunks */
39512 -                               switch(c->type) {
39513 -                               case FILE_CHUNK:
39514 -
39515 -                                       if (c->file.mmap.start == MAP_FAILED) {
39516 -                                               if (-1 == c->file.fd &&  /* open the file if not already open */
39517 -                                                   -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
39518 -                                                       log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
39519 -                                       
39520 -                                                       return -1;
39521 -                                               }
39522 -                               
39523 -                                               if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
39524 -                                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ", 
39525 -                                                                       strerror(errno), c->file.name,  c->file.fd);
39526 +                               return HANDLER_FINISHED;
39527 +                       }
39528  
39529 -                                                       return -1;
39530 -                                               }
39531 +                       /* we only support <num>- ... */
39532  
39533 -                                               c->file.mmap.length = c->file.length;
39534 +                       num += 6;
39535  
39536 -                                               close(c->file.fd);
39537 -                                               c->file.fd = -1;
39538 -       
39539 -                                               /* chunk_reset() or chunk_free() will cleanup for us */
39540 -                                       }
39541 -
39542 -                                       if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
39543 -                                               switch(errno) {
39544 -                                               case ENOSPC:
39545 -                                                       con->http_status = 507;
39546 -               
39547 -                                                       break;
39548 -                                               default:
39549 -                                                       con->http_status = 403;
39550 -                                                       break;
39551 -                                               }
39552 -                                       }
39553 -                                       break;
39554 -                               case MEM_CHUNK:
39555 -                                       if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
39556 -                                               switch(errno) {
39557 -                                               case ENOSPC:
39558 -                                                       con->http_status = 507;
39559 -               
39560 -                                                       break;
39561 -                                               default:
39562 -                                                       con->http_status = 403;
39563 -                                                       break;
39564 -                                               }
39565 -                                       }
39566 +                       /* skip WS */
39567 +                       while (*num == ' ' || *num == '\t') num++;
39568 +
39569 +                       if (*num == '\0') {
39570 +                               con->http_status = 501; /* not implemented */
39571 +
39572 +                               return HANDLER_FINISHED;
39573 +                       }
39574 +
39575 +                       offset = strtoll(num, &err, 10);
39576 +
39577 +                       if (*err != '-' || offset < 0) {
39578 +                               con->http_status = 501; /* not implemented */
39579 +
39580 +                               return HANDLER_FINISHED;
39581 +                       }
39582 +
39583 +                       if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY, 0600))) {
39584 +                               switch (errno) {
39585 +                               case ENOENT:
39586 +                                       con->http_status = 404; /* not found */
39587                                         break;
39588 -                               case UNUSED_CHUNK:
39589 +                               default:
39590 +                                       con->http_status = 403; /* not found */
39591                                         break;
39592                                 }
39593 +                               return HANDLER_FINISHED;
39594 +                       }
39595 +
39596 +                       if (-1 == lseek(fd, offset, SEEK_SET)) {
39597 +                               con->http_status = 501; /* not implemented */
39598 +
39599 +                               close(fd);
39600 +
39601 +                               return HANDLER_FINISHED;
39602 +                       }
39603 +                       con->http_status = 200; /* modified */
39604 +               } else {
39605 +                       /* take what we have in the request-body and write it to a file */
39606 +
39607 +                       /* if the file doesn't exist, create it */
39608 +                       if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_TRUNC, 0600))) {
39609 +                               if (errno == ENOENT &&
39610 +                                   -1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0600))) {
39611 +                                       /* we can't open the file */
39612 +                                       con->http_status = 403;
39613  
39614 -                               if (r > 0) {
39615 -                                       c->offset += r;
39616 -                                       cq->bytes_out += r;
39617 +                                       return HANDLER_FINISHED;
39618                                 } else {
39619 -                                       break;
39620 +                                       con->http_status = 201; /* created */
39621 +                               }
39622 +                       } else {
39623 +                               con->http_status = 200; /* modified */
39624 +                       }
39625 +               }
39626 +
39627 +               con->file_finished = 1;
39628 +
39629 +               for (c = cq->first; c; c = cq->first) {
39630 +                       int r = 0;
39631 +
39632 +                       /* copy all chunks */
39633 +                       switch(c->type) {
39634 +                       case FILE_CHUNK:
39635 +
39636 +                               if (c->file.mmap.start == MAP_FAILED) {
39637 +                                       if (-1 == c->file.fd &&  /* open the file if not already open */
39638 +                                           -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
39639 +                                               log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
39640 +
39641 +                                               return -1;
39642 +                                       }
39643 +
39644 +                                       if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
39645 +                                               log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
39646 +                                                               strerror(errno), c->file.name,  c->file.fd);
39647 +
39648 +                                               return -1;
39649 +                                       }
39650 +
39651 +                                       c->file.mmap.length = c->file.length;
39652 +
39653 +                                       close(c->file.fd);
39654 +                                       c->file.fd = -1;
39655 +
39656 +                                       /* chunk_reset() or chunk_free() will cleanup for us */
39657 +                               }
39658 +
39659 +                               if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
39660 +                                       switch(errno) {
39661 +                                       case ENOSPC:
39662 +                                               con->http_status = 507;
39663 +
39664 +                                               break;
39665 +                                       default:
39666 +                                               con->http_status = 403;
39667 +                                               break;
39668 +                                       }
39669                                 }
39670 -                               chunkqueue_remove_finished_chunks(cq);
39671 +                               break;
39672 +                       case MEM_CHUNK:
39673 +                               if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
39674 +                                       switch(errno) {
39675 +                                       case ENOSPC:
39676 +                                               con->http_status = 507;
39677 +
39678 +                                               break;
39679 +                                       default:
39680 +                                               con->http_status = 403;
39681 +                                               break;
39682 +                                       }
39683 +                               }
39684 +                               break;
39685 +                       case UNUSED_CHUNK:
39686 +                               break;
39687                         }
39688 -                       close(fd);
39689  
39690 +                       if (r > 0) {
39691 +                               c->offset += r;
39692 +                               cq->bytes_out += r;
39693 +                       } else {
39694 +                               break;
39695 +                       }
39696 +                       chunkqueue_remove_finished_chunks(cq);
39697                 }
39698 +               close(fd);
39699 +
39700                 return HANDLER_FINISHED;
39701         }
39702 -       case HTTP_METHOD_MOVE: 
39703 +       case HTTP_METHOD_MOVE:
39704         case HTTP_METHOD_COPY: {
39705                 buffer *destination = NULL;
39706                 char *sep, *start;
39707 @@ -1475,7 +1775,15 @@
39708                         con->http_status = 403;
39709                         return HANDLER_FINISHED;
39710                 }
39711 -               
39712 +
39713 +               /* is a exclusive lock set on the source */
39714 +               if (con->request.http_method == HTTP_METHOD_MOVE) {
39715 +                       if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39716 +                               con->http_status = 423;
39717 +                               return HANDLER_FINISHED;
39718 +                       }
39719 +               }
39720 +
39721                 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Destination"))) {
39722                         destination = ds->value;
39723                 } else {
39724 @@ -1549,10 +1857,10 @@
39725                 }
39726  
39727                 buffer_copy_string_buffer(p->physical.path, p->physical.doc_root);
39728 -               BUFFER_APPEND_SLASH(p->physical.path);
39729 +               PATHNAME_APPEND_SLASH(p->physical.path);
39730                 buffer_copy_string_buffer(p->physical.basedir, p->physical.path);
39731  
39732 -               /* don't add a second / */ 
39733 +               /* don't add a second / */
39734                 if (p->physical.rel_path->ptr[0] == '/') {
39735                         buffer_append_string_len(p->physical.path, p->physical.rel_path->ptr + 1, p->physical.rel_path->used - 2);
39736                 } else {
39737 @@ -1613,6 +1921,12 @@
39738                         /* it is just a file, good */
39739                         int r;
39740  
39741 +                       /* does the client have a lock for this connection ? */
39742 +                       if (!webdav_has_lock(srv, con, p, p->uri.path)) {
39743 +                               con->http_status = 423;
39744 +                               return HANDLER_FINISHED;
39745 +                       }
39746 +
39747                         /* destination exists */
39748                         if (0 == (r = stat(p->physical.path->ptr, &st))) {
39749                                 if (S_ISDIR(st.st_mode)) {
39750 @@ -1636,7 +1950,7 @@
39751                                         return HANDLER_FINISHED;
39752                                 }
39753                         } else if (overwrite == 0) {
39754 -                               /* destination exists, but overwrite is not set */ 
39755 +                               /* destination exists, but overwrite is not set */
39756                                 con->http_status = 412;
39757                                 return HANDLER_FINISHED;
39758                         } else {
39759 @@ -1655,16 +1969,16 @@
39760                                                 sqlite3_reset(stmt);
39761  
39762                                                 /* bind the values to the insert */
39763 -                                               sqlite3_bind_text(stmt, 1, 
39764 -                                                                 p->uri.path->ptr, 
39765 +                                               sqlite3_bind_text(stmt, 1,
39766 +                                                                 p->uri.path->ptr,
39767                                                                   p->uri.path->used - 1,
39768                                                                   SQLITE_TRANSIENT);
39769  
39770 -                                               sqlite3_bind_text(stmt, 2, 
39771 -                                                                 con->uri.path->ptr, 
39772 +                                               sqlite3_bind_text(stmt, 2,
39773 +                                                                 con->uri.path->ptr,
39774                                                                   con->uri.path->used - 1,
39775                                                                   SQLITE_TRANSIENT);
39776 -                                               
39777 +
39778                                                 if (SQLITE_DONE != sqlite3_step(stmt)) {
39779                                                         log_error_write(srv, __FILE__, __LINE__, "ss", "sql-move failed:", sqlite3_errmsg(p->conf.sql));
39780                                                 }
39781 @@ -1691,12 +2005,17 @@
39782  
39783                 return HANDLER_FINISHED;
39784         }
39785 -       case HTTP_METHOD_PROPPATCH: {
39786 +       case HTTP_METHOD_PROPPATCH:
39787                 if (p->conf.is_readonly) {
39788                         con->http_status = 403;
39789                         return HANDLER_FINISHED;
39790                 }
39791  
39792 +               if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39793 +                       con->http_status = 423;
39794 +                       return HANDLER_FINISHED;
39795 +               }
39796 +
39797                 /* check if destination exists */
39798                 if (-1 == stat(con->physical.path->ptr, &st)) {
39799                         switch(errno) {
39800 @@ -1737,7 +2056,7 @@
39801  
39802                                                         sqlite3_stmt *stmt;
39803  
39804 -                                                       stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ? 
39805 +                                                       stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ?
39806                                                                 p->conf.stmt_delete_prop : p->conf.stmt_update_prop;
39807  
39808                                                         for (props = cmd->children; props; props = props->next) {
39809 @@ -1762,34 +2081,35 @@
39810  
39811                                                                         /* bind the values to the insert */
39812  
39813 -                                                                       sqlite3_bind_text(stmt, 1, 
39814 -                                                                                         con->uri.path->ptr, 
39815 +                                                                       sqlite3_bind_text(stmt, 1,
39816 +                                                                                         con->uri.path->ptr,
39817                                                                                           con->uri.path->used - 1,
39818                                                                                           SQLITE_TRANSIENT);
39819 -                                                                       sqlite3_bind_text(stmt, 2, 
39820 +                                                                       sqlite3_bind_text(stmt, 2,
39821                                                                                           (char *)prop->name,
39822                                                                                           strlen((char *)prop->name),
39823                                                                                           SQLITE_TRANSIENT);
39824                                                                         if (prop->ns) {
39825 -                                                                               sqlite3_bind_text(stmt, 3, 
39826 +                                                                               sqlite3_bind_text(stmt, 3,
39827                                                                                                   (char *)prop->ns->href,
39828                                                                                                   strlen((char *)prop->ns->href),
39829                                                                                                   SQLITE_TRANSIENT);
39830                                                                         } else {
39831 -                                                                               sqlite3_bind_text(stmt, 3, 
39832 +                                                                               sqlite3_bind_text(stmt, 3,
39833                                                                                                   "",
39834                                                                                                   0,
39835                                                                                                   SQLITE_TRANSIENT);
39836                                                                         }
39837                                                                         if (stmt == p->conf.stmt_update_prop) {
39838 -                                                                               sqlite3_bind_text(stmt, 4, 
39839 +                                                                               sqlite3_bind_text(stmt, 4,
39840                                                                                           (char *)xmlNodeGetContent(prop),
39841                                                                                           strlen((char *)xmlNodeGetContent(prop)),
39842                                                                                           SQLITE_TRANSIENT);
39843                                                                         }
39844 -                                                               
39845 +
39846                                                                         if (SQLITE_DONE != (r = sqlite3_step(stmt))) {
39847 -                                                                               log_error_write(srv, __FILE__, __LINE__, "ss", "sql-set failed:", sqlite3_errmsg(p->conf.sql));
39848 +                                                                               log_error_write(srv, __FILE__, __LINE__, "ss",
39849 +                                                                                               "sql-set failed:", sqlite3_errmsg(p->conf.sql));
39850                                                                         }
39851                                                                 }
39852                                                         }
39853 @@ -1804,7 +2124,7 @@
39854  
39855                                                         goto propmatch_cleanup;
39856                                                 }
39857 -       
39858 +
39859                                                 con->http_status = 400;
39860                                         } else {
39861                                                 if (SQLITE_OK != sqlite3_exec(p->conf.sql, "COMMIT", NULL, NULL, &err)) {
39862 @@ -1821,6 +2141,7 @@
39863                                 }
39864  
39865  propmatch_cleanup:
39866 +
39867                                 xmlFreeDoc(xml);
39868                         } else {
39869                                 con->http_status = 400;
39870 @@ -1830,11 +2151,307 @@
39871  #endif
39872                 con->http_status = 501;
39873                 return HANDLER_FINISHED;
39874 -       }
39875 +       case HTTP_METHOD_LOCK:
39876 +               /**
39877 +                * a mac wants to write
39878 +                *
39879 +                * LOCK /dav/expire.txt HTTP/1.1\r\n
39880 +                * User-Agent: WebDAVFS/1.3 (01308000) Darwin/8.1.0 (Power Macintosh)\r\n
39881 +                * Accept: * / *\r\n
39882 +                * Depth: 0\r\n
39883 +                * Timeout: Second-600\r\n
39884 +                * Content-Type: text/xml; charset=\"utf-8\"\r\n
39885 +                * Content-Length: 229\r\n
39886 +                * Connection: keep-alive\r\n
39887 +                * Host: 192.168.178.23:1025\r\n
39888 +                * \r\n
39889 +                * <?xml version=\"1.0\" encoding=\"utf-8\"?>\n
39890 +                * <D:lockinfo xmlns:D=\"DAV:\">\n
39891 +                *  <D:lockscope><D:exclusive/></D:lockscope>\n
39892 +                *  <D:locktype><D:write/></D:locktype>\n
39893 +                *  <D:owner>\n
39894 +                *   <D:href>http://www.apple.com/webdav_fs/</D:href>\n
39895 +                *  </D:owner>\n
39896 +                * </D:lockinfo>\n
39897 +                */
39898 +
39899 +               if (depth != 0 && depth != -1) {
39900 +                       con->http_status = 400;
39901 +
39902 +                       return HANDLER_FINISHED;
39903 +               }
39904 +
39905 +#ifdef USE_LOCKS
39906 +               if (con->request.content_length) {
39907 +                       xmlDocPtr xml;
39908 +                       buffer *hdr_if = NULL;
39909 +
39910 +                       if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
39911 +                               hdr_if = ds->value;
39912 +                       }
39913 +
39914 +                       /* we don't support Depth: Infinity on locks */
39915 +                       if (hdr_if == NULL && depth == -1) {
39916 +                               con->http_status = 409; /* Conflict */
39917 +
39918 +                               return HANDLER_FINISHED;
39919 +                       }
39920 +
39921 +                       if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) {
39922 +                               xmlNode *rootnode = xmlDocGetRootElement(xml);
39923 +
39924 +                               assert(rootnode);
39925 +
39926 +                               if (0 == xmlStrcmp(rootnode->name, BAD_CAST "lockinfo")) {
39927 +                                       xmlNode *lockinfo;
39928 +                                       const xmlChar *lockscope = NULL, *locktype = NULL, *owner = NULL;
39929 +
39930 +                                       for (lockinfo = rootnode->children; lockinfo; lockinfo = lockinfo->next) {
39931 +                                               if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "lockscope")) {
39932 +                                                       xmlNode *value;
39933 +                                                       for (value = lockinfo->children; value; value = value->next) {
39934 +                                                               if ((0 == xmlStrcmp(value->name, BAD_CAST "exclusive")) ||
39935 +                                                                   (0 == xmlStrcmp(value->name, BAD_CAST "shared"))) {
39936 +                                                                       lockscope = value->name;
39937 +                                                               } else {
39938 +                                                                       con->http_status = 400;
39939 +
39940 +                                                                       xmlFreeDoc(xml);
39941 +                                                                       return HANDLER_FINISHED;
39942 +                                                               }
39943 +                                                       }
39944 +                                               } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "locktype")) {
39945 +                                                       xmlNode *value;
39946 +                                                       for (value = lockinfo->children; value; value = value->next) {
39947 +                                                               if ((0 == xmlStrcmp(value->name, BAD_CAST "write"))) {
39948 +                                                                       locktype = value->name;
39949 +                                                               } else {
39950 +                                                                       con->http_status = 400;
39951 +
39952 +                                                                       xmlFreeDoc(xml);
39953 +                                                                       return HANDLER_FINISHED;
39954 +                                                               }
39955 +                                                       }
39956 +
39957 +                                               } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "owner")) {
39958 +                                               }
39959 +                                       }
39960 +
39961 +                                       if (lockscope && locktype) {
39962 +                                               sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
39963 +
39964 +                                               /* is this resourse already locked ? */
39965 +
39966 +                                               /* SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout
39967 +                                                *   FROM locks
39968 +                                                *  WHERE resource = ? */
39969 +
39970 +                                               if (stmt) {
39971 +
39972 +                                                       sqlite3_reset(stmt);
39973 +
39974 +                                                       sqlite3_bind_text(stmt, 1,
39975 +                                                                         p->uri.path->ptr,
39976 +                                                                         p->uri.path->used - 1,
39977 +                                                                         SQLITE_TRANSIENT);
39978 +
39979 +                                                       /* it is the PK */
39980 +                                                       while (SQLITE_ROW == sqlite3_step(stmt)) {
39981 +                                                               /* we found a lock
39982 +                                                                * 1. is it compatible ?
39983 +                                                                * 2. is it ours */
39984 +                                                               char *sql_lockscope = (char *)sqlite3_column_text(stmt, 2);
39985 +
39986 +                                                               if (strcmp(sql_lockscope, "exclusive")) {
39987 +                                                                       con->http_status = 423;
39988 +                                                               } else if (0 == xmlStrcmp(lockscope, BAD_CAST "exclusive")) {
39989 +                                                                       /* resourse is locked with a shared lock
39990 +                                                                        * client wants exclusive */
39991 +                                                                       con->http_status = 423;
39992 +                                                               }
39993 +                                                       }
39994 +                                                       if (con->http_status == 423) {
39995 +                                                               xmlFreeDoc(xml);
39996 +                                                               return HANDLER_FINISHED;
39997 +                                                       }
39998 +                                               }
39999 +
40000 +                                               stmt = p->conf.stmt_create_lock;
40001 +                                               if (stmt) {
40002 +                                                       /* create a lock-token */
40003 +                                                       uuid_t id;
40004 +                                                       char uuid[37] /* 36 + \0 */;
40005 +
40006 +                                                       uuid_generate(id);
40007 +                                                       uuid_unparse(id, uuid);
40008 +
40009 +                                                       buffer_copy_string(p->tmp_buf, "opaquelocktoken:");
40010 +                                                       buffer_append_string(p->tmp_buf, uuid);
40011 +
40012 +                                                       /* "CREATE TABLE locks ("
40013 +                                                        * "  locktoken TEXT NOT NULL,"
40014 +                                                        * "  resource TEXT NOT NULL,"
40015 +                                                        * "  lockscope TEXT NOT NULL,"
40016 +                                                        * "  locktype TEXT NOT NULL,"
40017 +                                                        * "  owner TEXT NOT NULL,"
40018 +                                                        * "  depth INT NOT NULL,"
40019 +                                                        */
40020 +
40021 +                                                       sqlite3_reset(stmt);
40022 +
40023 +                                                       sqlite3_bind_text(stmt, 1,
40024 +                                                                         CONST_BUF_LEN(p->tmp_buf),
40025 +                                                                         SQLITE_TRANSIENT);
40026 +
40027 +                                                       sqlite3_bind_text(stmt, 2,
40028 +                                                                         CONST_BUF_LEN(con->uri.path),
40029 +                                                                         SQLITE_TRANSIENT);
40030 +
40031 +                                                       sqlite3_bind_text(stmt, 3,
40032 +                                                                         lockscope,
40033 +                                                                         xmlStrlen(lockscope),
40034 +                                                                         SQLITE_TRANSIENT);
40035 +
40036 +                                                       sqlite3_bind_text(stmt, 4,
40037 +                                                                         locktype,
40038 +                                                                         xmlStrlen(locktype),
40039 +                                                                         SQLITE_TRANSIENT);
40040 +
40041 +                                                       /* owner */
40042 +                                                       sqlite3_bind_text(stmt, 5,
40043 +                                                                         "",
40044 +                                                                         0,
40045 +                                                                         SQLITE_TRANSIENT);
40046 +
40047 +                                                       /* depth */
40048 +                                                       sqlite3_bind_int(stmt, 6,
40049 +                                                                        depth);
40050 +
40051 +
40052 +                                                       if (SQLITE_DONE != sqlite3_step(stmt)) {
40053 +                                                               log_error_write(srv, __FILE__, __LINE__, "ss",
40054 +                                                                               "create lock:", sqlite3_errmsg(p->conf.sql));
40055 +                                                       }
40056 +
40057 +                                                       /* looks like we survived */
40058 +                                                       webdav_lockdiscovery(srv, con, p->tmp_buf, lockscope, locktype, depth);
40059 +
40060 +                                                       con->http_status = 201;
40061 +                                                       con->file_finished = 1;
40062 +                                               }
40063 +                                       }
40064 +                               }
40065 +
40066 +                               xmlFreeDoc(xml);
40067 +                               return HANDLER_FINISHED;
40068 +                       } else {
40069 +                               con->http_status = 400;
40070 +                               return HANDLER_FINISHED;
40071 +                       }
40072 +               } else {
40073 +
40074 +                       if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
40075 +                               buffer *locktoken = ds->value;
40076 +                               sqlite3_stmt *stmt = p->conf.stmt_refresh_lock;
40077 +
40078 +                               /* remove the < > around the token */
40079 +                               if (locktoken->used < 6) {
40080 +                                       con->http_status = 400;
40081 +
40082 +                                       return HANDLER_FINISHED;
40083 +                               }
40084 +
40085 +                               buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 2, locktoken->used - 5);
40086 +
40087 +                               sqlite3_reset(stmt);
40088 +
40089 +                               sqlite3_bind_text(stmt, 1,
40090 +                                         CONST_BUF_LEN(p->tmp_buf),
40091 +                                         SQLITE_TRANSIENT);
40092 +
40093 +                               if (SQLITE_DONE != sqlite3_step(stmt)) {
40094 +                                       log_error_write(srv, __FILE__, __LINE__, "ss",
40095 +                                               "refresh lock:", sqlite3_errmsg(p->conf.sql));
40096 +                               }
40097 +
40098 +                               webdav_lockdiscovery(srv, con, p->tmp_buf, "exclusive", "write", 0);
40099 +
40100 +                               con->http_status = 200;
40101 +                               con->file_finished = 1;
40102 +                               return HANDLER_FINISHED;
40103 +                       } else {
40104 +                               /* we need a lock-token to refresh */
40105 +                               con->http_status = 400;
40106 +
40107 +                               return HANDLER_FINISHED;
40108 +                       }
40109 +               }
40110 +               break;
40111 +#else
40112 +               con->http_status = 501;
40113 +               return HANDLER_FINISHED;
40114 +#endif
40115 +       case HTTP_METHOD_UNLOCK:
40116 +#ifdef USE_LOCKS
40117 +               if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Lock-Token"))) {
40118 +                       buffer *locktoken = ds->value;
40119 +                       sqlite3_stmt *stmt = p->conf.stmt_remove_lock;
40120 +
40121 +                       /* remove the < > around the token */
40122 +                       if (locktoken->used < 4) {
40123 +                               con->http_status = 400;
40124 +
40125 +                               return HANDLER_FINISHED;
40126 +                       }
40127 +
40128 +                       /**
40129 +                        * FIXME:
40130 +                        *
40131 +                        * if the resourse is locked:
40132 +                        * - by us: unlock
40133 +                        * - by someone else: 401
40134 +                        * if the resource is not locked:
40135 +                        * - 412
40136 +                        *  */
40137 +
40138 +                       buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 1, locktoken->used - 3);
40139 +
40140 +                       sqlite3_reset(stmt);
40141 +
40142 +                       sqlite3_bind_text(stmt, 1,
40143 +                                 CONST_BUF_LEN(p->tmp_buf),
40144 +                                 SQLITE_TRANSIENT);
40145 +
40146 +                       sqlite3_bind_text(stmt, 2,
40147 +                                 CONST_BUF_LEN(con->uri.path),
40148 +                                 SQLITE_TRANSIENT);
40149 +
40150 +                       if (SQLITE_DONE != sqlite3_step(stmt)) {
40151 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
40152 +                                       "remove lock:", sqlite3_errmsg(p->conf.sql));
40153 +                       }
40154 +
40155 +                       if (0 == sqlite3_changes(p->conf.sql)) {
40156 +                               con->http_status = 401;
40157 +                       } else {
40158 +                               con->http_status = 204;
40159 +                       }
40160 +                       return HANDLER_FINISHED;
40161 +               } else {
40162 +                       /* we need a lock-token to unlock */
40163 +                       con->http_status = 400;
40164 +
40165 +                       return HANDLER_FINISHED;
40166 +               }
40167 +               break;
40168 +#else
40169 +               con->http_status = 501;
40170 +               return HANDLER_FINISHED;
40171 +#endif
40172         default:
40173                 break;
40174         }
40175 -       
40176 +
40177         /* not found */
40178         return HANDLER_GO_ON;
40179  }
40180 @@ -1845,14 +2462,14 @@
40181  int mod_webdav_plugin_init(plugin *p) {
40182         p->version     = LIGHTTPD_VERSION_ID;
40183         p->name        = buffer_init_string("webdav");
40184 -       
40185 +
40186         p->init        = mod_webdav_init;
40187         p->handle_uri_clean  = mod_webdav_uri_handler;
40188         p->handle_physical   = mod_webdav_subrequest_handler;
40189         p->set_defaults  = mod_webdav_set_defaults;
40190         p->cleanup     = mod_webdav_free;
40191 -       
40192 +
40193         p->data        = NULL;
40194 -       
40195 +
40196         return 0;
40197  }
40198 --- lighttpd-1.4.11/src/network.c       2006-03-04 16:45:46.000000000 +0200
40199 +++ lighttpd-1.4.12/src/network.c       2006-07-11 22:07:51.000000000 +0300
40200 @@ -1,14 +1,14 @@
40201  #include <sys/types.h>
40202  #include <sys/stat.h>
40203 -#include <sys/time.h>
40204  
40205  #include <errno.h>
40206  #include <fcntl.h>
40207 -#include <unistd.h>
40208  #include <string.h>
40209  #include <stdlib.h>
40210  #include <assert.h>
40211  
40212 +#include <stdio.h>
40213 +
40214  #include "network.h"
40215  #include "fdevent.h"
40216  #include "log.h"
40217 @@ -19,11 +19,12 @@
40218  #include "network_backends.h"
40219  #include "sys-mmap.h"
40220  #include "sys-socket.h"
40221 +#include "sys-files.h"
40222  
40223  #ifdef USE_OPENSSL
40224 -# include <openssl/ssl.h> 
40225 -# include <openssl/err.h> 
40226 -# include <openssl/rand.h> 
40227 +# include <openssl/ssl.h>
40228 +# include <openssl/err.h>
40229 +# include <openssl/rand.h>
40230  #endif
40231  
40232  handler_t network_server_handle_fdevent(void *s, void *context, int revents) {
40233 @@ -31,11 +32,11 @@
40234         server_socket *srv_socket = (server_socket *)context;
40235         connection *con;
40236         int loops = 0;
40237 -       
40238 +
40239         UNUSED(context);
40240 -       
40241 +
40242         if (revents != FDEVENT_IN) {
40243 -               log_error_write(srv, __FILE__, __LINE__, "sdd", 
40244 +               log_error_write(srv, __FILE__, __LINE__, "sdd",
40245                                 "strange event for server socket",
40246                                 srv_socket->fd,
40247                                 revents);
40248 @@ -44,12 +45,12 @@
40249  
40250         /* accept()s at most 100 connections directly
40251          *
40252 -        * we jump out after 100 to give the waiting connections a chance */    
40253 +        * we jump out after 100 to give the waiting connections a chance */
40254         for (loops = 0; loops < 100 && NULL != (con = connection_accept(srv, srv_socket)); loops++) {
40255                 handler_t r;
40256 -               
40257 +
40258                 connection_state_machine(srv, con);
40259 -               
40260 +
40261                 switch(r = plugins_call_handle_joblist(srv, con)) {
40262                 case HANDLER_FINISHED:
40263                 case HANDLER_GO_ON:
40264 @@ -72,18 +73,18 @@
40265         buffer *b;
40266         int is_unix_domain_socket = 0;
40267         int fd;
40268 -       
40269 +
40270  #ifdef SO_ACCEPTFILTER
40271         struct accept_filter_arg afa;
40272  #endif
40273  
40274 -#ifdef __WIN32
40275 +#ifdef _WIN32
40276         WORD wVersionRequested;
40277         WSADATA wsaData;
40278         int err;
40279 -        
40280 +
40281         wVersionRequested = MAKEWORD( 2, 2 );
40282 -        
40283 +
40284         err = WSAStartup( wVersionRequested, &wsaData );
40285         if ( err != 0 ) {
40286                     /* Tell the user that we could not find a usable */
40287 @@ -91,37 +92,37 @@
40288                     return -1;
40289         }
40290  #endif
40291 -       
40292 +
40293         srv_socket = calloc(1, sizeof(*srv_socket));
40294         srv_socket->fd = -1;
40295 -       
40296 +
40297         srv_socket->srv_token = buffer_init();
40298         buffer_copy_string_buffer(srv_socket->srv_token, host_token);
40299 -       
40300 +
40301         b = buffer_init();
40302         buffer_copy_string_buffer(b, host_token);
40303 -       
40304 -       /* ipv4:port 
40305 +
40306 +       /* ipv4:port
40307          * [ipv6]:port
40308          */
40309         if (NULL == (sp = strrchr(b->ptr, ':'))) {
40310                 log_error_write(srv, __FILE__, __LINE__, "sb", "value of $SERVER[\"socket\"] has to be \"ip:port\".", b);
40311 -               
40312 +
40313                 return -1;
40314         }
40315 -       
40316 +
40317         host = b->ptr;
40318 -       
40319 +
40320         /* check for [ and ] */
40321         if (b->ptr[0] == '[' && *(sp-1) == ']') {
40322                 *(sp-1) = '\0';
40323                 host++;
40324 -               
40325 +
40326                 s->use_ipv6 = 1;
40327         }
40328 -       
40329 +
40330         *(sp++) = '\0';
40331 -       
40332 +
40333         port = strtol(sp, NULL, 10);
40334  
40335         if (host[0] == '/') {
40336 @@ -129,17 +130,17 @@
40337                 is_unix_domain_socket = 1;
40338         } else if (port == 0 || port > 65535) {
40339                 log_error_write(srv, __FILE__, __LINE__, "sd", "port out of range:", port);
40340 -       
40341 +
40342                 return -1;
40343         }
40344 -       
40345 +
40346         if (*host == '\0') host = NULL;
40347  
40348         if (is_unix_domain_socket) {
40349  #ifdef HAVE_SYS_UN_H
40350  
40351                 srv_socket->addr.plain.sa_family = AF_UNIX;
40352 -               
40353 +
40354                 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) {
40355                         log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
40356                         return -1;
40357 @@ -154,7 +155,7 @@
40358  #ifdef HAVE_IPV6
40359         if (s->use_ipv6) {
40360                 srv_socket->addr.plain.sa_family = AF_INET6;
40361 -               
40362 +
40363                 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
40364                         log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
40365                         return -1;
40366 @@ -162,7 +163,7 @@
40367                 srv_socket->use_ipv6 = 1;
40368         }
40369  #endif
40370 -                               
40371 +
40372         if (srv_socket->fd == -1) {
40373                 srv_socket->addr.plain.sa_family = AF_INET;
40374                 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
40375 @@ -170,16 +171,16 @@
40376                         return -1;
40377                 }
40378         }
40379 -       
40380 +
40381         /* */
40382         srv->cur_fds = srv_socket->fd;
40383 -       
40384 +
40385         val = 1;
40386         if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
40387                 log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt failed:", strerror(errno));
40388                 return -1;
40389         }
40390 -       
40391 +
40392         switch(srv_socket->addr.plain.sa_family) {
40393  #ifdef HAVE_IPV6
40394         case AF_INET6:
40395 @@ -190,23 +191,23 @@
40396                 } else {
40397                         struct addrinfo hints, *res;
40398                         int r;
40399 -                       
40400 +
40401                         memset(&hints, 0, sizeof(hints));
40402 -                       
40403 +
40404                         hints.ai_family   = AF_INET6;
40405                         hints.ai_socktype = SOCK_STREAM;
40406                         hints.ai_protocol = IPPROTO_TCP;
40407 -                       
40408 +
40409                         if (0 != (r = getaddrinfo(host, NULL, &hints, &res))) {
40410 -                               log_error_write(srv, __FILE__, __LINE__, 
40411 -                                               "sssss", "getaddrinfo failed: ", 
40412 +                               log_error_write(srv, __FILE__, __LINE__,
40413 +                                               "sssss", "getaddrinfo failed: ",
40414                                                 gai_strerror(r), "'", host, "'");
40415 -                               
40416 +
40417                                 return -1;
40418                         }
40419 -                       
40420 +
40421                         memcpy(&(srv_socket->addr), res->ai_addr, res->ai_addrlen);
40422 -                       
40423 +
40424                         freeaddrinfo(res);
40425                 }
40426                 srv_socket->addr.ipv6.sin6_port = htons(port);
40427 @@ -221,33 +222,34 @@
40428                 } else {
40429                         struct hostent *he;
40430                         if (NULL == (he = gethostbyname(host))) {
40431 -                               log_error_write(srv, __FILE__, __LINE__, 
40432 -                                               "sds", "gethostbyname failed: ", 
40433 +                               log_error_write(srv, __FILE__, __LINE__,
40434 +                                               "sds", "gethostbyname failed: ",
40435                                                 h_errno, host);
40436                                 return -1;
40437                         }
40438 -                       
40439 +
40440                         if (he->h_addrtype != AF_INET) {
40441                                 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
40442                                 return -1;
40443                         }
40444 -                       
40445 +
40446                         if (he->h_length != sizeof(struct in_addr)) {
40447                                 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
40448                                 return -1;
40449                         }
40450 -                       
40451 +
40452                         memcpy(&(srv_socket->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
40453                 }
40454                 srv_socket->addr.ipv4.sin_port = htons(port);
40455 -               
40456 +
40457                 addr_len = sizeof(struct sockaddr_in);
40458 -               
40459 +
40460                 break;
40461 +#ifndef _WIN32
40462         case AF_UNIX:
40463                 srv_socket->addr.un.sun_family = AF_UNIX;
40464                 strcpy(srv_socket->addr.un.sun_path, host);
40465 -               
40466 +
40467  #ifdef SUN_LEN
40468                 addr_len = SUN_LEN(&srv_socket->addr.un);
40469  #else
40470 @@ -259,8 +261,8 @@
40471                 if (-1 != (fd = connect(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) {
40472                         close(fd);
40473  
40474 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
40475 -                               "server socket is still in use:", 
40476 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
40477 +                               "server socket is still in use:",
40478                                 host);
40479  
40480  
40481 @@ -275,88 +277,89 @@
40482                 case ENOENT:
40483                         break;
40484                 default:
40485 -                       log_error_write(srv, __FILE__, __LINE__, "sds", 
40486 -                               "testing socket failed:", 
40487 +                       log_error_write(srv, __FILE__, __LINE__, "sds",
40488 +                               "testing socket failed:",
40489                                 host, strerror(errno));
40490  
40491                         return -1;
40492                 }
40493  
40494                 break;
40495 +#endif
40496         default:
40497                 addr_len = 0;
40498 -               
40499 +
40500                 return -1;
40501         }
40502 -       
40503 +
40504         if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
40505                 switch(srv_socket->addr.plain.sa_family) {
40506                 case AF_UNIX:
40507 -                       log_error_write(srv, __FILE__, __LINE__, "sds", 
40508 -                                       "can't bind to socket:", 
40509 +                       log_error_write(srv, __FILE__, __LINE__, "sds",
40510 +                                       "can't bind to socket:",
40511                                         host, strerror(errno));
40512                         break;
40513                 default:
40514 -                       log_error_write(srv, __FILE__, __LINE__, "ssds", 
40515 -                                       "can't bind to port:", 
40516 +                       log_error_write(srv, __FILE__, __LINE__, "ssds",
40517 +                                       "can't bind to port:",
40518                                         host, port, strerror(errno));
40519                         break;
40520                 }
40521                 return -1;
40522         }
40523 -       
40524 +
40525         if (-1 == listen(srv_socket->fd, 128 * 8)) {
40526                 log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno));
40527                 return -1;
40528         }
40529 -       
40530 +
40531         if (s->is_ssl) {
40532  #ifdef USE_OPENSSL
40533                 if (srv->ssl_is_init == 0) {
40534                         SSL_load_error_strings();
40535                         SSL_library_init();
40536                         srv->ssl_is_init = 1;
40537 -                       
40538 +
40539                         if (0 == RAND_status()) {
40540 -                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", 
40541 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40542                                                 "not enough entropy in the pool");
40543                                 return -1;
40544                         }
40545                 }
40546 -               
40547 +
40548                 if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
40549 -                       log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", 
40550 +                       log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40551                                         ERR_error_string(ERR_get_error(), NULL));
40552                         return -1;
40553                 }
40554 -               
40555 +
40556                 if (buffer_is_empty(s->ssl_pemfile)) {
40557                         log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set");
40558                         return -1;
40559                 }
40560 -               
40561 +
40562                 if (!buffer_is_empty(s->ssl_ca_file)) {
40563                         if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) {
40564 -                               log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", 
40565 +                               log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40566                                                 ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
40567                                 return -1;
40568                         }
40569                 }
40570 -               
40571 +
40572                 if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
40573 -                       log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", 
40574 +                       log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40575                                         ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
40576                         return -1;
40577                 }
40578 -               
40579 +
40580                 if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
40581 -                       log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", 
40582 +                       log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40583                                         ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
40584                         return -1;
40585                 }
40586 -               
40587 +
40588                 if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
40589 -                       log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:", 
40590 +                       log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
40591                                         "Private key does not match the certificate public key, reason:",
40592                                         ERR_error_string(ERR_get_error(), NULL),
40593                                         s->ssl_pemfile);
40594 @@ -364,15 +367,15 @@
40595                 }
40596                 srv_socket->ssl_ctx = s->ssl_ctx;
40597  #else
40598 -               
40599 +
40600                 buffer_free(srv_socket->srv_token);
40601                 free(srv_socket);
40602 -               
40603 +
40604                 buffer_free(b);
40605 -               
40606 -               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", 
40607 +
40608 +               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40609                                 "ssl requested but openssl support is not compiled in");
40610 -               
40611 +
40612                 return -1;
40613  #endif
40614         } else {
40615 @@ -390,10 +393,10 @@
40616                 }
40617  #endif
40618         }
40619 -       
40620 +
40621         srv_socket->is_ssl = s->is_ssl;
40622         srv_socket->fde_ndx = -1;
40623 -       
40624 +
40625         if (srv->srv_sockets.size == 0) {
40626                 srv->srv_sockets.size = 4;
40627                 srv->srv_sockets.used = 0;
40628 @@ -402,11 +405,10 @@
40629                 srv->srv_sockets.size += 4;
40630                 srv->srv_sockets.ptr = realloc(srv->srv_sockets.ptr, srv->srv_sockets.size * sizeof(server_socket));
40631         }
40632 -       
40633 +
40634         srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket;
40635 -       
40636         buffer_free(b);
40637 -       
40638 +
40639         return 0;
40640  }
40641  
40642 @@ -414,45 +416,58 @@
40643         size_t i;
40644         for (i = 0; i < srv->srv_sockets.used; i++) {
40645                 server_socket *srv_socket = srv->srv_sockets.ptr[i];
40646 -               
40647 +
40648                 if (srv_socket->fd != -1) {
40649                         /* check if server fd are already registered */
40650                         if (srv_socket->fde_ndx != -1) {
40651                                 fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
40652                                 fdevent_unregister(srv->ev, srv_socket->fd);
40653                         }
40654 -               
40655 +
40656                         close(srv_socket->fd);
40657                 }
40658 -               
40659 +
40660 +               if (srv_socket->is_ssl) {
40661 +#ifdef USE_OPENSSL
40662 +                       SSL_CTX_free(srv_socket->ssl_ctx);
40663 +#endif
40664 +               }
40665 +
40666                 buffer_free(srv_socket->srv_token);
40667 -               
40668 +
40669                 free(srv_socket);
40670         }
40671 -       
40672 +
40673 +#ifdef USE_OPENSSL
40674 +       ERR_free_strings();
40675 +#endif
40676         free(srv->srv_sockets.ptr);
40677 -       
40678 +
40679         return 0;
40680  }
40681  
40682  typedef enum {
40683         NETWORK_BACKEND_UNSET,
40684 +
40685         NETWORK_BACKEND_WRITE,
40686         NETWORK_BACKEND_WRITEV,
40687         NETWORK_BACKEND_LINUX_SENDFILE,
40688         NETWORK_BACKEND_FREEBSD_SENDFILE,
40689 -       NETWORK_BACKEND_SOLARIS_SENDFILEV
40690 +       NETWORK_BACKEND_SOLARIS_SENDFILEV,
40691 +
40692 +    NETWORK_BACKEND_WIN32_SEND,
40693 +    NETWORK_BACKEND_WIN32_TRANSMITFILE,
40694  } network_backend_t;
40695  
40696  int network_init(server *srv) {
40697         buffer *b;
40698         size_t i;
40699         network_backend_t backend;
40700 -       
40701 -       struct nb_map { 
40702 -               network_backend_t nb; 
40703 -               const char *name; 
40704 -       } network_backends[] = { 
40705 +
40706 +       struct nb_map {
40707 +               network_backend_t nb;
40708 +               const char *name;
40709 +       } network_backends[] = {
40710                 /* lowest id wins */
40711  #if defined USE_LINUX_SENDFILE
40712                 { NETWORK_BACKEND_LINUX_SENDFILE,       "linux-sendfile" },
40713 @@ -466,21 +481,30 @@
40714  #if defined USE_WRITEV
40715                 { NETWORK_BACKEND_WRITEV,               "writev" },
40716  #endif
40717 +#if defined USE_WRITE
40718                 { NETWORK_BACKEND_WRITE,                "write" },
40719 +#endif
40720 +#if defined USE_WIN32_TRANSMITFILE
40721 +               { NETWORK_BACKEND_WIN32_TRANSMITFILE,   "win32-transmitfile" },
40722 +#endif
40723 +#if defined USE_WIN32_SEND
40724 +               { NETWORK_BACKEND_WIN32_SEND,           "win32-send" },
40725 +#endif
40726 +
40727                 { NETWORK_BACKEND_UNSET,                NULL }
40728         };
40729 -       
40730 +
40731         b = buffer_init();
40732 -               
40733 +
40734         buffer_copy_string_buffer(b, srv->srvconf.bindhost);
40735         buffer_append_string(b, ":");
40736         buffer_append_long(b, srv->srvconf.port);
40737 -       
40738 +
40739         if (0 != network_server_init(srv, b, srv->config_storage[0])) {
40740                 return -1;
40741         }
40742         buffer_free(b);
40743 -               
40744 +
40745  #ifdef USE_OPENSSL
40746         srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
40747  #endif
40748 @@ -500,54 +524,80 @@
40749                 if (NULL == network_backends[i].name) {
40750                         /* we don't know it */
40751  
40752 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
40753 -                                       "server.network-backend has a unknown value:", 
40754 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
40755 +                                       "server.network-backend has a unknown value:",
40756                                         srv->srvconf.network_backend);
40757  
40758                         return -1;
40759                 }
40760         }
40761  
40762 +#define SET_NETWORK_BACKEND(read, write) \
40763 +    srv->network_backend_write = network_write_chunkqueue_##write;\
40764 +    srv->network_backend_read = network_read_chunkqueue_##read
40765 +
40766 +#define SET_NETWORK_BACKEND_SSL(read, write) \
40767 +    srv->network_ssl_backend_write = network_write_chunkqueue_##write;\
40768 +    srv->network_ssl_backend_read = network_read_chunkqueue_##read
40769 +
40770         switch(backend) {
40771 +
40772 +#ifdef USE_WIN32_SEND
40773 +       case NETWORK_BACKEND_WIN32_SEND:
40774 +        SET_NETWORK_BACKEND(win32recv, win32send);
40775 +               break;
40776 +#ifdef USE_WIN32_TRANSMITFILE
40777 +       case NETWORK_BACKEND_WIN32_TRANSMITFILE:
40778 +        SET_NETWORK_BACKEND(win32recv, win32transmitfile);
40779 +               break;
40780 +#endif
40781 +#endif
40782 +
40783 +#ifdef USE_WRITE
40784         case NETWORK_BACKEND_WRITE:
40785 -               srv->network_backend_write = network_write_chunkqueue_write;
40786 +        SET_NETWORK_BACKEND(read, write);
40787                 break;
40788 +
40789  #ifdef USE_WRITEV
40790         case NETWORK_BACKEND_WRITEV:
40791 -               srv->network_backend_write = network_write_chunkqueue_writev;
40792 +        SET_NETWORK_BACKEND(read, writev);
40793                 break;
40794  #endif
40795  #ifdef USE_LINUX_SENDFILE
40796         case NETWORK_BACKEND_LINUX_SENDFILE:
40797 -               srv->network_backend_write = network_write_chunkqueue_linuxsendfile; 
40798 +        SET_NETWORK_BACKEND(read, linuxsendfile);
40799                 break;
40800  #endif
40801  #ifdef USE_FREEBSD_SENDFILE
40802         case NETWORK_BACKEND_FREEBSD_SENDFILE:
40803 -               srv->network_backend_write = network_write_chunkqueue_freebsdsendfile; 
40804 +        SET_NETWORK_BACKEND(read, freebsdsendfile);
40805                 break;
40806  #endif
40807  #ifdef USE_SOLARIS_SENDFILEV
40808         case NETWORK_BACKEND_SOLARIS_SENDFILEV:
40809 -               srv->network_backend_write = network_write_chunkqueue_solarissendfilev; 
40810 +        SET_NETWORK_BACKEND(read, solarissendfilev);
40811                 break;
40812  #endif
40813 +#endif
40814         default:
40815                 return -1;
40816         }
40817 +#ifdef USE_OPENSSL
40818 +        SET_NETWORK_BACKEND_SSL(openssl, openssl);
40819 +#endif
40820  
40821         /* check for $SERVER["socket"] */
40822         for (i = 1; i < srv->config_context->used; i++) {
40823                 data_config *dc = (data_config *)srv->config_context->data[i];
40824                 specific_config *s = srv->config_storage[i];
40825                 size_t j;
40826 -               
40827 +
40828                 /* not our stage */
40829                 if (COMP_SERVER_SOCKET != dc->comp) continue;
40830 -               
40831 +
40832                 if (dc->cond != CONFIG_COND_EQ) {
40833                         log_error_write(srv, __FILE__, __LINE__, "s", "only == is allowed for $SERVER[\"socket\"].");
40834 -                       
40835 +
40836                         return -1;
40837                 }
40838  
40839 @@ -558,36 +608,47 @@
40840                                 break;
40841                         }
40842                 }
40843 -               
40844 +
40845                 if (j == srv->srv_sockets.used) {
40846                         if (0 != network_server_init(srv, dc->string, s)) return -1;
40847                 }
40848         }
40849 -       
40850 +
40851         return 0;
40852  }
40853  
40854  int network_register_fdevents(server *srv) {
40855         size_t i;
40856 -       
40857         if (-1 == fdevent_reset(srv->ev)) {
40858                 return -1;
40859         }
40860 -       
40861         /* register fdevents after reset */
40862         for (i = 0; i < srv->srv_sockets.used; i++) {
40863                 server_socket *srv_socket = srv->srv_sockets.ptr[i];
40864 -               
40865                 fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket);
40866                 fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
40867         }
40868         return 0;
40869  }
40870  
40871 -int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
40872 -       int ret = -1;
40873 +network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
40874 +    server_socket *srv_socket = con->srv_socket;
40875 +
40876 +       if (srv_socket->is_ssl) {
40877 +#ifdef USE_OPENSSL
40878 +               return srv->network_ssl_backend_read(srv, con, con->ssl, cq);
40879 +#else
40880 +               return NETWORK_STATUS_FATAL_ERROR;
40881 +#endif
40882 +       } else {
40883 +               return srv->network_backend_read(srv, con, con->fd, cq);
40884 +       }
40885 +}
40886 +
40887 +network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
40888 +       network_status_t ret = NETWORK_STATUS_UNSET;
40889         off_t written = 0;
40890 -#ifdef TCP_CORK        
40891 +#ifdef TCP_CORK
40892         int corked = 0;
40893  #endif
40894         server_socket *srv_socket = con->srv_socket;
40895 @@ -600,11 +661,11 @@
40896                 joblist_append(srv, con);
40897  
40898                 return 1;
40899 -       }  
40900 +       }
40901  
40902         written = cq->bytes_out;
40903  
40904 -#ifdef TCP_CORK        
40905 +#ifdef TCP_CORK
40906         /* Linux: put a cork into the socket as we want to combine the write() calls
40907          * but only if we really have multiple chunks
40908          */
40909 @@ -613,7 +674,7 @@
40910                 setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
40911         }
40912  #endif
40913 -       
40914 +
40915         if (srv_socket->is_ssl) {
40916  #ifdef USE_OPENSSL
40917                 ret = srv->network_ssl_backend_write(srv, con, con->ssl, cq);
40918 @@ -621,12 +682,17 @@
40919         } else {
40920                 ret = srv->network_backend_write(srv, con, con->fd, cq);
40921         }
40922 -       
40923 -       if (ret >= 0) {
40924 +
40925 +    switch (ret) {
40926 +    case NETWORK_STATUS_WAIT_FOR_EVENT:
40927 +    case NETWORK_STATUS_SUCCESS:
40928                 chunkqueue_remove_finished_chunks(cq);
40929 -               ret = chunkqueue_is_empty(cq) ? 0 : 1;
40930 +
40931 +        break;
40932 +    default:
40933 +        break;
40934         }
40935 -       
40936 +
40937  #ifdef TCP_CORK
40938         if (corked) {
40939                 corked = 0;
40940 @@ -639,13 +705,13 @@
40941         con->bytes_written_cur_second += written;
40942  
40943         *(con->conf.global_bytes_per_second_cnt_ptr) += written;
40944 -       
40945 +
40946         if (con->conf.kbytes_per_second &&
40947             (con->bytes_written_cur_second > con->conf.kbytes_per_second * 1024)) {
40948                 /* we reached the traffic limit */
40949  
40950                 con->traffic_limit_reached = 1;
40951                 joblist_append(srv, con);
40952 -       }  
40953 +       }
40954         return ret;
40955  }
40956 --- lighttpd-1.4.11/src/network.h       2005-08-11 01:26:42.000000000 +0300
40957 +++ lighttpd-1.4.12/src/network.h       2006-07-11 22:07:51.000000000 +0300
40958 @@ -3,7 +3,8 @@
40959  
40960  #include "server.h"
40961  
40962 -int network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
40963 +network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
40964 +network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *c);
40965  
40966  int network_init(server *srv);
40967  int network_close(server *srv);
40968 --- lighttpd-1.4.11/src/network_backends.h      2005-10-24 15:13:51.000000000 +0300
40969 +++ lighttpd-1.4.12/src/network_backends.h      2006-07-11 22:07:52.000000000 +0300
40970 @@ -43,16 +43,52 @@
40971  # define USE_AIX_SENDFILE
40972  #endif
40973  
40974 +/**
40975 +* unix can use read/write or recv/send on sockets
40976 +* win32 only recv/send
40977 +*/
40978 +#ifdef _WIN32
40979 +# define USE_WIN32_SEND
40980 +/* wait for async-io support
40981 +# define USE_WIN32_TRANSMITFILE
40982 +*/
40983 +#else
40984 +# define USE_WRITE
40985 +#endif
40986 +
40987  #include "base.h"
40988 +#include "network.h"
40989 +
40990 +#define NETWORK_BACKEND_WRITE_CHUNK(x) \
40991 +    network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq, chunk *c)
40992 +
40993 +#define NETWORK_BACKEND_WRITE(x) \
40994 +    network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq)
40995 +#define NETWORK_BACKEND_READ(x) \
40996 +    network_status_t network_read_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq)
40997  
40998 +NETWORK_BACKEND_WRITE_CHUNK(writev_mem);
40999 +
41000 +NETWORK_BACKEND_WRITE(write);
41001 +NETWORK_BACKEND_WRITE(writev);
41002 +NETWORK_BACKEND_WRITE(linuxsendfile);
41003 +NETWORK_BACKEND_WRITE(freebsdsendfile);
41004 +NETWORK_BACKEND_WRITE(solarissendfilev);
41005 +
41006 +NETWORK_BACKEND_WRITE(win32transmitfile);
41007 +NETWORK_BACKEND_WRITE(win32send);
41008 +
41009 +NETWORK_BACKEND_READ(read);
41010 +NETWORK_BACKEND_READ(win32recv);
41011  
41012 -int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq);
41013 -int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq);
41014 -int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
41015 -int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
41016 -int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq);
41017  #ifdef USE_OPENSSL
41018 -int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq);
41019 +#define NETWORK_BACKEND_WRITE_SSL(x) \
41020 +    network_status_t network_write_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq)
41021 +#define NETWORK_BACKEND_READ_SSL(x) \
41022 +    network_status_t network_read_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq)
41023 +
41024 +NETWORK_BACKEND_WRITE_SSL(openssl);
41025 +NETWORK_BACKEND_READ_SSL(openssl);
41026  #endif
41027  
41028  #endif
41029 --- lighttpd-1.4.11/src/network_freebsd_sendfile.c      2005-10-22 12:28:18.000000000 +0300
41030 +++ lighttpd-1.4.12/src/network_freebsd_sendfile.c      2006-07-11 22:07:52.000000000 +0300
41031 @@ -26,142 +26,61 @@
41032  
41033  #ifndef UIO_MAXIOV
41034  # ifdef __FreeBSD__
41035 -/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */ 
41036 +/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */
41037  #  define UIO_MAXIOV 1024
41038  # endif
41039  #endif
41040  
41041 -int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
41042 +NETWORK_BACKEND_WRITE(freebsdsendfile) {
41043         chunk *c;
41044         size_t chunks_written = 0;
41045 -       
41046 +
41047         for(c = cq->first; c; c = c->next, chunks_written++) {
41048                 int chunk_finished = 0;
41049 -               
41050 +               network_status_t ret;
41051 +
41052                 switch(c->type) {
41053 -               case MEM_CHUNK: {
41054 -                       char * offset;
41055 -                       size_t toSend;
41056 -                       ssize_t r;
41057 -                       
41058 -                       size_t num_chunks, i;
41059 -                       struct iovec chunks[UIO_MAXIOV];
41060 -                       chunk *tc;
41061 -                       size_t num_bytes = 0;
41062 -                       
41063 -                       /* we can't send more then SSIZE_MAX bytes in one chunk */
41064 -                       
41065 -                       /* build writev list 
41066 -                        * 
41067 -                        * 1. limit: num_chunks < UIO_MAXIOV
41068 -                        * 2. limit: num_bytes < SSIZE_MAX
41069 -                        */
41070 -                       for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
41071 -                       
41072 -                       for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
41073 -                               if (tc->mem->used == 0) {
41074 -                                       chunks[i].iov_base = tc->mem->ptr;
41075 -                                       chunks[i].iov_len  = 0;
41076 -                               } else {
41077 -                                       offset = tc->mem->ptr + tc->offset;
41078 -                                       toSend = tc->mem->used - 1 - tc->offset;
41079 -                                       
41080 -                                       chunks[i].iov_base = offset;
41081 -                                       
41082 -                                       /* protect the return value of writev() */
41083 -                                       if (toSend > SSIZE_MAX ||
41084 -                                           num_bytes + toSend > SSIZE_MAX) {
41085 -                                               chunks[i].iov_len = SSIZE_MAX - num_bytes;
41086 -                                               
41087 -                                               num_chunks = i + 1;
41088 -                                               break;
41089 -                                       } else {
41090 -                                               chunks[i].iov_len = toSend;
41091 -                                       }
41092 -                                
41093 -                                       num_bytes += toSend;
41094 -                               }
41095 -                       }
41096 -                       
41097 -                       if ((r = writev(fd, chunks, num_chunks)) < 0) {
41098 -                               switch (errno) {
41099 -                               case EAGAIN:
41100 -                               case EINTR:
41101 -                                       r = 0;
41102 -                                       break;
41103 -                               case EPIPE:
41104 -                               case ECONNRESET:
41105 -                                       return -2;
41106 -                               default:
41107 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
41108 -                                                       "writev failed:", strerror(errno), fd);
41109 -                                       
41110 -                                       return -1;
41111 -                               }
41112 +               case MEM_CHUNK:
41113 +                       ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
41114  
41115 -                               r = 0;
41116 -                       }
41117 -                       
41118 -                       /* check which chunks have been written */
41119 -                       cq->bytes_out += r;
41120 -                       
41121 -                       for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41122 -                               if (r >= (ssize_t)chunks[i].iov_len) {
41123 -                                       /* written */
41124 -                                       r -= chunks[i].iov_len;
41125 -                                       tc->offset += chunks[i].iov_len;
41126 -                                       
41127 -                                       if (chunk_finished) {
41128 -                                               /* skip the chunks from further touches */
41129 -                                               chunks_written++;
41130 -                                               c = c->next;
41131 -                                       } else {
41132 -                                               /* chunks_written + c = c->next is done in the for()*/
41133 -                                               chunk_finished++;
41134 -                                       }
41135 -                               } else {
41136 -                                       /* partially written */
41137 -                                       
41138 -                                       tc->offset += r;
41139 -                                       chunk_finished = 0;
41140 -                                       
41141 -                                       break;
41142 -                               }
41143 +                       if (ret != NETWORK_STATUS_SUCCESS) {
41144 +                               return ret;
41145                         }
41146 -                       
41147 +
41148 +                       chunk_finished = 1;
41149 +
41150                         break;
41151 -               }
41152                 case FILE_CHUNK: {
41153                         off_t offset, r;
41154                         size_t toSend;
41155                         stat_cache_entry *sce = NULL;
41156                         int ifd;
41157 -                       
41158 +
41159                         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41160                                 log_error_write(srv, __FILE__, __LINE__, "sb",
41161                                                 strerror(errno), c->file.name);
41162 -                               return -1;
41163 +                               return NETWORK_STATUS_FATAL_ERROR;
41164                         }
41165 -                       
41166 +
41167                         offset = c->file.start + c->offset;
41168                         /* limit the toSend to 2^31-1 bytes in a chunk */
41169 -                       toSend = c->file.length - c->offset > ((1 << 30) - 1) ? 
41170 +                       toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
41171                                 ((1 << 30) - 1) : c->file.length - c->offset;
41172 -                               
41173 +
41174                         if (offset > sce->st.st_size) {
41175                                 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
41176 -                               
41177 -                               return -1;
41178 +
41179 +                               return NETWORK_STATUS_FATAL_ERROR;
41180                         }
41181 -                       
41182 +
41183                         if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
41184                                 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
41185 -                               
41186 -                               return -1;
41187 +
41188 +                               return NETWORK_STATUS_FATAL_ERROR;
41189                         }
41190 -                       
41191 +
41192                         r = 0;
41193 -                       
41194 +
41195                         /* FreeBSD sendfile() */
41196                         if (-1 == sendfile(ifd, fd, offset, toSend, NULL, &r, 0)) {
41197                                 switch(errno) {
41198 @@ -169,39 +88,39 @@
41199                                         break;
41200                                 case ENOTCONN:
41201                                         close(ifd);
41202 -                                       return -2;
41203 +                                       return NETWORK_STATUS_CONNECTION_CLOSE;
41204                                 default:
41205                                         log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
41206                                         close(ifd);
41207 -                                       return -1;
41208 +                                       return NETWORK_STATUS_FATAL_ERROR;
41209                                 }
41210                         }
41211                         close(ifd);
41212 -                       
41213 +
41214                         c->offset += r;
41215                         cq->bytes_out += r;
41216 -                       
41217 +
41218                         if (c->offset == c->file.length) {
41219                                 chunk_finished = 1;
41220                         }
41221 -                       
41222 +
41223                         break;
41224                 }
41225                 default:
41226 -                       
41227 +
41228                         log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
41229 -                       
41230 +
41231                         return -1;
41232                 }
41233 -               
41234 +
41235                 if (!chunk_finished) {
41236                         /* not finished yet */
41237 -                       
41238 +
41239                         break;
41240                 }
41241         }
41242  
41243 -       return chunks_written;
41244 +       return NETWORK_STATUS_SUCCESS;
41245  }
41246  
41247  #endif
41248 --- lighttpd-1.4.11/src/network_linux_sendfile.c        2006-02-15 20:02:36.000000000 +0200
41249 +++ lighttpd-1.4.12/src/network_linux_sendfile.c        2006-07-11 22:07:53.000000000 +0300
41250 @@ -26,122 +26,54 @@
41251  /* on linux 2.4.29 + debian/ubuntu we have crashes if this is enabled */
41252  #undef HAVE_POSIX_FADVISE
41253  
41254 -int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
41255 -       chunk *c;
41256 +NETWORK_BACKEND_WRITE(linuxsendfile) {
41257 +       chunk *c, *tc;
41258         size_t chunks_written = 0;
41259 -       
41260 +
41261         for(c = cq->first; c; c = c->next, chunks_written++) {
41262                 int chunk_finished = 0;
41263 -               
41264 +               network_status_t ret;
41265 +
41266                 switch(c->type) {
41267 -               case MEM_CHUNK: {
41268 -                       char * offset;
41269 -                       size_t toSend;
41270 -                       ssize_t r;
41271 -                       
41272 -                       size_t num_chunks, i;
41273 -                       struct iovec chunks[UIO_MAXIOV];
41274 -                       chunk *tc;
41275 -                       size_t num_bytes = 0;
41276 -                       
41277 -                       /* we can't send more then SSIZE_MAX bytes in one chunk */
41278 -                       
41279 -                       /* build writev list 
41280 -                        * 
41281 -                        * 1. limit: num_chunks < UIO_MAXIOV
41282 -                        * 2. limit: num_bytes < SSIZE_MAX
41283 -                        */
41284 -                       for (num_chunks = 0, tc = c; 
41285 -                            tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; 
41286 -                            tc = tc->next, num_chunks++);
41287 -                       
41288 -                       for (tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
41289 -                               if (tc->mem->used == 0) {
41290 -                                       chunks[i].iov_base = tc->mem->ptr;
41291 -                                       chunks[i].iov_len  = 0;
41292 -                               } else {
41293 -                                       offset = tc->mem->ptr + tc->offset;
41294 -                                       toSend = tc->mem->used - 1 - tc->offset;
41295 -                               
41296 -                                       chunks[i].iov_base = offset;
41297 -                                       
41298 -                                       /* protect the return value of writev() */
41299 -                                       if (toSend > SSIZE_MAX ||
41300 -                                           num_bytes + toSend > SSIZE_MAX) {
41301 -                                               chunks[i].iov_len = SSIZE_MAX - num_bytes;
41302 -                                               
41303 -                                               num_chunks = i + 1;
41304 -                                               break;
41305 -                                       } else {
41306 -                                               chunks[i].iov_len = toSend;
41307 -                                       }
41308 -                                
41309 -                                       num_bytes += toSend;
41310 -                               }
41311 -                       }
41312 -                       
41313 -                       if ((r = writev(fd, chunks, num_chunks)) < 0) {
41314 -                               switch (errno) {
41315 -                               case EAGAIN:
41316 -                               case EINTR:
41317 -                                       r = 0;
41318 -                                       break;
41319 -                               case EPIPE:
41320 -                               case ECONNRESET:
41321 -                                       return -2;
41322 -                               default:
41323 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
41324 -                                                       "writev failed:", strerror(errno), fd);
41325 -                               
41326 -                                       return -1;
41327 -                               }
41328 -                       }
41329 -                       
41330 -                       /* check which chunks have been written */
41331 -                       cq->bytes_out += r;
41332 +               case MEM_CHUNK:
41333 +                       ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
41334  
41335 -                       for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41336 -                               if (r >= (ssize_t)chunks[i].iov_len) {
41337 -                                       /* written */
41338 -                                       r -= chunks[i].iov_len;
41339 -                                       tc->offset += chunks[i].iov_len;
41340 -                                       
41341 +                       /* check which chunks are finished now */
41342 +                       for (tc = c; tc; tc = tc->next) {
41343 +                               /* finished the chunk */
41344 +                               if (tc->offset == tc->mem->used - 1) {
41345 +                                       /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
41346                                         if (chunk_finished) {
41347 -                                               /* skip the chunks from further touches */
41348 -                                               chunks_written++;
41349                                                 c = c->next;
41350                                         } else {
41351 -                                               /* chunks_written + c = c->next is done in the for()*/
41352 -                                               chunk_finished++;
41353 +                                               chunk_finished = 1;
41354                                         }
41355                                 } else {
41356 -                                       /* partially written */
41357 -                                       
41358 -                                       tc->offset += r;
41359 -                                       chunk_finished = 0;
41360 -                                       
41361                                         break;
41362                                 }
41363                         }
41364 -                       
41365 +
41366 +                       if (ret != NETWORK_STATUS_SUCCESS) {
41367 +                               return ret;
41368 +                       }
41369 +
41370                         break;
41371 -               }
41372                 case FILE_CHUNK: {
41373                         ssize_t r;
41374                         off_t offset;
41375                         size_t toSend;
41376                         stat_cache_entry *sce = NULL;
41377 -                       
41378 +
41379                         offset = c->file.start + c->offset;
41380                         /* limit the toSend to 2^31-1 bytes in a chunk */
41381 -                       toSend = c->file.length - c->offset > ((1 << 30) - 1) ? 
41382 +                       toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
41383                                 ((1 << 30) - 1) : c->file.length - c->offset;
41384 -                               
41385 -                       /* open file if not already opened */   
41386 +
41387 +                       /* open file if not already opened */
41388                         if (-1 == c->file.fd) {
41389                                 if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
41390                                         log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
41391 -                               
41392 +
41393                                         return -1;
41394                                 }
41395  #ifdef FD_CLOEXEC
41396 @@ -151,7 +83,7 @@
41397                                 /* tell the kernel that we want to stream the file */
41398                                 if (-1 == posix_fadvise(c->file.fd, 0, 0, POSIX_FADV_SEQUENTIAL)) {
41399                                         if (ENOSYS != errno) {
41400 -                                               log_error_write(srv, __FILE__, __LINE__, "ssd", 
41401 +                                               log_error_write(srv, __FILE__, __LINE__, "ssd",
41402                                                         "posix_fadvise failed:", strerror(errno), c->file.fd);
41403                                         }
41404                                 }
41405 @@ -168,7 +100,7 @@
41406                                 case ECONNRESET:
41407                                         return -2;
41408                                 default:
41409 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
41410 +                                       log_error_write(srv, __FILE__, __LINE__, "ssd",
41411                                                         "sendfile failed:", strerror(errno), fd);
41412                                         return -1;
41413                                 }
41414 @@ -179,7 +111,7 @@
41415                                  *
41416                                  * - the file shrinked -> error
41417                                  * - the remote side closed inbetween -> remote-close */
41418 -       
41419 +
41420                                 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41421                                         /* file is gone ? */
41422                                         return -1;
41423 @@ -196,22 +128,22 @@
41424  #ifdef HAVE_POSIX_FADVISE
41425  #if 0
41426  #define K * 1024
41427 -#define M * 1024 K     
41428 +#define M * 1024 K
41429  #define READ_AHEAD 4 M
41430                         /* check if we need a new chunk */
41431                         if ((c->offset & ~(READ_AHEAD - 1)) != ((c->offset + r) & ~(READ_AHEAD - 1))) {
41432                                 /* tell the kernel that we want to stream the file */
41433                                 if (-1 == posix_fadvise(c->file.fd, (c->offset + r) & ~(READ_AHEAD - 1), READ_AHEAD, POSIX_FADV_NOREUSE)) {
41434 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
41435 +                                       log_error_write(srv, __FILE__, __LINE__, "ssd",
41436                                                 "posix_fadvise failed:", strerror(errno), c->file.fd);
41437                                 }
41438                         }
41439  #endif
41440  #endif
41441 -                       
41442 +
41443                         c->offset += r;
41444                         cq->bytes_out += r;
41445 -                       
41446 +
41447                         if (c->offset == c->file.length) {
41448                                 chunk_finished = 1;
41449  
41450 @@ -222,19 +154,19 @@
41451                                         c->file.fd = -1;
41452                                 }
41453                         }
41454 -                       
41455 +
41456                         break;
41457                 }
41458                 default:
41459 -                       
41460 +
41461                         log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
41462 -                       
41463 +
41464                         return -1;
41465                 }
41466 -               
41467 +
41468                 if (!chunk_finished) {
41469                         /* not finished yet */
41470 -                       
41471 +
41472                         break;
41473                 }
41474         }
41475 --- lighttpd-1.4.11/src/network_openssl.c       2005-11-17 14:53:29.000000000 +0200
41476 +++ lighttpd-1.4.12/src/network_openssl.c       2006-07-11 22:07:52.000000000 +0300
41477 @@ -23,17 +23,87 @@
41478  #include "log.h"
41479  #include "stat_cache.h"
41480  
41481 -# include <openssl/ssl.h> 
41482 -# include <openssl/err.h> 
41483 +# include <openssl/ssl.h>
41484 +# include <openssl/err.h>
41485  
41486 -int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq) {
41487 +NETWORK_BACKEND_READ_SSL(openssl) {
41488 +       buffer *b;
41489 +       off_t len;
41490 +
41491 +       b = chunkqueue_get_append_buffer(cq);
41492 +       buffer_prepare_copy(b, 8192);
41493 +       len = SSL_read(ssl, b->ptr, b->size - 1);
41494 +
41495 +       log_error_write(srv, __FILE__, __LINE__, "so", "SSL:", len);
41496 +
41497 +       if (len < 0) {
41498 +               int r, ssl_err;
41499 +
41500 +               switch ((r = SSL_get_error(con->ssl, len))) {
41501 +               case SSL_ERROR_WANT_READ:
41502 +                       return NETWORK_STATUS_WAIT_FOR_EVENT;
41503 +               case SSL_ERROR_SYSCALL:
41504 +                       /**
41505 +                        * man SSL_get_error()
41506 +                        *
41507 +                        * SSL_ERROR_SYSCALL
41508 +                        *   Some I/O error occurred.  The OpenSSL error queue may contain more
41509 +                        *   information on the error.  If the error queue is empty (i.e.
41510 +                        *   ERR_get_error() returns 0), ret can be used to find out more about
41511 +                        *   the error: If ret == 0, an EOF was observed that violates the
41512 +                        *   protocol.  If ret == -1, the underlying BIO reported an I/O error
41513 +                        *   (for socket I/O on Unix systems, consult errno for details).
41514 +                        *
41515 +                        */
41516 +                       while((ssl_err = ERR_get_error())) {
41517 +                               /* get all errors from the error-queue */
41518 +                               log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
41519 +                                               r, ERR_error_string(ssl_err, NULL));
41520 +                       }
41521 +
41522 +                       switch(errno) {
41523 +                       default:
41524 +                               log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41525 +                                               len, r, errno,
41526 +                                               strerror(errno));
41527 +                               break;
41528 +                       }
41529 +
41530 +                       break;
41531 +               case SSL_ERROR_ZERO_RETURN:
41532 +                       /* clean shutdown on the remote side */
41533 +
41534 +                       if (r == 0) {
41535 +                               /* FIXME: later */
41536 +                       }
41537 +
41538 +                       /* fall thourgh */
41539 +               default:
41540 +                       while((ssl_err = ERR_get_error())) {
41541 +                               /* get all errors from the error-queue */
41542 +                               log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
41543 +                                               r, ERR_error_string(ssl_err, NULL));
41544 +                       }
41545 +                       break;
41546 +               }
41547 +       }
41548 +
41549 +       assert(len > 0);
41550 +       b->used += len;
41551 +       b->ptr[b->used - 1] = '\0';
41552 +
41553 +       return NETWORK_STATUS_SUCCESS;
41554 +}
41555 +
41556 +
41557 +NETWORK_BACKEND_WRITE_SSL(openssl) {
41558         int ssl_r;
41559         chunk *c;
41560         size_t chunks_written = 0;
41561  
41562         /* this is a 64k sendbuffer
41563          *
41564 -        * it has to stay at the same location all the time to satisfy the needs 
41565 +        * it has to stay at the same location all the time to satisfy the needs
41566          * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE
41567          *
41568          * the buffer is allocated once, is NOT realloced and is NOT freed at shutdown
41569 @@ -43,14 +113,14 @@
41570          * In reality we would like to use mmap() but we don't have a guarantee that
41571          * we get the same mmap() address for each call. On openbsd the mmap() address
41572          * even randomized.
41573 -        *   That means either we keep the mmap() open or we do a read() into a 
41574 -        * constant buffer 
41575 +        *   That means either we keep the mmap() open or we do a read() into a
41576 +        * constant buffer
41577          * */
41578  #define LOCAL_SEND_BUFSIZE (64 * 1024)
41579         static char *local_send_buffer = NULL;
41580  
41581         /* the remote side closed the connection before without shutdown request
41582 -        * - IE 
41583 +        * - IE
41584          * - wget
41585          * if keep-alive is disabled */
41586  
41587 @@ -60,32 +130,34 @@
41588  
41589         for(c = cq->first; c; c = c->next) {
41590                 int chunk_finished = 0;
41591 -               
41592 +
41593                 switch(c->type) {
41594                 case MEM_CHUNK: {
41595                         char * offset;
41596                         size_t toSend;
41597 -                       ssize_t r;
41598 -                       
41599 +                       ssize_t r = 0;
41600 +
41601                         if (c->mem->used == 0) {
41602                                 chunk_finished = 1;
41603                                 break;
41604                         }
41605 -                       
41606 +
41607                         offset = c->mem->ptr + c->offset;
41608                         toSend = c->mem->used - 1 - c->offset;
41609 -                       
41610 +
41611                         /**
41612                          * SSL_write man-page
41613 -                        * 
41614 +                        *
41615                          * WARNING
41616                          *        When an SSL_write() operation has to be repeated because of
41617                          *        SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be
41618                          *        repeated with the same arguments.
41619 -                        * 
41620 +                        *
41621 +                        * SSL_write(..., 0) return 0 which is handle as an error (Success)
41622 +                        * checking toSend and not calling SSL_write() is simpler
41623                          */
41624 -                       
41625 -                       if ((r = SSL_write(ssl, offset, toSend)) <= 0) {
41626 +
41627 +                       if (toSend != 0 && (r = SSL_write(ssl, offset, toSend)) <= 0) {
41628                                 unsigned long err;
41629  
41630                                 switch ((ssl_r = SSL_get_error(ssl, r))) {
41631 @@ -95,7 +167,7 @@
41632                                         /* perhaps we have error waiting in our error-queue */
41633                                         if (0 != (err = ERR_get_error())) {
41634                                                 do {
41635 -                                                       log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", 
41636 +                                                       log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41637                                                                         ssl_r, r,
41638                                                                         ERR_error_string(err, NULL));
41639                                                 } while((err = ERR_get_error()));
41640 @@ -105,43 +177,43 @@
41641                                                 case EPIPE:
41642                                                         return -2;
41643                                                 default:
41644 -                                                       log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:", 
41645 +                                                       log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41646                                                                         ssl_r, r, errno,
41647                                                                         strerror(errno));
41648                                                         break;
41649                                                 }
41650                                         } else {
41651                                                 /* neither error-queue nor errno ? */
41652 -                                               log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):", 
41653 +                                               log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
41654                                                                 ssl_r, r, errno,
41655                                                                 strerror(errno));
41656                                         }
41657 -                                       
41658 +
41659                                         return  -1;
41660                                 case SSL_ERROR_ZERO_RETURN:
41661                                         /* clean shutdown on the remote side */
41662 -                                       
41663 +
41664                                         if (r == 0) return -2;
41665 -                                       
41666 +
41667                                         /* fall through */
41668                                 default:
41669                                         while((err = ERR_get_error())) {
41670 -                                               log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", 
41671 +                                               log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41672                                                                 ssl_r, r,
41673                                                                 ERR_error_string(err, NULL));
41674                                         }
41675 -                                       
41676 +
41677                                         return  -1;
41678                                 }
41679                         } else {
41680                                 c->offset += r;
41681                                 cq->bytes_out += r;
41682                         }
41683 -                       
41684 +
41685                         if (c->offset == (off_t)c->mem->used - 1) {
41686                                 chunk_finished = 1;
41687                         }
41688 -                       
41689 +
41690                         break;
41691                 }
41692                 case FILE_CHUNK: {
41693 @@ -150,7 +222,7 @@
41694                         stat_cache_entry *sce = NULL;
41695                         int ifd;
41696                         int write_wait = 0;
41697 -                       
41698 +
41699                         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41700                                 log_error_write(srv, __FILE__, __LINE__, "sb",
41701                                                 strerror(errno), c->file.name);
41702 @@ -164,13 +236,13 @@
41703  
41704                         do {
41705                                 off_t offset = c->file.start + c->offset;
41706 -                               off_t toSend = c->file.length - c->offset; 
41707 +                               off_t toSend = c->file.length - c->offset;
41708  
41709                                 if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE;
41710 -                       
41711 +
41712                                 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
41713                                         log_error_write(srv, __FILE__, __LINE__, "ss", "open failed:", strerror(errno));
41714 -                               
41715 +
41716                                         return -1;
41717                                 }
41718  
41719 @@ -183,9 +255,9 @@
41720                                 }
41721  
41722                                 s = local_send_buffer;
41723 -                       
41724 +
41725                                 close(ifd);
41726 -                       
41727 +
41728                                 if ((r = SSL_write(ssl, s, toSend)) <= 0) {
41729                                         unsigned long err;
41730  
41731 @@ -197,7 +269,7 @@
41732                                                 /* perhaps we have error waiting in our error-queue */
41733                                                 if (0 != (err = ERR_get_error())) {
41734                                                         do {
41735 -                                                               log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", 
41736 +                                                               log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41737                                                                                 ssl_r, r,
41738                                                                                 ERR_error_string(err, NULL));
41739                                                         } while((err = ERR_get_error()));
41740 @@ -207,58 +279,58 @@
41741                                                         case EPIPE:
41742                                                                 return -2;
41743                                                         default:
41744 -                                                               log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:", 
41745 +                                                               log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41746                                                                                 ssl_r, r, errno,
41747                                                                                 strerror(errno));
41748                                                                 break;
41749                                                         }
41750                                                 } else {
41751                                                         /* neither error-queue nor errno ? */
41752 -                                                       log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):", 
41753 +                                                       log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
41754                                                                         ssl_r, r, errno,
41755                                                                         strerror(errno));
41756                                                 }
41757 -                                       
41758 +
41759                                                 return  -1;
41760                                         case SSL_ERROR_ZERO_RETURN:
41761                                                 /* clean shutdown on the remote side */
41762 -                                       
41763 +
41764                                                 if (r == 0)  return -2;
41765 -                                       
41766 +
41767                                                 /* fall thourgh */
41768                                         default:
41769                                                 while((err = ERR_get_error())) {
41770 -                                                       log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", 
41771 +                                                       log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41772                                                                         ssl_r, r,
41773                                                                         ERR_error_string(err, NULL));
41774                                                 }
41775 -                                       
41776 +
41777                                                 return -1;
41778                                         }
41779                                 } else {
41780                                         c->offset += r;
41781                                         cq->bytes_out += r;
41782                                 }
41783 -                       
41784 +
41785                                 if (c->offset == c->file.length) {
41786                                         chunk_finished = 1;
41787                                 }
41788                         } while(!chunk_finished && !write_wait);
41789 -                       
41790 +
41791                         break;
41792                 }
41793                 default:
41794                         log_error_write(srv, __FILE__, __LINE__, "s", "type not known");
41795 -                       
41796 +
41797                         return -1;
41798                 }
41799 -                       
41800 +
41801                 if (!chunk_finished) {
41802                         /* not finished yet */
41803 -                       
41804 +
41805                         break;
41806                 }
41807 -                       
41808 +
41809                 chunks_written++;
41810         }
41811  
41812 --- lighttpd-1.4.11/src/network_solaris_sendfilev.c     2005-10-22 12:28:27.000000000 +0300
41813 +++ lighttpd-1.4.12/src/network_solaris_sendfilev.c     2006-07-11 22:07:53.000000000 +0300
41814 @@ -29,114 +29,34 @@
41815  #endif
41816  
41817  /**
41818 - * a very simple sendfilev() interface for solaris which can be optimised a lot more 
41819 + * a very simple sendfilev() interface for solaris which can be optimised a lot more
41820   * as solaris sendfilev() supports 'sending everythin in one syscall()'
41821 - * 
41822 - * If you want such an interface and need the performance, just give me an account on 
41823 - * a solaris box. 
41824 + *
41825 + * If you want such an interface and need the performance, just give me an account on
41826 + * a solaris box.
41827   *   - jan@kneschke.de
41828   */
41829  
41830  
41831 -int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq) {
41832 +NETWORK_BACKEND_WRITE(solarissendfilev) {
41833         chunk *c;
41834         size_t chunks_written = 0;
41835 -       
41836 +
41837         for(c = cq->first; c; c = c->next, chunks_written++) {
41838                 int chunk_finished = 0;
41839 -               
41840 +               network_status_t ret;
41841 +
41842                 switch(c->type) {
41843 -               case MEM_CHUNK: {
41844 -                       char * offset;
41845 -                       size_t toSend;
41846 -                       ssize_t r;
41847 -                       
41848 -                       size_t num_chunks, i;
41849 -                       struct iovec chunks[UIO_MAXIOV];
41850 -                       chunk *tc;
41851 -                       
41852 -                       size_t num_bytes = 0;
41853 -                       
41854 -                       /* we can't send more then SSIZE_MAX bytes in one chunk */
41855 -                       
41856 -                       /* build writev list 
41857 -                        * 
41858 -                        * 1. limit: num_chunks < UIO_MAXIOV
41859 -                        * 2. limit: num_bytes < SSIZE_MAX
41860 -                        */
41861 -                       for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
41862 -                       
41863 -                       for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
41864 -                               if (tc->mem->used == 0) {
41865 -                                       chunks[i].iov_base = tc->mem->ptr;
41866 -                                       chunks[i].iov_len  = 0;
41867 -                               } else {
41868 -                                       offset = tc->mem->ptr + tc->offset;
41869 -                                       toSend = tc->mem->used - 1 - tc->offset;
41870 -                               
41871 -                                       chunks[i].iov_base = offset;
41872 -                                       
41873 -                                       /* protect the return value of writev() */
41874 -                                       if (toSend > SSIZE_MAX ||
41875 -                                           num_bytes + toSend > SSIZE_MAX) {
41876 -                                               chunks[i].iov_len = SSIZE_MAX - num_bytes;
41877 -                                               
41878 -                                               num_chunks = i + 1;
41879 -                                               break;
41880 -                                       } else {
41881 -                                               chunks[i].iov_len = toSend;
41882 -                                       }
41883 -                                       
41884 -                                       num_bytes += toSend;
41885 -                               }
41886 -                       }
41887 -                       
41888 -                       if ((r = writev(fd, chunks, num_chunks)) < 0) {
41889 -                               switch (errno) {
41890 -                               case EAGAIN:
41891 -                               case EINTR:
41892 -                                       r = 0;
41893 -                                       break;
41894 -                               case EPIPE:
41895 -                               case ECONNRESET:
41896 -                                       return -2;
41897 -                               default:
41898 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
41899 -                                                       "writev failed:", strerror(errno), fd);
41900 -                               
41901 -                                       return -1;
41902 -                               }
41903 -                       }
41904 -                       
41905 -                       /* check which chunks have been written */
41906 -                       cq->bytes_out += r;
41907 -                       
41908 -                       for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41909 -                               if (r >= (ssize_t)chunks[i].iov_len) {
41910 -                                       /* written */
41911 -                                       r -= chunks[i].iov_len;
41912 -                                       tc->offset += chunks[i].iov_len;
41913 -                                       
41914 -                                       if (chunk_finished) {
41915 -                                               /* skip the chunks from further touches */
41916 -                                               chunks_written++;
41917 -                                               c = c->next;
41918 -                                       } else {
41919 -                                               /* chunks_written + c = c->next is done in the for()*/
41920 -                                               chunk_finished++;
41921 -                                       }
41922 -                               } else {
41923 -                                       /* partially written */
41924 -                                       
41925 -                                       tc->offset += r;
41926 -                                       chunk_finished = 0;
41927 -                                       
41928 -                                       break;
41929 -                               }
41930 +               case MEM_CHUNK:
41931 +                       ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
41932 +
41933 +                       if (ret != NETWORK_STATUS_SUCCESS) {
41934 +                               return ret;
41935                         }
41936 -                       
41937 +
41938 +                       chunk_finished = 1;
41939 +
41940                         break;
41941 -               }
41942                 case FILE_CHUNK: {
41943                         ssize_t r;
41944                         off_t offset;
41945 @@ -144,25 +64,25 @@
41946                         sendfilevec_t fvec;
41947                         stat_cache_entry *sce = NULL;
41948                         int ifd;
41949 -                       
41950 +
41951                         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41952                                 log_error_write(srv, __FILE__, __LINE__, "sb",
41953                                                 strerror(errno), c->file.name);
41954                                 return -1;
41955                         }
41956 -                                       
41957 +
41958                         offset = c->file.start + c->offset;
41959                         toSend = c->file.length - c->offset;
41960 -                       
41961 +
41962                         if (offset > sce->st.st_size) {
41963                                 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
41964 -                               
41965 +
41966                                 return -1;
41967                         }
41968  
41969                         if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
41970                                 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
41971 -                               
41972 +
41973                                 return -1;
41974                         }
41975  
41976 @@ -170,44 +90,43 @@
41977                         fvec.sfv_flag = 0;
41978                         fvec.sfv_off = offset;
41979                         fvec.sfv_len = toSend;
41980 -                       
41981 +
41982                         /* Solaris sendfilev() */
41983                         if (-1 == (r = sendfilev(fd, &fvec, 1, &written))) {
41984                                 if (errno != EAGAIN) {
41985                                         log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
41986 -                                       
41987 +
41988                                         close(ifd);
41989 -                                       return -1;
41990 +                                       return NETWORK_STATUS_FATAL_ERROR;
41991                                 }
41992 -                               
41993 +
41994                                 r = 0;
41995                         }
41996 -                       
41997 +
41998                         close(ifd);
41999                         c->offset += written;
42000                         cq->bytes_out += written;
42001 -                       
42002 +
42003                         if (c->offset == c->file.length) {
42004                                 chunk_finished = 1;
42005                         }
42006 -                       
42007 +
42008                         break;
42009                 }
42010                 default:
42011 -                       
42012                         log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
42013 -                       
42014 -                       return -1;
42015 +
42016 +                       return NETWORK_STATUS_FATAL_ERROR;
42017                 }
42018 -               
42019 +
42020                 if (!chunk_finished) {
42021                         /* not finished yet */
42022 -                       
42023 +
42024                         break;
42025                 }
42026         }
42027  
42028 -       return chunks_written;
42029 +       return NETWORK_STATUS_SUCCESS;
42030  }
42031  
42032  #endif
42033 --- lighttpd-1.4.11/src/network_write.c 2005-10-22 12:27:56.000000000 +0300
42034 +++ lighttpd-1.4.12/src/network_write.c 2006-07-11 22:07:51.000000000 +0300
42035 @@ -1,11 +1,11 @@
42036  #include <sys/types.h>
42037  #include <sys/stat.h>
42038 -#include <sys/time.h>
42039 +
42040  #include <errno.h>
42041  #include <fcntl.h>
42042 -#include <unistd.h>
42043  #include <string.h>
42044  #include <stdlib.h>
42045 +#include <assert.h>
42046  
42047  #include "network.h"
42048  #include "fdevent.h"
42049 @@ -13,9 +13,12 @@
42050  #include "stat_cache.h"
42051  
42052  #include "sys-socket.h"
42053 +#include "sys-files.h"
42054  
42055  #include "network_backends.h"
42056  
42057 +#ifdef USE_WRITE
42058 +
42059  #ifdef HAVE_SYS_FILIO_H
42060  # include <sys/filio.h>
42061  #endif
42062 @@ -24,47 +27,86 @@
42063  #include <sys/resource.h>
42064  #endif
42065  
42066 -int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq) {
42067 +/**
42068 +* fill the chunkqueue will all the data that we can get
42069 +*
42070 +* this might be optimized into a readv() which uses the chunks
42071 +* as vectors
42072 +*/
42073 +NETWORK_BACKEND_READ(read) {
42074 +    int toread;
42075 +    buffer *b;
42076 +    off_t r;
42077 +
42078 +       /* check how much we have to read */
42079 +       if (ioctl(fd, FIONREAD, &toread)) {
42080 +               log_error_write(srv, __FILE__, __LINE__, "sd",
42081 +                               "ioctl failed: ",
42082 +                               fd);
42083 +               return NETWORK_STATUS_FATAL_ERROR;
42084 +       }
42085 +
42086 +       if (toread == 0) return NETWORK_STATUS_WAIT_FOR_EVENT;
42087 +
42088 +    /*
42089 +    * our chunk queue is quiet large already
42090 +    *
42091 +    * let's buffer it to disk
42092 +    */
42093 +
42094 +    b = chunkqueue_get_append_buffer(cq);
42095 +
42096 +    buffer_prepare_copy(b, toread);
42097 +
42098 +    if (-1 == (r = read(fd, b->ptr, toread))) {
42099 +               log_error_write(srv, __FILE__, __LINE__, "sds",
42100 +                               "unexpected end-of-file (perhaps the proxy process died):",
42101 +                               fd, strerror(errno));
42102 +               return NETWORK_STATUS_FATAL_ERROR;
42103 +       }
42104 +
42105 +       /* this should be catched by the b > 0 above */
42106 +       assert(r);
42107 +       b->used += r + 1;
42108 +       b->ptr[b->used - 1] = '\0';
42109 +
42110 +    return NETWORK_STATUS_SUCCESS;
42111 +}
42112 +
42113 +NETWORK_BACKEND_WRITE(write) {
42114         chunk *c;
42115         size_t chunks_written = 0;
42116 -       
42117 +
42118         for(c = cq->first; c; c = c->next) {
42119                 int chunk_finished = 0;
42120 -               
42121 +
42122                 switch(c->type) {
42123                 case MEM_CHUNK: {
42124                         char * offset;
42125                         size_t toSend;
42126                         ssize_t r;
42127 -                       
42128 +
42129                         if (c->mem->used == 0) {
42130                                 chunk_finished = 1;
42131                                 break;
42132                         }
42133 -                       
42134 +
42135                         offset = c->mem->ptr + c->offset;
42136                         toSend = c->mem->used - 1 - c->offset;
42137 -#ifdef __WIN32 
42138 -                       if ((r = send(fd, offset, toSend, 0)) < 0) {
42139 -                               log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
42140 -                               
42141 -                               return -1;
42142 -                       }
42143 -#else
42144 +
42145                         if ((r = write(fd, offset, toSend)) < 0) {
42146                                 log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
42147 -                               
42148 -                               return -1;
42149 +
42150 +                               return NETWORK_STATUS_FATAL_ERROR;
42151                         }
42152 -#endif
42153 -                       
42154 +
42155                         c->offset += r;
42156                         cq->bytes_out += r;
42157 -                       
42158 +
42159                         if (c->offset == (off_t)c->mem->used - 1) {
42160                                 chunk_finished = 1;
42161                         }
42162 -                       
42163 +
42164                         break;
42165                 }
42166                 case FILE_CHUNK: {
42167 @@ -76,93 +118,89 @@
42168                         size_t toSend;
42169                         stat_cache_entry *sce = NULL;
42170                         int ifd;
42171 -                       
42172 +
42173                         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
42174                                 log_error_write(srv, __FILE__, __LINE__, "sb",
42175                                                 strerror(errno), c->file.name);
42176 -                               return -1;
42177 +                               return NETWORK_STATUS_FATAL_ERROR;
42178                         }
42179 -                       
42180 +
42181                         offset = c->file.start + c->offset;
42182                         toSend = c->file.length - c->offset;
42183 -                       
42184 +
42185                         if (offset > sce->st.st_size) {
42186                                 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
42187 -                               
42188 -                               return -1;
42189 +
42190 +                               return NETWORK_STATUS_FATAL_ERROR;
42191                         }
42192  
42193                         if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
42194                                 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
42195 -                               
42196 -                               return -1;
42197 +
42198 +                               return NETWORK_STATUS_FATAL_ERROR;
42199                         }
42200 -                       
42201 +
42202  #if defined USE_MMAP
42203                         if (MAP_FAILED == (p = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
42204                                 log_error_write(srv, __FILE__, __LINE__, "ss", "mmap failed: ", strerror(errno));
42205  
42206                                 close(ifd);
42207 -                               
42208 -                               return -1;
42209 +
42210 +                               return NETWORK_STATUS_FATAL_ERROR;
42211                         }
42212                         close(ifd);
42213  
42214                         if ((r = write(fd, p + offset, toSend)) <= 0) {
42215                                 log_error_write(srv, __FILE__, __LINE__, "ss", "write failed: ", strerror(errno));
42216                                 munmap(p, sce->st.st_size);
42217 -                               return -1;
42218 +                               return NETWORK_STATUS_FATAL_ERROR;
42219                         }
42220 -                       
42221 +
42222                         munmap(p, sce->st.st_size);
42223  #else
42224                         buffer_prepare_copy(srv->tmp_buf, toSend);
42225 -                       
42226 +
42227                         lseek(ifd, offset, SEEK_SET);
42228                         if (-1 == (toSend = read(ifd, srv->tmp_buf->ptr, toSend))) {
42229                                 log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno));
42230                                 close(ifd);
42231 -                               
42232 -                               return -1;
42233 +
42234 +                               return NETWORK_STATUS_FATAL_ERROR;
42235                         }
42236                         close(ifd);
42237  
42238                         if (-1 == (r = send(fd, srv->tmp_buf->ptr, toSend, 0))) {
42239                                 log_error_write(srv, __FILE__, __LINE__, "ss", "write: ", strerror(errno));
42240 -                               
42241 -                               return -1;
42242 +
42243 +                               return NETWORK_STATUS_FATAL_ERROR;
42244                         }
42245  #endif
42246                         c->offset += r;
42247                         cq->bytes_out += r;
42248 -                       
42249 +
42250                         if (c->offset == c->file.length) {
42251                                 chunk_finished = 1;
42252                         }
42253 -                       
42254 +
42255                         break;
42256                 }
42257                 default:
42258 -                       
42259 +
42260                         log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
42261 -                       
42262 -                       return -1;
42263 +
42264 +                       return NETWORK_STATUS_FATAL_ERROR;
42265                 }
42266 -               
42267 +
42268                 if (!chunk_finished) {
42269                         /* not finished yet */
42270 -                       
42271 +
42272                         break;
42273                 }
42274 -               
42275 +
42276                 chunks_written++;
42277         }
42278  
42279 -       return chunks_written;
42280 +       return NETWORK_STATUS_SUCCESS;
42281  }
42282  
42283 -#if 0
42284 -network_write_init(void) {
42285 -       p->write = network_write_write_chunkset;
42286 -}
42287  #endif
42288 --- lighttpd-1.4.11/src/network_writev.c        2006-02-15 01:02:36.000000000 +0200
42289 +++ lighttpd-1.4.12/src/network_writev.c        2006-07-11 22:07:52.000000000 +0300
42290 @@ -28,10 +28,10 @@
42291  
42292  #ifndef UIO_MAXIOV
42293  # if defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__)
42294 -/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */ 
42295 +/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */
42296  #  define UIO_MAXIOV 1024
42297  # elif defined(__sgi)
42298 -/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */ 
42299 +/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */
42300  #  define UIO_MAXIOV 512
42301  # elif defined(__sun)
42302  /* Solaris (and SunOS?) defines IOV_MAX instead */
42303 @@ -51,105 +51,119 @@
42304  #define LOCAL_BUFFERING 1
42305  #endif
42306  
42307 -int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq) {
42308 -       chunk *c;
42309 +NETWORK_BACKEND_WRITE_CHUNK(writev_mem) {
42310 +       char * offset;
42311 +       size_t toSend;
42312 +       ssize_t r;
42313 +
42314 +       size_t num_chunks, i;
42315 +       struct iovec chunks[UIO_MAXIOV];
42316 +       chunk *tc; /* transfer chunks */
42317 +       size_t num_bytes = 0;
42318 +
42319 +       /* we can't send more then SSIZE_MAX bytes in one chunk */
42320 +
42321 +       /* build writev list
42322 +        *
42323 +        * 1. limit: num_chunks < UIO_MAXIOV
42324 +        * 2. limit: num_bytes < SSIZE_MAX
42325 +        */
42326 +       for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
42327 +
42328 +       for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
42329 +               if (tc->mem->used == 0) {
42330 +                       chunks[i].iov_base = tc->mem->ptr;
42331 +                       chunks[i].iov_len  = 0;
42332 +               } else {
42333 +                       offset = tc->mem->ptr + tc->offset;
42334 +                       toSend = tc->mem->used - 1 - tc->offset;
42335 +
42336 +                       chunks[i].iov_base = offset;
42337 +
42338 +                       /* protect the return value of writev() */
42339 +                       if (toSend > SSIZE_MAX ||
42340 +                           num_bytes + toSend > SSIZE_MAX) {
42341 +                               chunks[i].iov_len = SSIZE_MAX - num_bytes;
42342 +
42343 +                               num_chunks = i + 1;
42344 +                               break;
42345 +                       } else {
42346 +                               chunks[i].iov_len = toSend;
42347 +                       }
42348 +
42349 +                       num_bytes += toSend;
42350 +               }
42351 +       }
42352 +
42353 +       if ((r = writev(fd, chunks, num_chunks)) < 0) {
42354 +               switch (errno) {
42355 +               case EAGAIN:
42356 +               case EINTR:
42357 +                       r = 0;
42358 +                       break;
42359 +               case EPIPE:
42360 +               case ECONNRESET:
42361 +                       return NETWORK_STATUS_CONNECTION_CLOSE;
42362 +               default:
42363 +                       log_error_write(srv, __FILE__, __LINE__, "ssd",
42364 +                                       "writev failed:", strerror(errno), fd);
42365 +
42366 +                       return NETWORK_STATUS_FATAL_ERROR;
42367 +               }
42368 +       }
42369 +
42370 +       cq->bytes_out += r;
42371 +
42372 +       /* check which chunks have been written */
42373 +
42374 +       for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
42375 +               if (r >= (ssize_t)chunks[i].iov_len) {
42376 +                       /* written */
42377 +                       r -= chunks[i].iov_len;
42378 +                       tc->offset += chunks[i].iov_len;
42379 +               } else {
42380 +                       /* partially written */
42381 +
42382 +                       tc->offset += r;
42383 +                       break;
42384 +               }
42385 +       }
42386 +
42387 +       return NETWORK_STATUS_SUCCESS;
42388 +}
42389 +
42390 +NETWORK_BACKEND_WRITE(writev) {
42391 +       chunk *c, *tc;
42392         size_t chunks_written = 0;
42393 -       
42394 +
42395         for(c = cq->first; c; c = c->next) {
42396                 int chunk_finished = 0;
42397 -               
42398 +               network_status_t ret;
42399 +
42400                 switch(c->type) {
42401 -               case MEM_CHUNK: {
42402 -                       char * offset;
42403 -                       size_t toSend;
42404 -                       ssize_t r;
42405 -                       
42406 -                       size_t num_chunks, i;
42407 -                       struct iovec chunks[UIO_MAXIOV];
42408 -                       chunk *tc;
42409 -                       size_t num_bytes = 0;
42410 -                       
42411 -                       /* we can't send more then SSIZE_MAX bytes in one chunk */
42412 -                       
42413 -                       /* build writev list 
42414 -                        * 
42415 -                        * 1. limit: num_chunks < UIO_MAXIOV
42416 -                        * 2. limit: num_bytes < SSIZE_MAX
42417 -                        */
42418 -                       for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
42419 -                       
42420 -                       for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
42421 -                               if (tc->mem->used == 0) {
42422 -                                       chunks[i].iov_base = tc->mem->ptr;
42423 -                                       chunks[i].iov_len  = 0;
42424 -                               } else {
42425 -                                       offset = tc->mem->ptr + tc->offset;
42426 -                                       toSend = tc->mem->used - 1 - tc->offset;
42427 -                               
42428 -                                       chunks[i].iov_base = offset;
42429 -                                       
42430 -                                       /* protect the return value of writev() */
42431 -                                       if (toSend > SSIZE_MAX ||
42432 -                                           num_bytes + toSend > SSIZE_MAX) {
42433 -                                               chunks[i].iov_len = SSIZE_MAX - num_bytes;
42434 -                                               
42435 -                                               num_chunks = i + 1;
42436 -                                               break;
42437 -                                       } else {
42438 -                                               chunks[i].iov_len = toSend;
42439 -                                       }
42440 -                                       
42441 -                                       num_bytes += toSend;
42442 -                               }
42443 -                       }
42444 -                       
42445 -                       if ((r = writev(fd, chunks, num_chunks)) < 0) {
42446 -                               switch (errno) {
42447 -                               case EAGAIN:
42448 -                               case EINTR:
42449 -                                       r = 0;
42450 -                                       break;
42451 -                               case EPIPE:
42452 -                               case ECONNRESET:
42453 -                                       return -2;
42454 -                               default:
42455 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
42456 -                                                       "writev failed:", strerror(errno), fd);
42457 -                               
42458 -                                       return -1;
42459 -                               }
42460 -                       }
42461 -                       
42462 -                       cq->bytes_out += r;
42463 +               case MEM_CHUNK:
42464 +                       ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
42465  
42466 -                       /* check which chunks have been written */
42467 -                       
42468 -                       for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
42469 -                               if (r >= (ssize_t)chunks[i].iov_len) {
42470 -                                       /* written */
42471 -                                       r -= chunks[i].iov_len;
42472 -                                       tc->offset += chunks[i].iov_len;
42473 -                                       
42474 +                       /* check which chunks are finished now */
42475 +                       for (tc = c; tc; tc = tc->next) {
42476 +                               /* finished the chunk */
42477 +                               if (tc->offset == tc->mem->used - 1) {
42478 +                                       /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
42479                                         if (chunk_finished) {
42480 -                                               /* skip the chunks from further touches */
42481 -                                               chunks_written++;
42482                                                 c = c->next;
42483                                         } else {
42484 -                                               /* chunks_written + c = c->next is done in the for()*/
42485 -                                               chunk_finished++;
42486 +                                               chunk_finished = 1;
42487                                         }
42488                                 } else {
42489 -                                       /* partially written */
42490 -                                       
42491 -                                       tc->offset += r;
42492 -                                       chunk_finished = 0;
42493 -
42494                                         break;
42495                                 }
42496                         }
42497 -                       
42498 +
42499 +                       if (ret != NETWORK_STATUS_SUCCESS) {
42500 +                               return ret;
42501 +                       }
42502 +
42503                         break;
42504 -               }
42505                 case FILE_CHUNK: {
42506                         ssize_t r;
42507                         off_t abs_offset;
42508 @@ -159,26 +173,26 @@
42509  #define KByte * 1024
42510  #define MByte * 1024 KByte
42511  #define GByte * 1024 MByte
42512 -                       const off_t we_want_to_mmap = 512 KByte; 
42513 +                       const off_t we_want_to_mmap = 512 KByte;
42514                         char *start = NULL;
42515  
42516                         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
42517                                 log_error_write(srv, __FILE__, __LINE__, "sb",
42518                                                 strerror(errno), c->file.name);
42519 -                               return -1;
42520 +                               return NETWORK_STATUS_FATAL_ERROR;
42521                         }
42522  
42523                         abs_offset = c->file.start + c->offset;
42524 -                       
42525 +
42526                         if (abs_offset > sce->st.st_size) {
42527 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
42528 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
42529                                                 "file was shrinked:", c->file.name);
42530 -                               
42531 -                               return -1;
42532 +
42533 +                               return NETWORK_STATUS_FATAL_ERROR;
42534                         }
42535  
42536 -                       /* mmap the buffer 
42537 -                        * - first mmap 
42538 +                       /* mmap the buffer
42539 +                        * - first mmap
42540                          * - new mmap as the we are at the end of the last one */
42541                         if (c->file.mmap.start == MAP_FAILED ||
42542                             abs_offset == (off_t)(c->file.mmap.offset + c->file.mmap.length)) {
42543 @@ -188,7 +202,7 @@
42544                                  * adaptive mem-mapping
42545                                  *   the problem:
42546                                  *     we mmap() the whole file. If someone has alot large files and 32bit
42547 -                                *     machine the virtual address area will be unrun and we will have a failing 
42548 +                                *     machine the virtual address area will be unrun and we will have a failing
42549                                  *     mmap() call.
42550                                  *   solution:
42551                                  *     only mmap 16M in one chunk and move the window as soon as we have finished
42552 @@ -234,8 +248,8 @@
42553                                 if (-1 == c->file.fd) {  /* open the file if not already open */
42554                                         if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
42555                                                 log_error_write(srv, __FILE__, __LINE__, "sbs", "open failed for:", c->file.name, strerror(errno));
42556 -                               
42557 -                                               return -1;
42558 +
42559 +                                               return NETWORK_STATUS_FATAL_ERROR;
42560                                         }
42561  #ifdef FD_CLOEXEC
42562                                         fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
42563 @@ -245,10 +259,10 @@
42564                                 if (MAP_FAILED == (c->file.mmap.start = mmap(0, to_mmap, PROT_READ, MAP_SHARED, c->file.fd, c->file.mmap.offset))) {
42565                                         /* close it here, otherwise we'd have to set FD_CLOEXEC */
42566  
42567 -                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:", 
42568 +                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:",
42569                                                         strerror(errno), c->file.name, c->file.fd);
42570  
42571 -                                       return -1;
42572 +                                       return NETWORK_STATUS_FATAL_ERROR;
42573                                 }
42574  
42575                                 c->file.mmap.length = to_mmap;
42576 @@ -258,7 +272,7 @@
42577  #ifdef HAVE_MADVISE
42578                                 /* don't advise files < 64Kb */
42579                                 if (c->file.mmap.length > (64 KByte)) {
42580 -                                       /* darwin 7 is returning EINVAL all the time and I don't know how to 
42581 +                                       /* darwin 7 is returning EINVAL all the time and I don't know how to
42582                                          * detect this at runtime.i
42583                                          *
42584                                          * ignore the return value for now */
42585 @@ -274,12 +288,12 @@
42586                         toSend = (c->file.mmap.offset + c->file.mmap.length) - (abs_offset);
42587  
42588                         if (toSend < 0) {
42589 -                               log_error_write(srv, __FILE__, __LINE__, "soooo", 
42590 +                               log_error_write(srv, __FILE__, __LINE__, "soooo",
42591                                                 "toSend is negative:",
42592                                                 toSend,
42593                                                 c->file.mmap.length,
42594                                                 abs_offset,
42595 -                                               c->file.mmap.offset); 
42596 +                                               c->file.mmap.offset);
42597                                 assert(toSend < 0);
42598                         }
42599  
42600 @@ -297,18 +311,18 @@
42601                                         break;
42602                                 case EPIPE:
42603                                 case ECONNRESET:
42604 -                                       return -2;
42605 +                                       return NETWORK_STATUS_CONNECTION_CLOSE;
42606                                 default:
42607 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
42608 +                                       log_error_write(srv, __FILE__, __LINE__, "ssd",
42609                                                         "write failed:", strerror(errno), fd);
42610 -                                       
42611 -                                       return -1;
42612 +
42613 +                                       return NETWORK_STATUS_FATAL_ERROR;
42614                                 }
42615                         }
42616 -                       
42617 +
42618                         c->offset += r;
42619                         cq->bytes_out += r;
42620 -                       
42621 +
42622                         if (c->offset == c->file.length) {
42623                                 chunk_finished = 1;
42624  
42625 @@ -318,26 +332,26 @@
42626                                         c->file.mmap.start = MAP_FAILED;
42627                                 }
42628                         }
42629 -                       
42630 +
42631                         break;
42632                 }
42633                 default:
42634 -                       
42635 +
42636                         log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
42637 -                       
42638 -                       return -1;
42639 +
42640 +                       return NETWORK_STATUS_FATAL_ERROR;
42641                 }
42642 -               
42643 +
42644                 if (!chunk_finished) {
42645                         /* not finished yet */
42646 -                       
42647 +
42648                         break;
42649                 }
42650 -               
42651 +
42652                 chunks_written++;
42653         }
42654  
42655 -       return chunks_written;
42656 +       return NETWORK_STATUS_SUCCESS;
42657  }
42658  
42659  #endif
42660 --- lighttpd-1.4.11/src/plugin.c        2006-02-08 14:00:54.000000000 +0200
42661 +++ lighttpd-1.4.12/src/plugin.c        2006-07-11 22:07:52.000000000 +0300
42662 @@ -13,27 +13,27 @@
42663  #include <valgrind/valgrind.h>
42664  #endif
42665  
42666 -#ifndef __WIN32
42667 +#ifndef _WIN32
42668  #include <dlfcn.h>
42669  #endif
42670  /*
42671 - * 
42672 + *
42673   * if you change this enum to add a new callback, be sure
42674   * - that PLUGIN_FUNC_SIZEOF is the last entry
42675   * - that you add PLUGIN_TO_SLOT twice:
42676 - *   1. as callback-dispatcher 
42677 + *   1. as callback-dispatcher
42678   *   2. in plugins_call_init()
42679 - * 
42680 + *
42681   */
42682  
42683  typedef struct {
42684         PLUGIN_DATA;
42685  } plugin_data;
42686  
42687 -typedef enum { 
42688 +typedef enum {
42689         PLUGIN_FUNC_UNSET,
42690 -               PLUGIN_FUNC_HANDLE_URI_CLEAN, 
42691 -               PLUGIN_FUNC_HANDLE_URI_RAW, 
42692 +               PLUGIN_FUNC_HANDLE_URI_CLEAN,
42693 +               PLUGIN_FUNC_HANDLE_URI_RAW,
42694                 PLUGIN_FUNC_HANDLE_REQUEST_DONE,
42695                 PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE,
42696                 PLUGIN_FUNC_HANDLE_TRIGGER,
42697 @@ -44,38 +44,42 @@
42698                 PLUGIN_FUNC_HANDLE_DOCROOT,
42699                 PLUGIN_FUNC_HANDLE_PHYSICAL,
42700                 PLUGIN_FUNC_CONNECTION_RESET,
42701 -               PLUGIN_FUNC_INIT, 
42702 +               PLUGIN_FUNC_INIT,
42703                 PLUGIN_FUNC_CLEANUP,
42704                 PLUGIN_FUNC_SET_DEFAULTS,
42705 -               
42706 +
42707                 PLUGIN_FUNC_SIZEOF
42708  } plugin_t;
42709  
42710  static plugin *plugin_init(void) {
42711         plugin *p;
42712 -       
42713 +
42714         p = calloc(1, sizeof(*p));
42715 -       
42716 +
42717 +       p->required_plugins = array_init();
42718 +
42719         return p;
42720  }
42721  
42722  static void plugin_free(plugin *p) {
42723         int use_dlclose = 1;
42724         if (p->name) buffer_free(p->name);
42725 +
42726 +       array_free(p->required_plugins);
42727  #ifdef HAVE_VALGRIND_VALGRIND_H
42728         /*if (RUNNING_ON_VALGRIND) use_dlclose = 0;*/
42729  #endif
42730  
42731  #ifndef LIGHTTPD_STATIC
42732 -       if (use_dlclose && p->lib) {    
42733 -#ifdef __WIN32
42734 +       if (use_dlclose && p->lib) {
42735 +#ifdef _WIN32
42736                 FreeLibrary(p->lib);
42737  #else
42738                 dlclose(p->lib);
42739  #endif
42740         }
42741  #endif
42742 -               
42743 +
42744         free(p);
42745  }
42746  
42747 @@ -89,17 +93,17 @@
42748                 srv->plugins.size += 4;
42749                 srv->plugins.ptr   = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps));
42750         }
42751 -       
42752 +
42753         ps = srv->plugins.ptr;
42754         ps[srv->plugins.used++] = p;
42755 -       
42756 +
42757         return 0;
42758  }
42759  
42760  /**
42761 - * 
42762 - * 
42763 - * 
42764 + *
42765 + *
42766 + *
42767   */
42768  
42769  #ifdef LIGHTTPD_STATIC
42770 @@ -121,30 +125,35 @@
42771  #else
42772  int plugins_load(server *srv) {
42773         plugin *p;
42774 +#ifdef _WIN32
42775 +    FARPROC init;
42776 +#else
42777         int (*init)(plugin *pl);
42778 +#endif
42779 +
42780         const char *error;
42781 -       size_t i;
42782 -       
42783 +       size_t i, j, k;
42784 +
42785         for (i = 0; i < srv->srvconf.modules->used; i++) {
42786                 data_string *d = (data_string *)srv->srvconf.modules->data[i];
42787                 char *modules = d->value->ptr;
42788 -       
42789 +
42790                 buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.modules_dir);
42791  
42792                 buffer_append_string(srv->tmp_buf, "/");
42793                 buffer_append_string(srv->tmp_buf, modules);
42794 -#if defined(__WIN32) || defined(__CYGWIN__)
42795 +#if defined(_WIN32) || defined(__CYGWIN__)
42796                 buffer_append_string(srv->tmp_buf, ".dll");
42797  #else
42798                 buffer_append_string(srv->tmp_buf, ".so");
42799  #endif
42800 -       
42801 +
42802                 p = plugin_init();
42803 -#ifdef __WIN32
42804 +#ifdef _WIN32
42805                 if (NULL == (p->lib = LoadLibrary(srv->tmp_buf->ptr))) {
42806                         LPVOID lpMsgBuf;
42807                         FormatMessage(
42808 -                               FORMAT_MESSAGE_ALLOCATE_BUFFER | 
42809 +                               FORMAT_MESSAGE_ALLOCATE_BUFFER |
42810                                 FORMAT_MESSAGE_FROM_SYSTEM,
42811                                 NULL,
42812                                 GetLastError(),
42813 @@ -152,36 +161,36 @@
42814                                 (LPTSTR) &lpMsgBuf,
42815                                 0, NULL );
42816  
42817 -                       log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed", 
42818 +                       log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
42819                                         lpMsgBuf, srv->tmp_buf);
42820 -                       
42821 +
42822                         plugin_free(p);
42823 -                       
42824 +
42825                         return -1;
42826  
42827                 }
42828 -#else  
42829 +#else
42830                 if (NULL == (p->lib = dlopen(srv->tmp_buf->ptr, RTLD_LAZY))) {
42831 -                       log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:", 
42832 +                       log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
42833                                         srv->tmp_buf, dlerror());
42834 -                       
42835 +
42836                         plugin_free(p);
42837 -                       
42838 +
42839                         return -1;
42840                 }
42841 -               
42842 +
42843  #endif
42844                 buffer_reset(srv->tmp_buf);
42845                 buffer_copy_string(srv->tmp_buf, modules);
42846                 buffer_append_string(srv->tmp_buf, "_plugin_init");
42847  
42848 -#ifdef __WIN32
42849 +#ifdef _WIN32
42850                 init = GetProcAddress(p->lib, srv->tmp_buf->ptr);
42851  
42852                 if (init == NULL)  {
42853                         LPVOID lpMsgBuf;
42854                         FormatMessage(
42855 -                               FORMAT_MESSAGE_ALLOCATE_BUFFER | 
42856 +                               FORMAT_MESSAGE_ALLOCATE_BUFFER |
42857                                 FORMAT_MESSAGE_FROM_SYSTEM,
42858                                 NULL,
42859                                 GetLastError(),
42860 @@ -190,7 +199,7 @@
42861                                 0, NULL );
42862  
42863                         log_error_write(srv, __FILE__, __LINE__, "sbs", "getprocaddress failed:", srv->tmp_buf, lpMsgBuf);
42864 -                       
42865 +
42866                         plugin_free(p);
42867                         return -1;
42868                 }
42869 @@ -203,24 +212,43 @@
42870  #endif
42871                 if ((error = dlerror()) != NULL)  {
42872                         log_error_write(srv, __FILE__, __LINE__, "s", error);
42873 -                       
42874 +
42875                         plugin_free(p);
42876                         return -1;
42877                 }
42878 -       
42879 +
42880  #endif
42881                 if ((*init)(p)) {
42882                         log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin init failed" );
42883 -                       
42884 +
42885                         plugin_free(p);
42886                         return -1;
42887                 }
42888  #if 0
42889                 log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin loaded" );
42890  #endif
42891 +               /* check if the required plugin is loaded */
42892 +               for (k = 0; k < p->required_plugins->used; k++) {
42893 +                       data_string *req = (data_string *)p->required_plugins->data[k];
42894 +
42895 +                       for (j = 0; j < i; j++) {
42896 +                               data_string *mod = (data_string *)srv->srvconf.modules->data[j];
42897 +
42898 +                               if (buffer_is_equal(req->value, mod->value)) break;
42899 +                       }
42900 +
42901 +                       if (j == i) {
42902 +                               /* not found */
42903 +                               log_error_write(srv, __FILE__, __LINE__, "ssbs", modules, "failed to load. required plugin", req->value, "was not loaded" );
42904 +
42905 +                               plugin_free(p);
42906 +                       
42907 +                               return -1;
42908 +                       }
42909 +               }
42910                 plugins_register(srv, p);
42911         }
42912 -       
42913 +
42914         return 0;
42915  }
42916  #endif
42917 @@ -253,8 +281,8 @@
42918         }
42919  
42920  /**
42921 - * plugins that use 
42922 - * 
42923 + * plugins that use
42924 + *
42925   * - server *srv
42926   * - connection *con
42927   * - void *p_d (plugin_data *)
42928 @@ -301,12 +329,12 @@
42929         }
42930  
42931  /**
42932 - * plugins that use 
42933 - * 
42934 + * plugins that use
42935 + *
42936   * - server *srv
42937   * - void *p_d (plugin_data *)
42938   */
42939 -                                                                       
42940 +
42941  PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger)
42942  PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup)
42943  PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup)
42944 @@ -314,18 +342,18 @@
42945  
42946  #undef PLUGIN_TO_SLOT
42947  
42948 -#if 0                                                                  
42949 +#if 0
42950  /**
42951 - * 
42952 + *
42953   * special handler
42954 - * 
42955 + *
42956   */
42957  handler_t plugins_call_handle_fdevent(server *srv, const fd_conn *fdc) {
42958         size_t i;
42959         plugin **ps;
42960 -       
42961 +
42962         ps = srv->plugins.ptr;
42963 -       
42964 +
42965         for (i = 0; i < srv->plugins.used; i++) {
42966                 plugin *p = ps[i];
42967                 if (p->handle_fdevent) {
42968 @@ -344,34 +372,34 @@
42969                         }
42970                 }
42971         }
42972 -       
42973 +
42974         return HANDLER_GO_ON;
42975  }
42976  #endif
42977  /**
42978 - * 
42979 + *
42980   * - call init function of all plugins to init the plugin-internals
42981   * - added each plugin that supports has callback to the corresponding slot
42982 - * 
42983 + *
42984   * - is only called once.
42985   */
42986  
42987  handler_t plugins_call_init(server *srv) {
42988         size_t i;
42989         plugin **ps;
42990 -       
42991 +
42992         ps = srv->plugins.ptr;
42993 -       
42994 +
42995         /* fill slots */
42996 -       
42997 +
42998         srv->plugin_slots = calloc(PLUGIN_FUNC_SIZEOF, sizeof(ps));
42999 -       
43000 +
43001         for (i = 0; i < srv->plugins.used; i++) {
43002                 size_t j;
43003                 /* check which calls are supported */
43004 -               
43005 +
43006                 plugin *p = ps[i];
43007 -               
43008 +
43009  #define PLUGIN_TO_SLOT(x, y) \
43010         if (p->y) { \
43011                 plugin **slot = ((plugin ***)(srv->plugin_slots))[x]; \
43012 @@ -384,11 +412,11 @@
43013                         slot[j] = p;\
43014                         break;\
43015                 }\
43016 -       } 
43017 -               
43018 -               
43019 -               PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean); 
43020 -               PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw); 
43021 +       }
43022 +
43023 +
43024 +               PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
43025 +               PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
43026                 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle_request_done);
43027                 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close);
43028                 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger);
43029 @@ -402,19 +430,19 @@
43030                 PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup);
43031                 PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults);
43032  #undef PLUGIN_TO_SLOT
43033 -               
43034 +
43035                 if (p->init) {
43036                         if (NULL == (p->data = p->init())) {
43037 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
43038 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
43039                                                 "plugin-init failed for module", p->name);
43040                                 return HANDLER_ERROR;
43041                         }
43042 -                       
43043 +
43044                         /* used for con->mode, DIRECT == 0, plugins above that */
43045                         ((plugin_data *)(p->data))->id = i + 1;
43046 -                       
43047 +
43048                         if (p->version != LIGHTTPD_VERSION_ID) {
43049 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
43050 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
43051                                                 "plugin-version doesn't match lighttpd-version for", p->name);
43052                                 return HANDLER_ERROR;
43053                         }
43054 @@ -422,29 +450,46 @@
43055                         p->data = NULL;
43056                 }
43057         }
43058 -       
43059 +
43060         return HANDLER_GO_ON;
43061  }
43062  
43063 +/**
43064 + * get the config-storage of the named plugin 
43065 + */
43066 +void *plugin_get_config(server *srv, const char *name) {
43067 +       size_t i;
43068 +
43069 +       for (i = 0; i < srv->plugins.used; i++) {
43070 +               plugin *p = ((plugin **)srv->plugins.ptr)[i];
43071 +
43072 +               if (buffer_is_equal_string(p->name, name, strlen(name))) {
43073 +                       return p->data;
43074 +               }
43075 +       }
43076 +
43077 +       return NULL;
43078 +}
43079 +
43080  void plugins_free(server *srv) {
43081         size_t i;
43082         plugins_call_cleanup(srv);
43083 -       
43084 +
43085         for (i = 0; i < srv->plugins.used; i++) {
43086                 plugin *p = ((plugin **)srv->plugins.ptr)[i];
43087 -               
43088 +
43089                 plugin_free(p);
43090         }
43091 -       
43092 +
43093         for (i = 0; srv->plugin_slots && i < PLUGIN_FUNC_SIZEOF; i++) {
43094                 plugin **slot = ((plugin ***)(srv->plugin_slots))[i];
43095 -               
43096 +
43097                 if (slot) free(slot);
43098         }
43099 -       
43100 +
43101         free(srv->plugin_slots);
43102         srv->plugin_slots = NULL;
43103 -       
43104 +
43105         free(srv->plugins.ptr);
43106         srv->plugins.ptr = NULL;
43107         srv->plugins.used = 0;
43108 --- lighttpd-1.4.11/src/plugin.h        2005-08-15 12:28:56.000000000 +0300
43109 +++ lighttpd-1.4.12/src/plugin.h        2006-07-11 22:07:52.000000000 +0300
43110 @@ -12,6 +12,12 @@
43111  
43112  #define INIT_FUNC(x) \
43113                 static void *x()
43114 +/*
43115 + * The PATCH_OPTION() macro is used in the patch_connection() functions
43116 + * of the modules to update the config object for the current request.
43117 + */
43118 +#define PATCH_OPTION(x) \
43119 +               p->conf.x = s->x
43120  
43121  #define FREE_FUNC          SERVER_FUNC
43122  #define TRIGGER_FUNC       SERVER_FUNC
43123 @@ -25,19 +31,19 @@
43124  #define URIHANDLER_FUNC    CONNECTION_FUNC
43125  
43126  #define PLUGIN_DATA        size_t id
43127 -                                                                                                                                               
43128 +
43129  typedef struct {
43130         size_t version;
43131 -       
43132 +
43133         buffer *name; /* name of the plugin */
43134 -       
43135 +
43136         void *(* init)                       ();
43137         handler_t (* set_defaults)           (server *srv, void *p_d);
43138         handler_t (* cleanup)                (server *srv, void *p_d);
43139                                                                                            /* is called ... */
43140         handler_t (* handle_trigger)         (server *srv, void *p_d);                     /* once a second */
43141         handler_t (* handle_sighup)          (server *srv, void *p_d);                     /* at a signup */
43142 -       
43143 +
43144         handler_t (* handle_uri_raw)         (server *srv, connection *con, void *p_d);    /* after uri_raw is set */
43145         handler_t (* handle_uri_clean)       (server *srv, connection *con, void *p_d);    /* after uri is set */
43146         handler_t (* handle_docroot)         (server *srv, connection *con, void *p_d);    /* getting the document-root */
43147 @@ -45,20 +51,22 @@
43148         handler_t (* handle_request_done)    (server *srv, connection *con, void *p_d);    /* at the end of a request */
43149         handler_t (* handle_connection_close)(server *srv, connection *con, void *p_d);    /* at the end of a connection */
43150         handler_t (* handle_joblist)         (server *srv, connection *con, void *p_d);    /* after all events are handled */
43151 -       
43152 -       
43153 -       
43154 -       handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);   
43155 -       
43156 -                                                                                          /* when a handler for the request 
43157 +
43158 +
43159 +
43160 +       handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);
43161 +
43162 +                                                                                          /* when a handler for the request
43163                                                                                             * has to be found
43164                                                                                             */
43165         handler_t (* handle_subrequest)      (server *srv, connection *con, void *p_d);    /* */
43166         handler_t (* connection_reset)       (server *srv, connection *con, void *p_d);    /* */
43167         void *data;
43168 -       
43169 +
43170         /* dlopen handle */
43171         void *lib;
43172 +
43173 +       array *required_plugins;
43174  } plugin;
43175  
43176  int plugins_load(server *srv);
43177 @@ -88,5 +96,8 @@
43178  int config_patch_connection(server *srv, connection *con, comp_key_t comp);
43179  int config_check_cond(server *srv, connection *con, data_config *dc);
43180  int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n);
43181 +int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result);
43182 +
43183 +void *plugin_get_config(server *srv, const char *name);
43184  
43185  #endif
43186 --- lighttpd-1.4.11/src/proc_open.c     2005-08-11 01:26:39.000000000 +0300
43187 +++ lighttpd-1.4.12/src/proc_open.c     2006-07-11 22:07:53.000000000 +0300
43188 @@ -13,13 +13,13 @@
43189  #endif
43190  
43191  
43192 -#ifdef WIN32
43193 +#ifdef _WIN32
43194  /* {{{ win32 stuff */
43195  # define SHELLENV "ComSpec"
43196  # define SECURITY_DC , SECURITY_ATTRIBUTES *security
43197  # define SECURITY_CC , security
43198  # define pipe(pair) (CreatePipe(&pair[0], &pair[1], security, 2048L) ? 0 : -1)
43199 -static inline HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
43200 +static HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
43201  {
43202         HANDLE copy, self = GetCurrentProcess();
43203  
43204 @@ -148,11 +148,14 @@
43205         STARTUPINFO si;
43206         BOOL procok;
43207         SECURITY_ATTRIBUTES security;
43208 -       const char *shell;
43209 +       const char *shell = NULL;
43210 +       const char *windir = NULL;
43211         buffer *cmdline;
43212  
43213 -       if (NULL == (shell = getenv(SHELLENV))) {
43214 -               fprintf(stderr, "env %s is required", SHELLENV);
43215 +       if (NULL == (shell = getenv(SHELLENV)) &&
43216 +                       NULL == (windir = getenv("SystemRoot")) &&
43217 +                       NULL == (windir = getenv("windir"))) {
43218 +               fprintf(stderr, "One of %s,%%SystemRoot,%%windir is required", SHELLENV);
43219                 return -1;
43220         }
43221  
43222 @@ -177,17 +180,23 @@
43223         memset(&pi, 0, sizeof(pi));
43224  
43225         cmdline = buffer_init();
43226 -       buffer_append_string(cmdline, shell);
43227 +       if (shell) {
43228 +               buffer_append_string(cmdline, shell);
43229 +       } else {
43230 +               buffer_append_string(cmdline, windir);
43231 +               buffer_append_string(cmdline, "\\system32\\cmd.exe");
43232 +       }
43233         buffer_append_string_len(cmdline, CONST_STR_LEN(" /c "));
43234         buffer_append_string(cmdline, command);
43235         procok = CreateProcess(NULL, cmdline->ptr, &security, &security, TRUE,
43236                         NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
43237 -       buffer_free(cmdline);
43238  
43239         if (FALSE == procok) {
43240 -               fprintf(stderr, "failed to CreateProcess");
43241 +               fprintf(stderr, "failed to CreateProcess: %s", cmdline->ptr);
43242 +               buffer_free(cmdline);
43243                 return -1;
43244         }
43245 +       buffer_free(cmdline);
43246  
43247         proc->child = pi.hProcess;
43248         CloseHandle(pi.hThread);
43249 @@ -226,8 +235,7 @@
43250         const char *shell;
43251  
43252         if (NULL == (shell = getenv(SHELLENV))) {
43253 -               fprintf(stderr, "env %s is required", SHELLENV);
43254 -               return -1;
43255 +               shell = "/bin/sh";
43256         }
43257  
43258         if (proc_open_pipes(proc) != 0) {
43259 @@ -262,11 +270,11 @@
43260         }
43261  }
43262  /* }}} */
43263 -#endif /* WIN32 */
43264 +#endif /* _WIN32 */
43265  
43266  /* {{{ proc_read_fd_to_buffer */
43267  static void proc_read_fd_to_buffer(int fd, buffer *b) {
43268 -       ssize_t s;
43269 +       int s; /* win32 has not ssize_t */
43270  
43271         for (;;) {
43272                 buffer_prepare_append(b, 512);
43273 --- lighttpd-1.4.11/src/proc_open.h     2005-08-11 01:26:39.000000000 +0300
43274 +++ lighttpd-1.4.12/src/proc_open.h     2006-07-11 22:07:53.000000000 +0300
43275 @@ -1,7 +1,7 @@
43276  
43277  #include "buffer.h"
43278  
43279 -#ifdef WIN32
43280 +#ifdef _WIN32
43281  #include <windows.h>
43282  typedef HANDLE descriptor_t;
43283  typedef HANDLE proc_pid_t;
43284 --- lighttpd-1.4.11/src/request.c       2006-03-05 11:58:09.000000000 +0200
43285 +++ lighttpd-1.4.12/src/request.c       2006-07-11 22:07:52.000000000 +0300
43286 @@ -10,15 +10,17 @@
43287  #include "keyvalue.h"
43288  #include "log.h"
43289  
43290 +#include "sys-strings.h"
43291 +
43292  static int request_check_hostname(server *srv, connection *con, buffer *host) {
43293         enum { DOMAINLABEL, TOPLABEL } stage = TOPLABEL;
43294         size_t i;
43295         int label_len = 0;
43296         size_t host_len;
43297         char *colon;
43298 -       int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */ 
43299 +       int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */
43300         int level = 0;
43301 -       
43302 +
43303         UNUSED(srv);
43304         UNUSED(con);
43305  
43306 @@ -32,17 +34,17 @@
43307          *       IPv6address   = "[" ... "]"
43308          *       port          = *digit
43309          */
43310 -       
43311 +
43312         /* no Host: */
43313         if (!host || host->used == 0) return 0;
43314 -       
43315 +
43316         host_len = host->used - 1;
43317 -       
43318 +
43319         /* IPv6 adress */
43320         if (host->ptr[0] == '[') {
43321                 char *c = host->ptr + 1;
43322                 int colon_cnt = 0;
43323 -               
43324 +
43325                 /* check portnumber */
43326                 for (; *c && *c != ']'; c++) {
43327                         if (*c == ':') {
43328 @@ -53,12 +55,12 @@
43329                                 return -1;
43330                         }
43331                 }
43332 -               
43333 +
43334                 /* missing ] */
43335                 if (!*c) {
43336                         return -1;
43337                 }
43338 -               
43339 +
43340                 /* check port */
43341                 if (*(c+1) == ':') {
43342                         for (c += 2; *c; c++) {
43343 @@ -69,39 +71,39 @@
43344                 }
43345                 return 0;
43346         }
43347 -       
43348 +
43349         if (NULL != (colon = memchr(host->ptr, ':', host_len))) {
43350                 char *c = colon + 1;
43351 -               
43352 +
43353                 /* check portnumber */
43354                 for (; *c; c++) {
43355                         if (!light_isdigit(*c)) return -1;
43356                 }
43357 -               
43358 +
43359                 /* remove the port from the host-len */
43360                 host_len = colon - host->ptr;
43361         }
43362 -       
43363 +
43364         /* Host is empty */
43365         if (host_len == 0) return -1;
43366 -       
43367 +
43368         /* scan from the right and skip the \0 */
43369         for (i = host_len - 1; i + 1 > 0; i--) {
43370                 const char c = host->ptr[i];
43371  
43372                 switch (stage) {
43373 -               case TOPLABEL: 
43374 +               case TOPLABEL:
43375                         if (c == '.') {
43376                                 /* only switch stage, if this is not the last character */
43377                                 if (i != host_len - 1) {
43378                                         if (label_len == 0) {
43379                                                 return -1;
43380                                         }
43381 -                                       
43382 +
43383                                         /* check the first character at right of the dot */
43384                                         if (is_ip == 0) {
43385                                                 if (!light_isalpha(host->ptr[i+1])) {
43386 -                                                       return -1; 
43387 +                                                       return -1;
43388                                                 }
43389                                         } else if (!light_isdigit(host->ptr[i+1])) {
43390                                                 is_ip = 0;
43391 @@ -111,9 +113,9 @@
43392                                                 /* just digits */
43393                                                 is_ip = 1;
43394                                         }
43395 -                                               
43396 +
43397                                         stage = DOMAINLABEL;
43398 -                                       
43399 +
43400                                         label_len = 0;
43401                                         level++;
43402                                 } else if (i == 0) {
43403 @@ -135,7 +137,7 @@
43404                                 }
43405                                 label_len++;
43406                         }
43407 -                       
43408 +
43409                         break;
43410                 case DOMAINLABEL:
43411                         if (is_ip == 1) {
43412 @@ -143,7 +145,7 @@
43413                                         if (label_len == 0) {
43414                                                 return -1;
43415                                         }
43416 -                                       
43417 +
43418                                         label_len = 0;
43419                                         level++;
43420                                 } else if (!light_isdigit(c)) {
43421 @@ -156,12 +158,12 @@
43422                                         if (label_len == 0) {
43423                                                 return -1;
43424                                         }
43425 -                                       
43426 +
43427                                         /* c is either - or alphanum here */
43428                                         if ('-' == host->ptr[i+1]) {
43429                                                 return -1;
43430                                         }
43431 -                                       
43432 +
43433                                         label_len = 0;
43434                                         level++;
43435                                 } else if (i == 0) {
43436 @@ -176,20 +178,20 @@
43437                                         label_len++;
43438                                 }
43439                         }
43440 -                       
43441 +
43442                         break;
43443                 }
43444         }
43445 -       
43446 +
43447         /* a IP has to consist of 4 parts */
43448         if (is_ip == 1 && level != 3) {
43449                 return -1;
43450         }
43451 -       
43452 +
43453         if (label_len == 0) {
43454                 return -1;
43455         }
43456 -       
43457 +
43458         return 0;
43459  }
43460  
43461 @@ -201,53 +203,53 @@
43462         char *s;
43463         size_t i;
43464         int state = 0;
43465 -       /*  
43466 -        * parse 
43467 -        * 
43468 +       /*
43469 +        * parse
43470 +        *
43471          * val1, val2, val3, val4
43472 -        * 
43473 +        *
43474          * into a array (more or less a explode() incl. striping of whitespaces
43475          */
43476 -       
43477 +
43478         if (b->used == 0) return 0;
43479 -       
43480 +
43481         s = b->ptr;
43482 -       
43483 +
43484         for (i =0; i < b->used - 1; ) {
43485                 char *start = NULL, *end = NULL;
43486                 data_string *ds;
43487 -               
43488 +
43489                 switch (state) {
43490                 case 0: /* ws */
43491 -                       
43492 +
43493                         /* skip ws */
43494                         for (; (*s == ' ' || *s == '\t') && i < b->used - 1; i++, s++);
43495 -                       
43496 -                       
43497 +
43498 +
43499                         state = 1;
43500                         break;
43501                 case 1: /* value */
43502                         start = s;
43503 -                       
43504 +
43505                         for (; *s != ',' && i < b->used - 1; i++, s++);
43506                         end = s - 1;
43507 -                       
43508 +
43509                         for (; (*end == ' ' || *end == '\t') && end > start; end--);
43510 -                       
43511 +
43512                         if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
43513                                 ds = data_string_init();
43514                         }
43515  
43516                         buffer_copy_string_len(ds->value, start, end-start+1);
43517                         array_insert_unique(vals, (data_unset *)ds);
43518 -                       
43519 +
43520                         if (*s == ',') {
43521                                 state = 0;
43522                                 i++;
43523                                 s++;
43524                         } else {
43525                                 /* end of string */
43526 -                               
43527 +
43528                                 state = 2;
43529                         }
43530                         break;
43531 @@ -263,7 +265,7 @@
43532         if (c <= 32) return 0;
43533         if (c == 127) return 0;
43534         if (c == 255) return 0;
43535 -       
43536 +
43537         return 1;
43538  }
43539  
43540 @@ -271,28 +273,28 @@
43541         char *uri = NULL, *proto = NULL, *method = NULL, con_length_set;
43542         int is_key = 1, key_len = 0, is_ws_after_key = 0, in_folding;
43543         char *value = NULL, *key = NULL;
43544 -       
43545 +
43546         enum { HTTP_CONNECTION_UNSET, HTTP_CONNECTION_KEEPALIVE, HTTP_CONNECTION_CLOSE } keep_alive_set = HTTP_CONNECTION_UNSET;
43547 -       
43548 +
43549         int line = 0;
43550 -       
43551 +
43552         int request_line_stage = 0;
43553         size_t i, first;
43554 -       
43555 +
43556         int done = 0;
43557 -       
43558 +
43559         data_string *ds = NULL;
43560 -       
43561 -       /* 
43562 -        * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$" 
43563 -        * Option : "^([-a-zA-Z]+): (.+)$"                    
43564 +
43565 +       /*
43566 +        * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
43567 +        * Option : "^([-a-zA-Z]+): (.+)$"
43568          * End    : "^$"
43569          */
43570  
43571         if (con->conf.log_request_header) {
43572 -               log_error_write(srv, __FILE__, __LINE__, "sdsdSb", 
43573 -                               "fd:", con->fd, 
43574 -                               "request-len:", con->request.request->used, 
43575 +               log_error_write(srv, __FILE__, __LINE__, "sdsdSb",
43576 +                               "fd:", con->fd,
43577 +                               "request-len:", con->request.request->used,
43578                                 "\n", con->request.request);
43579         }
43580  
43581 @@ -300,13 +302,13 @@
43582             con->request.request->ptr[0] == '\r' &&
43583             con->request.request->ptr[1] == '\n') {
43584                 /* we are in keep-alive and might get \r\n after a previous POST request.*/
43585 -               
43586 +
43587                 buffer_copy_string_len(con->parse_request, con->request.request->ptr + 2, con->request.request->used - 1 - 2);
43588         } else {
43589                 /* fill the local request buffer */
43590                 buffer_copy_string_buffer(con->parse_request, con->request.request);
43591         }
43592 -       
43593 +
43594         keep_alive_set = 0;
43595         con_length_set = 0;
43596  
43597 @@ -318,25 +320,25 @@
43598          * */
43599         for (i = 0, first = 0; i < con->parse_request->used && line == 0; i++) {
43600                 char *cur = con->parse_request->ptr + i;
43601 -               
43602 +
43603                 switch(*cur) {
43604 -               case '\r': 
43605 +               case '\r':
43606                         if (con->parse_request->ptr[i+1] == '\n') {
43607                                 http_method_t r;
43608                                 char *nuri = NULL;
43609                                 size_t j;
43610 -                               
43611 +
43612                                 /* \r\n -> \0\0 */
43613                                 con->parse_request->ptr[i] = '\0';
43614                                 con->parse_request->ptr[i+1] = '\0';
43615 -                               
43616 +
43617                                 buffer_copy_string_len(con->request.request_line, con->parse_request->ptr, i);
43618 -                               
43619 +
43620                                 if (request_line_stage != 2) {
43621                                         con->http_status = 400;
43622                                         con->response.keep_alive = 0;
43623                                         con->keep_alive = 0;
43624 -                                       
43625 +
43626                                         if (srv->srvconf.log_request_header_on_error) {
43627                                                 log_error_write(srv, __FILE__, __LINE__, "s", "incomplete request line -> 400");
43628                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
43629 @@ -345,36 +347,36 @@
43630                                         }
43631                                         return 0;
43632                                 }
43633 -                               
43634 +
43635                                 proto = con->parse_request->ptr + first;
43636 -                               
43637 +
43638                                 *(uri - 1) = '\0';
43639                                 *(proto - 1) = '\0';
43640 -                               
43641 +
43642                                 /* we got the first one :) */
43643                                 if (-1 == (r = get_http_method_key(method))) {
43644                                         con->http_status = 501;
43645                                         con->response.keep_alive = 0;
43646                                         con->keep_alive = 0;
43647 -                                       
43648 +
43649                                         if (srv->srvconf.log_request_header_on_error) {
43650                                                 log_error_write(srv, __FILE__, __LINE__, "s", "unknown http-method -> 501");
43651                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
43652                                                                 "request-header:\n",
43653                                                                 con->request.request);
43654                                         }
43655 -                               
43656 +
43657                                         return 0;
43658                                 }
43659 -                               
43660 +
43661                                 con->request.http_method = r;
43662 -                       
43663 -                               /* 
43664 +
43665 +                               /*
43666                                  * RFC2616 says:
43667                                  *
43668                                  * HTTP-Version   = "HTTP" "/" 1*DIGIT "." 1*DIGIT
43669                                  *
43670 -                                * */   
43671 +                                * */
43672                                 if (0 == strncmp(proto, "HTTP/", sizeof("HTTP/") - 1)) {
43673                                         char * major = proto + sizeof("HTTP/") - 1;
43674                                         char * minor = strchr(major, '.');
43675 @@ -413,10 +415,10 @@
43676                                         }
43677  
43678                                         if (major_num == 1 && minor_num == 1) {
43679 -                                               con->request.http_version = con->conf.allow_http11 ? HTTP_VERSION_1_1 : HTTP_VERSION_1_0;
43680 +                                               con->request.http_version = HTTP_VERSION_1_1;
43681                                         } else if (major_num == 1 && minor_num == 0) {
43682                                                 con->request.http_version = HTTP_VERSION_1_0;
43683 -                                       } else { 
43684 +                                       } else {
43685                                                 con->http_status = 505;
43686  
43687                                                 if (srv->srvconf.log_request_header_on_error) {
43688 @@ -439,30 +441,30 @@
43689                                         }
43690                                         return 0;
43691                                 }
43692 -                               
43693 +
43694                                 if (0 == strncmp(uri, "http://", 7) &&
43695                                     NULL != (nuri = strchr(uri + 7, '/'))) {
43696                                         /* ignore the host-part */
43697 -                                       
43698 +
43699                                         buffer_copy_string_len(con->request.uri, nuri, proto - nuri - 1);
43700                                 } else {
43701                                         /* everything looks good so far */
43702                                         buffer_copy_string_len(con->request.uri, uri, proto - uri - 1);
43703                                 }
43704 -                               
43705 +
43706                                 /* check uri for invalid characters */
43707                                 for (j = 0; j < con->request.uri->used - 1; j++) {
43708                                         if (!request_uri_is_valid_char(con->request.uri->ptr[j])) {
43709                                                 unsigned char buf[2];
43710                                                 con->http_status = 400;
43711                                                 con->keep_alive = 0;
43712 -                                               
43713 +
43714                                                 if (srv->srvconf.log_request_header_on_error) {
43715                                                         buf[0] = con->request.uri->ptr[j];
43716                                                         buf[1] = '\0';
43717 -                                       
43718 +
43719                                                         if (con->request.uri->ptr[j] > 32 &&
43720 -                                                           con->request.uri->ptr[j] != 127) {  
43721 +                                                           con->request.uri->ptr[j] != 127) {
43722                                                                 /* the character is printable -> print it */
43723                                                                 log_error_write(srv, __FILE__, __LINE__, "ss",
43724                                                                                 "invalid character in URI -> 400",
43725 @@ -473,20 +475,20 @@
43726                                                                                 "invalid character in URI -> 400",
43727                                                                                 con->request.uri->ptr[j]);
43728                                                         }
43729 -                                               
43730 +
43731                                                         log_error_write(srv, __FILE__, __LINE__, "Sb",
43732                                                                         "request-header:\n",
43733                                                                         con->request.request);
43734                                                 }
43735 -                                               
43736 +
43737                                                 return 0;
43738                                         }
43739                                 }
43740 -                               
43741 +
43742                                 buffer_copy_string_buffer(con->request.orig_uri, con->request.uri);
43743 -                               
43744 +
43745                                 con->http_status = 0;
43746 -                               
43747 +
43748                                 i++;
43749                                 line++;
43750                                 first = i+1;
43751 @@ -494,14 +496,14 @@
43752                         break;
43753                 case ' ':
43754                         switch(request_line_stage) {
43755 -                       case 0: 
43756 +                       case 0:
43757                                 /* GET|POST|... */
43758 -                               method = con->parse_request->ptr + first; 
43759 +                               method = con->parse_request->ptr + first;
43760                                 first = i + 1;
43761                                 break;
43762                         case 1:
43763                                 /* /foobar/... */
43764 -                               uri = con->parse_request->ptr + first; 
43765 +                               uri = con->parse_request->ptr + first;
43766                                 first = i + 1;
43767                                 break;
43768                         default:
43769 @@ -509,7 +511,7 @@
43770                                 con->http_status = 400;
43771                                 con->response.keep_alive = 0;
43772                                 con->keep_alive = 0;
43773 -                               
43774 +
43775                                 if (srv->srvconf.log_request_header_on_error) {
43776                                         log_error_write(srv, __FILE__, __LINE__, "s", "overlong request line -> 400");
43777                                         log_error_write(srv, __FILE__, __LINE__, "Sb",
43778 @@ -518,12 +520,12 @@
43779                                 }
43780                                 return 0;
43781                         }
43782 -                       
43783 +
43784                         request_line_stage++;
43785                         break;
43786                 }
43787         }
43788 -       
43789 +
43790         in_folding = 0;
43791  
43792         if (con->request.uri->used == 1) {
43793 @@ -540,30 +542,30 @@
43794                 return 0;
43795         }
43796  
43797 -       
43798 +
43799         for (; i < con->parse_request->used && !done; i++) {
43800                 char *cur = con->parse_request->ptr + i;
43801 -               
43802 +
43803                 if (is_key) {
43804                         size_t j;
43805                         int got_colon = 0;
43806 -                       
43807 +
43808                         /**
43809                          * 1*<any CHAR except CTLs or separators>
43810                          * CTLs == 0-31 + 127
43811 -                        * 
43812 +                        *
43813                          */
43814                         switch(*cur) {
43815                         case ':':
43816                                 is_key = 0;
43817 -                               
43818 +
43819                                 value = cur + 1;
43820 -                               
43821 +
43822                                 if (is_ws_after_key == 0) {
43823                                         key_len = i - first;
43824                                 }
43825                                 is_ws_after_key = 0;
43826 -                                       
43827 +
43828                                 break;
43829                         case '(':
43830                         case ')':
43831 @@ -584,8 +586,8 @@
43832                                 con->http_status = 400;
43833                                 con->keep_alive = 0;
43834                                 con->response.keep_alive = 0;
43835 -                               
43836 -                               log_error_write(srv, __FILE__, __LINE__, "sbsds", 
43837 +
43838 +                               log_error_write(srv, __FILE__, __LINE__, "sbsds",
43839                                                 "invalid character in key", con->request.request, cur, *cur, "-> 400");
43840                                 return 0;
43841                         case ' ':
43842 @@ -594,13 +596,13 @@
43843                                         is_key = 0;
43844                                         in_folding = 1;
43845                                         value = cur;
43846 -                                       
43847 +
43848                                         break;
43849                                 }
43850 -                               
43851 -                               
43852 +
43853 +
43854                                 key_len = i - first;
43855 -                               
43856 +
43857                                 /* skip every thing up to the : */
43858                                 for (j = 1; !got_colon; j++) {
43859                                         switch(con->parse_request->ptr[j + i]) {
43860 @@ -610,40 +612,40 @@
43861                                                 continue;
43862                                         case ':':
43863                                                 /* ok, done */
43864 -                                               
43865 +
43866                                                 i += j - 1;
43867                                                 got_colon = 1;
43868 -                                               
43869 +
43870                                                 break;
43871                                         default:
43872                                                 /* error */
43873 -                                               
43874 +
43875                                                 if (srv->srvconf.log_request_header_on_error) {
43876                                                         log_error_write(srv, __FILE__, __LINE__, "s", "WS character in key -> 400");
43877                                                         log_error_write(srv, __FILE__, __LINE__, "Sb",
43878                                                                 "request-header:\n",
43879                                                                 con->request.request);
43880                                                 }
43881 -                                       
43882 +
43883                                                 con->http_status = 400;
43884                                                 con->response.keep_alive = 0;
43885                                                 con->keep_alive = 0;
43886 -                                               
43887 +
43888                                                 return 0;
43889                                         }
43890                                 }
43891 -                               
43892 +
43893                                 break;
43894                         case '\r':
43895                                 if (con->parse_request->ptr[i+1] == '\n' && i == first) {
43896                                         /* End of Header */
43897                                         con->parse_request->ptr[i] = '\0';
43898                                         con->parse_request->ptr[i+1] = '\0';
43899 -                                       
43900 +
43901                                         i++;
43902 -                                       
43903 +
43904                                         done = 1;
43905 -                                       
43906 +
43907                                         break;
43908                                 } else {
43909                                         if (srv->srvconf.log_request_header_on_error) {
43910 @@ -652,7 +654,7 @@
43911                                                         "request-header:\n",
43912                                                         con->request.request);
43913                                         }
43914 -                                       
43915 +
43916                                         con->http_status = 400;
43917                                         con->keep_alive = 0;
43918                                         con->response.keep_alive = 0;
43919 @@ -693,16 +695,16 @@
43920                                 con->http_status = 400;
43921                                 con->keep_alive = 0;
43922                                 con->response.keep_alive = 0;
43923 -                               
43924 +
43925                                 if (srv->srvconf.log_request_header_on_error) {
43926 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsds", 
43927 +                                       log_error_write(srv, __FILE__, __LINE__, "sbsds",
43928                                                 "CTL character in key", con->request.request, cur, *cur, "-> 400");
43929  
43930                                         log_error_write(srv, __FILE__, __LINE__, "Sb",
43931                                                 "request-header:\n",
43932                                                 con->request.request);
43933                                 }
43934 -                               
43935 +
43936                                 return 0;
43937                         default:
43938                                 /* ok */
43939 @@ -710,25 +712,25 @@
43940                         }
43941                 } else {
43942                         switch(*cur) {
43943 -                       case '\r': 
43944 +                       case '\r':
43945                                 if (con->parse_request->ptr[i+1] == '\n') {
43946                                         /* End of Headerline */
43947                                         con->parse_request->ptr[i] = '\0';
43948                                         con->parse_request->ptr[i+1] = '\0';
43949 -                                       
43950 +
43951                                         if (in_folding) {
43952                                                 if (!ds) {
43953                                                         /* 400 */
43954 -                                       
43955 +
43956                                                         if (srv->srvconf.log_request_header_on_error) {
43957                                                                 log_error_write(srv, __FILE__, __LINE__, "s", "WS at the start of first line -> 400");
43958 -                                                       
43959 +
43960                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
43961                                                                         "request-header:\n",
43962                                                                         con->request.request);
43963                                                         }
43964  
43965 -                                       
43966 +
43967                                                         con->http_status = 400;
43968                                                         con->keep_alive = 0;
43969                                                         con->response.keep_alive = 0;
43970 @@ -738,9 +740,9 @@
43971                                         } else {
43972                                                 int s_len;
43973                                                 key = con->parse_request->ptr + first;
43974 -                                       
43975 +
43976                                                 s_len = cur - value;
43977 -                                               
43978 +
43979                                                 if (s_len > 0) {
43980                                                         int cmp = 0;
43981                                                         if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
43982 @@ -748,86 +750,87 @@
43983                                                         }
43984                                                         buffer_copy_string_len(ds->key, key, key_len);
43985                                                         buffer_copy_string_len(ds->value, value, s_len);
43986 -                                                       
43987 -                                                       /* retreive values 
43988 -                                                        * 
43989 -                                                        * 
43990 +
43991 +                                                       /* retreive values
43992 +                                                        *
43993 +                                                        *
43994                                                          * the list of options is sorted to simplify the search
43995                                                          */
43996 -                                                       
43997 +
43998                                                         if (0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Connection")))) {
43999                                                                 array *vals;
44000                                                                 size_t vi;
44001 -                                                               
44002 +
44003                                                                 /* split on , */
44004 -                                                               
44005 +
44006                                                                 vals = srv->split_vals;
44007  
44008                                                                 array_reset(vals);
44009 -                                                               
44010 +
44011                                                                 http_request_split_value(vals, ds->value);
44012 -                                                               
44013 +
44014                                                                 for (vi = 0; vi < vals->used; vi++) {
44015                                                                         data_string *dsv = (data_string *)vals->data[vi];
44016 -                                                                       
44017 +
44018                                                                         if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("keep-alive"))) {
44019                                                                                 keep_alive_set = HTTP_CONNECTION_KEEPALIVE;
44020 -                                                                               
44021 +
44022                                                                                 break;
44023                                                                         } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("close"))) {
44024                                                                                 keep_alive_set = HTTP_CONNECTION_CLOSE;
44025 -                                                                               
44026 +
44027                                                                                 break;
44028                                                                         }
44029                                                                 }
44030 -                                                               
44031 +
44032                                                         } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Length")))) {
44033                                                                 char *err;
44034                                                                 unsigned long int r;
44035                                                                 size_t j;
44036 -                                                               
44037 +
44038                                                                 if (con_length_set) {
44039                                                                         con->http_status = 400;
44040                                                                         con->keep_alive = 0;
44041 -                                                                       
44042 +
44043                                                                         if (srv->srvconf.log_request_header_on_error) {
44044 -                                                                               log_error_write(srv, __FILE__, __LINE__, "s", 
44045 +                                                                               log_error_write(srv, __FILE__, __LINE__, "s",
44046                                                                                                 "duplicate Content-Length-header -> 400");
44047                                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44048                                                                                                 "request-header:\n",
44049                                                                                                 con->request.request);
44050                                                                         }
44051 +                                                                       ds->free((data_unset *) ds);
44052                                                                         return 0;
44053                                                                 }
44054 -                                                               
44055 +
44056                                                                 if (ds->value->used == 0) SEGFAULT();
44057 -                                                               
44058 +
44059                                                                 for (j = 0; j < ds->value->used - 1; j++) {
44060                                                                         char c = ds->value->ptr[j];
44061                                                                         if (!isdigit((unsigned char)c)) {
44062 -                                                                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
44063 +                                                                               log_error_write(srv, __FILE__, __LINE__, "sbs",
44064                                                                                                 "content-length broken:", ds->value, "-> 400");
44065 -                                                                               
44066 +
44067                                                                                 con->http_status = 400;
44068                                                                                 con->keep_alive = 0;
44069 -                                                                               
44070 +
44071                                                                                 array_insert_unique(con->request.headers, (data_unset *)ds);
44072                                                                                 return 0;
44073                                                                         }
44074                                                                 }
44075 -                                                               
44076 +
44077                                                                 r = strtoul(ds->value->ptr, &err, 10);
44078 -                                                               
44079 +
44080                                                                 if (*err == '\0') {
44081                                                                         con_length_set = 1;
44082                                                                         con->request.content_length = r;
44083                                                                 } else {
44084 -                                                                       log_error_write(srv, __FILE__, __LINE__, "sbs", 
44085 +                                                                       log_error_write(srv, __FILE__, __LINE__, "sbs",
44086                                                                                         "content-length broken:", ds->value, "-> 400");
44087 -                                                                       
44088 +
44089                                                                         con->http_status = 400;
44090                                                                         con->keep_alive = 0;
44091 -                                                                       
44092 +
44093                                                                         array_insert_unique(con->request.headers, (data_unset *)ds);
44094                                                                         return 0;
44095                                                                 }
44096 @@ -838,23 +841,24 @@
44097                                                                 } else {
44098                                                                         con->http_status = 400;
44099                                                                         con->keep_alive = 0;
44100 -                                                                       
44101 +
44102                                                                         if (srv->srvconf.log_request_header_on_error) {
44103 -                                                                               log_error_write(srv, __FILE__, __LINE__, "s", 
44104 +                                                                               log_error_write(srv, __FILE__, __LINE__, "s",
44105                                                                                                 "duplicate Content-Type-header -> 400");
44106                                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44107                                                                                                 "request-header:\n",
44108                                                                                                 con->request.request);
44109                                                                         }
44110 +                                                                       ds->free((data_unset *) ds);
44111                                                                         return 0;
44112                                                                 }
44113                                                         } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Expect")))) {
44114 -                                                               /* HTTP 2616 8.2.3 
44115 +                                                               /* HTTP 2616 8.2.3
44116                                                                  * Expect: 100-continue
44117 -                                                                * 
44118 +                                                                *
44119                                                                  *   -> (10.1.1)  100 (read content, process request, send final status-code)
44120                                                                  *   -> (10.4.18) 417 (close)
44121 -                                                                * 
44122 +                                                                *
44123                                                                  * (not handled at all yet, we always send 417 here)
44124                                                                  *
44125                                                                  * What has to be added ?
44126 @@ -863,10 +867,10 @@
44127                                                                  *    header
44128                                                                  *
44129                                                                  */
44130 -                                                               
44131 +
44132                                                                 con->http_status = 417;
44133                                                                 con->keep_alive = 0;
44134 -                                                               
44135 +
44136                                                                 array_insert_unique(con->request.headers, (data_unset *)ds);
44137                                                                 return 0;
44138                                                         } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Host")))) {
44139 @@ -875,14 +879,15 @@
44140                                                                 } else {
44141                                                                         con->http_status = 400;
44142                                                                         con->keep_alive = 0;
44143 -                                                                       
44144 +
44145                                                                         if (srv->srvconf.log_request_header_on_error) {
44146 -                                                                               log_error_write(srv, __FILE__, __LINE__, "s", 
44147 +                                                                               log_error_write(srv, __FILE__, __LINE__, "s",
44148                                                                                                 "duplicate Host-header -> 400");
44149                                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44150                                                                                                 "request-header:\n",
44151                                                                                                 con->request.request);
44152                                                                         }
44153 +                                                                       ds->free((data_unset *) ds);
44154                                                                         return 0;
44155                                                                 }
44156                                                         } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-Modified-Since")))) {
44157 @@ -897,14 +902,15 @@
44158                                                                 } else {
44159                                                                         con->http_status = 400;
44160                                                                         con->keep_alive = 0;
44161 -                                                                       
44162 +
44163                                                                         if (srv->srvconf.log_request_header_on_error) {
44164 -                                                                               log_error_write(srv, __FILE__, __LINE__, "s", 
44165 +                                                                               log_error_write(srv, __FILE__, __LINE__, "s",
44166                                                                                                 "duplicate If-Modified-Since header -> 400");
44167                                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44168                                                                                                 "request-header:\n",
44169                                                                                                 con->request.request);
44170                                                                         }
44171 +                                                                       ds->free((data_unset *) ds);
44172                                                                         return 0;
44173                                                                 }
44174                                                         } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-None-Match")))) {
44175 @@ -914,47 +920,49 @@
44176                                                                 } else {
44177                                                                         con->http_status = 400;
44178                                                                         con->keep_alive = 0;
44179 -                                                                       
44180 +
44181                                                                         if (srv->srvconf.log_request_header_on_error) {
44182 -                                                                               log_error_write(srv, __FILE__, __LINE__, "s", 
44183 +                                                                               log_error_write(srv, __FILE__, __LINE__, "s",
44184                                                                                                 "duplicate If-None-Match-header -> 400");
44185                                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44186                                                                                                 "request-header:\n",
44187                                                                                                 con->request.request);
44188                                                                         }
44189 +                                                                       ds->free((data_unset *) ds);
44190                                                                         return 0;
44191                                                                 }
44192                                                         } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Range")))) {
44193                                                                 if (!con->request.http_range) {
44194                                                                         /* bytes=.*-.* */
44195 -                                                               
44196 +
44197                                                                         if (0 == strncasecmp(ds->value->ptr, "bytes=", 6) &&
44198                                                                             NULL != strchr(ds->value->ptr+6, '-')) {
44199 -                                                                               
44200 +
44201                                                                                 /* if dup, only the first one will survive */
44202                                                                                 con->request.http_range = ds->value->ptr + 6;
44203                                                                         }
44204                                                                 } else {
44205                                                                         con->http_status = 400;
44206                                                                         con->keep_alive = 0;
44207 -                                                                       
44208 +
44209                                                                         if (srv->srvconf.log_request_header_on_error) {
44210 -                                                                               log_error_write(srv, __FILE__, __LINE__, "s", 
44211 +                                                                               log_error_write(srv, __FILE__, __LINE__, "s",
44212                                                                                                 "duplicate Range-header -> 400");
44213                                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44214                                                                                                 "request-header:\n",
44215                                                                                                 con->request.request);
44216                                                                         }
44217 +                                                                       ds->free((data_unset *) ds);
44218                                                                         return 0;
44219                                                                 }
44220                                                         }
44221 -                                                       
44222 +
44223                                                         array_insert_unique(con->request.headers, (data_unset *)ds);
44224                                                 } else {
44225                                                         /* empty header-fields are not allowed by HTTP-RFC, we just ignore them */
44226                                                 }
44227                                         }
44228 -                                       
44229 +
44230                                         i++;
44231                                         first = i+1;
44232                                         is_key = 1;
44233 @@ -963,10 +971,10 @@
44234                                         in_folding = 0;
44235                                 } else {
44236                                         if (srv->srvconf.log_request_header_on_error) {
44237 -                                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
44238 +                                               log_error_write(srv, __FILE__, __LINE__, "sbs",
44239                                                                 "CR without LF", con->request.request, "-> 400");
44240                                         }
44241 -                                       
44242 +
44243                                         con->http_status = 400;
44244                                         con->keep_alive = 0;
44245                                         con->response.keep_alive = 0;
44246 @@ -982,28 +990,28 @@
44247                         }
44248                 }
44249         }
44250 -       
44251 +
44252         con->header_len = i;
44253 -       
44254 +
44255         /* do some post-processing */
44256  
44257         if (con->request.http_version == HTTP_VERSION_1_1) {
44258                 if (keep_alive_set != HTTP_CONNECTION_CLOSE) {
44259                         /* no Connection-Header sent */
44260 -                       
44261 +
44262                         /* HTTP/1.1 -> keep-alive default TRUE */
44263                         con->keep_alive = 1;
44264                 } else {
44265                         con->keep_alive = 0;
44266                 }
44267 -               
44268 +
44269                 /* RFC 2616, 14.23 */
44270                 if (con->request.http_host == NULL ||
44271                     buffer_is_empty(con->request.http_host)) {
44272                         con->http_status = 400;
44273                         con->response.keep_alive = 0;
44274                         con->keep_alive = 0;
44275 -                       
44276 +
44277                         if (srv->srvconf.log_request_header_on_error) {
44278                                 log_error_write(srv, __FILE__, __LINE__, "s", "HTTP/1.1 but Host missing -> 400");
44279                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44280 @@ -1015,18 +1023,18 @@
44281         } else {
44282                 if (keep_alive_set == HTTP_CONNECTION_KEEPALIVE) {
44283                         /* no Connection-Header sent */
44284 -                       
44285 +
44286                         /* HTTP/1.0 -> keep-alive default FALSE  */
44287                         con->keep_alive = 1;
44288                 } else {
44289                         con->keep_alive = 0;
44290                 }
44291         }
44292 -       
44293 +
44294         /* check hostname field if it is set */
44295         if (NULL != con->request.http_host &&
44296             0 != request_check_hostname(srv, con, con->request.http_host)) {
44297 -               
44298 +
44299                 if (srv->srvconf.log_request_header_on_error) {
44300                         log_error_write(srv, __FILE__, __LINE__, "s",
44301                                         "Invalid Hostname -> 400");
44302 @@ -1038,7 +1046,7 @@
44303                 con->http_status = 400;
44304                 con->response.keep_alive = 0;
44305                 con->keep_alive = 0;
44306 -               
44307 +
44308                 return 0;
44309         }
44310  
44311 @@ -1048,7 +1056,7 @@
44312                 /* content-length is forbidden for those */
44313                 if (con_length_set && con->request.content_length != 0) {
44314                         /* content-length is missing */
44315 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
44316 +                       log_error_write(srv, __FILE__, __LINE__, "s",
44317                                         "GET/HEAD with content-length -> 400");
44318  
44319                         con->keep_alive = 0;
44320 @@ -1060,7 +1068,7 @@
44321                 /* content-length is required for them */
44322                 if (!con_length_set) {
44323                         /* content-length is missing */
44324 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
44325 +                       log_error_write(srv, __FILE__, __LINE__, "s",
44326                                         "POST-request, but content-length missing -> 411");
44327  
44328                         con->keep_alive = 0;
44329 @@ -1073,16 +1081,16 @@
44330                 /* the may have a content-length */
44331                 break;
44332         }
44333 -                       
44334 -       
44335 +
44336 +
44337         /* check if we have read post data */
44338         if (con_length_set) {
44339                 /* don't handle more the SSIZE_MAX bytes in content-length */
44340                 if (con->request.content_length > SSIZE_MAX) {
44341 -                       con->http_status = 413; 
44342 +                       con->http_status = 413;
44343                         con->keep_alive = 0;
44344  
44345 -                       log_error_write(srv, __FILE__, __LINE__, "sds", 
44346 +                       log_error_write(srv, __FILE__, __LINE__, "sds",
44347                                         "request-size too long:", con->request.content_length, "-> 413");
44348                         return 0;
44349                 }
44350 @@ -1090,25 +1098,25 @@
44351                 /* divide by 1024 as srvconf.max_request_size is in kBytes */
44352                 if (srv->srvconf.max_request_size != 0 &&
44353                     (con->request.content_length >> 10) > srv->srvconf.max_request_size) {
44354 -                       /* the request body itself is larger then 
44355 +                       /* the request body itself is larger then
44356                          * our our max_request_size
44357                          */
44358 -               
44359 +
44360                         con->http_status = 413;
44361                         con->keep_alive = 0;
44362 -               
44363 -                       log_error_write(srv, __FILE__, __LINE__, "sds", 
44364 +
44365 +                       log_error_write(srv, __FILE__, __LINE__, "sds",
44366                                         "request-size too long:", con->request.content_length, "-> 413");
44367                         return 0;
44368                 }
44369 -               
44370 -               
44371 +
44372 +
44373                 /* we have content */
44374                 if (con->request.content_length != 0) {
44375                         return 1;
44376                 }
44377         }
44378 -       
44379 +
44380         return 0;
44381  }
44382  
44383 @@ -1116,9 +1124,9 @@
44384         UNUSED(srv);
44385  
44386         if (con->request.request->used < 5) return 0;
44387 -       
44388 +
44389         if (0 == memcmp(con->request.request->ptr + con->request.request->used - 5, "\r\n\r\n", 4)) return 1;
44390         if (NULL != strstr(con->request.request->ptr, "\r\n\r\n")) return 1;
44391 -       
44392 +
44393         return 0;
44394  }
44395 --- lighttpd-1.4.11/src/response.c      2006-03-04 16:41:39.000000000 +0200
44396 +++ lighttpd-1.4.12/src/response.c      2006-07-11 22:07:52.000000000 +0300
44397 @@ -7,7 +7,6 @@
44398  #include <stdlib.h>
44399  #include <string.h>
44400  #include <time.h>
44401 -#include <unistd.h>
44402  #include <ctype.h>
44403  #include <assert.h>
44404  
44405 @@ -24,15 +23,17 @@
44406  #include "plugin.h"
44407  
44408  #include "sys-socket.h"
44409 +#include "sys-files.h"
44410 +#include "sys-strings.h"
44411  
44412  int http_response_write_header(server *srv, connection *con) {
44413         buffer *b;
44414         size_t i;
44415         int have_date = 0;
44416         int have_server = 0;
44417 -       
44418 +
44419         b = chunkqueue_get_prepend_buffer(con->write_queue);
44420 -       
44421 +
44422         if (con->request.http_version == HTTP_VERSION_1_1) {
44423                 BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
44424         } else {
44425 @@ -41,25 +42,26 @@
44426         buffer_append_long(b, con->http_status);
44427         BUFFER_APPEND_STRING_CONST(b, " ");
44428         buffer_append_string(b, get_http_status_name(con->http_status));
44429 -       
44430 +
44431         if (con->request.http_version != HTTP_VERSION_1_1 || con->keep_alive == 0) {
44432                 BUFFER_APPEND_STRING_CONST(b, "\r\nConnection: ");
44433                 buffer_append_string(b, con->keep_alive ? "keep-alive" : "close");
44434         }
44435 -       
44436 +
44437         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
44438                 BUFFER_APPEND_STRING_CONST(b, "\r\nTransfer-Encoding: chunked");
44439         }
44440 -       
44441 -       
44442 +
44443 +
44444         /* add all headers */
44445         for (i = 0; i < con->response.headers->used; i++) {
44446                 data_string *ds;
44447 -               
44448 +
44449                 ds = (data_string *)con->response.headers->data[i];
44450 -               
44451 +
44452                 if (ds->value->used && ds->key->used &&
44453 -                   0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1)) {
44454 +                   0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1) &&
44455 +                   0 != strcasecmp(ds->key->ptr, "X-Sendfile")) {
44456                         if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Date"))) have_date = 1;
44457                         if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Server"))) have_server = 1;
44458  
44459 @@ -68,28 +70,28 @@
44460                         BUFFER_APPEND_STRING_CONST(b, ": ");
44461                         buffer_append_string_buffer(b, ds->value);
44462  #if 0
44463 -                       log_error_write(srv, __FILE__, __LINE__, "bb", 
44464 +                       log_error_write(srv, __FILE__, __LINE__, "bb",
44465                                         ds->key, ds->value);
44466  #endif
44467                 }
44468         }
44469 -       
44470 +
44471         if (!have_date) {
44472                 /* HTTP/1.1 requires a Date: header */
44473                 BUFFER_APPEND_STRING_CONST(b, "\r\nDate: ");
44474 -       
44475 +
44476                 /* cache the generated timestamp */
44477                 if (srv->cur_ts != srv->last_generated_date_ts) {
44478                         buffer_prepare_copy(srv->ts_date_str, 255);
44479 -               
44480 -                       strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1, 
44481 +
44482 +                       strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1,
44483                                  "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(srv->cur_ts)));
44484 -                        
44485 +
44486                         srv->ts_date_str->used = strlen(srv->ts_date_str->ptr) + 1;
44487 -               
44488 +
44489                         srv->last_generated_date_ts = srv->cur_ts;
44490                 }
44491 -       
44492 +
44493                 buffer_append_string_buffer(b, srv->ts_date_str);
44494         }
44495  
44496 @@ -101,16 +103,16 @@
44497                         buffer_append_string_buffer(b, con->conf.server_tag);
44498                 }
44499         }
44500 -       
44501 +
44502         BUFFER_APPEND_STRING_CONST(b, "\r\n\r\n");
44503 -       
44504 -       
44505 +
44506 +
44507         con->bytes_header = b->used - 1;
44508 -       
44509 +
44510         if (con->conf.log_response_header) {
44511                 log_error_write(srv, __FILE__, __LINE__, "sSb", "Response-Header:", "\n", b);
44512         }
44513 -       
44514 +
44515         return 0;
44516  }
44517  
44518 @@ -118,71 +120,71 @@
44519  
44520  handler_t http_response_prepare(server *srv, connection *con) {
44521         handler_t r;
44522 -       
44523 -       /* looks like someone has already done a decision */
44524 -       if (con->mode == DIRECT && 
44525 +
44526 +       /* looks like someone has already made a decision */
44527 +       if (con->mode == DIRECT &&
44528             (con->http_status != 0 && con->http_status != 200)) {
44529                 /* remove a packets in the queue */
44530                 if (con->file_finished == 0) {
44531                         chunkqueue_reset(con->write_queue);
44532                 }
44533 -               
44534 +
44535                 return HANDLER_FINISHED;
44536         }
44537 -       
44538 +
44539         /* no decision yet, build conf->filename */
44540         if (con->mode == DIRECT && con->physical.path->used == 0) {
44541                 char *qstr;
44542  
44543 -               /* we only come here when we have the parse the full request again
44544 -                * 
44545 -                * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a 
44546 +               /* we only come here when we have to parse the full request again
44547 +                *
44548 +                * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
44549                  * problem here as mod_setenv might get called multiple times
44550                  *
44551                  * fastcgi-auth might lead to a COMEBACK too
44552                  * fastcgi again dead server too
44553                  *
44554                  * mod_compress might add headers twice too
44555 -                * 
44556 +                *
44557                  *  */
44558 -               
44559 +
44560                 if (con->conf.log_condition_handling) {
44561                         log_error_write(srv, __FILE__, __LINE__,  "s",  "run condition");
44562                 }
44563                 config_patch_connection(srv, con, COMP_SERVER_SOCKET); /* SERVERsocket */
44564 -               
44565 +
44566                 /**
44567                  * prepare strings
44568 -                * 
44569 -                * - uri.path_raw 
44570 +                *
44571 +                * - uri.path_raw
44572                  * - uri.path (secure)
44573                  * - uri.query
44574 -                * 
44575 +                *
44576                  */
44577 -               
44578 -               /** 
44579 +
44580 +               /**
44581                  * Name according to RFC 2396
44582 -                * 
44583 +                *
44584                  * - scheme
44585                  * - authority
44586                  * - path
44587                  * - query
44588 -                * 
44589 +                *
44590                  * (scheme)://(authority)(path)?(query)
44591 -                * 
44592 -                * 
44593 +                *
44594 +                *
44595                  */
44596 -       
44597 +
44598                 buffer_copy_string(con->uri.scheme, con->conf.is_ssl ? "https" : "http");
44599                 buffer_copy_string_buffer(con->uri.authority, con->request.http_host);
44600                 buffer_to_lower(con->uri.authority);
44601 -               
44602 +
44603                 config_patch_connection(srv, con, COMP_HTTP_HOST);      /* Host:        */
44604                 config_patch_connection(srv, con, COMP_HTTP_REMOTEIP);  /* Client-IP */
44605                 config_patch_connection(srv, con, COMP_HTTP_REFERER);   /* Referer:     */
44606                 config_patch_connection(srv, con, COMP_HTTP_USERAGENT); /* User-Agent:  */
44607                 config_patch_connection(srv, con, COMP_HTTP_COOKIE);    /* Cookie:  */
44608 -               
44609 +
44610                 /** extract query string from request.uri */
44611                 if (NULL != (qstr = strchr(con->request.uri->ptr, '?'))) {
44612                         buffer_copy_string    (con->uri.query, qstr + 1);
44613 @@ -200,22 +202,22 @@
44614                         log_error_write(srv, __FILE__, __LINE__,  "sb", "URI-path     : ", con->uri.path_raw);
44615                         log_error_write(srv, __FILE__, __LINE__,  "sb", "URI-query    : ", con->uri.query);
44616                 }
44617 -               
44618 +
44619                 /* disable keep-alive if requested */
44620 -               
44621 +
44622                 if (con->request_count > con->conf.max_keep_alive_requests) {
44623                         con->keep_alive = 0;
44624                 }
44625 -               
44626 -               
44627 +
44628 +
44629                 /**
44630 -                *  
44631 -                * call plugins 
44632 -                * 
44633 +                *
44634 +                * call plugins
44635 +                *
44636                  * - based on the raw URL
44637 -                * 
44638 +                *
44639                  */
44640 -               
44641 +
44642                 switch(r = plugins_call_handle_uri_raw(srv, con)) {
44643                 case HANDLER_GO_ON:
44644                         break;
44645 @@ -229,14 +231,14 @@
44646                         break;
44647                 }
44648  
44649 -               /* build filename 
44650 +               /* build filename
44651                  *
44652                  * - decode url-encodings  (e.g. %20 -> ' ')
44653                  * - remove path-modifiers (e.g. /../)
44654                  */
44655 -               
44656 -               
44657 -               
44658 +
44659 +
44660 +
44661                 if (con->request.http_method == HTTP_METHOD_OPTIONS &&
44662                     con->uri.path_raw->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
44663                         /* OPTIONS * ... */
44664 @@ -253,15 +255,20 @@
44665                 }
44666  
44667                 /**
44668 -                *  
44669 -                * call plugins 
44670 -                * 
44671 +                *
44672 +                * call plugins
44673 +                *
44674                  * - based on the clean URL
44675 -                * 
44676 +                *
44677                  */
44678 -               
44679 +
44680                 config_patch_connection(srv, con, COMP_HTTP_URL); /* HTTPurl */
44681 -               
44682 +
44683 +               /* do we have to downgrade to 1.0 ? */
44684 +               if (!con->conf.allow_http11) {
44685 +                       con->request.http_version = HTTP_VERSION_1_0;
44686 +               }
44687 +
44688                 switch(r = plugins_call_handle_uri_clean(srv, con)) {
44689                 case HANDLER_GO_ON:
44690                         break;
44691 @@ -274,11 +281,11 @@
44692                         log_error_write(srv, __FILE__, __LINE__, "");
44693                         break;
44694                 }
44695 -               
44696 +
44697                 if (con->request.http_method == HTTP_METHOD_OPTIONS &&
44698                     con->uri.path->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
44699 -                       /* option requests are handled directly without checking of the path */
44700 -               
44701 +                       /* option requests are handled directly without checking the path */
44702 +
44703                         response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
44704  
44705                         con->http_status = 200;
44706 @@ -288,46 +295,47 @@
44707                 }
44708  
44709                 /***
44710 -                * 
44711 -                * border 
44712 -                * 
44713 +                *
44714 +                * border
44715 +                *
44716                  * logical filename (URI) becomes a physical filename here
44717 -                * 
44718 -                * 
44719 -                * 
44720 +                *
44721 +                *
44722 +                *
44723                  */
44724 -               
44725 -               
44726 -               
44727 -               
44728 +
44729 +
44730 +
44731 +
44732                 /* 1. stat()
44733                  * ... ISREG() -> ok, go on
44734                  * ... ISDIR() -> index-file -> redirect
44735 -                * 
44736 -                * 2. pathinfo() 
44737 +                *
44738 +                * 2. pathinfo()
44739                  * ... ISREG()
44740 -                * 
44741 +                *
44742                  * 3. -> 404
44743 -                * 
44744 +                *
44745                  */
44746 -               
44747 +
44748                 /*
44749                  * SEARCH DOCUMENT ROOT
44750                  */
44751 -               
44752 +
44753                 /* set a default */
44754 -               
44755 +
44756                 buffer_copy_string_buffer(con->physical.doc_root, con->conf.document_root);
44757                 buffer_copy_string_buffer(con->physical.rel_path, con->uri.path);
44758 -               
44759 -#if defined(__WIN32) || defined(__CYGWIN__)
44760 -               /* strip dots from the end and spaces
44761 +
44762 +               filename_unix2local(con->physical.rel_path);
44763 +#if defined(_WIN32) || defined(__CYGWIN__)
44764 +               /* strip dots and spaces from the end
44765                  *
44766                  * windows/dos handle those filenames as the same file
44767                  *
44768                  * foo == foo. == foo..... == "foo...   " == "foo..  ./"
44769                  *
44770 -                * This will affect in some cases PATHINFO
44771 +                * This will affect PATHINFO in some cases
44772                  *
44773                  * on native windows we could prepend the filename with \\?\ to circumvent
44774                  * this behaviour. I have no idea how to push this through cygwin
44775 @@ -377,36 +385,41 @@
44776                         log_error_write(srv, __FILE__, __LINE__, "");
44777                         break;
44778                 }
44779 -               
44780 -               /* MacOS X and Windows can't distiguish between upper and lower-case 
44781 -                * 
44782 -                * convert to lower-case
44783 +
44784 +               /* The default Mac OS X and Windows filesystems can't distiguish between
44785 +                * upper- and lowercase, so convert to lowercase
44786                  */
44787                 if (con->conf.force_lowercase_filenames) {
44788                         buffer_to_lower(con->physical.rel_path);
44789                 }
44790  
44791 -               /* the docroot plugins might set the servername, if they don't we take http-host */
44792 +               /* the docroot plugins might set the servername; if they don't we take http-host */
44793                 if (buffer_is_empty(con->server_name)) {
44794                         buffer_copy_string_buffer(con->server_name, con->uri.authority);
44795                 }
44796 -               
44797 -               /** 
44798 -                * create physical filename 
44799 +
44800 +               /**
44801 +                * create physical filename
44802                  * -> physical.path = docroot + rel_path
44803 -                * 
44804 +                *
44805                  */
44806 -               
44807 +
44808                 buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
44809 -               BUFFER_APPEND_SLASH(con->physical.path);
44810 +               PATHNAME_APPEND_SLASH(con->physical.path);
44811                 buffer_copy_string_buffer(con->physical.basedir, con->physical.path);
44812                 if (con->physical.rel_path->used &&
44813 -                   con->physical.rel_path->ptr[0] == '/') {
44814 +                   con->physical.rel_path->ptr[0] == DIR_SEPERATOR) {
44815                         buffer_append_string_len(con->physical.path, con->physical.rel_path->ptr + 1, con->physical.rel_path->used - 2);
44816                 } else {
44817                         buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
44818                 }
44819  
44820 +        /* win32: directories can't have a trailing slash */
44821 +        if (con->physical.path->ptr[con->physical.path->used - 2] == DIR_SEPERATOR) {
44822 +            con->physical.path->ptr[con->physical.path->used - 2] = '\0';
44823 +            con->physical.path->used--;
44824 +        }
44825 +
44826                 if (con->conf.log_request_handling) {
44827                         log_error_write(srv, __FILE__, __LINE__,  "s",  "-- after doc_root");
44828                         log_error_write(srv, __FILE__, __LINE__,  "sb", "Doc-Root     :", con->physical.doc_root);
44829 @@ -426,7 +439,7 @@
44830                         log_error_write(srv, __FILE__, __LINE__, "");
44831                         break;
44832                 }
44833 -               
44834 +
44835                 if (con->conf.log_request_handling) {
44836                         log_error_write(srv, __FILE__, __LINE__,  "s",  "-- logical -> physical");
44837                         log_error_write(srv, __FILE__, __LINE__,  "sb", "Doc-Root     :", con->physical.doc_root);
44838 @@ -434,38 +447,38 @@
44839                         log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
44840                 }
44841         }
44842 -       
44843 -       /* 
44844 -        * Noone catched away the file from normal path of execution yet (like mod_access)
44845 -        * 
44846 +
44847 +       /*
44848 +        * No one took the file away from the normal path of execution yet (like mod_access)
44849 +        *
44850          * Go on and check of the file exists at all
44851          */
44852 -       
44853 +
44854         if (con->mode == DIRECT) {
44855                 char *slash = NULL;
44856                 char *pathinfo = NULL;
44857                 int found = 0;
44858                 stat_cache_entry *sce = NULL;
44859 -               
44860 +
44861                 if (con->conf.log_request_handling) {
44862                         log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling physical path");
44863                         log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
44864                 }
44865 -               
44866 +
44867                 if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
44868                         /* file exists */
44869 -                       
44870 +
44871                         if (con->conf.log_request_handling) {
44872                                 log_error_write(srv, __FILE__, __LINE__,  "s",  "-- file found");
44873                                 log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
44874                         }
44875 -                       
44876 +
44877                         if (S_ISDIR(sce->st.st_mode)) {
44878 -                               if (con->physical.path->ptr[con->physical.path->used - 2] != '/') {
44879 +                               if (con->uri.path->ptr[con->uri.path->used - 2] != '/') {
44880                                         /* redirect to .../ */
44881 -                                       
44882 +
44883                                         http_response_redirect_to_directory(srv, con);
44884 -                                       
44885 +
44886                                         return HANDLER_FINISHED;
44887                                 }
44888                         } else if (!S_ISREG(sce->st.st_mode)) {
44889 @@ -477,12 +490,12 @@
44890                         switch (errno) {
44891                         case EACCES:
44892                                 con->http_status = 403;
44893 -       
44894 +
44895                                 if (con->conf.log_request_handling) {
44896                                         log_error_write(srv, __FILE__, __LINE__,  "s",  "-- access denied");
44897                                         log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
44898                                 }
44899 -                       
44900 +
44901                                 buffer_reset(con->physical.path);
44902                                 return HANDLER_FINISHED;
44903                         case ENOENT:
44904 @@ -499,77 +512,77 @@
44905                                 /* PATH_INFO ! :) */
44906                                 break;
44907                         default:
44908 -                               /* we have no idea what happend. let's tell the user so. */
44909 +                               /* we have no idea what happened, so tell the user. */
44910                                 con->http_status = 500;
44911                                 buffer_reset(con->physical.path);
44912 -                               
44913 +
44914                                 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
44915                                                 "file not found ... or so: ", strerror(errno),
44916                                                 con->uri.path,
44917                                                 "->", con->physical.path);
44918 -                               
44919 +
44920                                 return HANDLER_FINISHED;
44921                         }
44922 -                       
44923 +
44924                         /* not found, perhaps PATHINFO */
44925 -                       
44926 +
44927                         buffer_copy_string_buffer(srv->tmp_buf, con->physical.path);
44928 -                       
44929 +
44930                         do {
44931                                 struct stat st;
44932 -                               
44933 +
44934                                 if (slash) {
44935                                         buffer_copy_string_len(con->physical.path, srv->tmp_buf->ptr, slash - srv->tmp_buf->ptr);
44936                                 } else {
44937                                         buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
44938                                 }
44939 -                               
44940 +
44941                                 if (0 == stat(con->physical.path->ptr, &(st)) &&
44942                                     S_ISREG(st.st_mode)) {
44943                                         found = 1;
44944                                         break;
44945                                 }
44946 -                               
44947 +
44948                                 if (pathinfo != NULL) {
44949                                         *pathinfo = '\0';
44950                                 }
44951                                 slash = strrchr(srv->tmp_buf->ptr, '/');
44952 -                               
44953 +
44954                                 if (pathinfo != NULL) {
44955                                         /* restore '/' */
44956                                         *pathinfo = '/';
44957                                 }
44958 -                               
44959 +
44960                                 if (slash) pathinfo = slash;
44961                         } while ((found == 0) && (slash != NULL) && (slash - srv->tmp_buf->ptr > con->physical.basedir->used - 2));
44962 -                       
44963 +
44964                         if (found == 0) {
44965 -                               /* no it really doesn't exists */
44966 +                               /* no, it really doesn't exists */
44967                                 con->http_status = 404;
44968 -                               
44969 +
44970                                 if (con->conf.log_file_not_found) {
44971                                         log_error_write(srv, __FILE__, __LINE__, "sbsb",
44972                                                         "file not found:", con->uri.path,
44973                                                         "->", con->physical.path);
44974                                 }
44975 -                               
44976 +
44977                                 buffer_reset(con->physical.path);
44978 -                               
44979 +
44980                                 return HANDLER_FINISHED;
44981                         }
44982 -                       
44983 +
44984                         /* we have a PATHINFO */
44985                         if (pathinfo) {
44986                                 buffer_copy_string(con->request.pathinfo, pathinfo);
44987 -                               
44988 +
44989                                 /*
44990                                  * shorten uri.path
44991                                  */
44992 -                               
44993 +
44994                                 con->uri.path->used -= strlen(pathinfo);
44995                                 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
44996                         }
44997 -                       
44998 +
44999                         if (con->conf.log_request_handling) {
45000                                 log_error_write(srv, __FILE__, __LINE__,  "s",  "-- after pathinfo check");
45001                                 log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
45002 @@ -577,12 +590,12 @@
45003                                 log_error_write(srv, __FILE__, __LINE__,  "sb", "Pathinfo     :", con->request.pathinfo);
45004                         }
45005                 }
45006 -               
45007 +
45008                 if (con->conf.log_request_handling) {
45009                         log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling subrequest");
45010                         log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
45011                 }
45012 -               
45013 +
45014                 /* call the handlers */
45015                 switch(r = plugins_call_handle_subrequest_start(srv, con)) {
45016                 case HANDLER_GO_ON:
45017 @@ -593,32 +606,32 @@
45018                         if (con->conf.log_request_handling) {
45019                                 log_error_write(srv, __FILE__, __LINE__,  "s",  "-- subrequest finished");
45020                         }
45021 -                       
45022 -                       /* something strange happend */
45023 +
45024 +                       /* something strange happened */
45025                         return r;
45026                 }
45027 -               
45028 -               /* if we are still here, no one wanted the file, status 403 is ok I think */
45029 -               
45030 +
45031 +               /* if we are still here, no one wanted the file; status 403 is ok I think */
45032 +
45033                 if (con->mode == DIRECT) {
45034                         con->http_status = 403;
45035 -                       
45036 +
45037                         return HANDLER_FINISHED;
45038                 }
45039 -               
45040 +
45041         }
45042 -       
45043 +
45044         switch(r = plugins_call_handle_subrequest(srv, con)) {
45045         case HANDLER_GO_ON:
45046 -               /* request was not handled, looks like we are done */
45047 +               /* request was not handled; looks like we are done */
45048                 return HANDLER_FINISHED;
45049         case HANDLER_FINISHED:
45050                 /* request is finished */
45051         default:
45052 -               /* something strange happend */
45053 +               /* something strange happened */
45054                 return r;
45055         }
45056 -       
45057 +
45058         /* can't happen */
45059         return HANDLER_COMEBACK;
45060  }
45061 --- lighttpd-1.4.11/src/server.c        2006-03-04 19:12:17.000000000 +0200
45062 +++ lighttpd-1.4.12/src/server.c        2006-07-11 22:07:53.000000000 +0300
45063 @@ -1,11 +1,9 @@
45064  #include <sys/types.h>
45065 -#include <sys/time.h>
45066  #include <sys/stat.h>
45067  
45068  #include <string.h>
45069  #include <errno.h>
45070  #include <fcntl.h>
45071 -#include <unistd.h>
45072  #include <stdlib.h>
45073  #include <time.h>
45074  #include <signal.h>
45075 @@ -29,9 +27,14 @@
45076  #include "plugin.h"
45077  #include "joblist.h"
45078  #include "network_backends.h"
45079 -
45080 +#ifdef _WIN32
45081 +/* use local getopt implementation */
45082 +# undef HAVE_GETOPT_H
45083 +#endif
45084  #ifdef HAVE_GETOPT_H
45085  #include <getopt.h>
45086 +#else
45087 +#include "getopt.h"
45088  #endif
45089  
45090  #ifdef HAVE_VALGRIND_VALGRIND_H
45091 @@ -60,8 +63,16 @@
45092  /* #define USE_ALARM */
45093  #endif
45094  
45095 +#ifdef _WIN32
45096 +#undef HAVE_SIGNAL
45097 +#endif
45098 +
45099 +#include "sys-files.h"
45100 +#include "sys-process.h"
45101 +
45102  static volatile sig_atomic_t srv_shutdown = 0;
45103  static volatile sig_atomic_t graceful_shutdown = 0;
45104 +static volatile sig_atomic_t graceful_restart = 0;
45105  static volatile sig_atomic_t handle_sig_alarm = 1;
45106  static volatile sig_atomic_t handle_sig_hup = 0;
45107  
45108 @@ -72,9 +83,9 @@
45109  
45110         switch (sig) {
45111         case SIGTERM: srv_shutdown = 1; break;
45112 -       case SIGINT: 
45113 +       case SIGINT:
45114              if (graceful_shutdown) srv_shutdown = 1;
45115 -            else graceful_shutdown = 1; 
45116 +            else graceful_shutdown = 1;
45117  
45118              break;
45119         case SIGALRM: handle_sig_alarm = 1; break;
45120 @@ -86,9 +97,9 @@
45121  static void signal_handler(int sig) {
45122         switch (sig) {
45123         case SIGTERM: srv_shutdown = 1; break;
45124 -       case SIGINT: 
45125 +       case SIGINT:
45126              if (graceful_shutdown) srv_shutdown = 1;
45127 -            else graceful_shutdown = 1; 
45128 +            else graceful_shutdown = 1;
45129  
45130              break;
45131         case SIGALRM: handle_sig_alarm = 1; break;
45132 @@ -110,25 +121,26 @@
45133         signal(SIGTSTP, SIG_IGN);
45134  #endif
45135         if (0 != fork()) exit(0);
45136 -       
45137 +
45138         if (-1 == setsid()) exit(0);
45139  
45140         signal(SIGHUP, SIG_IGN);
45141  
45142         if (0 != fork()) exit(0);
45143 -       
45144 +
45145         if (0 != chdir("/")) exit(0);
45146  }
45147  #endif
45148  
45149  static server *server_init(void) {
45150         int i;
45151 -       
45152 +
45153         server *srv = calloc(1, sizeof(*srv));
45154         assert(srv);
45155 +    srv->max_fds = 1024;
45156  #define CLEAN(x) \
45157         srv->x = buffer_init();
45158 -       
45159 +
45160         CLEAN(response_header);
45161         CLEAN(parse_full_path);
45162         CLEAN(ts_debug_str);
45163 @@ -138,7 +150,7 @@
45164         CLEAN(tmp_buf);
45165         srv->empty_string = buffer_init_string("");
45166         CLEAN(cond_check_buf);
45167 -       
45168 +
45169         CLEAN(srvconf.errorlog_file);
45170         CLEAN(srvconf.groupname);
45171         CLEAN(srvconf.username);
45172 @@ -146,58 +158,58 @@
45173         CLEAN(srvconf.bindhost);
45174         CLEAN(srvconf.event_handler);
45175         CLEAN(srvconf.pid_file);
45176 -       
45177 +
45178         CLEAN(tmp_chunk_len);
45179  #undef CLEAN
45180 -       
45181 +
45182  #define CLEAN(x) \
45183         srv->x = array_init();
45184 -       
45185 +
45186         CLEAN(config_context);
45187         CLEAN(config_touched);
45188         CLEAN(status);
45189  #undef CLEAN
45190 -       
45191 +
45192         for (i = 0; i < FILE_CACHE_MAX; i++) {
45193                 srv->mtime_cache[i].str = buffer_init();
45194         }
45195 -       
45196 +
45197         srv->cur_ts = time(NULL);
45198         srv->startup_ts = srv->cur_ts;
45199 -       
45200 +
45201         srv->conns = calloc(1, sizeof(*srv->conns));
45202         assert(srv->conns);
45203 -       
45204 +
45205         srv->joblist = calloc(1, sizeof(*srv->joblist));
45206         assert(srv->joblist);
45207 -       
45208 +
45209         srv->fdwaitqueue = calloc(1, sizeof(*srv->fdwaitqueue));
45210         assert(srv->fdwaitqueue);
45211 -       
45212 +
45213         srv->srvconf.modules = array_init();
45214         srv->srvconf.modules_dir = buffer_init_string(LIBRARY_DIR);
45215         srv->srvconf.network_backend = buffer_init();
45216         srv->srvconf.upload_tempdirs = array_init();
45217 -       
45218 +
45219         /* use syslog */
45220         srv->errorlog_fd = -1;
45221         srv->errorlog_mode = ERRORLOG_STDERR;
45222  
45223         srv->split_vals = array_init();
45224 -       
45225 +
45226         return srv;
45227  }
45228  
45229  static void server_free(server *srv) {
45230         size_t i;
45231 -       
45232 +
45233         for (i = 0; i < FILE_CACHE_MAX; i++) {
45234                 buffer_free(srv->mtime_cache[i].str);
45235         }
45236 -       
45237 +
45238  #define CLEAN(x) \
45239         buffer_free(srv->x);
45240 -       
45241 +
45242         CLEAN(response_header);
45243         CLEAN(parse_full_path);
45244         CLEAN(ts_debug_str);
45245 @@ -207,7 +219,7 @@
45246         CLEAN(tmp_buf);
45247         CLEAN(empty_string);
45248         CLEAN(cond_check_buf);
45249 -       
45250 +
45251         CLEAN(srvconf.errorlog_file);
45252         CLEAN(srvconf.groupname);
45253         CLEAN(srvconf.username);
45254 @@ -217,7 +229,7 @@
45255         CLEAN(srvconf.pid_file);
45256         CLEAN(srvconf.modules_dir);
45257         CLEAN(srvconf.network_backend);
45258 -       
45259 +
45260         CLEAN(tmp_chunk_len);
45261  #undef CLEAN
45262  
45263 @@ -225,15 +237,15 @@
45264         fdevent_unregister(srv->ev, srv->fd);
45265  #endif
45266         fdevent_free(srv->ev);
45267 -       
45268 +
45269         free(srv->conns);
45270 -       
45271 +
45272         if (srv->config_storage) {
45273                 for (i = 0; i < srv->config_context->used; i++) {
45274                         specific_config *s = srv->config_storage[i];
45275  
45276                         if (!s) continue;
45277 -                       
45278 +
45279                         buffer_free(s->document_root);
45280                         buffer_free(s->server_name);
45281                         buffer_free(s->server_tag);
45282 @@ -242,32 +254,32 @@
45283                         buffer_free(s->error_handler);
45284                         buffer_free(s->errorfile_prefix);
45285                         array_free(s->mimetypes);
45286 -                       
45287 +
45288                         free(s);
45289                 }
45290                 free(srv->config_storage);
45291                 srv->config_storage = NULL;
45292         }
45293 -       
45294 +
45295  #define CLEAN(x) \
45296         array_free(srv->x);
45297 -       
45298 +
45299         CLEAN(config_context);
45300         CLEAN(config_touched);
45301         CLEAN(status);
45302         CLEAN(srvconf.upload_tempdirs);
45303  #undef CLEAN
45304 -       
45305 +
45306         joblist_free(srv, srv->joblist);
45307         fdwaitqueue_free(srv, srv->fdwaitqueue);
45308 -       
45309 +
45310         if (srv->stat_cache) {
45311                 stat_cache_free(srv->stat_cache);
45312         }
45313  
45314         array_free(srv->srvconf.modules);
45315         array_free(srv->split_vals);
45316 -       
45317 +
45318         free(srv);
45319  }
45320  
45321 @@ -281,14 +293,12 @@
45322  " - a light and fast webserver\n" \
45323  "Build-Date: " __DATE__ " " __TIME__ "\n";
45324  ;
45325 -#undef TEXT_SSL        
45326 +#undef TEXT_SSL
45327         write(STDOUT_FILENO, b, strlen(b));
45328  }
45329  
45330  static void show_features (void) {
45331 -  show_version();
45332 -  printf("\nEvent Handlers:\n\n%s",
45333 -
45334 +  const char *s = ""
45335  #ifdef USE_SELECT
45336        "\t+ select (generic)\n"
45337  #else
45338 @@ -355,11 +365,6 @@
45339  #else
45340        "\t- crypt support\n"
45341  #endif
45342 -#ifdef USE_PAM
45343 -      "\t+ PAM support\n"
45344 -#else
45345 -      "\t- PAM support\n"
45346 -#endif
45347  #ifdef USE_OPENSSL
45348        "\t+ SSL Support\n"
45349  #else
45350 @@ -371,9 +376,9 @@
45351        "\t- PCRE support\n"
45352  #endif
45353  #ifdef HAVE_MYSQL
45354 -      "\t+ mySQL support\n"
45355 +      "\t+ MySQL support\n"
45356  #else
45357 -      "\t- mySQL support\n"
45358 +      "\t- MySQL support\n"
45359  #endif
45360  #if defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER)
45361        "\t+ LDAP support\n"
45362 @@ -410,8 +415,11 @@
45363  #else
45364        "\t- GDBM support\n"
45365  #endif
45366 -      "\n"
45367 -      );
45368 +      "\n";
45369 +
45370 +  show_version();
45371 +
45372 +  printf("\nEvent Handlers:\n\n%s", s);
45373  }
45374  
45375  static void show_help (void) {
45376 @@ -433,12 +441,12 @@
45377  " -h         show this help\n" \
45378  "\n"
45379  ;
45380 -#undef TEXT_SSL        
45381 +#undef TEXT_SSL
45382  #undef TEXT_IPV6
45383         write(STDOUT_FILENO, b, strlen(b));
45384  }
45385  
45386 -int main (int argc, char **argv) {
45387 +int main (int argc, char **argv, char **envp) {
45388         server *srv = NULL;
45389         int print_config = 0;
45390         int test_config = 0;
45391 @@ -447,33 +455,37 @@
45392         int num_childs = 0;
45393         int pid_fd = -1, fd;
45394         size_t i;
45395 +#ifdef _WIN32
45396 +       char *optarg = NULL;
45397 +#endif
45398 +
45399  #ifdef HAVE_SIGACTION
45400         struct sigaction act;
45401  #endif
45402  #ifdef HAVE_GETRLIMIT
45403         struct rlimit rlim;
45404  #endif
45405 -       
45406 +
45407  #ifdef USE_ALARM
45408         struct itimerval interval;
45409 -       
45410 +
45411         interval.it_interval.tv_sec = 1;
45412         interval.it_interval.tv_usec = 0;
45413         interval.it_value.tv_sec = 1;
45414         interval.it_value.tv_usec = 0;
45415  #endif
45416 -       
45417 -       
45418 +
45419 +
45420         /* for nice %b handling in strfime() */
45421         setlocale(LC_TIME, "C");
45422 -       
45423 +
45424         if (NULL == (srv = server_init())) {
45425                 fprintf(stderr, "did this really happen?\n");
45426                 return -1;
45427         }
45428 -       
45429 +
45430         /* init structs done */
45431 -       
45432 +
45433         srv->srvconf.port = 0;
45434  #ifdef HAVE_GETUID
45435         i_am_root = (getuid() == 0);
45436 @@ -481,14 +493,19 @@
45437         i_am_root = 0;
45438  #endif
45439         srv->srvconf.dont_daemonize = 0;
45440 -       
45441 +
45442         while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) {
45443                 switch(o) {
45444 -               case 'f': 
45445 -                       if (config_read(srv, optarg)) { 
45446 +               case 'f':
45447 +#ifdef _WIN32
45448 +                       /* evil HACK for windows, optarg is not set */
45449 +                       optarg = argv[optind-1];
45450 +#endif
45451 +                       if (config_read(srv, optarg)) {
45452                                 server_free(srv);
45453                                 return -1;
45454                         }
45455 +
45456                         break;
45457                 case 'm':
45458                         buffer_copy_string(srv->srvconf.modules_dir, optarg);
45459 @@ -497,23 +514,23 @@
45460                 case 't': test_config = 1; break;
45461                 case 'D': srv->srvconf.dont_daemonize = 1; break;
45462                 case 'v': show_version(); return 0;
45463 -               case 'V': show_features(); return 0;          
45464 +               case 'V': show_features(); return 0;
45465                 case 'h': show_help(); return 0;
45466 -               default: 
45467 +               default:
45468                         show_help();
45469                         server_free(srv);
45470                         return -1;
45471                 }
45472         }
45473 -       
45474 +
45475         if (!srv->config_storage) {
45476                 log_error_write(srv, __FILE__, __LINE__, "s",
45477                                 "No configuration available. Try using -f option.");
45478 -               
45479 +
45480                 server_free(srv);
45481                 return -1;
45482         }
45483 -       
45484 +
45485         if (print_config) {
45486                 data_unset *dc = srv->config_context->data[0];
45487                 if (dc) {
45488 @@ -533,7 +550,7 @@
45489                 server_free(srv);
45490                 return 0;
45491         }
45492 -       
45493 +
45494         /* close stdin and stdout, as they are not needed */
45495         /* move stdin to /dev/null */
45496         if (-1 != (fd = open("/dev/null", O_RDONLY))) {
45497 @@ -541,54 +558,55 @@
45498                 dup2(fd, STDIN_FILENO);
45499                 close(fd);
45500         }
45501 -       
45502 +
45503         /* move stdout to /dev/null */
45504         if (-1 != (fd = open("/dev/null", O_WRONLY))) {
45505                 close(STDOUT_FILENO);
45506                 dup2(fd, STDOUT_FILENO);
45507                 close(fd);
45508         }
45509 -       
45510 +
45511         if (0 != config_set_defaults(srv)) {
45512 -               log_error_write(srv, __FILE__, __LINE__, "s", 
45513 +               log_error_write(srv, __FILE__, __LINE__, "s",
45514                                 "setting default values failed");
45515                 server_free(srv);
45516                 return -1;
45517         }
45518 -       
45519 +
45520         /* UID handling */
45521  #ifdef HAVE_GETUID
45522         if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
45523                 /* we are setuid-root */
45524 -               
45525 -               log_error_write(srv, __FILE__, __LINE__, "s", 
45526 +
45527 +               log_error_write(srv, __FILE__, __LINE__, "s",
45528                                 "Are you nuts ? Don't apply a SUID bit to this binary");
45529 -               
45530 +
45531                 server_free(srv);
45532                 return -1;
45533         }
45534  #endif
45535 -       
45536 +
45537         /* check document-root */
45538         if (srv->config_storage[0]->document_root->used <= 1) {
45539 -               log_error_write(srv, __FILE__, __LINE__, "s", 
45540 +               log_error_write(srv, __FILE__, __LINE__, "s",
45541                                 "document-root is not set\n");
45542 -               
45543 +
45544                 server_free(srv);
45545 -               
45546 +
45547                 return -1;
45548         }
45549 -       
45550 +
45551         if (plugins_load(srv)) {
45552                 log_error_write(srv, __FILE__, __LINE__, "s",
45553                                 "loading plugins finally failed");
45554 -               
45555 +
45556                 plugins_free(srv);
45557                 server_free(srv);
45558 -               
45559 +
45560                 return -1;
45561         }
45562 -       
45563 +
45564 +#ifndef _WIN32
45565         /* open pid file BEFORE chroot */
45566         if (srv->srvconf.pid_file->used) {
45567                 if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
45568 @@ -598,18 +616,18 @@
45569                                         "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
45570                                 return -1;
45571                         }
45572 -                       
45573 +
45574                         if (0 != stat(srv->srvconf.pid_file->ptr, &st)) {
45575                                 log_error_write(srv, __FILE__, __LINE__, "sbs",
45576                                                 "stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno));
45577                         }
45578 -                       
45579 +
45580                         if (!S_ISREG(st.st_mode)) {
45581                                 log_error_write(srv, __FILE__, __LINE__, "sb",
45582                                                 "pid-file exists and isn't regular file:", srv->srvconf.pid_file);
45583                                 return -1;
45584                         }
45585 -                       
45586 +
45587                         if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
45588                                 log_error_write(srv, __FILE__, __LINE__, "sbs",
45589                                                 "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
45590 @@ -617,13 +635,14 @@
45591                         }
45592                 }
45593         }
45594 -
45595 +#endif
45596         if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45597                 /* select limits itself
45598                  *
45599                  * as it is a hard limit and will lead to a segfault we add some safety
45600                  * */
45601 -               srv->max_fds = FD_SETSIZE - 200;
45602 +        fprintf(stderr, "%s.%d: max parallel connections: %d\r\n", __FILE__, __LINE__, FD_SETSIZE);
45603 +               srv->max_fds = FD_SETSIZE - 4;
45604         } else {
45605                 srv->max_fds = 4096;
45606         }
45607 @@ -636,7 +655,7 @@
45608  #ifdef HAVE_VALGRIND_VALGRIND_H
45609                 if (RUNNING_ON_VALGRIND) use_rlimit = 0;
45610  #endif
45611 -               
45612 +
45613  #ifdef HAVE_GETRLIMIT
45614                 if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
45615                         log_error_write(srv, __FILE__, __LINE__,
45616 @@ -644,13 +663,13 @@
45617                                         strerror(errno));
45618                         return -1;
45619                 }
45620 -               
45621 +
45622                 if (use_rlimit && srv->srvconf.max_fds) {
45623                         /* set rlimits */
45624 -                       
45625 +
45626                         rlim.rlim_cur = srv->srvconf.max_fds;
45627                         rlim.rlim_max = srv->srvconf.max_fds;
45628 -                       
45629 +
45630                         if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
45631                                 log_error_write(srv, __FILE__, __LINE__,
45632                                                 "ss", "couldn't set 'max filedescriptors'",
45633 @@ -659,7 +678,7 @@
45634                         }
45635                 }
45636  
45637 -               /* #372: solaris need some fds extra for devpoll */     
45638 +               /* #372: solaris need some fds extra for devpoll */
45639                 if (rlim.rlim_cur > 10) rlim.rlim_cur -= 10;
45640  
45641                 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45642 @@ -677,33 +696,33 @@
45643                 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45644                         /* don't raise the limit above FD_SET_SIZE */
45645                         if (srv->max_fds > FD_SETSIZE - 200) {
45646 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
45647 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
45648                                                 "can't raise max filedescriptors above",  FD_SETSIZE - 200,
45649                                                 "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
45650                                 return -1;
45651                         }
45652                 }
45653  
45654 -               
45655 +
45656  #ifdef HAVE_PWD_H
45657                 /* set user and group */
45658                 if (srv->srvconf.username->used) {
45659                         if (NULL == (pwd = getpwnam(srv->srvconf.username->ptr))) {
45660 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
45661 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
45662                                                 "can't find username", srv->srvconf.username);
45663                                 return -1;
45664                         }
45665 -                       
45666 +
45667                         if (pwd->pw_uid == 0) {
45668                                 log_error_write(srv, __FILE__, __LINE__, "s",
45669                                                 "I will not set uid to 0\n");
45670                                 return -1;
45671                         }
45672                 }
45673 -               
45674 +
45675                 if (srv->srvconf.groupname->used) {
45676                         if (NULL == (grp = getgrnam(srv->srvconf.groupname->ptr))) {
45677 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
45678 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
45679                                         "can't find groupname", srv->srvconf.groupname);
45680                                 return -1;
45681                         }
45682 @@ -713,15 +732,15 @@
45683                                 return -1;
45684                         }
45685                 }
45686 -#endif         
45687 +#endif
45688                 /* we need root-perms for port < 1024 */
45689                 if (0 != network_init(srv)) {
45690                         plugins_free(srv);
45691                         server_free(srv);
45692 -                       
45693 +
45694                         return -1;
45695                 }
45696 -#ifdef HAVE_CHROOT     
45697 +#ifdef HAVE_CHROOT
45698                 if (srv->srvconf.changeroot->used) {
45699                         tzset();
45700  
45701 @@ -761,7 +780,7 @@
45702                 }
45703  
45704                 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45705 -                       srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
45706 +                       srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 4 ? rlim.rlim_cur : FD_SETSIZE - 4;
45707                 } else {
45708                         srv->max_fds = rlim.rlim_cur;
45709                 }
45710 @@ -775,18 +794,18 @@
45711  #endif
45712                 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45713                         /* don't raise the limit above FD_SET_SIZE */
45714 -                       if (srv->max_fds > FD_SETSIZE - 200) {
45715 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
45716 -                                               "can't raise max filedescriptors above",  FD_SETSIZE - 200,
45717 +                       if (srv->max_fds > FD_SETSIZE - 4) {
45718 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
45719 +                                               "can't raise max filedescriptors above",  FD_SETSIZE - 4,
45720                                                 "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
45721                                 return -1;
45722                         }
45723                 }
45724 -               
45725 +
45726                 if (0 != network_init(srv)) {
45727                         plugins_free(srv);
45728                         server_free(srv);
45729 -                       
45730 +
45731                         return -1;
45732                 }
45733         }
45734 @@ -802,25 +821,27 @@
45735                 /* or use the default */
45736                 srv->max_conns = srv->max_fds;
45737         }
45738 -       
45739 +
45740         if (HANDLER_GO_ON != plugins_call_init(srv)) {
45741                 log_error_write(srv, __FILE__, __LINE__, "s", "Initialization of plugins failed. Going down.");
45742 -               
45743 +
45744                 plugins_free(srv);
45745                 network_close(srv);
45746                 server_free(srv);
45747 -               
45748 +
45749                 return -1;
45750         }
45751  
45752 -#ifdef HAVE_FORK       
45753 +#ifdef HAVE_FORK
45754         /* network is up, let's deamonize ourself */
45755         if (srv->srvconf.dont_daemonize == 0) daemonize();
45756  #endif
45757  
45758 +#ifdef HAVE_PWD_H
45759         srv->gid = getgid();
45760         srv->uid = getuid();
45761 -       
45762 +#endif
45763 +
45764         /* write pid file */
45765         if (pid_fd != -1) {
45766                 buffer_copy_long(srv->tmp_buf, getpid());
45767 @@ -829,17 +850,17 @@
45768                 close(pid_fd);
45769                 pid_fd = -1;
45770         }
45771 -       
45772 +
45773         if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) {
45774                 log_error_write(srv, __FILE__, __LINE__, "s", "Configuration of plugins failed. Going down.");
45775 -               
45776 +
45777                 plugins_free(srv);
45778                 network_close(srv);
45779                 server_free(srv);
45780 -               
45781 +
45782                 return -1;
45783         }
45784 -       
45785 +
45786         /* dump unused config-keys */
45787         for (i = 0; i < srv->config_context->used; i++) {
45788                 array *config = ((data_config *)srv->config_context->data[i])->value;
45789 @@ -847,43 +868,42 @@
45790  
45791                 for (j = 0; config && j < config->used; j++) {
45792                         data_unset *du = config->data[j];
45793 -                       
45794 +
45795                         /* all var.* is known as user defined variable */
45796                         if (strncmp(du->key->ptr, "var.", sizeof("var.") - 1) == 0) {
45797                                 continue;
45798                         }
45799  
45800                         if (NULL == array_get_element(srv->config_touched, du->key->ptr)) {
45801 -                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
45802 +                               log_error_write(srv, __FILE__, __LINE__, "sbs",
45803                                                 "WARNING: unknown config-key:",
45804                                                 du->key,
45805                                                 "(ignored)");
45806                         }
45807                 }
45808         }
45809 -       
45810 +
45811         if (srv->config_deprecated) {
45812 -               log_error_write(srv, __FILE__, __LINE__, "s", 
45813 +               log_error_write(srv, __FILE__, __LINE__, "s",
45814                                 "Configuration contains deprecated keys. Going down.");
45815 -               
45816 +
45817                 plugins_free(srv);
45818                 network_close(srv);
45819                 server_free(srv);
45820 -               
45821 +
45822                 return -1;
45823         }
45824 -       
45825 +
45826         if (-1 == log_error_open(srv)) {
45827 -               log_error_write(srv, __FILE__, __LINE__, "s", 
45828 +               log_error_write(srv, __FILE__, __LINE__, "s",
45829                                 "opening errorlog failed, dying");
45830 -               
45831 +
45832                 plugins_free(srv);
45833                 network_close(srv);
45834                 server_free(srv);
45835                 return -1;
45836         }
45837 -       
45838 -       
45839 +
45840  #ifdef HAVE_SIGACTION
45841         memset(&act, 0, sizeof(act));
45842         act.sa_handler = SIG_IGN;
45843 @@ -903,7 +923,7 @@
45844         sigaction(SIGHUP,  &act, NULL);
45845         sigaction(SIGALRM, &act, NULL);
45846         sigaction(SIGCHLD, &act, NULL);
45847 -       
45848 +
45849  #elif defined(HAVE_SIGNAL)
45850         /* ignore the SIGPIPE from sendfile() */
45851         signal(SIGPIPE, SIG_IGN);
45852 @@ -914,20 +934,20 @@
45853         signal(SIGCHLD,  signal_handler);
45854         signal(SIGINT,  signal_handler);
45855  #endif
45856 -       
45857 +
45858  #ifdef USE_ALARM
45859         signal(SIGALRM, signal_handler);
45860 -       
45861 +
45862         /* setup periodic timer (1 second) */
45863         if (setitimer(ITIMER_REAL, &interval, NULL)) {
45864                 log_error_write(srv, __FILE__, __LINE__, "s", "setting timer failed");
45865                 return -1;
45866         }
45867 -       
45868 +
45869         getitimer(ITIMER_REAL, &interval);
45870  #endif
45871  
45872 -#ifdef HAVE_FORK       
45873 +#ifdef HAVE_FORK
45874         /* start watcher and workers */
45875         num_childs = srv->srvconf.max_worker;
45876         if (num_childs > 0) {
45877 @@ -957,13 +977,13 @@
45878         }
45879  #endif
45880  
45881 -       if (NULL == (srv->ev = fdevent_init(srv->max_fds + 1, srv->event_handler))) {
45882 +       if (NULL == (srv->ev = fdevent_init(/*srv->max_fds + 1*/ 4096, srv->event_handler))) {
45883                 log_error_write(srv, __FILE__, __LINE__,
45884                                 "s", "fdevent_init failed");
45885                 return -1;
45886         }
45887 -       /* 
45888 -        * kqueue() is called here, select resets its internals, 
45889 +       /*
45890 +        * kqueue() is called here, select resets its internals,
45891          * all server sockets get their handlers
45892          *
45893          * */
45894 @@ -971,7 +991,7 @@
45895                 plugins_free(srv);
45896                 network_close(srv);
45897                 server_free(srv);
45898 -               
45899 +
45900                 return -1;
45901         }
45902  
45903 @@ -986,7 +1006,7 @@
45904         /* setup FAM */
45905         if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) {
45906                 if (0 != FAMOpen2(srv->stat_cache->fam, "lighttpd")) {
45907 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
45908 +                       log_error_write(srv, __FILE__, __LINE__, "s",
45909                                          "could not open a fam connection, dieing.");
45910                         return -1;
45911                 }
45912 @@ -1018,16 +1038,40 @@
45913                 int n;
45914                 size_t ndx;
45915                 time_t min_ts;
45916 -               
45917 +
45918                 if (handle_sig_hup) {
45919                         handler_t r;
45920 -                       
45921 +
45922                         /* reset notification */
45923                         handle_sig_hup = 0;
45924 -                       
45925 -                       
45926 +
45927 +#if 0
45928 +                               pid_t pid;
45929 +
45930 +                       /* send the old process into a graceful-shutdown and start a
45931 +                        * new process right away
45932 +                        *
45933 +                        * BUGS:
45934 +                        * - if webserver is running on port < 1024 (e.g. 80, 433)
45935 +                        *   we don't have the permissions to bind to that port anymore
45936 +                        *
45937 +                        *
45938 +                        *  */
45939 +                       if (0 == (pid = fork())) {
45940 +                               execve(argv[0], argv, envp);
45941 +
45942 +                               exit(-1);
45943 +                       } else if (pid == -1) {
45944 +
45945 +                       } else {
45946 +                               /* parent */
45947 +
45948 +                               graceful_shutdown = 1; /* shutdown without killing running connections */
45949 +                               graceful_restart = 1;  /* don't delete pid file */
45950 +                       }
45951 +#else
45952                         /* cycle logfiles */
45953 -                       
45954 +
45955                         switch(r = plugins_call_handle_sighup(srv)) {
45956                         case HANDLER_GO_ON:
45957                                 break;
45958 @@ -1035,30 +1079,31 @@
45959                                 log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r);
45960                                 break;
45961                         }
45962 -                       
45963 +
45964                         if (-1 == log_error_cycle(srv)) {
45965                                 log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying");
45966 -                               
45967 +
45968                                 return -1;
45969                         }
45970 +#endif
45971                 }
45972 -               
45973 +
45974                 if (handle_sig_alarm) {
45975                         /* a new second */
45976 -                       
45977 +
45978  #ifdef USE_ALARM
45979                         /* reset notification */
45980                         handle_sig_alarm = 0;
45981  #endif
45982 -                       
45983 +
45984                         /* get current time */
45985                         min_ts = time(NULL);
45986 -                       
45987 +
45988                         if (min_ts != srv->cur_ts) {
45989                                 int cs = 0;
45990                                 connections *conns = srv->conns;
45991                                 handler_t r;
45992 -                               
45993 +
45994                                 switch(r = plugins_call_handle_trigger(srv)) {
45995                                 case HANDLER_GO_ON:
45996                                         break;
45997 @@ -1069,21 +1114,21 @@
45998                                         log_error_write(srv, __FILE__, __LINE__, "d", r);
45999                                         break;
46000                                 }
46001 -                               
46002 +
46003                                 /* trigger waitpid */
46004                                 srv->cur_ts = min_ts;
46005 -                       
46006 -                               /* cleanup stat-cache */        
46007 +
46008 +                               /* cleanup stat-cache */
46009                                 stat_cache_trigger_cleanup(srv);
46010                                 /**
46011 -                                * check all connections for timeouts 
46012 -                                * 
46013 +                                * check all connections for timeouts
46014 +                                *
46015                                  */
46016                                 for (ndx = 0; ndx < conns->used; ndx++) {
46017                                         int changed = 0;
46018                                         connection *con;
46019                                         int t_diff;
46020 -                                       
46021 +
46022                                         con = conns->ptr[ndx];
46023  
46024                                         if (con->state == CON_STATE_READ ||
46025 @@ -1092,7 +1137,7 @@
46026                                                         if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {
46027                                                                 /* time - out */
46028  #if 0
46029 -                                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
46030 +                                                               log_error_write(srv, __FILE__, __LINE__, "sd",
46031                                                                                 "connection closed - read-timeout:", con->fd);
46032  #endif
46033                                                                 connection_set_state(srv, con, CON_STATE_ERROR);
46034 @@ -1102,7 +1147,7 @@
46035                                                         if (srv->cur_ts - con->read_idle_ts > con->conf.max_keep_alive_idle) {
46036                                                                 /* time - out */
46037  #if 0
46038 -                                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
46039 +                                                               log_error_write(srv, __FILE__, __LINE__, "sd",
46040                                                                                 "connection closed - read-timeout:", con->fd);
46041  #endif
46042                                                                 connection_set_state(srv, con, CON_STATE_ERROR);
46043 @@ -1110,20 +1155,20 @@
46044                                                         }
46045                                                 }
46046                                         }
46047 -                                       
46048 +
46049                                         if ((con->state == CON_STATE_WRITE) &&
46050 -                                           (con->write_request_ts != 0)) { 
46051 +                                           (con->write_request_ts != 0)) {
46052  #if 0
46053                                                 if (srv->cur_ts - con->write_request_ts > 60) {
46054 -                                                       log_error_write(srv, __FILE__, __LINE__, "sdd", 
46055 +                                                       log_error_write(srv, __FILE__, __LINE__, "sdd",
46056                                                                         "connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts);
46057                                                 }
46058  #endif
46059 -                                               
46060 +
46061                                                 if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {
46062                                                         /* time - out */
46063  #if 1
46064 -                                                       log_error_write(srv, __FILE__, __LINE__, "sbsosds", 
46065 +                                                       log_error_write(srv, __FILE__, __LINE__, "sbsosds",
46066                                                                         "NOTE: a request for",
46067                                                                         con->request.uri,
46068                                                                         "timed out after writing",
46069 @@ -1138,35 +1183,35 @@
46070                                         }
46071                                         /* we don't like div by zero */
46072                                         if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1;
46073 -       
46074 -                                       if (con->traffic_limit_reached && 
46075 -                                           (con->conf.kbytes_per_second == 0 || 
46076 +
46077 +                                       if (con->traffic_limit_reached &&
46078 +                                           (con->conf.kbytes_per_second == 0 ||
46079                                              ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) {
46080                                                 /* enable connection again */
46081                                                 con->traffic_limit_reached = 0;
46082 -                                               
46083 +
46084                                                 changed = 1;
46085                                         }
46086 -                                       
46087 +
46088                                         if (changed) {
46089                                                 connection_state_machine(srv, con);
46090                                         }
46091                                         con->bytes_written_cur_second = 0;
46092                                         *(con->conf.global_bytes_per_second_cnt_ptr) = 0;
46093 -                                       
46094 +
46095  #if 0
46096                                         if (cs == 0) {
46097                                                 fprintf(stderr, "connection-state: ");
46098                                                 cs = 1;
46099                                         }
46100 -                                       
46101 +
46102                                         fprintf(stderr, "c[%d,%d]: %s ",
46103                                                 con->fd,
46104                                                 con->fcgi.fd,
46105                                                 connection_get_state(con->state));
46106  #endif
46107                                 }
46108 -                               
46109 +
46110                                 if (cs == 1) fprintf(stderr, "\n");
46111                         }
46112                 }
46113 @@ -1181,18 +1226,18 @@
46114                                         server_socket *srv_socket = srv->srv_sockets.ptr[i];
46115                                         fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
46116                                 }
46117 -                       
46118 +
46119                                 log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again");
46120 -                       
46121 +
46122                                 srv->sockets_disabled = 0;
46123                         }
46124                 } else {
46125                         if ((srv->cur_fds + srv->want_fds > srv->max_fds * 0.9) || /* out of fds */
46126                             (srv->conns->used > srv->max_conns) || /* out of connections */
46127 -                           (graceful_shutdown)) { /* graceful_shutdown */ 
46128 +                           (graceful_shutdown)) { /* graceful_shutdown */
46129  
46130                                 /* disable server-fds */
46131 -                       
46132 +
46133                                 for (i = 0; i < srv->srv_sockets.used; i++) {
46134                                         server_socket *srv_socket = srv->srv_sockets.ptr[i];
46135                                         fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
46136 @@ -1211,7 +1256,7 @@
46137                                                 /* network_close() will cleanup after us */
46138                                         }
46139                                 }
46140 -               
46141 +
46142                                 if (graceful_shutdown) {
46143                                         log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started");
46144                                 } else if (srv->conns->used > srv->max_conns) {
46145 @@ -1219,7 +1264,7 @@
46146                                 } else {
46147                                         log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds");
46148                                 }
46149 -                       
46150 +
46151                                 srv->sockets_disabled = 1;
46152                         }
46153                 }
46154 @@ -1229,16 +1274,16 @@
46155                          * we are ready to terminate without harming anyone */
46156                         srv_shutdown = 1;
46157                 }
46158 -               
46159 +
46160                 /* we still have some fds to share */
46161 -               if (srv->want_fds) { 
46162 +               if (srv->want_fds) {
46163                         /* check the fdwaitqueue for waiting fds */
46164                         int free_fds = srv->max_fds - srv->cur_fds - 16;
46165                         connection *con;
46166 -                       
46167 +
46168                         for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) {
46169                                 connection_state_machine(srv, con);
46170 -                               
46171 +
46172                                 srv->want_fds--;
46173                         }
46174                 }
46175 @@ -1249,27 +1294,27 @@
46176                         int fd_ndx;
46177  #if 0
46178                         if (n > 0) {
46179 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
46180 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
46181                                                 "polls:", n);
46182                         }
46183 -#endif                 
46184 +#endif
46185                         fd_ndx = -1;
46186                         do {
46187                                 fdevent_handler handler;
46188                                 void *context;
46189                                 handler_t r;
46190 -                               
46191 +
46192                                 fd_ndx  = fdevent_event_next_fdndx (srv->ev, fd_ndx);
46193                                 revents = fdevent_event_get_revent (srv->ev, fd_ndx);
46194                                 fd      = fdevent_event_get_fd     (srv->ev, fd_ndx);
46195                                 handler = fdevent_get_handler(srv->ev, fd);
46196                                 context = fdevent_get_context(srv->ev, fd);
46197 -                               
46198 +
46199                                 /* connection_handle_fdevent needs a joblist_append */
46200  #if 0
46201 -                               log_error_write(srv, __FILE__, __LINE__, "sdd", 
46202 +                               log_error_write(srv, __FILE__, __LINE__, "sdd",
46203                                                 "event for", fd, revents);
46204 -#endif                         
46205 +#endif
46206                                 switch (r = (*handler)(srv, context, revents)) {
46207                                 case HANDLER_FINISHED:
46208                                 case HANDLER_GO_ON:
46209 @@ -1286,17 +1331,17 @@
46210                                 }
46211                         } while (--n > 0);
46212                 } else if (n < 0 && errno != EINTR) {
46213 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
46214 -                                       "fdevent_poll failed:", 
46215 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
46216 +                                       "fdevent_poll failed:",
46217                                         strerror(errno));
46218                 }
46219 -               
46220 +
46221                 for (ndx = 0; ndx < srv->joblist->used; ndx++) {
46222                         connection *con = srv->joblist->ptr[ndx];
46223                         handler_t r;
46224 -                       
46225 +
46226                         connection_state_machine(srv, con);
46227 -                       
46228 +
46229                         switch(r = plugins_call_handle_joblist(srv, con)) {
46230                         case HANDLER_FINISHED:
46231                         case HANDLER_GO_ON:
46232 @@ -1305,32 +1350,33 @@
46233                                 log_error_write(srv, __FILE__, __LINE__, "d", r);
46234                                 break;
46235                         }
46236 -                       
46237 +
46238                         con->in_joblist = 0;
46239                 }
46240 -               
46241 +
46242                 srv->joblist->used = 0;
46243         }
46244 -       
46245 -       if (srv->srvconf.pid_file->used &&
46246 +
46247 +       if (0 == graceful_restart &&
46248 +           srv->srvconf.pid_file->used &&
46249             srv->srvconf.changeroot->used == 0) {
46250                 if (0 != unlink(srv->srvconf.pid_file->ptr)) {
46251                         if (errno != EACCES && errno != EPERM) {
46252 -                               log_error_write(srv, __FILE__, __LINE__, "sbds", 
46253 -                                               "unlink failed for:", 
46254 +                               log_error_write(srv, __FILE__, __LINE__, "sbds",
46255 +                                               "unlink failed for:",
46256                                                 srv->srvconf.pid_file,
46257                                                 errno,
46258                                                 strerror(errno));
46259                         }
46260                 }
46261         }
46262 -       
46263 +
46264         /* clean-up */
46265         log_error_close(srv);
46266         network_close(srv);
46267         connections_free(srv);
46268         plugins_free(srv);
46269         server_free(srv);
46270 -       
46271 +
46272         return 0;
46273  }
46274 --- lighttpd-1.4.11/src/settings.h      2005-08-11 01:26:41.000000000 +0300
46275 +++ lighttpd-1.4.12/src/settings.h      2006-07-11 22:07:53.000000000 +0300
46276 @@ -9,24 +9,24 @@
46277  /**
46278   * max size of a buffer which will just be reset
46279   * to ->used = 0 instead of really freeing the buffer
46280 - * 
46281 + *
46282   * 64kB (no real reason, just a guess)
46283   */
46284  #define BUFFER_MAX_REUSE_SIZE  (4 * 1024)
46285  
46286  /**
46287   * max size of the HTTP request header
46288 - * 
46289 + *
46290   * 32k should be enough for everything (just a guess)
46291 - * 
46292 + *
46293   */
46294  #define MAX_HTTP_REQUEST_HEADER  (32 * 1024)
46295  
46296 -typedef enum { HANDLER_UNSET, 
46297 -               HANDLER_GO_ON, 
46298 +typedef enum { HANDLER_UNSET,
46299 +               HANDLER_GO_ON,
46300                 HANDLER_FINISHED,
46301 -               HANDLER_COMEBACK, 
46302 -               HANDLER_WAIT_FOR_EVENT, 
46303 +               HANDLER_COMEBACK,
46304 +               HANDLER_WAIT_FOR_EVENT,
46305                 HANDLER_ERROR,
46306                 HANDLER_WAIT_FOR_FD
46307  } handler_t;
46308 --- lighttpd-1.4.11/src/spawn-fcgi.c    2006-03-07 14:18:10.000000000 +0200
46309 +++ lighttpd-1.4.12/src/spawn-fcgi.c    2006-07-11 22:07:53.000000000 +0300
46310 @@ -1,19 +1,16 @@
46311  #include <sys/types.h>
46312 -#include <sys/time.h>
46313  #include <sys/stat.h>
46314  
46315  #include <stdlib.h>
46316  #include <string.h>
46317  #include <errno.h>
46318  #include <stdio.h>
46319 -#include <unistd.h>
46320  #include <fcntl.h>
46321 -
46322 +#include <time.h>
46323  #ifdef HAVE_CONFIG_H
46324  #include "config.h"
46325  #endif
46326  
46327 -
46328  #ifdef HAVE_PWD_H
46329  #include <grp.h>
46330  #include <pwd.h>
46331 @@ -30,6 +27,7 @@
46332  #endif
46333  
46334  #include "sys-socket.h"
46335 +#include "sys-files.h"
46336  
46337  #ifdef HAVE_SYS_WAIT_H
46338  #include <sys/wait.h>
46339 @@ -45,28 +43,28 @@
46340         int fcgi_fd;
46341         int socket_type, status;
46342         struct timeval tv = { 0, 100 * 1000 };
46343 -       
46344 +
46345         struct sockaddr_un fcgi_addr_un;
46346         struct sockaddr_in fcgi_addr_in;
46347         struct sockaddr *fcgi_addr;
46348 -       
46349 +
46350         socklen_t servlen;
46351 -       
46352 +
46353         if (child_count < 2) {
46354                 child_count = 5;
46355         }
46356 -       
46357 +
46358         if (child_count > 256) {
46359                 child_count = 256;
46360         }
46361 -       
46362 -       
46363 +
46364 +
46365         if (unixsocket) {
46366                 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
46367 -               
46368 +
46369                 fcgi_addr_un.sun_family = AF_UNIX;
46370                 strcpy(fcgi_addr_un.sun_path, unixsocket);
46371 -               
46372 +
46373  #ifdef SUN_LEN
46374                 servlen = SUN_LEN(&fcgi_addr_un);
46375  #else
46376 @@ -84,50 +82,50 @@
46377                  }
46378                 fcgi_addr_in.sin_port = htons(port);
46379                 servlen = sizeof(fcgi_addr_in);
46380 -               
46381 +
46382                 socket_type = AF_INET;
46383                 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
46384         }
46385 -       
46386 +
46387         if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
46388 -               fprintf(stderr, "%s.%d\n", 
46389 +               fprintf(stderr, "%s.%d\n",
46390                         __FILE__, __LINE__);
46391                 return -1;
46392         }
46393 -       
46394 +
46395         if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
46396                 /* server is not up, spawn in  */
46397                 pid_t child;
46398                 int val;
46399 -               
46400 +
46401                 if (unixsocket) unlink(unixsocket);
46402 -               
46403 +
46404                 close(fcgi_fd);
46405 -               
46406 +
46407                 /* reopen socket */
46408                 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
46409 -                       fprintf(stderr, "%s.%d\n", 
46410 +                       fprintf(stderr, "%s.%d\n",
46411                                 __FILE__, __LINE__);
46412                         return -1;
46413                 }
46414  
46415                 val = 1;
46416                 if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
46417 -                       fprintf(stderr, "%s.%d\n", 
46418 +                       fprintf(stderr, "%s.%d\n",
46419                                 __FILE__, __LINE__);
46420                         return -1;
46421                 }
46422  
46423                 /* create socket */
46424                 if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
46425 -                       fprintf(stderr, "%s.%d: bind failed: %s\n", 
46426 +                       fprintf(stderr, "%s.%d: bind failed: %s\n",
46427                                 __FILE__, __LINE__,
46428                                 strerror(errno));
46429                         return -1;
46430                 }
46431 -               
46432 +
46433                 if (-1 == listen(fcgi_fd, 1024)) {
46434 -                       fprintf(stderr, "%s.%d: fd = -1\n", 
46435 +                       fprintf(stderr, "%s.%d: fd = -1\n",
46436                                 __FILE__, __LINE__);
46437                         return -1;
46438                 }
46439 @@ -137,42 +135,45 @@
46440                 } else {
46441                         child = 0;
46442                 }
46443 -               
46444 +
46445                 switch (child) {
46446                 case 0: {
46447                         char cgi_childs[64];
46448                         char *b;
46449 -                       
46450 +
46451                         int i = 0;
46452 -                       
46453 +
46454 +                       /* loose control terminal */
46455 +                       setsid();
46456 +
46457                         /* is save as we limit to 256 childs */
46458                         sprintf(cgi_childs, "PHP_FCGI_CHILDREN=%d", child_count);
46459 -                       
46460 +
46461                         if(fcgi_fd != FCGI_LISTENSOCK_FILENO) {
46462                                 close(FCGI_LISTENSOCK_FILENO);
46463                                 dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
46464                                 close(fcgi_fd);
46465                         }
46466 -                       
46467 +
46468                         /* we don't need the client socket */
46469                         for (i = 3; i < 256; i++) {
46470                                 close(i);
46471                         }
46472 -                       
46473 +
46474                         /* create environment */
46475 -                       
46476 +
46477                         putenv(cgi_childs);
46478 -                       
46479 +
46480                         /* fork and replace shell */
46481                         b = malloc(strlen("exec ") + strlen(appPath) + 1);
46482                         strcpy(b, "exec ");
46483                         strcat(b, appPath);
46484 -                       
46485 +
46486                         /* exec the cgi */
46487                         execl("/bin/sh", "sh", "-c", b, NULL);
46488 -                       
46489 +
46490                         exit(errno);
46491 -                       
46492 +
46493                         break;
46494                 }
46495                 case -1:
46496 @@ -180,47 +181,47 @@
46497                         break;
46498                 default:
46499                         /* father */
46500 -                       
46501 +
46502                         /* wait */
46503                         select(0, NULL, NULL, NULL, &tv);
46504 -                       
46505 +
46506                         switch (waitpid(child, &status, WNOHANG)) {
46507                         case 0:
46508 -                               fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n", 
46509 +                               fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n",
46510                                         __FILE__, __LINE__,
46511                                         child);
46512 -                               
46513 +
46514                                 /* write pid file */
46515                                 if (pid_fd != -1) {
46516                                         /* assume a 32bit pid_t */
46517                                         char pidbuf[12];
46518 -                                       
46519 +
46520                                         snprintf(pidbuf, sizeof(pidbuf) - 1, "%d", child);
46521 -                                       
46522 +
46523                                         write(pid_fd, pidbuf, strlen(pidbuf));
46524                                         close(pid_fd);
46525                                         pid_fd = -1;
46526                                 }
46527 -                               
46528 +
46529                                 break;
46530                         case -1:
46531                                 break;
46532                         default:
46533                                 if (WIFEXITED(status)) {
46534 -                                       fprintf(stderr, "%s.%d: child exited with: %d, %s\n", 
46535 +                                       fprintf(stderr, "%s.%d: child exited with: %d, %s\n",
46536                                                 __FILE__, __LINE__,
46537                                                 WEXITSTATUS(status), strerror(WEXITSTATUS(status)));
46538                                 } else if (WIFSIGNALED(status)) {
46539 -                                       fprintf(stderr, "%s.%d: child signaled: %d\n", 
46540 +                                       fprintf(stderr, "%s.%d: child signaled: %d\n",
46541                                                 __FILE__, __LINE__,
46542                                                 WTERMSIG(status));
46543                                 } else {
46544 -                                       fprintf(stderr, "%s.%d: child died somehow: %d\n", 
46545 +                                       fprintf(stderr, "%s.%d: child died somehow: %d\n",
46546                                                 __FILE__, __LINE__,
46547                                                 status);
46548                                 }
46549                         }
46550 -                               
46551 +
46552                         break;
46553                 }
46554         } else {
46555 @@ -228,16 +229,16 @@
46556                         __FILE__, __LINE__);
46557                 return -1;
46558         }
46559 -       
46560 +
46561         close(fcgi_fd);
46562 -       
46563 +
46564         return 0;
46565  }
46566  
46567  
46568  void show_version () {
46569         char *b = "spawn-fcgi" "-" PACKAGE_VERSION \
46570 -" - spawns fastcgi processes\n" 
46571 +" - spawns fastcgi processes\n"
46572  ;
46573         write(1, b, strlen(b));
46574  }
46575 @@ -265,7 +266,7 @@
46576  
46577  
46578  int main(int argc, char **argv) {
46579 -       char *fcgi_app = NULL, *changeroot = NULL, *username = NULL, 
46580 +       char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
46581                 *groupname = NULL, *unixsocket = NULL, *pid_file = NULL,
46582                  *addr = NULL;
46583         unsigned short port = 0;
46584 @@ -273,9 +274,9 @@
46585         int i_am_root, o;
46586         int pid_fd = -1;
46587         int nofork = 0;
46588 -       
46589 +
46590         i_am_root = (getuid() == 0);
46591 -       
46592 +
46593         while(-1 != (o = getopt(argc, argv, "c:f:g:hna:p:u:vC:s:P:"))) {
46594                 switch(o) {
46595                 case 'f': fcgi_app = optarg; break;
46596 @@ -290,137 +291,137 @@
46597                 case 'P': pid_file = optarg; /* PID file */ break;
46598                 case 'v': show_version(); return 0;
46599                 case 'h': show_help(); return 0;
46600 -               default: 
46601 +               default:
46602                         show_help();
46603                         return -1;
46604                 }
46605         }
46606 -       
46607 +
46608         if (fcgi_app == NULL || (port == 0 && unixsocket == NULL)) {
46609                 show_help();
46610                 return -1;
46611         }
46612 -           
46613 +
46614         if (unixsocket && port) {
46615 -               fprintf(stderr, "%s.%d: %s\n", 
46616 +               fprintf(stderr, "%s.%d: %s\n",
46617                         __FILE__, __LINE__,
46618                         "either a unix domain socket or a tcp-port, but not both\n");
46619 -               
46620 +
46621                 return -1;
46622         }
46623 -       
46624 +
46625         if (unixsocket && strlen(unixsocket) > UNIX_PATH_MAX - 1) {
46626 -               fprintf(stderr, "%s.%d: %s\n", 
46627 +               fprintf(stderr, "%s.%d: %s\n",
46628                         __FILE__, __LINE__,
46629                         "path of the unix socket is too long\n");
46630 -               
46631 +
46632                 return -1;
46633         }
46634  
46635         /* UID handling */
46636         if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
46637                 /* we are setuid-root */
46638 -               
46639 -               fprintf(stderr, "%s.%d: %s\n", 
46640 +
46641 +               fprintf(stderr, "%s.%d: %s\n",
46642                         __FILE__, __LINE__,
46643                         "Are you nuts ? Don't apply a SUID bit to this binary\n");
46644 -               
46645 +
46646                 return -1;
46647         }
46648 -       
46649 -       if (pid_file && 
46650 +
46651 +       if (pid_file &&
46652             (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)))) {
46653                 struct stat st;
46654                 if (errno != EEXIST) {
46655 -                       fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n", 
46656 +                       fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
46657                                 __FILE__, __LINE__,
46658                                 pid_file, strerror(errno));
46659 -                       
46660 +
46661                         return -1;
46662                 }
46663 -               
46664 +
46665                 /* ok, file exists */
46666 -               
46667 +
46668                 if (0 != stat(pid_file, &st)) {
46669 -                       fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n", 
46670 +                       fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n",
46671                                 __FILE__, __LINE__,
46672                                 pid_file, strerror(errno));
46673 -                       
46674 +
46675                         return -1;
46676                 }
46677 -               
46678 +
46679                 /* is it a regular file ? */
46680 -               
46681 +
46682                 if (!S_ISREG(st.st_mode)) {
46683 -                       fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n", 
46684 +                       fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n",
46685                                 __FILE__, __LINE__,
46686                                 pid_file);
46687 -                       
46688 +
46689                         return -1;
46690                 }
46691 -               
46692 +
46693                 if (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
46694 -                       fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n", 
46695 +                       fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
46696                                 __FILE__, __LINE__,
46697                                 pid_file, strerror(errno));
46698 -                       
46699 +
46700                         return -1;
46701                 }
46702         }
46703 -       
46704 +
46705         if (i_am_root) {
46706                 struct group *grp = NULL;
46707                 struct passwd *pwd = NULL;
46708 -               
46709 +
46710                 /* set user and group */
46711 -               
46712 +
46713                 if (username) {
46714                         if (NULL == (pwd = getpwnam(username))) {
46715 -                               fprintf(stderr, "%s.%d: %s, %s\n", 
46716 +                               fprintf(stderr, "%s.%d: %s, %s\n",
46717                                         __FILE__, __LINE__,
46718                                         "can't find username", username);
46719                                 return -1;
46720                         }
46721 -                       
46722 +
46723                         if (pwd->pw_uid == 0) {
46724 -                               fprintf(stderr, "%s.%d: %s\n", 
46725 +                               fprintf(stderr, "%s.%d: %s\n",
46726                                         __FILE__, __LINE__,
46727                                         "I will not set uid to 0\n");
46728                                 return -1;
46729                         }
46730                 }
46731 -               
46732 +
46733                 if (groupname) {
46734                         if (NULL == (grp = getgrnam(groupname))) {
46735 -                               fprintf(stderr, "%s.%d: %s %s\n", 
46736 +                               fprintf(stderr, "%s.%d: %s %s\n",
46737                                         __FILE__, __LINE__,
46738 -                                       "can't find groupname", 
46739 +                                       "can't find groupname",
46740                                         groupname);
46741                                 return -1;
46742                         }
46743                         if (grp->gr_gid == 0) {
46744 -                               fprintf(stderr, "%s.%d: %s\n", 
46745 +                               fprintf(stderr, "%s.%d: %s\n",
46746                                         __FILE__, __LINE__,
46747                                         "I will not set gid to 0\n");
46748                                 return -1;
46749                         }
46750                 }
46751 -               
46752 +
46753                 if (changeroot) {
46754                         if (-1 == chroot(changeroot)) {
46755 -                               fprintf(stderr, "%s.%d: %s %s\n", 
46756 +                               fprintf(stderr, "%s.%d: %s %s\n",
46757                                         __FILE__, __LINE__,
46758                                         "chroot failed: ", strerror(errno));
46759                                 return -1;
46760                         }
46761                         if (-1 == chdir("/")) {
46762 -                               fprintf(stderr, "%s.%d: %s %s\n", 
46763 +                               fprintf(stderr, "%s.%d: %s %s\n",
46764                                         __FILE__, __LINE__,
46765                                         "chdir failed: ", strerror(errno));
46766                                 return -1;
46767                         }
46768                 }
46769 -               
46770 +
46771                 /* drop root privs */
46772                 if (groupname) {
46773                         setgid(grp->gr_gid);
46774 @@ -428,7 +429,7 @@
46775                 }
46776                 if (username) setuid(pwd->pw_uid);
46777         }
46778 -       
46779 +
46780         return fcgi_spawn_connection(fcgi_app, addr, port, unixsocket, child_count, pid_fd, nofork);
46781  }
46782  #else
46783 --- lighttpd-1.4.11/src/splaytree.c     2005-09-12 21:51:28.000000000 +0300
46784 +++ lighttpd-1.4.12/src/splaytree.c     2006-07-11 22:07:51.000000000 +0300
46785 @@ -56,19 +56,19 @@
46786  
46787  #define node_size splaytree_size
46788  
46789 -/* Splay using the key i (which may or may not be in the tree.) 
46790 - * The starting root is t, and the tree used is defined by rat 
46791 +/* Splay using the key i (which may or may not be in the tree.)
46792 + * The starting root is t, and the tree used is defined by rat
46793   * size fields are maintained */
46794  splay_tree * splaytree_splay (splay_tree *t, int i) {
46795      splay_tree N, *l, *r, *y;
46796      int comp, root_size, l_size, r_size;
46797 -    
46798 +
46799      if (t == NULL) return t;
46800      N.left = N.right = NULL;
46801      l = r = &N;
46802      root_size = node_size(t);
46803      l_size = r_size = 0;
46804
46805 +
46806      for (;;) {
46807          comp = compare(i, t->key);
46808          if (comp < 0) {
46809 @@ -120,7 +120,7 @@
46810          y->size = r_size;
46811          r_size -= 1+node_size(y->right);
46812      }
46813
46814 +
46815      l->right = t->left;                                /* assemble */
46816      r->left = t->right;
46817      t->left = N.right;
46818 --- lighttpd-1.4.11/src/splaytree.h     2005-09-12 21:51:13.000000000 +0300
46819 +++ lighttpd-1.4.12/src/splaytree.h     2006-07-11 22:07:51.000000000 +0300
46820 @@ -19,6 +19,6 @@
46821  /* This macro returns the size of a node.  Unlike "x->size",     */
46822  /* it works even if x=NULL.  The test could be avoided by using  */
46823  /* a special version of NULL which was a real node with size 0.  */
46824
46825 +
46826  
46827  #endif
46828 --- lighttpd-1.4.11/src/stat_cache.c    2005-11-22 15:23:51.000000000 +0200
46829 +++ lighttpd-1.4.12/src/stat_cache.c    2006-07-11 22:07:52.000000000 +0300
46830 @@ -6,7 +6,6 @@
46831  #include <stdlib.h>
46832  #include <string.h>
46833  #include <errno.h>
46834 -#include <unistd.h>
46835  #include <stdio.h>
46836  #include <fcntl.h>
46837  #include <assert.h>
46838 @@ -25,19 +24,8 @@
46839  #endif
46840  
46841  #include "sys-mmap.h"
46842 -
46843 -/* NetBSD 1.3.x needs it */
46844 -#ifndef MAP_FAILED
46845 -# define MAP_FAILED -1
46846 -#endif
46847 -
46848 -#ifndef O_LARGEFILE
46849 -# define O_LARGEFILE 0
46850 -#endif
46851 -
46852 -#ifndef HAVE_LSTAT
46853 -#define lstat stat
46854 -#endif
46855 +#include "sys-files.h"
46856 +#include "sys-strings.h"
46857  
46858  #if 0
46859  /* enables debug code for testing if all nodes in the stat-cache as accessable */
46860 @@ -52,8 +40,8 @@
46861   *
46862   * if we get a change-event from FAM, we increment the version in the FAM->dir mapping
46863   *
46864 - * if the stat()-cache is queried we check if the version id for the directory is the 
46865 - * same and return immediatly. 
46866 + * if the stat()-cache is queried we check if the version id for the directory is the
46867 + * same and return immediatly.
46868   *
46869   *
46870   * What we need:
46871 @@ -62,17 +50,17 @@
46872   * - for each FAMRequest we have to find the version in the directory cache (index as userdata)
46873   *
46874   * stat <<-> directory <-> FAMRequest
46875 - * 
46876 - * if file is deleted, directory is dirty, file is rechecked ... 
46877 + *
46878 + * if file is deleted, directory is dirty, file is rechecked ...
46879   * if directory is deleted, directory mapping is removed
46880 - *  
46881 + *
46882   * */
46883  
46884  #ifdef HAVE_FAM_H
46885  typedef struct {
46886         FAMRequest *req;
46887         FAMConnection *fc;
46888 -       
46889 +
46890         buffer *name;
46891  
46892         int version;
46893 @@ -83,16 +71,16 @@
46894   * - we need a hash
46895   * - the hash-key is used as sorting criteria for a tree
46896   * - a splay-tree is used as we can use the caching effect of it
46897 - */ 
46898 + */
46899  
46900  /* we want to cleanup the stat-cache every few seconds, let's say 10
46901   *
46902   * - remove entries which are outdated since 30s
46903   * - remove entries which are fresh but havn't been used since 60s
46904   * - if we don't have a stat-cache entry for a directory, release it from the monitor
46905 - */ 
46906 + */
46907  
46908 -#ifdef DEBUG_STAT_CACHE        
46909 +#ifdef DEBUG_STAT_CACHE
46910  typedef struct {
46911         int *ptr;
46912  
46913 @@ -105,15 +93,15 @@
46914  
46915  stat_cache *stat_cache_init(void) {
46916         stat_cache *fc = NULL;
46917 -       
46918 +
46919         fc = calloc(1, sizeof(*fc));
46920 -       
46921 +
46922         fc->dir_name = buffer_init();
46923  #ifdef HAVE_FAM_H
46924         fc->fam = calloc(1, sizeof(*fc->fam));
46925  #endif
46926  
46927 -#ifdef DEBUG_STAT_CACHE        
46928 +#ifdef DEBUG_STAT_CACHE
46929         ctrl.size = 0;
46930  #endif
46931  
46932 @@ -122,24 +110,24 @@
46933  
46934  static stat_cache_entry * stat_cache_entry_init(void) {
46935         stat_cache_entry *sce = NULL;
46936 -       
46937 +
46938         sce = calloc(1, sizeof(*sce));
46939 -       
46940 +
46941         sce->name = buffer_init();
46942         sce->etag = buffer_init();
46943         sce->content_type = buffer_init();
46944 -       
46945 +
46946         return sce;
46947  }
46948  
46949  static void stat_cache_entry_free(void *data) {
46950         stat_cache_entry *sce = data;
46951         if (!sce) return;
46952 -       
46953 +
46954         buffer_free(sce->etag);
46955         buffer_free(sce->name);
46956         buffer_free(sce->content_type);
46957 -       
46958 +
46959         free(sce);
46960  }
46961  
46962 @@ -148,22 +136,22 @@
46963         fam_dir_entry *fam_dir = NULL;
46964  
46965         fam_dir = calloc(1, sizeof(*fam_dir));
46966 -       
46967 +
46968         fam_dir->name = buffer_init();
46969 -       
46970 +
46971         return fam_dir;
46972  }
46973  
46974  static void fam_dir_entry_free(void *data) {
46975         fam_dir_entry *fam_dir = data;
46976 -       
46977 +
46978         if (!fam_dir) return;
46979 -       
46980 +
46981         FAMCancelMonitor(fam_dir->fc, fam_dir->req);
46982 -       
46983 +
46984         buffer_free(fam_dir->name);
46985         free(fam_dir->req);
46986 -       
46987 +
46988         free(fam_dir);
46989  }
46990  #endif
46991 @@ -174,7 +162,7 @@
46992                 splay_tree *node = sc->files;
46993  
46994                 osize = sc->files->size;
46995 -                       
46996 +
46997                 stat_cache_entry_free(node->data);
46998                 sc->files = splaytree_delete(sc->files, node->key);
46999  
47000 @@ -187,12 +175,12 @@
47001         while (sc->dirs) {
47002                 int osize;
47003                 splay_tree *node = sc->dirs;
47004 -               
47005 +
47006                 osize = sc->dirs->size;
47007  
47008                 fam_dir_entry_free(node->data);
47009                 sc->dirs = splaytree_delete(sc->dirs, node->key);
47010 -               
47011 +
47012                 if (osize == 1) {
47013                         assert(NULL == sc->dirs);
47014                 } else {
47015 @@ -212,7 +200,7 @@
47016  static int stat_cache_attr_get(buffer *buf, char *name) {
47017         int attrlen;
47018         int ret;
47019 -       
47020 +
47021         attrlen = 1024;
47022         buffer_prepare_copy(buf, attrlen);
47023         attrlen--;
47024 @@ -251,15 +239,15 @@
47025             sc->fam) {
47026  
47027                 events = FAMPending(sc->fam);
47028 -       
47029 +
47030                 for (i = 0; i < events; i++) {
47031                         FAMEvent fe;
47032                         fam_dir_entry *fam_dir;
47033                         splay_tree *node;
47034                         int ndx;
47035 -               
47036 +
47037                         FAMNextEvent(sc->fam, &fe);
47038 -       
47039 +
47040                         /* handle event */
47041  
47042                         switch(fe.code) {
47043 @@ -280,7 +268,7 @@
47044  
47045                                 sc->dirs = splaytree_splay(sc->dirs, ndx);
47046                                 node = sc->dirs;
47047 -                       
47048 +
47049                                 if (node && (node->key == ndx)) {
47050                                         int osize = splaytree_size(sc->dirs);
47051  
47052 @@ -308,7 +296,7 @@
47053  
47054                 sc->fam = NULL;
47055         }
47056 -       
47057 +
47058         return HANDLER_GO_ON;
47059  }
47060  
47061 @@ -332,7 +320,7 @@
47062   *
47063   *
47064   *
47065 - * returns: 
47066 + * returns:
47067   *  - HANDLER_FINISHED on cache-miss (don't forget to reopen the file)
47068   *  - HANDLER_ERROR on stat() failed -> see errno for problem
47069   */
47070 @@ -348,16 +336,16 @@
47071         struct stat st;
47072         size_t k;
47073         int fd;
47074 -#ifdef DEBUG_STAT_CACHE        
47075 +#ifdef DEBUG_STAT_CACHE
47076         size_t i;
47077  #endif
47078  
47079         int file_ndx;
47080         splay_tree *file_node = NULL;
47081  
47082 -       *ret_sce = NULL; 
47083 +       *ret_sce = NULL;
47084  
47085 -       /* 
47086 +       /*
47087          * check if the directory for this file has changed
47088          */
47089  
47090 @@ -366,23 +354,23 @@
47091         file_ndx = hashme(name);
47092         sc->files = splaytree_splay(sc->files, file_ndx);
47093  
47094 -#ifdef DEBUG_STAT_CACHE        
47095 +#ifdef DEBUG_STAT_CACHE
47096         for (i = 0; i < ctrl.used; i++) {
47097                 if (ctrl.ptr[i] == file_ndx) break;
47098         }
47099  #endif
47100  
47101         if (sc->files && (sc->files->key == file_ndx)) {
47102 -#ifdef DEBUG_STAT_CACHE        
47103 +#ifdef DEBUG_STAT_CACHE
47104                 /* it was in the cache */
47105                 assert(i < ctrl.used);
47106  #endif
47107 -               
47108 -               /* we have seen this file already and 
47109 +
47110 +               /* we have seen this file already and
47111                  * don't stat() it again in the same second */
47112  
47113                 file_node = sc->files;
47114 -               
47115 +
47116                 sce = file_node->data;
47117  
47118                 /* check if the name is the same, we might have a collision */
47119 @@ -390,7 +378,7 @@
47120                 if (buffer_is_equal(name, sce->name)) {
47121                         if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_SIMPLE) {
47122                                 if (sce->stat_ts == srv->cur_ts) {
47123 -                                       *ret_sce = sce; 
47124 +                                       *ret_sce = sce;
47125                                         return HANDLER_GO_ON;
47126                                 }
47127                         }
47128 @@ -400,15 +388,15 @@
47129                          * file_node is used by the FAM check below to see if we know this file
47130                          * and if we can save a stat().
47131                          *
47132 -                        * BUT, the sce is not reset here as the entry into the cache is ok, we 
47133 +                        * BUT, the sce is not reset here as the entry into the cache is ok, we
47134                          * it is just not pointing to our requested file.
47135 -                        * 
47136 +                        *
47137                          *  */
47138  
47139                         file_node = NULL;
47140                 }
47141         } else {
47142 -#ifdef DEBUG_STAT_CACHE        
47143 +#ifdef DEBUG_STAT_CACHE
47144                 if (i != ctrl.used) {
47145                         fprintf(stderr, "%s.%d: %08x was already inserted but not found in cache, %s\n", __FILE__, __LINE__, file_ndx, name->ptr);
47146                 }
47147 @@ -424,23 +412,23 @@
47148                 }
47149  
47150                 dir_ndx = hashme(sc->dir_name);
47151 -               
47152 +
47153                 sc->dirs = splaytree_splay(sc->dirs, dir_ndx);
47154 -               
47155 +
47156                 if (sc->dirs && (sc->dirs->key == dir_ndx)) {
47157                         dir_node = sc->dirs;
47158                 }
47159 -               
47160 +
47161                 if (dir_node && file_node) {
47162                         /* we found a file */
47163 -                       
47164 +
47165                         sce = file_node->data;
47166                         fam_dir = dir_node->data;
47167 -                       
47168 +
47169                         if (fam_dir->version == sce->dir_version) {
47170                                 /* the stat()-cache entry is still ok */
47171 -                               
47172 -                               *ret_sce = sce; 
47173 +
47174 +                               *ret_sce = sce;
47175                                 return HANDLER_GO_ON;
47176                         }
47177                 }
47178 @@ -448,7 +436,7 @@
47179  #endif
47180  
47181         /*
47182 -        * *lol* 
47183 +        * *lol*
47184          * - open() + fstat() on a named-pipe results in a (intended) hang.
47185          * - stat() if regualar file + open() to see if we can read from it is better
47186          *
47187 @@ -469,16 +457,16 @@
47188  
47189         if (NULL == sce) {
47190                 int osize = 0;
47191 -                      
47192 +
47193                 if (sc->files) {
47194                         osize = sc->files->size;
47195                 }
47196  
47197                 sce = stat_cache_entry_init();
47198                 buffer_copy_string_buffer(sce->name, name);
47199 -               
47200 -               sc->files = splaytree_insert(sc->files, file_ndx, sce); 
47201 -#ifdef DEBUG_STAT_CACHE        
47202 +
47203 +               sc->files = splaytree_insert(sc->files, file_ndx, sce);
47204 +#ifdef DEBUG_STAT_CACHE
47205                 if (ctrl.size == 0) {
47206                         ctrl.size = 16;
47207                         ctrl.used = 0;
47208 @@ -499,29 +487,29 @@
47209         sce->st = st;
47210         sce->stat_ts = srv->cur_ts;
47211  
47212 -       /* catch the obvious symlinks 
47213 +       /* catch the obvious symlinks
47214          *
47215          * this is not a secure check as we still have a race-condition between
47216 -        * the stat() and the open. We can only solve this by 
47217 +        * the stat() and the open. We can only solve this by
47218          * 1. open() the file
47219          * 2. fstat() the fd
47220          *
47221          * and keeping the file open for the rest of the time. But this can
47222          * only be done at network level.
47223 -        * 
47224 +        *
47225          * */
47226         if (S_ISLNK(st.st_mode) && !con->conf.follow_symlink) {
47227                 return HANDLER_ERROR;
47228         }
47229  
47230 -       if (S_ISREG(st.st_mode)) {      
47231 +       if (S_ISREG(st.st_mode)) {
47232                 /* determine mimetype */
47233                 buffer_reset(sce->content_type);
47234 -               
47235 +
47236                 for (k = 0; k < con->conf.mimetypes->used; k++) {
47237                         data_string *ds = (data_string *)con->conf.mimetypes->data[k];
47238                         buffer *type = ds->key;
47239 -               
47240 +
47241                         if (type->used == 0) continue;
47242  
47243                         /* check if the right side is the same */
47244 @@ -539,7 +527,7 @@
47245                 }
47246  #endif
47247         }
47248 -               
47249 +
47250  #ifdef HAVE_FAM_H
47251         if (sc->fam &&
47252             (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM)) {
47253 @@ -549,19 +537,19 @@
47254                         fam_dir->fc = sc->fam;
47255  
47256                         buffer_copy_string_buffer(fam_dir->name, sc->dir_name);
47257 -                       
47258 +
47259                         fam_dir->version = 1;
47260 -                       
47261 +
47262                         fam_dir->req = calloc(1, sizeof(FAMRequest));
47263 -                       
47264 -                       if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr, 
47265 +
47266 +                       if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr,
47267                                                      fam_dir->req, fam_dir)) {
47268 -                               
47269 -                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
47270 -                                               "monitoring dir failed:", 
47271 -                                               fam_dir->name, 
47272 +
47273 +                               log_error_write(srv, __FILE__, __LINE__, "sbs",
47274 +                                               "monitoring dir failed:",
47275 +                                               fam_dir->name,
47276                                                 FamErrlist[FAMErrno]);
47277 -                               
47278 +
47279                                 fam_dir_entry_free(fam_dir);
47280                         } else {
47281                                 int osize = 0;
47282 @@ -570,7 +558,7 @@
47283                                         osize = sc->dirs->size;
47284                                 }
47285  
47286 -                               sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir); 
47287 +                               sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir);
47288                                 assert(sc->dirs);
47289                                 assert(sc->dirs->data == fam_dir);
47290                                 assert(osize == (sc->dirs->size - 1));
47291 @@ -578,9 +566,9 @@
47292                 } else {
47293                         fam_dir = dir_node->data;
47294                 }
47295 -               
47296 +
47297                 /* bind the fam_fc to the stat() cache entry */
47298 -                       
47299 +
47300                 if (fam_dir) {
47301                         sce->dir_version = fam_dir->version;
47302                         sce->dir_ndx     = dir_ndx;
47303 @@ -594,11 +582,11 @@
47304  }
47305  
47306  /**
47307 - * remove stat() from cache which havn't been stat()ed for 
47308 + * remove stat() from cache which havn't been stat()ed for
47309   * more than 10 seconds
47310 - * 
47311   *
47312 - * walk though the stat-cache, collect the ids which are too old 
47313 + *
47314 + * walk though the stat-cache, collect the ids which are too old
47315   * and remove them in a second loop
47316   */
47317  
47318 @@ -639,9 +627,9 @@
47319                 sc->files = splaytree_splay(sc->files, ndx);
47320  
47321                 node = sc->files;
47322 -               
47323 +
47324                 if (node && (node->key == ndx)) {
47325 -#ifdef DEBUG_STAT_CACHE        
47326 +#ifdef DEBUG_STAT_CACHE
47327                         size_t j;
47328                         int osize = splaytree_size(sc->files);
47329                         stat_cache_entry *sce = node->data;
47330 @@ -649,7 +637,7 @@
47331                         stat_cache_entry_free(node->data);
47332                         sc->files = splaytree_delete(sc->files, ndx);
47333  
47334 -#ifdef DEBUG_STAT_CACHE        
47335 +#ifdef DEBUG_STAT_CACHE
47336                         for (j = 0; j < ctrl.used; j++) {
47337                                 if (ctrl.ptr[j] == ndx) {
47338                                         ctrl.ptr[j] = ctrl.ptr[--ctrl.used];
47339 --- lighttpd-1.4.11/src/stream.c        2005-09-23 21:50:15.000000000 +0300
47340 +++ lighttpd-1.4.12/src/stream.c        2006-07-11 22:07:53.000000000 +0300
47341 @@ -1,7 +1,6 @@
47342  #include <sys/types.h>
47343  #include <sys/stat.h>
47344  
47345 -#include <unistd.h> 
47346  #include <fcntl.h>
47347  
47348  #include "stream.h"
47349 @@ -10,6 +9,7 @@
47350  #endif
47351  
47352  #include "sys-mmap.h"
47353 +#include "sys-files.h"
47354  
47355  #ifndef O_BINARY
47356  # define O_BINARY 0
47357 @@ -19,39 +19,39 @@
47358         struct stat st;
47359  #ifdef HAVE_MMAP
47360         int fd;
47361 -#elif defined __WIN32
47362 +#elif defined _WIN32
47363         HANDLE *fh, *mh;
47364         void *p;
47365  #endif
47366  
47367         f->start = NULL;
47368 -       
47369 +
47370         if (-1 == stat(fn->ptr, &st)) {
47371                 return -1;
47372         }
47373 -       
47374 +
47375         f->size = st.st_size;
47376  
47377  #ifdef HAVE_MMAP
47378         if (-1 == (fd = open(fn->ptr, O_RDONLY | O_BINARY))) {
47379                 return -1;
47380         }
47381 -       
47382 +
47383         f->start = mmap(0, f->size, PROT_READ, MAP_SHARED, fd, 0);
47384 -       
47385 +
47386         close(fd);
47387 -       
47388 +
47389         if (MAP_FAILED == f->start) {
47390                 return -1;
47391         }
47392  
47393 -#elif defined __WIN32
47394 -       fh = CreateFile(fn->ptr, 
47395 -                       GENERIC_READ, 
47396 -                       FILE_SHARE_READ, 
47397 -                       NULL, 
47398 -                       OPEN_EXISTING, 
47399 -                       FILE_ATTRIBUTE_READONLY, 
47400 +#elif defined _WIN32
47401 +       fh = CreateFile(fn->ptr,
47402 +                       GENERIC_READ,
47403 +                       FILE_SHARE_READ,
47404 +                       NULL,
47405 +                       OPEN_EXISTING,
47406 +                       FILE_ATTRIBUTE_READONLY,
47407                         NULL);
47408  
47409         if (!fh) return -1;
47410 @@ -66,7 +66,7 @@
47411         if (!mh) {
47412                 LPVOID lpMsgBuf;
47413                 FormatMessage(
47414 -                       FORMAT_MESSAGE_ALLOCATE_BUFFER | 
47415 +                       FORMAT_MESSAGE_ALLOCATE_BUFFER |
47416                         FORMAT_MESSAGE_FROM_SYSTEM,
47417                         NULL,
47418                         GetLastError(),
47419 @@ -76,7 +76,7 @@
47420  
47421                 return -1;
47422         }
47423 -       
47424 +
47425         p = MapViewOfFile(mh,
47426                         FILE_MAP_READ,
47427                         0,
47428 @@ -87,9 +87,9 @@
47429  
47430         f->start = p;
47431  #else
47432 -# error no mmap found  
47433 +# error no mmap found
47434  #endif
47435 -       
47436 +
47437         return 0;
47438  }
47439  
47440 --- lighttpd-1.4.11/src/sys-files.h     1970-01-01 03:00:00.000000000 +0300
47441 +++ lighttpd-1.4.12/src/sys-files.h     2006-07-11 22:07:53.000000000 +0300
47442 @@ -0,0 +1,67 @@
47443 +#ifndef _SYS_FILES_H_
47444 +#define _SYS_FILES_H_
47445 +
47446 +#define DIR_SEPERATOR_UNIX '/'
47447 +#define DIR_SEPERATOR_WIN '\\'
47448 +
47449 +#ifdef _WIN32
47450 +#include <windows.h>
47451 +#include <io.h>     /* open */
47452 +#include <direct.h> /* chdir */
47453 +
47454 +#include "buffer.h"
47455 +
47456 +#define DIR_SEPERATOR DIR_SEPERATOR_WIN
47457 +
47458 +#define __S_ISTYPE(mode, mask)  (((mode) & _S_IFMT) == (mask))
47459 +
47460 +#define S_ISDIR(mode)    __S_ISTYPE((mode), _S_IFDIR)
47461 +#define S_ISCHR(mode)    __S_ISTYPE((mode), _S_IFCHR)
47462 +#define S_ISBLK(mode)    __S_ISTYPE((mode), _S_IFBLK)
47463 +#define S_ISREG(mode)    __S_ISTYPE((mode), _S_IFREG)
47464 +/* we don't support symlinks */
47465 +#define S_ISLNK(mode)    0
47466 +
47467 +#define lstat stat
47468 +#define mkstemp mktemp
47469 +#define mkdir(x, y) mkdir(x)
47470 +
47471 +struct dirent {
47472 +    const char *d_name;
47473 +};
47474 +
47475 +typedef struct {
47476 +    HANDLE h;
47477 +    WIN32_FIND_DATA finddata;
47478 +    struct dirent dent;
47479 +} DIR;
47480 +
47481 +DIR *opendir(const char *dn);
47482 +struct dirent *readdir(DIR *d);
47483 +void closedir(DIR *d);
47484 +
47485 +buffer *filename_unix2local(buffer *b);
47486 +buffer *pathname_unix2local(buffer *b);
47487 +
47488 +#else
47489 +#include <unistd.h>
47490 +#include <dirent.h>
47491 +
47492 +#define DIR_SEPERATOR DIR_SEPERATOR_UNIX
47493 +
47494 +#define filename_unix2local(x) (x)
47495 +#define pathname_unix2local(x) (x)
47496 +#endif
47497 +
47498 +#define PATHNAME_APPEND_SLASH(x) \
47499 +       if (x->used > 1 && x->ptr[x->used - 2] != DIR_SEPERATOR) { \
47500 +        char sl[2] = { DIR_SEPERATOR, 0 }; \
47501 +        BUFFER_APPEND_STRING_CONST(x, sl); \
47502 +    }
47503 +
47504 +#ifndef O_LARGEFILE
47505 +# define O_LARGEFILE 0
47506 +#endif
47507 +
47508 +#endif
47509 +
47510 --- lighttpd-1.4.11/src/sys-mmap.h      2005-08-11 01:26:34.000000000 +0300
47511 +++ lighttpd-1.4.12/src/sys-mmap.h      2006-07-11 22:07:52.000000000 +0300
47512 @@ -1,7 +1,7 @@
47513  #ifndef WIN32_MMAP_H
47514  #define WIN32_MMAP_H
47515  
47516 -#ifdef __WIN32
47517 +#ifdef _WIN32
47518  
47519  #define MAP_FAILED -1
47520  #define PROT_SHARED 0
47521 --- lighttpd-1.4.11/src/sys-process.h   1970-01-01 03:00:00.000000000 +0300
47522 +++ lighttpd-1.4.12/src/sys-process.h   2006-07-11 22:07:52.000000000 +0300
47523 @@ -0,0 +1,16 @@
47524 +#ifndef _SYS_PROCESS_H_
47525 +#define _SYS_PROCESS_H_
47526 +
47527 +#ifdef _WIN32
47528 +#include <process.h>
47529 +#define pid_t int
47530 +/* win32 has no fork() */
47531 +#define kill(x, y)
47532 +
47533 +#else
47534 +#include <sys/wait.h>
47535 +#include <unistd.h>
47536 +#endif
47537 +
47538 +#endif
47539 +
47540 --- lighttpd-1.4.11/src/sys-socket.h    2005-08-11 01:26:39.000000000 +0300
47541 +++ lighttpd-1.4.12/src/sys-socket.h    2006-07-11 22:07:52.000000000 +0300
47542 @@ -1,15 +1,26 @@
47543  #ifndef WIN32_SOCKET_H
47544  #define WIN32_SOCKET_H
47545  
47546 -#ifdef __WIN32
47547 +#ifdef _WIN32
47548  
47549  #include <winsock2.h>
47550  
47551  #define ECONNRESET WSAECONNRESET
47552  #define EINPROGRESS WSAEINPROGRESS
47553  #define EALREADY WSAEALREADY
47554 +#define ENOTCONN WSAENOTCONN
47555 +#define EWOULDBLOCK WSAEWOULDBLOCK
47556  #define ioctl ioctlsocket
47557  #define hstrerror(x) ""
47558 +#define STDIN_FILENO 0
47559 +#define STDOUT_FILENO 1
47560 +#define STDERR_FILENO 2
47561 +#define ssize_t int
47562 +
47563 +int inet_aton(const char *cp, struct in_addr *inp);
47564 +#define HAVE_INET_ADDR
47565 +#undef HAVE_INET_ATON
47566 +
47567  #else
47568  #include <sys/socket.h>
47569  #include <sys/ioctl.h>
47570 @@ -18,6 +29,11 @@
47571  #include <sys/un.h>
47572  #include <arpa/inet.h>
47573  
47574 +#ifndef SUN_LEN
47575 +#define SUN_LEN(su) \
47576 +        (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
47577 +#endif
47578 +
47579  #include <netdb.h>
47580  #endif
47581  
47582 --- lighttpd-1.4.11/src/sys-strings.h   1970-01-01 03:00:00.000000000 +0300
47583 +++ lighttpd-1.4.12/src/sys-strings.h   2006-07-11 22:07:51.000000000 +0300
47584 @@ -0,0 +1,11 @@
47585 +#ifndef _SYS_STRINGS_H_
47586 +#define _SYS_STRINGS_H_
47587 +
47588 +#ifdef _WIN32
47589 +#define strcasecmp stricmp
47590 +#define strncasecmp strnicmp
47591 +#define strtoll(p, e, b) _strtoi64(p, e, b)
47592 +#endif
47593 +
47594 +#endif
47595 +
47596 --- lighttpd-1.4.11/tests/LightyTest.pm 2006-01-14 20:32:31.000000000 +0200
47597 +++ lighttpd-1.4.12/tests/LightyTest.pm 2006-07-11 22:07:53.000000000 +0300
47598 @@ -87,14 +87,14 @@
47599         # pre-process configfile if necessary
47600         #
47601  
47602 -       unlink($self->{TESTDIR}."/tmp/cfg.file");
47603 -       system("cat ".$self->{SRCDIR}."/".$self->{CONFIGFILE}.' | perl -pe "s#\@SRCDIR\@#'.$self->{BASEDIR}.'/tests/#" > '.$self->{TESTDIR}.'/tmp/cfg.file');
47604 +       $ENV{'SRCDIR'} = $self->{BASEDIR}.'/tests';
47605 +       $ENV{'PORT'} = $self->{PORT};
47606  
47607         unlink($self->{LIGHTTPD_PIDFILE});
47608         if (1) {
47609 -               system($self->{LIGHTTPD_PATH}." -f ".$self->{TESTDIR}."/tmp/cfg.file -m ".$self->{MODULES_PATH});
47610 +               system($self->{LIGHTTPD_PATH}." -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH});
47611         } else {
47612 -               system("valgrind --tool=memcheck --show-reachable=yes --leak-check=yes --logfile=foo ".$self->{LIGHTTPD_PATH}." -D -f ".$self->{TESTDIR}."/tmp/cfg.file -m ".$self->{MODULES_PATH}." &");
47613 +               system("valgrind --tool=memcheck --show-reachable=yes --leak-check=yes --logfile=foo ".$self->{LIGHTTPD_PATH}." -D -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH}." &");
47614         }
47615  
47616         select(undef, undef, undef, 0.1);
47617 @@ -184,7 +184,7 @@
47618                                         (my $h = $1) =~ tr/[A-Z]/[a-z]/;
47619  
47620                                         if (defined $resp_hdr{$h}) {
47621 -                                               diag(sprintf("header %s is duplicated: %s and %s\n",
47622 +                                               diag(sprintf("header '%s' is duplicated: '%s' and '%s'\n",
47623                                                              $h, $resp_hdr{$h}, $2));
47624                                         } else {
47625                                                 $resp_hdr{$h} = $2;
47626 @@ -196,6 +196,9 @@
47627                         }
47628                 }
47629  
47630 +               $t->{etag} = $resp_hdr{'etag'};
47631 +               $t->{date} = $resp_hdr{'date'};
47632 +
47633                 # check length
47634                 if (defined $resp_hdr{"content-length"}) {
47635                         $resp_body = substr($lines, 0, $resp_hdr{"content-length"});
47636 --- lighttpd-1.4.11/tests/Makefile.am   2005-09-16 15:48:40.000000000 +0300
47637 +++ lighttpd-1.4.12/tests/Makefile.am   2006-07-11 22:07:53.000000000 +0300
47638 @@ -39,10 +39,15 @@
47639        mod-redirect.t \
47640        mod-userdir.t \
47641        mod-rewrite.t \
47642 +      mod-proxy.t \
47643        request.t \
47644        mod-ssi.t \
47645        LightyTest.pm \
47646 -      mod-setenv.t 
47647 +      mod-setenv.t \
47648 +      lowercase.t \
47649 +      lowercase.conf \
47650 +      proxy.conf \
47651 +      cachable.t
47652  
47653  
47654  TESTS_ENVIRONMENT=$(srcdir)/wrapper.sh $(srcdir) $(top_builddir) 
47655 --- lighttpd-1.4.11/tests/Makefile.in   2006-03-07 14:21:03.000000000 +0200
47656 +++ lighttpd-1.4.12/tests/Makefile.in   2006-07-11 21:48:14.000000000 +0300
47657 @@ -1,4 +1,4 @@
47658 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
47659 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
47660  # @configure_input@
47661  
47662  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
47663 @@ -13,8 +13,6 @@
47664  # PARTICULAR PURPOSE.
47665  
47666  @SET_MAKE@
47667 -SOURCES = $(fcgi_auth_SOURCES) $(fcgi_responder_SOURCES)
47668 -
47669  srcdir = @srcdir@
47670  top_srcdir = @top_srcdir@
47671  VPATH = @srcdir@
47672 @@ -46,7 +44,7 @@
47673  am__aclocal_m4_deps = $(top_srcdir)/configure.in
47674  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
47675         $(ACLOCAL_M4)
47676 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
47677 +mkinstalldirs = $(install_sh) -d
47678  CONFIG_HEADER = $(top_builddir)/config.h
47679  CONFIG_CLEAN_FILES =
47680  am__fcgi_auth_SOURCES_DIST = fcgi-auth.c
47681 @@ -67,8 +65,8 @@
47682         $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
47683         $(AM_CFLAGS) $(CFLAGS)
47684  CCLD = $(CC)
47685 -LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
47686 -       $(AM_LDFLAGS) $(LDFLAGS) -o $@
47687 +LINK = $(LIBTOOL) --tag=CC --mode=link "$(CCLD)" $(AM_CFLAGS) \
47688 +       $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
47689  SOURCES = $(fcgi_auth_SOURCES) $(fcgi_responder_SOURCES)
47690  DIST_SOURCES = $(am__fcgi_auth_SOURCES_DIST) \
47691         $(am__fcgi_responder_SOURCES_DIST)
47692 @@ -134,7 +132,6 @@
47693  LIBTOOL = @LIBTOOL@
47694  LN_S = @LN_S@
47695  LTLIBOBJS = @LTLIBOBJS@
47696 -LUACONFIG = @LUACONFIG@
47697  LUA_CFLAGS = @LUA_CFLAGS@
47698  LUA_LIBS = @LUA_LIBS@
47699  MAINT = @MAINT@
47700 @@ -177,6 +174,7 @@
47701  ac_ct_F77 = @ac_ct_F77@
47702  ac_ct_RANLIB = @ac_ct_RANLIB@
47703  ac_ct_STRIP = @ac_ct_STRIP@
47704 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
47705  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
47706  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
47707  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
47708 @@ -253,10 +251,15 @@
47709        mod-redirect.t \
47710        mod-userdir.t \
47711        mod-rewrite.t \
47712 +      mod-proxy.t \
47713        request.t \
47714        mod-ssi.t \
47715        LightyTest.pm \
47716 -      mod-setenv.t 
47717 +      mod-setenv.t \
47718 +      lowercase.t \
47719 +      lowercase.conf \
47720 +      proxy.conf \
47721 +      cachable.t
47722  
47723  TESTS_ENVIRONMENT = $(srcdir)/wrapper.sh $(srcdir) $(top_builddir) 
47724  EXTRA_DIST = wrapper.sh lighttpd.conf \
47725 --- lighttpd-1.4.11/tests/bug-06.conf   2005-08-27 17:44:19.000000000 +0300
47726 +++ lighttpd-1.4.12/tests/bug-06.conf   2006-07-11 22:07:53.000000000 +0300
47727 @@ -1,5 +1,5 @@
47728 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47729 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47730 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47731 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47732  
47733  ## bind to port (default: 80)
47734  server.port                 = 2048
47735 @@ -8,7 +8,7 @@
47736  
47737  ## bind to localhost (default: all interfaces)
47738  server.bind                = "localhost"
47739 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47740 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47741  server.name                = "www.example.org"
47742  server.tag                 = "Apache 1.3.29"
47743  
47744 @@ -59,7 +59,7 @@
47745  ######################## MODULE CONFIG ############################
47746  
47747  
47748 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47749 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47750  
47751  mimetype.assign             = ( ".png"  => "image/png", 
47752                                  ".jpg"  => "image/jpeg",
47753 @@ -77,7 +77,7 @@
47754                                 ".c"    => "text/plain",
47755                                 ".conf" => "text/plain" )
47756  
47757 -compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
47758 +compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
47759  compress.filetype           = ("text/plain", "text/html")
47760  
47761  setenv.add-environment      = ( "TRAC_ENV" => "foo")
47762 @@ -90,7 +90,7 @@
47763                                     "host" => "127.0.0.1",
47764                                     "port" => 1026,
47765  #                                  "mode" => "authorizer",
47766 -#                                  "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
47767 +#                                  "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
47768                                   )
47769                                 )
47770                               )
47771 @@ -106,7 +106,7 @@
47772  ssl.pemfile                 = "server.pem"
47773  
47774  auth.backend                = "plain"
47775 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
47776 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
47777  auth.backend.plain.groupfile = "lighttpd.group"
47778  
47779  auth.backend.ldap.hostname  = "localhost"
47780 @@ -149,15 +149,15 @@
47781  status.config-url           = "/server-config"
47782  
47783  simple-vhost.document-root  = "pages"
47784 -simple-vhost.server-root    = "@SRCDIR@/tmp/lighttpd/servers/"
47785 +simple-vhost.server-root    = env.SRCDIR + "/tmp/lighttpd/servers/"
47786  simple-vhost.default-host   = "www.example.org"
47787  
47788  $HTTP["host"] == "vvv.example.org" {
47789 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47790 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47791  }
47792  
47793  $HTTP["host"] == "zzz.example.org" {
47794 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47795 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47796    server.name = "zzz.example.org"
47797  }
47798  
47799 --- lighttpd-1.4.11/tests/bug-12.conf   2005-08-27 17:44:19.000000000 +0300
47800 +++ lighttpd-1.4.12/tests/bug-12.conf   2006-07-11 22:07:53.000000000 +0300
47801 @@ -1,5 +1,5 @@
47802 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47803 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47804 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47805 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47806  
47807  ## bind to port (default: 80)
47808  server.port                 = 2048
47809 @@ -8,7 +8,7 @@
47810  
47811  ## bind to localhost (default: all interfaces)
47812  server.bind                = "localhost"
47813 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47814 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47815  server.name                = "www.example.org"
47816  server.tag                 = "Apache 1.3.29"
47817  
47818 @@ -61,7 +61,7 @@
47819  ######################## MODULE CONFIG ############################
47820  
47821  
47822 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47823 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47824  
47825  mimetype.assign             = ( ".png"  => "image/png", 
47826                                  ".jpg"  => "image/jpeg",
47827 @@ -79,7 +79,7 @@
47828                                 ".c"    => "text/plain",
47829                                 ".conf" => "text/plain" )
47830  
47831 -compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
47832 +compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
47833  compress.filetype           = ("text/plain", "text/html")
47834  
47835  setenv.add-environment      = ( "TRAC_ENV" => "foo")
47836 @@ -92,7 +92,7 @@
47837                                     "host" => "127.0.0.1",
47838                                     "port" => 1026,
47839  #                                  "mode" => "authorizer",
47840 -#                                  "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
47841 +#                                  "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
47842                                   )
47843                                 )
47844                               )
47845 @@ -108,7 +108,7 @@
47846  ssl.pemfile                 = "server.pem"
47847  
47848  auth.backend                = "plain"
47849 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
47850 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
47851  auth.backend.plain.groupfile = "lighttpd.group"
47852  
47853  auth.backend.ldap.hostname  = "localhost"
47854 @@ -151,15 +151,15 @@
47855  status.config-url           = "/server-config"
47856  
47857  simple-vhost.document-root  = "pages"
47858 -simple-vhost.server-root    = "@SRCDIR@/tmp/lighttpd/servers/"
47859 +simple-vhost.server-root    = env.SRCDIR + "/tmp/lighttpd/servers/"
47860  simple-vhost.default-host   = "www.example.org"
47861  
47862  $HTTP["host"] == "vvv.example.org" {
47863 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47864 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47865  }
47866  
47867  $HTTP["host"] == "zzz.example.org" {
47868 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47869 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47870    server.name = "zzz.example.org"
47871  }
47872  
47873 --- lighttpd-1.4.11/tests/cachable.t    1970-01-01 03:00:00.000000000 +0300
47874 +++ lighttpd-1.4.12/tests/cachable.t    2006-07-11 22:07:53.000000000 +0300
47875 @@ -0,0 +1,112 @@
47876 +#!/usr/bin/env perl
47877 +BEGIN {
47878 +    # add current source dir to the include-path
47879 +    # we need this for make distcheck
47880 +   (my $srcdir = $0) =~ s#/[^/]+$#/#;
47881 +   unshift @INC, $srcdir;
47882 +}
47883 +
47884 +use strict;
47885 +use IO::Socket;
47886 +use Test::More tests => 12;
47887 +use LightyTest;
47888 +
47889 +my $tf = LightyTest->new();
47890 +my $t;
47891 +
47892 +$tf->{CONFIGFILE} = 'lighttpd.conf';
47893 +    
47894 +ok($tf->start_proc == 0, "Starting lighttpd") or die();
47895 +
47896 +## check if If-Modified-Since, If-None-Match works
47897 +
47898 +$t->{REQUEST}  = ( <<EOF
47899 +GET / HTTP/1.0
47900 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT
47901 +EOF
47902 + );
47903 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47904 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since');
47905 +
47906 +$t->{REQUEST}  = ( <<EOF
47907 +GET / HTTP/1.0
47908 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
47909 +EOF
47910 + );
47911 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47912 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since, comment');
47913 +
47914 +my $now = $t->{date};
47915 +
47916 +$t->{REQUEST}  = ( <<EOF
47917 +GET / HTTP/1.0
47918 +If-Modified-Since: $now
47919 +EOF
47920 + );
47921 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47922 +ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since');
47923 +
47924 +$t->{REQUEST}  = ( <<EOF
47925 +GET / HTTP/1.0
47926 +If-Modified-Since: $now; foo
47927 +EOF
47928 + );
47929 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47930 +ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since, comment');
47931 +
47932 +$t->{REQUEST}  = ( <<EOF
47933 +GET / HTTP/1.0
47934 +If-None-Match: foo
47935 +EOF
47936 + );
47937 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47938 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
47939 +
47940 +my $etag = $t->{etag};
47941 +
47942 +$t->{REQUEST}  = ( <<EOF
47943 +GET / HTTP/1.0
47944 +If-None-Match: $etag
47945 +EOF
47946 + );
47947 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47948 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
47949 +
47950 +$t->{REQUEST}  = ( <<EOF
47951 +GET / HTTP/1.0
47952 +If-None-Match: $etag
47953 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
47954 +EOF
47955 + );
47956 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47957 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + old Last-Modified');
47958 +
47959 +$t->{REQUEST}  = ( <<EOF
47960 +GET / HTTP/1.0
47961 +If-None-Match: $etag
47962 +If-Modified-Since: $now; foo
47963 +EOF
47964 + );
47965 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47966 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag, Last-Modified + comment');
47967 +
47968 +$t->{REQUEST}  = ( <<EOF
47969 +GET / HTTP/1.0
47970 +If-None-Match: Foo
47971 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
47972 +EOF
47973 + );
47974 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47975 +ok($tf->handle_http($t) == 0, 'Conditional GET - old ETAG + old Last-Modified');
47976 +
47977 +$t->{REQUEST}  = ( <<EOF
47978 +GET / HTTP/1.0
47979 +If-None-Match: $etag
47980 +If-Modified-Since: $now foo
47981 +EOF
47982 + );
47983 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 412 } ];
47984 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + Last-Modified + overlong timestamp');
47985 +
47986 +ok($tf->stop_proc == 0, "Stopping lighttpd");
47987 +
47988 --- lighttpd-1.4.11/tests/condition.conf        2005-08-27 17:44:19.000000000 +0300
47989 +++ lighttpd-1.4.12/tests/condition.conf        2006-07-11 22:07:53.000000000 +0300
47990 @@ -2,15 +2,15 @@
47991  debug.log-request-handling = "enable"
47992  debug.log-condition-handling = "enable"
47993  
47994 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47995 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47996 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47997 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47998  
47999  ## bind to port (default: 80)
48000  server.port                 = 2048
48001  
48002  ## bind to localhost (default: all interfaces)
48003  server.bind                = "localhost"
48004 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48005 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48006  server.name                = "www.example.org"
48007  server.tag                 = "Apache 1.3.29"
48008  
48009 @@ -22,25 +22,25 @@
48010  ######################## MODULE CONFIG ############################
48011  
48012  
48013 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48014 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48015  
48016  mimetype.assign             = ( ".html" => "text/html" )
48017  
48018  url.redirect = ("^" => "/default")
48019  
48020  $HTTP["host"] == "www.example.org" {
48021 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48022 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48023    server.name = "www.example.org"
48024    url.redirect = ("^" => "/match_1")
48025  }
48026  else $HTTP["host"] == "test1.example.org" {
48027 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48028 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48029    server.name = "test1.example.org"
48030    url.redirect = ("^" => "/match_2")
48031  }
48032  # comments
48033  else $HTTP["host"] == "test2.example.org" {
48034 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48035 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48036    server.name = "test2.example.org"
48037    url.redirect = ("^" => "/match_3")
48038  }
48039 @@ -48,7 +48,7 @@
48040          # comments
48041  
48042  else $HTTP["host"] == "test3.example.org" {
48043 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48044 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48045    server.name = "test3.example.org"
48046    url.redirect = ("^" => "/match_4")
48047  
48048 --- lighttpd-1.4.11/tests/core-keepalive.t      2005-11-17 15:54:19.000000000 +0200
48049 +++ lighttpd-1.4.12/tests/core-keepalive.t      2006-07-11 22:07:53.000000000 +0300
48050 @@ -40,7 +40,7 @@
48051  
48052  GET /12345.txt HTTP/1.0
48053  Host: 123.example.org
48054 -Connection: keep-alive
48055 +Connection: close
48056  EOF
48057   );
48058  $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48059 --- lighttpd-1.4.11/tests/docroot/123/Makefile.in       2006-03-07 14:21:03.000000000 +0200
48060 +++ lighttpd-1.4.12/tests/docroot/123/Makefile.in       2006-07-11 21:48:15.000000000 +0300
48061 @@ -1,4 +1,4 @@
48062 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
48063 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
48064  # @configure_input@
48065  
48066  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
48067 @@ -42,7 +42,7 @@
48068  am__aclocal_m4_deps = $(top_srcdir)/configure.in
48069  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
48070         $(ACLOCAL_M4)
48071 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
48072 +mkinstalldirs = $(install_sh) -d
48073  CONFIG_HEADER = $(top_builddir)/config.h
48074  CONFIG_CLEAN_FILES =
48075  SOURCES =
48076 @@ -100,7 +100,6 @@
48077  LIBTOOL = @LIBTOOL@
48078  LN_S = @LN_S@
48079  LTLIBOBJS = @LTLIBOBJS@
48080 -LUACONFIG = @LUACONFIG@
48081  LUA_CFLAGS = @LUA_CFLAGS@
48082  LUA_LIBS = @LUA_LIBS@
48083  MAINT = @MAINT@
48084 @@ -143,6 +142,7 @@
48085  ac_ct_F77 = @ac_ct_F77@
48086  ac_ct_RANLIB = @ac_ct_RANLIB@
48087  ac_ct_STRIP = @ac_ct_STRIP@
48088 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
48089  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
48090  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
48091  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
48092 --- lighttpd-1.4.11/tests/docroot/Makefile.in   2006-03-07 14:21:04.000000000 +0200
48093 +++ lighttpd-1.4.12/tests/docroot/Makefile.in   2006-07-11 21:48:15.000000000 +0300
48094 @@ -1,4 +1,4 @@
48095 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
48096 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
48097  # @configure_input@
48098  
48099  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
48100 @@ -42,7 +42,7 @@
48101  am__aclocal_m4_deps = $(top_srcdir)/configure.in
48102  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
48103         $(ACLOCAL_M4)
48104 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
48105 +mkinstalldirs = $(install_sh) -d
48106  CONFIG_HEADER = $(top_builddir)/config.h
48107  CONFIG_CLEAN_FILES =
48108  SOURCES =
48109 @@ -109,7 +109,6 @@
48110  LIBTOOL = @LIBTOOL@
48111  LN_S = @LN_S@
48112  LTLIBOBJS = @LTLIBOBJS@
48113 -LUACONFIG = @LUACONFIG@
48114  LUA_CFLAGS = @LUA_CFLAGS@
48115  LUA_LIBS = @LUA_LIBS@
48116  MAINT = @MAINT@
48117 @@ -152,6 +151,7 @@
48118  ac_ct_F77 = @ac_ct_F77@
48119  ac_ct_RANLIB = @ac_ct_RANLIB@
48120  ac_ct_STRIP = @ac_ct_STRIP@
48121 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
48122  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
48123  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
48124  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
48125 --- lighttpd-1.4.11/tests/docroot/www/Makefile.in       2006-03-07 14:21:05.000000000 +0200
48126 +++ lighttpd-1.4.12/tests/docroot/www/Makefile.in       2006-07-11 21:48:15.000000000 +0300
48127 @@ -1,4 +1,4 @@
48128 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
48129 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
48130  # @configure_input@
48131  
48132  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
48133 @@ -42,7 +42,7 @@
48134  am__aclocal_m4_deps = $(top_srcdir)/configure.in
48135  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
48136         $(ACLOCAL_M4)
48137 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
48138 +mkinstalldirs = $(install_sh) -d
48139  CONFIG_HEADER = $(top_builddir)/config.h
48140  CONFIG_CLEAN_FILES =
48141  SOURCES =
48142 @@ -109,7 +109,6 @@
48143  LIBTOOL = @LIBTOOL@
48144  LN_S = @LN_S@
48145  LTLIBOBJS = @LTLIBOBJS@
48146 -LUACONFIG = @LUACONFIG@
48147  LUA_CFLAGS = @LUA_CFLAGS@
48148  LUA_LIBS = @LUA_LIBS@
48149  MAINT = @MAINT@
48150 @@ -152,6 +151,7 @@
48151  ac_ct_F77 = @ac_ct_F77@
48152  ac_ct_RANLIB = @ac_ct_RANLIB@
48153  ac_ct_STRIP = @ac_ct_STRIP@
48154 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
48155  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
48156  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
48157  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
48158 --- lighttpd-1.4.11/tests/docroot/www/dummydir/.svn/entries     2006-03-09 19:21:49.000000000 +0200
48159 +++ lighttpd-1.4.12/tests/docroot/www/dummydir/.svn/entries     2006-07-11 22:07:54.000000000 +0300
48160 @@ -9,5 +9,6 @@
48161     last-author="jan"
48162     kind="dir"
48163     uuid="152afb58-edef-0310-8abb-c4023f1b3aa9"
48164 -   revision="1040"/>
48165 +   repos="svn://svn.lighttpd.net/lighttpd"
48166 +   revision="1154"/>
48167  </wc-entries>
48168 --- lighttpd-1.4.11/tests/docroot/www/expire/Makefile.in        2006-03-07 14:21:05.000000000 +0200
48169 +++ lighttpd-1.4.12/tests/docroot/www/expire/Makefile.in        2006-07-11 21:48:15.000000000 +0300
48170 @@ -1,4 +1,4 @@
48171 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
48172 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
48173  # @configure_input@
48174  
48175  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
48176 @@ -42,7 +42,7 @@
48177  am__aclocal_m4_deps = $(top_srcdir)/configure.in
48178  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
48179         $(ACLOCAL_M4)
48180 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
48181 +mkinstalldirs = $(install_sh) -d
48182  CONFIG_HEADER = $(top_builddir)/config.h
48183  CONFIG_CLEAN_FILES =
48184  SOURCES =
48185 @@ -100,7 +100,6 @@
48186  LIBTOOL = @LIBTOOL@
48187  LN_S = @LN_S@
48188  LTLIBOBJS = @LTLIBOBJS@
48189 -LUACONFIG = @LUACONFIG@
48190  LUA_CFLAGS = @LUA_CFLAGS@
48191  LUA_LIBS = @LUA_LIBS@
48192  MAINT = @MAINT@
48193 @@ -143,6 +142,7 @@
48194  ac_ct_F77 = @ac_ct_F77@
48195  ac_ct_RANLIB = @ac_ct_RANLIB@
48196  ac_ct_STRIP = @ac_ct_STRIP@
48197 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
48198  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
48199  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
48200  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
48201 --- lighttpd-1.4.11/tests/docroot/www/go/Makefile.in    2006-03-07 14:21:06.000000000 +0200
48202 +++ lighttpd-1.4.12/tests/docroot/www/go/Makefile.in    2006-07-11 21:48:16.000000000 +0300
48203 @@ -1,4 +1,4 @@
48204 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
48205 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
48206  # @configure_input@
48207  
48208  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
48209 @@ -42,7 +42,7 @@
48210  am__aclocal_m4_deps = $(top_srcdir)/configure.in
48211  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
48212         $(ACLOCAL_M4)
48213 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
48214 +mkinstalldirs = $(install_sh) -d
48215  CONFIG_HEADER = $(top_builddir)/config.h
48216  CONFIG_CLEAN_FILES =
48217  SOURCES =
48218 @@ -100,7 +100,6 @@
48219  LIBTOOL = @LIBTOOL@
48220  LN_S = @LN_S@
48221  LTLIBOBJS = @LTLIBOBJS@
48222 -LUACONFIG = @LUACONFIG@
48223  LUA_CFLAGS = @LUA_CFLAGS@
48224  LUA_LIBS = @LUA_LIBS@
48225  MAINT = @MAINT@
48226 @@ -143,6 +142,7 @@
48227  ac_ct_F77 = @ac_ct_F77@
48228  ac_ct_RANLIB = @ac_ct_RANLIB@
48229  ac_ct_STRIP = @ac_ct_STRIP@
48230 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
48231  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
48232  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
48233  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
48234 --- lighttpd-1.4.11/tests/docroot/www/indexfile/Makefile.in     2006-03-07 14:21:07.000000000 +0200
48235 +++ lighttpd-1.4.12/tests/docroot/www/indexfile/Makefile.in     2006-07-11 21:48:16.000000000 +0300
48236 @@ -1,4 +1,4 @@
48237 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
48238 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
48239  # @configure_input@
48240  
48241  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
48242 @@ -42,7 +42,7 @@
48243  am__aclocal_m4_deps = $(top_srcdir)/configure.in
48244  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
48245         $(ACLOCAL_M4)
48246 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
48247 +mkinstalldirs = $(install_sh) -d
48248  CONFIG_HEADER = $(top_builddir)/config.h
48249  CONFIG_CLEAN_FILES =
48250  SOURCES =
48251 @@ -100,7 +100,6 @@
48252  LIBTOOL = @LIBTOOL@
48253  LN_S = @LN_S@
48254  LTLIBOBJS = @LTLIBOBJS@
48255 -LUACONFIG = @LUACONFIG@
48256  LUA_CFLAGS = @LUA_CFLAGS@
48257  LUA_LIBS = @LUA_LIBS@
48258  MAINT = @MAINT@
48259 @@ -143,6 +142,7 @@
48260  ac_ct_F77 = @ac_ct_F77@
48261  ac_ct_RANLIB = @ac_ct_RANLIB@
48262  ac_ct_STRIP = @ac_ct_STRIP@
48263 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
48264  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
48265  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
48266  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
48267 --- lighttpd-1.4.11/tests/fastcgi-10.conf       2005-08-31 23:36:34.000000000 +0300
48268 +++ lighttpd-1.4.12/tests/fastcgi-10.conf       2006-07-11 22:07:53.000000000 +0300
48269 @@ -1,12 +1,12 @@
48270 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48271 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48272 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48273 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48274  
48275  ## bind to port (default: 80)
48276  server.port                 = 2048
48277  
48278  ## bind to localhost (default: all interfaces)
48279  server.bind                = "localhost"
48280 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48281 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48282  server.name                = "www.example.org"
48283  server.tag                 = "Apache 1.3.29"
48284  
48285 @@ -44,7 +44,7 @@
48286  ######################## MODULE CONFIG ############################
48287  
48288  
48289 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48290 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48291  
48292  mimetype.assign             = ( ".png"  => "image/png", 
48293                                  ".jpg"  => "image/jpeg",
48294 @@ -62,7 +62,7 @@
48295                                 ".c"    => "text/plain",
48296                                 ".conf" => "text/plain" )
48297  
48298 -compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48299 +compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48300  compress.filetype           = ("text/plain", "text/html")
48301  
48302  fastcgi.debug               = 0
48303 @@ -85,7 +85,7 @@
48304  ssl.pemfile                 = "server.pem"
48305  
48306  auth.backend                = "plain"
48307 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48308 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48309  auth.backend.plain.groupfile = "lighttpd.group"
48310  
48311  auth.backend.ldap.hostname  = "localhost"
48312 @@ -128,11 +128,11 @@
48313  status.config-url           = "/server-config"
48314  
48315  $HTTP["host"] == "vvv.example.org" {
48316 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48317 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48318  }
48319  
48320  $HTTP["host"] == "zzz.example.org" {
48321 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48322 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48323    server.name = "zzz.example.org"
48324  }
48325  
48326 --- lighttpd-1.4.11/tests/fastcgi-13.conf       2006-01-03 12:38:17.000000000 +0200
48327 +++ lighttpd-1.4.12/tests/fastcgi-13.conf       2006-07-11 22:07:53.000000000 +0300
48328 @@ -1,5 +1,5 @@
48329 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48330 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48331 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48332 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48333  
48334  debug.log-request-header   = "enable"
48335  debug.log-response-header  = "enable"
48336 @@ -10,7 +10,7 @@
48337  
48338  ## bind to localhost (default: all interfaces)
48339  server.bind                = "localhost"
48340 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48341 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48342  server.name                = "www.example.org"
48343  server.tag                 = "Apache 1.3.29"
48344  
48345 @@ -59,7 +59,7 @@
48346  ######################## MODULE CONFIG ############################
48347  
48348  
48349 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48350 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48351  
48352  mimetype.assign             = ( ".png"  => "image/png", 
48353                                  ".jpg"  => "image/jpeg",
48354 @@ -77,7 +77,7 @@
48355                                 ".c"    => "text/plain",
48356                                 ".conf" => "text/plain" )
48357  
48358 -compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48359 +compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48360  compress.filetype           = ("text/plain", "text/html")
48361  
48362  fastcgi.debug               = 0
48363 @@ -102,7 +102,7 @@
48364  ssl.pemfile                 = "server.pem"
48365  
48366  auth.backend                = "plain"
48367 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48368 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48369  auth.backend.plain.groupfile = "lighttpd.group"
48370  
48371  auth.backend.ldap.hostname  = "localhost"
48372 @@ -145,11 +145,11 @@
48373  status.config-url           = "/server-config"
48374  
48375  $HTTP["host"] == "vvv.example.org" {
48376 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48377 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48378  }
48379  
48380  $HTTP["host"] == "zzz.example.org" {
48381 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48382 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48383    server.name = "zzz.example.org"
48384  }
48385  
48386 --- lighttpd-1.4.11/tests/fastcgi-auth.conf     2005-08-27 17:44:19.000000000 +0300
48387 +++ lighttpd-1.4.12/tests/fastcgi-auth.conf     2006-07-11 22:07:53.000000000 +0300
48388 @@ -1,5 +1,5 @@
48389 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48390 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48391 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48392 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48393  
48394  debug.log-request-header   = "enable"
48395  debug.log-response-header  = "enable"
48396 @@ -12,7 +12,7 @@
48397  
48398  ## bind to localhost (default: all interfaces)
48399  server.bind                = "localhost"
48400 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48401 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48402  server.name                = "www.example.org"
48403  server.tag                 = "Apache 1.3.29"
48404  
48405 @@ -61,7 +61,7 @@
48406  ######################## MODULE CONFIG ############################
48407  
48408  
48409 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48410 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48411  
48412  mimetype.assign             = ( ".png"  => "image/png", 
48413                                  ".jpg"  => "image/jpeg",
48414 @@ -79,7 +79,7 @@
48415                                 ".c"    => "text/plain",
48416                                 ".conf" => "text/plain" )
48417  
48418 -compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48419 +compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48420  compress.filetype           = ("text/plain", "text/html")
48421  
48422  fastcgi.debug               = 0
48423 @@ -87,9 +87,9 @@
48424                                    "grisu" => ( 
48425                                     "host" => "127.0.0.1",
48426                                     "port" => 20000,
48427 -                                   "bin-path" => "@SRCDIR@/fcgi-auth",
48428 +                                   "bin-path" => env.SRCDIR + "/fcgi-auth",
48429                                      "mode" => "authorizer",
48430 -                                    "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
48431 +                                    "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
48432                                     
48433                                   )
48434                                 )
48435 @@ -106,7 +106,7 @@
48436  ssl.pemfile                 = "server.pem"
48437  
48438  auth.backend                = "plain"
48439 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48440 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48441  auth.backend.plain.groupfile = "lighttpd.group"
48442  
48443  auth.backend.ldap.hostname  = "localhost"
48444 @@ -149,11 +149,11 @@
48445  status.config-url           = "/server-config"
48446  
48447  $HTTP["host"] == "vvv.example.org" {
48448 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48449 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48450  }
48451  
48452  $HTTP["host"] == "zzz.example.org" {
48453 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48454 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48455    server.name = "zzz.example.org"
48456  }
48457  
48458 --- lighttpd-1.4.11/tests/fastcgi-responder.conf        2005-08-27 17:44:19.000000000 +0300
48459 +++ lighttpd-1.4.12/tests/fastcgi-responder.conf        2006-07-11 22:07:53.000000000 +0300
48460 @@ -1,5 +1,5 @@
48461 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48462 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48463 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48464 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48465  
48466  #debug.log-request-header   = "enable"
48467  #debug.log-response-header  = "enable"
48468 @@ -15,7 +15,7 @@
48469  
48470  ## bind to localhost (default: all interfaces)
48471  server.bind                = "localhost"
48472 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48473 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48474  server.name                = "www.example.org"
48475  server.tag                 = "Apache 1.3.29"
48476  
48477 @@ -64,7 +64,7 @@
48478  ######################## MODULE CONFIG ############################
48479  
48480  
48481 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48482 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48483  
48484  mimetype.assign             = ( ".png"  => "image/png", 
48485                                  ".jpg"  => "image/jpeg",
48486 @@ -82,7 +82,7 @@
48487                                 ".c"    => "text/plain",
48488                                 ".conf" => "text/plain" )
48489  
48490 -compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48491 +compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48492  compress.filetype           = ("text/plain", "text/html")
48493  
48494  fastcgi.debug               = 0
48495 @@ -90,10 +90,11 @@
48496                                    "grisu" => ( 
48497                                     "host" => "127.0.0.1",
48498                                     "port" => 10000,
48499 -                                   "bin-path" => "@SRCDIR@/fcgi-responder",
48500 +                                   "bin-path" => env.SRCDIR + "/fcgi-responder",
48501                                     "check-local" => "disable",
48502                                     "max-procs" => 1,
48503 -                                   "min-procs" => 1
48504 +                                   "min-procs" => 1,
48505 +                                   "allow-x-send-file" => "enable",
48506                                   )
48507                                 )
48508                               )
48509 @@ -109,7 +110,7 @@
48510  ssl.pemfile                 = "server.pem"
48511  
48512  auth.backend                = "plain"
48513 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48514 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48515  auth.backend.plain.groupfile = "lighttpd.group"
48516  
48517  auth.backend.ldap.hostname  = "localhost"
48518 @@ -152,11 +153,11 @@
48519  status.config-url           = "/server-config"
48520  
48521  $HTTP["host"] == "vvv.example.org" {
48522 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48523 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48524  }
48525  
48526  $HTTP["host"] == "zzz.example.org" {
48527 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48528 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48529    server.name = "zzz.example.org"
48530  }
48531  
48532 --- lighttpd-1.4.11/tests/fcgi-responder.c      2005-08-11 01:26:55.000000000 +0300
48533 +++ lighttpd-1.4.12/tests/fcgi-responder.c      2006-07-11 22:07:53.000000000 +0300
48534 @@ -6,11 +6,17 @@
48535  int main () {
48536         int num_requests = 2;
48537         
48538 -       while (num_requests > 0 &&
48539 -              FCGI_Accept() >= 0) {
48540 -               char* p;
48541 -               
48542 -               if (NULL != (p = getenv("QUERY_STRING"))) {
48543 +       while (num_requests > 0 && FCGI_Accept() >= 0) {
48544 +               char* p = NULL;
48545 +               char* doc_root = NULL;
48546 +               char fname[4096];
48547 +               char* pfname = (char *)fname;
48548 +
48549 +               doc_root = getenv("DOCUMENT_ROOT");
48550 +               p = getenv("QUERY_STRING");
48551 +
48552 +               if (NULL != p && NULL != doc_root) {
48553 +                       snprintf(pfname, sizeof(fname), "%s/phpinfo.php", doc_root);
48554                         if (0 == strcmp(p, "lf")) {
48555                                 printf("Status: 200 OK\n\n");
48556                         } else if (0 == strcmp(p, "crlf")) {
48557 @@ -23,6 +29,18 @@
48558                                 printf("Status: 200 OK\r\n");
48559                                 fflush(stdout);
48560                                 printf("\r\n");
48561 +                       } else if (0 == strcmp(p,"x-lighttpd-send-file")) {
48562 +                               printf("Status: 200 OK\r\n");
48563 +                               printf("X-LIGHTTPD-send-file: %s\r\n", pfname);
48564 +                               printf("\r\n");
48565 +                       } else if (0 == strcmp(p,"xsendfile")) {
48566 +                               printf("Status: 200 OK\r\n");
48567 +                               printf("X-Sendfile: %s\r\n", pfname);
48568 +                               printf("\r\n");
48569 +                       } else if (0 == strcmp(p,"xsendfile-mixed-case")) {
48570 +                               printf("Status: 200 OK\r\n");
48571 +                               printf("X-SeNdFiLe: %s\r\n", pfname);
48572 +                               printf("\r\n");
48573                         } else if (0 == strcmp(p, "die-at-end")) {
48574                                 printf("Status: 200 OK\r\n\r\n");
48575                                 num_requests--;
48576 --- lighttpd-1.4.11/tests/lighttpd.conf 2006-03-09 15:26:58.000000000 +0200
48577 +++ lighttpd-1.4.12/tests/lighttpd.conf 2006-07-11 22:07:53.000000000 +0300
48578 @@ -1,80 +1,18 @@
48579 -debug.log-request-handling = "enable"
48580 -debug.log-condition-handling = "enable"
48581 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48582 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48583 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48584 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48585 +server.tag = "Apache 1.3.29"
48586  
48587  ## 64 Mbyte ... nice limit
48588  server.max-request-size = 65000
48589  
48590 -## bind to port (default: 80)
48591 -server.port                 = 2048
48592 +include "default.conf"
48593  
48594 -## bind to localhost (default: all interfaces)
48595 -server.bind                = "localhost"
48596 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48597 -server.name                = "www.example.org"
48598 -server.tag                 = "Apache 1.3.29"
48599 -
48600 -server.dir-listing          = "enable"
48601 -
48602 -#server.event-handler        = "linux-sysepoll"
48603 -#server.event-handler        = "linux-rtsig"
48604 -
48605 -#server.modules.path         = ""
48606 -server.modules              = ( 
48607 -                               "mod_rewrite",
48608 -                               "mod_setenv",
48609 -                               "mod_secdownload",
48610 -                               "mod_access", 
48611 -                               "mod_auth",
48612 -#                              "mod_httptls",
48613 -                               "mod_status", 
48614 -                               "mod_expire",
48615 -                               "mod_simple_vhost",
48616 -                               "mod_redirect", 
48617 -#                              "mod_evhost",
48618 -#                              "mod_localizer",
48619 -                               "mod_fastcgi",
48620 -                               "mod_cgi",
48621 -                               "mod_compress",
48622 -                               "mod_userdir",
48623 -                               "mod_ssi",
48624 -                               "mod_accesslog" ) 
48625 -
48626 -server.indexfiles           = ( "index.php", "index.html", 
48627 -                                "index.htm", "default.htm" )
48628 -
48629 -
48630 -######################## MODULE CONFIG ############################
48631 -
48632 -ssi.extension = ( ".shtml" )
48633 -
48634 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48635 -
48636 -mimetype.assign             = ( ".png"  => "image/png", 
48637 -                                ".jpg"  => "image/jpeg",
48638 -                                ".jpeg" => "image/jpeg",
48639 -                                ".gif"  => "image/gif",
48640 -                                ".html" => "text/html",
48641 -                                ".htm"  => "text/html",
48642 -                                ".pdf"  => "application/pdf",
48643 -                                ".swf"  => "application/x-shockwave-flash",
48644 -                                ".spl"  => "application/futuresplash",
48645 -                                ".txt"  => "text/plain",
48646 -                                ".tar.gz" =>   "application/x-tgz",
48647 -                                ".tgz"  => "application/x-tgz",
48648 -                                ".gz"   => "application/x-gzip",
48649 -                               ".c"    => "text/plain",
48650 -                               ".conf" => "text/plain" )
48651 +setenv.add-request-header   = ( "FOO" => "foo")
48652 +setenv.add-response-header  = ( "BAR" => "foo")
48653  
48654  $HTTP["host"] == "cache.example.org" {
48655 -  compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48656 +  compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48657  }
48658 -compress.filetype           = ("text/plain", "text/html")
48659 -
48660 -setenv.add-environment      = ( "TRAC_ENV" => "tracenv", "SETENV" => "setenv")
48661 -setenv.add-request-header   = ( "FOO" => "foo")
48662 -setenv.add-response-header  = ( "BAR" => "foo")
48663  
48664  $HTTP["url"] =~ "\.pdf$" {
48665    server.range-requests = "disable"
48666 @@ -85,76 +23,31 @@
48667                                 "/prefix.fcgi" => ( ( "host" => "127.0.0.1", "port" => 1026, "check-local" => "disable", "broken-scriptfilename" => "enable" ) )
48668                               )
48669                 
48670 -
48671 -cgi.assign                  = ( ".pl"  => "/usr/bin/perl",
48672 -                                ".cgi" => "/usr/bin/perl",
48673 -                               ".py"  => "/usr/bin/python" )
48674 -                       
48675 -userdir.include-user = ( "jan" )
48676 -userdir.path = "/"
48677 -
48678 -ssl.engine                  = "disable"
48679 -ssl.pemfile                 = "server.pem"
48680 -
48681  $HTTP["host"] == "auth-htpasswd.example.org" {
48682         auth.backend                = "htpasswd"
48683  }
48684  
48685 -auth.backend                = "plain"
48686 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48687 -
48688 -auth.backend.htpasswd.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.htpasswd"
48689 -
48690 -
48691 -auth.require                = ( "/server-status" => 
48692 -                                ( 
48693 -                                 "method"  => "digest",
48694 -                                 "realm"   => "download archiv",
48695 -                                 "require" => "group=www|user=jan|host=192.168.2.10"
48696 -                               ),
48697 -                               "/server-config" => 
48698 -                                ( 
48699 -                                 "method"  => "basic",
48700 -                                 "realm"   => "download archiv",
48701 -                                 "require" => "valid-user"
48702 -                               )
48703 -                              )
48704 -
48705 -url.access-deny             = ( "~", ".inc")
48706 -
48707 -url.rewrite                = ( "^/rewrite/foo($|\?.+)" => "/indexfile/rewrite.php$1",
48708 -                               "^/rewrite/bar(?:$|\?(.+))" => "/indexfile/rewrite.php?bar&$1" )
48709 -
48710 -expire.url                  = ( "/expire/access" => "access 2 hours", 
48711 -                               "/expire/modification" => "access plus 1 seconds 2 minutes")
48712 -
48713 -#cache.cache-dir             = "/home/weigon/wwwroot/cache/"
48714 -
48715 -#### status module
48716 -status.status-url           = "/server-status"
48717 -status.config-url           = "/server-config"
48718 -
48719  $HTTP["host"] == "vvv.example.org" {
48720 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48721 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48722    secdownload.secret          = "verysecret"
48723 -  secdownload.document-root   = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48724 +  secdownload.document-root   = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48725    secdownload.uri-prefix      = "/sec/"
48726    secdownload.timeout         = 120
48727  }
48728  
48729  $HTTP["host"] == "zzz.example.org" {
48730 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48731 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48732    server.name = "zzz.example.org"
48733  }
48734  
48735  $HTTP["host"] == "no-simple.example.org" {
48736 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/123.example.org/pages/"
48737 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/123.example.org/pages/"
48738    server.name = "zzz.example.org"
48739  }
48740  
48741  $HTTP["host"] !~ "(no-simple\.example\.org)" {
48742    simple-vhost.document-root  = "pages"
48743 -  simple-vhost.server-root    = "@SRCDIR@/tmp/lighttpd/servers/"
48744 +  simple-vhost.server-root    = env.SRCDIR + "/tmp/lighttpd/servers/"
48745    simple-vhost.default-host   = "www.example.org"
48746  }
48747  
48748 --- lighttpd-1.4.11/tests/lowercase.conf        1970-01-01 03:00:00.000000000 +0300
48749 +++ lighttpd-1.4.12/tests/lowercase.conf        2006-07-11 22:07:53.000000000 +0300
48750 @@ -0,0 +1,80 @@
48751 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48752 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48753 +
48754 +## bind to port (default: 80)
48755 +server.port                 = 2048
48756 +
48757 +## bind to localhost (default: all interfaces)
48758 +server.bind                = "localhost"
48759 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48760 +
48761 +server.force-lowercase-filenames = "enable"
48762 +
48763 +server.dir-listing          = "enable"
48764 +
48765 +server.modules              = ( 
48766 +                               "mod_rewrite",
48767 +                               "mod_setenv",
48768 +                               "mod_secdownload",
48769 +                               "mod_access", 
48770 +                               "mod_auth",
48771 +                               "mod_status", 
48772 +                               "mod_expire",
48773 +                               "mod_redirect", 
48774 +                               "mod_fastcgi",
48775 +                               "mod_cgi" ) 
48776 +
48777 +server.indexfiles           = ( "index.php", "index.html", 
48778 +                                "index.htm", "default.htm" )
48779 +
48780 +
48781 +######################## MODULE CONFIG ############################
48782 +
48783 +mimetype.assign             = ( ".png"  => "image/png", 
48784 +                                ".jpg"  => "image/jpeg",
48785 +                                ".jpeg" => "image/jpeg",
48786 +                                ".gif"  => "image/gif",
48787 +                                ".html" => "text/html",
48788 +                                ".htm"  => "text/html",
48789 +                                ".pdf"  => "application/pdf",
48790 +                                ".swf"  => "application/x-shockwave-flash",
48791 +                                ".spl"  => "application/futuresplash",
48792 +                                ".txt"  => "text/plain",
48793 +                                ".tar.gz" =>   "application/x-tgz",
48794 +                                ".tgz"  => "application/x-tgz",
48795 +                                ".gz"   => "application/x-gzip",
48796 +                               ".c"    => "text/plain",
48797 +                               ".conf" => "text/plain" )
48798 +
48799 +fastcgi.debug               = 0
48800 +fastcgi.server              = ( ".php" =>        ( ( "host" => "127.0.0.1", "port" => 1026, "broken-scriptfilename" => "enable" ) ),
48801 +                               "/prefix.fcgi" => ( ( "host" => "127.0.0.1", "port" => 1026, "check-local" => "disable", "broken-scriptfilename" => "enable" ) )
48802 +                             )
48803 +               
48804 +
48805 +cgi.assign                  = ( ".pl"  => "/usr/bin/perl",
48806 +                                ".cgi" => "/usr/bin/perl",
48807 +                               ".py"  => "/usr/bin/python" )
48808 +                       
48809 +auth.backend                = "plain"
48810 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48811 +
48812 +auth.backend.htpasswd.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.htpasswd"
48813 +
48814 +$HTTP["host"] == "lowercase-auth" {
48815 +  auth.require             = ( "/image.jpg" => 
48816 +                                ( 
48817 +                                 "method"  => "digest",
48818 +                                 "realm"   => "download archiv",
48819 +                                 "require" => "valid-user"
48820 +                               )
48821 +                              )
48822 +}
48823 +
48824 +$HTTP["host"] == "lowercase-deny" {
48825 +  url.access-deny             = ( ".jpg")
48826 +}
48827 +
48828 +$HTTP["host"] == "lowercase-exclude" {
48829 +  static-file.exclude-extensions = ( ".jpg" )
48830 +}
48831 --- lighttpd-1.4.11/tests/lowercase.t   1970-01-01 03:00:00.000000000 +0300
48832 +++ lighttpd-1.4.12/tests/lowercase.t   2006-07-11 22:07:53.000000000 +0300
48833 @@ -0,0 +1,94 @@
48834 +#!/usr/bin/env perl
48835 +BEGIN {
48836 +    # add current source dir to the include-path
48837 +    # we need this for make distcheck
48838 +   (my $srcdir = $0) =~ s#/[^/]+$#/#;
48839 +   unshift @INC, $srcdir;
48840 +}
48841 +
48842 +use strict;
48843 +use IO::Socket;
48844 +use Test::More tests => 10;
48845 +use LightyTest;
48846 +
48847 +my $tf = LightyTest->new();
48848 +my $t;
48849 +
48850 +$tf->{CONFIGFILE} = 'lowercase.conf';
48851 +    
48852 +ok($tf->start_proc == 0, "Starting lighttpd") or die();
48853 +
48854 +## check if lower-casing works
48855 +
48856 +$t->{REQUEST}  = ( <<EOF
48857 +GET /image.JPG HTTP/1.0
48858 +EOF
48859 + );
48860 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48861 +ok($tf->handle_http($t) == 0, 'uppercase access');
48862 +
48863 +$t->{REQUEST}  = ( <<EOF
48864 +GET /image.jpg HTTP/1.0
48865 +EOF
48866 + );
48867 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48868 +ok($tf->handle_http($t) == 0, 'lowercase access');
48869 +
48870 +## check that mod-auth works
48871 +
48872 +$t->{REQUEST}  = ( <<EOF
48873 +GET /image.JPG HTTP/1.0
48874 +Host: lowercase-auth
48875 +EOF
48876 + );
48877 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
48878 +ok($tf->handle_http($t) == 0, 'uppercase access');
48879 +
48880 +$t->{REQUEST}  = ( <<EOF
48881 +GET /image.jpg HTTP/1.0
48882 +Host: lowercase-auth
48883 +EOF
48884 + );
48885 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
48886 +ok($tf->handle_http($t) == 0, 'lowercase access');
48887 +
48888 +
48889 +## check that mod-staticfile exclude works
48890 +$t->{REQUEST}  = ( <<EOF
48891 +GET /image.JPG HTTP/1.0
48892 +Host: lowercase-exclude
48893 +EOF
48894 + );
48895 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48896 +ok($tf->handle_http($t) == 0, 'upper case access to staticfile.exclude-extension');
48897 +
48898 +$t->{REQUEST}  = ( <<EOF
48899 +GET /image.jpg HTTP/1.0
48900 +Host: lowercase-exclude
48901 +EOF
48902 + );
48903 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48904 +ok($tf->handle_http($t) == 0, 'lowercase access');
48905 +
48906 +
48907 +## check that mod-access exclude works
48908 +$t->{REQUEST}  = ( <<EOF
48909 +GET /image.JPG HTTP/1.0
48910 +Host: lowercase-deny
48911 +EOF
48912 + );
48913 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48914 +ok($tf->handle_http($t) == 0, 'uppercase access to url.access-deny protected location');
48915 +
48916 +$t->{REQUEST}  = ( <<EOF
48917 +GET /image.jpg HTTP/1.0
48918 +Host: lowercase-deny
48919 +EOF
48920 + );
48921 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
48922 +ok($tf->handle_http($t) == 0, 'lowercase access');
48923 +
48924 +
48925 +
48926 +ok($tf->stop_proc == 0, "Stopping lighttpd");
48927 +
48928 --- lighttpd-1.4.11/tests/mod-fastcgi.t 2006-03-09 15:30:45.000000000 +0200
48929 +++ lighttpd-1.4.12/tests/mod-fastcgi.t 2006-07-11 22:07:53.000000000 +0300
48930 @@ -7,7 +7,7 @@
48931  }
48932  
48933  use strict;
48934 -use Test::More tests => 47;
48935 +use Test::More tests => 49;
48936  use LightyTest;
48937  
48938  my $tf = LightyTest->new();
48939 @@ -15,7 +15,7 @@
48940  my $t;
48941  
48942  SKIP: {
48943 -       skip "no PHP running on port 1026", 30 unless $tf->listening_on(1026);
48944 +       skip "no PHP running on port 1026", 29 unless $tf->listening_on(1026);
48945  
48946         ok($tf->start_proc == 0, "Starting lighttpd") or die();
48947  
48948 @@ -223,7 +223,7 @@
48949  }
48950  
48951  SKIP: {
48952 -       skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php"; 
48953 +       skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php";
48954         $tf->{CONFIGFILE} = 'fastcgi-13.conf';
48955         ok($tf->start_proc == 0, "Starting lighttpd with $tf->{CONFIGFILE}") or die();
48956         $t->{REQUEST}  = ( <<EOF
48957 @@ -285,6 +285,34 @@
48958         $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'test123' } ];
48959         ok($tf->handle_http($t) == 0, 'line-ending \r\n + \r\n');
48960  
48961 +    # X-LIGHTTPD-send-file
48962 +       $t->{REQUEST}  = ( <<EOF
48963 +GET /index.fcgi?x-lighttpd-send-file HTTP/1.0
48964 +Host: www.example.org
48965 +EOF
48966 + );
48967 +       $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48968 +' } ];
48969 +       ok($tf->handle_http($t) == 0, 'X-LIGHTTPD-send-file');
48970 +    # X-Sendfile
48971 +       $t->{REQUEST}  = ( <<EOF
48972 +GET /index.fcgi?xsendfile HTTP/1.0
48973 +Host: www.example.org
48974 +EOF
48975 + );
48976 +       $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48977 +' } ];
48978 +       ok($tf->handle_http($t) == 0, 'X-Sendfile');
48979 +
48980 +       $t->{REQUEST}  = ( <<EOF
48981 +GET /index.fcgi?xsendfile-mixed-case HTTP/1.0
48982 +Host: www.example.org
48983 +EOF
48984 + );
48985 +       $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48986 +' } ];
48987 +       ok($tf->handle_http($t) == 0, 'X-SeNdFiLe in mixed case');
48988 +
48989         $t->{REQUEST}  = ( <<EOF
48990  GET /index.fcgi?die-at-end HTTP/1.0
48991  Host: www.example.org
48992 --- lighttpd-1.4.11/tests/mod-proxy.t   1970-01-01 03:00:00.000000000 +0300
48993 +++ lighttpd-1.4.12/tests/mod-proxy.t   2006-07-11 22:07:53.000000000 +0300
48994 @@ -0,0 +1,173 @@
48995 +#!/usr/bin/env perl
48996 +BEGIN {
48997 +    # add current source dir to the include-path
48998 +    # we need this for make distcheck
48999 +   (my $srcdir = $0) =~ s#/[^/]+$#/#;
49000 +   unshift @INC, $srcdir;
49001 +}
49002 +
49003 +use strict;
49004 +use IO::Socket;
49005 +use Test::More tests => 21;
49006 +use LightyTest;
49007 +
49008 +my $tf_proxy = LightyTest->new();
49009 +my $tf_backend1 = LightyTest->new();
49010 +my $tf_backend2 = LightyTest->new();
49011 +
49012 +my $t;
49013 +
49014 +## we need two procs
49015 +## 1. the real webserver
49016 +## 2. the proxy server
49017 +
49018 +$tf_proxy->{PORT} = 2048;
49019 +$tf_proxy->{CONFIGFILE} = 'proxy.conf';
49020 +$tf_proxy->{LIGHTTPD_PIDFILE} = $tf_proxy->{SRCDIR}.'/tmp/lighttpd/lighttpd-proxy.pid';
49021 +
49022 +$tf_backend1->{PORT} = 2050;
49023 +$tf_backend1->{CONFIGFILE} = 'proxy-backend-1.conf';
49024 +$tf_backend1->{LIGHTTPD_PIDFILE} = $tf_backend1->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-1.pid';
49025 +
49026 +$tf_backend2->{PORT} = 2051;
49027 +$tf_backend2->{CONFIGFILE} = 'proxy-backend-2.conf';
49028 +$tf_backend2->{LIGHTTPD_PIDFILE} = $tf_backend2->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-2.pid';
49029 +
49030 +
49031 +ok($tf_backend1->start_proc == 0, "Starting lighttpd") or die();
49032 +
49033 +ok($tf_proxy->start_proc == 0, "Starting lighttpd as proxy") or die();
49034 +
49035 +sleep(1);
49036 +
49037 +$t->{REQUEST}  = ( <<EOF
49038 +GET /index.html HTTP/1.0
49039 +Host: www.example.org
49040 +EOF
49041 + );
49042 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
49043 +ok($tf_proxy->handle_http($t) == 0, 'valid request');
49044 +
49045 +$t->{REQUEST}  = ( <<EOF
49046 +GET /index.html HTTP/1.0
49047 +Host: www.example.org
49048 +EOF
49049 + );
49050 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Server' => 'proxy-backend-1' } ];
49051 +ok($tf_proxy->handle_http($t) == 0, 'drop Server from real server');
49052 +
49053 +$t->{REQUEST}  = ( <<EOF
49054 +GET /balance-rr/foo HTTP/1.0
49055 +Host: www.example.org
49056 +EOF
49057 + );
49058 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
49059 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - one backend');
49060 +
49061 +$t->{REQUEST}  = ( <<EOF
49062 +GET /balance-rr/foo HTTP/1.0
49063 +Host: www.example.org
49064 +EOF
49065 + );
49066 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
49067 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - one host down, failover');
49068 +
49069 +$t->{REQUEST}  = ( <<EOF
49070 +GET /balance-fair/foo HTTP/1.0
49071 +Host: www.example.org
49072 +EOF
49073 + );
49074 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
49075 +ok($tf_proxy->handle_http($t) == 0, 'balance fair - one backend');
49076 +
49077 +## backend 2 starting 
49078 +ok($tf_backend2->start_proc == 0, "Starting second proxy backend") or die();
49079 +
49080 +$t->{REQUEST}  = ( <<EOF
49081 +GET /balance-rr/foo HTTP/1.0
49082 +Host: www.example.org
49083 +EOF
49084 + );
49085 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49086 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 1');
49087 +
49088 +$t->{REQUEST}  = ( <<EOF
49089 +GET /balance-rr/foo HTTP/1.0
49090 +Host: www.example.org
49091 +EOF
49092 + );
49093 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
49094 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 2');
49095 +
49096 +$t->{REQUEST}  = ( <<EOF
49097 +GET /balance-hash/foo HTTP/1.0
49098 +Host: www.example.org
49099 +EOF
49100 + );
49101 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
49102 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1');
49103 +
49104 +$t->{REQUEST}  = ( <<EOF
49105 +GET /balance-hash/foo HTTP/1.0
49106 +Host: www.example.org
49107 +EOF
49108 + );
49109 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
49110 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1 - same URL');
49111 +
49112 +$t->{REQUEST}  = ( <<EOF
49113 +GET /balance-hash/bar HTTP/1.0
49114 +Host: www.example.org
49115 +EOF
49116 + );
49117 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49118 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2');
49119 +
49120 +$t->{REQUEST}  = ( <<EOF
49121 +GET /balance-hash/bar HTTP/1.0
49122 +Host: www.example.org
49123 +EOF
49124 + );
49125 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49126 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2 - same URL');
49127 +
49128 +## backend 1 stopping, failover 
49129 +ok($tf_backend1->stop_proc == 0, "Stopping backend 1");
49130 +
49131 +$t->{REQUEST}  = ( <<EOF
49132 +GET /balance-hash/foo HTTP/1.0
49133 +Host: www.example.org
49134 +EOF
49135 + );
49136 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49137 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2');
49138 +
49139 +$t->{REQUEST}  = ( <<EOF
49140 +GET /balance-hash/bar HTTP/1.0
49141 +Host: www.example.org
49142 +EOF
49143 + );
49144 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49145 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2 - same URL');
49146 +
49147 +$t->{REQUEST}  = ( <<EOF
49148 +GET /balance-rr/foo HTTP/1.0
49149 +Host: www.example.org
49150 +EOF
49151 + );
49152 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49153 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - failover to backend 2');
49154 +
49155 +$t->{REQUEST}  = ( <<EOF
49156 +GET /balance-fair/foo HTTP/1.0
49157 +Host: www.example.org
49158 +EOF
49159 + );
49160 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49161 +ok($tf_proxy->handle_http($t) == 0, 'balance fair - failover to backend 2');
49162 +
49163 +
49164 +ok($tf_backend2->stop_proc == 0, "Stopping lighttpd");
49165 +
49166 +ok($tf_proxy->stop_proc == 0, "Stopping lighttpd proxy");
49167 +
49168 --- lighttpd-1.4.11/tests/proxy.conf    1970-01-01 03:00:00.000000000 +0300
49169 +++ lighttpd-1.4.12/tests/proxy.conf    2006-07-11 22:07:53.000000000 +0300
49170 @@ -0,0 +1,26 @@
49171 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
49172 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd-proxy.pid"
49173 +server.tag = "proxy"
49174 +
49175 +include "default.conf"
49176 +
49177 +## 127.0.0.1 and 127.0.0.2 are the same host
49178 +proxy.server              = ( 
49179 +  "" => (( "host" => "127.0.0.1",
49180 +          "port" => 2050 ),
49181 +         ( "host" => "127.0.0.2",
49182 +           "port" => 2051 )
49183 +  ))
49184 +               
49185 +$HTTP["url"] =~ "^/balance-rr/" {
49186 +  proxy.balance = "round-robin"
49187 +}
49188 +
49189 +$HTTP["url"] =~ "^/balance-hash/" {
49190 +  proxy.balance = "hash"
49191 +}
49192 +
49193 +$HTTP["url"] =~ "^/balance-fair/" {
49194 +  proxy.balance = "fair"
49195 +}
49196 +
49197 --- lighttpd-1.4.11/tests/var-include.conf      2005-08-27 17:44:19.000000000 +0300
49198 +++ lighttpd-1.4.12/tests/var-include.conf      2006-07-11 22:07:53.000000000 +0300
49199 @@ -2,15 +2,15 @@
49200  debug.log-request-handling = "enable"
49201  debug.log-condition-handling = "enable"
49202  
49203 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
49204 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
49205 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
49206 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
49207  
49208  ## bind to port (default: 80)
49209  server.port                 = 2048
49210  
49211  ## bind to localhost (default: all interfaces)
49212  server.bind                = "localhost"
49213 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
49214 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
49215  server.name                = "www.example.org"
49216  server.tag                 = "Apache 1.3.29"
49217  
49218 @@ -21,19 +21,19 @@
49219  ######################## MODULE CONFIG ############################
49220  
49221  
49222 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
49223 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
49224  
49225  mimetype.assign             = ( ".html" => "text/html" )
49226  
49227  url.redirect = ("^" => "/default")
49228  
49229  $HTTP["host"] == "www.example.org" {
49230 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
49231 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
49232    server.name = "www.example.org"
49233    url.redirect = ("^" => "/redirect")
49234  }
49235  $HTTP["host"] == "test.example.org" {
49236 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
49237 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
49238    server.name = "test.example.org"
49239    var.myvar = "good"
49240    var.one = 1
This page took 4.873755 seconds and 2 git commands to generate.