]> git.pld-linux.org Git - packages/lighttpd.git/blob - lighttpd-branch.diff
- due missing files in previous diff, create diff from make dist in svn dir
[packages/lighttpd.git] / lighttpd-branch.diff
1 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/Makefile.in lighttpd-1.4.12/Makefile.in
2 --- lighttpd-1.4.11/Makefile.in 2006-03-07 14:21:08.000000000 +0200
3 +++ lighttpd-1.4.12/Makefile.in 2006-07-11 21:48:16.000000000 +0300
4 @@ -1,4 +1,4 @@
5 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
6 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
7  # @configure_input@
8  
9  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
10 @@ -41,7 +41,7 @@
11         $(srcdir)/distribute.sh.in $(srcdir)/lighttpd.spec.in \
12         $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
13         compile config.guess config.sub depcomp install-sh ltmain.sh \
14 -       missing mkinstalldirs
15 +       missing
16  subdir = .
17  ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
18  am__aclocal_m4_deps = $(top_srcdir)/configure.in
19 @@ -49,7 +49,7 @@
20         $(ACLOCAL_M4)
21  am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
22   configure.lineno configure.status.lineno
23 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
24 +mkinstalldirs = $(install_sh) -d
25  CONFIG_HEADER = config.h
26  CONFIG_CLEAN_FILES = lighttpd.spec distribute.sh
27  SOURCES =
28 @@ -126,7 +126,6 @@
29  LIBTOOL = @LIBTOOL@
30  LN_S = @LN_S@
31  LTLIBOBJS = @LTLIBOBJS@
32 -LUACONFIG = @LUACONFIG@
33  LUA_CFLAGS = @LUA_CFLAGS@
34  LUA_LIBS = @LUA_LIBS@
35  MAINT = @MAINT@
36 @@ -169,6 +168,7 @@
37  ac_ct_F77 = @ac_ct_F77@
38  ac_ct_RANLIB = @ac_ct_RANLIB@
39  ac_ct_STRIP = @ac_ct_STRIP@
40 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
41  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
42  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
43  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
44 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/NEWS lighttpd-1.4.12/NEWS
45 --- lighttpd-1.4.11/NEWS        2006-03-09 19:34:33.000000000 +0200
46 +++ lighttpd-1.4.12/NEWS        2006-07-11 21:23:42.000000000 +0300
47 @@ -3,6 +3,23 @@
48  NEWS
49  ====
50  
51 +- 1.4.12 - 2006-..-..
52 +
53 +  * added handling of Content-Range to PUT requests in mod_webdav
54 +  * added handling of ETag and If-Modified-Since to mod_compress if 
55 +    cache-dir is not set
56 +  * added experimental LOCK support for mod_webdav 
57 +  * added support for X-Sendfile as addition to X-LIGHTTPD-send-file.
58 +    This allows compatibility with mod_xsendfile for apache
59 +    (http://celebnamer.celebworld.ws/stuff/mod_xsendfile/)
60 +  * fixed handling of If-Modified-Since if Etag is not set
61 +  * fixed hanging fastcgi connections
62 +  * fixed stalling SSL POST requests 
63 +  * fixed round-robin load-balancing in mod_proxy
64 +  * TODO: add fail-over to mod-proxy
65 +  * TODO: fix CACHE_HIT/MISS in mod_cml
66 +  * TODO: finish LOCK/UNLOCK in mod_webdav
67 +
68  - 1.4.11 - 2006-03-09
69  
70    * added ability to specify which ip address spawn-fci listens on 
71 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/configure.in lighttpd-1.4.12/configure.in
72 --- lighttpd-1.4.11/configure.in        2006-03-04 16:32:38.000000000 +0200
73 +++ lighttpd-1.4.12/configure.in        2006-07-11 21:23:42.000000000 +0300
74 @@ -1,7 +1,7 @@
75  #                                               -*- Autoconf -*-
76  # Process this file with autoconf to produce a configure script.
77  AC_PREREQ(2.57)
78 -AC_INIT(lighttpd, 1.4.11, jan@kneschke.de)
79 +AC_INIT(lighttpd, 1.4.12, jan@kneschke.de)
80  AC_CONFIG_SRCDIR([src/server.c])
81  
82  AC_CANONICAL_TARGET
83 @@ -66,7 +66,7 @@
84  AC_TYPE_PID_T
85  AC_TYPE_SIZE_T
86  
87 -AC_CHECK_MEMBER(struct tm.tm_gmtoff,AC_DEFINE([HAVE_STRUCT_TM_GMTOFF],[1],[gmtoff in struct tm]),,[#include <time.h>])
88 +AC_CHECK_MEMBER(struct tm.tm_gmtoff,[AC_DEFINE([HAVE_STRUCT_TM_GMTOFF],[1],[gmtoff in struct tm])],,[#include <time.h>])
89  AC_CHECK_TYPES(struct sockaddr_storage,,,[#include <sys/socket.h>])
90  AC_CHECK_TYPES(socklen_t,,,[#include <sys/types.h>
91  #include <sys/socket.h>])
92 @@ -339,6 +339,22 @@
93      AC_DEFINE([HAVE_SQLITE3], [1], [libsqlite3])
94      AC_DEFINE([HAVE_SQLITE3_H], [1], [sqlite3.h])
95   ])
96 +
97 + AC_MSG_CHECKING(for locks in mod_webdav)
98 + AC_ARG_WITH(webdav-locks, AC_HELP_STRING([--with-webdav-locks],[locks in mod_webdav]),
99 + [WITH_WEBDAV_LOCKS=$withval],[WITH_WEBDAV_LOCKS=no])
100 + AC_MSG_RESULT([$WITH_WEBDAV_LOCKS])
101 +
102 + if test "$WITH_WEBDAV_LOCKS" != "no"; then
103 +   AC_CHECK_LIB(uuid, uuid_unparse, [
104 +         AC_CHECK_HEADERS([uuid/uuid.h],[
105 +                 UUID_LIB=-luuid
106 +                 AC_DEFINE([HAVE_UUID], [1], [libuuid])
107 +                AC_DEFINE([HAVE_UUID_H], [1], [uuid/uuid.h is available])
108 +         ])
109 + ])
110 +
111 + fi
112  fi
113  
114  dnl Check for gdbm
115 @@ -381,30 +397,11 @@
116  
117  AC_MSG_RESULT($WITH_LUA)
118  if test "$WITH_LUA" != "no"; then
119 - AC_PATH_PROG(LUACONFIG, lua-config)
120 -
121 - if test x"$LUACONFIG" != x; then
122 -   LUA_CFLAGS=`$LUACONFIG --include`
123 -   LUA_LIBS=`$LUACONFIG --libs --extralibs`
124 + # try pkgconfig
125 + PKG_CHECK_MODULES(LUA, lua >= 5.1, [
126     AC_DEFINE([HAVE_LUA], [1], [liblua])
127     AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
128 - else
129 -   AC_CHECK_LIB(lua, lua_open, [
130 -     AC_CHECK_HEADERS([lua.h],[
131 -       LUA_LIBS="-llua -llualib"
132 -       AC_DEFINE([HAVE_LUA], [1], [liblua])
133 -       AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
134 -     ])
135 -   ])
136 - fi
137 -
138 - if test x"$LUA_LIBS" = x; then
139 -   # try pkgconfig
140 -   PKG_CHECK_MODULES(LUA, lua, [
141 -     AC_DEFINE([HAVE_LUA], [1], [liblua])
142 -     AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
143 -   ])
144 - fi
145 + ])
146  
147   AC_SUBST(LUA_CFLAGS)
148   AC_SUBST(LUA_LIBS)
149 @@ -440,7 +437,7 @@
150  esac
151  
152  AC_CHECK_FUNCS([dup2 getcwd inet_ntoa inet_ntop memset mmap munmap strchr \
153 -                 strdup strerror strstr strtol sendfile  getopt socket \
154 +                 strdup strerror strstr strtol sendfile  getopt socket lstat \
155                   gethostbyname poll sigtimedwait epoll_ctl getrlimit chroot \
156                   getuid select signal pathconf madvise posix_fadvise posix_madvise \
157                   writev sigaction sendfile64 send_file kqueue port_create localtime_r])
158 @@ -538,7 +535,7 @@
159  AC_OUTPUT
160  
161  
162 -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" 
163 +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" 
164  
165  plugins="mod_rewrite mod_redirect mod_ssi mod_trigger_b4_dl"
166  features="regex-conditionals"
167 @@ -642,6 +639,14 @@
168         disable_feature="$disable_feature $features"
169  fi
170  
171 +features="webdav-locks"
172 +if test "x$UUID_LIB" \!= x; then
173 +       enable_feature="$enable_feature $features"
174 +else
175 +       disable_feature="$disable_feature $features"
176 +fi
177 +
178 +
179  ## output
180  
181  $ECHO
182 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/cygwin/Makefile.in lighttpd-1.4.12/cygwin/Makefile.in
183 --- lighttpd-1.4.11/cygwin/Makefile.in  2006-03-07 14:20:57.000000000 +0200
184 +++ lighttpd-1.4.12/cygwin/Makefile.in  2006-07-11 21:48:12.000000000 +0300
185 @@ -1,4 +1,4 @@
186 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
187 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
188  # @configure_input@
189  
190  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
191 @@ -43,7 +43,7 @@
192  am__aclocal_m4_deps = $(top_srcdir)/configure.in
193  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
194         $(ACLOCAL_M4)
195 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
196 +mkinstalldirs = $(install_sh) -d
197  CONFIG_HEADER = $(top_builddir)/config.h
198  CONFIG_CLEAN_FILES = lighttpd.README
199  SOURCES =
200 @@ -101,7 +101,6 @@
201  LIBTOOL = @LIBTOOL@
202  LN_S = @LN_S@
203  LTLIBOBJS = @LTLIBOBJS@
204 -LUACONFIG = @LUACONFIG@
205  LUA_CFLAGS = @LUA_CFLAGS@
206  LUA_LIBS = @LUA_LIBS@
207  MAINT = @MAINT@
208 @@ -144,6 +143,7 @@
209  ac_ct_F77 = @ac_ct_F77@
210  ac_ct_RANLIB = @ac_ct_RANLIB@
211  ac_ct_STRIP = @ac_ct_STRIP@
212 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
213  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
214  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
215  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
216 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/cygwin/lighttpd.README lighttpd-1.4.12/cygwin/lighttpd.README
217 --- lighttpd-1.4.11/cygwin/lighttpd.README      2006-03-07 14:22:19.000000000 +0200
218 +++ lighttpd-1.4.12/cygwin/lighttpd.README      2006-07-11 21:49:09.000000000 +0300
219 @@ -1,114 +1,114 @@
220 -lighttpd\r
221 -------------------------------------------\r
222 -A fast, secure and flexible webserver\r
223 -\r
224 -Runtime requirements:\r
225 -  cygwin-1.5.10 or newer\r
226 -  crypt-1.1 or newer\r
227 -  libbz2_1-1.0.2 or newer\r
228 -  libpcre0-4.5 or newer\r
229 -  openssl-0.9.7d or newer\r
230 -  zlib-1.2.1 or newer\r
231 -\r
232 -Build requirements:\r
233 -  cygwin-1.5.10 or newer\r
234 -  gcc-3.3.1-3 or newer\r
235 -  binutils-20030901-1 or newer\r
236 -  crypt\r
237 -  openssl-devel\r
238 -  openssl\r
239 -  openldap\r
240 -  openldap-devel\r
241 -  zlib\r
242 -  bzip2\r
243 -\r
244 -Canonical homepage:\r
245 -  http://jan.kneschke.de/projects/lighttpd/\r
246 -\r
247 -Canonical download:\r
248 -  http://jan.kneschke.de/projects/lighttpd/download\r
249 -\r
250 -------------------------------------\r
251 -\r
252 -Build instructions:\r
253 -  unpack lighttpd-1.4.11-<REL>-src.tar.bz2\r
254 -    if you use setup to install this src package, it will be\r
255 -        unpacked under /usr/src automatically\r
256 -  cd /usr/src\r
257 -  ./lighttpd-1.4.11-<REL>.sh all\r
258 -\r
259 -This will create:\r
260 -  /usr/src/lighttpd-1.4.11-<REL>.tar.bz2\r
261 -  /usr/src/lighttpd-1.4.11-<REL>-src.tar.bz2\r
262 -\r
263 -Or use './lighttpd-1.4.11-<REL>.sh prep' to get a patched source directory\r
264 -\r
265 --------------------------------------------\r
266 -\r
267 -Files included in the binary distribution:\r
268 -\r
269 -  /etc/lighttpd/lighttpd.conf.default\r
270 -  /usr/lib/cyglightcomp.dll\r
271 -  /usr/lib/lighttpd/mod_access.dll\r
272 -  /usr/lib/lighttpd/mod_accesslog.dll\r
273 -  /usr/lib/lighttpd/mod_auth.dll\r
274 -  /usr/lib/lighttpd/mod_cgi.dll\r
275 -  /usr/lib/lighttpd/mod_compress.dll\r
276 -  /usr/lib/lighttpd/mod_evhost.dll\r
277 -  /usr/lib/lighttpd/mod_expire.dll\r
278 -  /usr/lib/lighttpd/mod_fastcgi.dll\r
279 -  /usr/lib/lighttpd/mod_httptls.dll\r
280 -  /usr/lib/lighttpd/mod_maps.dll\r
281 -  /usr/lib/lighttpd/mod_proxy.dll\r
282 -  /usr/lib/lighttpd/mod_redirect.dll\r
283 -  /usr/lib/lighttpd/mod_rewrite.dll\r
284 -  /usr/lib/lighttpd/mod_rrdtool.dll\r
285 -  /usr/lib/lighttpd/mod_secdownload.dll\r
286 -  /usr/lib/lighttpd/mod_simple_vhost.dll\r
287 -  /usr/lib/lighttpd/mod_ssi.dll\r
288 -  /usr/lib/lighttpd/mod_status.dll\r
289 -  /usr/lib/lighttpd/mod_usertrack.dll\r
290 -  /usr/sbin/lighttpd.exe\r
291 -  /usr/share/doc/Cygwin/lighttpd-1.3.0.README\r
292 -  /usr/share/doc/lighttpd-1.3.0/accesslog.txt\r
293 -  /usr/share/doc/lighttpd-1.3.0/authentification.txt\r
294 -  /usr/share/doc/lighttpd-1.3.0/AUTHORS\r
295 -  /usr/share/doc/lighttpd-1.3.0/cgi.txt\r
296 -  /usr/share/doc/lighttpd-1.3.0/ChangeLog\r
297 -  /usr/share/doc/lighttpd-1.3.0/compress.txt\r
298 -  /usr/share/doc/lighttpd-1.3.0/configuration.txt\r
299 -  /usr/share/doc/lighttpd-1.3.0/COPYING\r
300 -  /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt\r
301 -  /usr/share/doc/lighttpd-1.3.0/fastcgi.txt\r
302 -  /usr/share/doc/lighttpd-1.3.0/features.txt\r
303 -  /usr/share/doc/lighttpd-1.3.0/INSTALL\r
304 -  /usr/share/doc/lighttpd-1.3.0/NEWS\r
305 -  /usr/share/doc/lighttpd-1.3.0/performance.txt\r
306 -  /usr/share/doc/lighttpd-1.3.0/plugins.txt\r
307 -  /usr/share/doc/lighttpd-1.3.0/proxy.txt\r
308 -  /usr/share/doc/lighttpd-1.3.0/README\r
309 -  /usr/share/doc/lighttpd-1.3.0/redirect.txt\r
310 -  /usr/share/doc/lighttpd-1.3.0/rewrite.txt\r
311 -  /usr/share/doc/lighttpd-1.3.0/rrdtool.txt\r
312 -  /usr/share/doc/lighttpd-1.3.0/secdownload.txt\r
313 -  /usr/share/doc/lighttpd-1.3.0/security.txt\r
314 -  /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt\r
315 -  /usr/share/doc/lighttpd-1.3.0/skeleton.txt\r
316 -  /usr/share/doc/lighttpd-1.3.0/ssi.txt\r
317 -  /usr/share/doc/lighttpd-1.3.0/state.txt\r
318 -  /usr/share/man/man1/lighttpd.1.gz\r
319 -\r
320 -------------------\r
321 -\r
322 -Port Notes:\r
323 -\r
324 -----------  lighttpd-1.3.1-1 -----------\r
325 -\r
326 -Updated to 1.3.1\r
327 -\r
328 -----------  lighttpd-1.3.0-1 -----------\r
329 -Initial release\r
330 -\r
331 -Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>\r
332 -Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>\r
333 -\r
334 +lighttpd
335 +------------------------------------------
336 +A fast, secure and flexible webserver
337 +
338 +Runtime requirements:
339 +  cygwin-1.5.10 or newer
340 +  crypt-1.1 or newer
341 +  libbz2_1-1.0.2 or newer
342 +  libpcre0-4.5 or newer
343 +  openssl-0.9.7d or newer
344 +  zlib-1.2.1 or newer
345 +
346 +Build requirements:
347 +  cygwin-1.5.10 or newer
348 +  gcc-3.3.1-3 or newer
349 +  binutils-20030901-1 or newer
350 +  crypt
351 +  openssl-devel
352 +  openssl
353 +  openldap
354 +  openldap-devel
355 +  zlib
356 +  bzip2
357 +
358 +Canonical homepage:
359 +  http://jan.kneschke.de/projects/lighttpd/
360 +
361 +Canonical download:
362 +  http://jan.kneschke.de/projects/lighttpd/download
363 +
364 +------------------------------------
365 +
366 +Build instructions:
367 +  unpack lighttpd-1.4.12-<REL>-src.tar.bz2
368 +    if you use setup to install this src package, it will be
369 +        unpacked under /usr/src automatically
370 +  cd /usr/src
371 +  ./lighttpd-1.4.12-<REL>.sh all
372 +
373 +This will create:
374 +  /usr/src/lighttpd-1.4.12-<REL>.tar.bz2
375 +  /usr/src/lighttpd-1.4.12-<REL>-src.tar.bz2
376 +
377 +Or use './lighttpd-1.4.12-<REL>.sh prep' to get a patched source directory
378 +
379 +-------------------------------------------
380 +
381 +Files included in the binary distribution:
382 +
383 +  /etc/lighttpd/lighttpd.conf.default
384 +  /usr/lib/cyglightcomp.dll
385 +  /usr/lib/lighttpd/mod_access.dll
386 +  /usr/lib/lighttpd/mod_accesslog.dll
387 +  /usr/lib/lighttpd/mod_auth.dll
388 +  /usr/lib/lighttpd/mod_cgi.dll
389 +  /usr/lib/lighttpd/mod_compress.dll
390 +  /usr/lib/lighttpd/mod_evhost.dll
391 +  /usr/lib/lighttpd/mod_expire.dll
392 +  /usr/lib/lighttpd/mod_fastcgi.dll
393 +  /usr/lib/lighttpd/mod_httptls.dll
394 +  /usr/lib/lighttpd/mod_maps.dll
395 +  /usr/lib/lighttpd/mod_proxy.dll
396 +  /usr/lib/lighttpd/mod_redirect.dll
397 +  /usr/lib/lighttpd/mod_rewrite.dll
398 +  /usr/lib/lighttpd/mod_rrdtool.dll
399 +  /usr/lib/lighttpd/mod_secdownload.dll
400 +  /usr/lib/lighttpd/mod_simple_vhost.dll
401 +  /usr/lib/lighttpd/mod_ssi.dll
402 +  /usr/lib/lighttpd/mod_status.dll
403 +  /usr/lib/lighttpd/mod_usertrack.dll
404 +  /usr/sbin/lighttpd.exe
405 +  /usr/share/doc/Cygwin/lighttpd-1.3.0.README
406 +  /usr/share/doc/lighttpd-1.3.0/accesslog.txt
407 +  /usr/share/doc/lighttpd-1.3.0/authentification.txt
408 +  /usr/share/doc/lighttpd-1.3.0/AUTHORS
409 +  /usr/share/doc/lighttpd-1.3.0/cgi.txt
410 +  /usr/share/doc/lighttpd-1.3.0/ChangeLog
411 +  /usr/share/doc/lighttpd-1.3.0/compress.txt
412 +  /usr/share/doc/lighttpd-1.3.0/configuration.txt
413 +  /usr/share/doc/lighttpd-1.3.0/COPYING
414 +  /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
415 +  /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
416 +  /usr/share/doc/lighttpd-1.3.0/features.txt
417 +  /usr/share/doc/lighttpd-1.3.0/INSTALL
418 +  /usr/share/doc/lighttpd-1.3.0/NEWS
419 +  /usr/share/doc/lighttpd-1.3.0/performance.txt
420 +  /usr/share/doc/lighttpd-1.3.0/plugins.txt
421 +  /usr/share/doc/lighttpd-1.3.0/proxy.txt
422 +  /usr/share/doc/lighttpd-1.3.0/README
423 +  /usr/share/doc/lighttpd-1.3.0/redirect.txt
424 +  /usr/share/doc/lighttpd-1.3.0/rewrite.txt
425 +  /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
426 +  /usr/share/doc/lighttpd-1.3.0/secdownload.txt
427 +  /usr/share/doc/lighttpd-1.3.0/security.txt
428 +  /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
429 +  /usr/share/doc/lighttpd-1.3.0/skeleton.txt
430 +  /usr/share/doc/lighttpd-1.3.0/ssi.txt
431 +  /usr/share/doc/lighttpd-1.3.0/state.txt
432 +  /usr/share/man/man1/lighttpd.1.gz
433 +
434 +------------------
435 +
436 +Port Notes:
437 +
438 +----------  lighttpd-1.3.1-1 -----------
439 +
440 +Updated to 1.3.1
441 +
442 +----------  lighttpd-1.3.0-1 -----------
443 +Initial release
444 +
445 +Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
446 +Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
447 +
448 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/cygwin/lighttpd.README.in lighttpd-1.4.12/cygwin/lighttpd.README.in
449 --- lighttpd-1.4.11/cygwin/lighttpd.README.in   2005-08-11 01:26:59.000000000 +0300
450 +++ lighttpd-1.4.12/cygwin/lighttpd.README.in   2006-07-11 21:23:40.000000000 +0300
451 @@ -1,114 +1,114 @@
452 -lighttpd\r
453 -------------------------------------------\r
454 -A fast, secure and flexible webserver\r
455 -\r
456 -Runtime requirements:\r
457 -  cygwin-1.5.10 or newer\r
458 -  crypt-1.1 or newer\r
459 -  libbz2_1-1.0.2 or newer\r
460 -  libpcre0-4.5 or newer\r
461 -  openssl-0.9.7d or newer\r
462 -  zlib-1.2.1 or newer\r
463 -\r
464 -Build requirements:\r
465 -  cygwin-1.5.10 or newer\r
466 -  gcc-3.3.1-3 or newer\r
467 -  binutils-20030901-1 or newer\r
468 -  crypt\r
469 -  openssl-devel\r
470 -  openssl\r
471 -  openldap\r
472 -  openldap-devel\r
473 -  zlib\r
474 -  bzip2\r
475 -\r
476 -Canonical homepage:\r
477 -  http://jan.kneschke.de/projects/lighttpd/\r
478 -\r
479 -Canonical download:\r
480 -  http://jan.kneschke.de/projects/lighttpd/download\r
481 -\r
482 -------------------------------------\r
483 -\r
484 -Build instructions:\r
485 -  unpack lighttpd-@VERSION@-<REL>-src.tar.bz2\r
486 -    if you use setup to install this src package, it will be\r
487 -        unpacked under /usr/src automatically\r
488 -  cd /usr/src\r
489 -  ./lighttpd-@VERSION@-<REL>.sh all\r
490 -\r
491 -This will create:\r
492 -  /usr/src/lighttpd-@VERSION@-<REL>.tar.bz2\r
493 -  /usr/src/lighttpd-@VERSION@-<REL>-src.tar.bz2\r
494 -\r
495 -Or use './lighttpd-@VERSION@-<REL>.sh prep' to get a patched source directory\r
496 -\r
497 --------------------------------------------\r
498 -\r
499 -Files included in the binary distribution:\r
500 -\r
501 -  /etc/lighttpd/lighttpd.conf.default\r
502 -  /usr/lib/cyglightcomp.dll\r
503 -  /usr/lib/lighttpd/mod_access.dll\r
504 -  /usr/lib/lighttpd/mod_accesslog.dll\r
505 -  /usr/lib/lighttpd/mod_auth.dll\r
506 -  /usr/lib/lighttpd/mod_cgi.dll\r
507 -  /usr/lib/lighttpd/mod_compress.dll\r
508 -  /usr/lib/lighttpd/mod_evhost.dll\r
509 -  /usr/lib/lighttpd/mod_expire.dll\r
510 -  /usr/lib/lighttpd/mod_fastcgi.dll\r
511 -  /usr/lib/lighttpd/mod_httptls.dll\r
512 -  /usr/lib/lighttpd/mod_maps.dll\r
513 -  /usr/lib/lighttpd/mod_proxy.dll\r
514 -  /usr/lib/lighttpd/mod_redirect.dll\r
515 -  /usr/lib/lighttpd/mod_rewrite.dll\r
516 -  /usr/lib/lighttpd/mod_rrdtool.dll\r
517 -  /usr/lib/lighttpd/mod_secdownload.dll\r
518 -  /usr/lib/lighttpd/mod_simple_vhost.dll\r
519 -  /usr/lib/lighttpd/mod_ssi.dll\r
520 -  /usr/lib/lighttpd/mod_status.dll\r
521 -  /usr/lib/lighttpd/mod_usertrack.dll\r
522 -  /usr/sbin/lighttpd.exe\r
523 -  /usr/share/doc/Cygwin/lighttpd-1.3.0.README\r
524 -  /usr/share/doc/lighttpd-1.3.0/accesslog.txt\r
525 -  /usr/share/doc/lighttpd-1.3.0/authentification.txt\r
526 -  /usr/share/doc/lighttpd-1.3.0/AUTHORS\r
527 -  /usr/share/doc/lighttpd-1.3.0/cgi.txt\r
528 -  /usr/share/doc/lighttpd-1.3.0/ChangeLog\r
529 -  /usr/share/doc/lighttpd-1.3.0/compress.txt\r
530 -  /usr/share/doc/lighttpd-1.3.0/configuration.txt\r
531 -  /usr/share/doc/lighttpd-1.3.0/COPYING\r
532 -  /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt\r
533 -  /usr/share/doc/lighttpd-1.3.0/fastcgi.txt\r
534 -  /usr/share/doc/lighttpd-1.3.0/features.txt\r
535 -  /usr/share/doc/lighttpd-1.3.0/INSTALL\r
536 -  /usr/share/doc/lighttpd-1.3.0/NEWS\r
537 -  /usr/share/doc/lighttpd-1.3.0/performance.txt\r
538 -  /usr/share/doc/lighttpd-1.3.0/plugins.txt\r
539 -  /usr/share/doc/lighttpd-1.3.0/proxy.txt\r
540 -  /usr/share/doc/lighttpd-1.3.0/README\r
541 -  /usr/share/doc/lighttpd-1.3.0/redirect.txt\r
542 -  /usr/share/doc/lighttpd-1.3.0/rewrite.txt\r
543 -  /usr/share/doc/lighttpd-1.3.0/rrdtool.txt\r
544 -  /usr/share/doc/lighttpd-1.3.0/secdownload.txt\r
545 -  /usr/share/doc/lighttpd-1.3.0/security.txt\r
546 -  /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt\r
547 -  /usr/share/doc/lighttpd-1.3.0/skeleton.txt\r
548 -  /usr/share/doc/lighttpd-1.3.0/ssi.txt\r
549 -  /usr/share/doc/lighttpd-1.3.0/state.txt\r
550 -  /usr/share/man/man1/lighttpd.1.gz\r
551 -\r
552 -------------------\r
553 -\r
554 -Port Notes:\r
555 -\r
556 -----------  lighttpd-1.3.1-1 -----------\r
557 -\r
558 -Updated to 1.3.1\r
559 -\r
560 -----------  lighttpd-1.3.0-1 -----------\r
561 -Initial release\r
562 -\r
563 -Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>\r
564 -Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>\r
565 -\r
566 +lighttpd
567 +------------------------------------------
568 +A fast, secure and flexible webserver
569 +
570 +Runtime requirements:
571 +  cygwin-1.5.10 or newer
572 +  crypt-1.1 or newer
573 +  libbz2_1-1.0.2 or newer
574 +  libpcre0-4.5 or newer
575 +  openssl-0.9.7d or newer
576 +  zlib-1.2.1 or newer
577 +
578 +Build requirements:
579 +  cygwin-1.5.10 or newer
580 +  gcc-3.3.1-3 or newer
581 +  binutils-20030901-1 or newer
582 +  crypt
583 +  openssl-devel
584 +  openssl
585 +  openldap
586 +  openldap-devel
587 +  zlib
588 +  bzip2
589 +
590 +Canonical homepage:
591 +  http://jan.kneschke.de/projects/lighttpd/
592 +
593 +Canonical download:
594 +  http://jan.kneschke.de/projects/lighttpd/download
595 +
596 +------------------------------------
597 +
598 +Build instructions:
599 +  unpack lighttpd-@VERSION@-<REL>-src.tar.bz2
600 +    if you use setup to install this src package, it will be
601 +        unpacked under /usr/src automatically
602 +  cd /usr/src
603 +  ./lighttpd-@VERSION@-<REL>.sh all
604 +
605 +This will create:
606 +  /usr/src/lighttpd-@VERSION@-<REL>.tar.bz2
607 +  /usr/src/lighttpd-@VERSION@-<REL>-src.tar.bz2
608 +
609 +Or use './lighttpd-@VERSION@-<REL>.sh prep' to get a patched source directory
610 +
611 +-------------------------------------------
612 +
613 +Files included in the binary distribution:
614 +
615 +  /etc/lighttpd/lighttpd.conf.default
616 +  /usr/lib/cyglightcomp.dll
617 +  /usr/lib/lighttpd/mod_access.dll
618 +  /usr/lib/lighttpd/mod_accesslog.dll
619 +  /usr/lib/lighttpd/mod_auth.dll
620 +  /usr/lib/lighttpd/mod_cgi.dll
621 +  /usr/lib/lighttpd/mod_compress.dll
622 +  /usr/lib/lighttpd/mod_evhost.dll
623 +  /usr/lib/lighttpd/mod_expire.dll
624 +  /usr/lib/lighttpd/mod_fastcgi.dll
625 +  /usr/lib/lighttpd/mod_httptls.dll
626 +  /usr/lib/lighttpd/mod_maps.dll
627 +  /usr/lib/lighttpd/mod_proxy.dll
628 +  /usr/lib/lighttpd/mod_redirect.dll
629 +  /usr/lib/lighttpd/mod_rewrite.dll
630 +  /usr/lib/lighttpd/mod_rrdtool.dll
631 +  /usr/lib/lighttpd/mod_secdownload.dll
632 +  /usr/lib/lighttpd/mod_simple_vhost.dll
633 +  /usr/lib/lighttpd/mod_ssi.dll
634 +  /usr/lib/lighttpd/mod_status.dll
635 +  /usr/lib/lighttpd/mod_usertrack.dll
636 +  /usr/sbin/lighttpd.exe
637 +  /usr/share/doc/Cygwin/lighttpd-1.3.0.README
638 +  /usr/share/doc/lighttpd-1.3.0/accesslog.txt
639 +  /usr/share/doc/lighttpd-1.3.0/authentification.txt
640 +  /usr/share/doc/lighttpd-1.3.0/AUTHORS
641 +  /usr/share/doc/lighttpd-1.3.0/cgi.txt
642 +  /usr/share/doc/lighttpd-1.3.0/ChangeLog
643 +  /usr/share/doc/lighttpd-1.3.0/compress.txt
644 +  /usr/share/doc/lighttpd-1.3.0/configuration.txt
645 +  /usr/share/doc/lighttpd-1.3.0/COPYING
646 +  /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
647 +  /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
648 +  /usr/share/doc/lighttpd-1.3.0/features.txt
649 +  /usr/share/doc/lighttpd-1.3.0/INSTALL
650 +  /usr/share/doc/lighttpd-1.3.0/NEWS
651 +  /usr/share/doc/lighttpd-1.3.0/performance.txt
652 +  /usr/share/doc/lighttpd-1.3.0/plugins.txt
653 +  /usr/share/doc/lighttpd-1.3.0/proxy.txt
654 +  /usr/share/doc/lighttpd-1.3.0/README
655 +  /usr/share/doc/lighttpd-1.3.0/redirect.txt
656 +  /usr/share/doc/lighttpd-1.3.0/rewrite.txt
657 +  /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
658 +  /usr/share/doc/lighttpd-1.3.0/secdownload.txt
659 +  /usr/share/doc/lighttpd-1.3.0/security.txt
660 +  /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
661 +  /usr/share/doc/lighttpd-1.3.0/skeleton.txt
662 +  /usr/share/doc/lighttpd-1.3.0/ssi.txt
663 +  /usr/share/doc/lighttpd-1.3.0/state.txt
664 +  /usr/share/man/man1/lighttpd.1.gz
665 +
666 +------------------
667 +
668 +Port Notes:
669 +
670 +----------  lighttpd-1.3.1-1 -----------
671 +
672 +Updated to 1.3.1
673 +
674 +----------  lighttpd-1.3.0-1 -----------
675 +Initial release
676 +
677 +Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
678 +Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
679 +
680 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/doc/Makefile.in lighttpd-1.4.12/doc/Makefile.in
681 --- lighttpd-1.4.11/doc/Makefile.in     2006-03-07 14:20:57.000000000 +0200
682 +++ lighttpd-1.4.12/doc/Makefile.in     2006-07-11 21:48:12.000000000 +0300
683 @@ -1,4 +1,4 @@
684 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
685 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
686  # @configure_input@
687  
688  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
689 @@ -43,7 +43,7 @@
690  am__aclocal_m4_deps = $(top_srcdir)/configure.in
691  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
692         $(ACLOCAL_M4)
693 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
694 +mkinstalldirs = $(install_sh) -d
695  CONFIG_HEADER = $(top_builddir)/config.h
696  CONFIG_CLEAN_FILES =
697  SOURCES =
698 @@ -105,7 +105,6 @@
699  LIBTOOL = @LIBTOOL@
700  LN_S = @LN_S@
701  LTLIBOBJS = @LTLIBOBJS@
702 -LUACONFIG = @LUACONFIG@
703  LUA_CFLAGS = @LUA_CFLAGS@
704  LUA_LIBS = @LUA_LIBS@
705  MAINT = @MAINT@
706 @@ -148,6 +147,7 @@
707  ac_ct_F77 = @ac_ct_F77@
708  ac_ct_RANLIB = @ac_ct_RANLIB@
709  ac_ct_STRIP = @ac_ct_STRIP@
710 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
711  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
712  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
713  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
714 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/doc/authentication.txt lighttpd-1.4.12/doc/authentication.txt
715 --- lighttpd-1.4.11/doc/authentication.txt      2006-01-12 20:34:26.000000000 +0200
716 +++ lighttpd-1.4.12/doc/authentication.txt      2006-07-11 21:23:42.000000000 +0300
717 @@ -7,8 +7,8 @@
718  ----------------
719  
720  :Author: Jan Kneschke
721 -:Date: $Date$
722 -:Revision: $Revision$
723 +:Date: $Date$
724 +:Revision: $Revision$
725  
726  :abstract:
727    The auth module provides ...
728 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/doc/compress.txt lighttpd-1.4.12/doc/compress.txt
729 --- lighttpd-1.4.11/doc/compress.txt    2005-08-11 01:26:16.000000000 +0300
730 +++ lighttpd-1.4.12/doc/compress.txt    2006-07-11 21:23:42.000000000 +0300
731 @@ -22,12 +22,38 @@
732  ===========
733  
734  Output compression reduces the network load and can improve the overall
735 -throughput of the webserver. 
736 +throughput of the webserver. All major http-clients support compression by
737 +announcing it in the Accept-Encoding header. This is used to negotiate the 
738 +most suitable compression method. We support deflate, gzip and bzip2.
739  
740 -Only static content is supported up to now.
741 +deflate (RFC1950, RFC1951) and gzip (RFC1952) depend on zlib while bzip2 
742 +depends on libbzip2. bzip2 is only supported by lynx and some other console
743 +text-browsers.
744  
745 -The server negotiates automaticly which compression method is used.
746 -Supported are gzip, deflate, bzip.
747 +Currently we limit to compression support to static files.
748 +
749 +Caching
750 +-------
751 +
752 +mod_compress can stored compressed files on disk to optimized the compression
753 +on a second request away. As soon as compress.cache-dir is set the files are
754 +compressed. 
755 +
756 +The names of the cache files are made of the filename, the compression method
757 +and the etag associated to the file.
758 +
759 +Cleaning the cache is left to the user. A cron job deleting files older than
760 +10 days should do fine.
761 +
762 +Limitations
763 +-----------
764 +
765 +The module limits the compression of files to files larger than 128 Byte and
766 +smaller than 128 MByte.
767 +
768 +The lower limit is set as small files tend to become larger by compressing due
769 +to the compression headers, the upper limit is set to work sensable with
770 +memory and cpu-time.
771  
772  Options
773  =======
774 @@ -47,15 +73,28 @@
775    Default: not set, compress the file for every request
776  
777  compress.filetype
778 -  mimetypes where might get compressed
779 +  mimetypes which might get compressed
780    
781    e.g.: ::
782    
783      compress.filetype           = ("text/plain", "text/html")
784  
785 +  Keep in mind that compressed JavaScript and CSS files are broken in some
786 +  browsers.
787 +
788    Default: not set
789  
790 +compress.max-file-size 
791 +  maximum size of the original file to be compressed kBytes.
792 +
793 +  This is meant to protect the server against DoSing as compressing large
794 +  (let's say 1Gbyte) takes a lot of time and would delay the whole operation
795 +  of the server.
796  
797 +  There is a hard upper limit of 128Mbyte.
798 +
799 +  Default: unlimited (== hard-limit of 128MByte)
800 +  
801  Compressing Dynamic Content
802  ===========================
803  
804 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/doc/configuration.txt lighttpd-1.4.12/doc/configuration.txt
805 --- lighttpd-1.4.11/doc/configuration.txt       2006-03-09 02:10:40.000000000 +0200
806 +++ lighttpd-1.4.12/doc/configuration.txt       2006-07-11 21:23:42.000000000 +0300
807 @@ -7,8 +7,8 @@
808  ------------
809  
810  :Author: Jan Kneschke
811 -:Date: $Date$
812 -:Revision: $Revision$
813 +:Date: $Date$
814 +:Revision: $Revision$
815  
816  :abstract:
817    the layout of the configuration file
818 @@ -511,3 +511,10 @@
819  
820  debug.log-request-handling
821    default: disabled 
822 +
823 +debug.log-condition-handling
824 +  default: disabled 
825 +
826 +debug.log-condition-cache-handling
827 +  for developers only
828 +  default: disabled 
829 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/doc/fastcgi.txt lighttpd-1.4.12/doc/fastcgi.txt
830 --- lighttpd-1.4.11/doc/fastcgi.txt     2006-02-16 17:03:52.000000000 +0200
831 +++ lighttpd-1.4.12/doc/fastcgi.txt     2006-07-11 21:23:42.000000000 +0300
832 @@ -144,8 +144,8 @@
833                  PHP can extract PATH_INFO from it (default: disabled)
834    :"disable-time": time to wait before a disabled backend is checked
835                  again
836 -  :"allow-x-send-file": controls if X-LIGHTTPD-send-file headers
837 -                are allowed 
838 +  :"allow-x-send-file": controls if X-LIGHTTPD-send-file and X-Sendfile
839 +                headers are allowed 
840  
841    If bin-path is set:
842  
843 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/doc/lighttpd.conf lighttpd-1.4.12/doc/lighttpd.conf
844 --- lighttpd-1.4.11/doc/lighttpd.conf   2006-03-04 14:41:12.000000000 +0200
845 +++ lighttpd-1.4.12/doc/lighttpd.conf   2006-07-11 21:23:42.000000000 +0300
846 @@ -172,10 +172,11 @@
847  #dir-listing.activate       = "enable"
848  
849  ## enable debugging
850 -#debug.log-request-header   = "enable"
851 -#debug.log-response-header  = "enable"
852 -#debug.log-request-handling = "enable"
853 -#debug.log-file-not-found   = "enable"
854 +#debug.log-request-header     = "enable"
855 +#debug.log-response-header    = "enable"
856 +#debug.log-request-handling   = "enable"
857 +#debug.log-file-not-found     = "enable"
858 +#debug.log-condition-handling = "enable"
859  
860  ### only root can use these options
861  #
862 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/doc/performance.txt lighttpd-1.4.12/doc/performance.txt
863 --- lighttpd-1.4.11/doc/performance.txt 2006-02-02 13:01:08.000000000 +0200
864 +++ lighttpd-1.4.12/doc/performance.txt 2006-07-11 21:23:42.000000000 +0300
865 @@ -183,6 +183,8 @@
866  
867    server.stat-cache-engine = "fam"   # either fam, simple or disabled
868  
869 +See http://oss.sgi.com/projects/fam/faq.html for information about FAM.
870 +See http://www.gnome.org/~veillard/gamin/overview.html for information about gamin.
871  
872  Platform-Specific Notes
873  =======================
874 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/doc/secdownload.txt lighttpd-1.4.12/doc/secdownload.txt
875 --- lighttpd-1.4.11/doc/secdownload.txt 2005-12-20 15:58:58.000000000 +0200
876 +++ lighttpd-1.4.12/doc/secdownload.txt 2006-07-11 21:23:42.000000000 +0300
877 @@ -118,7 +118,7 @@
878    $secret = "verysecret";
879    $uri_prefix = "/dl/";
880    
881 -  # filename
882 +  # filename, make sure it's started with a "/" or you'll get 404 in the browser
883    $f = "/secret-file.txt";
884    
885    # current timestamp
886 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/lighttpd.spec lighttpd-1.4.12/lighttpd.spec
887 --- lighttpd-1.4.11/lighttpd.spec       2006-03-07 14:22:18.000000000 +0200
888 +++ lighttpd-1.4.12/lighttpd.spec       2006-07-11 21:49:09.000000000 +0300
889 @@ -1,6 +1,6 @@
890  Summary: A fast webserver with minimal memory-footprint (lighttpd)
891  Name: lighttpd
892 -Version: 1.4.11
893 +Version: 1.4.12
894  Release: 1
895  Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-%version.tar.gz
896  Packager: Jan Kneschke <jan@kneschke.de>
897 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/openwrt/Makefile.in lighttpd-1.4.12/openwrt/Makefile.in
898 --- lighttpd-1.4.11/openwrt/Makefile.in 2006-03-07 14:20:58.000000000 +0200
899 +++ lighttpd-1.4.12/openwrt/Makefile.in 2006-07-11 21:48:12.000000000 +0300
900 @@ -1,4 +1,4 @@
901 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
902 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
903  # @configure_input@
904  
905  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
906 @@ -43,7 +43,7 @@
907  am__aclocal_m4_deps = $(top_srcdir)/configure.in
908  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
909         $(ACLOCAL_M4)
910 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
911 +mkinstalldirs = $(install_sh) -d
912  CONFIG_HEADER = $(top_builddir)/config.h
913  CONFIG_CLEAN_FILES = control lighttpd.mk
914  SOURCES =
915 @@ -101,7 +101,6 @@
916  LIBTOOL = @LIBTOOL@
917  LN_S = @LN_S@
918  LTLIBOBJS = @LTLIBOBJS@
919 -LUACONFIG = @LUACONFIG@
920  LUA_CFLAGS = @LUA_CFLAGS@
921  LUA_LIBS = @LUA_LIBS@
922  MAINT = @MAINT@
923 @@ -144,6 +143,7 @@
924  ac_ct_F77 = @ac_ct_F77@
925  ac_ct_RANLIB = @ac_ct_RANLIB@
926  ac_ct_STRIP = @ac_ct_STRIP@
927 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
928  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
929  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
930  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
931 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/openwrt/control lighttpd-1.4.12/openwrt/control
932 --- lighttpd-1.4.11/openwrt/control     2006-03-07 14:22:19.000000000 +0200
933 +++ lighttpd-1.4.12/openwrt/control     2006-07-11 21:49:10.000000000 +0300
934 @@ -1,8 +1,8 @@
935  Package: lighttpd
936 -Version: 1.4.11
937 +Version: 1.4.12
938  Architecture: mipsel
939  Maintainer: Jan Kneschke <jan@kneschke.de>
940 -Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-1.4.11.tar.gz
941 +Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-1.4.12.tar.gz
942  Section: net
943  Priority: optional
944  Depends:
945 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/openwrt/lighttpd.mk lighttpd-1.4.12/openwrt/lighttpd.mk
946 --- lighttpd-1.4.11/openwrt/lighttpd.mk 2006-03-07 14:22:19.000000000 +0200
947 +++ lighttpd-1.4.12/openwrt/lighttpd.mk 2006-07-11 21:49:10.000000000 +0300
948 @@ -10,7 +10,7 @@
949  
950  #  For this example we'll use a fairly simple package that compiles easily
951  #  and has sources available for download at sourceforge
952 -LIGHTTPD=lighttpd-1.4.11
953 +LIGHTTPD=lighttpd-1.4.12
954  LIGHTTPD_TARGET=.built
955  LIGHTTPD_DIR=$(BUILD_DIR)/$(LIGHTTPD)
956  LIGHTTPD_IPK=$(BUILD_DIR)/$(LIGHTTPD)_mipsel.ipk
957 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/Makefile.am lighttpd-1.4.12/src/Makefile.am
958 --- lighttpd-1.4.11/src/Makefile.am     2006-03-07 14:20:20.000000000 +0200
959 +++ lighttpd-1.4.12/src/Makefile.am     2006-07-11 21:23:40.000000000 +0300
960 @@ -16,14 +16,19 @@
961  else
962  configparser.y: lemon
963  mod_ssi_exprparser.y: lemon
964 +http_resp_parser.y: lemon
965  
966  configparser.c configparser.h: configparser.y
967         rm -f configparser.h
968 -       $(LEMON) -q $(srcdir)/configparser.y $(srcdir)/lempar.c
969 +       $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
970 +
971 +http_resp_parser.c http_resp_parser.h: http_resp_parser.y
972 +       rm -f http_resp_parser.h
973 +       $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
974  
975  mod_ssi_exprparser.c mod_ssi_exprparser.h: mod_ssi_exprparser.y 
976         rm -f mod_ssi_exprparser.h
977 -       $(LEMON) -q $(srcdir)/mod_ssi_exprparser.y $(srcdir)/lempar.c
978 +       $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
979  endif
980  
981  configfile.c: configparser.h
982 @@ -46,7 +51,7 @@
983        network_write.c network_linux_sendfile.c \
984        network_freebsd_sendfile.c network_writev.c \
985        network_solaris_sendfilev.c network_openssl.c \
986 -      splaytree.c 
987 +      splaytree.c http_resp.c http_resp_parser.c 
988        
989  src = server.c response.c connections.c network.c \
990        configfile.c configparser.c request.c proc_open.c
991 @@ -82,9 +87,9 @@
992  
993  lib_LTLIBRARIES += mod_webdav.la
994  mod_webdav_la_SOURCES = mod_webdav.c
995 -mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
996 +mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS) 
997  mod_webdav_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
998 -mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS)
999 +mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS) $(UUID_LIB)
1000  
1001  lib_LTLIBRARIES += mod_cml.la
1002  mod_cml_la_SOURCES = mod_cml.c mod_cml_lua.c mod_cml_funcs.c
1003 @@ -103,6 +108,11 @@
1004  mod_mysql_vhost_la_LIBADD = $(MYSQL_LIBS) $(common_libadd)
1005  mod_mysql_vhost_la_CPPFLAGS = $(MYSQL_INCLUDE)
1006  
1007 +lib_LTLIBRARIES += mod_sql_vhost_core.la
1008 +mod_sql_vhost_core_la_SOURCES = mod_sql_vhost_core.c
1009 +mod_sql_vhost_core_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1010 +mod_sql_vhost_core_la_LIBADD = $(common_libadd)
1011 +
1012  lib_LTLIBRARIES += mod_cgi.la
1013  mod_cgi_la_SOURCES = mod_cgi.c 
1014  mod_cgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1015 @@ -240,7 +250,7 @@
1016        mod_ssi.h mod_ssi_expr.h inet_ntop_cache.h \
1017        configparser.h mod_ssi_exprparser.h \
1018        sys-mmap.h sys-socket.h mod_cml.h mod_cml_funcs.h \
1019 -      splaytree.h proc_open.h
1020 +      splaytree.h proc_open.h http_resp.h mod_sql_vhost_core.h
1021  
1022  DEFS= @DEFS@ -DLIBRARY_DIR="\"$(libdir)\""
1023  
1024 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/Makefile.in lighttpd-1.4.12/src/Makefile.in
1025 --- lighttpd-1.4.11/src/Makefile.in     2006-03-07 14:21:02.000000000 +0200
1026 +++ lighttpd-1.4.12/src/Makefile.in     2006-07-11 21:48:14.000000000 +0300
1027 @@ -1,4 +1,4 @@
1028 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
1029 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
1030  # @configure_input@
1031  
1032  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
1033 @@ -16,8 +16,6 @@
1034  
1035  
1036  
1037 -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)
1038 -
1039  srcdir = @srcdir@
1040  top_srcdir = @top_srcdir@
1041  VPATH = @srcdir@
1042 @@ -57,7 +55,7 @@
1043  am__aclocal_m4_deps = $(top_srcdir)/configure.in
1044  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
1045         $(ACLOCAL_M4)
1046 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
1047 +mkinstalldirs = $(install_sh) -d
1048  CONFIG_HEADER = $(top_builddir)/config.h
1049  CONFIG_CLEAN_FILES =
1050  am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
1051 @@ -84,7 +82,8 @@
1052         inet_ntop_cache.c crc32.c connections-glue.c configfile-glue.c \
1053         http-header-glue.c network_write.c network_linux_sendfile.c \
1054         network_freebsd_sendfile.c network_writev.c \
1055 -       network_solaris_sendfilev.c network_openssl.c splaytree.c
1056 +       network_solaris_sendfilev.c network_openssl.c splaytree.c \
1057 +       http_resp.c http_resp_parser.c
1058  am__objects_1 = liblightcomp_la-buffer.lo liblightcomp_la-log.lo \
1059         liblightcomp_la-keyvalue.lo liblightcomp_la-chunk.lo \
1060         liblightcomp_la-http_chunk.lo liblightcomp_la-stream.lo \
1061 @@ -111,7 +110,8 @@
1062         liblightcomp_la-network_writev.lo \
1063         liblightcomp_la-network_solaris_sendfilev.lo \
1064         liblightcomp_la-network_openssl.lo \
1065 -       liblightcomp_la-splaytree.lo
1066 +       liblightcomp_la-splaytree.lo liblightcomp_la-http_resp.lo \
1067 +       liblightcomp_la-http_resp_parser.lo
1068  @NO_RDYNAMIC_TRUE@am_liblightcomp_la_OBJECTS = $(am__objects_1)
1069  liblightcomp_la_OBJECTS = $(am_liblightcomp_la_OBJECTS)
1070  @NO_RDYNAMIC_TRUE@am_liblightcomp_la_rpath = -rpath $(libdir)
1071 @@ -193,6 +193,9 @@
1072  mod_simple_vhost_la_DEPENDENCIES = $(am__DEPENDENCIES_2)
1073  am_mod_simple_vhost_la_OBJECTS = mod_simple_vhost.lo
1074  mod_simple_vhost_la_OBJECTS = $(am_mod_simple_vhost_la_OBJECTS)
1075 +mod_sql_vhost_core_la_DEPENDENCIES = $(am__DEPENDENCIES_2)
1076 +am_mod_sql_vhost_core_la_OBJECTS = mod_sql_vhost_core.lo
1077 +mod_sql_vhost_core_la_OBJECTS = $(am_mod_sql_vhost_core_la_OBJECTS)
1078  mod_ssi_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
1079  am_mod_ssi_la_OBJECTS = mod_ssi_exprparser.lo mod_ssi_expr.lo \
1080         mod_ssi.lo
1081 @@ -236,7 +239,8 @@
1082         connections-glue.c configfile-glue.c http-header-glue.c \
1083         network_write.c network_linux_sendfile.c \
1084         network_freebsd_sendfile.c network_writev.c \
1085 -       network_solaris_sendfilev.c network_openssl.c splaytree.c
1086 +       network_solaris_sendfilev.c network_openssl.c splaytree.c \
1087 +       http_resp.c http_resp_parser.c
1088  am__objects_2 = buffer.$(OBJEXT) log.$(OBJEXT) keyvalue.$(OBJEXT) \
1089         chunk.$(OBJEXT) http_chunk.$(OBJEXT) stream.$(OBJEXT) \
1090         fdevent.$(OBJEXT) stat_cache.$(OBJEXT) plugin.$(OBJEXT) \
1091 @@ -254,7 +258,8 @@
1092         network_linux_sendfile.$(OBJEXT) \
1093         network_freebsd_sendfile.$(OBJEXT) network_writev.$(OBJEXT) \
1094         network_solaris_sendfilev.$(OBJEXT) network_openssl.$(OBJEXT) \
1095 -       splaytree.$(OBJEXT)
1096 +       splaytree.$(OBJEXT) http_resp.$(OBJEXT) \
1097 +       http_resp_parser.$(OBJEXT)
1098  @NO_RDYNAMIC_FALSE@am__objects_3 = $(am__objects_2)
1099  am__objects_4 = server.$(OBJEXT) response.$(OBJEXT) \
1100         connections.$(OBJEXT) network.$(OBJEXT) configfile.$(OBJEXT) \
1101 @@ -282,8 +287,8 @@
1102         $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
1103         $(AM_CFLAGS) $(CFLAGS)
1104  CCLD = $(CC)
1105 -LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
1106 -       $(AM_LDFLAGS) $(LDFLAGS) -o $@
1107 +LINK = $(LIBTOOL) --tag=CC --mode=link "$(CCLD)" $(AM_CFLAGS) \
1108 +       $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
1109  SOURCES = $(liblightcomp_la_SOURCES) $(mod_access_la_SOURCES) \
1110         $(mod_accesslog_la_SOURCES) $(mod_alias_la_SOURCES) \
1111         $(mod_auth_la_SOURCES) $(mod_cgi_la_SOURCES) \
1112 @@ -296,11 +301,12 @@
1113         $(mod_rewrite_la_SOURCES) $(mod_rrdtool_la_SOURCES) \
1114         $(mod_scgi_la_SOURCES) $(mod_secdownload_la_SOURCES) \
1115         $(mod_setenv_la_SOURCES) $(mod_simple_vhost_la_SOURCES) \
1116 -       $(mod_ssi_la_SOURCES) $(mod_staticfile_la_SOURCES) \
1117 -       $(mod_status_la_SOURCES) $(mod_trigger_b4_dl_la_SOURCES) \
1118 -       $(mod_userdir_la_SOURCES) $(mod_usertrack_la_SOURCES) \
1119 -       $(mod_webdav_la_SOURCES) $(lemon_SOURCES) $(lighttpd_SOURCES) \
1120 -       $(proc_open_SOURCES) $(spawn_fcgi_SOURCES)
1121 +       $(mod_sql_vhost_core_la_SOURCES) $(mod_ssi_la_SOURCES) \
1122 +       $(mod_staticfile_la_SOURCES) $(mod_status_la_SOURCES) \
1123 +       $(mod_trigger_b4_dl_la_SOURCES) $(mod_userdir_la_SOURCES) \
1124 +       $(mod_usertrack_la_SOURCES) $(mod_webdav_la_SOURCES) \
1125 +       $(lemon_SOURCES) $(lighttpd_SOURCES) $(proc_open_SOURCES) \
1126 +       $(spawn_fcgi_SOURCES)
1127  DIST_SOURCES = $(am__liblightcomp_la_SOURCES_DIST) \
1128         $(mod_access_la_SOURCES) $(mod_accesslog_la_SOURCES) \
1129         $(mod_alias_la_SOURCES) $(mod_auth_la_SOURCES) \
1130 @@ -313,7 +319,8 @@
1131         $(mod_redirect_la_SOURCES) $(mod_rewrite_la_SOURCES) \
1132         $(mod_rrdtool_la_SOURCES) $(mod_scgi_la_SOURCES) \
1133         $(mod_secdownload_la_SOURCES) $(mod_setenv_la_SOURCES) \
1134 -       $(mod_simple_vhost_la_SOURCES) $(mod_ssi_la_SOURCES) \
1135 +       $(mod_simple_vhost_la_SOURCES) \
1136 +       $(mod_sql_vhost_core_la_SOURCES) $(mod_ssi_la_SOURCES) \
1137         $(mod_staticfile_la_SOURCES) $(mod_status_la_SOURCES) \
1138         $(mod_trigger_b4_dl_la_SOURCES) $(mod_userdir_la_SOURCES) \
1139         $(mod_usertrack_la_SOURCES) $(mod_webdav_la_SOURCES) \
1140 @@ -375,7 +382,6 @@
1141  LIBTOOL = @LIBTOOL@
1142  LN_S = @LN_S@
1143  LTLIBOBJS = @LTLIBOBJS@
1144 -LUACONFIG = @LUACONFIG@
1145  LUA_CFLAGS = @LUA_CFLAGS@
1146  LUA_LIBS = @LUA_LIBS@
1147  MAINT = @MAINT@
1148 @@ -418,6 +424,7 @@
1149  ac_ct_F77 = @ac_ct_F77@
1150  ac_ct_RANLIB = @ac_ct_RANLIB@
1151  ac_ct_STRIP = @ac_ct_STRIP@
1152 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
1153  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
1154  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
1155  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
1156 @@ -479,7 +486,7 @@
1157        network_write.c network_linux_sendfile.c \
1158        network_freebsd_sendfile.c network_writev.c \
1159        network_solaris_sendfilev.c network_openssl.c \
1160 -      splaytree.c 
1161 +      splaytree.c http_resp.c http_resp_parser.c 
1162  
1163  src = server.c response.c connections.c network.c configfile.c \
1164         configparser.c request.c proc_open.c $(am__append_2)
1165 @@ -491,10 +498,11 @@
1166  #mod_httptls_la_LIBADD = $(common_libadd)
1167  lib_LTLIBRARIES = $(am__append_1) mod_flv_streaming.la mod_evasive.la \
1168         mod_webdav.la mod_cml.la mod_trigger_b4_dl.la \
1169 -       mod_mysql_vhost.la mod_cgi.la mod_scgi.la mod_staticfile.la \
1170 -       mod_dirlisting.la mod_indexfile.la mod_setenv.la mod_alias.la \
1171 -       mod_userdir.la mod_rrdtool.la mod_usertrack.la mod_proxy.la \
1172 -       mod_ssi.la mod_secdownload.la mod_expire.la mod_evhost.la \
1173 +       mod_mysql_vhost.la mod_sql_vhost_core.la mod_cgi.la \
1174 +       mod_scgi.la mod_staticfile.la mod_dirlisting.la \
1175 +       mod_indexfile.la mod_setenv.la mod_alias.la mod_userdir.la \
1176 +       mod_rrdtool.la mod_usertrack.la mod_proxy.la mod_ssi.la \
1177 +       mod_secdownload.la mod_expire.la mod_evhost.la \
1178         mod_simple_vhost.la mod_fastcgi.la mod_access.la \
1179         mod_compress.la mod_auth.la mod_rewrite.la mod_redirect.la \
1180         mod_status.la mod_accesslog.la
1181 @@ -511,9 +519,9 @@
1182  mod_evasive_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1183  mod_evasive_la_LIBADD = $(common_libadd)
1184  mod_webdav_la_SOURCES = mod_webdav.c
1185 -mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
1186 +mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS) 
1187  mod_webdav_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1188 -mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS)
1189 +mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS) $(UUID_LIB)
1190  mod_cml_la_SOURCES = mod_cml.c mod_cml_lua.c mod_cml_funcs.c
1191  mod_cml_la_CFLAGS = $(AM_CFLAGS) $(LUA_CFLAGS)
1192  mod_cml_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1193 @@ -525,6 +533,9 @@
1194  mod_mysql_vhost_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1195  mod_mysql_vhost_la_LIBADD = $(MYSQL_LIBS) $(common_libadd)
1196  mod_mysql_vhost_la_CPPFLAGS = $(MYSQL_INCLUDE)
1197 +mod_sql_vhost_core_la_SOURCES = mod_sql_vhost_core.c
1198 +mod_sql_vhost_core_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1199 +mod_sql_vhost_core_la_LIBADD = $(common_libadd)
1200  mod_cgi_la_SOURCES = mod_cgi.c 
1201  mod_cgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
1202  mod_cgi_la_LIBADD = $(common_libadd)
1203 @@ -608,7 +619,7 @@
1204        mod_ssi.h mod_ssi_expr.h inet_ntop_cache.h \
1205        configparser.h mod_ssi_exprparser.h \
1206        sys-mmap.h sys-socket.h mod_cml.h mod_cml_funcs.h \
1207 -      splaytree.h proc_open.h
1208 +      splaytree.h proc_open.h http_resp.h mod_sql_vhost_core.h
1209  
1210  lighttpd_SOURCES = $(src)
1211  lighttpd_LDADD = $(PCRE_LIB) $(DL_LIB) $(SENDFILE_LIB) $(ATTR_LIB) $(common_libadd) $(SSL_LIB) $(FAM_LIBS)
1212 @@ -739,6 +750,8 @@
1213         $(LINK) -rpath $(libdir) $(mod_setenv_la_LDFLAGS) $(mod_setenv_la_OBJECTS) $(mod_setenv_la_LIBADD) $(LIBS)
1214  mod_simple_vhost.la: $(mod_simple_vhost_la_OBJECTS) $(mod_simple_vhost_la_DEPENDENCIES) 
1215         $(LINK) -rpath $(libdir) $(mod_simple_vhost_la_LDFLAGS) $(mod_simple_vhost_la_OBJECTS) $(mod_simple_vhost_la_LIBADD) $(LIBS)
1216 +mod_sql_vhost_core.la: $(mod_sql_vhost_core_la_OBJECTS) $(mod_sql_vhost_core_la_DEPENDENCIES) 
1217 +       $(LINK) -rpath $(libdir) $(mod_sql_vhost_core_la_LDFLAGS) $(mod_sql_vhost_core_la_OBJECTS) $(mod_sql_vhost_core_la_LIBADD) $(LIBS)
1218  mod_ssi.la: $(mod_ssi_la_OBJECTS) $(mod_ssi_la_DEPENDENCIES) 
1219         $(LINK) -rpath $(libdir) $(mod_ssi_la_LDFLAGS) $(mod_ssi_la_OBJECTS) $(mod_ssi_la_LIBADD) $(LIBS)
1220  mod_staticfile.la: $(mod_staticfile_la_OBJECTS) $(mod_staticfile_la_DEPENDENCIES) 
1221 @@ -863,6 +876,8 @@
1222  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_auth.Plo@am__quote@
1223  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_auth_digest.Plo@am__quote@
1224  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_chunk.Po@am__quote@
1225 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_resp.Po@am__quote@
1226 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_resp_parser.Po@am__quote@
1227  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inet_ntop_cache.Po@am__quote@
1228  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/joblist.Po@am__quote@
1229  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keyvalue.Po@am__quote@
1230 @@ -890,6 +905,8 @@
1231  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-fdevent_solaris_devpoll.Plo@am__quote@
1232  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-http-header-glue.Plo@am__quote@
1233  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-http_chunk.Plo@am__quote@
1234 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-http_resp.Plo@am__quote@
1235 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-http_resp_parser.Plo@am__quote@
1236  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-inet_ntop_cache.Plo@am__quote@
1237  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-joblist.Plo@am__quote@
1238  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-keyvalue.Plo@am__quote@
1239 @@ -932,6 +949,7 @@
1240  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_secure_download.Plo@am__quote@
1241  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_setenv.Plo@am__quote@
1242  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_simple_vhost.Plo@am__quote@
1243 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_sql_vhost_core.Plo@am__quote@
1244  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_ssi.Plo@am__quote@
1245  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_ssi_expr.Plo@am__quote@
1246  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_ssi_exprparser.Plo@am__quote@
1247 @@ -1247,6 +1265,20 @@
1248  @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1249  @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
1250  
1251 +liblightcomp_la-http_resp.lo: http_resp.c
1252 +@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; \
1253 +@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
1254 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='http_resp.c' object='liblightcomp_la-http_resp.lo' libtool=yes @AMDEPBACKSLASH@
1255 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1256 +@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
1257 +
1258 +liblightcomp_la-http_resp_parser.lo: http_resp_parser.c
1259 +@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; \
1260 +@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
1261 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='http_resp_parser.c' object='liblightcomp_la-http_resp_parser.lo' libtool=yes @AMDEPBACKSLASH@
1262 +@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1263 +@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
1264 +
1265  mod_cml_la-mod_cml.lo: mod_cml.c
1266  @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; \
1267  @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
1268 @@ -1506,14 +1538,19 @@
1269  @CROSS_COMPILING_TRUE@mod_ssi_exprparser.c mod_ssi_exprparser.h: 
1270  @CROSS_COMPILING_FALSE@configparser.y: lemon
1271  @CROSS_COMPILING_FALSE@mod_ssi_exprparser.y: lemon
1272 +@CROSS_COMPILING_FALSE@http_resp_parser.y: lemon
1273  
1274  @CROSS_COMPILING_FALSE@configparser.c configparser.h: configparser.y
1275  @CROSS_COMPILING_FALSE@        rm -f configparser.h
1276 -@CROSS_COMPILING_FALSE@        $(LEMON) -q $(srcdir)/configparser.y $(srcdir)/lempar.c
1277 +@CROSS_COMPILING_FALSE@        $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
1278 +
1279 +@CROSS_COMPILING_FALSE@http_resp_parser.c http_resp_parser.h: http_resp_parser.y
1280 +@CROSS_COMPILING_FALSE@        rm -f http_resp_parser.h
1281 +@CROSS_COMPILING_FALSE@        $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
1282  
1283  @CROSS_COMPILING_FALSE@mod_ssi_exprparser.c mod_ssi_exprparser.h: mod_ssi_exprparser.y 
1284  @CROSS_COMPILING_FALSE@        rm -f mod_ssi_exprparser.h
1285 -@CROSS_COMPILING_FALSE@        $(LEMON) -q $(srcdir)/mod_ssi_exprparser.y $(srcdir)/lempar.c
1286 +@CROSS_COMPILING_FALSE@        $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
1287  
1288  configfile.c: configparser.h
1289  mod_ssi_expr.c: mod_ssi_exprparser.h
1290 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/array.c lighttpd-1.4.12/src/array.c
1291 --- lighttpd-1.4.11/src/array.c 2005-11-18 13:58:32.000000000 +0200
1292 +++ lighttpd-1.4.12/src/array.c 2006-07-11 21:23:39.000000000 +0300
1293 @@ -11,12 +11,12 @@
1294  
1295  array *array_init(void) {
1296         array *a;
1297 -       
1298 +
1299         a = calloc(1, sizeof(*a));
1300         assert(a);
1301 -       
1302 +
1303         a->next_power_of_2 = 1;
1304 -       
1305 +
1306         return a;
1307  }
1308  
1309 @@ -43,29 +43,29 @@
1310  void array_free(array *a) {
1311         size_t i;
1312         if (!a) return;
1313 -       
1314 +
1315         if (!a->is_weakref) {
1316                 for (i = 0; i < a->size; i++) {
1317                         if (a->data[i]) a->data[i]->free(a->data[i]);
1318                 }
1319         }
1320 -       
1321 +
1322         if (a->data) free(a->data);
1323         if (a->sorted) free(a->sorted);
1324 -       
1325 +
1326         free(a);
1327  }
1328  
1329  void array_reset(array *a) {
1330         size_t i;
1331         if (!a) return;
1332 -       
1333 +
1334         if (!a->is_weakref) {
1335                 for (i = 0; i < a->used; i++) {
1336                         a->data[i]->reset(a->data[i]);
1337                 }
1338         }
1339 -       
1340 +
1341         a->used = 0;
1342  }
1343  
1344 @@ -84,20 +84,20 @@
1345  static int array_get_index(array *a, const char *key, size_t keylen, int *rndx) {
1346         int ndx = -1;
1347         int i, pos = 0;
1348 -       
1349 +
1350         if (key == NULL) return -1;
1351 -       
1352 +
1353         /* try to find the string */
1354         for (i = pos = a->next_power_of_2 / 2; ; i >>= 1) {
1355                 int cmp;
1356 -               
1357 +
1358                 if (pos < 0) {
1359                         pos += i;
1360                 } else if (pos >= (int)a->used) {
1361                         pos -= i;
1362                 } else {
1363                         cmp = buffer_caseless_compare(key, keylen, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used);
1364 -                       
1365 +
1366                         if (cmp == 0) {
1367                                 /* found */
1368                                 ndx = a->sorted[pos];
1369 @@ -110,46 +110,46 @@
1370                 }
1371                 if (i == 0) break;
1372         }
1373 -       
1374 +
1375         if (rndx) *rndx = pos;
1376 -       
1377 +
1378         return ndx;
1379  }
1380  
1381  data_unset *array_get_element(array *a, const char *key) {
1382         int ndx;
1383 -       
1384 +
1385         if (-1 != (ndx = array_get_index(a, key, strlen(key) + 1, NULL))) {
1386                 /* found, leave here */
1387 -               
1388 +
1389                 return a->data[ndx];
1390 -       } 
1391 -       
1392 +       }
1393 +
1394         return NULL;
1395  }
1396  
1397  data_unset *array_get_unused_element(array *a, data_type_t t) {
1398         data_unset *ds = NULL;
1399 -       
1400 +
1401         UNUSED(t);
1402  
1403         if (a->size == 0) return NULL;
1404 -       
1405 +
1406         if (a->used == a->size) return NULL;
1407  
1408         if (a->data[a->used]) {
1409                 ds = a->data[a->used];
1410 -               
1411 +
1412                 a->data[a->used] = NULL;
1413         }
1414 -       
1415 +
1416         return ds;
1417  }
1418  
1419  /* replace or insert data, return the old one with the same key */
1420  data_unset *array_replace(array *a, data_unset *du) {
1421         int ndx;
1422 -       
1423 +
1424         if (-1 == (ndx = array_get_index(a, du->key->ptr, du->key->used, NULL))) {
1425                 array_insert_unique(a, du);
1426                 return NULL;
1427 @@ -164,13 +164,13 @@
1428         int ndx = -1;
1429         int pos = 0;
1430         size_t j;
1431 -       
1432 -       /* generate unique index if neccesary */
1433 +
1434 +       /* generate unique index if necessary */
1435         if (str->key->used == 0 || str->is_index_key) {
1436                 buffer_copy_long(str->key, a->unique_ndx++);
1437                 str->is_index_key = 1;
1438         }
1439 -       
1440 +
1441         /* try to find the string */
1442         if (-1 != (ndx = array_get_index(a, str->key->ptr, str->key->used, &pos))) {
1443                 /* found, leave here */
1444 @@ -181,14 +181,14 @@
1445                 }
1446                 return 0;
1447         }
1448 -       
1449 +
1450         /* insert */
1451 -       
1452 +
1453         if (a->used+1 > INT_MAX) {
1454                 /* we can't handle more then INT_MAX entries: see array_get_index() */
1455                 return -1;
1456         }
1457 -       
1458 +
1459         if (a->size == 0) {
1460                 a->size   = 16;
1461                 a->data   = malloc(sizeof(*a->data)     * a->size);
1462 @@ -204,27 +204,27 @@
1463                 assert(a->sorted);
1464                 for (j = a->used; j < a->size; j++) a->data[j] = NULL;
1465         }
1466 -       
1467 +
1468         ndx = (int) a->used;
1469 -       
1470 +
1471         a->data[a->used++] = str;
1472 -       
1473 +
1474         if (pos != ndx &&
1475 -           ((pos < 0) || 
1476 +           ((pos < 0) ||
1477              buffer_caseless_compare(str->key->ptr, str->key->used, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used) > 0)) {
1478                 pos++;
1479 -       } 
1480 -       
1481 -       /* move everything on step to the right */
1482 +       }
1483 +
1484 +       /* move everything one step to the right */
1485         if (pos != ndx) {
1486                 memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted));
1487         }
1488 -       
1489 +
1490         /* insert */
1491         a->sorted[pos] = ndx;
1492 -       
1493 +
1494         if (a->next_power_of_2 == (size_t)ndx) a->next_power_of_2 <<= 1;
1495 -       
1496 +
1497         return 0;
1498  }
1499  
1500 @@ -254,7 +254,7 @@
1501         size_t i;
1502         size_t maxlen;
1503         int oneline = 1;
1504 -       
1505 +
1506         if (a->used > 5) {
1507                 oneline = 0;
1508         }
1509 @@ -314,7 +314,7 @@
1510         }
1511         array_print_indent(depth);
1512         fprintf(stderr, ")");
1513 -       
1514 +
1515         return 0;
1516  }
1517  
1518 @@ -323,47 +323,47 @@
1519         array *a;
1520         data_string *ds;
1521         data_count *dc;
1522 -       
1523 +
1524         UNUSED(argc);
1525         UNUSED(argv);
1526  
1527         a = array_init();
1528 -       
1529 +
1530         ds = data_string_init();
1531         buffer_copy_string(ds->key, "abc");
1532         buffer_copy_string(ds->value, "alfrag");
1533 -       
1534 +
1535         array_insert_unique(a, (data_unset *)ds);
1536 -       
1537 +
1538         ds = data_string_init();
1539         buffer_copy_string(ds->key, "abc");
1540         buffer_copy_string(ds->value, "hameplman");
1541 -       
1542 +
1543         array_insert_unique(a, (data_unset *)ds);
1544 -       
1545 +
1546         ds = data_string_init();
1547         buffer_copy_string(ds->key, "123");
1548         buffer_copy_string(ds->value, "alfrag");
1549 -       
1550 +
1551         array_insert_unique(a, (data_unset *)ds);
1552 -       
1553 +
1554         dc = data_count_init();
1555         buffer_copy_string(dc->key, "def");
1556 -       
1557 +
1558         array_insert_unique(a, (data_unset *)dc);
1559 -       
1560 +
1561         dc = data_count_init();
1562         buffer_copy_string(dc->key, "def");
1563 -       
1564 +
1565         array_insert_unique(a, (data_unset *)dc);
1566 -       
1567 +
1568         array_print(a, 0);
1569 -       
1570 +
1571         array_free(a);
1572 -       
1573 +
1574         fprintf(stderr, "%d\n",
1575                buffer_caseless_compare(CONST_STR_LEN("Content-Type"), CONST_STR_LEN("Content-type")));
1576 -       
1577 +
1578         return 0;
1579  }
1580  #endif
1581 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/array.h lighttpd-1.4.12/src/array.h
1582 --- lighttpd-1.4.11/src/array.h 2005-09-23 21:24:18.000000000 +0300
1583 +++ lighttpd-1.4.12/src/array.h 2006-07-11 21:23:39.000000000 +0300
1584 @@ -16,7 +16,7 @@
1585  #define DATA_UNSET \
1586         data_type_t type; \
1587         buffer *key; \
1588 -       int is_index_key; /* 1 if key is a array index (autogenerated keys) */ \
1589 +       int is_index_key; /* 1 if key is an array index (auto-generated keys) */ \
1590         struct data_unset *(*copy)(const struct data_unset *src); \
1591         void (* free)(struct data_unset *p); \
1592         void (* reset)(struct data_unset *p); \
1593 @@ -29,21 +29,21 @@
1594  
1595  typedef struct {
1596         data_unset  **data;
1597 -       
1598 +
1599         size_t *sorted;
1600 -       
1601 +
1602         size_t used;
1603         size_t size;
1604 -       
1605 +
1606         size_t unique_ndx;
1607 -       
1608 +
1609         size_t next_power_of_2;
1610         int is_weakref; /* data is weakref, don't bother the data */
1611  } array;
1612  
1613  typedef struct {
1614         DATA_UNSET;
1615 -       
1616 +
1617         int count;
1618  } data_count;
1619  
1620 @@ -51,7 +51,7 @@
1621  
1622  typedef struct {
1623         DATA_UNSET;
1624 -       
1625 +
1626         buffer *value;
1627  } data_string;
1628  
1629 @@ -60,7 +60,7 @@
1630  
1631  typedef struct {
1632         DATA_UNSET;
1633 -       
1634 +
1635         array *value;
1636  } data_array;
1637  
1638 @@ -74,7 +74,7 @@
1639         COMP_SERVER_SOCKET, COMP_HTTP_URL, COMP_HTTP_HOST, COMP_HTTP_REFERER, COMP_HTTP_USERAGENT, COMP_HTTP_COOKIE, COMP_HTTP_REMOTEIP
1640  } comp_key_t;
1641  
1642 -/* $HTTP["host"] ==    "incremental.home.kneschke.de" { ... } 
1643 +/* $HTTP["host"] ==    "incremental.home.kneschke.de" { ... }
1644   * for print:   comp_key      op    string
1645   * for compare: comp          cond  string/regex
1646   */
1647 @@ -82,15 +82,15 @@
1648  typedef struct _data_config data_config;
1649  struct _data_config {
1650         DATA_UNSET;
1651 -       
1652 +
1653         array *value;
1654 -       
1655 +
1656         buffer *comp_key;
1657         comp_key_t comp;
1658 -       
1659 +
1660         config_cond_t cond;
1661         buffer *op;
1662 -       
1663 +
1664         int context_ndx; /* more or less like an id */
1665         array *childs;
1666         /* nested */
1667 @@ -98,7 +98,7 @@
1668         /* for chaining only */
1669         data_config *prev;
1670         data_config *next;
1671 -       
1672 +
1673         buffer *string;
1674  #ifdef HAVE_PCRE_H
1675         pcre   *regex;
1676 @@ -110,7 +110,7 @@
1677  
1678  typedef struct {
1679         DATA_UNSET;
1680 -       
1681 +
1682         int value;
1683  } data_integer;
1684  
1685 @@ -120,13 +120,13 @@
1686         DATA_UNSET;
1687  
1688         buffer *host;
1689 -       
1690 +
1691         unsigned short port;
1692  
1693         time_t disable_ts;
1694         int is_disabled;
1695         size_t balance;
1696 -               
1697 +
1698         int usage; /* fair-balancing needs the no. of connections active on this host */
1699         int last_used_ndx; /* round robin */
1700  } data_fastcgi;
1701 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/base.h lighttpd-1.4.12/src/base.h
1702 --- lighttpd-1.4.11/src/base.h  2006-01-11 16:51:04.000000000 +0200
1703 +++ lighttpd-1.4.12/src/base.h  2006-07-11 21:23:39.000000000 +0300
1704 @@ -2,7 +2,6 @@
1705  #define _BASE_H_
1706  
1707  #include <sys/types.h>
1708 -#include <sys/time.h>
1709  #include <sys/stat.h>
1710  
1711  #ifdef HAVE_CONFIG_H
1712 @@ -26,10 +25,9 @@
1713  #include "sys-socket.h"
1714  #include "splaytree.h"
1715  
1716 -
1717  #if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H
1718  # define USE_OPENSSL
1719 -# include <openssl/ssl.h> 
1720 +# include <openssl/ssl.h>
1721  #endif
1722  
1723  #ifdef HAVE_FAM_H
1724 @@ -40,10 +38,6 @@
1725  # define O_BINARY 0
1726  #endif
1727  
1728 -#ifndef O_LARGEFILE
1729 -# define O_LARGEFILE 0
1730 -#endif
1731 -
1732  #ifndef SIZE_MAX
1733  # ifdef SIZE_T_MAX
1734  #  define SIZE_MAX SIZE_T_MAX
1735 @@ -70,7 +64,8 @@
1736  
1737  /* solaris and NetBSD 1.3.x again */
1738  #if (!defined(HAVE_STDINT_H)) && (!defined(HAVE_INTTYPES_H)) && (!defined(uint32_t))
1739 -# define uint32_t u_int32_t
1740 +/* # define uint32_t u_int32_t */
1741 +typedef unsigned __int32 uint32_t;
1742  #endif
1743  
1744  
1745 @@ -80,24 +75,24 @@
1746  
1747  #include "settings.h"
1748  
1749 -typedef enum { T_CONFIG_UNSET, 
1750 -               T_CONFIG_STRING, 
1751 -               T_CONFIG_SHORT, 
1752 -               T_CONFIG_BOOLEAN, 
1753 -               T_CONFIG_ARRAY, 
1754 -               T_CONFIG_LOCAL, 
1755 +typedef enum { T_CONFIG_UNSET,
1756 +               T_CONFIG_STRING,
1757 +               T_CONFIG_SHORT,
1758 +               T_CONFIG_BOOLEAN,
1759 +               T_CONFIG_ARRAY,
1760 +               T_CONFIG_LOCAL,
1761                 T_CONFIG_DEPRECATED
1762  } config_values_type_t;
1763  
1764 -typedef enum { T_CONFIG_SCOPE_UNSET, 
1765 -               T_CONFIG_SCOPE_SERVER, 
1766 +typedef enum { T_CONFIG_SCOPE_UNSET,
1767 +               T_CONFIG_SCOPE_SERVER,
1768                 T_CONFIG_SCOPE_CONNECTION
1769  } config_scope_type_t;
1770  
1771  typedef struct {
1772         const char *key;
1773         void *destination;
1774 -       
1775 +
1776         config_values_type_t type;
1777         config_scope_type_t scope;
1778  } config_values_t;
1779 @@ -142,40 +137,40 @@
1780         /* the request-line */
1781         buffer *request;
1782         buffer *uri;
1783 -       
1784 +
1785         buffer *orig_uri;
1786 -       
1787 +
1788         http_method_t  http_method;
1789         http_version_t http_version;
1790 -       
1791 +
1792         buffer *request_line;
1793 -       
1794 +
1795         /* strings to the header */
1796         buffer *http_host; /* not alloced */
1797         const char   *http_range;
1798         const char   *http_content_type;
1799         const char   *http_if_modified_since;
1800         const char   *http_if_none_match;
1801 -       
1802 +
1803         array  *headers;
1804 -       
1805 +
1806         /* CONTENT */
1807         size_t content_length; /* returned by strtoul() */
1808 -       
1809 +
1810         /* internal representation */
1811         int     accept_encoding;
1812 -       
1813 +
1814         /* internal */
1815         buffer *pathinfo;
1816  } request;
1817  
1818  typedef struct {
1819         off_t   content_length;
1820 -       int     keep_alive;               /* used by  the subrequests in proxy, cgi and fcgi to say the subrequest was keep-alive or not */
1821 -       
1822 +       int     keep_alive;               /* used by the subrequests in proxy, cgi and fcgi to say whether the subrequest was keep-alive or not */
1823 +
1824         array  *headers;
1825 -       
1826 -       enum { 
1827 +
1828 +       enum {
1829                 HTTP_TRANSFER_ENCODING_IDENTITY, HTTP_TRANSFER_ENCODING_CHUNKED
1830         } transfer_encoding;
1831  } response;
1832 @@ -191,21 +186,21 @@
1833  typedef struct {
1834         buffer *path;
1835         buffer *basedir; /* path = "(basedir)(.*)" */
1836 -       
1837 +
1838         buffer *doc_root; /* path = doc_root + rel_path */
1839         buffer *rel_path;
1840 -       
1841 +
1842         buffer *etag;
1843  } physical;
1844  
1845  typedef struct {
1846         buffer *name;
1847         buffer *etag;
1848 -       
1849 +
1850         struct stat st;
1851 -       
1852 +
1853         time_t stat_ts;
1854 -       
1855 +
1856  #ifdef HAVE_FAM_H
1857         int    dir_version;
1858         int    dir_ndx;
1859 @@ -215,8 +210,8 @@
1860  } stat_cache_entry;
1861  
1862  typedef struct {
1863 -       splay_tree *files; /* the nodes of the tree are stat_cache_entry's */
1864 -       
1865 +       splay_tree *files; /* the nodes of the tree are stat_cache_entries */
1866 +
1867         buffer *dir_name; /* for building the dirname from the filename */
1868  #ifdef HAVE_FAM_H
1869         splay_tree *dirs; /* the nodes of the tree are fam_dir_entry */
1870 @@ -228,7 +223,7 @@
1871  
1872  typedef struct {
1873         array *mimetypes;
1874 -       
1875 +
1876         /* virtual-servers */
1877         buffer *document_root;
1878         buffer *server_name;
1879 @@ -236,7 +231,7 @@
1880         buffer *server_tag;
1881         buffer *dirlist_encoding;
1882         buffer *errorfile_prefix;
1883 -       
1884 +
1885         unsigned short max_keep_alive_requests;
1886         unsigned short max_keep_alive_idle;
1887         unsigned short max_read_idle;
1888 @@ -244,16 +239,17 @@
1889         unsigned short use_xattr;
1890         unsigned short follow_symlink;
1891         unsigned short range_requests;
1892 -       
1893 +
1894         /* debug */
1895 -       
1896 +
1897         unsigned short log_file_not_found;
1898         unsigned short log_request_header;
1899         unsigned short log_request_handling;
1900         unsigned short log_response_header;
1901         unsigned short log_condition_handling;
1902 -       
1903 -       
1904 +       unsigned short log_condition_cache_handling;
1905 +
1906 +
1907         /* server wide */
1908         buffer *ssl_pemfile;
1909         buffer *ssl_ca_file;
1910 @@ -268,22 +264,22 @@
1911         /* configside */
1912         unsigned short global_kbytes_per_second; /*  */
1913  
1914 -       off_t  global_bytes_per_second_cnt; 
1915 +       off_t  global_bytes_per_second_cnt;
1916         /* server-wide traffic-shaper
1917 -        * 
1918 +        *
1919          * each context has the counter which is inited once
1920 -        * a second by the global_kbytes_per_second config-var
1921 +        * per second by the global_kbytes_per_second config-var
1922          *
1923          * as soon as global_kbytes_per_second gets below 0
1924          * the connected conns are "offline" a little bit
1925          *
1926          * the problem:
1927 -        * we somehow have to loose our "we are writable" signal 
1928 +        * we somehow have to lose our "we are writable" signal
1929          * on the way.
1930 -        * 
1931 +        *
1932          */
1933         off_t *global_bytes_per_second_cnt_ptr; /*  */
1934 -       
1935 +
1936  #ifdef USE_OPENSSL
1937         SSL_CTX *ssl_ctx;
1938  #endif
1939 @@ -291,18 +287,18 @@
1940  
1941  /* the order of the items should be the same as they are processed
1942   * read before write as we use this later */
1943 -typedef enum { 
1944 -       CON_STATE_CONNECT, 
1945 -       CON_STATE_REQUEST_START, 
1946 -       CON_STATE_READ, 
1947 -       CON_STATE_REQUEST_END, 
1948 -       CON_STATE_READ_POST, 
1949 -       CON_STATE_HANDLE_REQUEST, 
1950 -       CON_STATE_RESPONSE_START, 
1951 -       CON_STATE_WRITE, 
1952 -       CON_STATE_RESPONSE_END, 
1953 -       CON_STATE_ERROR, 
1954 -       CON_STATE_CLOSE 
1955 +typedef enum {
1956 +       CON_STATE_CONNECT,
1957 +       CON_STATE_REQUEST_START,
1958 +       CON_STATE_READ,
1959 +       CON_STATE_REQUEST_END,
1960 +       CON_STATE_READ_POST,
1961 +       CON_STATE_HANDLE_REQUEST,
1962 +       CON_STATE_RESPONSE_START,
1963 +       CON_STATE_WRITE,
1964 +       CON_STATE_RESPONSE_END,
1965 +       CON_STATE_ERROR,
1966 +       CON_STATE_CLOSE
1967  } connection_state_t;
1968  
1969  typedef enum { COND_RESULT_UNSET, COND_RESULT_FALSE, COND_RESULT_TRUE } cond_result_t;
1970 @@ -315,88 +311,88 @@
1971  
1972  typedef struct {
1973         connection_state_t state;
1974 -       
1975 +
1976         /* timestamps */
1977         time_t read_idle_ts;
1978         time_t close_timeout_ts;
1979         time_t write_request_ts;
1980 -       
1981 +
1982         time_t connection_start;
1983         time_t request_start;
1984 -       
1985 +
1986         struct timeval start_tv;
1987 -       
1988 +
1989         size_t request_count;        /* number of requests handled in this connection */
1990         size_t loops_per_request;    /* to catch endless loops in a single request
1991 -                                     * 
1992 +                                     *
1993                                       * used by mod_rewrite, mod_fastcgi, ... and others
1994                                       * this is self-protection
1995                                       */
1996 -       
1997 +
1998         int fd;                      /* the FD for this connection */
1999         int fde_ndx;                 /* index for the fdevent-handler */
2000         int ndx;                     /* reverse mapping to server->connection[ndx] */
2001 -       
2002 +
2003         /* fd states */
2004         int is_readable;
2005         int is_writable;
2006 -       
2007 -       int     keep_alive;           /* only request.c can enable it, all other just disable */
2008 -       
2009 +
2010 +       int     keep_alive;           /* only request.c can enable it, all others just disable */
2011 +
2012         int file_started;
2013         int file_finished;
2014 -       
2015 +
2016         chunkqueue *write_queue;      /* a large queue for low-level write ( HTTP response ) [ file, mem ] */
2017         chunkqueue *read_queue;       /* a small queue for low-level read ( HTTP request ) [ mem ] */
2018         chunkqueue *request_content_queue; /* takes request-content into tempfile if necessary [ tempfile, mem ]*/
2019 -       
2020 +
2021         int traffic_limit_reached;
2022 -       
2023 +
2024         off_t bytes_written;          /* used by mod_accesslog, mod_rrd */
2025         off_t bytes_written_cur_second; /* used by mod_accesslog, mod_rrd */
2026         off_t bytes_read;             /* used by mod_accesslog, mod_rrd */
2027         off_t bytes_header;
2028 -       
2029 +
2030         int http_status;
2031 -       
2032 +
2033         sock_addr dst_addr;
2034         buffer *dst_addr_buf;
2035  
2036         /* request */
2037         buffer *parse_request;
2038         unsigned int parsed_response; /* bitfield which contains the important header-fields of the parsed response header */
2039 -       
2040 +
2041         request  request;
2042         request_uri uri;
2043 -       physical physical; 
2044 +       physical physical;
2045         response response;
2046 -       
2047 +
2048         size_t header_len;
2049 -       
2050 +
2051         buffer *authed_user;
2052         array  *environment; /* used to pass lighttpd internal stuff to the FastCGI/CGI apps, setenv does that */
2053 -       
2054 +
2055         /* response */
2056         int    got_response;
2057 -       
2058 +
2059         int    in_joblist;
2060 -       
2061 +
2062         connection_type mode;
2063 -       
2064 +
2065         void **plugin_ctx;           /* plugin connection specific config */
2066 -       
2067 +
2068         specific_config conf;        /* global connection specific config */
2069         cond_cache_t *cond_cache;
2070 -       
2071 +
2072         buffer *server_name;
2073 -       
2074 +
2075         /* error-handler */
2076         buffer *error_handler;
2077         int error_handler_saved_status;
2078         int in_error_handler;
2079 -       
2080 +
2081         void *srv_socket;   /* reference to the server-socket (typecast to server_socket) */
2082 -       
2083 +
2084  #ifdef USE_OPENSSL
2085         SSL *ssl;
2086  #endif
2087 @@ -439,39 +435,48 @@
2088         size_t size;
2089  } buffer_plugin;
2090  
2091 +typedef enum {
2092 +    NETWORK_STATUS_UNSET,
2093 +    NETWORK_STATUS_SUCCESS,
2094 +    NETWORK_STATUS_FATAL_ERROR,
2095 +    NETWORK_STATUS_CONNECTION_CLOSE,
2096 +    NETWORK_STATUS_WAIT_FOR_EVENT,
2097 +    NETWORK_STATUS_INTERRUPTED
2098 +} network_status_t;
2099 +
2100  typedef struct {
2101         unsigned short port;
2102         buffer *bindhost;
2103 -       
2104 +
2105         buffer *errorlog_file;
2106         unsigned short errorlog_use_syslog;
2107 -       
2108 +
2109         unsigned short dont_daemonize;
2110         buffer *changeroot;
2111         buffer *username;
2112         buffer *groupname;
2113 -       
2114 +
2115         buffer *pid_file;
2116 -       
2117 +
2118         buffer *event_handler;
2119 -       
2120 +
2121         buffer *modules_dir;
2122         buffer *network_backend;
2123         array *modules;
2124         array *upload_tempdirs;
2125 -       
2126 +
2127         unsigned short max_worker;
2128         unsigned short max_fds;
2129         unsigned short max_conns;
2130         unsigned short max_request_size;
2131 -       
2132 +
2133         unsigned short log_request_header_on_error;
2134         unsigned short log_state_handling;
2135 -       
2136 -       enum { STAT_CACHE_ENGINE_UNSET, 
2137 -                       STAT_CACHE_ENGINE_NONE, 
2138 -                       STAT_CACHE_ENGINE_SIMPLE, 
2139 -                       STAT_CACHE_ENGINE_FAM 
2140 +
2141 +       enum { STAT_CACHE_ENGINE_UNSET,
2142 +                       STAT_CACHE_ENGINE_NONE,
2143 +                       STAT_CACHE_ENGINE_SIMPLE,
2144 +                       STAT_CACHE_ENGINE_FAM
2145         } stat_cache_engine;
2146         unsigned short enable_cores;
2147  } server_config;
2148 @@ -480,14 +485,14 @@
2149         sock_addr addr;
2150         int       fd;
2151         int       fde_ndx;
2152 -       
2153 +
2154         buffer *ssl_pemfile;
2155         buffer *ssl_ca_file;
2156         unsigned short use_ipv6;
2157         unsigned short is_ssl;
2158 -       
2159 +
2160         buffer *srv_token;
2161 -       
2162 +
2163  #ifdef USE_OPENSSL
2164         SSL_CTX *ssl_ctx;
2165  #endif
2166 @@ -495,37 +500,37 @@
2167  
2168  typedef struct {
2169         server_socket **ptr;
2170 -       
2171 +
2172         size_t size;
2173         size_t used;
2174  } server_socket_array;
2175  
2176  typedef struct server {
2177         server_socket_array srv_sockets;
2178 -       
2179 +
2180         /* the errorlog */
2181         int errorlog_fd;
2182         enum { ERRORLOG_STDERR, ERRORLOG_FILE, ERRORLOG_SYSLOG } errorlog_mode;
2183         buffer *errorlog_buf;
2184 -       
2185 +
2186         fdevents *ev, *ev_ins;
2187 -       
2188 +
2189         buffer_plugin plugins;
2190         void *plugin_slots;
2191 -       
2192 +
2193         /* counters */
2194         int con_opened;
2195         int con_read;
2196         int con_written;
2197         int con_closed;
2198 -       
2199 +
2200         int ssl_is_init;
2201 -       
2202 +
2203         int max_fds;    /* max possible fds */
2204         int cur_fds;    /* currently used fds */
2205         int want_fds;   /* waiting fds */
2206         int sockets_disabled;
2207 -       
2208 +
2209         size_t max_conns;
2210  
2211         /* buffers */
2212 @@ -533,13 +538,13 @@
2213         buffer *response_header;
2214         buffer *response_range;
2215         buffer *tmp_buf;
2216 -       
2217 +
2218         buffer *tmp_chunk_len;
2219 -       
2220 +
2221         buffer *empty_string; /* is necessary for cond_match */
2222  
2223         buffer *cond_check_buf;
2224 -       
2225 +
2226         /* caches */
2227  #ifdef HAVE_IPV6
2228         inet_ntop_cache_type inet_ntop_cache[INET_NTOP_CACHE_MAX];
2229 @@ -547,31 +552,31 @@
2230         mtime_cache_type mtime_cache[FILE_CACHE_MAX];
2231  
2232         array *split_vals;
2233 -       
2234 +
2235         /* Timestamps */
2236         time_t cur_ts;
2237         time_t last_generated_date_ts;
2238         time_t last_generated_debug_ts;
2239         time_t startup_ts;
2240 -       
2241 +
2242         buffer *ts_debug_str;
2243         buffer *ts_date_str;
2244 -       
2245 +
2246         /* config-file */
2247         array *config;
2248         array *config_touched;
2249 -       
2250 +
2251         array *config_context;
2252         specific_config **config_storage;
2253 -       
2254 +
2255         server_config  srvconf;
2256 -       
2257 +
2258         int config_deprecated;
2259 -       
2260 +
2261         connections *conns;
2262         connections *joblist;
2263         connections *fdwaitqueue;
2264 -       
2265 +
2266         stat_cache  *stat_cache;
2267  
2268         /**
2269 @@ -588,18 +593,20 @@
2270          *   fastcgi.backend.<key>.disconnects = ...
2271          */
2272         array *status;
2273 -       
2274 +
2275         fdevent_handler_t event_handler;
2276  
2277 -       int (* network_backend_write)(struct server *srv, connection *con, int fd, chunkqueue *cq);
2278 -       int (* network_backend_read)(struct server *srv, connection *con, int fd, chunkqueue *cq);
2279 +       network_status_t (* network_backend_write)(struct server *srv, connection *con, int fd, chunkqueue *cq);
2280 +       network_status_t (* network_backend_read)(struct server *srv, connection *con, int fd, chunkqueue *cq);
2281  #ifdef USE_OPENSSL
2282 -       int (* network_ssl_backend_write)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
2283 -       int (* network_ssl_backend_read)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
2284 +       network_status_t (* network_ssl_backend_write)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
2285 +       network_status_t (* network_ssl_backend_read)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
2286  #endif
2287  
2288 +#ifdef HAVE_PWD_H
2289         uid_t uid;
2290         gid_t gid;
2291 +#endif
2292  } server;
2293  
2294  
2295 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/buffer.c lighttpd-1.4.12/src/buffer.c
2296 --- lighttpd-1.4.11/src/buffer.c        2006-01-13 00:00:45.000000000 +0200
2297 +++ lighttpd-1.4.12/src/buffer.c        2006-07-11 21:23:40.000000000 +0300
2298 @@ -12,20 +12,20 @@
2299  
2300  
2301  /**
2302 - * init the buffer 
2303 - * 
2304 + * init the buffer
2305 + *
2306   */
2307  
2308  buffer* buffer_init(void) {
2309         buffer *b;
2310 -       
2311 +
2312         b = malloc(sizeof(*b));
2313         assert(b);
2314 -       
2315 +
2316         b->ptr = NULL;
2317         b->size = 0;
2318         b->used = 0;
2319 -       
2320 +
2321         return b;
2322  }
2323  
2324 @@ -36,8 +36,8 @@
2325  }
2326  
2327  /**
2328 - * free the buffer 
2329 - * 
2330 + * free the buffer
2331 + *
2332   */
2333  
2334  void buffer_free(buffer *b) {
2335 @@ -49,39 +49,39 @@
2336  
2337  void buffer_reset(buffer *b) {
2338         if (!b) return;
2339 -       
2340 +
2341         /* limit don't reuse buffer larger than ... bytes */
2342         if (b->size > BUFFER_MAX_REUSE_SIZE) {
2343                 free(b->ptr);
2344                 b->ptr = NULL;
2345                 b->size = 0;
2346         }
2347 -       
2348 +
2349         b->used = 0;
2350  }
2351  
2352  
2353  /**
2354 - * 
2355 - * allocate (if neccessary) enough space for 'size' bytes and 
2356 + *
2357 + * allocate (if necessary) enough space for 'size' bytes and
2358   * set the 'used' counter to 0
2359 - * 
2360 + *
2361   */
2362  
2363  #define BUFFER_PIECE_SIZE 64
2364  
2365  int buffer_prepare_copy(buffer *b, size_t size) {
2366         if (!b) return -1;
2367 -       
2368 -       if ((0 == b->size) || 
2369 +
2370 +       if ((0 == b->size) ||
2371             (size > b->size)) {
2372                 if (b->size) free(b->ptr);
2373 -               
2374 +
2375                 b->size = size;
2376 -               
2377 -               /* always allocate a multiply of BUFFER_PIECE_SIZE */
2378 +
2379 +               /* always allocate a multiple of BUFFER_PIECE_SIZE */
2380                 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
2381 -               
2382 +
2383                 b->ptr = malloc(b->size);
2384                 assert(b->ptr);
2385         }
2386 @@ -90,30 +90,30 @@
2387  }
2388  
2389  /**
2390 - * 
2391 - * increase the internal buffer (if neccessary) to append another 'size' byte
2392 + *
2393 + * increase the internal buffer (if necessary) to append another 'size' byte
2394   * ->used isn't changed
2395 - * 
2396 + *
2397   */
2398  
2399  int buffer_prepare_append(buffer *b, size_t size) {
2400         if (!b) return -1;
2401 -       
2402 +
2403         if (0 == b->size) {
2404                 b->size = size;
2405 -               
2406 -               /* always allocate a multiply of BUFFER_PIECE_SIZE */
2407 +
2408 +               /* always allocate a multiple of BUFFER_PIECE_SIZE */
2409                 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
2410 -               
2411 +
2412                 b->ptr = malloc(b->size);
2413                 b->used = 0;
2414                 assert(b->ptr);
2415         } else if (b->used + size > b->size) {
2416                 b->size += size;
2417 -               
2418 -               /* always allocate a multiply of BUFFER_PIECE_SIZE */
2419 +
2420 +               /* always allocate a multiple of BUFFER_PIECE_SIZE */
2421                 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
2422 -               
2423 +
2424                 b->ptr = realloc(b->ptr, b->size);
2425                 assert(b->ptr);
2426         }
2427 @@ -122,7 +122,7 @@
2428  
2429  int buffer_copy_string(buffer *b, const char *s) {
2430         size_t s_len;
2431 -       
2432 +
2433         if (!s || !b) return -1;
2434  
2435         s_len = strlen(s) + 1;
2436 @@ -136,26 +136,26 @@
2437  
2438  int buffer_copy_string_len(buffer *b, const char *s, size_t s_len) {
2439         if (!s || !b) return -1;
2440 -#if 0  
2441 -       /* removed optimization as we have to keep the empty string 
2442 +#if 0
2443 +       /* removed optimization as we have to keep the empty string
2444          * in some cases for the config handling
2445 -        * 
2446 +        *
2447          * url.access-deny = ( "" )
2448          */
2449         if (s_len == 0) return 0;
2450 -#endif 
2451 +#endif
2452         buffer_prepare_copy(b, s_len + 1);
2453 -       
2454 +
2455         memcpy(b->ptr, s, s_len);
2456         b->ptr[s_len] = '\0';
2457         b->used = s_len + 1;
2458 -       
2459 +
2460         return 0;
2461  }
2462  
2463  int buffer_copy_string_buffer(buffer *b, const buffer *src) {
2464         if (!src) return -1;
2465 -       
2466 +
2467         if (src->used == 0) {
2468                 b->used = 0;
2469                 return 0;
2470 @@ -201,10 +201,10 @@
2471  
2472  /**
2473   * append a string to the end of the buffer
2474 - * 
2475 - * the resulting buffer is terminated with a '\0' 
2476 - * s is treated as a un-terminated string (a \0 is handled a normal character)
2477 - * 
2478 + *
2479 + * the resulting buffer is terminated with a '\0'
2480 + * s is treated as an un-terminated string (a \0 is handled as a normal character)
2481 + *
2482   * @param b a buffer
2483   * @param s the string
2484   * @param s_len size of the string (without the terminating \0)
2485 @@ -228,7 +228,7 @@
2486  int buffer_append_string_buffer(buffer *b, const buffer *src) {
2487         if (!src) return -1;
2488         if (src->used == 0) return 0;
2489 -       
2490 +
2491         return buffer_append_string_len(b, src->ptr, src->used - 1);
2492  }
2493  
2494 @@ -245,9 +245,9 @@
2495  
2496  int buffer_copy_memory(buffer *b, const char *s, size_t s_len) {
2497         if (!s || !b) return -1;
2498 -       
2499 +
2500         b->used = 0;
2501 -       
2502 +
2503         return buffer_append_memory(b, s, s_len);
2504  }
2505  
2506 @@ -402,46 +402,115 @@
2507  
2508  
2509  /**
2510 - * init the buffer 
2511 - * 
2512 + * init the ptr buffer
2513 + *
2514 + */
2515 +buffer_ptr *buffer_ptr_init(buffer_ptr_free_t freer)
2516 +{
2517 +       buffer_ptr *l = calloc(1, sizeof(buffer_ptr));
2518 +       l->free = freer;
2519 +
2520 +       return l;
2521 +}
2522 +
2523 +/**
2524 + * free the buffer_array
2525 + *
2526 + */
2527 +void buffer_ptr_free(buffer_ptr *l)
2528 +{
2529 +       if (NULL != l) {
2530 +               buffer_ptr_clear(l);
2531 +               free(l);
2532 +       }
2533 +}
2534 +
2535 +void buffer_ptr_clear(buffer_ptr *l)
2536 +{
2537 +       assert(NULL != l);
2538 +
2539 +       if (l->free && l->used) {
2540 +               size_t i;
2541 +               for (i = 0; i < l->used; i ++) {
2542 +                       l->free(l->ptr[i]);
2543 +               }
2544 +       }
2545 +
2546 +       if (l->ptr) {
2547 +               free(l->ptr);
2548 +               l->ptr = NULL;
2549 +       }
2550 +       l->used = 0;
2551 +       l->size = 0;
2552 +}
2553 +
2554 +void buffer_ptr_append(buffer_ptr* l, void *item)
2555 +{
2556 +       assert(NULL != l);
2557 +       if (l->ptr == NULL) {
2558 +               l->size = 16;
2559 +               l->ptr = (void **)malloc(sizeof(void *) * l->size);
2560 +       }
2561 +       else if (l->used == l->size) {
2562 +               l->size += 16;
2563 +               l->ptr = realloc(l->ptr, sizeof(void *) * l->size);
2564 +       }
2565 +       l->ptr[l->used++] = item;
2566 +}
2567 +
2568 +void *buffer_ptr_pop(buffer_ptr* l)
2569 +{
2570 +       assert(NULL != l && l->used > 0);
2571 +       return l->ptr[--l->used];
2572 +}
2573 +
2574 +void *buffer_ptr_top(buffer_ptr* l)
2575 +{
2576 +       assert(NULL != l && l->used > 0);
2577 +       return l->ptr[l->used-1];
2578 +}
2579 +
2580 +/**
2581 + * init the buffer
2582 + *
2583   */
2584  
2585  buffer_array* buffer_array_init(void) {
2586         buffer_array *b;
2587 -       
2588 +
2589         b = malloc(sizeof(*b));
2590 -       
2591 +
2592         assert(b);
2593         b->ptr = NULL;
2594         b->size = 0;
2595         b->used = 0;
2596 -       
2597 +
2598         return b;
2599  }
2600  
2601  void buffer_array_reset(buffer_array *b) {
2602         size_t i;
2603 -       
2604 +
2605         if (!b) return;
2606 -       
2607 +
2608         /* if they are too large, reduce them */
2609         for (i = 0; i < b->used; i++) {
2610                 buffer_reset(b->ptr[i]);
2611         }
2612 -       
2613 +
2614         b->used = 0;
2615  }
2616  
2617  
2618  /**
2619 - * free the buffer_array 
2620 - * 
2621 + * free the buffer_array
2622 + *
2623   */
2624  
2625  void buffer_array_free(buffer_array *b) {
2626         size_t i;
2627         if (!b) return;
2628 -       
2629 +
2630         for (i = 0; i < b->size; i++) {
2631                 if (b->ptr[i]) buffer_free(b->ptr[i]);
2632         }
2633 @@ -451,7 +520,7 @@
2634  
2635  buffer *buffer_array_append_get_buffer(buffer_array *b) {
2636         size_t i;
2637 -       
2638 +
2639         if (b->size == 0) {
2640                 b->size = 16;
2641                 b->ptr = malloc(sizeof(*b->ptr) * b->size);
2642 @@ -467,13 +536,13 @@
2643                         b->ptr[i] = NULL;
2644                 }
2645         }
2646 -       
2647 +
2648         if (b->ptr[b->used] == NULL) {
2649                 b->ptr[b->used] = buffer_init();
2650         }
2651 -       
2652 +
2653         b->ptr[b->used]->used = 0;
2654 -       
2655 +
2656         return b->ptr[b->used++];
2657  }
2658  
2659 @@ -482,23 +551,23 @@
2660         size_t i;
2661         if (len == 0) return NULL;
2662         if (needle == NULL) return NULL;
2663 -       
2664 +
2665         if (b->used < len) return NULL;
2666 -       
2667 +
2668         for(i = 0; i < b->used - len; i++) {
2669                 if (0 == memcmp(b->ptr + i, needle, len)) {
2670                         return b->ptr + i;
2671                 }
2672         }
2673 -       
2674 +
2675         return NULL;
2676  }
2677  
2678  buffer *buffer_init_string(const char *str) {
2679         buffer *b = buffer_init();
2680 -       
2681 +
2682         buffer_copy_string(b, str);
2683 -       
2684 +
2685         return b;
2686  }
2687  
2688 @@ -507,8 +576,8 @@
2689  }
2690  
2691  /**
2692 - * check if two buffer contain the same data
2693 - * 
2694 + * check if two buffers contain the same data
2695 + *
2696   * HISTORY: this function was pretty much optimized, but didn't handled
2697   * alignment properly.
2698   */
2699 @@ -522,100 +591,100 @@
2700  
2701  int buffer_is_equal_string(buffer *a, const char *s, size_t b_len) {
2702         buffer b;
2703 -       
2704 +
2705         b.ptr = (char *)s;
2706         b.used = b_len + 1;
2707 -       
2708 +
2709         return buffer_is_equal(a, &b);
2710  }
2711  
2712  /* simple-assumption:
2713 - * 
2714 - * most parts are equal and doing a case conversion needs time
2715 - * 
2716 + *
2717 + * most parts are equal and doing a case conversion takes time
2718 + *
2719   */
2720  int buffer_caseless_compare(const char *a, size_t a_len, const char *b, size_t b_len) {
2721         size_t ndx = 0, max_ndx;
2722         size_t *al, *bl;
2723         size_t mask = sizeof(*al) - 1;
2724 -       
2725 +
2726         al = (size_t *)a;
2727         bl = (size_t *)b;
2728 -       
2729 -       /* is the alignment correct ? */
2730 +
2731 +       /* is the alignment correct? */
2732         if ( ((size_t)al & mask) == 0 &&
2733              ((size_t)bl & mask) == 0 ) {
2734 -               
2735 +
2736                 max_ndx = ((a_len < b_len) ? a_len : b_len) & ~mask;
2737 -               
2738 +
2739                 for (; ndx < max_ndx; ndx += sizeof(*al)) {
2740                         if (*al != *bl) break;
2741                         al++; bl++;
2742 -                       
2743 +
2744                 }
2745 -               
2746 +
2747         }
2748 -       
2749 +
2750         a = (char *)al;
2751         b = (char *)bl;
2752 -       
2753 +
2754         max_ndx = ((a_len < b_len) ? a_len : b_len);
2755 -       
2756 +
2757         for (; ndx < max_ndx; ndx++) {
2758                 char a1 = *a++, b1 = *b++;
2759 -               
2760 +
2761                 if (a1 != b1) {
2762                         if ((a1 >= 'A' && a1 <= 'Z') && (b1 >= 'a' && b1 <= 'z'))
2763                                 a1 |= 32;
2764                         else if ((a1 >= 'a' && a1 <= 'z') && (b1 >= 'A' && b1 <= 'Z'))
2765                                 b1 |= 32;
2766                         if ((a1 - b1) != 0) return (a1 - b1);
2767 -                       
2768 +
2769                 }
2770         }
2771 -       
2772 +
2773         return 0;
2774  }
2775  
2776  
2777  /**
2778   * check if the rightmost bytes of the string are equal.
2779 - * 
2780 - * 
2781 + *
2782 + *
2783   */
2784  
2785  int buffer_is_equal_right_len(buffer *b1, buffer *b2, size_t len) {
2786         /* no, len -> equal */
2787         if (len == 0) return 1;
2788 -       
2789 +
2790         /* len > 0, but empty buffers -> not equal */
2791         if (b1->used == 0 || b2->used == 0) return 0;
2792 -       
2793 +
2794         /* buffers too small -> not equal */
2795 -       if (b1->used - 1 < len || b1->used - 1 < len) return 0;
2796 -       
2797 -       if (0 == strncmp(b1->ptr + b1->used - 1 - len, 
2798 +       if (b1->used - 1 < len || b2->used - 1 < len) return 0;
2799 +
2800 +       if (0 == strncmp(b1->ptr + b1->used - 1 - len,
2801                          b2->ptr + b2->used - 1 - len, len)) {
2802                 return 1;
2803         }
2804 -       
2805 +
2806         return 0;
2807  }
2808  
2809  int buffer_copy_string_hex(buffer *b, const char *in, size_t in_len) {
2810         size_t i;
2811 -       
2812 +
2813         /* BO protection */
2814         if (in_len * 2 < in_len) return -1;
2815 -       
2816 +
2817         buffer_prepare_copy(b, in_len * 2 + 1);
2818 -       
2819 +
2820         for (i = 0; i < in_len; i++) {
2821                 b->ptr[b->used++] = hex_chars[(in[i] >> 4) & 0x0F];
2822                 b->ptr[b->used++] = hex_chars[in[i] & 0x0F];
2823         }
2824         b->ptr[b->used++] = '\0';
2825 -       
2826 +
2827         return 0;
2828  }
2829  
2830 @@ -624,7 +693,7 @@
2831         0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
2832         */
2833         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
2834 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */ 
2835 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
2836         1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1,  /*  20 -  2F space " # $ % & ' + , / */
2837         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,  /*  30 -  3F : ; = ? @ < > */
2838         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  40 -  4F */
2839 @@ -646,7 +715,7 @@
2840         0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
2841         */
2842         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
2843 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */ 
2844 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
2845         1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0,  /*  20 -  2F space " # $ % & ' + , / */
2846         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,  /*  30 -  3F : ; = ? @ < > */
2847         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  40 -  4F */
2848 @@ -668,7 +737,7 @@
2849         0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
2850         */
2851         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
2852 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */ 
2853 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
2854         0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  20 -  2F & */
2855         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,  /*  30 -  3F < > */
2856         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  40 -  4F */
2857 @@ -690,7 +759,7 @@
2858         0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
2859         */
2860         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
2861 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */ 
2862 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
2863         0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  20 -  2F & */
2864         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,  /*  30 -  3F < > */
2865         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /*  40 -  4F */
2866 @@ -712,12 +781,12 @@
2867         0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
2868         */
2869         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  00 -  0F control chars */
2870 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */ 
2871 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  20 -  2F */ 
2872 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  30 -  3F */ 
2873 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  40 -  4F */ 
2874 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  50 -  5F */ 
2875 -       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  60 -  6F */ 
2876 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  10 -  1F */
2877 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  20 -  2F */
2878 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  30 -  3F */
2879 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  40 -  4F */
2880 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  50 -  5F */
2881 +       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  60 -  6F */
2882         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  70 -  7F */
2883         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  80 -  8F */
2884         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /*  90 -  9F */
2885 @@ -734,13 +803,13 @@
2886         unsigned char *ds, *d;
2887         size_t d_len, ndx;
2888         const char *map = NULL;
2889 -       
2890 +
2891         if (!s || !b) return -1;
2892 -       
2893 +
2894         if (b->ptr[b->used - 1] != '\0') {
2895                 SEGFAULT();
2896         }
2897 -       
2898 +
2899         if (s_len == 0) return 0;
2900  
2901         switch(encoding) {
2902 @@ -760,12 +829,12 @@
2903                 map = encoded_chars_hex;
2904                 break;
2905         case ENCODING_UNSET:
2906 -               break;
2907 +               return buffer_append_string_len(b, s, s_len);
2908         }
2909  
2910         assert(map != NULL);
2911 -       
2912 -       /* count to-be-encoded-characters */
2913 +
2914 +       /* count to-be-encoded characters */
2915         for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
2916                 if (map[*ds]) {
2917                         switch(encoding) {
2918 @@ -787,9 +856,9 @@
2919                         d_len ++;
2920                 }
2921         }
2922 -       
2923 +
2924         buffer_prepare_append(b, d_len);
2925 -       
2926 +
2927         for (ds = (unsigned char *)s, d = (unsigned char *)b->ptr + b->used - 1, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
2928                 if (map[*ds]) {
2929                         switch(encoding) {
2930 @@ -820,16 +889,16 @@
2931                 }
2932         }
2933  
2934 -       /* terminate buffer and calculate new length */ 
2935 +       /* terminate buffer and calculate new length */
2936         b->ptr[b->used + d_len - 1] = '\0';
2937 -       
2938 +
2939         b->used += d_len;
2940  
2941         return 0;
2942  }
2943  
2944  
2945 -/* decodes url-special-chars inplace.
2946 +/* decodes url-special chars in-place.
2947   * replaces non-printable characters with '_'
2948   */
2949  
2950 @@ -854,10 +923,10 @@
2951                                 low = hex2int(*(src + 2));
2952                                 if (low != 0xFF) {
2953                                         high = (high << 4) | low;
2954 -                                       
2955 -                                       /* map control-characters out */        
2956 +
2957 +                                       /* map out control characters */
2958                                         if (high < 32 || high == 127) high = '_';
2959 -                                       
2960 +
2961                                         *dst = high;
2962                                         src += 2;
2963                                 }
2964 @@ -891,7 +960,7 @@
2965   * /abc/./xyz       gets  /abc/xyz
2966   * /abc//xyz        gets  /abc/xyz
2967   *
2968 - * NOTE: src and dest can point to the same buffer, in which case,
2969 + * NOTE: src and dest can point to the same buffer, in which case
2970   *       the operation is performed in-place.
2971   */
2972  
2973 @@ -979,7 +1048,7 @@
2974  
2975  int light_isxdigit(int c) {
2976         if (light_isdigit(c)) return 1;
2977 -       
2978 +
2979         c |= 32;
2980         return (c >= 'a' && c <= 'f');
2981  }
2982 @@ -993,31 +1062,56 @@
2983         return light_isdigit(c) || light_isalpha(c);
2984  }
2985  
2986 +#undef BUFFER_CTYPE_FUNC
2987 +#define BUFFER_CTYPE_FUNC(type) \
2988 +       int buffer_is##type(buffer *b) { \
2989 +               size_t i, len; \
2990 +               if (b->used < 2) return 0; \
2991 +               /* strlen */ \
2992 +               len = b->used - 1; \
2993 +               /* c-string only */ \
2994 +               if (b->ptr[len] != '\0') { \
2995 +                       return 0; \
2996 +               } \
2997 +               /* check on the whole string */ \
2998 +               for (i = 0; i < len; i ++) { \
2999 +                       if (!light_is##type(b->ptr[i])) { \
3000 +                               return 0; \
3001 +                       } \
3002 +               } \
3003 +               return 1; \
3004 +       }
3005 +
3006 +BUFFER_CTYPE_FUNC(digit)
3007 +BUFFER_CTYPE_FUNC(xdigit)
3008 +BUFFER_CTYPE_FUNC(alpha)
3009 +BUFFER_CTYPE_FUNC(alnum)
3010 +
3011  int buffer_to_lower(buffer *b) {
3012         char *c;
3013 -       
3014 +
3015         if (b->used == 0) return 0;
3016 -       
3017 +
3018         for (c = b->ptr; *c; c++) {
3019                 if (*c >= 'A' && *c <= 'Z') {
3020                         *c |= 32;
3021                 }
3022         }
3023 -       
3024 +
3025         return 0;
3026  }
3027  
3028  
3029  int buffer_to_upper(buffer *b) {
3030         char *c;
3031 -       
3032 +
3033         if (b->used == 0) return 0;
3034 -       
3035 +
3036         for (c = b->ptr; *c; c++) {
3037                 if (*c >= 'a' && *c <= 'z') {
3038                         *c &= ~32;
3039                 }
3040         }
3041 -       
3042 +
3043         return 0;
3044  }
3045 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/buffer.h lighttpd-1.4.12/src/buffer.h
3046 --- lighttpd-1.4.11/src/buffer.h        2006-01-13 00:00:45.000000000 +0200
3047 +++ lighttpd-1.4.12/src/buffer.h        2006-07-11 21:23:40.000000000 +0300
3048 @@ -12,27 +12,44 @@
3049  
3050  typedef struct {
3051         char *ptr;
3052 -       
3053 +
3054         size_t used;
3055         size_t size;
3056  } buffer;
3057  
3058 +
3059 +typedef void (*buffer_ptr_free_t)(void *p);
3060 +
3061 +typedef struct {
3062 +       void **ptr;
3063 +       size_t size;
3064 +       size_t used;
3065 +       buffer_ptr_free_t free;
3066 +} buffer_ptr;
3067 +
3068  typedef struct {
3069         buffer **ptr;
3070 -       
3071 +
3072         size_t used;
3073         size_t size;
3074  } buffer_array;
3075  
3076  typedef struct {
3077         char *ptr;
3078 -       
3079 -       size_t offset; /* input-pointer */
3080 -       
3081 -       size_t used;   /* output-pointer */
3082 +
3083 +       size_t offset; /* input pointer */
3084 +
3085 +       size_t used;   /* output pointer */
3086         size_t size;
3087  } read_buffer;
3088  
3089 +buffer_ptr *buffer_ptr_init(buffer_ptr_free_t freer);
3090 +void buffer_ptr_free(buffer_ptr *b);
3091 +void buffer_ptr_clear(buffer_ptr *b);
3092 +void buffer_ptr_append(buffer_ptr *b, void *item);
3093 +void *buffer_ptr_pop(buffer_ptr *b);
3094 +void *buffer_ptr_top(buffer_ptr *b);
3095 +
3096  buffer_array* buffer_array_init(void);
3097  void buffer_array_free(buffer_array *b);
3098  void buffer_array_reset(buffer_array *b);
3099 @@ -43,7 +60,7 @@
3100  buffer* buffer_init_string(const char *str);
3101  void buffer_free(buffer *b);
3102  void buffer_reset(buffer *b);
3103 -       
3104 +
3105  int buffer_prepare_copy(buffer *b, size_t size);
3106  int buffer_prepare_append(buffer *b, size_t size);
3107  
3108 @@ -85,9 +102,9 @@
3109  
3110  typedef enum {
3111         ENCODING_UNSET,
3112 -       ENCODING_REL_URI, /* for coding a rel-uri (/with space/and%percent) nicely as part of a href */
3113 -       ENCODING_REL_URI_PART, /* same as ENC_REL_URL plus coding / too as %2F */
3114 -       ENCODING_HTML,    /* & becomes &amp; and so on */
3115 +       ENCODING_REL_URI, /* for coding a rel-uri (/with space/and%percent) nicely as part of an href */
3116 +       ENCODING_REL_URI_PART, /* same as ENC_REL_URL plus encoding "/" as "%2F" */
3117 +       ENCODING_HTML,    /* "&" becomes "&amp;" and so on */
3118         ENCODING_MINIMAL_XML, /* minimal encoding for xml */
3119         ENCODING_HEX      /* encode string as hex */
3120  } buffer_encoding_t;
3121 @@ -111,19 +128,21 @@
3122  int light_isalpha(int c);
3123  int light_isalnum(int c);
3124  
3125 +#define BUFFER_CTYPE_FUNC(type) int buffer_is##type(buffer *b);
3126 +BUFFER_CTYPE_FUNC(digit)
3127 +BUFFER_CTYPE_FUNC(xdigit)
3128 +BUFFER_CTYPE_FUNC(alpha)
3129 +BUFFER_CTYPE_FUNC(alnum)
3130 +
3131  #define BUFFER_APPEND_STRING_CONST(x, y) \
3132         buffer_append_string_len(x, y, sizeof(y) - 1)
3133  
3134  #define BUFFER_COPY_STRING_CONST(x, y) \
3135         buffer_copy_string_len(x, y, sizeof(y) - 1)
3136  
3137 -#define BUFFER_APPEND_SLASH(x) \
3138 -       if (x->used > 1 && x->ptr[x->used - 2] != '/') { BUFFER_APPEND_STRING_CONST(x, "/"); }
3139 -
3140  #define CONST_STR_LEN(x) x, x ? sizeof(x) - 1 : 0
3141  #define CONST_BUF_LEN(x) x->ptr, x->used ? x->used - 1 : 0
3142  
3143 -
3144  #define SEGFAULT() do { fprintf(stderr, "%s.%d: aborted\n", __FILE__, __LINE__); abort(); } while(0)
3145  #define UNUSED(x) ( (void)(x) )
3146  
3147 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/chunk.c lighttpd-1.4.12/src/chunk.c
3148 --- lighttpd-1.4.11/src/chunk.c 2005-11-18 15:18:19.000000000 +0200
3149 +++ lighttpd-1.4.12/src/chunk.c 2006-07-11 21:23:39.000000000 +0300
3150 @@ -1,16 +1,14 @@
3151  /**
3152   * the network chunk-API
3153 - * 
3154 - * 
3155 + *
3156 + *
3157   */
3158  
3159  #include <sys/types.h>
3160  #include <sys/stat.h>
3161 -#include <sys/mman.h>
3162  
3163  #include <stdlib.h>
3164  #include <fcntl.h>
3165 -#include <unistd.h>
3166  
3167  #include <stdio.h>
3168  #include <errno.h>
3169 @@ -18,36 +16,39 @@
3170  
3171  #include "chunk.h"
3172  
3173 +#include "sys-mmap.h"
3174 +#include "sys-files.h"
3175 +
3176  chunkqueue *chunkqueue_init(void) {
3177         chunkqueue *cq;
3178 -       
3179 +
3180         cq = calloc(1, sizeof(*cq));
3181 -       
3182 +
3183         cq->first = NULL;
3184         cq->last = NULL;
3185 -       
3186 +
3187         cq->unused = NULL;
3188 -       
3189 +
3190         return cq;
3191  }
3192  
3193  static chunk *chunk_init(void) {
3194         chunk *c;
3195 -       
3196 +
3197         c = calloc(1, sizeof(*c));
3198 -       
3199 +
3200         c->mem = buffer_init();
3201         c->file.name = buffer_init();
3202         c->file.fd = -1;
3203         c->file.mmap.start = MAP_FAILED;
3204         c->next = NULL;
3205 -       
3206 +
3207         return c;
3208  }
3209  
3210  static void chunk_free(chunk *c) {
3211         if (!c) return;
3212 -       
3213 +
3214         buffer_free(c->mem);
3215         buffer_free(c->file.name);
3216  
3217 @@ -56,13 +57,13 @@
3218  
3219  static void chunk_reset(chunk *c) {
3220         if (!c) return;
3221 -       
3222 +
3223         buffer_reset(c->mem);
3224  
3225         if (c->file.is_temp && !buffer_is_empty(c->file.name)) {
3226                 unlink(c->file.name->ptr);
3227         }
3228 -       
3229 +
3230         buffer_reset(c->file.name);
3231  
3232         if (c->file.fd != -1) {
3233 @@ -78,28 +79,28 @@
3234  
3235  void chunkqueue_free(chunkqueue *cq) {
3236         chunk *c, *pc;
3237 -       
3238 +
3239         if (!cq) return;
3240 -       
3241 +
3242         for (c = cq->first; c; ) {
3243                 pc = c;
3244                 c = c->next;
3245                 chunk_free(pc);
3246         }
3247 -       
3248 +
3249         for (c = cq->unused; c; ) {
3250                 pc = c;
3251                 c = c->next;
3252                 chunk_free(pc);
3253         }
3254 -       
3255 +
3256         free(cq);
3257  }
3258  
3259  static chunk *chunkqueue_get_unused_chunk(chunkqueue *cq) {
3260         chunk *c;
3261 -       
3262 -       /* check if we have a unused chunk */
3263 +
3264 +       /* check if we have an unused chunk */
3265         if (!cq->unused) {
3266                 c = chunk_init();
3267         } else {
3268 @@ -109,18 +110,18 @@
3269                 c->next = NULL;
3270                 cq->unused_chunks--;
3271         }
3272 -       
3273 +
3274         return c;
3275  }
3276  
3277  static int chunkqueue_prepend_chunk(chunkqueue *cq, chunk *c) {
3278         c->next = cq->first;
3279         cq->first = c;
3280 -       
3281 +
3282         if (cq->last == NULL) {
3283                 cq->last = c;
3284         }
3285 -       
3286 +
3287         return 0;
3288  }
3289  
3290 @@ -129,19 +130,19 @@
3291                 cq->last->next = c;
3292         }
3293         cq->last = c;
3294 -       
3295 +
3296         if (cq->first == NULL) {
3297                 cq->first = c;
3298         }
3299 -       
3300 +
3301         return 0;
3302  }
3303  
3304  void chunkqueue_reset(chunkqueue *cq) {
3305         chunk *c;
3306         /* move everything to the unused queue */
3307 -       
3308 -       /* mark all read written */ 
3309 +
3310 +       /* mark all read written */
3311         for (c = cq->first; c; c = c->next) {
3312                 switch(c->type) {
3313                 case MEM_CHUNK:
3314 @@ -150,7 +151,7 @@
3315                 case FILE_CHUNK:
3316                         c->offset = c->file.length;
3317                         break;
3318 -               default: 
3319 +               default:
3320                         break;
3321                 }
3322         }
3323 @@ -162,93 +163,93 @@
3324  
3325  int chunkqueue_append_file(chunkqueue *cq, buffer *fn, off_t offset, off_t len) {
3326         chunk *c;
3327 -       
3328 +
3329         if (len == 0) return 0;
3330 -       
3331 +
3332         c = chunkqueue_get_unused_chunk(cq);
3333 -       
3334 +
3335         c->type = FILE_CHUNK;
3336 -       
3337 +
3338         buffer_copy_string_buffer(c->file.name, fn);
3339         c->file.start = offset;
3340         c->file.length = len;
3341         c->offset = 0;
3342 -       
3343 +
3344         chunkqueue_append_chunk(cq, c);
3345 -       
3346 +
3347         return 0;
3348  }
3349  
3350  int chunkqueue_append_buffer(chunkqueue *cq, buffer *mem) {
3351         chunk *c;
3352 -       
3353 +
3354         if (mem->used == 0) return 0;
3355 -       
3356 +
3357         c = chunkqueue_get_unused_chunk(cq);
3358         c->type = MEM_CHUNK;
3359         c->offset = 0;
3360         buffer_copy_string_buffer(c->mem, mem);
3361 -       
3362 +
3363         chunkqueue_append_chunk(cq, c);
3364 -       
3365 +
3366         return 0;
3367  }
3368  
3369  int chunkqueue_prepend_buffer(chunkqueue *cq, buffer *mem) {
3370         chunk *c;
3371 -       
3372 +
3373         if (mem->used == 0) return 0;
3374 -       
3375 +
3376         c = chunkqueue_get_unused_chunk(cq);
3377         c->type = MEM_CHUNK;
3378         c->offset = 0;
3379         buffer_copy_string_buffer(c->mem, mem);
3380 -       
3381 +
3382         chunkqueue_prepend_chunk(cq, c);
3383 -       
3384 +
3385         return 0;
3386  }
3387  
3388  int chunkqueue_append_mem(chunkqueue *cq, const char * mem, size_t len) {
3389         chunk *c;
3390 -       
3391 +
3392         if (len == 0) return 0;
3393 -       
3394 +
3395         c = chunkqueue_get_unused_chunk(cq);
3396         c->type = MEM_CHUNK;
3397         c->offset = 0;
3398         buffer_copy_string_len(c->mem, mem, len - 1);
3399 -       
3400 +
3401         chunkqueue_append_chunk(cq, c);
3402 -       
3403 +
3404         return 0;
3405  }
3406  
3407  buffer * chunkqueue_get_prepend_buffer(chunkqueue *cq) {
3408         chunk *c;
3409 -       
3410 +
3411         c = chunkqueue_get_unused_chunk(cq);
3412 -       
3413 +
3414         c->type = MEM_CHUNK;
3415         c->offset = 0;
3416         buffer_reset(c->mem);
3417 -       
3418 +
3419         chunkqueue_prepend_chunk(cq, c);
3420 -       
3421 +
3422         return c->mem;
3423  }
3424  
3425  buffer *chunkqueue_get_append_buffer(chunkqueue *cq) {
3426         chunk *c;
3427 -       
3428 +
3429         c = chunkqueue_get_unused_chunk(cq);
3430 -       
3431 +
3432         c->type = MEM_CHUNK;
3433         c->offset = 0;
3434         buffer_reset(c->mem);
3435 -       
3436 +
3437         chunkqueue_append_chunk(cq, c);
3438 -       
3439 +
3440         return c->mem;
3441  }
3442  
3443 @@ -263,7 +264,7 @@
3444  chunk *chunkqueue_get_append_tempfile(chunkqueue *cq) {
3445         chunk *c;
3446         buffer *template = buffer_init_string("/var/tmp/lighttpd-upload-XXXXXX");
3447 -       
3448 +
3449         c = chunkqueue_get_unused_chunk(cq);
3450  
3451         c->type = FILE_CHUNK;
3452 @@ -273,12 +274,12 @@
3453                 size_t i;
3454  
3455                 /* we have several tempdirs, only if all of them fail we jump out */
3456 -               
3457 +
3458                 for (i = 0; i < cq->tempdirs->used; i++) {
3459                         data_string *ds = (data_string *)cq->tempdirs->data[i];
3460  
3461                         buffer_copy_string_buffer(template, ds->value);
3462 -                       BUFFER_APPEND_SLASH(template);
3463 +                       PATHNAME_APPEND_SLASH(template);
3464                         BUFFER_APPEND_STRING_CONST(template, "lighttpd-upload-XXXXXX");
3465  
3466                         if (-1 != (c->file.fd = mkstemp(template->ptr))) {
3467 @@ -300,7 +301,7 @@
3468         chunkqueue_append_chunk(cq, c);
3469  
3470         buffer_free(template);
3471 -       
3472 +
3473         return c;
3474  }
3475  
3476 @@ -308,7 +309,7 @@
3477  off_t chunkqueue_length(chunkqueue *cq) {
3478         off_t len = 0;
3479         chunk *c;
3480 -       
3481 +
3482         for (c = cq->first; c; c = c->next) {
3483                 switch (c->type) {
3484                 case MEM_CHUNK:
3485 @@ -321,14 +322,14 @@
3486                         break;
3487                 }
3488         }
3489 -       
3490 +
3491         return len;
3492  }
3493  
3494  off_t chunkqueue_written(chunkqueue *cq) {
3495         off_t len = 0;
3496         chunk *c;
3497 -       
3498 +
3499         for (c = cq->first; c; c = c->next) {
3500                 switch (c->type) {
3501                 case MEM_CHUNK:
3502 @@ -339,7 +340,7 @@
3503                         break;
3504                 }
3505         }
3506 -       
3507 +
3508         return len;
3509  }
3510  
3511 @@ -358,9 +359,9 @@
3512                         if (c->offset == (off_t)c->mem->used - 1) is_finished = 1;
3513                         break;
3514                 case FILE_CHUNK:
3515 -                       if (c->offset == c->file.length) is_finished = 1; 
3516 +                       if (c->offset == c->file.length) is_finished = 1;
3517                         break;
3518 -               default: 
3519 +               default:
3520                         break;
3521                 }
3522  
3523 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/chunk.h lighttpd-1.4.12/src/chunk.h
3524 --- lighttpd-1.4.11/src/chunk.h 2005-11-01 09:32:21.000000000 +0200
3525 +++ lighttpd-1.4.12/src/chunk.h 2006-07-11 21:23:40.000000000 +0300
3526 @@ -6,7 +6,7 @@
3527  
3528  typedef struct chunk {
3529         enum { UNUSED_CHUNK, MEM_CHUNK, FILE_CHUNK } type;
3530 -       
3531 +
3532         buffer *mem; /* either the storage of the mem-chunk or the read-ahead buffer */
3533  
3534         struct {
3535 @@ -16,28 +16,28 @@
3536                 off_t  length; /* octets to send from the starting offset */
3537  
3538                 int    fd;
3539 -               struct { 
3540 +               struct {
3541                         char   *start; /* the start pointer of the mmap'ed area */
3542                         size_t length; /* size of the mmap'ed area */
3543 -                       off_t  offset; /* start is <n> octet away from the start of the file */
3544 +                       off_t  offset; /* start is <n> octets away from the start of the file */
3545                 } mmap;
3546  
3547 -               int is_temp; /* file is temporary and will be deleted if on cleanup */
3548 +               int is_temp; /* file is temporary and will be deleted on cleanup */
3549         } file;
3550 -       
3551 -       off_t  offset; /* octets sent from this chunk 
3552 -                         the size of the chunk is either 
3553 +
3554 +       off_t  offset; /* octets sent from this chunk
3555 +                         the size of the chunk is either
3556                           - mem-chunk: mem->used - 1
3557                           - file-chunk: file.length
3558                         */
3559 -       
3560 +
3561         struct chunk *next;
3562  } chunk;
3563  
3564  typedef struct {
3565         chunk *first;
3566         chunk *last;
3567 -       
3568 +
3569         chunk *unused;
3570         size_t unused_chunks;
3571  
3572 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/configfile-glue.c lighttpd-1.4.12/src/configfile-glue.c
3573 --- lighttpd-1.4.11/src/configfile-glue.c       2006-03-03 20:14:56.000000000 +0200
3574 +++ lighttpd-1.4.12/src/configfile-glue.c       2006-07-11 21:23:39.000000000 +0300
3575 @@ -1,4 +1,5 @@
3576  #include <string.h>
3577 +#include <ctype.h>
3578  
3579  #include "base.h"
3580  #include "buffer.h"
3581 @@ -11,10 +12,10 @@
3582   * are the external interface of lighttpd. The functions
3583   * are used by the server itself and the plugins.
3584   *
3585 - * The main-goal is to have a small library in the end 
3586 - * which is linked against both and which will define 
3587 + * The main-goal is to have a small library in the end
3588 + * which is linked against both and which will define
3589   * the interface itself in the end.
3590 - * 
3591 + *
3592   */
3593  
3594  
3595 @@ -24,56 +25,60 @@
3596  int config_insert_values_internal(server *srv, array *ca, const config_values_t cv[]) {
3597         size_t i;
3598         data_unset *du;
3599 -       
3600 +
3601         for (i = 0; cv[i].key; i++) {
3602 -               
3603 +
3604                 if (NULL == (du = array_get_element(ca, cv[i].key))) {
3605                         /* no found */
3606 -                       
3607 +
3608                         continue;
3609                 }
3610 -               
3611 +
3612                 switch (cv[i].type) {
3613                 case T_CONFIG_ARRAY:
3614                         if (du->type == TYPE_ARRAY) {
3615                                 size_t j;
3616                                 data_array *da = (data_array *)du;
3617 -                               
3618 +
3619                                 for (j = 0; j < da->value->used; j++) {
3620                                         if (da->value->data[j]->type == TYPE_STRING) {
3621                                                 data_string *ds = data_string_init();
3622 -                                               
3623 +
3624                                                 buffer_copy_string_buffer(ds->value, ((data_string *)(da->value->data[j]))->value);
3625                                                 if (!da->is_index_key) {
3626                                                         /* the id's were generated automaticly, as we copy now we might have to renumber them
3627 -                                                        * this is used to prepend server.modules by mod_indexfiles as it has to be loaded 
3628 +                                                        * this is used to prepend server.modules by mod_indexfiles as it has to be loaded
3629                                                          * before mod_fastcgi and friends */
3630                                                         buffer_copy_string_buffer(ds->key, ((data_string *)(da->value->data[j]))->key);
3631                                                 }
3632 -                                               
3633 +
3634                                                 array_insert_unique(cv[i].destination, (data_unset *)ds);
3635                                         } else {
3636 -                                               log_error_write(srv, __FILE__, __LINE__, "sssd", 
3637 -                                                               "the key of and array can only be a string or a integer, variable:", 
3638 -                                                               cv[i].key, "type:", da->value->data[j]->type); 
3639 -                                               
3640 +                                               log_error_write(srv, __FILE__, __LINE__, "sssd",
3641 +                                                               "the key of and array can only be a string or a integer, variable:",
3642 +                                                               cv[i].key, "type:", da->value->data[j]->type);
3643 +
3644                                                 return -1;
3645                                         }
3646                                 }
3647                         } else {
3648                                 log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", cv[i].key, "array of strings");
3649 -                               
3650 +
3651                                 return -1;
3652                         }
3653                         break;
3654                 case T_CONFIG_STRING:
3655                         if (du->type == TYPE_STRING) {
3656                                 data_string *ds = (data_string *)du;
3657 -                               
3658 +
3659                                 buffer_copy_string_buffer(cv[i].destination, ds->value);
3660 +                       } else if (du->type == TYPE_INTEGER) {
3661 +                               data_integer *di = (data_integer *)du;
3662 +
3663 +                               buffer_copy_long(cv[i].destination, di->value);
3664                         } else {
3665                                 log_error_write(srv, __FILE__, __LINE__, "ssss", "unexpected type for key: ", cv[i].key, "(string)", "\"...\"");
3666 -                               
3667 +
3668                                 return -1;
3669                         }
3670                         break;
3671 @@ -81,15 +86,20 @@
3672                         switch(du->type) {
3673                         case TYPE_INTEGER: {
3674                                 data_integer *di = (data_integer *)du;
3675 -                               
3676 +
3677                                 *((unsigned short *)(cv[i].destination)) = di->value;
3678                                 break;
3679                         }
3680                         case TYPE_STRING: {
3681                                 data_string *ds = (data_string *)du;
3682 -                                       
3683 +
3684 +                               if (buffer_isdigit(ds->value)) {
3685 +                                       *((unsigned short *)(cv[i].destination)) = strtol(ds->value->ptr, NULL, 10);
3686 +                                       break;
3687 +                               }
3688 +
3689                                 log_error_write(srv, __FILE__, __LINE__, "ssb", "get a string but expected a short:", cv[i].key, ds->value);
3690 -                               
3691 +
3692                                 return -1;
3693                         }
3694                         default:
3695 @@ -100,19 +110,19 @@
3696                 case T_CONFIG_BOOLEAN:
3697                         if (du->type == TYPE_STRING) {
3698                                 data_string *ds = (data_string *)du;
3699 -                               
3700 +
3701                                 if (buffer_is_equal_string(ds->value, CONST_STR_LEN("enable"))) {
3702                                         *((unsigned short *)(cv[i].destination)) = 1;
3703                                 } else if (buffer_is_equal_string(ds->value, CONST_STR_LEN("disable"))) {
3704                                         *((unsigned short *)(cv[i].destination)) = 0;
3705                                 } else {
3706                                         log_error_write(srv, __FILE__, __LINE__, "ssbs", "ERROR: unexpected value for key:", cv[i].key, ds->value, "(enable|disable)");
3707 -                                               
3708 +
3709                                         return -1;
3710                                 }
3711                         } else {
3712                                 log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: unexpected type for key:", cv[i].key, "(string)", "\"(enable|disable)\"");
3713 -                               
3714 +
3715                                 return -1;
3716                         }
3717                         break;
3718 @@ -121,9 +131,9 @@
3719                         break;
3720                 case T_CONFIG_DEPRECATED:
3721                         log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found deprecated key:", cv[i].key, "-", (char *)(cv[i].destination));
3722 -                       
3723 +
3724                         srv->config_deprecated = 1;
3725 -                       
3726 +
3727                         break;
3728                 }
3729         }
3730 @@ -133,25 +143,25 @@
3731  int config_insert_values_global(server *srv, array *ca, const config_values_t cv[]) {
3732         size_t i;
3733         data_unset *du;
3734 -       
3735 +
3736         for (i = 0; cv[i].key; i++) {
3737                 data_string *touched;
3738 -               
3739 +
3740                 if (NULL == (du = array_get_element(ca, cv[i].key))) {
3741                         /* no found */
3742 -                       
3743 +
3744                         continue;
3745                 }
3746 -               
3747 +
3748                 /* touched */
3749                 touched = data_string_init();
3750 -               
3751 +
3752                 buffer_copy_string(touched->value, "");
3753                 buffer_copy_string_buffer(touched->key, du->key);
3754 -               
3755 +
3756                 array_insert_unique(srv->config_touched, (data_unset *)touched);
3757         }
3758 -       
3759 +
3760         return config_insert_values_internal(srv, ca, cv);
3761  }
3762  
3763 @@ -191,25 +201,25 @@
3764         }
3765  
3766         /* pass the rules */
3767 -       
3768 +
3769         switch (dc->comp) {
3770         case COMP_HTTP_HOST: {
3771                 char *ck_colon = NULL, *val_colon = NULL;
3772 -               
3773 +
3774                 if (!buffer_is_empty(con->uri.authority)) {
3775 -               
3776 -                       /* 
3777 +
3778 +                       /*
3779                          * append server-port to the HTTP_POST if necessary
3780                          */
3781 -                       
3782 +
3783                         l = con->uri.authority;
3784 -                       
3785 +
3786                         switch(dc->cond) {
3787                         case CONFIG_COND_NE:
3788                         case CONFIG_COND_EQ:
3789                                 ck_colon = strchr(dc->string->ptr, ':');
3790                                 val_colon = strchr(l->ptr, ':');
3791 -                               
3792 +
3793                                 if (ck_colon == val_colon) {
3794                                         /* nothing to do with it */
3795                                         break;
3796 @@ -230,21 +240,21 @@
3797                                 break;
3798                         }
3799                 } else {
3800 -                       l = NULL;
3801 +                       l = srv->empty_string;
3802                 }
3803                 break;
3804         }
3805         case COMP_HTTP_REMOTEIP: {
3806                 char *nm_slash;
3807 -               /* handle remoteip limitations 
3808 -                * 
3809 +               /* handle remoteip limitations
3810 +                *
3811                  * "10.0.0.1" is provided for all comparisions
3812 -                * 
3813 +                *
3814                  * only for == and != we support
3815 -                * 
3816 +                *
3817                  * "10.0.0.1/24"
3818                  */
3819 -               
3820 +
3821                 if ((dc->cond == CONFIG_COND_EQ ||
3822                      dc->cond == CONFIG_COND_NE) &&
3823                     (con->dst_addr.plain.sa_family == AF_INET) &&
3824 @@ -253,41 +263,48 @@
3825                         long nm;
3826                         char *err;
3827                         struct in_addr val_inp;
3828 -                       
3829 +
3830 +                       if (con->conf.log_condition_handling) {
3831 +                               l = srv->empty_string;
3832 +
3833 +                               log_error_write(srv, __FILE__, __LINE__,  "bsbsb", dc->comp_key,
3834 +                                               "(", l, ") compare to", dc->string);
3835 +                       }
3836 +
3837                         if (*(nm_slash+1) == '\0') {
3838                                 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", dc->string);
3839 -                                       
3840 +
3841                                 return COND_RESULT_FALSE;
3842                         }
3843 -                       
3844 +
3845                         nm_bits = strtol(nm_slash + 1, &err, 10);
3846 -                       
3847 +
3848                         if (*err) {
3849                                 log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", dc->string, *err);
3850 -                               
3851 +
3852                                 return COND_RESULT_FALSE;
3853                         }
3854 -                       
3855 +
3856                         /* take IP convert to the native */
3857                         buffer_copy_string_len(srv->cond_check_buf, dc->string->ptr, nm_slash - dc->string->ptr);
3858 -#ifdef __WIN32                 
3859 +#ifdef _WIN32
3860                         if (INADDR_NONE == (val_inp.s_addr = inet_addr(srv->cond_check_buf->ptr))) {
3861                                 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
3862 -                               
3863 +
3864                                 return COND_RESULT_FALSE;
3865                         }
3866  
3867  #else
3868                         if (0 == inet_aton(srv->cond_check_buf->ptr, &val_inp)) {
3869                                 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
3870 -                               
3871 +
3872                                 return COND_RESULT_FALSE;
3873                         }
3874  #endif
3875 -                       
3876 +
3877                         /* build netmask */
3878                         nm = htonl(~((1 << (32 - nm_bits)) - 1));
3879 -                       
3880 +
3881                         if ((val_inp.s_addr & nm) == (con->dst_addr.ipv4.sin_addr.s_addr & nm)) {
3882                                 return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE;
3883                         } else {
3884 @@ -308,7 +325,7 @@
3885  
3886         case COMP_HTTP_REFERER: {
3887                 data_string *ds;
3888 -               
3889 +
3890                 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Referer"))) {
3891                         l = ds->value;
3892                 } else {
3893 @@ -338,7 +355,7 @@
3894         default:
3895                 return COND_RESULT_FALSE;
3896         }
3897 -       
3898 +
3899         if (NULL == l) {
3900                 if (con->conf.log_condition_handling) {
3901                         log_error_write(srv, __FILE__, __LINE__,  "bsbs", dc->comp_key,
3902 @@ -346,10 +363,10 @@
3903                 }
3904                 return COND_RESULT_FALSE;
3905         }
3906 -       
3907 +
3908         if (con->conf.log_condition_handling) {
3909                 log_error_write(srv, __FILE__, __LINE__,  "bsbsb", dc->comp_key,
3910 -                               "(", l, ") compare to ", dc->string);
3911 +                               "(", l, ") compare to", dc->string);
3912         }
3913         switch(dc->cond) {
3914         case CONFIG_COND_NE:
3915 @@ -365,13 +382,13 @@
3916         case CONFIG_COND_MATCH: {
3917                 cond_cache_t *cache = &con->cond_cache[dc->context_ndx];
3918                 int n;
3919 -               
3920 +
3921  #ifndef elementsof
3922  #define elementsof(x) (sizeof(x) / sizeof(x[0]))
3923  #endif
3924                 n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0,
3925                                 cache->matches, elementsof(cache->matches));
3926 -               
3927 +
3928                 cache->patterncount = n;
3929                 if (n > 0) {
3930                         cache->comp_value = l;
3931 @@ -387,7 +404,7 @@
3932                 /* no way */
3933                 break;
3934         }
3935 -       
3936 +
3937         return COND_RESULT_FALSE;
3938  }
3939  
3940 @@ -395,6 +412,9 @@
3941         cond_cache_t *caches = con->cond_cache;
3942  
3943         if (COND_RESULT_UNSET == caches[dc->context_ndx].result) {
3944 +               if (con->conf.log_condition_handling) {
3945 +                       log_error_write(srv, __FILE__, __LINE__,  "sds",  "=== start of", dc->context_ndx, "condition block ===");
3946 +               }
3947                 if (COND_RESULT_TRUE == (caches[dc->context_ndx].result = config_check_cond_nocache(srv, con, dc))) {
3948                         if (dc->next) {
3949                                 data_config *c;
3950 @@ -409,11 +429,11 @@
3951                 }
3952                 if (con->conf.log_condition_handling) {
3953                         log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,
3954 -                                       "(uncached) result:",
3955 +                                       "result:",
3956                                         caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false");
3957                 }
3958         } else {
3959 -               if (con->conf.log_condition_handling) {
3960 +               if (con->conf.log_condition_cache_handling) {
3961                         log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,
3962                                         "(cached) result:",
3963                                         caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false");
3964 @@ -423,9 +443,6 @@
3965  }
3966  
3967  int config_check_cond(server *srv, connection *con, data_config *dc) {
3968 -       if (con->conf.log_condition_handling) {
3969 -               log_error_write(srv, __FILE__, __LINE__,  "s",  "=== start of condition block ===");
3970 -       }
3971         return (config_check_cond_cached(srv, con, dc) == COND_RESULT_TRUE);
3972  }
3973  
3974 @@ -443,3 +460,85 @@
3975         return 1;
3976  }
3977  
3978 +/* return <0 on error
3979 + * return 0-x if matched (and replaced)
3980 + */
3981 +int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result)
3982 +{
3983 +#ifdef HAVE_PCRE_H
3984 +       pcre *match;
3985 +       pcre_extra *extra;
3986 +       const char *pattern;
3987 +       size_t pattern_len;
3988 +       int n;
3989 +       size_t i;
3990 +       pcre_keyvalue *kv;
3991 +# define N 10
3992 +       int ovec[N * 3];
3993 +
3994 +       for (i = 0; i < kvb->used; i++) {
3995 +               kv = kvb->kv[i];
3996 +
3997 +               match       = kv->key;
3998 +               extra       = kv->key_extra;
3999 +               pattern     = kv->value->ptr;
4000 +               pattern_len = kv->value->used - 1;
4001 +
4002 +               if ((n = pcre_exec(match, extra, match_buf->ptr, match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
4003 +                       if (n != PCRE_ERROR_NOMATCH) {
4004 +                               return n;
4005 +                       }
4006 +               } else {
4007 +                       const char **list;
4008 +                       size_t start, end;
4009 +                       size_t k;
4010 +
4011 +                       /* it matched */
4012 +                       pcre_get_substring_list(match_buf->ptr, ovec, n, &list);
4013 +
4014 +                       /* search for $[0-9] */
4015 +
4016 +                       buffer_reset(result);
4017 +
4018 +                       start = 0; end = pattern_len;
4019 +                       for (k = 0; k < pattern_len; k++) {
4020 +                               if ((pattern[k] == '$' || pattern[k] == '%') &&
4021 +                                   isdigit((unsigned char)pattern[k + 1])) {
4022 +                                       /* got one */
4023 +
4024 +                                       size_t num = pattern[k + 1] - '0';
4025 +
4026 +                                       end = k;
4027 +
4028 +                                       buffer_append_string_len(result, pattern + start, end - start);
4029 +
4030 +                                       if (pattern[k] == '$') {
4031 +                                               /* n is always > 0 */
4032 +                                               if (num < (size_t)n) {
4033 +                                                       buffer_append_string(result, list[num]);
4034 +                                               }
4035 +                                       } else {
4036 +                                               config_append_cond_match_buffer(con, context, result, num);
4037 +                                       }
4038 +
4039 +                                       k++;
4040 +                                       start = k + 1;
4041 +                               }
4042 +                       }
4043 +
4044 +                       buffer_append_string_len(result, pattern + start, pattern_len - start);
4045 +
4046 +                       pcre_free(list);
4047 +
4048 +                       return i;
4049 +               }
4050 +       }
4051 +
4052 +       return PCRE_ERROR_NOMATCH;
4053 +#undef N
4054 +#else
4055 +       UNUSED(kvb);
4056 +       return -2;
4057 +#endif
4058 +}
4059 +
4060 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/configfile.c lighttpd-1.4.12/src/configfile.c
4061 --- lighttpd-1.4.11/src/configfile.c    2006-02-15 14:26:42.000000000 +0200
4062 +++ lighttpd-1.4.12/src/configfile.c    2006-07-11 21:23:39.000000000 +0300
4063 @@ -2,7 +2,6 @@
4064  
4065  #include <stdlib.h>
4066  #include <fcntl.h>
4067 -#include <unistd.h>
4068  #include <errno.h>
4069  #include <string.h>
4070  #include <stdio.h>
4071 @@ -13,21 +12,24 @@
4072  #include "log.h"
4073  #include "stream.h"
4074  #include "plugin.h"
4075 -#ifdef USE_LICENSE
4076 -#include "license.h"
4077 -#endif
4078 -
4079  #include "configparser.h"
4080  #include "configfile.h"
4081  #include "proc_open.h"
4082  
4083 +#include "sys-files.h"
4084 +#include "sys-process.h"
4085 +
4086 +#ifndef PATH_MAX
4087 +/* win32 */
4088 +#define PATH_MAX 64
4089 +#endif
4090  
4091  static int config_insert(server *srv) {
4092         size_t i;
4093         int ret = 0;
4094         buffer *stat_cache_string;
4095 -       
4096 -       config_values_t cv[] = { 
4097 +
4098 +       config_values_t cv[] = {
4099                 { "server.bind",                 NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 0 */
4100                 { "server.errorlog",             NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 1 */
4101                 { "server.errorfile-prefix",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 2 */
4102 @@ -38,7 +40,7 @@
4103                 { "server.tag",                  NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },  /* 7 */
4104                 { "server.use-ipv6",             NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
4105                 { "server.modules",              NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_SERVER },       /* 9 */
4106 -               
4107 +
4108                 { "server.event-handler",        NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 10 */
4109                 { "server.pid-file",             NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 11 */
4110                 { "server.max-request-size",     NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },   /* 12 */
4111 @@ -49,7 +51,7 @@
4112                 { "server.max-keep-alive-requests", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 17 */
4113                 { "server.name",                 NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },  /* 18 */
4114                 { "server.max-keep-alive-idle",  NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },   /* 19 */
4115 -               
4116 +
4117                 { "server.max-read-idle",        NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },   /* 20 */
4118                 { "server.max-write-idle",       NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },   /* 21 */
4119                 { "server.error-handler-404",    NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },  /* 22 */
4120 @@ -60,19 +62,19 @@
4121                 { "mimetype.use-xattr",          NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 27 */
4122                 { "mimetype.assign",             NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },   /* 28 */
4123                 { "ssl.pemfile",                 NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 29 */
4124 -               
4125 +
4126                 { "ssl.engine",                  NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 30 */
4127 -               
4128 +
4129                 { "debug.log-file-not-found",    NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 31 */
4130                 { "debug.log-request-handling",  NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 32 */
4131                 { "debug.log-response-header",   NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 33 */
4132                 { "debug.log-request-header",    NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 34 */
4133 -               
4134 +
4135                 { "server.protocol-http11",      NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 35 */
4136                 { "debug.log-request-header-on-error", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 36 */
4137                 { "debug.log-state-handling",    NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 37 */
4138                 { "ssl.ca-file",                 NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 38 */
4139 -               
4140 +
4141                 { "server.errorlog-use-syslog",  NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 39 */
4142                 { "server.range-requests",       NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 40 */
4143                 { "server.stat-cache-engine",    NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },  /* 41 */
4144 @@ -80,7 +82,8 @@
4145                 { "server.network-backend",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },  /* 43 */
4146                 { "server.upload-dirs",          NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },   /* 44 */
4147                 { "server.core-files",           NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 45 */
4148 -               
4149 +               { "debug.log-condition-cache-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },    /* 46 */
4150 +
4151                 { "server.host",                 "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
4152                 { "server.docroot",              "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
4153                 { "server.virtual-root",         "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
4154 @@ -90,11 +93,11 @@
4155                 { "server.groupid",              "use server.groupname instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
4156                 { "server.use-keep-alive",       "use server.max-keep-alive-requests = 0 instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
4157                 { "server.force-lower-case-files",       "use server.force-lowercase-filenames instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
4158 -               
4159 +
4160                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
4161         };
4162  
4163 -       
4164 +
4165         /* 0 */
4166         cv[0].destination = srv->srvconf.bindhost;
4167         cv[1].destination = srv->srvconf.errorlog_file;
4168 @@ -102,33 +105,33 @@
4169         cv[4].destination = srv->srvconf.username;
4170         cv[5].destination = srv->srvconf.groupname;
4171         cv[6].destination = &(srv->srvconf.port);
4172 -       
4173 +
4174         cv[9].destination = srv->srvconf.modules;
4175         cv[10].destination = srv->srvconf.event_handler;
4176         cv[11].destination = srv->srvconf.pid_file;
4177 -       
4178 +
4179         cv[13].destination = &(srv->srvconf.max_worker);
4180         cv[23].destination = &(srv->srvconf.max_fds);
4181         cv[36].destination = &(srv->srvconf.log_request_header_on_error);
4182         cv[37].destination = &(srv->srvconf.log_state_handling);
4183 -       
4184 +
4185         cv[39].destination = &(srv->srvconf.errorlog_use_syslog);
4186 -       
4187 +
4188         stat_cache_string = buffer_init();
4189         cv[41].destination = stat_cache_string;
4190         cv[43].destination = srv->srvconf.network_backend;
4191         cv[44].destination = srv->srvconf.upload_tempdirs;
4192         cv[45].destination = &(srv->srvconf.enable_cores);
4193 -       
4194 +
4195         cv[42].destination = &(srv->srvconf.max_conns);
4196         cv[12].destination = &(srv->srvconf.max_request_size);
4197         srv->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
4198  
4199         assert(srv->config_storage);
4200 -       
4201 +
4202         for (i = 0; i < srv->config_context->used; i++) {
4203                 specific_config *s;
4204 -               
4205 +
4206                 s = calloc(1, sizeof(specific_config));
4207                 assert(s);
4208                 s->document_root = buffer_init();
4209 @@ -154,17 +157,18 @@
4210                 s->global_kbytes_per_second = 0;
4211                 s->global_bytes_per_second_cnt = 0;
4212                 s->global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
4213 -               
4214 +
4215                 cv[2].destination = s->errorfile_prefix;
4216 -               
4217 +
4218                 cv[7].destination = s->server_tag;
4219                 cv[8].destination = &(s->use_ipv6);
4220 -               
4221 -               
4222 +
4223 +
4224                 /* 13 max-worker */
4225                 cv[14].destination = s->document_root;
4226                 cv[15].destination = &(s->force_lowercase_filenames);
4227                 cv[16].destination = &(s->log_condition_handling);
4228 +               cv[46].destination = &(s->log_condition_cache_handling);
4229                 cv[17].destination = &(s->max_keep_alive_requests);
4230                 cv[18].destination = s->server_name;
4231                 cv[19].destination = &(s->max_keep_alive_idle);
4232 @@ -179,23 +183,23 @@
4233                 cv[28].destination = s->mimetypes;
4234                 cv[29].destination = s->ssl_pemfile;
4235                 cv[30].destination = &(s->is_ssl);
4236 -               
4237 +
4238                 cv[31].destination = &(s->log_file_not_found);
4239                 cv[32].destination = &(s->log_request_handling);
4240                 cv[33].destination = &(s->log_response_header);
4241                 cv[34].destination = &(s->log_request_header);
4242 -               
4243 +
4244                 cv[35].destination = &(s->allow_http11);
4245                 cv[38].destination = s->ssl_ca_file;
4246                 cv[40].destination = &(s->range_requests);
4247 -               
4248 +
4249                 srv->config_storage[i] = s;
4250 -       
4251 +
4252                 if (0 != (ret = config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv))) {
4253                         break;
4254                 }
4255         }
4256 -       
4257 +
4258         if (buffer_is_empty(stat_cache_string)) {
4259                 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE;
4260         } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("simple"))) {
4261 @@ -205,22 +209,22 @@
4262         } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("disable"))) {
4263                 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_NONE;
4264         } else {
4265 -               log_error_write(srv, __FILE__, __LINE__, "sb", 
4266 +               log_error_write(srv, __FILE__, __LINE__, "sb",
4267                                 "server.stat-cache-engine can be one of \"disable\", \"simple\", \"fam\", but not:", stat_cache_string);
4268                 ret = HANDLER_ERROR;
4269         }
4270 -       
4271 +
4272         buffer_free(stat_cache_string);
4273 -       
4274 +
4275         return ret;
4276 -                                                                
4277 -}
4278  
4279 +}
4280  
4281 -#define PATCH(x) con->conf.x = s->x
4282 +#define PATCH(x) \
4283 +       con->conf.x = s->x
4284  int config_setup_connection(server *srv, connection *con) {
4285         specific_config *s = srv->config_storage[0];
4286 -       
4287 +
4288         PATCH(allow_http11);
4289         PATCH(mimetypes);
4290         PATCH(document_root);
4291 @@ -236,20 +240,21 @@
4292         PATCH(kbytes_per_second);
4293         PATCH(global_kbytes_per_second);
4294         PATCH(global_bytes_per_second_cnt);
4295 -       
4296 +
4297         con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
4298         buffer_copy_string_buffer(con->server_name, s->server_name);
4299 -       
4300 +
4301         PATCH(log_request_header);
4302         PATCH(log_response_header);
4303         PATCH(log_request_handling);
4304         PATCH(log_condition_handling);
4305 +       PATCH(log_condition_cache_handling);
4306         PATCH(log_file_not_found);
4307 -       
4308 +
4309         PATCH(range_requests);
4310         PATCH(force_lowercase_filenames);
4311         PATCH(is_ssl);
4312 -       
4313 +
4314         PATCH(ssl_pemfile);
4315         PATCH(ssl_ca_file);
4316         return 0;
4317 @@ -257,22 +262,22 @@
4318  
4319  int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
4320         size_t i, j;
4321 -       
4322 +
4323         /* skip the first, the global context */
4324         for (i = 1; i < srv->config_context->used; i++) {
4325                 data_config *dc = (data_config *)srv->config_context->data[i];
4326                 specific_config *s = srv->config_storage[i];
4327 -               
4328 +
4329                 /* not our stage */
4330                 if (comp != dc->comp) continue;
4331 -               
4332 +
4333                 /* condition didn't match */
4334                 if (!config_check_cond(srv, con, dc)) continue;
4335 -               
4336 +
4337                 /* merge config */
4338                 for (j = 0; j < dc->value->used; j++) {
4339                         data_unset *du = dc->value->data[j];
4340 -                       
4341 +
4342                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.document-root"))) {
4343                                 PATCH(document_root);
4344                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.range-requests"))) {
4345 @@ -315,11 +320,13 @@
4346                                 PATCH(log_response_header);
4347                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-handling"))) {
4348                                 PATCH(log_condition_handling);
4349 +                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-cache-handling"))) {
4350 +                               PATCH(log_condition_cache_handling);
4351                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-file-not-found"))) {
4352                                 PATCH(log_file_not_found);
4353                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.protocol-http11"))) {
4354                                 PATCH(allow_http11);
4355 -                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {  
4356 +                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
4357                                 PATCH(force_lowercase_filenames);
4358                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.kbytes-per-second"))) {
4359                                 PATCH(global_kbytes_per_second);
4360 @@ -328,7 +335,7 @@
4361                         }
4362                 }
4363         }
4364 -       
4365 +
4366         return 0;
4367  }
4368  #undef PATCH
4369 @@ -336,15 +343,15 @@
4370  typedef struct {
4371         int foo;
4372         int bar;
4373 -       
4374 +
4375         const buffer *source;
4376         const char *input;
4377         size_t offset;
4378         size_t size;
4379 -       
4380 +
4381         int line_pos;
4382         int line;
4383 -       
4384 +
4385         int in_key;
4386         int in_brace;
4387         int in_cond;
4388 @@ -362,7 +369,7 @@
4389         }
4390  
4391         if (0 != stream_open(&(t->s), t->file)) {
4392 -               log_error_write(srv, __FILE__, __LINE__, "sbss", 
4393 +               log_error_write(srv, __FILE__, __LINE__, "sbss",
4394                                 "opening configfile ", t->file, "failed:", strerror(errno));
4395                 buffer_free(t->file);
4396                 return -1;
4397 @@ -373,7 +380,7 @@
4398         t->size = t->s.size;
4399         t->line = 1;
4400         t->line_pos = 1;
4401 -       
4402 +
4403         t->in_key = 1;
4404         t->in_brace = 0;
4405         t->in_cond = 0;
4406 @@ -401,7 +408,7 @@
4407  static int config_skip_comment(tokenizer_t *t) {
4408         int i;
4409         assert(t->input[t->offset] == '#');
4410 -       for (i = 1; t->input[t->offset + i] && 
4411 +       for (i = 1; t->input[t->offset + i] &&
4412              (t->input[t->offset + i] != '\n' && t->input[t->offset + i] != '\r');
4413              i++);
4414         t->offset += i;
4415 @@ -411,44 +418,44 @@
4416  static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *token) {
4417         int tid = 0;
4418         size_t i;
4419 -       
4420 +
4421         for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
4422                 char c = t->input[t->offset];
4423                 const char *start = NULL;
4424 -               
4425 +
4426                 switch (c) {
4427 -               case '=': 
4428 +               case '=':
4429                         if (t->in_brace) {
4430                                 if (t->input[t->offset + 1] == '>') {
4431                                         t->offset += 2;
4432 -                                       
4433 +
4434                                         buffer_copy_string(token, "=>");
4435 -                                       
4436 +
4437                                         tid = TK_ARRAY_ASSIGN;
4438                                 } else {
4439 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4440 +                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4441                                                         "source:", t->source,
4442 -                                                       "line:", t->line, "pos:", t->line_pos, 
4443 +                                                       "line:", t->line, "pos:", t->line_pos,
4444                                                         "use => for assignments in arrays");
4445                                         return -1;
4446                                 }
4447                         } else if (t->in_cond) {
4448                                 if (t->input[t->offset + 1] == '=') {
4449                                         t->offset += 2;
4450 -                                       
4451 +
4452                                         buffer_copy_string(token, "==");
4453 -                                       
4454 +
4455                                         tid = TK_EQ;
4456                                 } else if (t->input[t->offset + 1] == '~') {
4457                                         t->offset += 2;
4458 -                                       
4459 +
4460                                         buffer_copy_string(token, "=~");
4461 -                                       
4462 +
4463                                         tid = TK_MATCH;
4464                                 } else {
4465 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4466 +                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4467                                                         "source:", t->source,
4468 -                                                       "line:", t->line, "pos:", t->line_pos, 
4469 +                                                       "line:", t->line, "pos:", t->line_pos,
4470                                                         "only =~ and == are allowed in the condition");
4471                                         return -1;
4472                                 }
4473 @@ -456,51 +463,51 @@
4474                                 t->in_cond = 0;
4475                         } else if (t->in_key) {
4476                                 tid = TK_ASSIGN;
4477 -                               
4478 +
4479                                 buffer_copy_string_len(token, t->input + t->offset, 1);
4480 -                               
4481 +
4482                                 t->offset++;
4483                                 t->line_pos++;
4484                         } else {
4485 -                               log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4486 +                               log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4487                                                 "source:", t->source,
4488 -                                               "line:", t->line, "pos:", t->line_pos, 
4489 +                                               "line:", t->line, "pos:", t->line_pos,
4490                                                 "unexpected equal-sign: =");
4491                                 return -1;
4492                         }
4493 -                       
4494 +
4495                         break;
4496 -               case '!': 
4497 +               case '!':
4498                         if (t->in_cond) {
4499                                 if (t->input[t->offset + 1] == '=') {
4500                                         t->offset += 2;
4501 -                                       
4502 +
4503                                         buffer_copy_string(token, "!=");
4504 -                                       
4505 +
4506                                         tid = TK_NE;
4507                                 } else if (t->input[t->offset + 1] == '~') {
4508                                         t->offset += 2;
4509 -                                       
4510 +
4511                                         buffer_copy_string(token, "!~");
4512 -                                       
4513 +
4514                                         tid = TK_NOMATCH;
4515                                 } else {
4516 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4517 +                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4518                                                         "source:", t->source,
4519 -                                                       "line:", t->line, "pos:", t->line_pos, 
4520 +                                                       "line:", t->line, "pos:", t->line_pos,
4521                                                         "only !~ and != are allowed in the condition");
4522                                         return -1;
4523                                 }
4524                                 t->in_key = 1;
4525                                 t->in_cond = 0;
4526                         } else {
4527 -                               log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4528 +                               log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4529                                                 "source:", t->source,
4530 -                                               "line:", t->line, "pos:", t->line_pos, 
4531 +                                               "line:", t->line, "pos:", t->line_pos,
4532                                                 "unexpected exclamation-marks: !");
4533                                 return -1;
4534                         }
4535 -                       
4536 +
4537                         break;
4538                 case '\t':
4539                 case ' ':
4540 @@ -546,10 +553,10 @@
4541                 case ',':
4542                         if (t->in_brace > 0) {
4543                                 tid = TK_COMMA;
4544 -                               
4545 +
4546                                 buffer_copy_string(token, "(COMMA)");
4547                         }
4548 -                       
4549 +
4550                         t->offset++;
4551                         t->line_pos++;
4552                         break;
4553 @@ -557,70 +564,70 @@
4554                         /* search for the terminating " */
4555                         start = t->input + t->offset + 1;
4556                         buffer_copy_string(token, "");
4557 -                       
4558 +
4559                         for (i = 1; t->input[t->offset + i]; i++) {
4560                                 if (t->input[t->offset + i] == '\\' &&
4561                                     t->input[t->offset + i + 1] == '"') {
4562 -                                       
4563 +
4564                                         buffer_append_string_len(token, start, t->input + t->offset + i - start);
4565 -                                       
4566 +
4567                                         start = t->input + t->offset + i + 1;
4568 -                                       
4569 +
4570                                         /* skip the " */
4571                                         i++;
4572                                         continue;
4573                                 }
4574 -                               
4575 -                               
4576 +
4577 +
4578                                 if (t->input[t->offset + i] == '"') {
4579                                         tid = TK_STRING;
4580 -                               
4581 +
4582                                         buffer_append_string_len(token, start, t->input + t->offset + i - start);
4583 -                                       
4584 +
4585                                         break;
4586                                 }
4587                         }
4588  
4589                         if (t->input[t->offset + i] == '\0') {
4590                                 /* ERROR */
4591 -                               
4592 -                               log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4593 +
4594 +                               log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4595                                                 "source:", t->source,
4596 -                                               "line:", t->line, "pos:", t->line_pos, 
4597 +                                               "line:", t->line, "pos:", t->line_pos,
4598                                                 "missing closing quote");
4599 -                               
4600 +
4601                                 return -1;
4602                         }
4603 -                       
4604 +
4605                         t->offset += i + 1;
4606                         t->line_pos += i + 1;
4607 -                       
4608 +
4609                         break;
4610                 case '(':
4611                         t->offset++;
4612                         t->in_brace++;
4613 -                               
4614 +
4615                         tid = TK_LPARAN;
4616 -                               
4617 +
4618                         buffer_copy_string(token, "(");
4619                         break;
4620                 case ')':
4621                         t->offset++;
4622                         t->in_brace--;
4623 -                               
4624 +
4625                         tid = TK_RPARAN;
4626 -                               
4627 +
4628                         buffer_copy_string(token, ")");
4629                         break;
4630                 case '$':
4631                         t->offset++;
4632 -                               
4633 +
4634                         tid = TK_DOLLAR;
4635                         t->in_cond = 1;
4636                         t->in_key = 0;
4637 -                               
4638 +
4639                         buffer_copy_string(token, "$");
4640 -                       
4641 +
4642                         break;
4643  
4644                 case '+':
4645 @@ -637,96 +644,88 @@
4646  
4647                 case '{':
4648                         t->offset++;
4649 -                               
4650 +
4651                         tid = TK_LCURLY;
4652 -                               
4653 +
4654                         buffer_copy_string(token, "{");
4655 -                       
4656 +
4657                         break;
4658 -                       
4659 +
4660                 case '}':
4661                         t->offset++;
4662 -                               
4663 +
4664                         tid = TK_RCURLY;
4665 -                               
4666 +
4667                         buffer_copy_string(token, "}");
4668 -                       
4669 +
4670                         break;
4671  
4672                 case '[':
4673                         t->offset++;
4674 -                               
4675 +
4676                         tid = TK_LBRACKET;
4677 -                               
4678 +
4679                         buffer_copy_string(token, "[");
4680 -                       
4681 +
4682                         break;
4683 -                       
4684 +
4685                 case ']':
4686                         t->offset++;
4687 -                               
4688 +
4689                         tid = TK_RBRACKET;
4690 -                               
4691 +
4692                         buffer_copy_string(token, "]");
4693 -                       
4694 +
4695                         break;
4696                 case '#':
4697                         t->line_pos += config_skip_comment(t);
4698 -                       
4699 +
4700                         break;
4701                 default:
4702                         if (t->in_cond) {
4703 -                               for (i = 0; t->input[t->offset + i] && 
4704 +                               for (i = 0; t->input[t->offset + i] &&
4705                                      (isalpha((unsigned char)t->input[t->offset + i])
4706                                       ); i++);
4707 -                               
4708 +
4709                                 if (i && t->input[t->offset + i]) {
4710                                         tid = TK_SRVVARNAME;
4711                                         buffer_copy_string_len(token, t->input + t->offset, i);
4712 -                                       
4713 +
4714                                         t->offset += i;
4715                                         t->line_pos += i;
4716                                 } else {
4717                                         /* ERROR */
4718 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4719 +                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4720                                                         "source:", t->source,
4721 -                                                       "line:", t->line, "pos:", t->line_pos, 
4722 +                                                       "line:", t->line, "pos:", t->line_pos,
4723                                                         "invalid character in condition");
4724                                         return -1;
4725                                 }
4726                         } else if (isdigit((unsigned char)c)) {
4727                                 /* take all digits */
4728                                 for (i = 0; t->input[t->offset + i] && isdigit((unsigned char)t->input[t->offset + i]);  i++);
4729 -                               
4730 +
4731                                 /* was there it least a digit ? */
4732 -                               if (i && t->input[t->offset + i]) {
4733 +                               if (i) {
4734                                         tid = TK_INTEGER;
4735 -                                       
4736 +
4737                                         buffer_copy_string_len(token, t->input + t->offset, i);
4738 -                                       
4739 +
4740                                         t->offset += i;
4741                                         t->line_pos += i;
4742 -                               } else {
4743 -                                       /* ERROR */
4744 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4745 -                                                       "source:", t->source,
4746 -                                                       "line:", t->line, "pos:", t->line_pos, 
4747 -                                                       "unexpected EOF");
4748 -                                       
4749 -                                       return -1;
4750                                 }
4751                         } else {
4752                                 /* the key might consist of [-.0-9a-z] */
4753 -                               for (i = 0; t->input[t->offset + i] && 
4754 -                                    (isalnum((unsigned char)t->input[t->offset + i]) || 
4755 +                               for (i = 0; t->input[t->offset + i] &&
4756 +                                    (isalnum((unsigned char)t->input[t->offset + i]) ||
4757                                       t->input[t->offset + i] == '.' ||
4758                                       t->input[t->offset + i] == '_' || /* for env.* */
4759                                       t->input[t->offset + i] == '-'
4760                                       ); i++);
4761 -                               
4762 +
4763                                 if (i && t->input[t->offset + i]) {
4764                                         buffer_copy_string_len(token, t->input + t->offset, i);
4765 -                                       
4766 +
4767                                         if (strcmp(token->ptr, "include") == 0) {
4768                                                 tid = TK_INCLUDE;
4769                                         } else if (strcmp(token->ptr, "include_shell") == 0) {
4770 @@ -738,14 +737,14 @@
4771                                         } else {
4772                                                 tid = TK_LKEY;
4773                                         }
4774 -                                       
4775 +
4776                                         t->offset += i;
4777                                         t->line_pos += i;
4778                                 } else {
4779                                         /* ERROR */
4780 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds", 
4781 +                                       log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4782                                                         "source:", t->source,
4783 -                                                       "line:", t->line, "pos:", t->line_pos, 
4784 +                                                       "line:", t->line, "pos:", t->line_pos,
4785                                                         "invalid character in variable name");
4786                                         return -1;
4787                                 }
4788 @@ -753,16 +752,16 @@
4789                         break;
4790                 }
4791         }
4792 -       
4793 +
4794         if (tid) {
4795                 *token_id = tid;
4796  #if 0
4797 -               log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd", 
4798 +               log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd",
4799                                 "source:", t->source,
4800                                 "line:", t->line, "pos:", t->line_pos,
4801                                 token, token->used - 1, tid);
4802  #endif
4803 -               
4804 +
4805                 return 1;
4806         } else if (t->offset < t->size) {
4807                 fprintf(stderr, "%s.%d: %d, %s\n",
4808 @@ -781,10 +780,11 @@
4809         pParser = configparserAlloc( malloc );
4810         lasttoken = buffer_init();
4811         token = buffer_init();
4812 +
4813         while((1 == (ret = config_tokenizer(srv, t, &token_id, token))) && context->ok) {
4814                 buffer_copy_string_buffer(lasttoken, token);
4815                 configparser(pParser, token_id, token, context);
4816 -               
4817 +
4818                 token = buffer_init();
4819         }
4820         buffer_free(token);
4821 @@ -797,14 +797,14 @@
4822                 }
4823         }
4824         configparserFree(pParser, free);
4825 -       
4826 +
4827         if (ret == -1) {
4828 -               log_error_write(srv, __FILE__, __LINE__, "sb", 
4829 +               log_error_write(srv, __FILE__, __LINE__, "sb",
4830                                 "configfile parser failed:", lasttoken);
4831         } else if (context->ok == 0) {
4832 -               log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb", 
4833 +               log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb",
4834                                 "source:", t->source,
4835 -                               "line:", t->line, "pos:", t->line_pos, 
4836 +                               "line:", t->line, "pos:", t->line_pos,
4837                                 "parser failed somehow near here:", lasttoken);
4838                 ret = -1;
4839         }
4840 @@ -821,7 +821,7 @@
4841         t->offset = 0;
4842         t->line = 1;
4843         t->line_pos = 1;
4844 -       
4845 +
4846         t->in_key = 1;
4847         t->in_brace = 0;
4848         t->in_cond = 0;
4849 @@ -844,7 +844,7 @@
4850         }
4851  
4852         if (0 != stream_open(&s, filename)) {
4853 -               log_error_write(srv, __FILE__, __LINE__, "sbss", 
4854 +               log_error_write(srv, __FILE__, __LINE__, "sbss",
4855                                 "opening configfile ", filename, "failed:", strerror(errno));
4856                 ret = -1;
4857         } else {
4858 @@ -866,7 +866,7 @@
4859         char oldpwd[PATH_MAX];
4860  
4861         if (NULL == getcwd(oldpwd, sizeof(oldpwd))) {
4862 -               log_error_write(srv, __FILE__, __LINE__, "s", 
4863 +               log_error_write(srv, __FILE__, __LINE__, "s",
4864                                 "cannot get cwd", strerror(errno));
4865                 return -1;
4866         }
4867 @@ -879,7 +879,7 @@
4868         }
4869  
4870         if (0 != proc_open_buffer(&proc, cmd, NULL, out, NULL)) {
4871 -               log_error_write(srv, __FILE__, __LINE__, "sbss", 
4872 +               log_error_write(srv, __FILE__, __LINE__, "sbss",
4873                                 "opening", source, "failed:", strerror(errno));
4874                 ret = -1;
4875         } else {
4876 @@ -896,13 +896,12 @@
4877  static void context_init(server *srv, config_t *context) {
4878         context->srv = srv;
4879         context->ok = 1;
4880 -       context->configs_stack = array_init();
4881 -       context->configs_stack->is_weakref = 1;
4882 +       context->configs_stack = buffer_ptr_init(NULL);
4883         context->basedir = buffer_init();
4884  }
4885  
4886  static void context_free(config_t *context) {
4887 -       array_free(context->configs_stack);
4888 +       buffer_ptr_free(context->configs_stack);
4889         buffer_free(context->basedir);
4890  }
4891  
4892 @@ -918,18 +917,15 @@
4893         context_init(srv, &context);
4894         context.all_configs = srv->config_context;
4895  
4896 -       pos = strrchr(fn,
4897 -#ifdef __WIN32
4898 -                       '\\'
4899 -#else
4900 -                       '/'
4901 -#endif
4902 -                       );
4903 +    /* use the current dir as basedir for all other includes
4904 +    */
4905 +       pos = strrchr(fn, DIR_SEPERATOR);
4906 +
4907         if (pos) {
4908                 buffer_copy_string_len(context.basedir, fn, pos - fn + 1);
4909                 fn = pos + 1;
4910         }
4911 -       
4912 +
4913         dc = data_config_init();
4914         buffer_copy_string(dc->key, "global");
4915  
4916 @@ -944,7 +940,7 @@
4917         dpid->value = getpid();
4918         buffer_copy_string(dpid->key, "var.PID");
4919         array_insert_unique(srv->config, (data_unset *)dpid);
4920 -       
4921 +
4922         dcwd = data_string_init();
4923         buffer_prepare_copy(dcwd->value, 1024);
4924         if (NULL != getcwd(dcwd->value->ptr, dcwd->value->size - 1)) {
4925 @@ -968,7 +964,7 @@
4926         } else {
4927                 return -1;
4928         }
4929 -       
4930 +
4931         if (NULL != (modules = (data_array *)array_get_element(srv->config, "server.modules"))) {
4932                 data_string *ds;
4933                 data_array *prepends;
4934 @@ -1026,22 +1022,23 @@
4935                 buffer_copy_string(modules->key, "server.modules");
4936                 array_insert_unique(srv->config, (data_unset *)modules);
4937         }
4938 -       
4939 +
4940  
4941         if (0 != config_insert(srv)) {
4942                 return -1;
4943         }
4944 -       
4945 +
4946         return 0;
4947  }
4948  
4949 +
4950  int config_set_defaults(server *srv) {
4951         size_t i;
4952         specific_config *s = srv->config_storage[0];
4953         struct stat st1, st2;
4954 -       
4955 -       struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] = 
4956 -       { 
4957 +
4958 +       struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
4959 +       {
4960                 /* - poll is most reliable
4961                  * - select works everywhere
4962                  * - linux-* are experimental
4963 @@ -1067,20 +1064,21 @@
4964  #endif
4965                 { FDEVENT_HANDLER_UNSET,          NULL }
4966         };
4967 -       
4968  
4969 -       if (buffer_is_empty(s->document_root)) {  
4970 -               log_error_write(srv, __FILE__, __LINE__, "s",  
4971 -                               "a default document-root has to be set");  
4972 -               
4973 -               return -1;  
4974 -       }  
4975 -       
4976 +
4977 +       if (buffer_is_empty(s->document_root)) {
4978 +               log_error_write(srv, __FILE__, __LINE__, "s",
4979 +                               "a default document-root has to be set");
4980 +
4981 +               return -1;
4982 +       }
4983 +
4984         if (buffer_is_empty(srv->srvconf.changeroot)) {
4985 -               if (-1 == stat(s->document_root->ptr, &st1)) {  
4986 -                       log_error_write(srv, __FILE__, __LINE__, "sb",  
4987 +        pathname_unix2local(s->document_root);
4988 +               if (-1 == stat(s->document_root->ptr, &st1)) {
4989 +                       log_error_write(srv, __FILE__, __LINE__, "sbs",
4990                                         "base-docroot doesn't exist:",
4991 -                                       s->document_root);  
4992 +                                       s->document_root, strerror(errno));
4993                         return -1;
4994                 }
4995  
4996 @@ -1088,18 +1086,18 @@
4997                 buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.changeroot);
4998                 buffer_append_string_buffer(srv->tmp_buf, s->document_root);
4999  
5000 -               if (-1 == stat(srv->tmp_buf->ptr, &st1)) {  
5001 -                       log_error_write(srv, __FILE__, __LINE__, "sb",  
5002 +               if (-1 == stat(srv->tmp_buf->ptr, &st1)) {
5003 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
5004                                         "base-docroot doesn't exist:",
5005 -                                       srv->tmp_buf);  
5006 +                                       srv->tmp_buf);
5007                         return -1;
5008                 }
5009 -               
5010 +
5011         }
5012 -       
5013 -       buffer_copy_string_buffer(srv->tmp_buf, s->document_root);  
5014  
5015 -       buffer_to_lower(srv->tmp_buf);  
5016 +       buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
5017 +
5018 +       buffer_to_lower(srv->tmp_buf);
5019  
5020         if (0 == stat(srv->tmp_buf->ptr, &st1)) {
5021                 int is_lower = 0;
5022 @@ -1107,68 +1105,68 @@
5023                 is_lower = buffer_is_equal(srv->tmp_buf, s->document_root);
5024  
5025                 /* lower-case existed, check upper-case */
5026 -               buffer_copy_string_buffer(srv->tmp_buf, s->document_root);  
5027 +               buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
5028  
5029 -               buffer_to_upper(srv->tmp_buf);  
5030 +               buffer_to_upper(srv->tmp_buf);
5031  
5032                 /* we have to handle the special case that upper and lower-casing results in the same filename
5033                  * as in server.document-root = "/" or "/12345/" */
5034  
5035                 if (is_lower && buffer_is_equal(srv->tmp_buf, s->document_root)) {
5036 -                       /* lower-casing and upper-casing didn't result in  
5037 -                        * an other filename, no need to stat(), 
5038 +                       /* lower-casing and upper-casing didn't result in
5039 +                        * an other filename, no need to stat(),
5040                          * just assume it is case-sensitive. */
5041  
5042                         s->force_lowercase_filenames = 0;
5043 -               } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {  
5044 +               } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {
5045 +
5046 +                       /* upper case exists too, doesn't the FS handle this ? */
5047 +
5048 +                       /* upper and lower have the same inode -> case-insensitve FS */
5049 +
5050 +                       if (st1.st_ino == st2.st_ino) {
5051 +                               /* upper and lower have the same inode -> case-insensitve FS */
5052 +
5053 +                               s->force_lowercase_filenames = 1;
5054 +                       }
5055 +               }
5056 +       }
5057  
5058 -                       /* upper case exists too, doesn't the FS handle this ? */  
5059 -                       
5060 -                       /* upper and lower have the same inode -> case-insensitve FS */  
5061 -                       
5062 -                       if (st1.st_ino == st2.st_ino) {  
5063 -                               /* upper and lower have the same inode -> case-insensitve FS */  
5064 -                               
5065 -                               s->force_lowercase_filenames = 1;  
5066 -                       }  
5067 -               }  
5068 -       }  
5069 -       
5070         if (srv->srvconf.port == 0) {
5071                 srv->srvconf.port = s->is_ssl ? 443 : 80;
5072         }
5073 -       
5074 +
5075         if (srv->srvconf.event_handler->used == 0) {
5076                 /* choose a good default
5077 -                * 
5078 -                * the event_handler list is sorted by 'goodness' 
5079 +                *
5080 +                * the event_handler list is sorted by 'goodness'
5081                  * taking the first available should be the best solution
5082                  */
5083                 srv->event_handler = event_handlers[0].et;
5084 -               
5085 +
5086                 if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
5087 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
5088 +                       log_error_write(srv, __FILE__, __LINE__, "s",
5089                                         "sorry, there is no event handler for this system");
5090 -                       
5091 +
5092                         return -1;
5093                 }
5094         } else {
5095                 /*
5096                  * User override
5097                  */
5098 -               
5099 +
5100                 for (i = 0; event_handlers[i].name; i++) {
5101                         if (0 == strcmp(event_handlers[i].name, srv->srvconf.event_handler->ptr)) {
5102                                 srv->event_handler = event_handlers[i].et;
5103                                 break;
5104                         }
5105                 }
5106 -               
5107 +
5108                 if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
5109 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
5110 -                                       "the selected event-handler in unknown or not supported:", 
5111 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
5112 +                                       "the selected event-handler in unknown or not supported:",
5113                                         srv->srvconf.event_handler );
5114 -                       
5115 +
5116                         return -1;
5117                 }
5118         }
5119 @@ -1176,19 +1174,19 @@
5120         if (s->is_ssl) {
5121                 if (buffer_is_empty(s->ssl_pemfile)) {
5122                         /* PEM file is require */
5123 -                       
5124 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
5125 +
5126 +                       log_error_write(srv, __FILE__, __LINE__, "s",
5127                                         "ssl.pemfile has to be set");
5128                         return -1;
5129                 }
5130 -               
5131 +
5132  #ifndef USE_OPENSSL
5133 -               log_error_write(srv, __FILE__, __LINE__, "s", 
5134 +               log_error_write(srv, __FILE__, __LINE__, "s",
5135                                 "ssl support is missing, recompile with --with-openssl");
5136 -               
5137 +
5138                 return -1;
5139  #endif
5140         }
5141 -       
5142 +
5143         return 0;
5144  }
5145 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/configfile.h lighttpd-1.4.12/src/configfile.h
5146 --- lighttpd-1.4.11/src/configfile.h    2005-08-23 17:36:12.000000000 +0300
5147 +++ lighttpd-1.4.12/src/configfile.h    2006-07-11 21:23:39.000000000 +0300
5148 @@ -9,7 +9,7 @@
5149         server *srv;
5150         int     ok;
5151         array  *all_configs;
5152 -       array  *configs_stack; /* to parse nested block */
5153 +       buffer_ptr  *configs_stack; /* to parse nested block */
5154         data_config *current; /* current started with { */
5155         buffer *basedir;
5156  } config_t;
5157 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/configparser.c lighttpd-1.4.12/src/configparser.c
5158 --- lighttpd-1.4.11/src/configparser.c  2006-02-01 19:51:15.000000000 +0200
5159 +++ lighttpd-1.4.12/src/configparser.c  2006-07-11 21:49:18.000000000 +0300
5160 @@ -24,52 +24,34 @@
5161      dc->parent = ctx->current;
5162      array_insert_unique(dc->parent->childs, (data_unset *)dc);
5163    }
5164 -  array_insert_unique(ctx->configs_stack, (data_unset *)ctx->current);
5165 +  buffer_ptr_append(ctx->configs_stack, (void *)ctx->current);
5166    ctx->current = dc;
5167  }
5168  
5169  static data_config *configparser_pop(config_t *ctx) {
5170    data_config *old = ctx->current;
5171 -  ctx->current = (data_config *) array_pop(ctx->configs_stack);
5172 +  ctx->current = (data_config *) buffer_ptr_pop(ctx->configs_stack);
5173    return old;
5174  }
5175  
5176  /* return a copied variable */
5177  static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
5178 -  if (strncmp(key->ptr, "env.", sizeof("env.") - 1) == 0) {
5179 -    char *env;
5180 -
5181 -    if (NULL != (env = getenv(key->ptr + 4))) {
5182 -      data_string *ds;
5183 -      ds = data_string_init();
5184 -      buffer_append_string(ds->value, env);
5185 -      return (data_unset *)ds;
5186 -    }
5187 -
5188 -    fprintf(stderr, "Undefined env variable: %s\n", key->ptr + 4);
5189 -    ctx->ok = 0;
5190 -
5191 -    return NULL;
5192 -  } else {
5193 -    data_unset *du;
5194 -    data_config *dc;
5195 +  data_unset *du;
5196 +  data_config *dc;
5197  
5198  #if 0
5199 -    fprintf(stderr, "get var %s\n", key->ptr);
5200 +  fprintf(stderr, "get var %s\n", key->ptr);
5201  #endif
5202 -    for (dc = ctx->current; dc; dc = dc->parent) {
5203 +  for (dc = ctx->current; dc; dc = dc->parent) {
5204  #if 0
5205 -      fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
5206 -      array_print(dc->value, 0);
5207 +    fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
5208 +    array_print(dc->value, 0);
5209  #endif
5210 -      if (NULL != (du = array_get_element(dc->value, key->ptr))) {
5211 -        return du->copy(du);
5212 -      }
5213 +    if (NULL != (du = array_get_element(dc->value, key->ptr))) {
5214 +      return du->copy(du);
5215      }
5216 -    fprintf(stderr, "Undefined config variable: %s\n", key->ptr);
5217 -    ctx->ok = 0;
5218 -    return NULL;
5219    }
5220 +  return NULL;
5221  }
5222  
5223  /* op1 is to be eat/return by this function, op1->key is not cared
5224 @@ -124,14 +106,14 @@
5225  }
5226  
5227  
5228 -#line 128 "configparser.c"
5229 +#line 110 "configparser.c"
5230  /* Next is all token values, in a form suitable for use by makeheaders.
5231  ** This section will be null unless lemon is run with the -m switch.
5232  */
5233 -/* 
5234 +/*
5235  ** These constants (all generated automatically by the parser generator)
5236  ** specify the various kinds of tokens (terminals) that the parser
5237 -** understands. 
5238 +** understands.
5239  **
5240  ** Each symbol here is a terminal symbol in the grammar.
5241  */
5242 @@ -148,7 +130,7 @@
5243  **                       and nonterminals.  "int" is used otherwise.
5244  **    YYNOCODE           is a number of type YYCODETYPE which corresponds
5245  **                       to no legal terminal or nonterminal number.  This
5246 -**                       number is used to fill in empty slots of the hash 
5247 +**                       number is used to fill in empty slots of the hash
5248  **                       table.
5249  **    YYFALLBACK         If defined, this indicates that one or more tokens
5250  **                       have fall-back values which should be used if the
5251 @@ -157,7 +139,7 @@
5252  **                       and nonterminal numbers.  "unsigned char" is
5253  **                       used if there are fewer than 250 rules and
5254  **                       states combined.  "int" is used otherwise.
5255 -**    configparserTOKENTYPE     is the data type used for minor tokens given 
5256 +**    configparserTOKENTYPE     is the data type used for minor tokens given
5257  **                       directly to the parser from the tokenizer.
5258  **    YYMINORTYPE        is the data type used for all minor tokens.
5259  **                       This is typically a union of many types, one of
5260 @@ -192,8 +174,8 @@
5261  #define configparserARG_PDECL ,config_t *ctx
5262  #define configparserARG_FETCH config_t *ctx = yypParser->ctx
5263  #define configparserARG_STORE yypParser->ctx = ctx
5264 -#define YYNSTATE 62
5265 -#define YYNRULE 39
5266 +#define YYNSTATE 63
5267 +#define YYNRULE 40
5268  #define YYERRORSYMBOL 26
5269  #define YYERRSYMDT yy95
5270  #define YY_NO_ACTION      (YYNSTATE+YYNRULE+2)
5271 @@ -203,7 +185,7 @@
5272  /* Next are that tables used to determine what action to take based on the
5273  ** current state and lookahead token.  These tables are used to implement
5274  ** functions that take a state number and lookahead value and return an
5275 -** action integer.  
5276 +** action integer.
5277  **
5278  ** Suppose the action integer is N.  Then the action is determined as
5279  ** follows
5280 @@ -228,7 +210,7 @@
5281  ** If the index value yy_shift_ofst[S]+X is out of range or if the value
5282  ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
5283  ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
5284 -** and that yy_default[S] should be used instead.  
5285 +** and that yy_default[S] should be used instead.
5286  **
5287  ** The formula above is for computing the action when the lookahead is
5288  ** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
5289 @@ -248,67 +230,69 @@
5290  **  yy_default[]       Default action for each state.
5291  */
5292  static YYACTIONTYPE yy_action[] = {
5293 - /*     0 */     2,    3,    4,    5,   13,   14,   62,   15,    7,   44,
5294 - /*    10 */    20,   86,   16,   45,   28,   48,   40,   10,   39,   25,
5295 - /*    20 */    22,   49,   45,    8,   15,  102,    1,   20,   28,   18,
5296 - /*    30 */    57,   59,   19,   25,   22,   39,   19,   61,   98,   45,
5297 - /*    40 */    20,    6,   23,   24,   26,   28,   35,   57,   59,   12,
5298 - /*    50 */    25,   22,   28,   27,   36,   87,   29,   25,   22,   33,
5299 - /*    60 */    15,   30,   31,   20,   28,   38,    9,   17,   37,   25,
5300 - /*    70 */    22,   39,   42,   43,   10,   45,   11,   53,   54,   55,
5301 - /*    80 */    56,   28,   52,   57,   59,   34,   25,   22,   28,   27,
5302 - /*    90 */    32,   88,   41,   25,   22,   33,   28,   48,   46,   28,
5303 - /*   100 */    48,   25,   22,   58,   25,   22,   60,   21,   19,   47,
5304 - /*   110 */    51,   50,   25,   22,   88,   88,   93,
5305 + /*     0 */     2,    3,    4,    5,   13,   14,   63,   15,    7,   45,
5306 + /*    10 */    20,   88,   16,   46,   28,   49,   41,   10,   40,   25,
5307 + /*    20 */    22,   50,   46,    8,   15,  104,    1,   20,   28,   18,
5308 + /*    30 */    58,   60,    6,   25,   22,   40,   47,   62,   11,   46,
5309 + /*    40 */    20,    9,   23,   24,   26,   29,   89,   58,   60,   10,
5310 + /*    50 */    17,   38,   28,   27,   37,   19,   30,   25,   22,   34,
5311 + /*    60 */    15,  100,   20,   20,   23,   24,   26,   12,   19,   31,
5312 + /*    70 */    32,   40,   19,   44,   43,   46,   95,   35,   90,   89,
5313 + /*    80 */    28,   49,   42,   58,   60,   25,   22,   59,   28,   27,
5314 + /*    90 */    33,   48,   52,   25,   22,   34,   28,   49,   51,   28,
5315 + /*   100 */    36,   25,   22,   61,   25,   22,   89,   28,   39,   89,
5316 + /*   110 */    89,   89,   25,   22,   54,   55,   56,   57,   89,   28,
5317 + /*   120 */    53,   21,   89,   89,   25,   22,   25,   22,
5318  };
5319  static YYCODETYPE yy_lookahead[] = {
5320   /*     0 */    29,   30,   31,   32,   33,   34,    0,    1,   44,   38,
5321   /*    10 */     4,   15,   41,   16,   35,   36,   45,   46,   12,   40,
5322   /*    20 */    41,   42,   16,   15,    1,   27,   28,    4,   35,   36,
5323 - /*    30 */    24,   25,    5,   40,   41,   12,    5,   14,   11,   16,
5324 - /*    40 */     4,    1,    6,    7,    8,   35,   36,   24,   25,   28,
5325 - /*    50 */    40,   41,   35,   36,   37,   15,   39,   40,   41,   42,
5326 - /*    60 */     1,    9,   10,    4,   35,   36,   38,    2,    3,   40,
5327 - /*    70 */    41,   12,   28,   14,   46,   16,   13,   20,   21,   22,
5328 - /*    80 */    23,   35,   36,   24,   25,   11,   40,   41,   35,   36,
5329 - /*    90 */    37,   13,   13,   40,   41,   42,   35,   36,   17,   35,
5330 - /*   100 */    36,   40,   41,   42,   40,   41,   42,   35,    5,   18,
5331 - /*   110 */    43,   19,   40,   41,   47,   47,   13,
5332 + /*    30 */    24,   25,    1,   40,   41,   12,   17,   14,   13,   16,
5333 + /*    40 */     4,   38,    6,    7,    8,    9,   15,   24,   25,   46,
5334 + /*    50 */     2,    3,   35,   36,   37,    5,   39,   40,   41,   42,
5335 + /*    60 */     1,   11,    4,    4,    6,    7,    8,   28,    5,    9,
5336 + /*    70 */    10,   12,    5,   14,   28,   16,   13,   11,   13,   47,
5337 + /*    80 */    35,   36,   13,   24,   25,   40,   41,   42,   35,   36,
5338 + /*    90 */    37,   18,   43,   40,   41,   42,   35,   36,   19,   35,
5339 + /*   100 */    36,   40,   41,   42,   40,   41,   47,   35,   36,   47,
5340 + /*   110 */    47,   47,   40,   41,   20,   21,   22,   23,   47,   35,
5341 + /*   120 */    36,   35,   47,   47,   40,   41,   40,   41,
5342  };
5343  #define YY_SHIFT_USE_DFLT (-5)
5344  static signed char yy_shift_ofst[] = {
5345 - /*     0 */    -5,    6,   -5,   -5,   -5,   40,   -4,    8,   -3,   -5,
5346 - /*    10 */    63,   -5,   23,   -5,   -5,   -5,   65,   36,   31,   36,
5347 - /*    20 */    -5,   -5,   -5,   -5,   -5,   -5,   36,   27,   -5,   52,
5348 - /*    30 */    -5,   36,   -5,   74,   36,   31,   -5,   36,   31,   78,
5349 - /*    40 */    79,   -5,   59,   -5,   -5,   81,   91,   36,   31,   92,
5350 - /*    50 */    57,   36,  103,   -5,   -5,   -5,   -5,   36,   -5,   36,
5351 - /*    60 */    -5,   -5,
5352 + /*     0 */    -5,    6,   -5,   -5,   -5,   31,   -4,    8,   -3,   -5,
5353 + /*    10 */    25,   -5,   23,   -5,   -5,   -5,   48,   58,   67,   58,
5354 + /*    20 */    -5,   -5,   -5,   -5,   -5,   -5,   36,   50,   -5,   -5,
5355 + /*    30 */    60,   -5,   58,   -5,   66,   58,   67,   -5,   58,   67,
5356 + /*    40 */    65,   69,   -5,   59,   -5,   -5,   19,   73,   58,   67,
5357 + /*    50 */    79,   94,   58,   63,   -5,   -5,   -5,   -5,   58,   -5,
5358 + /*    60 */    58,   -5,   -5,
5359  };
5360  #define YY_REDUCE_USE_DFLT (-37)
5361  static signed char yy_reduce_ofst[] = {
5362 - /*     0 */    -2,  -29,  -37,  -37,  -37,  -36,  -37,  -37,   28,  -37,
5363 - /*    10 */   -37,   21,  -29,  -37,  -37,  -37,  -37,   -7,  -37,   72,
5364 + /*     0 */    -2,  -29,  -37,  -37,  -37,  -36,  -37,  -37,    3,  -37,
5365 + /*    10 */   -37,   39,  -29,  -37,  -37,  -37,  -37,   -7,  -37,   86,
5366   /*    20 */   -37,  -37,  -37,  -37,  -37,  -37,   17,  -37,  -37,  -37,
5367 - /*    30 */   -37,   53,  -37,  -37,   10,  -37,  -37,   29,  -37,  -37,
5368 - /*    40 */   -37,   44,  -29,  -37,  -37,  -37,  -37,  -21,  -37,  -37,
5369 - /*    50 */    67,   46,  -37,  -37,  -37,  -37,  -37,   61,  -37,   64,
5370 - /*    60 */   -37,  -37,
5371 + /*    30 */   -37,  -37,   53,  -37,  -37,   64,  -37,  -37,   72,  -37,
5372 + /*    40 */   -37,  -37,   46,  -29,  -37,  -37,  -37,  -37,  -21,  -37,
5373 + /*    50 */   -37,   49,   84,  -37,  -37,  -37,  -37,  -37,   45,  -37,
5374 + /*    60 */    61,  -37,  -37,
5375  };
5376  static YYACTIONTYPE yy_default[] = {
5377 - /*     0 */    64,  101,   63,   65,   66,  101,   67,  101,  101,   90,
5378 - /*    10 */   101,   64,  101,   68,   69,   70,  101,  101,   71,  101,
5379 - /*    20 */    73,   74,   76,   77,   78,   79,  101,   84,   75,  101,
5380 - /*    30 */    80,   82,   81,  101,  101,   85,   83,  101,   72,  101,
5381 - /*    40 */   101,   64,  101,   89,   91,  101,  101,  101,   98,  101,
5382 - /*    50 */   101,  101,  101,   94,   95,   96,   97,  101,   99,  101,
5383 - /*    60 */   100,   92,
5384 + /*     0 */    65,  103,   64,   66,   67,  103,   68,  103,  103,   92,
5385 + /*    10 */   103,   65,  103,   69,   70,   71,  103,  103,   72,  103,
5386 + /*    20 */    74,   75,   77,   78,   79,   80,  103,   86,   76,   81,
5387 + /*    30 */   103,   82,   84,   83,  103,  103,   87,   85,  103,   73,
5388 + /*    40 */   103,  103,   65,  103,   91,   93,  103,  103,  103,  100,
5389 + /*    50 */   103,  103,  103,  103,   96,   97,   98,   99,  103,  101,
5390 + /*    60 */   103,  102,   94,
5391  };
5392  #define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
5393  
5394  /* The next table maps tokens into fallback tokens.  If a construct
5395  ** like the following:
5396 -** 
5397 +**
5398  **      %fallback ID X Y Z.
5399  **
5400  ** appears in the grammer, then ID becomes a fallback token for X, Y,
5401 @@ -359,10 +343,10 @@
5402  #endif /* NDEBUG */
5403  
5404  #ifndef NDEBUG
5405 -/* 
5406 +/*
5407  ** Turn parser tracing on by giving a stream to which to write the trace
5408  ** and a prompt to preface each trace message.  Tracing is turned off
5409 -** by making either argument NULL 
5410 +** by making either argument NULL
5411  **
5412  ** Inputs:
5413  ** <ul>
5414 @@ -387,7 +371,7 @@
5415  #ifndef NDEBUG
5416  /* For tracing shifts, the names of all terminals and nonterminals
5417  ** are required.  The following table supplies these names */
5418 -static const char *yyTokenName[] = { 
5419 +static const char *yyTokenName[] = {
5420    "$",             "EOL",           "ASSIGN",        "APPEND",      
5421    "LKEY",          "PLUS",          "STRING",        "INTEGER",     
5422    "LPARAN",        "RPARAN",        "COMMA",         "ARRAY_ASSIGN",
5423 @@ -425,27 +409,28 @@
5424   /*  15 */ "value ::= STRING",
5425   /*  16 */ "value ::= INTEGER",
5426   /*  17 */ "value ::= array",
5427 - /*  18 */ "array ::= LPARAN aelements RPARAN",
5428 - /*  19 */ "aelements ::= aelements COMMA aelement",
5429 - /*  20 */ "aelements ::= aelements COMMA",
5430 - /*  21 */ "aelements ::= aelement",
5431 - /*  22 */ "aelement ::= expression",
5432 - /*  23 */ "aelement ::= stringop ARRAY_ASSIGN expression",
5433 - /*  24 */ "eols ::= EOL",
5434 - /*  25 */ "eols ::=",
5435 - /*  26 */ "globalstart ::= GLOBAL",
5436 - /*  27 */ "global ::= globalstart LCURLY metalines RCURLY",
5437 - /*  28 */ "condlines ::= condlines eols ELSE condline",
5438 - /*  29 */ "condlines ::= condline",
5439 - /*  30 */ "condline ::= context LCURLY metalines RCURLY",
5440 - /*  31 */ "context ::= DOLLAR SRVVARNAME LBRACKET stringop RBRACKET cond expression",
5441 - /*  32 */ "cond ::= EQ",
5442 - /*  33 */ "cond ::= MATCH",
5443 - /*  34 */ "cond ::= NE",
5444 - /*  35 */ "cond ::= NOMATCH",
5445 - /*  36 */ "stringop ::= expression",
5446 - /*  37 */ "include ::= INCLUDE stringop",
5447 - /*  38 */ "include_shell ::= INCLUDE_SHELL stringop",
5448 + /*  18 */ "array ::= LPARAN RPARAN",
5449 + /*  19 */ "array ::= LPARAN aelements RPARAN",
5450 + /*  20 */ "aelements ::= aelements COMMA aelement",
5451 + /*  21 */ "aelements ::= aelements COMMA",
5452 + /*  22 */ "aelements ::= aelement",
5453 + /*  23 */ "aelement ::= expression",
5454 + /*  24 */ "aelement ::= stringop ARRAY_ASSIGN expression",
5455 + /*  25 */ "eols ::= EOL",
5456 + /*  26 */ "eols ::=",
5457 + /*  27 */ "globalstart ::= GLOBAL",
5458 + /*  28 */ "global ::= globalstart LCURLY metalines RCURLY",
5459 + /*  29 */ "condlines ::= condlines eols ELSE condline",
5460 + /*  30 */ "condlines ::= condline",
5461 + /*  31 */ "condline ::= context LCURLY metalines RCURLY",
5462 + /*  32 */ "context ::= DOLLAR SRVVARNAME LBRACKET stringop RBRACKET cond expression",
5463 + /*  33 */ "cond ::= EQ",
5464 + /*  34 */ "cond ::= MATCH",
5465 + /*  35 */ "cond ::= NE",
5466 + /*  36 */ "cond ::= NOMATCH",
5467 + /*  37 */ "stringop ::= expression",
5468 + /*  38 */ "include ::= INCLUDE stringop",
5469 + /*  39 */ "include_shell ::= INCLUDE_SHELL stringop",
5470  };
5471  #endif /* NDEBUG */
5472  
5473 @@ -465,7 +450,7 @@
5474  #endif
5475  }
5476  
5477 -/* 
5478 +/*
5479  ** This function allocates a new parser.
5480  ** The only argument is a pointer to a function which works like
5481  ** malloc.
5482 @@ -496,7 +481,7 @@
5483      /* Here is inserted the actions which take place when a
5484      ** terminal or non-terminal is destroyed.  This can happen
5485      ** when the symbol is popped from the stack during a
5486 -    ** reduce or during error processing or when a parser is 
5487 +    ** reduce or during error processing or when a parser is
5488      ** being destroyed before it is finished parsing.
5489      **
5490      ** Note: during a reduce, the only symbols destroyed are those
5491 @@ -528,44 +513,44 @@
5492      case 23:
5493      case 24:
5494      case 25:
5495 -#line 160 "./configparser.y"
5496 +#line 143 "./configparser.y"
5497  { buffer_free((yypminor->yy0)); }
5498 -#line 533 "configparser.c"
5499 +#line 518 "configparser.c"
5500        break;
5501      case 35:
5502 -#line 151 "./configparser.y"
5503 +#line 134 "./configparser.y"
5504  { (yypminor->yy41)->free((yypminor->yy41)); }
5505 -#line 538 "configparser.c"
5506 +#line 523 "configparser.c"
5507        break;
5508      case 36:
5509 -#line 152 "./configparser.y"
5510 +#line 135 "./configparser.y"
5511  { (yypminor->yy41)->free((yypminor->yy41)); }
5512 -#line 543 "configparser.c"
5513 +#line 528 "configparser.c"
5514        break;
5515      case 37:
5516 -#line 153 "./configparser.y"
5517 +#line 136 "./configparser.y"
5518  { (yypminor->yy41)->free((yypminor->yy41)); }
5519 -#line 548 "configparser.c"
5520 +#line 533 "configparser.c"
5521        break;
5522      case 39:
5523 -#line 154 "./configparser.y"
5524 +#line 137 "./configparser.y"
5525  { array_free((yypminor->yy40)); }
5526 -#line 553 "configparser.c"
5527 +#line 538 "configparser.c"
5528        break;
5529      case 40:
5530 -#line 155 "./configparser.y"
5531 +#line 138 "./configparser.y"
5532  { array_free((yypminor->yy40)); }
5533 -#line 558 "configparser.c"
5534 +#line 543 "configparser.c"
5535        break;
5536      case 41:
5537 -#line 156 "./configparser.y"
5538 +#line 139 "./configparser.y"
5539  { buffer_free((yypminor->yy43)); }
5540 -#line 563 "configparser.c"
5541 +#line 548 "configparser.c"
5542        break;
5543      case 42:
5544 -#line 157 "./configparser.y"
5545 +#line 140 "./configparser.y"
5546  { buffer_free((yypminor->yy43)); }
5547 -#line 568 "configparser.c"
5548 +#line 553 "configparser.c"
5549        break;
5550      default:  break;   /* If no destructor action specified: do nothing */
5551    }
5552 @@ -597,7 +582,7 @@
5553    return yymajor;
5554  }
5555  
5556 -/* 
5557 +/*
5558  ** Deallocate and destroy a parser.  Destructors are all called for
5559  ** all stack elements before shutting the parser down.
5560  **
5561 @@ -633,7 +618,7 @@
5562  ){
5563    int i;
5564    int stateno = pParser->yystack[pParser->yyidx].stateno;
5565
5566 +
5567    /* if( pParser->yyidx<0 ) return YY_NO_ACTION;  */
5568    i = yy_shift_ofst[stateno];
5569    if( i==YY_SHIFT_USE_DFLT ){
5570 @@ -677,7 +662,7 @@
5571  ){
5572    int i;
5573    int stateno = pParser->yystack[pParser->yyidx].stateno;
5574
5575 +
5576    i = yy_reduce_ofst[stateno];
5577    if( i==YY_REDUCE_USE_DFLT ){
5578      return yy_default[stateno];
5579 @@ -759,6 +744,7 @@
5580    { 35, 1 },
5581    { 35, 1 },
5582    { 35, 1 },
5583 +  { 40, 2 },
5584    { 40, 3 },
5585    { 39, 3 },
5586    { 39, 2 },
5587 @@ -800,7 +786,7 @@
5588    configparserARG_FETCH;
5589    yymsp = &yypParser->yystack[yypParser->yyidx];
5590  #ifndef NDEBUG
5591 -  if( yyTraceFILE && yyruleno>=0 
5592 +  if( yyTraceFILE && yyruleno>=0
5593          && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
5594      fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
5595        yyRuleName[yyruleno]);
5596 @@ -832,9 +818,9 @@
5597          /* No destructor defined for global */
5598          break;
5599        case 5:
5600 -#line 134 "./configparser.y"
5601 +#line 116 "./configparser.y"
5602  { yymsp[-1].minor.yy78 = NULL; }
5603 -#line 837 "configparser.c"
5604 +#line 823 "configparser.c"
5605    yy_destructor(1,&yymsp[0].minor);
5606          break;
5607        case 6:
5608 @@ -847,10 +833,15 @@
5609    yy_destructor(1,&yymsp[0].minor);
5610          break;
5611        case 9:
5612 -#line 162 "./configparser.y"
5613 +#line 145 "./configparser.y"
5614  {
5615    buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
5616 -  if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) {
5617 +  if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
5618 +    fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
5619 +        ctx->current->context_ndx,
5620 +        ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
5621 +    ctx->ok = 0;
5622 +  } else if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) {
5623      array_insert_unique(ctx->current->value, yymsp[0].minor.yy41);
5624      yymsp[0].minor.yy41 = NULL;
5625    } else {
5626 @@ -864,16 +855,21 @@
5627    buffer_free(yymsp[-2].minor.yy43);
5628    yymsp[-2].minor.yy43 = NULL;
5629  }
5630 -#line 867 "configparser.c"
5631 +#line 858 "configparser.c"
5632    yy_destructor(2,&yymsp[-1].minor);
5633          break;
5634        case 10:
5635 -#line 179 "./configparser.y"
5636 +#line 167 "./configparser.y"
5637  {
5638    array *vars = ctx->current->value;
5639    data_unset *du;
5640  
5641 -  if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) {
5642 +  if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
5643 +    fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n",
5644 +        ctx->current->context_ndx,
5645 +        ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
5646 +    ctx->ok = 0;
5647 +  } else if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) {
5648      /* exists in current block */
5649      du = configparser_merge_data(du, yymsp[0].minor.yy41);
5650      if (NULL == du) {
5651 @@ -883,6 +879,7 @@
5652        buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43);
5653        array_replace(vars, du);
5654      }
5655 +    yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5656    } else if (NULL != (du = configparser_get_variable(ctx, yymsp[-2].minor.yy43))) {
5657      du = configparser_merge_data(du, yymsp[0].minor.yy41);
5658      if (NULL == du) {
5659 @@ -892,22 +889,20 @@
5660        buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43);
5661        array_insert_unique(ctx->current->value, du);
5662      }
5663 +    yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5664    } else {
5665 -    fprintf(stderr, "Undefined config variable in conditional %d %s: %s\n", 
5666 -            ctx->current->context_ndx,
5667 -            ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
5668 -    ctx->ok = 0;
5669 +    buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
5670 +    array_insert_unique(ctx->current->value, yymsp[0].minor.yy41);
5671    }
5672    buffer_free(yymsp[-2].minor.yy43);
5673    yymsp[-2].minor.yy43 = NULL;
5674 -  yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5675    yymsp[0].minor.yy41 = NULL;
5676  }
5677 -#line 906 "configparser.c"
5678 +#line 901 "configparser.c"
5679    yy_destructor(3,&yymsp[-1].minor);
5680          break;
5681        case 11:
5682 -#line 214 "./configparser.y"
5683 +#line 206 "./configparser.y"
5684  {
5685    if (strchr(yymsp[0].minor.yy0->ptr, '.') == NULL) {
5686      yygotominor.yy43 = buffer_init_string("var.");
5687 @@ -919,10 +914,10 @@
5688      yymsp[0].minor.yy0 = NULL;
5689    }
5690  }
5691 -#line 922 "configparser.c"
5692 +#line 917 "configparser.c"
5693          break;
5694        case 12:
5695 -#line 226 "./configparser.y"
5696 +#line 218 "./configparser.y"
5697  {
5698    yygotominor.yy41 = configparser_merge_data(yymsp[-2].minor.yy41, yymsp[0].minor.yy41);
5699    if (NULL == yygotominor.yy41) {
5700 @@ -932,21 +927,38 @@
5701    yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5702    yymsp[0].minor.yy41 = NULL;
5703  }
5704 -#line 935 "configparser.c"
5705 +#line 930 "configparser.c"
5706    yy_destructor(5,&yymsp[-1].minor);
5707          break;
5708        case 13:
5709 -#line 236 "./configparser.y"
5710 +#line 228 "./configparser.y"
5711  {
5712    yygotominor.yy41 = yymsp[0].minor.yy41;
5713    yymsp[0].minor.yy41 = NULL;
5714  }
5715 -#line 944 "configparser.c"
5716 +#line 939 "configparser.c"
5717          break;
5718        case 14:
5719 -#line 241 "./configparser.y"
5720 +#line 233 "./configparser.y"
5721  {
5722 -  yygotominor.yy41 = configparser_get_variable(ctx, yymsp[0].minor.yy43);
5723 +  if (strncmp(yymsp[0].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
5724 +    char *env;
5725 +
5726 +    if (NULL != (env = getenv(yymsp[0].minor.yy43->ptr + 4))) {
5727 +      data_string *ds;
5728 +      ds = data_string_init();
5729 +      buffer_append_string(ds->value, env);
5730 +      yygotominor.yy41 = (data_unset *)ds;
5731 +    }
5732 +    else {
5733 +      yygotominor.yy41 = NULL;
5734 +      fprintf(stderr, "Undefined env variable: %s\n", yymsp[0].minor.yy43->ptr + 4);
5735 +      ctx->ok = 0;
5736 +    }
5737 +  } else if (NULL == (yygotominor.yy41 = configparser_get_variable(ctx, yymsp[0].minor.yy43))) {
5738 +    fprintf(stderr, "Undefined config variable: %s\n", yymsp[0].minor.yy43->ptr);
5739 +    ctx->ok = 0;
5740 +  }
5741    if (!yygotominor.yy41) {
5742      /* make a dummy so it won't crash */
5743      yygotominor.yy41 = (data_unset *)data_string_init();
5744 @@ -954,50 +966,59 @@
5745    buffer_free(yymsp[0].minor.yy43);
5746    yymsp[0].minor.yy43 = NULL;
5747  }
5748 -#line 957 "configparser.c"
5749 +#line 969 "configparser.c"
5750          break;
5751        case 15:
5752 -#line 251 "./configparser.y"
5753 +#line 260 "./configparser.y"
5754  {
5755    yygotominor.yy41 = (data_unset *)data_string_init();
5756    buffer_copy_string_buffer(((data_string *)(yygotominor.yy41))->value, yymsp[0].minor.yy0);
5757    buffer_free(yymsp[0].minor.yy0);
5758    yymsp[0].minor.yy0 = NULL;
5759  }
5760 -#line 967 "configparser.c"
5761 +#line 979 "configparser.c"
5762          break;
5763        case 16:
5764 -#line 258 "./configparser.y"
5765 +#line 267 "./configparser.y"
5766  {
5767    yygotominor.yy41 = (data_unset *)data_integer_init();
5768    ((data_integer *)(yygotominor.yy41))->value = strtol(yymsp[0].minor.yy0->ptr, NULL, 10);
5769    buffer_free(yymsp[0].minor.yy0);
5770    yymsp[0].minor.yy0 = NULL;
5771  }
5772 -#line 977 "configparser.c"
5773 +#line 989 "configparser.c"
5774          break;
5775        case 17:
5776 -#line 264 "./configparser.y"
5777 +#line 273 "./configparser.y"
5778  {
5779    yygotominor.yy41 = (data_unset *)data_array_init();
5780    array_free(((data_array *)(yygotominor.yy41))->value);
5781    ((data_array *)(yygotominor.yy41))->value = yymsp[0].minor.yy40;
5782    yymsp[0].minor.yy40 = NULL;
5783  }
5784 -#line 987 "configparser.c"
5785 +#line 999 "configparser.c"
5786          break;
5787        case 18:
5788 -#line 270 "./configparser.y"
5789 +#line 279 "./configparser.y"
5790 +{
5791 +  yygotominor.yy40 = array_init();
5792 +}
5793 +#line 1006 "configparser.c"
5794 +  yy_destructor(8,&yymsp[-1].minor);
5795 +  yy_destructor(9,&yymsp[0].minor);
5796 +        break;
5797 +      case 19:
5798 +#line 282 "./configparser.y"
5799  {
5800    yygotominor.yy40 = yymsp[-1].minor.yy40;
5801    yymsp[-1].minor.yy40 = NULL;
5802  }
5803 -#line 995 "configparser.c"
5804 +#line 1016 "configparser.c"
5805    yy_destructor(8,&yymsp[-2].minor);
5806    yy_destructor(9,&yymsp[0].minor);
5807          break;
5808 -      case 19:
5809 -#line 275 "./configparser.y"
5810 +      case 20:
5811 +#line 287 "./configparser.y"
5812  {
5813    if (buffer_is_empty(yymsp[0].minor.yy41->key) ||
5814        NULL == array_get_element(yymsp[-2].minor.yy40, yymsp[0].minor.yy41->key->ptr)) {
5815 @@ -1014,37 +1035,37 @@
5816    yygotominor.yy40 = yymsp[-2].minor.yy40;
5817    yymsp[-2].minor.yy40 = NULL;
5818  }
5819 -#line 1017 "configparser.c"
5820 +#line 1038 "configparser.c"
5821    yy_destructor(10,&yymsp[-1].minor);
5822          break;
5823 -      case 20:
5824 -#line 292 "./configparser.y"
5825 +      case 21:
5826 +#line 304 "./configparser.y"
5827  {
5828    yygotominor.yy40 = yymsp[-1].minor.yy40;
5829    yymsp[-1].minor.yy40 = NULL;
5830  }
5831 -#line 1026 "configparser.c"
5832 +#line 1047 "configparser.c"
5833    yy_destructor(10,&yymsp[0].minor);
5834          break;
5835 -      case 21:
5836 -#line 297 "./configparser.y"
5837 +      case 22:
5838 +#line 309 "./configparser.y"
5839  {
5840    yygotominor.yy40 = array_init();
5841    array_insert_unique(yygotominor.yy40, yymsp[0].minor.yy41);
5842    yymsp[0].minor.yy41 = NULL;
5843  }
5844 -#line 1036 "configparser.c"
5845 +#line 1057 "configparser.c"
5846          break;
5847 -      case 22:
5848 -#line 303 "./configparser.y"
5849 +      case 23:
5850 +#line 315 "./configparser.y"
5851  {
5852    yygotominor.yy41 = yymsp[0].minor.yy41;
5853    yymsp[0].minor.yy41 = NULL;
5854  }
5855 -#line 1044 "configparser.c"
5856 +#line 1065 "configparser.c"
5857          break;
5858 -      case 23:
5859 -#line 307 "./configparser.y"
5860 +      case 24:
5861 +#line 319 "./configparser.y"
5862  {
5863    buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
5864    buffer_free(yymsp[-2].minor.yy43);
5865 @@ -1053,27 +1074,27 @@
5866    yygotominor.yy41 = yymsp[0].minor.yy41;
5867    yymsp[0].minor.yy41 = NULL;
5868  }
5869 -#line 1056 "configparser.c"
5870 +#line 1077 "configparser.c"
5871    yy_destructor(11,&yymsp[-1].minor);
5872          break;
5873 -      case 24:
5874 -  yy_destructor(1,&yymsp[0].minor);
5875 -        break;
5876        case 25:
5877 +  yy_destructor(1,&yymsp[0].minor);
5878          break;
5879        case 26:
5880 -#line 319 "./configparser.y"
5881 +        break;
5882 +      case 27:
5883 +#line 331 "./configparser.y"
5884  {
5885    data_config *dc;
5886    dc = (data_config *)array_get_element(ctx->srv->config_context, "global");
5887    assert(dc);
5888    configparser_push(ctx, dc, 0);
5889  }
5890 -#line 1072 "configparser.c"
5891 +#line 1093 "configparser.c"
5892    yy_destructor(12,&yymsp[0].minor);
5893          break;
5894 -      case 27:
5895 -#line 326 "./configparser.y"
5896 +      case 28:
5897 +#line 338 "./configparser.y"
5898  {
5899    data_config *cur;
5900    
5901 @@ -1082,16 +1103,16 @@
5902  
5903    assert(cur && ctx->current);
5904  
5905 -  yygotominor.yy0 = cur;
5906 +  yygotominor.yy78 = cur;
5907  }
5908 -#line 1087 "configparser.c"
5909 +#line 1108 "configparser.c"
5910          /* No destructor defined for globalstart */
5911    yy_destructor(13,&yymsp[-2].minor);
5912          /* No destructor defined for metalines */
5913    yy_destructor(14,&yymsp[0].minor);
5914          break;
5915 -      case 28:
5916 -#line 337 "./configparser.y"
5917 +      case 29:
5918 +#line 349 "./configparser.y"
5919  {
5920    assert(yymsp[-3].minor.yy78->context_ndx < yymsp[0].minor.yy78->context_ndx);
5921    yymsp[0].minor.yy78->prev = yymsp[-3].minor.yy78;
5922 @@ -1100,20 +1121,20 @@
5923    yymsp[-3].minor.yy78 = NULL;
5924    yymsp[0].minor.yy78 = NULL;
5925  }
5926 -#line 1103 "configparser.c"
5927 +#line 1124 "configparser.c"
5928          /* No destructor defined for eols */
5929    yy_destructor(15,&yymsp[-1].minor);
5930          break;
5931 -      case 29:
5932 -#line 346 "./configparser.y"
5933 +      case 30:
5934 +#line 358 "./configparser.y"
5935  {
5936    yygotominor.yy78 = yymsp[0].minor.yy78;
5937    yymsp[0].minor.yy78 = NULL;
5938  }
5939 -#line 1113 "configparser.c"
5940 +#line 1134 "configparser.c"
5941          break;
5942 -      case 30:
5943 -#line 351 "./configparser.y"
5944 +      case 31:
5945 +#line 363 "./configparser.y"
5946  {
5947    data_config *cur;
5948    
5949 @@ -1124,14 +1145,14 @@
5950  
5951    yygotominor.yy78 = cur;
5952  }
5953 -#line 1127 "configparser.c"
5954 +#line 1148 "configparser.c"
5955          /* No destructor defined for context */
5956    yy_destructor(13,&yymsp[-2].minor);
5957          /* No destructor defined for metalines */
5958    yy_destructor(14,&yymsp[0].minor);
5959          break;
5960 -      case 31:
5961 -#line 362 "./configparser.y"
5962 +      case 32:
5963 +#line 374 "./configparser.y"
5964  {
5965    data_config *dc;
5966    buffer *b, *rvalue, *op;
5967 @@ -1266,45 +1287,45 @@
5968    yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5969    yymsp[0].minor.yy41 = NULL;
5970  }
5971 -#line 1269 "configparser.c"
5972 +#line 1290 "configparser.c"
5973    yy_destructor(16,&yymsp[-6].minor);
5974    yy_destructor(18,&yymsp[-4].minor);
5975    yy_destructor(19,&yymsp[-2].minor);
5976          break;
5977 -      case 32:
5978 -#line 496 "./configparser.y"
5979 +      case 33:
5980 +#line 508 "./configparser.y"
5981  {
5982    yygotominor.yy27 = CONFIG_COND_EQ;
5983  }
5984 -#line 1279 "configparser.c"
5985 +#line 1300 "configparser.c"
5986    yy_destructor(20,&yymsp[0].minor);
5987          break;
5988 -      case 33:
5989 -#line 499 "./configparser.y"
5990 +      case 34:
5991 +#line 511 "./configparser.y"
5992  {
5993    yygotominor.yy27 = CONFIG_COND_MATCH;
5994  }
5995 -#line 1287 "configparser.c"
5996 +#line 1308 "configparser.c"
5997    yy_destructor(21,&yymsp[0].minor);
5998          break;
5999 -      case 34:
6000 -#line 502 "./configparser.y"
6001 +      case 35:
6002 +#line 514 "./configparser.y"
6003  {
6004    yygotominor.yy27 = CONFIG_COND_NE;
6005  }
6006 -#line 1295 "configparser.c"
6007 +#line 1316 "configparser.c"
6008    yy_destructor(22,&yymsp[0].minor);
6009          break;
6010 -      case 35:
6011 -#line 505 "./configparser.y"
6012 +      case 36:
6013 +#line 517 "./configparser.y"
6014  {
6015    yygotominor.yy27 = CONFIG_COND_NOMATCH;
6016  }
6017 -#line 1303 "configparser.c"
6018 +#line 1324 "configparser.c"
6019    yy_destructor(23,&yymsp[0].minor);
6020          break;
6021 -      case 36:
6022 -#line 509 "./configparser.y"
6023 +      case 37:
6024 +#line 521 "./configparser.y"
6025  {
6026    yygotominor.yy43 = NULL;
6027    if (ctx->ok) {
6028 @@ -1321,10 +1342,10 @@
6029    yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
6030    yymsp[0].minor.yy41 = NULL;
6031  }
6032 -#line 1324 "configparser.c"
6033 +#line 1345 "configparser.c"
6034          break;
6035 -      case 37:
6036 -#line 526 "./configparser.y"
6037 +      case 38:
6038 +#line 538 "./configparser.y"
6039  {
6040    if (ctx->ok) {
6041      if (0 != config_parse_file(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
6042 @@ -1334,11 +1355,11 @@
6043      yymsp[0].minor.yy43 = NULL;
6044    }
6045  }
6046 -#line 1337 "configparser.c"
6047 +#line 1358 "configparser.c"
6048    yy_destructor(24,&yymsp[-1].minor);
6049          break;
6050 -      case 38:
6051 -#line 536 "./configparser.y"
6052 +      case 39:
6053 +#line 548 "./configparser.y"
6054  {
6055    if (ctx->ok) {
6056      if (0 != config_parse_cmd(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
6057 @@ -1348,7 +1369,7 @@
6058      yymsp[0].minor.yy43 = NULL;
6059    }
6060  }
6061 -#line 1351 "configparser.c"
6062 +#line 1372 "configparser.c"
6063    yy_destructor(25,&yymsp[-1].minor);
6064          break;
6065    };
6066 @@ -1378,11 +1399,11 @@
6067    while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
6068    /* Here code is inserted which will be executed whenever the
6069    ** parser fails */
6070 -#line 125 "./configparser.y"
6071 +#line 107 "./configparser.y"
6072  
6073    ctx->ok = 0;
6074  
6075 -#line 1385 "configparser.c"
6076 +#line 1406 "configparser.c"
6077    configparserARG_STORE; /* Suppress warning about unused %extra_argument variable */
6078  }
6079  
6080 @@ -1489,7 +1510,7 @@
6081  #ifdef YYERRORSYMBOL
6082        /* A syntax error has occurred.
6083        ** The response to an error depends upon whether or not the
6084 -      ** grammar defines an error token "ERROR".  
6085 +      ** grammar defines an error token "ERROR".
6086        **
6087        ** This is what we do if the grammar does define ERROR:
6088        **
6089 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/configparser.y lighttpd-1.4.12/src/configparser.y
6090 --- lighttpd-1.4.11/src/configparser.y  2006-01-26 18:46:25.000000000 +0200
6091 +++ lighttpd-1.4.12/src/configparser.y  2006-07-11 21:23:40.000000000 +0300
6092 @@ -21,52 +21,34 @@
6093      dc->parent = ctx->current;
6094      array_insert_unique(dc->parent->childs, (data_unset *)dc);
6095    }
6096 -  array_insert_unique(ctx->configs_stack, (data_unset *)ctx->current);
6097 +  buffer_ptr_append(ctx->configs_stack, (void *)ctx->current);
6098    ctx->current = dc;
6099  }
6100  
6101  static data_config *configparser_pop(config_t *ctx) {
6102    data_config *old = ctx->current;
6103 -  ctx->current = (data_config *) array_pop(ctx->configs_stack);
6104 +  ctx->current = (data_config *) buffer_ptr_pop(ctx->configs_stack);
6105    return old;
6106  }
6107  
6108  /* return a copied variable */
6109  static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
6110 -  if (strncmp(key->ptr, "env.", sizeof("env.") - 1) == 0) {
6111 -    char *env;
6112 -
6113 -    if (NULL != (env = getenv(key->ptr + 4))) {
6114 -      data_string *ds;
6115 -      ds = data_string_init();
6116 -      buffer_append_string(ds->value, env);
6117 -      return (data_unset *)ds;
6118 -    }
6119 -
6120 -    fprintf(stderr, "Undefined env variable: %s\n", key->ptr + 4);
6121 -    ctx->ok = 0;
6122 -
6123 -    return NULL;
6124 -  } else {
6125 -    data_unset *du;
6126 -    data_config *dc;
6127 +  data_unset *du;
6128 +  data_config *dc;
6129  
6130  #if 0
6131 -    fprintf(stderr, "get var %s\n", key->ptr);
6132 +  fprintf(stderr, "get var %s\n", key->ptr);
6133  #endif
6134 -    for (dc = ctx->current; dc; dc = dc->parent) {
6135 +  for (dc = ctx->current; dc; dc = dc->parent) {
6136  #if 0
6137 -      fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
6138 -      array_print(dc->value, 0);
6139 +    fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
6140 +    array_print(dc->value, 0);
6141  #endif
6142 -      if (NULL != (du = array_get_element(dc->value, key->ptr))) {
6143 -        return du->copy(du);
6144 -      }
6145 +    if (NULL != (du = array_get_element(dc->value, key->ptr))) {
6146 +      return du->copy(du);
6147      }
6148 -    fprintf(stderr, "Undefined config variable: %s\n", key->ptr);
6149 -    ctx->ok = 0;
6150 -    return NULL;
6151    }
6152 +  return NULL;
6153  }
6154  
6155  /* op1 is to be eat/return by this function, op1->key is not cared
6156 @@ -141,6 +123,7 @@
6157  %type       aelement               {data_unset *}
6158  %type       condline               {data_config *}
6159  %type       condlines              {data_config *}
6160 +%type       global                 {data_config *}
6161  %type       aelements              {array *}
6162  %type       array                  {array *}
6163  %type       key                    {buffer *}
6164 @@ -161,7 +144,12 @@
6165  
6166  varline ::= key(A) ASSIGN expression(B). {
6167    buffer_copy_string_buffer(B->key, A);
6168 -  if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
6169 +  if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
6170 +    fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
6171 +        ctx->current->context_ndx,
6172 +        ctx->current->key->ptr, A->ptr);
6173 +    ctx->ok = 0;
6174 +  } else if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
6175      array_insert_unique(ctx->current->value, B);
6176      B = NULL;
6177    } else {
6178 @@ -180,7 +168,12 @@
6179    array *vars = ctx->current->value;
6180    data_unset *du;
6181  
6182 -  if (NULL != (du = array_get_element(vars, A->ptr))) {
6183 +  if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
6184 +    fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n",
6185 +        ctx->current->context_ndx,
6186 +        ctx->current->key->ptr, A->ptr);
6187 +    ctx->ok = 0;
6188 +  } else if (NULL != (du = array_get_element(vars, A->ptr))) {
6189      /* exists in current block */
6190      du = configparser_merge_data(du, B);
6191      if (NULL == du) {
6192 @@ -190,6 +183,7 @@
6193        buffer_copy_string_buffer(du->key, A);
6194        array_replace(vars, du);
6195      }
6196 +    B->free(B);
6197    } else if (NULL != (du = configparser_get_variable(ctx, A))) {
6198      du = configparser_merge_data(du, B);
6199      if (NULL == du) {
6200 @@ -199,15 +193,13 @@
6201        buffer_copy_string_buffer(du->key, A);
6202        array_insert_unique(ctx->current->value, du);
6203      }
6204 +    B->free(B);
6205    } else {
6206 -    fprintf(stderr, "Undefined config variable in conditional %d %s: %s\n", 
6207 -            ctx->current->context_ndx,
6208 -            ctx->current->key->ptr, A->ptr);
6209 -    ctx->ok = 0;
6210 +    buffer_copy_string_buffer(B->key, A);
6211 +    array_insert_unique(ctx->current->value, B);
6212    }
6213    buffer_free(A);
6214    A = NULL;
6215 -  B->free(B);
6216    B = NULL;
6217  }
6218  
6219 @@ -239,7 +231,24 @@
6220  }
6221  
6222  value(A) ::= key(B). {
6223 -  A = configparser_get_variable(ctx, B);
6224 +  if (strncmp(B->ptr, "env.", sizeof("env.") - 1) == 0) {
6225 +    char *env;
6226 +
6227 +    if (NULL != (env = getenv(B->ptr + 4))) {
6228 +      data_string *ds;
6229 +      ds = data_string_init();
6230 +      buffer_append_string(ds->value, env);
6231 +      A = (data_unset *)ds;
6232 +    }
6233 +    else {
6234 +      A = NULL;
6235 +      fprintf(stderr, "Undefined env variable: %s\n", B->ptr + 4);
6236 +      ctx->ok = 0;
6237 +    }
6238 +  } else if (NULL == (A = configparser_get_variable(ctx, B))) {
6239 +    fprintf(stderr, "Undefined config variable: %s\n", B->ptr);
6240 +    ctx->ok = 0;
6241 +  }
6242    if (!A) {
6243      /* make a dummy so it won't crash */
6244      A = (data_unset *)data_string_init();
6245 @@ -267,6 +276,9 @@
6246    ((data_array *)(A))->value = B;
6247    B = NULL;
6248  }
6249 +array(A) ::= LPARAN RPARAN. {
6250 +  A = array_init();
6251 +}
6252  array(A) ::= LPARAN aelements(B) RPARAN. {
6253    A = B;
6254    B = NULL;
6255 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/connections-glue.c lighttpd-1.4.12/src/connections-glue.c
6256 --- lighttpd-1.4.11/src/connections-glue.c      2005-09-12 10:04:23.000000000 +0300
6257 +++ lighttpd-1.4.12/src/connections-glue.c      2006-07-11 21:23:39.000000000 +0300
6258 @@ -13,7 +13,7 @@
6259         case CON_STATE_REQUEST_END: return "req-end";
6260         case CON_STATE_RESPONSE_START: return "resp-start";
6261         case CON_STATE_RESPONSE_END: return "resp-end";
6262 -       default: return "(unknown)";    
6263 +       default: return "(unknown)";
6264         }
6265  }
6266  
6267 @@ -30,15 +30,15 @@
6268         case CON_STATE_REQUEST_END: return "Q";
6269         case CON_STATE_RESPONSE_START: return "s";
6270         case CON_STATE_RESPONSE_END: return "S";
6271 -       default: return "x";    
6272 +       default: return "x";
6273         }
6274  }
6275  
6276  int connection_set_state(server *srv, connection *con, connection_state_t state) {
6277         UNUSED(srv);
6278 -       
6279 +
6280         con->state = state;
6281 -       
6282 +
6283         return 0;
6284  }
6285  
6286 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/connections.c lighttpd-1.4.12/src/connections.c
6287 --- lighttpd-1.4.11/src/connections.c   2006-03-05 22:14:53.000000000 +0200
6288 +++ lighttpd-1.4.12/src/connections.c   2006-07-11 21:23:39.000000000 +0300
6289 @@ -2,7 +2,6 @@
6290  
6291  #include <stdlib.h>
6292  #include <stdio.h>
6293 -#include <unistd.h>
6294  #include <errno.h>
6295  #include <string.h>
6296  #include <fcntl.h>
6297 @@ -26,8 +25,8 @@
6298  #include "inet_ntop_cache.h"
6299  
6300  #ifdef USE_OPENSSL
6301 -# include <openssl/ssl.h> 
6302 -# include <openssl/err.h> 
6303 +# include <openssl/ssl.h>
6304 +# include <openssl/err.h>
6305  #endif
6306  
6307  #ifdef HAVE_SYS_FILIO_H
6308 @@ -35,6 +34,7 @@
6309  #endif
6310  
6311  #include "sys-socket.h"
6312 +#include "sys-files.h"
6313  
6314  typedef struct {
6315                 PLUGIN_DATA;
6316 @@ -43,7 +43,7 @@
6317  static connection *connections_get_new_connection(server *srv) {
6318         connections *conns = srv->conns;
6319         size_t i;
6320 -       
6321 +
6322         if (conns->size == 0) {
6323                 conns->size = 128;
6324                 conns->ptr = NULL;
6325 @@ -54,21 +54,21 @@
6326         } else if (conns->size == conns->used) {
6327                 conns->size += 128;
6328                 conns->ptr = realloc(conns->ptr, sizeof(*conns->ptr) * conns->size);
6329 -               
6330 +
6331                 for (i = conns->used; i < conns->size; i++) {
6332                         conns->ptr[i] = connection_init(srv);
6333                 }
6334         }
6335  
6336         connection_reset(srv, conns->ptr[conns->used]);
6337 -#if 0  
6338 +#if 0
6339         fprintf(stderr, "%s.%d: add: ", __FILE__, __LINE__);
6340         for (i = 0; i < conns->used + 1; i++) {
6341                 fprintf(stderr, "%d ", conns->ptr[i]->fd);
6342         }
6343         fprintf(stderr, "\n");
6344 -#endif 
6345 -       
6346 +#endif
6347 +
6348         conns->ptr[conns->used]->ndx = conns->used;
6349         return conns->ptr[conns->used++];
6350  }
6351 @@ -77,26 +77,26 @@
6352         size_t i;
6353         connections *conns = srv->conns;
6354         connection *temp;
6355 -       
6356 +
6357         if (con == NULL) return -1;
6358 -       
6359 +
6360         if (-1 == con->ndx) return -1;
6361 -       
6362 +
6363         i = con->ndx;
6364 -       
6365 +
6366         /* not last element */
6367 -       
6368 +
6369         if (i != conns->used - 1) {
6370                 temp = conns->ptr[i];
6371                 conns->ptr[i] = conns->ptr[conns->used - 1];
6372                 conns->ptr[conns->used - 1] = temp;
6373 -               
6374 +
6375                 conns->ptr[i]->ndx = i;
6376                 conns->ptr[conns->used - 1]->ndx = -1;
6377         }
6378 -       
6379 +
6380         conns->used--;
6381 -       
6382 +
6383         con->ndx = -1;
6384  #if 0
6385         fprintf(stderr, "%s.%d: del: (%d)", __FILE__, __LINE__, conns->used);
6386 @@ -104,25 +104,23 @@
6387                 fprintf(stderr, "%d ", conns->ptr[i]->fd);
6388         }
6389         fprintf(stderr, "\n");
6390 -#endif 
6391 +#endif
6392         return 0;
6393  }
6394  
6395  int connection_close(server *srv, connection *con) {
6396  #ifdef USE_OPENSSL
6397         server_socket *srv_sock = con->srv_socket;
6398 -#endif
6399 -       
6400 -#ifdef USE_OPENSSL
6401 +
6402         if (srv_sock->is_ssl) {
6403                 if (con->ssl) SSL_free(con->ssl);
6404                 con->ssl = NULL;
6405         }
6406  #endif
6407 -       
6408 +
6409         fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
6410         fdevent_unregister(srv->ev, con->fd);
6411 -#ifdef __WIN32
6412 +#ifdef _WIN32
6413         if (closesocket(con->fd)) {
6414                 log_error_write(srv, __FILE__, __LINE__, "sds",
6415                                 "(warning) close:", con->fd, strerror(errno));
6416 @@ -133,207 +131,96 @@
6417                                 "(warning) close:", con->fd, strerror(errno));
6418         }
6419  #endif
6420 -       
6421 +
6422         srv->cur_fds--;
6423  #if 0
6424         log_error_write(srv, __FILE__, __LINE__, "sd",
6425                         "closed()", con->fd);
6426  #endif
6427 -       
6428 +
6429         connection_del(srv, con);
6430         connection_set_state(srv, con, CON_STATE_CONNECT);
6431 -       
6432 +
6433         return 0;
6434  }
6435  
6436  #if 0
6437  static void dump_packet(const unsigned char *data, size_t len) {
6438         size_t i, j;
6439 -       
6440 +
6441         if (len == 0) return;
6442 -       
6443 +
6444         for (i = 0; i < len; i++) {
6445                 if (i % 16 == 0) fprintf(stderr, "  ");
6446 -               
6447 +
6448                 fprintf(stderr, "%02x ", data[i]);
6449 -               
6450 +
6451                 if ((i + 1) % 16 == 0) {
6452                         fprintf(stderr, "  ");
6453                         for (j = 0; j <= i % 16; j++) {
6454                                 unsigned char c;
6455 -                               
6456 +
6457                                 if (i-15+j >= len) break;
6458 -                               
6459 +
6460                                 c = data[i-15+j];
6461 -                               
6462 +
6463                                 fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
6464                         }
6465 -                       
6466 +
6467                         fprintf(stderr, "\n");
6468                 }
6469         }
6470 -       
6471 +
6472         if (len % 16 != 0) {
6473                 for (j = i % 16; j < 16; j++) {
6474                         fprintf(stderr, "   ");
6475                 }
6476 -               
6477 +
6478                 fprintf(stderr, "  ");
6479                 for (j = i & ~0xf; j < len; j++) {
6480                         unsigned char c;
6481 -                       
6482 +
6483                         c = data[j];
6484                         fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
6485                 }
6486                 fprintf(stderr, "\n");
6487         }
6488  }
6489 -#endif 
6490 -
6491 -static int connection_handle_read(server *srv, connection *con) {
6492 -       int len;
6493 -       buffer *b;
6494 -       int toread;
6495 -#ifdef USE_OPENSSL
6496 -       server_socket *srv_sock = con->srv_socket;
6497  #endif
6498  
6499 -       b = chunkqueue_get_append_buffer(con->read_queue);
6500 -       buffer_prepare_copy(b, 4096);
6501 +static network_status_t connection_handle_read(server *srv, connection *con) {
6502 +       off_t oldlen, newlen;
6503  
6504 -#ifdef USE_OPENSSL
6505 -       if (srv_sock->is_ssl) {
6506 -               len = SSL_read(con->ssl, b->ptr, b->size - 1);
6507 -       } else {
6508 -               if (ioctl(con->fd, FIONREAD, &toread)) {
6509 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
6510 -                                       "unexpected end-of-file:",
6511 -                                       con->fd);
6512 -                       return -1;
6513 -               }
6514 -               buffer_prepare_copy(b, toread);
6515 +    oldlen = chunkqueue_length(con->read_queue);
6516  
6517 -               len = read(con->fd, b->ptr, b->size - 1);
6518 -       }
6519 -#elif defined(__WIN32)
6520 -       len = recv(con->fd, b->ptr, b->size - 1, 0);
6521 -#else
6522 -       if (ioctl(con->fd, FIONREAD, &toread)) {
6523 -               log_error_write(srv, __FILE__, __LINE__, "sd", 
6524 -                               "unexpected end-of-file:",
6525 -                               con->fd);
6526 -               return -1;
6527 -       }
6528 -       buffer_prepare_copy(b, toread);
6529 -
6530 -       len = read(con->fd, b->ptr, b->size - 1);
6531 -#endif
6532 -       
6533 -       if (len < 0) {
6534 -               con->is_readable = 0;
6535 -               
6536 -#ifdef USE_OPENSSL
6537 -               if (srv_sock->is_ssl) {
6538 -                       int r, ssl_err;
6539 -                       
6540 -                       switch ((r = SSL_get_error(con->ssl, len))) {
6541 -                       case SSL_ERROR_WANT_READ:
6542 -                               return 0;
6543 -                       case SSL_ERROR_SYSCALL:
6544 -                               /**
6545 -                                * man SSL_get_error()
6546 -                                * 
6547 -                                * SSL_ERROR_SYSCALL
6548 -                                *   Some I/O error occurred.  The OpenSSL error queue may contain more 
6549 -                                *   information on the error.  If the error queue is empty (i.e.
6550 -                                *   ERR_get_error() returns 0), ret can be used to find out more about 
6551 -                                *   the error: If ret == 0, an EOF was observed that violates the
6552 -                                *   protocol.  If ret == -1, the underlying BIO reported an I/O error 
6553 -                                *   (for socket I/O on Unix systems, consult errno for details).
6554 -                                *
6555 -                                */
6556 -                               while((ssl_err = ERR_get_error())) {
6557 -                                       /* get all errors from the error-queue */
6558 -                                       log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:", 
6559 -                                                       r, ERR_error_string(ssl_err, NULL));
6560 -                               }
6561 +    switch(network_read_chunkqueue(srv, con, con->read_queue)) {
6562 +    case NETWORK_STATUS_SUCCESS:
6563 +        break;
6564 +    case NETWORK_STATUS_WAIT_FOR_EVENT:
6565 +        con->is_readable = 0;
6566 +        return NETWORK_STATUS_WAIT_FOR_EVENT;
6567 +    case NETWORK_STATUS_INTERRUPTED:
6568 +        con->is_readable = 1;
6569 +        return NETWORK_STATUS_WAIT_FOR_EVENT;
6570 +    case NETWORK_STATUS_CONNECTION_CLOSE:
6571 +        /* pipelining */
6572 +        con->is_readable = 0;
6573 +        return NETWORK_STATUS_CONNECTION_CLOSE;
6574 +    case NETWORK_STATUS_FATAL_ERROR:
6575 +        con->is_readable = 0;
6576 +
6577 +        connection_set_state(srv, con, CON_STATE_ERROR);
6578 +        return NETWORK_STATUS_FATAL_ERROR;
6579 +    default:
6580 +        SEGFAULT();
6581 +        break;
6582 +    }
6583  
6584 -                               switch(errno) {
6585 -                               default:
6586 -                                       log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:", 
6587 -                                                       len, r, errno,
6588 -                                                       strerror(errno));
6589 -                                       break;
6590 -                               }
6591 -                               
6592 -                               break;
6593 -                       case SSL_ERROR_ZERO_RETURN:
6594 -                               /* clean shutdown on the remote side */
6595 -                               
6596 -                               if (r == 0) {
6597 -                                       /* FIXME: later */
6598 -                               }
6599 -                               
6600 -                               /* fall thourgh */
6601 -                       default:
6602 -                               while((ssl_err = ERR_get_error())) {
6603 -                                       /* get all errors from the error-queue */
6604 -                                       log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:", 
6605 -                                                       r, ERR_error_string(ssl_err, NULL));
6606 -                               }
6607 -                               break;
6608 -                       }
6609 -               } else {
6610 -                       if (errno == EAGAIN) return 0;
6611 -                       if (errno == EINTR) {
6612 -                               /* we have been interrupted before we could read */
6613 -                               con->is_readable = 1;
6614 -                               return 0;
6615 -                       }
6616 -               
6617 -                       if (errno != ECONNRESET) {
6618 -                               /* expected for keep-alive */
6619 -                               log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
6620 -                       }
6621 -               }
6622 -#else
6623 -               if (errno == EAGAIN) return 0;
6624 -               if (errno == EINTR) {
6625 -                       /* we have been interrupted before we could read */
6626 -                       con->is_readable = 1;
6627 -                       return 0;
6628 -               }
6629 -               
6630 -               if (errno != ECONNRESET) {
6631 -                       /* expected for keep-alive */
6632 -                       log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
6633 -               }
6634 -#endif
6635 -               connection_set_state(srv, con, CON_STATE_ERROR);
6636 -               
6637 -               return -1;
6638 -       } else if (len == 0) {
6639 -               con->is_readable = 0;
6640 -               /* the other end close the connection -> KEEP-ALIVE */
6641 -
6642 -               /* pipelining */
6643 -
6644 -               return -2;
6645 -       } else if ((size_t)len < b->size - 1) {
6646 -               /* we got less then expected, wait for the next fd-event */
6647 -               
6648 -               con->is_readable = 0;
6649 -       }
6650 -       
6651 -       b->used = len;
6652 -       b->ptr[b->used++] = '\0';
6653 -       
6654 -       con->bytes_read += len;
6655 -#if 0
6656 -       dump_packet(b->ptr, len);
6657 -#endif
6658 -       
6659 -       return 0;
6660 +    newlen = chunkqueue_length(con->read_queue);
6661 +
6662 +       con->bytes_read += (newlen - oldlen);
6663 +
6664 +       return NETWORK_STATUS_SUCCESS;
6665  }
6666  
6667  static int connection_handle_write_prepare(server *srv, connection *con) {
6668 @@ -343,6 +230,7 @@
6669                 case HTTP_METHOD_GET:
6670                 case HTTP_METHOD_POST:
6671                 case HTTP_METHOD_HEAD:
6672 +                       /* webdav */
6673                 case HTTP_METHOD_PUT:
6674                 case HTTP_METHOD_MKCOL:
6675                 case HTTP_METHOD_DELETE:
6676 @@ -350,12 +238,14 @@
6677                 case HTTP_METHOD_MOVE:
6678                 case HTTP_METHOD_PROPFIND:
6679                 case HTTP_METHOD_PROPPATCH:
6680 +               case HTTP_METHOD_LOCK:
6681 +               case HTTP_METHOD_UNLOCK:
6682                         break;
6683                 case HTTP_METHOD_OPTIONS:
6684                         /*
6685                          * 400 is coming from the request-parser BEFORE uri.path is set
6686 -                        * 403 is from the response handler when noone else catched it 
6687 -                        * 
6688 +                        * 403 is from the response handler when noone else catched it
6689 +                        *
6690                          * */
6691                         if (con->uri.path->used &&
6692                             con->uri.path->ptr[0] != '*') {
6693 @@ -381,55 +271,58 @@
6694                         break;
6695                 }
6696         }
6697 -       
6698 +
6699         if (con->http_status == 0) {
6700                 con->http_status = 403;
6701         }
6702 -       
6703 +
6704         switch(con->http_status) {
6705         case 400: /* class: header + custom body */
6706         case 401:
6707         case 403:
6708         case 404:
6709         case 408:
6710 +       case 409:
6711 +       case 410:
6712         case 411:
6713         case 416:
6714         case 423:
6715         case 500:
6716         case 501:
6717         case 503:
6718 -       case 505: 
6719 +       case 505:
6720 +       case 509:
6721                 if (con->mode != DIRECT) break;
6722 -               
6723 +
6724                 con->file_finished = 0;
6725 -               
6726 +
6727                 buffer_reset(con->physical.path);
6728 -                               
6729 +
6730                 /* try to send static errorfile */
6731                 if (!buffer_is_empty(con->conf.errorfile_prefix)) {
6732                         stat_cache_entry *sce = NULL;
6733 -                       
6734 +
6735                         buffer_copy_string_buffer(con->physical.path, con->conf.errorfile_prefix);
6736                         buffer_append_string(con->physical.path, get_http_status_body_name(con->http_status));
6737 -                       
6738 +
6739                         if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
6740                                 con->file_finished = 1;
6741 -                               
6742 +
6743                                 http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
6744                                 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
6745                         }
6746                 }
6747 -               
6748 -               if (!con->file_finished) {                      
6749 +
6750 +               if (!con->file_finished) {
6751                         buffer *b;
6752 -                       
6753 +
6754                         buffer_reset(con->physical.path);
6755 -                       
6756 +
6757                         con->file_finished = 1;
6758                         b = chunkqueue_get_append_buffer(con->write_queue);
6759 -                               
6760 +
6761                         /* build default error-page */
6762 -                       buffer_copy_string(b, 
6763 +                       buffer_copy_string(b,
6764                                            "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
6765                                            "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
6766                                            "         \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
6767 @@ -439,7 +332,7 @@
6768                         buffer_append_long(b, con->http_status);
6769                         buffer_append_string(b, " - ");
6770                         buffer_append_string(b, get_http_status_name(con->http_status));
6771 -                       
6772 +
6773                         buffer_append_string(b,
6774                                              "</title>\n"
6775                                              " </head>\n"
6776 @@ -448,12 +341,12 @@
6777                         buffer_append_long(b, con->http_status);
6778                         buffer_append_string(b, " - ");
6779                         buffer_append_string(b, get_http_status_name(con->http_status));
6780 -                       
6781 -                       buffer_append_string(b,"</h1>\n" 
6782 +
6783 +                       buffer_append_string(b,"</h1>\n"
6784                                              " </body>\n"
6785                                              "</html>\n"
6786                                              );
6787 -                       
6788 +
6789                         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
6790                 }
6791                 /* fall through */
6792 @@ -463,10 +356,10 @@
6793         case 301:
6794         case 302:
6795                 break;
6796 -               
6797 +
6798         case 206: /* write_queue is already prepared */
6799                 con->file_finished = 1;
6800 -               
6801 +
6802                 break;
6803         case 205: /* class: header only */
6804         case 304:
6805 @@ -474,19 +367,19 @@
6806                 /* disable chunked encoding again as we have no body */
6807                 con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
6808                 chunkqueue_reset(con->write_queue);
6809 -               
6810 +
6811                 con->file_finished = 1;
6812                 break;
6813         }
6814 -       
6815 +
6816  
6817         if (con->file_finished) {
6818 -               /* we have all the content and chunked encoding is not used, set a content-length */ 
6819 -               
6820 -               if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) && 
6821 +               /* we have all the content and chunked encoding is not used, set a content-length */
6822 +
6823 +               if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) &&
6824                     (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) {
6825                         buffer_copy_off_t(srv->tmp_buf, chunkqueue_length(con->write_queue));
6826 -               
6827 +
6828                         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf));
6829                 }
6830         } else {
6831 @@ -495,74 +388,77 @@
6832                     ((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0)) {
6833                         con->keep_alive = 0;
6834                 }
6835 -               
6836 +
6837                 if (0 == (con->parsed_response & HTTP_CONNECTION)) {
6838                         /* (f)cgi did'nt send Connection: header
6839 -                        *                          
6840 +                        *
6841                          * shall we ?
6842                          */
6843                         if (((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) &&
6844                             (con->parsed_response & HTTP_CONTENT_LENGTH) == 0) {
6845                                 /* without content_length, no keep-alive */
6846 -                               
6847 +
6848                                 con->keep_alive = 0;
6849                         }
6850                 } else {
6851                         /* a subrequest disable keep-alive although the client wanted it */
6852                         if (con->keep_alive && !con->response.keep_alive) {
6853                                 con->keep_alive = 0;
6854 -                               
6855 +
6856                                 /* FIXME: we have to drop the Connection: Header from the subrequest */
6857                         }
6858                 }
6859         }
6860 -       
6861 +
6862         if (con->request.http_method == HTTP_METHOD_HEAD) {
6863                 chunkqueue_reset(con->write_queue);
6864         }
6865  
6866         http_response_write_header(srv, con);
6867 -               
6868 +
6869         return 0;
6870  }
6871  
6872  static int connection_handle_write(server *srv, connection *con) {
6873 -       switch(network_write_chunkqueue(srv, con, con->write_queue)) {
6874 -       case 0:
6875 +    switch(network_write_chunkqueue(srv, con, con->write_queue)) {
6876 +       case NETWORK_STATUS_SUCCESS:
6877                 if (con->file_finished) {
6878                         connection_set_state(srv, con, CON_STATE_RESPONSE_END);
6879                         joblist_append(srv, con);
6880                 }
6881                 break;
6882 -       case -1: /* error on our side */
6883 +       case NETWORK_STATUS_FATAL_ERROR: /* error on our side */
6884                 log_error_write(srv, __FILE__, __LINE__, "sd",
6885                                 "connection closed: write failed on fd", con->fd);
6886                 connection_set_state(srv, con, CON_STATE_ERROR);
6887                 joblist_append(srv, con);
6888                 break;
6889 -       case -2: /* remote close */
6890 +       case NETWORK_STATUS_CONNECTION_CLOSE: /* remote close */
6891                 connection_set_state(srv, con, CON_STATE_ERROR);
6892                 joblist_append(srv, con);
6893                 break;
6894 -       case 1:
6895 +       case NETWORK_STATUS_WAIT_FOR_EVENT:
6896                 con->is_writable = 0;
6897 -               
6898 +
6899                 /* not finished yet -> WRITE */
6900                 break;
6901 +       case NETWORK_STATUS_INTERRUPTED:
6902 +               con->is_writable = 1;
6903 +               break;
6904 +       case NETWORK_STATUS_UNSET:
6905 +               break;
6906         }
6907 -       
6908 +
6909         return 0;
6910  }
6911  
6912 -
6913 -
6914  connection *connection_init(server *srv) {
6915         connection *con;
6916 -       
6917 +
6918         UNUSED(srv);
6919  
6920         con = calloc(1, sizeof(*con));
6921 -               
6922 +
6923         con->fd = 0;
6924         con->ndx = -1;
6925         con->fde_ndx = -1;
6926 @@ -573,32 +469,32 @@
6927  
6928  #define CLEAN(x) \
6929         con->x = buffer_init();
6930 -       
6931 +
6932         CLEAN(request.uri);
6933         CLEAN(request.request_line);
6934         CLEAN(request.request);
6935         CLEAN(request.pathinfo);
6936 -       
6937 +
6938         CLEAN(request.orig_uri);
6939 -       
6940 +
6941         CLEAN(uri.scheme);
6942         CLEAN(uri.authority);
6943         CLEAN(uri.path);
6944         CLEAN(uri.path_raw);
6945         CLEAN(uri.query);
6946 -       
6947 +
6948         CLEAN(physical.doc_root);
6949         CLEAN(physical.path);
6950         CLEAN(physical.basedir);
6951         CLEAN(physical.rel_path);
6952         CLEAN(physical.etag);
6953         CLEAN(parse_request);
6954 -       
6955 +
6956         CLEAN(authed_user);
6957         CLEAN(server_name);
6958         CLEAN(error_handler);
6959         CLEAN(dst_addr_buf);
6960 -       
6961 +
6962  #undef CLEAN
6963         con->write_queue = chunkqueue_init();
6964         con->read_queue = chunkqueue_init();
6965 @@ -608,26 +504,26 @@
6966         con->request.headers      = array_init();
6967         con->response.headers     = array_init();
6968         con->environment     = array_init();
6969 -       
6970 +
6971         /* init plugin specific connection structures */
6972 -       
6973 +
6974         con->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *));
6975 -       
6976 +
6977         con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t));
6978         config_setup_connection(srv, con);
6979 -       
6980 +
6981         return con;
6982  }
6983  
6984  void connections_free(server *srv) {
6985         connections *conns = srv->conns;
6986 -       size_t i;       
6987 -       
6988 +       size_t i;
6989 +
6990         for (i = 0; i < conns->size; i++) {
6991                 connection *con = conns->ptr[i];
6992 -               
6993 +
6994                 connection_reset(srv, con);
6995 -               
6996 +
6997                 chunkqueue_free(con->write_queue);
6998                 chunkqueue_free(con->read_queue);
6999                 chunkqueue_free(con->request_content_queue);
7000 @@ -637,27 +533,27 @@
7001  
7002  #define CLEAN(x) \
7003         buffer_free(con->x);
7004 -               
7005 +
7006                 CLEAN(request.uri);
7007                 CLEAN(request.request_line);
7008                 CLEAN(request.request);
7009                 CLEAN(request.pathinfo);
7010 -               
7011 +
7012                 CLEAN(request.orig_uri);
7013 -               
7014 +
7015                 CLEAN(uri.scheme);
7016                 CLEAN(uri.authority);
7017                 CLEAN(uri.path);
7018                 CLEAN(uri.path_raw);
7019                 CLEAN(uri.query);
7020 -               
7021 +
7022                 CLEAN(physical.doc_root);
7023                 CLEAN(physical.path);
7024                 CLEAN(physical.basedir);
7025                 CLEAN(physical.etag);
7026                 CLEAN(physical.rel_path);
7027                 CLEAN(parse_request);
7028 -               
7029 +
7030                 CLEAN(authed_user);
7031                 CLEAN(server_name);
7032                 CLEAN(error_handler);
7033 @@ -665,97 +561,97 @@
7034  #undef CLEAN
7035                 free(con->plugin_ctx);
7036                 free(con->cond_cache);
7037 -               
7038 +
7039                 free(con);
7040         }
7041 -       
7042 +
7043         free(conns->ptr);
7044  }
7045  
7046  
7047  int connection_reset(server *srv, connection *con) {
7048         size_t i;
7049 -       
7050 +
7051         plugins_call_connection_reset(srv, con);
7052 -       
7053 +
7054         con->is_readable = 1;
7055         con->is_writable = 1;
7056         con->http_status = 0;
7057         con->file_finished = 0;
7058         con->file_started = 0;
7059         con->got_response = 0;
7060 -       
7061 +
7062         con->parsed_response = 0;
7063 -       
7064 +
7065         con->bytes_written = 0;
7066         con->bytes_written_cur_second = 0;
7067         con->bytes_read = 0;
7068         con->bytes_header = 0;
7069         con->loops_per_request = 0;
7070 -       
7071 +
7072         con->request.http_method = HTTP_METHOD_UNSET;
7073         con->request.http_version = HTTP_VERSION_UNSET;
7074 -       
7075 +
7076         con->request.http_if_modified_since = NULL;
7077         con->request.http_if_none_match = NULL;
7078 -       
7079 +
7080         con->response.keep_alive = 0;
7081         con->response.content_length = -1;
7082         con->response.transfer_encoding = 0;
7083 -       
7084 +
7085         con->mode = DIRECT;
7086 -       
7087 +
7088  #define CLEAN(x) \
7089         if (con->x) buffer_reset(con->x);
7090 -       
7091 +
7092         CLEAN(request.uri);
7093         CLEAN(request.request_line);
7094         CLEAN(request.pathinfo);
7095         CLEAN(request.request);
7096 -       
7097 +
7098         CLEAN(request.orig_uri);
7099 -       
7100 +
7101         CLEAN(uri.scheme);
7102         CLEAN(uri.authority);
7103         CLEAN(uri.path);
7104         CLEAN(uri.path_raw);
7105         CLEAN(uri.query);
7106 -       
7107 +
7108         CLEAN(physical.doc_root);
7109         CLEAN(physical.path);
7110         CLEAN(physical.basedir);
7111         CLEAN(physical.rel_path);
7112         CLEAN(physical.etag);
7113 -       
7114 +
7115         CLEAN(parse_request);
7116 -       
7117 +
7118         CLEAN(authed_user);
7119         CLEAN(server_name);
7120         CLEAN(error_handler);
7121 -#undef CLEAN   
7122 -       
7123 +#undef CLEAN
7124 +
7125  #define CLEAN(x) \
7126 -       if (con->x) con->x->used = 0;   
7127 -       
7128 +       if (con->x) con->x->used = 0;
7129 +
7130  #undef CLEAN
7131 -       
7132 +
7133  #define CLEAN(x) \
7134                 con->request.x = NULL;
7135 -       
7136 +
7137         CLEAN(http_host);
7138         CLEAN(http_range);
7139         CLEAN(http_content_type);
7140  #undef CLEAN
7141         con->request.content_length = 0;
7142 -       
7143 +
7144         array_reset(con->request.headers);
7145         array_reset(con->response.headers);
7146         array_reset(con->environment);
7147 -       
7148 +
7149         chunkqueue_reset(con->write_queue);
7150         chunkqueue_reset(con->request_content_queue);
7151  
7152 -       /* the plugins should cleanup themself */       
7153 +       /* the plugins should cleanup themself */
7154         for (i = 0; i < srv->plugins.used; i++) {
7155                 plugin *p = ((plugin **)(srv->plugins.ptr))[i];
7156                 plugin_data *pd = p->data;
7157 @@ -768,7 +664,7 @@
7158  
7159                 con->plugin_ctx[pd->id] = NULL;
7160         }
7161 -       
7162 +
7163  #if COND_RESULT_UNSET
7164         for (i = srv->config_context->used - 1; i >= 0; i --) {
7165                 con->cond_cache[i].result = COND_RESULT_UNSET;
7166 @@ -777,56 +673,56 @@
7167  #else
7168         memset(con->cond_cache, 0, sizeof(cond_cache_t) * srv->config_context->used);
7169  #endif
7170 -       
7171 +
7172         con->header_len = 0;
7173         con->in_error_handler = 0;
7174 -       
7175 +
7176         config_setup_connection(srv, con);
7177 -       
7178 +
7179         return 0;
7180  }
7181  
7182  /**
7183 - * 
7184 - * search for \r\n\r\n 
7185 - * 
7186 + *
7187 + * search for \r\n\r\n
7188 + *
7189   * this is a special 32bit version which is using a sliding window for
7190 - * the comparisions 
7191 - * 
7192 + * the comparisions
7193 + *
7194   * how it works:
7195 - * 
7196 + *
7197   * b:      'abcdefg'
7198   * rnrn:   'cdef'
7199 - * 
7200 + *
7201   * cmpbuf: abcd != cdef
7202   * cmpbuf: bcde != cdef
7203   * cmpbuf: cdef == cdef -> return &c
7204 - * 
7205 - * cmpbuf and rnrn are treated as 32bit uint and bit-ops are used to 
7206 + *
7207 + * cmpbuf and rnrn are treated as 32bit uint and bit-ops are used to
7208   * maintain cmpbuf and rnrn
7209 - * 
7210 + *
7211   */
7212  
7213  char *buffer_search_rnrn(buffer *b) {
7214         uint32_t cmpbuf, rnrn;
7215         char *cp;
7216         size_t i;
7217 -       
7218 +
7219         if (b->used < 4) return NULL;
7220 -       
7221 +
7222         rnrn = ('\r' << 24) | ('\n' << 16) |
7223                 ('\r' << 8) | ('\n' << 0);
7224 -       
7225 +
7226         cmpbuf = (b->ptr[0] << 24) | (b->ptr[1] << 16) |
7227                 (b->ptr[2] << 8) | (b->ptr[3] << 0);
7228 -               
7229 +
7230         cp = b->ptr + 4;
7231         for (i = 0; i < b->used - 4; i++) {
7232                 if (cmpbuf == rnrn) return cp - 4;
7233 -                       
7234 +
7235                 cmpbuf = (cmpbuf << 8 | *(cp++)) & 0xffffffff;
7236         }
7237 -       
7238 +
7239         return NULL;
7240  }
7241  /**
7242 @@ -840,22 +736,25 @@
7243         chunk *c;
7244         chunkqueue *cq = con->read_queue;
7245         chunkqueue *dst_cq = con->request_content_queue;
7246 -       
7247 +
7248         if (con->is_readable) {
7249                 con->read_idle_ts = srv->cur_ts;
7250 -       
7251 +
7252                 switch(connection_handle_read(srv, con)) {
7253 -               case -1:
7254 +               case NETWORK_STATUS_FATAL_ERROR:
7255                         return -1;
7256 -               case -2:
7257 +               case NETWORK_STATUS_CONNECTION_CLOSE:
7258                         /* remote side closed the connection
7259                          * if we still have content, handle it, if not leave here */
7260  
7261                         if (cq->first == cq->last &&
7262 -                           cq->first->mem->used == 0) {
7263 +                (NULL == cq->first ||
7264 +                           cq->first->mem->used == 0)) {
7265  
7266                                 /* conn-closed, leave here */
7267                                 connection_set_state(srv, con, CON_STATE_ERROR);
7268 +
7269 +                return 0;
7270                         }
7271                 default:
7272                         break;
7273 @@ -891,14 +790,14 @@
7274                         /* the last node was empty */
7275                         if (c->next == NULL) {
7276                                 cq->last = c;
7277 -                       } 
7278 +                       }
7279  
7280                         c = c->next;
7281                 } else {
7282                         c = c->next;
7283                 }
7284         }
7285 -       
7286 +
7287         /* nothing to handle */
7288         if (cq->first == NULL) return 0;
7289  
7290 @@ -906,25 +805,26 @@
7291         case CON_STATE_READ:
7292                 /* prepare con->request.request */
7293                 c = cq->first;
7294 -               
7295 +
7296                 /* check if we need the full package */
7297                 if (con->request.request->used == 0) {
7298                         buffer b;
7299 -                       
7300 +
7301                         b.ptr = c->mem->ptr + c->offset;
7302                         b.used = c->mem->used - c->offset;
7303 -                       
7304 +
7305                         if (NULL != (h_term = buffer_search_rnrn(&b))) {
7306                                 /* \r\n\r\n found
7307                                  * - copy everything incl. the terminator to request.request
7308                                  */
7309 -                               
7310 -                               buffer_copy_string_len(con->request.request, 
7311 -                                                      b.ptr, 
7312 +
7313 +                               buffer_copy_string_len(con->request.request,
7314 +                                                      b.ptr,
7315                                                        h_term - b.ptr + 4);
7316 -                               
7317 +
7318                                 /* the buffer has been read up to the terminator */
7319                                 c->offset += h_term - b.ptr + 4;
7320 +
7321                         } else {
7322                                 /* not found, copy everything */
7323                                 buffer_copy_string_len(con->request.request, c->mem->ptr + c->offset, c->mem->used - c->offset - 1);
7324 @@ -932,14 +832,14 @@
7325                         }
7326                 } else {
7327                         /* have to take care of overlapping header terminators */
7328 -                       
7329 +
7330                         size_t l = con->request.request->used - 2;
7331                         char *s  = con->request.request->ptr;
7332                         buffer b;
7333 -                       
7334 +
7335                         b.ptr = c->mem->ptr + c->offset;
7336                         b.used = c->mem->used - c->offset;
7337 -                       
7338 +
7339                         if (con->request.request->used - 1 > 3 &&
7340                             c->mem->used > 1 &&
7341                             s[l-2] == '\r' &&
7342 @@ -948,7 +848,7 @@
7343                             c->mem->ptr[0] == '\n') {
7344                                 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 1);
7345                                 c->offset += 1;
7346 -                               
7347 +
7348                                 h_term = con->request.request->ptr;
7349                         } else if (con->request.request->used - 1 > 2 &&
7350                                    c->mem->used > 2 &&
7351 @@ -958,7 +858,7 @@
7352                                    c->mem->ptr[1] == '\n') {
7353                                 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 2);
7354                                 c->offset += 2;
7355 -                               
7356 +
7357                                 h_term = con->request.request->ptr;
7358                         } else if (con->request.request->used - 1 > 1 &&
7359                                    c->mem->used > 3 &&
7360 @@ -968,17 +868,17 @@
7361                                    c->mem->ptr[2] == '\n') {
7362                                 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 3);
7363                                 c->offset += 3;
7364 -                               
7365 +
7366                                 h_term = con->request.request->ptr;
7367                         } else if (NULL != (h_term = buffer_search_string_len(&b, "\r\n\r\n", 4))) {
7368                                 /* \r\n\r\n found
7369                                  * - copy everything incl. the terminator to request.request
7370                                  */
7371 -                               
7372 -                               buffer_append_string_len(con->request.request, 
7373 -                                                      c->mem->ptr + c->offset, 
7374 +
7375 +                               buffer_append_string_len(con->request.request,
7376 +                                                      c->mem->ptr + c->offset,
7377                                                        c->offset + h_term - b.ptr + 4);
7378 -                               
7379 +
7380                                 /* the buffer has been read up to the terminator */
7381                                 c->offset += h_term - b.ptr + 4;
7382                         } else {
7383 @@ -999,16 +899,16 @@
7384                         connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7385                 }
7386                 break;
7387 -       case CON_STATE_READ_POST: 
7388 +       case CON_STATE_READ_POST:
7389                 for (c = cq->first; c && (dst_cq->bytes_in != (off_t)con->request.content_length); c = c->next) {
7390                         off_t weWant, weHave, toRead;
7391 -                       
7392 +
7393                         weWant = con->request.content_length - dst_cq->bytes_in;
7394 -                       
7395 +
7396                         assert(c->mem->used);
7397 -                       
7398 +
7399                         weHave = c->mem->used - c->offset - 1;
7400 -                               
7401 +
7402                         toRead = weHave > weWant ? weWant : weHave;
7403  
7404                         /* the new way, copy everything into a chunkqueue whcih might use tempfiles */
7405 @@ -1017,13 +917,13 @@
7406                                 /* copy everything to max 1Mb sized tempfiles */
7407  
7408                                 /*
7409 -                                * if the last chunk is 
7410 +                                * if the last chunk is
7411                                  * - smaller than 1Mb (size < 1Mb)
7412                                  * - not read yet (offset == 0)
7413                                  * -> append to it
7414                                  * otherwise
7415 -                                * -> create a new chunk 
7416 -                                * 
7417 +                                * -> create a new chunk
7418 +                                *
7419                                  * */
7420  
7421                                 if (dst_cq->last &&
7422 @@ -1056,14 +956,14 @@
7423                                 /* we have a chunk, let's write to it */
7424  
7425                                 if (dst_c->file.fd == -1) {
7426 -                                       /* we don't have file to write to, 
7427 +                                       /* we don't have file to write to,
7428                                          * EACCES might be one reason.
7429                                          *
7430                                          * Instead of sending 500 we send 413 and say the request is too large
7431                                          *  */
7432  
7433                                         log_error_write(srv, __FILE__, __LINE__, "sbs",
7434 -                                                       "denying upload as opening to temp-file for upload failed:", 
7435 +                                                       "denying upload as opening to temp-file for upload failed:",
7436                                                         dst_c->file.name, strerror(errno));
7437  
7438                                         con->http_status = 413; /* Request-Entity too large */
7439 @@ -1074,15 +974,15 @@
7440                                 }
7441  
7442                                 if (toRead != write(dst_c->file.fd, c->mem->ptr + c->offset, toRead)) {
7443 -                                       /* write failed for some reason ... disk full ? */ 
7444 +                                       /* write failed for some reason ... disk full ? */
7445                                         log_error_write(srv, __FILE__, __LINE__, "sbs",
7446 -                                                       "denying upload as writing to file failed:", 
7447 +                                                       "denying upload as writing to file failed:",
7448                                                         dst_c->file.name, strerror(errno));
7449 -                                       
7450 +
7451                                         con->http_status = 413; /* Request-Entity too large */
7452                                         con->keep_alive = 0;
7453                                         connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7454 -                               
7455 +
7456                                         close(dst_c->file.fd);
7457                                         dst_c->file.fd = -1;
7458  
7459 @@ -1090,7 +990,7 @@
7460                                 }
7461  
7462                                 dst_c->file.length += toRead;
7463 -                                       
7464 +
7465                                 if (dst_cq->bytes_in + toRead == (off_t)con->request.content_length) {
7466                                         /* we read everything, close the chunk */
7467                                         close(dst_c->file.fd);
7468 @@ -1102,7 +1002,7 @@
7469                                 b = chunkqueue_get_append_buffer(dst_cq);
7470                                 buffer_copy_string_len(b, c->mem->ptr + c->offset, toRead);
7471                         }
7472 -                       
7473 +
7474                         c->offset += toRead;
7475                         dst_cq->bytes_in += toRead;
7476                 }
7477 @@ -1111,7 +1011,7 @@
7478                 if (dst_cq->bytes_in == (off_t)con->request.content_length) {
7479                         connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7480                 }
7481 -                       
7482 +
7483                 break;
7484         }
7485  
7486 @@ -1123,9 +1023,9 @@
7487  handler_t connection_handle_fdevent(void *s, void *context, int revents) {
7488         server     *srv = (server *)s;
7489         connection *con = context;
7490 -       
7491 +
7492         joblist_append(srv, con);
7493 -       
7494 +
7495         if (revents & FDEVENT_IN) {
7496                 con->is_readable = 1;
7497  #if 0
7498 @@ -1136,19 +1036,19 @@
7499                 con->is_writable = 1;
7500                 /* we don't need the event twice */
7501         }
7502 -       
7503 -       
7504 +
7505 +
7506         if (revents & ~(FDEVENT_IN | FDEVENT_OUT)) {
7507                 /* looks like an error */
7508 -                                               
7509 +
7510                 /* FIXME: revents = 0x19 still means that we should read from the queue */
7511                 if (revents & FDEVENT_HUP) {
7512                         if (con->state == CON_STATE_CLOSE) {
7513                                 con->close_timeout_ts = 0;
7514                         } else {
7515                                 /* sigio reports the wrong event here
7516 -                                * 
7517 -                                * there was no HUP at all 
7518 +                                *
7519 +                                * there was no HUP at all
7520                                  */
7521  #ifdef USE_LINUX_SIGIO
7522                                 if (srv->ev->in_sigio == 1) {
7523 @@ -1160,32 +1060,39 @@
7524  #else
7525                                 connection_set_state(srv, con, CON_STATE_ERROR);
7526  #endif
7527 -                               
7528 +
7529                         }
7530                 } else if (revents & FDEVENT_ERR) {
7531  #ifndef USE_LINUX_SIGIO
7532                         log_error_write(srv, __FILE__, __LINE__, "sd",
7533                                         "connection closed: poll() -> ERR", con->fd);
7534 -#endif 
7535 +#endif
7536                         connection_set_state(srv, con, CON_STATE_ERROR);
7537                 } else {
7538                         log_error_write(srv, __FILE__, __LINE__, "sd",
7539                                         "connection closed: poll() -> ???", revents);
7540 -               } 
7541 +               }
7542         }
7543 -       
7544 +
7545         if (con->state == CON_STATE_READ ||
7546             con->state == CON_STATE_READ_POST) {
7547                 connection_handle_read_state(srv, con);
7548 +               /**
7549 +                * if SSL_read() is not readin in the full packet we won't get
7550 +                * a fdevent as the low-level has already fetched everything.
7551 +                *
7552 +                * we have to call the state-engine to read the rest of the packet
7553 +                */
7554 +               if (con->is_readable) joblist_append(srv, con);
7555         }
7556 -       
7557 +
7558         if (con->state == CON_STATE_WRITE &&
7559             !chunkqueue_is_empty(con->write_queue) &&
7560             con->is_writable) {
7561 -               
7562 +
7563                 if (-1 == connection_handle_write(srv, con)) {
7564                         connection_set_state(srv, con, CON_STATE_ERROR);
7565 -                       
7566 +
7567                         log_error_write(srv, __FILE__, __LINE__, "ds",
7568                                         con->fd,
7569                                         "handle write failed.");
7570 @@ -1193,30 +1100,30 @@
7571                         con->write_request_ts = srv->cur_ts;
7572                 }
7573         }
7574 -       
7575 +
7576         if (con->state == CON_STATE_CLOSE) {
7577                 /* flush the read buffers */
7578                 int b;
7579 -               
7580 +
7581                 if (ioctl(con->fd, FIONREAD, &b)) {
7582                         log_error_write(srv, __FILE__, __LINE__, "ss",
7583                                         "ioctl() failed", strerror(errno));
7584                 }
7585 -               
7586 +
7587                 if (b > 0) {
7588                         char buf[1024];
7589                         log_error_write(srv, __FILE__, __LINE__, "sdd",
7590                                         "CLOSE-read()", con->fd, b);
7591 -                       
7592 +
7593                         /* */
7594                         read(con->fd, buf, sizeof(buf));
7595                 } else {
7596                         /* nothing to read */
7597 -                       
7598 +
7599                         con->close_timeout_ts = 0;
7600                 }
7601         }
7602 -       
7603 +
7604         return HANDLER_FINISHED;
7605  }
7606  
7607 @@ -1229,63 +1136,68 @@
7608         sock_addr cnt_addr;
7609         socklen_t cnt_len;
7610         /* accept it and register the fd */
7611 -       
7612 +
7613         cnt_len = sizeof(cnt_addr);
7614  
7615         if (-1 == (cnt = accept(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) {
7616 +#ifdef _WIN32
7617 +        errno = WSAGetLastError();
7618 +#endif
7619                 if ((errno != EAGAIN) &&
7620 +            (errno != EWOULDBLOCK) &&
7621                     (errno != EINTR)) {
7622 -                       log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), errno);
7623 +                       log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), srv_socket->fd);
7624                 }
7625                 return NULL;
7626         } else {
7627                 connection *con;
7628 -               
7629 +
7630                 srv->cur_fds++;
7631 -               
7632 +
7633                 /* ok, we have the connection, register it */
7634  #if 0
7635                 log_error_write(srv, __FILE__, __LINE__, "sd",
7636                                 "appected()", cnt);
7637  #endif
7638                 srv->con_opened++;
7639 -               
7640 +
7641                 con = connections_get_new_connection(srv);
7642 -               
7643                 con->fd = cnt;
7644                 con->fde_ndx = -1;
7645 -#if 0          
7646 +#if 0
7647                 gettimeofday(&(con->start_tv), NULL);
7648 -#endif         
7649 +#endif
7650                 fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con);
7651 -               
7652 +
7653                 connection_set_state(srv, con, CON_STATE_REQUEST_START);
7654 -               
7655 +
7656                 con->connection_start = srv->cur_ts;
7657                 con->dst_addr = cnt_addr;
7658                 buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
7659                 con->srv_socket = srv_socket;
7660 -               
7661 +
7662                 if (-1 == (fdevent_fcntl_set(srv->ev, con->fd))) {
7663                         log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
7664 +                       connection_close(srv, con);
7665                         return NULL;
7666                 }
7667  #ifdef USE_OPENSSL
7668                 /* connect FD to SSL */
7669                 if (srv_socket->is_ssl) {
7670                         if (NULL == (con->ssl = SSL_new(srv_socket->ssl_ctx))) {
7671 -                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", 
7672 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7673                                                 ERR_error_string(ERR_get_error(), NULL));
7674 -                               
7675 +                               connection_close(srv, con);
7676                                 return NULL;
7677                         }
7678 -                       
7679 +
7680                         SSL_set_accept_state(con->ssl);
7681                         con->conf.is_ssl=1;
7682 -                       
7683 +
7684                         if (1 != (SSL_set_fd(con->ssl, cnt))) {
7685 -                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", 
7686 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7687                                                 ERR_error_string(ERR_get_error(), NULL));
7688 +                               connection_close(srv, con);
7689                                 return NULL;
7690                         }
7691                 }
7692 @@ -1300,10 +1212,10 @@
7693  #ifdef USE_OPENSSL
7694         server_socket *srv_sock = con->srv_socket;
7695  #endif
7696 -       
7697 +
7698         if (srv->srvconf.log_state_handling) {
7699 -               log_error_write(srv, __FILE__, __LINE__, "sds", 
7700 -                               "state at start", 
7701 +               log_error_write(srv, __FILE__, __LINE__, "sds",
7702 +                               "state at start",
7703                                 con->fd,
7704                                 connection_get_state(con->state));
7705         }
7706 @@ -1311,91 +1223,91 @@
7707         while (done == 0) {
7708                 size_t ostate = con->state;
7709                 int b;
7710 -               
7711 +
7712                 switch (con->state) {
7713                 case CON_STATE_REQUEST_START: /* transient */
7714                         if (srv->srvconf.log_state_handling) {
7715 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7716 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7717                                                 "state for fd", con->fd, connection_get_state(con->state));
7718                         }
7719 -                       
7720 +
7721                         con->request_start = srv->cur_ts;
7722                         con->read_idle_ts = srv->cur_ts;
7723 -                       
7724 +
7725                         con->request_count++;
7726                         con->loops_per_request = 0;
7727 -                       
7728 +
7729                         connection_set_state(srv, con, CON_STATE_READ);
7730 -                       
7731 +
7732                         break;
7733                 case CON_STATE_REQUEST_END: /* transient */
7734                         if (srv->srvconf.log_state_handling) {
7735 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7736 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7737                                                 "state for fd", con->fd, connection_get_state(con->state));
7738                         }
7739 -                       
7740 +
7741                         if (http_request_parse(srv, con)) {
7742                                 /* we have to read some data from the POST request */
7743 -                               
7744 +
7745                                 connection_set_state(srv, con, CON_STATE_READ_POST);
7746  
7747                                 break;
7748                         }
7749 -                       
7750 +
7751                         connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7752 -                       
7753 +
7754                         break;
7755                 case CON_STATE_HANDLE_REQUEST:
7756 -                       /* 
7757 +                       /*
7758                          * the request is parsed
7759 -                        * 
7760 +                        *
7761                          * decided what to do with the request
7762 -                        * - 
7763 -                        * 
7764 -                        * 
7765 +                        * -
7766 +                        *
7767 +                        *
7768                          */
7769 -                       
7770 +
7771                         if (srv->srvconf.log_state_handling) {
7772 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7773 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7774                                                 "state for fd", con->fd, connection_get_state(con->state));
7775                         }
7776 -                       
7777 +
7778                         switch (r = http_response_prepare(srv, con)) {
7779                         case HANDLER_FINISHED:
7780                                 if (con->http_status == 404 ||
7781                                     con->http_status == 403) {
7782                                         /* 404 error-handler */
7783 -                                       
7784 -                                       if (con->in_error_handler == 0 && 
7785 +
7786 +                                       if (con->in_error_handler == 0 &&
7787                                             (!buffer_is_empty(con->conf.error_handler) ||
7788                                              !buffer_is_empty(con->error_handler))) {
7789                                                 /* call error-handler */
7790 -                                               
7791 +
7792                                                 con->error_handler_saved_status = con->http_status;
7793                                                 con->http_status = 0;
7794 -                                               
7795 +
7796                                                 if (buffer_is_empty(con->error_handler)) {
7797                                                         buffer_copy_string_buffer(con->request.uri, con->conf.error_handler);
7798                                                 } else {
7799                                                         buffer_copy_string_buffer(con->request.uri, con->error_handler);
7800                                                 }
7801                                                 buffer_reset(con->physical.path);
7802 -                                               
7803 +
7804                                                 con->in_error_handler = 1;
7805 -                                               
7806 +
7807                                                 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7808 -                                               
7809 +
7810                                                 done = -1;
7811                                                 break;
7812                                         } else if (con->in_error_handler) {
7813                                                 /* error-handler is a 404 */
7814 -                                               
7815 +
7816                                                 /* continue as normal, status is the same */
7817 -                                               log_error_write(srv, __FILE__, __LINE__, "sb", 
7818 +                                               log_error_write(srv, __FILE__, __LINE__, "sb",
7819                                                                 "Warning: Either the error-handler returned status 404 or the error-handler itself was not found:", con->request.uri);
7820 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
7821 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
7822                                                                 "returning the original status", con->error_handler_saved_status);
7823 -                                               log_error_write(srv, __FILE__, __LINE__, "s", 
7824 +                                               log_error_write(srv, __FILE__, __LINE__, "s",
7825                                                                 "If this is a rails app: check your production.log");
7826                                                 con->http_status = con->error_handler_saved_status;
7827                                         }
7828 @@ -1403,26 +1315,26 @@
7829                                         /* error-handler is back and has generated content */
7830                                         /* if Status: was set, take it otherwise use 200 */
7831                                 }
7832 -                               
7833 +
7834                                 if (con->http_status == 0) con->http_status = 200;
7835 -                               
7836 +
7837                                 /* we have something to send, go on */
7838                                 connection_set_state(srv, con, CON_STATE_RESPONSE_START);
7839                                 break;
7840                         case HANDLER_WAIT_FOR_FD:
7841                                 srv->want_fds++;
7842 -                               
7843 +
7844                                 fdwaitqueue_append(srv, con);
7845 -                               
7846 +
7847                                 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7848 -                               
7849 +
7850                                 break;
7851                         case HANDLER_COMEBACK:
7852                                 done = -1;
7853                         case HANDLER_WAIT_FOR_EVENT:
7854                                 /* come back here */
7855                                 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7856 -                               
7857 +
7858                                 break;
7859                         case HANDLER_ERROR:
7860                                 /* something went wrong */
7861 @@ -1432,44 +1344,44 @@
7862                                 log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r);
7863                                 break;
7864                         }
7865 -                       
7866 +
7867                         break;
7868                 case CON_STATE_RESPONSE_START:
7869 -                       /* 
7870 +                       /*
7871                          * the decision is done
7872                          * - create the HTTP-Response-Header
7873 -                        * 
7874 +                        *
7875                          */
7876 -                       
7877 +
7878                         if (srv->srvconf.log_state_handling) {
7879 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7880 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7881                                                 "state for fd", con->fd, connection_get_state(con->state));
7882                         }
7883 -                       
7884 +
7885                         if (-1 == connection_handle_write_prepare(srv, con)) {
7886                                 connection_set_state(srv, con, CON_STATE_ERROR);
7887 -                               
7888 +
7889                                 break;
7890                         }
7891 -                       
7892 +
7893                         connection_set_state(srv, con, CON_STATE_WRITE);
7894                         break;
7895                 case CON_STATE_RESPONSE_END: /* transient */
7896                         /* log the request */
7897 -                       
7898 +
7899                         if (srv->srvconf.log_state_handling) {
7900 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7901 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7902                                                 "state for fd", con->fd, connection_get_state(con->state));
7903                         }
7904 -                       
7905 +
7906                         plugins_call_handle_request_done(srv, con);
7907 -                       
7908 +
7909                         srv->con_written++;
7910 -                       
7911 +
7912                         if (con->keep_alive) {
7913                                 connection_set_state(srv, con, CON_STATE_REQUEST_START);
7914 -                               
7915 -#if 0                                  
7916 +
7917 +#if 0
7918                                 con->request_start = srv->cur_ts;
7919                                 con->read_idle_ts = srv->cur_ts;
7920  #endif
7921 @@ -1482,7 +1394,7 @@
7922                                         log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r);
7923                                         break;
7924                                 }
7925 -                               
7926 +
7927  #ifdef USE_OPENSSL
7928                                 if (srv_sock->is_ssl) {
7929                                         switch (SSL_shutdown(con->ssl)) {
7930 @@ -1490,44 +1402,44 @@
7931                                                 /* done */
7932                                                 break;
7933                                         case 0:
7934 -                                               /* wait for fd-event 
7935 -                                                * 
7936 +                                               /* wait for fd-event
7937 +                                                *
7938                                                  * FIXME: wait for fdevent and call SSL_shutdown again
7939 -                                                * 
7940 +                                                *
7941                                                  */
7942 -                                               
7943 +
7944                                                 break;
7945                                         default:
7946 -                                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", 
7947 +                                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7948                                                                 ERR_error_string(ERR_get_error(), NULL));
7949                                         }
7950                                 }
7951  #endif
7952                                 connection_close(srv, con);
7953 -                               
7954 +
7955                                 srv->con_closed++;
7956                         }
7957 -                       
7958 +
7959                         connection_reset(srv, con);
7960 -                       
7961 +
7962                         break;
7963                 case CON_STATE_CONNECT:
7964                         if (srv->srvconf.log_state_handling) {
7965 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7966 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7967                                                 "state for fd", con->fd, connection_get_state(con->state));
7968                         }
7969 -                       
7970 +
7971                         chunkqueue_reset(con->read_queue);
7972 -                       
7973 +
7974                         con->request_count = 0;
7975 -                       
7976 +
7977                         break;
7978                 case CON_STATE_CLOSE:
7979                         if (srv->srvconf.log_state_handling) {
7980 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
7981 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
7982                                                 "state for fd", con->fd, connection_get_state(con->state));
7983                         }
7984 -                       
7985 +
7986                         if (con->keep_alive) {
7987                                 if (ioctl(con->fd, FIONREAD, &b)) {
7988                                         log_error_write(srv, __FILE__, __LINE__, "ss",
7989 @@ -1537,43 +1449,43 @@
7990                                         char buf[1024];
7991                                         log_error_write(srv, __FILE__, __LINE__, "sdd",
7992                                                         "CLOSE-read()", con->fd, b);
7993 -                                       
7994 +
7995                                         /* */
7996                                         read(con->fd, buf, sizeof(buf));
7997                                 } else {
7998                                         /* nothing to read */
7999 -                                       
8000 +
8001                                         con->close_timeout_ts = 0;
8002                                 }
8003                         } else {
8004                                 con->close_timeout_ts = 0;
8005                         }
8006 -                       
8007 +
8008                         if (srv->cur_ts - con->close_timeout_ts > 1) {
8009                                 connection_close(srv, con);
8010 -                               
8011 +
8012                                 if (srv->srvconf.log_state_handling) {
8013 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
8014 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
8015                                                         "connection closed for fd", con->fd);
8016                                 }
8017                         }
8018 -                       
8019 +
8020                         break;
8021                 case CON_STATE_READ_POST:
8022                 case CON_STATE_READ:
8023                         if (srv->srvconf.log_state_handling) {
8024 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
8025 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
8026                                                 "state for fd", con->fd, connection_get_state(con->state));
8027                         }
8028 -                       
8029 +
8030                         connection_handle_read_state(srv, con);
8031                         break;
8032                 case CON_STATE_WRITE:
8033                         if (srv->srvconf.log_state_handling) {
8034 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
8035 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
8036                                                 "state for fd", con->fd, connection_get_state(con->state));
8037                         }
8038 -                       
8039 +
8040                         /* only try to write if we have something in the queue */
8041                         if (!chunkqueue_is_empty(con->write_queue)) {
8042  #if 0
8043 @@ -1593,10 +1505,10 @@
8044                                         con->write_request_ts = srv->cur_ts;
8045                                 }
8046                         }
8047 -                       
8048 +
8049                         break;
8050                 case CON_STATE_ERROR: /* transient */
8051 -                       
8052 +
8053                         /* even if the connection was drop we still have to write it to the access log */
8054                         if (con->http_status) {
8055                                 plugins_call_handle_request_done(srv, con);
8056 @@ -1612,19 +1524,19 @@
8057                                         SSL_shutdown(con->ssl);
8058                                         break;
8059                                 default:
8060 -                                       log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:", 
8061 -                                                       SSL_get_error(con->ssl, ret), 
8062 +                                       log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
8063 +                                                       SSL_get_error(con->ssl, ret),
8064                                                         ERR_error_string(ERR_get_error(), NULL));
8065                                         return -1;
8066                                 }
8067                         }
8068  #endif
8069 -                       
8070 +
8071                         switch(con->mode) {
8072                         case DIRECT:
8073  #if 0
8074 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
8075 -                                               "emergency exit: direct", 
8076 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
8077 +                                               "emergency exit: direct",
8078                                                 con->fd);
8079  #endif
8080                                 break;
8081 @@ -1639,35 +1551,35 @@
8082                                 }
8083                                 break;
8084                         }
8085 -                       
8086 +
8087                         connection_reset(srv, con);
8088 -                       
8089 +
8090                         /* close the connection */
8091                         if ((con->keep_alive == 1) &&
8092                             (0 == shutdown(con->fd, SHUT_WR))) {
8093                                 con->close_timeout_ts = srv->cur_ts;
8094                                 connection_set_state(srv, con, CON_STATE_CLOSE);
8095 -                               
8096 +
8097                                 if (srv->srvconf.log_state_handling) {
8098 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
8099 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
8100                                                         "shutdown for fd", con->fd);
8101                                 }
8102                         } else {
8103                                 connection_close(srv, con);
8104                         }
8105 -                       
8106 +
8107                         con->keep_alive = 0;
8108 -                       
8109 +
8110                         srv->con_closed++;
8111 -                       
8112 +
8113                         break;
8114                 default:
8115 -                       log_error_write(srv, __FILE__, __LINE__, "sdd", 
8116 +                       log_error_write(srv, __FILE__, __LINE__, "sdd",
8117                                         "unknown state:", con->fd, con->state);
8118 -                       
8119 +
8120                         break;
8121                 }
8122 -               
8123 +
8124                 if (done == -1) {
8125                         done = 0;
8126                 } else if (ostate == con->state) {
8127 @@ -1676,12 +1588,12 @@
8128         }
8129  
8130         if (srv->srvconf.log_state_handling) {
8131 -               log_error_write(srv, __FILE__, __LINE__, "sds", 
8132 -                               "state at exit:", 
8133 +               log_error_write(srv, __FILE__, __LINE__, "sds",
8134 +                               "state at exit:",
8135                                 con->fd,
8136                                 connection_get_state(con->state));
8137         }
8138 -       
8139 +
8140         switch(con->state) {
8141         case CON_STATE_READ_POST:
8142         case CON_STATE_READ:
8143 @@ -1689,11 +1601,11 @@
8144                 fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_IN);
8145                 break;
8146         case CON_STATE_WRITE:
8147 -               /* request write-fdevent only if we really need it 
8148 +               /* request write-fdevent only if we really need it
8149                  * - if we have data to write
8150 -                * - if the socket is not writable yet 
8151 +                * - if the socket is not writable yet
8152                  */
8153 -               if (!chunkqueue_is_empty(con->write_queue) && 
8154 +               if (!chunkqueue_is_empty(con->write_queue) &&
8155                     (con->is_writable == 0) &&
8156                     (con->traffic_limit_reached == 0)) {
8157                         fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT);
8158 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/crc32.h lighttpd-1.4.12/src/crc32.h
8159 --- lighttpd-1.4.11/src/crc32.h 2005-09-30 20:18:59.000000000 +0300
8160 +++ lighttpd-1.4.12/src/crc32.h 2006-07-11 21:23:40.000000000 +0300
8161 @@ -6,6 +6,7 @@
8162  #endif
8163  
8164  #include <sys/types.h>
8165 +#include <stdlib.h>
8166  
8167  #if defined HAVE_STDINT_H
8168  #include <stdint.h>
8169 @@ -13,6 +14,10 @@
8170  #include <inttypes.h>
8171  #endif
8172  
8173 +#ifdef _WIN32
8174 +#define uint32_t unsigned __int32
8175 +#endif
8176 +
8177  uint32_t generate_crc32c(char *string, size_t length);
8178  
8179  #endif
8180 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/data_array.c lighttpd-1.4.12/src/data_array.c
8181 --- lighttpd-1.4.11/src/data_array.c    2005-08-23 17:36:12.000000000 +0300
8182 +++ lighttpd-1.4.12/src/data_array.c    2006-07-11 21:23:40.000000000 +0300
8183 @@ -17,16 +17,16 @@
8184  
8185  static void data_array_free(data_unset *d) {
8186         data_array *ds = (data_array *)d;
8187 -       
8188 +
8189         buffer_free(ds->key);
8190         array_free(ds->value);
8191 -       
8192 +
8193         free(d);
8194  }
8195  
8196  static void data_array_reset(data_unset *d) {
8197         data_array *ds = (data_array *)d;
8198 -       
8199 +
8200         /* reused array elements */
8201         buffer_reset(ds->key);
8202         array_reset(ds->value);
8203 @@ -36,7 +36,7 @@
8204         UNUSED(dst);
8205  
8206         src->free(src);
8207 -       
8208 +
8209         return 0;
8210  }
8211  
8212 @@ -48,18 +48,18 @@
8213  
8214  data_array *data_array_init(void) {
8215         data_array *ds;
8216 -       
8217 +
8218         ds = calloc(1, sizeof(*ds));
8219 -       
8220 +
8221         ds->key = buffer_init();
8222         ds->value = array_init();
8223 -       
8224 +
8225         ds->copy = data_array_copy;
8226         ds->free = data_array_free;
8227         ds->reset = data_array_reset;
8228         ds->insert_dup = data_array_insert_dup;
8229         ds->print = data_array_print;
8230         ds->type = TYPE_ARRAY;
8231 -       
8232 +
8233         return ds;
8234  }
8235 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/data_config.c lighttpd-1.4.12/src/data_config.c
8236 --- lighttpd-1.4.11/src/data_config.c   2005-08-17 12:53:19.000000000 +0300
8237 +++ lighttpd-1.4.12/src/data_config.c   2006-07-11 21:23:39.000000000 +0300
8238 @@ -17,26 +17,26 @@
8239  
8240  static void data_config_free(data_unset *d) {
8241         data_config *ds = (data_config *)d;
8242 -       
8243 +
8244         buffer_free(ds->key);
8245         buffer_free(ds->op);
8246         buffer_free(ds->comp_key);
8247 -       
8248 +
8249         array_free(ds->value);
8250         array_free(ds->childs);
8251 -       
8252 +
8253         if (ds->string) buffer_free(ds->string);
8254  #ifdef HAVE_PCRE_H
8255         if (ds->regex) pcre_free(ds->regex);
8256         if (ds->regex_study) pcre_free(ds->regex_study);
8257  #endif
8258 -       
8259 +
8260         free(d);
8261  }
8262  
8263  static void data_config_reset(data_unset *d) {
8264         data_config *ds = (data_config *)d;
8265 -       
8266 +
8267         /* reused array elements */
8268         buffer_reset(ds->key);
8269         buffer_reset(ds->comp_key);
8270 @@ -45,9 +45,9 @@
8271  
8272  static int data_config_insert_dup(data_unset *dst, data_unset *src) {
8273         UNUSED(dst);
8274 -       
8275 +
8276         src->free(src);
8277 -       
8278 +
8279         return 0;
8280  }
8281  
8282 @@ -56,7 +56,7 @@
8283         array *a = (array *)ds->value;
8284         size_t i;
8285         size_t maxlen;
8286 -       
8287 +
8288         if (0 == ds->context_ndx) {
8289                 fprintf(stderr, "config {\n");
8290         }
8291 @@ -117,22 +117,22 @@
8292  
8293  data_config *data_config_init(void) {
8294         data_config *ds;
8295 -       
8296 +
8297         ds = calloc(1, sizeof(*ds));
8298 -       
8299 +
8300         ds->key = buffer_init();
8301         ds->op = buffer_init();
8302         ds->comp_key = buffer_init();
8303         ds->value = array_init();
8304         ds->childs = array_init();
8305         ds->childs->is_weakref = 1;
8306 -       
8307 +
8308         ds->copy = data_config_copy;
8309         ds->free = data_config_free;
8310         ds->reset = data_config_reset;
8311         ds->insert_dup = data_config_insert_dup;
8312         ds->print = data_config_print;
8313         ds->type = TYPE_CONFIG;
8314 -       
8315 +
8316         return ds;
8317  }
8318 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/data_count.c lighttpd-1.4.12/src/data_count.c
8319 --- lighttpd-1.4.11/src/data_count.c    2005-08-23 17:36:12.000000000 +0300
8320 +++ lighttpd-1.4.12/src/data_count.c    2006-07-11 21:23:40.000000000 +0300
8321 @@ -16,53 +16,53 @@
8322  
8323  static void data_count_free(data_unset *d) {
8324         data_count *ds = (data_count *)d;
8325 -       
8326 +
8327         buffer_free(ds->key);
8328 -       
8329 +
8330         free(d);
8331  }
8332  
8333  static void data_count_reset(data_unset *d) {
8334         data_count *ds = (data_count *)d;
8335 -       
8336 +
8337         buffer_reset(ds->key);
8338 -       
8339 +
8340         ds->count = 0;
8341  }
8342  
8343  static int data_count_insert_dup(data_unset *dst, data_unset *src) {
8344         data_count *ds_dst = (data_count *)dst;
8345         data_count *ds_src = (data_count *)src;
8346 -       
8347 +
8348         ds_dst->count += ds_src->count;
8349 -       
8350 +
8351         src->free(src);
8352 -       
8353 +
8354         return 0;
8355  }
8356  
8357  static void data_count_print(const data_unset *d, int depth) {
8358         data_count *ds = (data_count *)d;
8359         UNUSED(depth);
8360 -       
8361 +
8362         fprintf(stderr, "count(%d)", ds->count);
8363  }
8364  
8365  
8366  data_count *data_count_init(void) {
8367         data_count *ds;
8368 -       
8369 +
8370         ds = calloc(1, sizeof(*ds));
8371 -       
8372 +
8373         ds->key = buffer_init();
8374         ds->count = 1;
8375 -       
8376 +
8377         ds->copy = data_count_copy;
8378         ds->free = data_count_free;
8379         ds->reset = data_count_reset;
8380         ds->insert_dup = data_count_insert_dup;
8381         ds->print = data_count_print;
8382         ds->type = TYPE_COUNT;
8383 -       
8384 +
8385         return ds;
8386  }
8387 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/data_fastcgi.c lighttpd-1.4.12/src/data_fastcgi.c
8388 --- lighttpd-1.4.11/src/data_fastcgi.c  2005-08-23 17:36:12.000000000 +0300
8389 +++ lighttpd-1.4.12/src/data_fastcgi.c  2006-07-11 21:23:40.000000000 +0300
8390 @@ -17,53 +17,53 @@
8391  
8392  static void data_fastcgi_free(data_unset *d) {
8393         data_fastcgi *ds = (data_fastcgi *)d;
8394 -       
8395 +
8396         buffer_free(ds->key);
8397         buffer_free(ds->host);
8398 -       
8399 +
8400         free(d);
8401  }
8402  
8403  static void data_fastcgi_reset(data_unset *d) {
8404         data_fastcgi *ds = (data_fastcgi *)d;
8405 -       
8406 +
8407         buffer_reset(ds->key);
8408         buffer_reset(ds->host);
8409 -       
8410 +
8411  }
8412  
8413  static int data_fastcgi_insert_dup(data_unset *dst, data_unset *src) {
8414         UNUSED(dst);
8415  
8416         src->free(src);
8417 -       
8418 +
8419         return 0;
8420  }
8421  
8422  static void data_fastcgi_print(const data_unset *d, int depth) {
8423         data_fastcgi *ds = (data_fastcgi *)d;
8424         UNUSED(depth);
8425 -       
8426 +
8427         fprintf(stderr, "fastcgi(%s)", ds->host->ptr);
8428  }
8429  
8430  
8431  data_fastcgi *data_fastcgi_init(void) {
8432         data_fastcgi *ds;
8433 -       
8434 +
8435         ds = calloc(1, sizeof(*ds));
8436 -       
8437 +
8438         ds->key = buffer_init();
8439         ds->host = buffer_init();
8440         ds->port = 0;
8441         ds->is_disabled = 0;
8442 -       
8443 +
8444         ds->copy = data_fastcgi_copy;
8445         ds->free = data_fastcgi_free;
8446         ds->reset = data_fastcgi_reset;
8447         ds->insert_dup = data_fastcgi_insert_dup;
8448         ds->print = data_fastcgi_print;
8449         ds->type = TYPE_FASTCGI;
8450 -       
8451 +
8452         return ds;
8453  }
8454 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/data_integer.c lighttpd-1.4.12/src/data_integer.c
8455 --- lighttpd-1.4.11/src/data_integer.c  2005-08-23 17:36:12.000000000 +0300
8456 +++ lighttpd-1.4.12/src/data_integer.c  2006-07-11 21:23:39.000000000 +0300
8457 @@ -16,15 +16,15 @@
8458  
8459  static void data_integer_free(data_unset *d) {
8460         data_integer *ds = (data_integer *)d;
8461 -       
8462 +
8463         buffer_free(ds->key);
8464 -       
8465 +
8466         free(d);
8467  }
8468  
8469  static void data_integer_reset(data_unset *d) {
8470         data_integer *ds = (data_integer *)d;
8471 -       
8472 +
8473         /* reused integer elements */
8474         buffer_reset(ds->key);
8475         ds->value = 0;
8476 @@ -32,9 +32,9 @@
8477  
8478  static int data_integer_insert_dup(data_unset *dst, data_unset *src) {
8479         UNUSED(dst);
8480 -       
8481 +
8482         src->free(src);
8483 -       
8484 +
8485         return 0;
8486  }
8487  
8488 @@ -48,18 +48,18 @@
8489  
8490  data_integer *data_integer_init(void) {
8491         data_integer *ds;
8492 -       
8493 +
8494         ds = calloc(1, sizeof(*ds));
8495 -       
8496 +
8497         ds->key = buffer_init();
8498         ds->value = 0;
8499 -       
8500 +
8501         ds->copy = data_integer_copy;
8502         ds->free = data_integer_free;
8503         ds->reset = data_integer_reset;
8504         ds->insert_dup = data_integer_insert_dup;
8505         ds->print = data_integer_print;
8506         ds->type = TYPE_INTEGER;
8507 -       
8508 +
8509         return ds;
8510  }
8511 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/data_string.c lighttpd-1.4.12/src/data_string.c
8512 --- lighttpd-1.4.11/src/data_string.c   2005-08-23 17:36:12.000000000 +0300
8513 +++ lighttpd-1.4.12/src/data_string.c   2006-07-11 21:23:40.000000000 +0300
8514 @@ -17,16 +17,16 @@
8515  
8516  static void data_string_free(data_unset *d) {
8517         data_string *ds = (data_string *)d;
8518 -       
8519 +
8520         buffer_free(ds->key);
8521         buffer_free(ds->value);
8522 -       
8523 +
8524         free(d);
8525  }
8526  
8527  static void data_string_reset(data_unset *d) {
8528         data_string *ds = (data_string *)d;
8529 -       
8530 +
8531         /* reused array elements */
8532         buffer_reset(ds->key);
8533         buffer_reset(ds->value);
8534 @@ -35,23 +35,23 @@
8535  static int data_string_insert_dup(data_unset *dst, data_unset *src) {
8536         data_string *ds_dst = (data_string *)dst;
8537         data_string *ds_src = (data_string *)src;
8538 -       
8539 +
8540         if (ds_dst->value->used) {
8541                 buffer_append_string(ds_dst->value, ", ");
8542                 buffer_append_string_buffer(ds_dst->value, ds_src->value);
8543         } else {
8544                 buffer_copy_string_buffer(ds_dst->value, ds_src->value);
8545         }
8546 -       
8547 +
8548         src->free(src);
8549 -       
8550 +
8551         return 0;
8552  }
8553  
8554  static int data_response_insert_dup(data_unset *dst, data_unset *src) {
8555         data_string *ds_dst = (data_string *)dst;
8556         data_string *ds_src = (data_string *)src;
8557 -       
8558 +
8559         if (ds_dst->value->used) {
8560                 buffer_append_string(ds_dst->value, "\r\n");
8561                 buffer_append_string_buffer(ds_dst->value, ds_dst->key);
8562 @@ -60,9 +60,9 @@
8563         } else {
8564                 buffer_copy_string_buffer(ds_dst->value, ds_src->value);
8565         }
8566 -       
8567 +
8568         src->free(src);
8569 -       
8570 +
8571         return 0;
8572  }
8573  
8574 @@ -77,28 +77,28 @@
8575  
8576  data_string *data_string_init(void) {
8577         data_string *ds;
8578 -       
8579 +
8580         ds = calloc(1, sizeof(*ds));
8581         assert(ds);
8582 -       
8583 +
8584         ds->key = buffer_init();
8585         ds->value = buffer_init();
8586 -       
8587 +
8588         ds->copy = data_string_copy;
8589         ds->free = data_string_free;
8590         ds->reset = data_string_reset;
8591         ds->insert_dup = data_string_insert_dup;
8592         ds->print = data_string_print;
8593         ds->type = TYPE_STRING;
8594 -       
8595 +
8596         return ds;
8597  }
8598  
8599  data_string *data_response_init(void) {
8600         data_string *ds;
8601 -       
8602 +
8603         ds = data_string_init();
8604         ds->insert_dup = data_response_insert_dup;
8605 -       
8606 +
8607         return ds;
8608  }
8609 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/etag.c lighttpd-1.4.12/src/etag.c
8610 --- lighttpd-1.4.11/src/etag.c  2005-08-11 01:26:40.000000000 +0300
8611 +++ lighttpd-1.4.12/src/etag.c  2006-07-11 21:23:40.000000000 +0300
8612 @@ -14,19 +14,19 @@
8613         buffer_append_off_t(etag, st->st_size);
8614         buffer_append_string_len(etag, CONST_STR_LEN("-"));
8615         buffer_append_long(etag, st->st_mtime);
8616 -       
8617 +
8618         return 0;
8619  }
8620  
8621  int etag_mutate(buffer *mut, buffer *etag) {
8622         size_t h, i;
8623 -       
8624 +
8625         for (h=0, i=0; i < etag->used; ++i) h = (h<<5)^(h>>27)^(etag->ptr[i]);
8626 -       
8627 +
8628         buffer_reset(mut);
8629         buffer_copy_string_len(mut, CONST_STR_LEN("\""));
8630         buffer_append_long(mut, h);
8631         buffer_append_string_len(mut, CONST_STR_LEN("\""));
8632 -       
8633 +
8634         return 0;
8635  }
8636 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/etag.h lighttpd-1.4.12/src/etag.h
8637 --- lighttpd-1.4.11/src/etag.h  2005-08-11 01:26:40.000000000 +0300
8638 +++ lighttpd-1.4.12/src/etag.h  2006-07-11 21:23:40.000000000 +0300
8639 @@ -3,13 +3,12 @@
8640  
8641  #include <sys/types.h>
8642  #include <sys/stat.h>
8643 -#include <unistd.h>
8644  
8645  #include "buffer.h"
8646  
8647  int etag_is_equal(buffer *etag, const char *matches);
8648  int etag_create(buffer *etag, struct stat *st);
8649  int etag_mutate(buffer *mut, buffer *etag);
8650 -       
8651 +
8652  
8653  #endif
8654 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/fastcgi.h lighttpd-1.4.12/src/fastcgi.h
8655 --- lighttpd-1.4.11/src/fastcgi.h       2005-08-11 01:26:40.000000000 +0300
8656 +++ lighttpd-1.4.12/src/fastcgi.h       2006-07-11 21:23:40.000000000 +0300
8657 @@ -1,4 +1,4 @@
8658 -/* 
8659 +/*
8660   * fastcgi.h --
8661   *
8662   *     Defines for the FastCGI protocol.
8663 @@ -123,7 +123,7 @@
8664  
8665  
8666  typedef struct {
8667 -    unsigned char type;    
8668 +    unsigned char type;
8669      unsigned char reserved[7];
8670  } FCGI_UnknownTypeBody;
8671  
8672 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/fdevent.c lighttpd-1.4.12/src/fdevent.c
8673 --- lighttpd-1.4.11/src/fdevent.c       2005-11-15 10:51:05.000000000 +0200
8674 +++ lighttpd-1.4.12/src/fdevent.c       2006-07-11 21:23:40.000000000 +0300
8675 @@ -2,7 +2,6 @@
8676  
8677  #include "settings.h"
8678  
8679 -#include <unistd.h>
8680  #include <stdlib.h>
8681  #include <string.h>
8682  #include <errno.h>
8683 @@ -12,59 +11,61 @@
8684  #include "fdevent.h"
8685  #include "buffer.h"
8686  
8687 +#include "sys-socket.h"
8688 +
8689  fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type) {
8690         fdevents *ev;
8691 -       
8692 +
8693         ev = calloc(1, sizeof(*ev));
8694         ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray));
8695         ev->maxfds = maxfds;
8696 -       
8697 +
8698         switch(type) {
8699         case FDEVENT_HANDLER_POLL:
8700                 if (0 != fdevent_poll_init(ev)) {
8701 -                       fprintf(stderr, "%s.%d: event-handler poll failed\n", 
8702 +                       fprintf(stderr, "%s.%d: event-handler poll failed\n",
8703                                 __FILE__, __LINE__);
8704 -                       
8705 +
8706                         return NULL;
8707                 }
8708                 break;
8709         case FDEVENT_HANDLER_SELECT:
8710                 if (0 != fdevent_select_init(ev)) {
8711 -                       fprintf(stderr, "%s.%d: event-handler select failed\n", 
8712 +                       fprintf(stderr, "%s.%d: event-handler select failed\n",
8713                                 __FILE__, __LINE__);
8714                         return NULL;
8715                 }
8716                 break;
8717         case FDEVENT_HANDLER_LINUX_RTSIG:
8718                 if (0 != fdevent_linux_rtsig_init(ev)) {
8719 -                       fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n", 
8720 +                       fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8721                                 __FILE__, __LINE__);
8722                         return NULL;
8723                 }
8724                 break;
8725         case FDEVENT_HANDLER_LINUX_SYSEPOLL:
8726                 if (0 != fdevent_linux_sysepoll_init(ev)) {
8727 -                       fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n", 
8728 +                       fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8729                                 __FILE__, __LINE__);
8730                         return NULL;
8731                 }
8732                 break;
8733         case FDEVENT_HANDLER_SOLARIS_DEVPOLL:
8734                 if (0 != fdevent_solaris_devpoll_init(ev)) {
8735 -                       fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n", 
8736 +                       fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8737                                 __FILE__, __LINE__);
8738                         return NULL;
8739                 }
8740                 break;
8741         case FDEVENT_HANDLER_FREEBSD_KQUEUE:
8742                 if (0 != fdevent_freebsd_kqueue_init(ev)) {
8743 -                       fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n", 
8744 +                       fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8745                                 __FILE__, __LINE__);
8746                         return NULL;
8747                 }
8748                 break;
8749         default:
8750 -               fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n", 
8751 +               fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n",
8752                         __FILE__, __LINE__);
8753                 return NULL;
8754         }
8755 @@ -75,26 +76,26 @@
8756  void fdevent_free(fdevents *ev) {
8757         size_t i;
8758         if (!ev) return;
8759 -       
8760 +
8761         if (ev->free) ev->free(ev);
8762 -       
8763 +
8764         for (i = 0; i < ev->maxfds; i++) {
8765                 if (ev->fdarray[i]) free(ev->fdarray[i]);
8766         }
8767 -       
8768 +
8769         free(ev->fdarray);
8770         free(ev);
8771  }
8772  
8773  int fdevent_reset(fdevents *ev) {
8774         if (ev->reset) return ev->reset(ev);
8775 -       
8776 +
8777         return 0;
8778  }
8779  
8780  fdnode *fdnode_init() {
8781         fdnode *fdn;
8782 -       
8783 +
8784         fdn = calloc(1, sizeof(*fdn));
8785         fdn->fd = -1;
8786         return fdn;
8787 @@ -106,12 +107,12 @@
8788  
8789  int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) {
8790         fdnode *fdn;
8791 -       
8792 +
8793         fdn = fdnode_init();
8794         fdn->handler = handler;
8795         fdn->fd      = fd;
8796         fdn->ctx     = ctx;
8797 -       
8798 +
8799         ev->fdarray[fd] = fdn;
8800  
8801         return 0;
8802 @@ -121,31 +122,31 @@
8803         fdnode *fdn;
8804          if (!ev) return 0;
8805         fdn = ev->fdarray[fd];
8806 -       
8807 +
8808         fdnode_free(fdn);
8809 -       
8810 +
8811         ev->fdarray[fd] = NULL;
8812 -       
8813 +
8814         return 0;
8815  }
8816  
8817  int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) {
8818         int fde = fde_ndx ? *fde_ndx : -1;
8819 -       
8820 +
8821         if (ev->event_del) fde = ev->event_del(ev, fde, fd);
8822 -       
8823 +
8824         if (fde_ndx) *fde_ndx = fde;
8825 -       
8826 +
8827         return 0;
8828  }
8829  
8830  int fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int events) {
8831         int fde = fde_ndx ? *fde_ndx : -1;
8832 -       
8833 +
8834         if (ev->event_add) fde = ev->event_add(ev, fde, fd, events);
8835 -       
8836 +
8837         if (fde_ndx) *fde_ndx = fde;
8838 -       
8839 +
8840         return 0;
8841  }
8842  
8843 @@ -156,38 +157,43 @@
8844  
8845  int fdevent_event_get_revent(fdevents *ev, size_t ndx) {
8846         if (ev->event_get_revent == NULL) SEGFAULT();
8847 -       
8848 +
8849         return ev->event_get_revent(ev, ndx);
8850  }
8851  
8852  int fdevent_event_get_fd(fdevents *ev, size_t ndx) {
8853         if (ev->event_get_fd == NULL) SEGFAULT();
8854 -       
8855 +
8856         return ev->event_get_fd(ev, ndx);
8857  }
8858  
8859  fdevent_handler fdevent_get_handler(fdevents *ev, int fd) {
8860         if (ev->fdarray[fd] == NULL) SEGFAULT();
8861         if (ev->fdarray[fd]->fd != fd) SEGFAULT();
8862 -       
8863 +
8864         return ev->fdarray[fd]->handler;
8865  }
8866  
8867  void * fdevent_get_context(fdevents *ev, int fd) {
8868         if (ev->fdarray[fd] == NULL) SEGFAULT();
8869         if (ev->fdarray[fd]->fd != fd) SEGFAULT();
8870 -       
8871 +
8872         return ev->fdarray[fd]->ctx;
8873  }
8874  
8875  int fdevent_fcntl_set(fdevents *ev, int fd) {
8876 +#ifdef _WIN32
8877 +    int i = 1;
8878 +#endif
8879  #ifdef FD_CLOEXEC
8880         /* close fd on exec (cgi) */
8881         fcntl(fd, F_SETFD, FD_CLOEXEC);
8882  #endif
8883         if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, fd);
8884 -#ifdef O_NONBLOCK      
8885 +#ifdef O_NONBLOCK
8886         return fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR);
8887 +#elif defined _WIN32
8888 +    return ioctlsocket(fd, FIONBIO, &i);
8889  #else
8890         return 0;
8891  #endif
8892 @@ -196,7 +202,7 @@
8893  
8894  int fdevent_event_next_fdndx(fdevents *ev, int ndx) {
8895         if (ev->event_next_fdndx) return ev->event_next_fdndx(ev, ndx);
8896 -       
8897 +
8898         return -1;
8899  }
8900  
8901 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/fdevent.h lighttpd-1.4.12/src/fdevent.h
8902 --- lighttpd-1.4.11/src/fdevent.h       2005-09-27 11:26:33.000000000 +0300
8903 +++ lighttpd-1.4.12/src/fdevent.h       2006-07-11 21:23:39.000000000 +0300
8904 @@ -17,13 +17,13 @@
8905  # include <sys/epoll.h>
8906  #endif
8907  
8908 -/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes 
8909 +/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes
8910   * under /usr/include/sys/ */
8911  #if defined HAVE_POLL && (defined(HAVE_SYS_POLL_H) || defined(HAVE_POLL_H))
8912  # define USE_POLL
8913  # ifdef HAVE_POLL_H
8914  #  include <poll.h>
8915 -# else 
8916 +# else
8917  #  include <sys/poll.h>
8918  # endif
8919  # if defined HAVE_SIGTIMEDWAIT && defined(__linux__)
8920 @@ -31,9 +31,11 @@
8921  #  include <signal.h>
8922  # endif
8923  #endif
8924 -
8925 +#ifdef _WIN32
8926 +# define HAVE_SELECT
8927 +#endif
8928  #if defined HAVE_SELECT
8929 -# ifdef __WIN32
8930 +# ifdef _WIN32
8931  #  include <winsock2.h>
8932  # endif
8933  # define USE_SELECT
8934 @@ -67,14 +69,14 @@
8935  #define FDEVENT_HUP    BV(4)
8936  #define FDEVENT_NVAL   BV(5)
8937  
8938 -typedef enum { FD_EVENT_TYPE_UNSET = -1, 
8939 -               FD_EVENT_TYPE_CONNECTION, 
8940 -               FD_EVENT_TYPE_FCGI_CONNECTION, 
8941 -               FD_EVENT_TYPE_DIRWATCH, 
8942 -               FD_EVENT_TYPE_CGI_CONNECTION 
8943 +typedef enum { FD_EVENT_TYPE_UNSET = -1,
8944 +               FD_EVENT_TYPE_CONNECTION,
8945 +               FD_EVENT_TYPE_FCGI_CONNECTION,
8946 +               FD_EVENT_TYPE_DIRWATCH,
8947 +               FD_EVENT_TYPE_CGI_CONNECTION
8948  } fd_event_t;
8949  
8950 -typedef enum { FDEVENT_HANDLER_UNSET, 
8951 +typedef enum { FDEVENT_HANDLER_UNSET,
8952                 FDEVENT_HANDLER_SELECT,
8953                 FDEVENT_HANDLER_POLL,
8954                 FDEVENT_HANDLER_LINUX_RTSIG,
8955 @@ -86,7 +88,7 @@
8956  
8957  /**
8958   * a mapping from fd to connection structure
8959 - * 
8960 + *
8961   */
8962  typedef struct {
8963         int fd;                  /**< the fd */
8964 @@ -98,41 +100,41 @@
8965  
8966  typedef struct {
8967         fd_conn *ptr;
8968 -       
8969 +
8970         size_t size;
8971         size_t used;
8972  } fd_conn_buffer;
8973  
8974  /**
8975   * array of unused fd's
8976 - * 
8977 + *
8978   */
8979  
8980  typedef struct _fdnode {
8981         fdevent_handler handler;
8982         void *ctx;
8983         int fd;
8984 -       
8985 +
8986         struct _fdnode *prev, *next;
8987  } fdnode;
8988  
8989  typedef struct {
8990         int *ptr;
8991 -       
8992 +
8993         size_t used;
8994         size_t size;
8995  } buffer_int;
8996  
8997  /**
8998   * fd-event handler for select(), poll() and rt-signals on Linux 2.4
8999 - * 
9000 + *
9001   */
9002  typedef struct fdevents {
9003         fdevent_handler_t type;
9004 -       
9005 +
9006         fdnode **fdarray;
9007         size_t maxfds;
9008 -       
9009 +
9010  #ifdef USE_LINUX_SIGIO
9011         int in_sigio;
9012         int signum;
9013 @@ -146,21 +148,21 @@
9014  #endif
9015  #ifdef USE_POLL
9016         struct pollfd *pollfds;
9017 -       
9018 +
9019         size_t size;
9020         size_t used;
9021 -       
9022 +
9023         buffer_int unused;
9024  #endif
9025  #ifdef USE_SELECT
9026         fd_set select_read;
9027         fd_set select_write;
9028         fd_set select_error;
9029 -       
9030 +
9031         fd_set select_set_read;
9032         fd_set select_set_write;
9033         fd_set select_set_error;
9034 -       
9035 +
9036         int select_max_fd;
9037  #endif
9038  #ifdef USE_SOLARIS_DEVPOLL
9039 @@ -177,16 +179,16 @@
9040  #endif
9041         int (*reset)(struct fdevents *ev);
9042         void (*free)(struct fdevents *ev);
9043 -       
9044 +
9045         int (*event_add)(struct fdevents *ev, int fde_ndx, int fd, int events);
9046         int (*event_del)(struct fdevents *ev, int fde_ndx, int fd);
9047         int (*event_get_revent)(struct fdevents *ev, size_t ndx);
9048         int (*event_get_fd)(struct fdevents *ev, size_t ndx);
9049 -       
9050 +
9051         int (*event_next_fdndx)(struct fdevents *ev, int ndx);
9052 -       
9053 +
9054         int (*poll)(struct fdevents *ev, int timeout_ms);
9055 -       
9056 +
9057         int (*fcntl_set)(struct fdevents *ev, int fd);
9058  } fdevents;
9059  
9060 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/fdevent_freebsd_kqueue.c lighttpd-1.4.12/src/fdevent_freebsd_kqueue.c
9061 --- lighttpd-1.4.11/src/fdevent_freebsd_kqueue.c        2005-09-01 10:46:24.000000000 +0300
9062 +++ lighttpd-1.4.12/src/fdevent_freebsd_kqueue.c        2006-07-11 21:23:39.000000000 +0300
9063 @@ -1,6 +1,5 @@
9064  #include <sys/types.h>
9065  
9066 -#include <unistd.h>
9067  #include <stdlib.h>
9068  #include <stdio.h>
9069  #include <string.h>
9070 @@ -48,7 +47,7 @@
9071  
9072                 return -1;
9073         }
9074 -       
9075 +
9076         return -1;
9077  }
9078  
9079 @@ -65,7 +64,7 @@
9080  
9081         ts.tv_sec  = 0;
9082         ts.tv_nsec = 0;
9083 -       
9084 +
9085         ret = kevent(ev->kq_fd,
9086                      &kev, 1,
9087                      NULL, 0,
9088 @@ -77,7 +76,7 @@
9089  
9090                 return -1;
9091         }
9092 -       
9093 +
9094         if (filter == EVFILT_READ) {
9095                 bitset_set_bit(ev->kq_bevents, fd);
9096         } else {
9097 @@ -124,7 +123,7 @@
9098         } else if (e == EVFILT_WRITE) {
9099                 events |= FDEVENT_OUT;
9100         }
9101 -       
9102 +
9103         e = ev->kq_results[ndx].flags;
9104  
9105         if (e & EV_EOF) {
9106 @@ -152,10 +151,10 @@
9107         if (-1 == (ev->kq_fd = kqueue())) {
9108                 fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
9109                         __FILE__, __LINE__, strerror(errno));
9110 -               
9111 +
9112                 return -1;
9113         }
9114 -       
9115 +
9116         return 0;
9117  }
9118  
9119 @@ -186,7 +185,7 @@
9120         if (-1 == (ev->kq_fd = kqueue())) {
9121                 fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
9122                         __FILE__, __LINE__, strerror(errno));
9123 -               
9124 +
9125                 return -1;
9126         }
9127  
9128 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/fdevent_linux_rtsig.c lighttpd-1.4.12/src/fdevent_linux_rtsig.c
9129 --- lighttpd-1.4.11/src/fdevent_linux_rtsig.c   2005-11-21 19:56:11.000000000 +0200
9130 +++ lighttpd-1.4.12/src/fdevent_linux_rtsig.c   2006-07-11 21:23:40.000000000 +0300
9131 @@ -1,6 +1,5 @@
9132  #include <sys/types.h>
9133  
9134 -#include <unistd.h>
9135  #include <stdlib.h>
9136  #include <stdio.h>
9137  #include <string.h>
9138 @@ -14,6 +13,7 @@
9139  #include "fdevent.h"
9140  #include "settings.h"
9141  #include "buffer.h"
9142 +#include "sys-process.h"
9143  
9144  #ifdef USE_LINUX_SIGIO
9145  static void fdevent_linux_rtsig_free(fdevents *ev) {
9146 @@ -26,19 +26,19 @@
9147  
9148  static int fdevent_linux_rtsig_event_del(fdevents *ev, int fde_ndx, int fd) {
9149         if (fde_ndx < 0) return -1;
9150 -       
9151 +
9152         if ((size_t)fde_ndx >= ev->used) {
9153                 fprintf(stderr, "%s.%d: del! out of range %d %zu\n", __FILE__, __LINE__, fde_ndx, ev->used);
9154                 SEGFAULT();
9155         }
9156 -       
9157 +
9158         if (ev->pollfds[fde_ndx].fd == fd) {
9159                 size_t k = fde_ndx;
9160 -               
9161 +
9162                 ev->pollfds[k].fd = -1;
9163  
9164                 bitset_clear_bit(ev->sigbset, fd);
9165 -               
9166 +
9167                 if (ev->unused.size == 0) {
9168                         ev->unused.size = 16;
9169                         ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
9170 @@ -46,29 +46,29 @@
9171                         ev->unused.size += 16;
9172                         ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
9173                 }
9174 -               
9175 +
9176                 ev->unused.ptr[ev->unused.used++] = k;
9177         } else {
9178                 fprintf(stderr, "%s.%d: del! %d %d\n", __FILE__, __LINE__, ev->pollfds[fde_ndx].fd, fd);
9179 -               
9180 +
9181                 SEGFAULT();
9182         }
9183 -       
9184 +
9185         return -1;
9186  }
9187  
9188  #if 0
9189  static int fdevent_linux_rtsig_event_compress(fdevents *ev) {
9190         size_t j;
9191 -       
9192 +
9193         if (ev->used == 0) return 0;
9194         if (ev->unused.used != 0) return 0;
9195 -       
9196 +
9197         for (j = ev->used - 1; j + 1 > 0; j--) {
9198                 if (ev->pollfds[j].fd == -1) ev->used--;
9199         }
9200 -       
9201 -       
9202 +
9203 +
9204         return 0;
9205  }
9206  #endif
9207 @@ -78,21 +78,21 @@
9208         if (fde_ndx != -1) {
9209                 if (ev->pollfds[fde_ndx].fd == fd) {
9210                         ev->pollfds[fde_ndx].events = events;
9211 -                       
9212 +
9213                         return fde_ndx;
9214                 }
9215                 fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd);
9216                 SEGFAULT();
9217         }
9218 -       
9219 +
9220         if (ev->unused.used > 0) {
9221                 int k = ev->unused.ptr[--ev->unused.used];
9222 -               
9223 +
9224                 ev->pollfds[k].fd = fd;
9225                 ev->pollfds[k].events = events;
9226  
9227                 bitset_set_bit(ev->sigbset, fd);
9228 -               
9229 +
9230                 return k;
9231         } else {
9232                 if (ev->size == 0) {
9233 @@ -102,12 +102,12 @@
9234                         ev->size += 16;
9235                         ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
9236                 }
9237 -               
9238 +
9239                 ev->pollfds[ev->used].fd = fd;
9240                 ev->pollfds[ev->used].events = events;
9241  
9242                 bitset_set_bit(ev->sigbset, fd);
9243 -       
9244 +
9245                 return ev->used++;
9246         }
9247  }
9248 @@ -115,20 +115,20 @@
9249  static int fdevent_linux_rtsig_poll(fdevents *ev, int timeout_ms) {
9250         struct timespec ts;
9251         int r;
9252 -       
9253 +
9254  #if 0
9255         fdevent_linux_rtsig_event_compress(ev);
9256  #endif
9257 -       
9258 +
9259         ev->in_sigio = 1;
9260 -               
9261 +
9262         ts.tv_sec =  timeout_ms / 1000;
9263         ts.tv_nsec = (timeout_ms % 1000) * 1000000;
9264         r = sigtimedwait(&(ev->sigset), &(ev->siginfo), &(ts));
9265 -               
9266 -       if (r == -1) { 
9267 +
9268 +       if (r == -1) {
9269                 if (errno == EAGAIN) return 0;
9270 -               return r; 
9271 +               return r;
9272         } else if (r == SIGIO) {
9273                 struct sigaction act;
9274  
9275 @@ -140,7 +140,7 @@
9276                 /* re-enable the signal queue */
9277                 act.sa_handler = SIG_DFL;
9278                 sigaction(ev->signum, &act, NULL);
9279 -               
9280 +
9281                 ev->in_sigio = 0;
9282                 r = poll(ev->pollfds, ev->used, timeout_ms);
9283  
9284 @@ -162,12 +162,12 @@
9285                 if (ev->siginfo.si_band == POLLERR) {
9286                         fprintf(stderr, "event: %d %02lx %02x %s\n", ev->siginfo.si_fd, ev->siginfo.si_band, errno, strerror(errno));
9287                 }
9288 -#  endif               
9289 +#  endif
9290                 if (ndx != 0) {
9291                         fprintf(stderr, "+\n");
9292                         return 0;
9293                 }
9294 -               
9295 +
9296                 return ev->siginfo.si_band & 0x3f;
9297         } else {
9298                 if (ndx >= ev->used) {
9299 @@ -188,13 +188,13 @@
9300  
9301  static int fdevent_linux_rtsig_fcntl_set(fdevents *ev, int fd) {
9302         static pid_t pid = 0;
9303 -       
9304 +
9305         if (pid == 0) pid = getpid();
9306 -       
9307 +
9308         if (-1 == fcntl(fd, F_SETSIG, ev->signum)) return -1;
9309 -       
9310 +
9311         if (-1 == fcntl(fd, F_SETOWN, (int) pid)) return -1;
9312 -       
9313 +
9314         return fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK | O_RDWR);
9315  }
9316  
9317 @@ -205,12 +205,12 @@
9318                 return -1;
9319         } else {
9320                 size_t i;
9321 -               
9322 +
9323                 i = (ndx < 0) ? 0 : ndx + 1;
9324                 for (; i < ev->used; i++) {
9325                         if (ev->pollfds[i].revents) break;
9326                 }
9327 -               
9328 +
9329                 return i;
9330         }
9331  }
9332 @@ -219,34 +219,34 @@
9333         ev->type = FDEVENT_HANDLER_LINUX_RTSIG;
9334  #define SET(x) \
9335         ev->x = fdevent_linux_rtsig_##x;
9336 -       
9337 +
9338         SET(free);
9339         SET(poll);
9340 -       
9341 +
9342         SET(event_del);
9343         SET(event_add);
9344 -       
9345 +
9346         SET(event_next_fdndx);
9347         SET(fcntl_set);
9348         SET(event_get_fd);
9349         SET(event_get_revent);
9350 -       
9351 +
9352         ev->signum = SIGRTMIN + 1;
9353 -       
9354 +
9355         sigemptyset(&(ev->sigset));
9356         sigaddset(&(ev->sigset), ev->signum);
9357         sigaddset(&(ev->sigset), SIGIO);
9358         if (-1 == sigprocmask(SIG_BLOCK, &(ev->sigset), NULL)) {
9359                 fprintf(stderr, "%s.%d: sigprocmask failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
9360                         __FILE__, __LINE__, strerror(errno));
9361 -               
9362 +
9363                 return -1;
9364         }
9365 -       
9366 +
9367         ev->in_sigio = 1;
9368  
9369         ev->sigbset = bitset_init(ev->maxfds);
9370 -       
9371 +
9372         return 0;
9373  }
9374  #else
9375 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/fdevent_linux_sysepoll.c lighttpd-1.4.12/src/fdevent_linux_sysepoll.c
9376 --- lighttpd-1.4.11/src/fdevent_linux_sysepoll.c        2005-09-30 20:29:27.000000000 +0300
9377 +++ lighttpd-1.4.12/src/fdevent_linux_sysepoll.c        2006-07-11 21:23:40.000000000 +0300
9378 @@ -1,6 +1,5 @@
9379  #include <sys/types.h>
9380  
9381 -#include <unistd.h>
9382  #include <stdlib.h>
9383  #include <stdio.h>
9384  #include <string.h>
9385 @@ -12,6 +11,8 @@
9386  #include "settings.h"
9387  #include "buffer.h"
9388  
9389 +#include "sys-files.h"
9390 +
9391  #ifdef USE_LINUX_EPOLL
9392  static void fdevent_linux_sysepoll_free(fdevents *ev) {
9393         close(ev->epoll_fd);
9394 @@ -20,36 +21,36 @@
9395  
9396  static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) {
9397         struct epoll_event ep;
9398 -       
9399 +
9400         if (fde_ndx < 0) return -1;
9401 -       
9402 +
9403         memset(&ep, 0, sizeof(ep));
9404 -       
9405 +
9406         ep.data.fd = fd;
9407         ep.data.ptr = NULL;
9408 -       
9409 +
9410         if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, &ep)) {
9411                 fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno));
9412 -               
9413 +
9414                 SEGFAULT();
9415 -               
9416 +
9417                 return 0;
9418         }
9419 -       
9420 -       
9421 +
9422 +
9423         return -1;
9424  }
9425  
9426  static int fdevent_linux_sysepoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9427         struct epoll_event ep;
9428         int add = 0;
9429 -       
9430 +
9431         if (fde_ndx == -1) add = 1;
9432 -       
9433 +
9434         memset(&ep, 0, sizeof(ep));
9435 -       
9436 +
9437         ep.events = 0;
9438 -       
9439 +
9440         if (events & FDEVENT_IN)  ep.events |= EPOLLIN;
9441         if (events & FDEVENT_OUT) ep.events |= EPOLLOUT;
9442  
9443 @@ -60,20 +61,20 @@
9444          * sent.
9445          *
9446          */
9447 -       
9448 +
9449         ep.events |= EPOLLERR | EPOLLHUP /* | EPOLLET */;
9450 -       
9451 +
9452         ep.data.ptr = NULL;
9453         ep.data.fd = fd;
9454 -       
9455 +
9456         if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) {
9457                 fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno));
9458 -               
9459 +
9460                 SEGFAULT();
9461 -               
9462 +
9463                 return 0;
9464         }
9465 -       
9466 +
9467         return fd;
9468  }
9469  
9470 @@ -83,14 +84,14 @@
9471  
9472  static int fdevent_linux_sysepoll_event_get_revent(fdevents *ev, size_t ndx) {
9473         int events = 0, e;
9474 -       
9475 +
9476         e = ev->epoll_events[ndx].events;
9477         if (e & EPOLLIN) events |= FDEVENT_IN;
9478         if (e & EPOLLOUT) events |= FDEVENT_OUT;
9479         if (e & EPOLLERR) events |= FDEVENT_ERR;
9480         if (e & EPOLLHUP) events |= FDEVENT_HUP;
9481         if (e & EPOLLPRI) events |= FDEVENT_PRI;
9482 -       
9483 +
9484         return e;
9485  }
9486  
9487 @@ -98,17 +99,17 @@
9488  # if 0
9489         fprintf(stderr, "%s.%d: %d, %d\n", __FILE__, __LINE__, ndx, ev->epoll_events[ndx].data.fd);
9490  # endif
9491 -       
9492 +
9493         return ev->epoll_events[ndx].data.fd;
9494  }
9495  
9496  static int fdevent_linux_sysepoll_event_next_fdndx(fdevents *ev, int ndx) {
9497         size_t i;
9498 -       
9499 +
9500         UNUSED(ev);
9501  
9502         i = (ndx < 0) ? 0 : ndx + 1;
9503 -       
9504 +
9505         return i;
9506  }
9507  
9508 @@ -116,17 +117,17 @@
9509         ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL;
9510  #define SET(x) \
9511         ev->x = fdevent_linux_sysepoll_##x;
9512 -       
9513 +
9514         SET(free);
9515         SET(poll);
9516 -       
9517 +
9518         SET(event_del);
9519         SET(event_add);
9520 -       
9521 +
9522         SET(event_next_fdndx);
9523         SET(event_get_fd);
9524         SET(event_get_revent);
9525 -       
9526 +
9527         if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) {
9528                 fprintf(stderr, "%s.%d: epoll_create failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
9529                         __FILE__, __LINE__, strerror(errno));
9530 @@ -154,7 +155,7 @@
9531  
9532         fprintf(stderr, "%s.%d: linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
9533                 __FILE__, __LINE__);
9534 -       
9535 +
9536         return -1;
9537  }
9538  #endif
9539 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/fdevent_poll.c lighttpd-1.4.12/src/fdevent_poll.c
9540 --- lighttpd-1.4.11/src/fdevent_poll.c  2005-11-18 13:59:16.000000000 +0200
9541 +++ lighttpd-1.4.12/src/fdevent_poll.c  2006-07-11 21:23:40.000000000 +0300
9542 @@ -1,6 +1,5 @@
9543  #include <sys/types.h>
9544  
9545 -#include <unistd.h>
9546  #include <stdlib.h>
9547  #include <stdio.h>
9548  #include <string.h>
9549 @@ -20,19 +19,19 @@
9550  
9551  static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) {
9552         if (fde_ndx < 0) return -1;
9553 -       
9554 +
9555         if ((size_t)fde_ndx >= ev->used) {
9556                 fprintf(stderr, "%s.%d: del! out of range %d %zd\n", __FILE__, __LINE__, fde_ndx, ev->used);
9557                 SEGFAULT();
9558         }
9559 -       
9560 +
9561         if (ev->pollfds[fde_ndx].fd == fd) {
9562                 size_t k = fde_ndx;
9563 -               
9564 +
9565                 ev->pollfds[k].fd = -1;
9566                 /* ev->pollfds[k].events = 0; */
9567                 /* ev->pollfds[k].revents = 0; */
9568 -               
9569 +
9570                 if (ev->unused.size == 0) {
9571                         ev->unused.size = 16;
9572                         ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
9573 @@ -40,47 +39,47 @@
9574                         ev->unused.size += 16;
9575                         ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
9576                 }
9577 -               
9578 +
9579                 ev->unused.ptr[ev->unused.used++] = k;
9580         } else {
9581                 SEGFAULT();
9582         }
9583 -       
9584 +
9585         return -1;
9586  }
9587  
9588  #if 0
9589  static int fdevent_poll_event_compress(fdevents *ev) {
9590         size_t j;
9591 -       
9592 +
9593         if (ev->used == 0) return 0;
9594         if (ev->unused.used != 0) return 0;
9595 -       
9596 +
9597         for (j = ev->used - 1; j + 1 > 0 && ev->pollfds[j].fd == -1; j--) ev->used--;
9598 -       
9599 +
9600         return 0;
9601  }
9602  #endif
9603  
9604  static int fdevent_poll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9605         /* known index */
9606 -       
9607 +
9608         if (fde_ndx != -1) {
9609                 if (ev->pollfds[fde_ndx].fd == fd) {
9610                         ev->pollfds[fde_ndx].events = events;
9611 -                       
9612 +
9613                         return fde_ndx;
9614                 }
9615                 fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd);
9616                 SEGFAULT();
9617         }
9618 -       
9619 +
9620         if (ev->unused.used > 0) {
9621                 int k = ev->unused.ptr[--ev->unused.used];
9622 -               
9623 +
9624                 ev->pollfds[k].fd = fd;
9625                 ev->pollfds[k].events = events;
9626 -               
9627 +
9628                 return k;
9629         } else {
9630                 if (ev->size == 0) {
9631 @@ -90,10 +89,10 @@
9632                         ev->size += 16;
9633                         ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
9634                 }
9635 -               
9636 +
9637                 ev->pollfds[ev->used].fd = fd;
9638                 ev->pollfds[ev->used].events = events;
9639 -               
9640 +
9641                 return ev->used++;
9642         }
9643  }
9644 @@ -109,12 +108,12 @@
9645         int r, poll_r;
9646         if (ndx >= ev->used) {
9647                 fprintf(stderr, "%s.%d: dying because: event: %zd >= %zd\n", __FILE__, __LINE__, ndx, ev->used);
9648 -               
9649 +
9650                 SEGFAULT();
9651 -               
9652 +
9653                 return 0;
9654         }
9655 -       
9656 +
9657         if (ev->pollfds[ndx].revents & POLLNVAL) {
9658                 /* should never happen */
9659                 SEGFAULT();
9660 @@ -131,7 +130,7 @@
9661         if (poll_r & POLLHUP) r |= FDEVENT_HUP;
9662         if (poll_r & POLLNVAL) r |= FDEVENT_NVAL;
9663         if (poll_r & POLLPRI) r |= FDEVENT_PRI;
9664 -       
9665 +
9666         return ev->pollfds[ndx].revents;
9667  }
9668  
9669 @@ -141,12 +140,12 @@
9670  
9671  static int fdevent_poll_event_next_fdndx(fdevents *ev, int ndx) {
9672         size_t i;
9673 -       
9674 +
9675         i = (ndx < 0) ? 0 : ndx + 1;
9676         for (; i < ev->used; i++) {
9677                 if (ev->pollfds[i].revents) break;
9678         }
9679 -       
9680 +
9681         return i;
9682  }
9683  
9684 @@ -154,17 +153,17 @@
9685         ev->type = FDEVENT_HANDLER_POLL;
9686  #define SET(x) \
9687         ev->x = fdevent_poll_##x;
9688 -       
9689 +
9690         SET(free);
9691         SET(poll);
9692 -       
9693 +
9694         SET(event_del);
9695         SET(event_add);
9696 -       
9697 +
9698         SET(event_next_fdndx);
9699         SET(event_get_fd);
9700         SET(event_get_revent);
9701 -       
9702 +
9703         return 0;
9704  }
9705  
9706 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/fdevent_select.c lighttpd-1.4.12/src/fdevent_select.c
9707 --- lighttpd-1.4.11/src/fdevent_select.c        2005-08-31 11:12:46.000000000 +0300
9708 +++ lighttpd-1.4.12/src/fdevent_select.c        2006-07-11 21:23:40.000000000 +0300
9709 @@ -1,18 +1,19 @@
9710 -#include <sys/time.h>
9711  #include <sys/types.h>
9712  
9713 -#include <unistd.h>
9714  #include <stdlib.h>
9715  #include <string.h>
9716  #include <errno.h>
9717  #include <signal.h>
9718  #include <fcntl.h>
9719  #include <assert.h>
9720 +#include <stdio.h>
9721  
9722  #include "fdevent.h"
9723  #include "settings.h"
9724  #include "buffer.h"
9725  
9726 +#include "sys-socket.h"
9727 +
9728  #ifdef USE_SELECT
9729  
9730  static int fdevent_select_reset(fdevents *ev) {
9731 @@ -38,7 +39,9 @@
9732         UNUSED(fde_ndx);
9733  
9734         /* we should be protected by max-fds, but you never know */
9735 +#ifndef _WIN32
9736         assert(fd < FD_SETSIZE);
9737 +#endif
9738  
9739         if (events & FDEVENT_IN) {
9740                 FD_SET(fd, &(ev->select_set_read));
9741 @@ -49,28 +52,28 @@
9742                 FD_SET(fd, &(ev->select_set_write));
9743         }
9744         FD_SET(fd, &(ev->select_set_error));
9745 -       
9746 +
9747         if (fd > ev->select_max_fd) ev->select_max_fd = fd;
9748 -       
9749 +
9750         return fd;
9751  }
9752  
9753  static int fdevent_select_poll(fdevents *ev, int timeout_ms) {
9754         struct timeval tv;
9755 -       
9756 +
9757         tv.tv_sec =  timeout_ms / 1000;
9758         tv.tv_usec = (timeout_ms % 1000) * 1000;
9759 -       
9760 +
9761         ev->select_read = ev->select_set_read;
9762         ev->select_write = ev->select_set_write;
9763         ev->select_error = ev->select_set_error;
9764 -       
9765 +
9766         return select(ev->select_max_fd + 1, &(ev->select_read), &(ev->select_write), &(ev->select_error), &tv);
9767  }
9768  
9769  static int fdevent_select_event_get_revent(fdevents *ev, size_t ndx) {
9770         int revents = 0;
9771 -       
9772 +
9773         if (FD_ISSET(ndx, &(ev->select_read))) {
9774                 revents |= FDEVENT_IN;
9775         }
9776 @@ -80,7 +83,7 @@
9777         if (FD_ISSET(ndx, &(ev->select_error))) {
9778                 revents |= FDEVENT_ERR;
9779         }
9780 -       
9781 +
9782         return revents;
9783  }
9784  
9785 @@ -92,15 +95,15 @@
9786  
9787  static int fdevent_select_event_next_fdndx(fdevents *ev, int ndx) {
9788         int i;
9789 -       
9790 +
9791         i = (ndx < 0) ? 0 : ndx + 1;
9792 -       
9793 +
9794         for (; i < ev->select_max_fd + 1; i++) {
9795                 if (FD_ISSET(i, &(ev->select_read))) break;
9796                 if (FD_ISSET(i, &(ev->select_write))) break;
9797                 if (FD_ISSET(i, &(ev->select_error))) break;
9798         }
9799 -       
9800 +
9801         return i;
9802  }
9803  
9804 @@ -108,17 +111,17 @@
9805         ev->type = FDEVENT_HANDLER_SELECT;
9806  #define SET(x) \
9807         ev->x = fdevent_select_##x;
9808 -       
9809 +
9810         SET(reset);
9811         SET(poll);
9812 -       
9813 +
9814         SET(event_del);
9815         SET(event_add);
9816 -       
9817 +
9818         SET(event_next_fdndx);
9819         SET(event_get_fd);
9820         SET(event_get_revent);
9821 -       
9822 +
9823         return 0;
9824  }
9825  
9826 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/fdevent_solaris_devpoll.c lighttpd-1.4.12/src/fdevent_solaris_devpoll.c
9827 --- lighttpd-1.4.11/src/fdevent_solaris_devpoll.c       2005-09-01 10:45:26.000000000 +0300
9828 +++ lighttpd-1.4.12/src/fdevent_solaris_devpoll.c       2006-07-11 21:23:40.000000000 +0300
9829 @@ -1,6 +1,5 @@
9830  #include <sys/types.h>
9831  
9832 -#include <unistd.h>
9833  #include <stdlib.h>
9834  #include <stdio.h>
9835  #include <string.h>
9836 @@ -23,55 +22,55 @@
9837  
9838  static int fdevent_solaris_devpoll_event_del(fdevents *ev, int fde_ndx, int fd) {
9839         struct pollfd pfd;
9840 -               
9841 +
9842         if (fde_ndx < 0) return -1;
9843 -       
9844 +
9845         pfd.fd = fd;
9846         pfd.events = POLLREMOVE;
9847         pfd.revents = 0;
9848 -       
9849 +
9850         if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
9851 -               fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n", 
9852 -                       __FILE__, __LINE__, 
9853 +               fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
9854 +                       __FILE__, __LINE__,
9855                         fd, strerror(errno));
9856 -               
9857 +
9858                 return -1;
9859         }
9860 -       
9861 +
9862         return -1;
9863  }
9864  
9865  static int fdevent_solaris_devpoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9866         struct pollfd pfd;
9867         int add = 0;
9868 -               
9869 +
9870         if (fde_ndx == -1) add = 1;
9871 -       
9872 +
9873         pfd.fd = fd;
9874         pfd.events = events;
9875         pfd.revents = 0;
9876 -       
9877 +
9878         if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
9879 -               fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n", 
9880 -                       __FILE__, __LINE__, 
9881 +               fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
9882 +                       __FILE__, __LINE__,
9883                         fd, strerror(errno));
9884 -               
9885 +
9886                 return -1;
9887         }
9888 -       
9889 +
9890         return fd;
9891  }
9892  
9893  static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) {
9894         struct dvpoll dopoll;
9895         int ret;
9896 -       
9897 +
9898         dopoll.dp_timeout = timeout_ms;
9899         dopoll.dp_nfds = ev->maxfds;
9900         dopoll.dp_fds = ev->devpollfds;
9901 -       
9902 +
9903         ret = ioctl(ev->devpoll_fd, DP_POLL, &dopoll);
9904 -       
9905 +
9906         return ret;
9907  }
9908  
9909 @@ -85,11 +84,11 @@
9910  
9911  static int fdevent_solaris_devpoll_event_next_fdndx(fdevents *ev, int last_ndx) {
9912         size_t i;
9913 -       
9914 +
9915         UNUSED(ev);
9916  
9917         i = (last_ndx < 0) ? 0 : last_ndx + 1;
9918 -       
9919 +
9920         return i;
9921  }
9922  
9923 @@ -117,20 +116,20 @@
9924         ev->type = FDEVENT_HANDLER_SOLARIS_DEVPOLL;
9925  #define SET(x) \
9926         ev->x = fdevent_solaris_devpoll_##x;
9927 -       
9928 +
9929         SET(free);
9930         SET(poll);
9931         SET(reset);
9932 -       
9933 +
9934         SET(event_del);
9935         SET(event_add);
9936 -       
9937 +
9938         SET(event_next_fdndx);
9939         SET(event_get_fd);
9940         SET(event_get_revent);
9941 -       
9942 +
9943         ev->devpollfds = malloc(sizeof(*ev->devpollfds) * ev->maxfds);
9944 -       
9945 +
9946         if ((ev->devpoll_fd = open("/dev/poll", O_RDWR)) < 0) {
9947                 fprintf(stderr, "%s.%d: opening /dev/poll failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
9948                         __FILE__, __LINE__, strerror(errno));
9949 @@ -152,7 +151,7 @@
9950  
9951         fprintf(stderr, "%s.%d: solaris-devpoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
9952                         __FILE__, __LINE__);
9953 -       
9954 +
9955         return -1;
9956  }
9957  #endif
9958 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/http-header-glue.c lighttpd-1.4.12/src/http-header-glue.c
9959 --- lighttpd-1.4.11/src/http-header-glue.c      2006-02-08 15:31:36.000000000 +0200
9960 +++ lighttpd-1.4.12/src/http-header-glue.c      2006-07-11 21:23:40.000000000 +0300
9961 @@ -45,20 +45,20 @@
9962  #   ifdef HAVE_STRUCT_SOCKADDR_STORAGE
9963  static size_t get_sa_len(const struct sockaddr *addr) {
9964         switch (addr->sa_family) {
9965 -               
9966 +
9967  #    ifdef AF_INET
9968         case AF_INET:
9969                 return (sizeof (struct sockaddr_in));
9970  #    endif
9971 -               
9972 +
9973  #    ifdef AF_INET6
9974         case AF_INET6:
9975                 return (sizeof (struct sockaddr_in6));
9976  #    endif
9977 -               
9978 +
9979         default:
9980                 return (sizeof (struct sockaddr));
9981 -               
9982 +
9983         }
9984  }
9985  #    define SA_LEN(addr)   (get_sa_len(addr))
9986 @@ -74,7 +74,7 @@
9987  
9988  int response_header_insert(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
9989         data_string *ds;
9990 -       
9991 +
9992         UNUSED(srv);
9993  
9994         if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
9995 @@ -82,32 +82,32 @@
9996         }
9997         buffer_copy_string_len(ds->key, key, keylen);
9998         buffer_copy_string_len(ds->value, value, vallen);
9999 -       
10000 +
10001         array_insert_unique(con->response.headers, (data_unset *)ds);
10002 -       
10003 +
10004         return 0;
10005  }
10006  
10007  int response_header_overwrite(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
10008         data_string *ds;
10009 -       
10010 +
10011         UNUSED(srv);
10012  
10013         /* if there already is a key by this name overwrite the value */
10014         if (NULL != (ds = (data_string *)array_get_element(con->response.headers, key))) {
10015                 buffer_copy_string(ds->value, value);
10016 -               
10017 +
10018                 return 0;
10019         }
10020 -       
10021 +
10022         return response_header_insert(srv, con, key, keylen, value, vallen);
10023  }
10024  
10025  int http_response_redirect_to_directory(server *srv, connection *con) {
10026         buffer *o;
10027 -       
10028 +
10029         o = buffer_init();
10030 -       
10031 +
10032         if (con->conf.is_ssl) {
10033                 buffer_copy_string(o, "https://");
10034         } else {
10035 @@ -123,36 +123,36 @@
10036  #endif
10037                 sock_addr our_addr;
10038                 socklen_t our_addr_len;
10039 -               
10040 +
10041                 our_addr_len = sizeof(our_addr);
10042 -               
10043 +
10044                 if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
10045                         con->http_status = 500;
10046 -                       
10047 +
10048                         log_error_write(srv, __FILE__, __LINE__, "ss",
10049                                         "can't get sockname", strerror(errno));
10050 -                       
10051 +
10052                         buffer_free(o);
10053                         return 0;
10054                 }
10055 -               
10056 -               
10057 +
10058 +
10059                 /* Lookup name: secondly try to get hostname for bind address */
10060                 switch(our_addr.plain.sa_family) {
10061  #ifdef HAVE_IPV6
10062                 case AF_INET6:
10063 -                       if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6), 
10064 -                                            SA_LEN((const struct sockaddr *)&our_addr.ipv6), 
10065 +                       if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6),
10066 +                                            SA_LEN((const struct sockaddr *)&our_addr.ipv6),
10067                                              hbuf, sizeof(hbuf), NULL, 0, 0)) {
10068 -                               
10069 +
10070                                 char dst[INET6_ADDRSTRLEN];
10071 -                               
10072 +
10073                                 log_error_write(srv, __FILE__, __LINE__,
10074                                                 "SSSS", "NOTICE: getnameinfo failed: ",
10075                                                 strerror(errno), ", using ip-address instead");
10076 -                               
10077 -                               buffer_append_string(o, 
10078 -                                                    inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr, 
10079 +
10080 +                               buffer_append_string(o,
10081 +                                                    inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr,
10082                                                                dst, sizeof(dst)));
10083                         } else {
10084                                 buffer_append_string(o, hbuf);
10085 @@ -164,7 +164,7 @@
10086                                 log_error_write(srv, __FILE__, __LINE__,
10087                                                 "SdSS", "NOTICE: gethostbyaddr failed: ",
10088                                                 h_errno, ", using ip-address instead");
10089 -                               
10090 +
10091                                 buffer_append_string(o, inet_ntoa(our_addr.ipv4.sin_addr));
10092                         } else {
10093                                 buffer_append_string(o, he->h_name);
10094 @@ -173,12 +173,12 @@
10095                 default:
10096                         log_error_write(srv, __FILE__, __LINE__,
10097                                         "S", "ERROR: unsupported address-type");
10098 -                       
10099 +
10100                         buffer_free(o);
10101                         return -1;
10102                 }
10103 -               
10104 -               if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) || 
10105 +
10106 +               if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) ||
10107                       (con->conf.is_ssl == 1 && srv->srvconf.port == 443))) {
10108                         buffer_append_string(o, ":");
10109                         buffer_append_long(o, srv->srvconf.port);
10110 @@ -190,41 +190,41 @@
10111                 buffer_append_string(o, "?");
10112                 buffer_append_string_buffer(o, con->uri.query);
10113         }
10114 -       
10115 +
10116         response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(o));
10117 -       
10118 +
10119         con->http_status = 301;
10120         con->file_finished = 1;
10121 -       
10122 +
10123         buffer_free(o);
10124 -       
10125 +
10126         return 0;
10127  }
10128  
10129  buffer * strftime_cache_get(server *srv, time_t last_mod) {
10130         struct tm *tm;
10131         size_t i;
10132 -               
10133 +
10134         for (i = 0; i < FILE_CACHE_MAX; i++) {
10135                 /* found cache-entry */
10136                 if (srv->mtime_cache[i].mtime == last_mod) return srv->mtime_cache[i].str;
10137 -                               
10138 +
10139                 /* found empty slot */
10140                 if (srv->mtime_cache[i].mtime == 0) break;
10141         }
10142 -       
10143 +
10144         if (i == FILE_CACHE_MAX) {
10145                 i = 0;
10146         }
10147 -               
10148 +
10149         srv->mtime_cache[i].mtime = last_mod;
10150         buffer_prepare_copy(srv->mtime_cache[i].str, 1024);
10151         tm = gmtime(&(srv->mtime_cache[i].mtime));
10152 -       srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr, 
10153 +       srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr,
10154                                                  srv->mtime_cache[i].str->size - 1,
10155                                                  "%a, %d %b %Y %H:%M:%S GMT", tm);
10156         srv->mtime_cache[i].str->used++;
10157 -       
10158 +
10159         return srv->mtime_cache[i].str;
10160  }
10161  
10162 @@ -239,56 +239,60 @@
10163          *    request. That is, if no entity tags match, then the server MUST NOT
10164          *    return a 304 (Not Modified) response.
10165          */
10166 -       
10167 +
10168         /* last-modified handling */
10169         if (con->request.http_if_none_match) {
10170                 if (etag_is_equal(con->physical.etag, con->request.http_if_none_match)) {
10171 -                       if (con->request.http_method == HTTP_METHOD_GET || 
10172 +                       if (con->request.http_method == HTTP_METHOD_GET ||
10173                             con->request.http_method == HTTP_METHOD_HEAD) {
10174 -                               
10175 +
10176                                 /* check if etag + last-modified */
10177                                 if (con->request.http_if_modified_since) {
10178                                         size_t used_len;
10179                                         char *semicolon;
10180 -                                       
10181 +
10182                                         if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
10183                                                 used_len = strlen(con->request.http_if_modified_since);
10184                                         } else {
10185                                                 used_len = semicolon - con->request.http_if_modified_since;
10186                                         }
10187 -                                       
10188 +
10189                                         if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
10190                                                 con->http_status = 304;
10191                                                 return HANDLER_FINISHED;
10192                                         } else {
10193 +#ifdef HAVE_STRPTIME
10194                                                 char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
10195 +                                               time_t t_header, t_file;
10196 +                                               struct tm tm;
10197  
10198 -                                               /* convert to timestamp */
10199 -                                               if (used_len < sizeof(buf)) {
10200 -                                                       time_t t_header, t_file;
10201 -                                                       struct tm tm;
10202 -                                                       
10203 -                                                       strncpy(buf, con->request.http_if_modified_since, used_len);
10204 -                                                       buf[used_len] = '\0';
10205 -                                                       
10206 -                                                       strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10207 -                                                       t_header = mktime(&tm);
10208 -                                                       
10209 -                                                       strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10210 -                                                       t_file = mktime(&tm);
10211 -
10212 -                                                       if (t_file > t_header) {
10213 -                                                               con->http_status = 304;
10214 -                                                               return HANDLER_FINISHED;
10215 -                                                       }
10216 -                                               } else {
10217 -                                                       log_error_write(srv, __FILE__, __LINE__, "ssdd", 
10218 -                                                                       "DEBUG: Last-Modified check failed as the received timestamp was too long:", 
10219 +                                               /* check if we can safely copy the string */
10220 +                                               if (used_len >= sizeof(buf)) {
10221 +                                                       log_error_write(srv, __FILE__, __LINE__, "ssdd",
10222 +                                                                       "DEBUG: Last-Modified check failed as the received timestamp was too long:",
10223                                                                         con->request.http_if_modified_since, used_len, sizeof(buf) - 1);
10224 -                                                       
10225 +
10226                                                         con->http_status = 412;
10227                                                         return HANDLER_FINISHED;
10228                                                 }
10229 +
10230 +
10231 +                                               strncpy(buf, con->request.http_if_modified_since, used_len);
10232 +                                               buf[used_len] = '\0';
10233 +
10234 +                                               strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10235 +                                               t_header = mktime(&tm);
10236 +
10237 +                                               strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10238 +                                               t_file = mktime(&tm);
10239 +
10240 +                                               if (t_file > t_header) return HANDLER_GO_ON;
10241 +
10242 +                                               con->http_status = 304;
10243 +                                               return HANDLER_FINISHED;
10244 +#else
10245 +                        return HANDLER_GO_ON;
10246 +#endif
10247                                         }
10248                                 } else {
10249                                         con->http_status = 304;
10250 @@ -302,16 +306,41 @@
10251         } else if (con->request.http_if_modified_since) {
10252                 size_t used_len;
10253                 char *semicolon;
10254 -               
10255 +
10256                 if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
10257                         used_len = strlen(con->request.http_if_modified_since);
10258                 } else {
10259                         used_len = semicolon - con->request.http_if_modified_since;
10260                 }
10261 -               
10262 +
10263                 if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
10264                         con->http_status = 304;
10265                         return HANDLER_FINISHED;
10266 +               } else {
10267 +#ifdef HAVE_STRPTIME
10268 +                       char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
10269 +                       time_t t_header, t_file;
10270 +                       struct tm tm;
10271 +
10272 +                       /* convert to timestamp */
10273 +                       if (used_len >= sizeof(buf)) return HANDLER_GO_ON;
10274 +
10275 +                       strncpy(buf, con->request.http_if_modified_since, used_len);
10276 +                       buf[used_len] = '\0';
10277 +
10278 +                       strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10279 +                       t_header = mktime(&tm);
10280 +
10281 +                       strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10282 +                       t_file = mktime(&tm);
10283 +
10284 +                       if (t_file > t_header) return HANDLER_GO_ON;
10285 +
10286 +                       con->http_status = 304;
10287 +                       return HANDLER_FINISHED;
10288 +#else
10289 +            return HANDLER_GO_ON;
10290 +#endif
10291                 }
10292         }
10293  
10294 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/http_auth.c lighttpd-1.4.12/src/http_auth.c
10295 --- lighttpd-1.4.11/src/http_auth.c     2006-02-01 13:02:52.000000000 +0200
10296 +++ lighttpd-1.4.12/src/http_auth.c     2006-07-11 21:23:40.000000000 +0300
10297 @@ -22,7 +22,6 @@
10298  #include <string.h>
10299  #include <time.h>
10300  #include <errno.h>
10301 -#include <unistd.h>
10302  #include <ctype.h>
10303  
10304  #include "server.h"
10305 @@ -31,23 +30,14 @@
10306  #include "http_auth_digest.h"
10307  #include "stream.h"
10308  
10309 +#include "sys-strings.h"
10310 +
10311  #ifdef USE_OPENSSL
10312  # include <openssl/md5.h>
10313  #else
10314  # include "md5.h"
10315  #endif
10316  
10317 -
10318 -#ifdef USE_PAM
10319 -#include <security/pam_appl.h>
10320 -#include <security/pam_misc.h>
10321 -
10322 -static struct pam_conv conv = {
10323 -       misc_conv,
10324 -               NULL
10325 -};
10326 -#endif
10327 -
10328  handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
10329  
10330  static const char base64_pad = '=';
10331 @@ -75,25 +65,25 @@
10332         unsigned char *result;
10333         int ch, j = 0, k;
10334         size_t i;
10335 -       
10336 +
10337         size_t in_len = strlen(in);
10338 -       
10339 +
10340         buffer_prepare_copy(out, in_len);
10341 -       
10342 +
10343         result = (unsigned char *)out->ptr;
10344 -       
10345 +
10346         ch = in[0];
10347         /* run through the whole string, converting as we go */
10348         for (i = 0; i < in_len; i++) {
10349                 ch = in[i];
10350 -               
10351 +
10352                 if (ch == '\0') break;
10353 -               
10354 +
10355                 if (ch == base64_pad) break;
10356 -               
10357 +
10358                 ch = base64_reverse_table[ch];
10359                 if (ch < 0) continue;
10360 -               
10361 +
10362                 switch(i % 4) {
10363                 case 0:
10364                         result[j] = ch << 2;
10365 @@ -125,168 +115,168 @@
10366                 }
10367         }
10368         result[k] = '\0';
10369 -       
10370 +
10371         out->used = k;
10372 -       
10373 +
10374         return result;
10375  }
10376  
10377  static int http_auth_get_password(server *srv, mod_auth_plugin_data *p, buffer *username, buffer *realm, buffer *password) {
10378         int ret = -1;
10379 -       
10380 +
10381         if (!username->used|| !realm->used) return -1;
10382 -       
10383 +
10384         if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
10385                 stream f;
10386                 char * f_line;
10387 -               
10388 +
10389                 if (buffer_is_empty(p->conf.auth_htdigest_userfile)) return -1;
10390 -               
10391 +
10392                 if (0 != stream_open(&f, p->conf.auth_htdigest_userfile)) {
10393                         log_error_write(srv, __FILE__, __LINE__, "sbss", "opening digest-userfile", p->conf.auth_htdigest_userfile, "failed:", strerror(errno));
10394 -                       
10395 +
10396                         return -1;
10397                 }
10398 -               
10399 +
10400                 f_line = f.start;
10401 -               
10402 +
10403                 while (f_line - f.start != f.size) {
10404                         char *f_user, *f_pwd, *e, *f_realm;
10405                         size_t u_len, pwd_len, r_len;
10406 -                       
10407 +
10408                         f_user = f_line;
10409 -                       
10410 -                       /* 
10411 +
10412 +                       /*
10413                          * htdigest format
10414 -                        * 
10415 -                        * user:realm:md5(user:realm:password) 
10416 +                        *
10417 +                        * user:realm:md5(user:realm:password)
10418                          */
10419 -                       
10420 +
10421                         if (NULL == (f_realm = memchr(f_user, ':', f.size - (f_user - f.start) ))) {
10422 -                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
10423 -                                               "parsed error in", p->conf.auth_htdigest_userfile, 
10424 +                               log_error_write(srv, __FILE__, __LINE__, "sbs",
10425 +                                               "parsed error in", p->conf.auth_htdigest_userfile,
10426                                                 "expected 'username:realm:hashed password'");
10427 -                               
10428 +
10429                                 stream_close(&f);
10430 -                               
10431 +
10432                                 return -1;
10433                         }
10434 -                       
10435 +
10436                         if (NULL == (f_pwd = memchr(f_realm + 1, ':', f.size - (f_realm + 1 - f.start)))) {
10437 -                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
10438 -                                               "parsed error in", p->conf.auth_plain_userfile, 
10439 +                               log_error_write(srv, __FILE__, __LINE__, "sbs",
10440 +                                               "parsed error in", p->conf.auth_plain_userfile,
10441                                                 "expected 'username:realm:hashed password'");
10442 -                               
10443 +
10444                                 stream_close(&f);
10445 -                               
10446 +
10447                                 return -1;
10448                         }
10449 -                       
10450 +
10451                         /* get pointers to the fields */
10452 -                       u_len = f_realm - f_user; 
10453 +                       u_len = f_realm - f_user;
10454                         f_realm++;
10455                         r_len = f_pwd - f_realm;
10456                         f_pwd++;
10457 -                       
10458 +
10459                         if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
10460                                 pwd_len = e - f_pwd;
10461                         } else {
10462                                 pwd_len = f.size - (f_pwd - f.start);
10463                         }
10464 -                       
10465 +
10466                         if (username->used - 1 == u_len &&
10467                             (realm->used - 1 == r_len) &&
10468                             (0 == strncmp(username->ptr, f_user, u_len)) &&
10469                             (0 == strncmp(realm->ptr, f_realm, r_len))) {
10470                                 /* found */
10471 -                               
10472 +
10473                                 buffer_copy_string_len(password, f_pwd, pwd_len);
10474 -                               
10475 +
10476                                 ret = 0;
10477                                 break;
10478                         }
10479 -                       
10480 +
10481                         /* EOL */
10482                         if (!e) break;
10483 -                       
10484 +
10485                         f_line = e + 1;
10486                 }
10487 -               
10488 +
10489                 stream_close(&f);
10490         } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD ||
10491                    p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
10492                 stream f;
10493                 char * f_line;
10494                 buffer *auth_fn;
10495 -               
10496 +
10497                 auth_fn = (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) ? p->conf.auth_htpasswd_userfile : p->conf.auth_plain_userfile;
10498 -               
10499 +
10500                 if (buffer_is_empty(auth_fn)) return -1;
10501 -               
10502 +
10503                 if (0 != stream_open(&f, auth_fn)) {
10504 -                       log_error_write(srv, __FILE__, __LINE__, "sbss", 
10505 +                       log_error_write(srv, __FILE__, __LINE__, "sbss",
10506                                         "opening plain-userfile", auth_fn, "failed:", strerror(errno));
10507 -                       
10508 +
10509                         return -1;
10510                 }
10511 -               
10512 +
10513                 f_line = f.start;
10514 -               
10515 +
10516                 while (f_line - f.start != f.size) {
10517                         char *f_user, *f_pwd, *e;
10518                         size_t u_len, pwd_len;
10519 -                       
10520 +
10521                         f_user = f_line;
10522 -                       
10523 -                       /* 
10524 +
10525 +                       /*
10526                          * htpasswd format
10527 -                        * 
10528 +                        *
10529                          * user:crypted passwd
10530                          */
10531 -                       
10532 +
10533                         if (NULL == (f_pwd = memchr(f_user, ':', f.size - (f_user - f.start) ))) {
10534 -                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
10535 -                                               "parsed error in", auth_fn, 
10536 +                               log_error_write(srv, __FILE__, __LINE__, "sbs",
10537 +                                               "parsed error in", auth_fn,
10538                                                 "expected 'username:hashed password'");
10539 -                               
10540 +
10541                                 stream_close(&f);
10542 -                               
10543 +
10544                                 return -1;
10545                         }
10546 -                       
10547 +
10548                         /* get pointers to the fields */
10549 -                       u_len = f_pwd - f_user; 
10550 +                       u_len = f_pwd - f_user;
10551                         f_pwd++;
10552 -                       
10553 +
10554                         if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
10555                                 pwd_len = e - f_pwd;
10556                         } else {
10557                                 pwd_len = f.size - (f_pwd - f.start);
10558                         }
10559 -                       
10560 +
10561                         if (username->used - 1 == u_len &&
10562                             (0 == strncmp(username->ptr, f_user, u_len))) {
10563                                 /* found */
10564 -                               
10565 +
10566                                 buffer_copy_string_len(password, f_pwd, pwd_len);
10567 -                               
10568 +
10569                                 ret = 0;
10570                                 break;
10571                         }
10572 -                       
10573 +
10574                         /* EOL */
10575                         if (!e) break;
10576 -                       
10577 +
10578                         f_line = e + 1;
10579                 }
10580 -               
10581 +
10582                 stream_close(&f);
10583         } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
10584                 ret = 0;
10585         } else {
10586                 return -1;
10587         }
10588 -       
10589 +
10590         return ret;
10591  }
10592  
10593 @@ -296,7 +286,7 @@
10594         int username_len;
10595         data_string *require;
10596         array *req;
10597 -       
10598 +
10599         UNUSED(group);
10600         UNUSED(host);
10601  
10602 @@ -304,12 +294,12 @@
10603         /* search auth-directives for path */
10604         for (i = 0; i < p->conf.auth_require->used; i++) {
10605                 if (p->conf.auth_require->data[i]->key->used == 0) continue;
10606 -               
10607 +
10608                 if (0 == strncmp(url, p->conf.auth_require->data[i]->key->ptr, p->conf.auth_require->data[i]->key->used - 1)) {
10609                         break;
10610                 }
10611         }
10612 -       
10613 +
10614         if (i == p->conf.auth_require->used) {
10615                 return -1;
10616         }
10617 @@ -317,72 +307,72 @@
10618         req = ((data_array *)(p->conf.auth_require->data[i]))->value;
10619  
10620         require = (data_string *)array_get_element(req, "require");
10621 -       
10622 +
10623         /* if we get here, the user we got a authed user */
10624         if (0 == strcmp(require->value->ptr, "valid-user")) {
10625                 return 0;
10626         }
10627 -       
10628 +
10629         /* user=name1|group=name3|host=name4 */
10630 -       
10631 +
10632         /* seperate the string by | */
10633  #if 0
10634         log_error_write(srv, __FILE__, __LINE__, "sb", "rules", require->value);
10635 -#endif 
10636 -       
10637 +#endif
10638 +
10639         username_len = username ? strlen(username) : 0;
10640 -       
10641 +
10642         r = rules = require->value->ptr;
10643 -       
10644 +
10645         while (1) {
10646                 const char *eq;
10647                 const char *k, *v, *e;
10648                 int k_len, v_len, r_len;
10649 -               
10650 +
10651                 e = strchr(r, '|');
10652 -               
10653 +
10654                 if (e) {
10655                         r_len = e - r;
10656                 } else {
10657                         r_len = strlen(rules) - (r - rules);
10658                 }
10659 -               
10660 +
10661                 /* from r to r + r_len is a rule */
10662 -               
10663 +
10664                 if (0 == strncmp(r, "valid-user", r_len)) {
10665 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
10666 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
10667                                         "parsing the 'require' section in 'auth.require' failed: valid-user cannot be combined with other require rules",
10668                                         require->value);
10669                         return -1;
10670                 }
10671 -               
10672 +
10673                 /* search for = in the rules */
10674                 if (NULL == (eq = strchr(r, '='))) {
10675 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
10676 -                                       "parsing the 'require' section in 'auth.require' failed: a = is missing", 
10677 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
10678 +                                       "parsing the 'require' section in 'auth.require' failed: a = is missing",
10679                                         require->value);
10680                         return -1;
10681                 }
10682 -               
10683 +
10684                 /* = out of range */
10685                 if (eq > r + r_len) {
10686 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
10687 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
10688                                         "parsing the 'require' section in 'auth.require' failed: = out of range",
10689                                         require->value);
10690 -                       
10691 +
10692                         return -1;
10693                 }
10694 -               
10695 +
10696                 /* the part before the = is user|group|host */
10697 -               
10698 +
10699                 k = r;
10700                 k_len = eq - r;
10701                 v = eq + 1;
10702                 v_len = r_len - k_len - 1;
10703 -               
10704 +
10705                 if (k_len == 4) {
10706                         if (0 == strncmp(k, "user", k_len)) {
10707 -                               if (username && 
10708 +                               if (username &&
10709                                     username_len == v_len &&
10710                                     0 == strncmp(username, v, v_len)) {
10711                                         return 0;
10712 @@ -404,19 +394,19 @@
10713                         log_error_write(srv, __FILE__, __LINE__, "s", "unknown  key");
10714                         return -1;
10715                 }
10716 -               
10717 +
10718                 if (!e) break;
10719                 r = e + 1;
10720         }
10721 -       
10722 +
10723         log_error_write(srv, __FILE__, __LINE__, "s", "nothing matched");
10724 -       
10725 +
10726         return -1;
10727  }
10728  
10729  /**
10730 - * 
10731 - * 
10732 + *
10733 + *
10734   * @param password password-string from the auth-backend
10735   * @param pw       password-string from the client
10736   */
10737 @@ -426,16 +416,16 @@
10738         UNUSED(req);
10739  
10740         if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
10741 -               /* 
10742 +               /*
10743                  * htdigest format
10744 -                * 
10745 -                * user:realm:md5(user:realm:password) 
10746 +                *
10747 +                * user:realm:md5(user:realm:password)
10748                  */
10749 -               
10750 +
10751                 MD5_CTX Md5Ctx;
10752                 HASH HA1;
10753                 char a1[256];
10754 -               
10755 +
10756                 MD5_Init(&Md5Ctx);
10757                 MD5_Update(&Md5Ctx, (unsigned char *)username->ptr, username->used - 1);
10758                 MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
10759 @@ -443,24 +433,24 @@
10760                 MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
10761                 MD5_Update(&Md5Ctx, (unsigned char *)pw, strlen(pw));
10762                 MD5_Final(HA1, &Md5Ctx);
10763 -               
10764 +
10765                 CvtHex(HA1, a1);
10766 -               
10767 +
10768                 if (0 == strcmp(password->ptr, a1)) {
10769                         return 0;
10770                 }
10771 -       } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) { 
10772 -#ifdef HAVE_CRYPT      
10773 +       } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) {
10774 +#ifdef HAVE_CRYPT
10775                 char salt[32];
10776                 char *crypted;
10777                 size_t salt_len = 0;
10778 -               /* 
10779 +               /*
10780                  * htpasswd format
10781 -                * 
10782 +                *
10783                  * user:crypted password
10784                  */
10785  
10786 -               /* 
10787 +               /*
10788                  *  Algorithm      Salt
10789                  *  CRYPT_STD_DES   2-character (Default)
10790                  *  CRYPT_EXT_DES   9-character
10791 @@ -478,7 +468,7 @@
10792                         salt_len = 2;
10793                 } else if (password->ptr[0] == '$' && password->ptr[2] == '$') {
10794                         char *dollar = NULL;
10795 -               
10796 +
10797                         if (NULL == (dollar = strchr(password->ptr + 3, '$'))) {
10798                                 fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
10799                                 return -1;
10800 @@ -495,7 +485,7 @@
10801                 strncpy(salt, password->ptr, salt_len);
10802  
10803                 salt[salt_len] = '\0';
10804 -               
10805 +
10806                 crypted = crypt(pw, salt);
10807  
10808                 if (0 == strcmp(password->ptr, crypted)) {
10809 @@ -503,40 +493,13 @@
10810                 } else {
10811                         fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
10812                 }
10813 -       
10814 -#endif 
10815 -       } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) { 
10816 +
10817 +#endif
10818 +       } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
10819                 if (0 == strcmp(password->ptr, pw)) {
10820                         return 0;
10821                 }
10822 -       } else if (p->conf.auth_backend == AUTH_BACKEND_PAM) { 
10823 -#ifdef USE_PAM
10824 -               pam_handle_t *pamh=NULL;
10825 -               int retval;
10826 -               
10827 -               retval = pam_start("lighttpd", username->ptr, &conv, &pamh);
10828 -               
10829 -               if (retval == PAM_SUCCESS)
10830 -                       retval = pam_authenticate(pamh, 0);    /* is user really user? */
10831 -               
10832 -               if (retval == PAM_SUCCESS)
10833 -                       retval = pam_acct_mgmt(pamh, 0);       /* permitted access? */
10834 -               
10835 -               /* This is where we have been authorized or not. */
10836 -               
10837 -               if (pam_end(pamh,retval) != PAM_SUCCESS) {     /* close Linux-PAM */
10838 -                       pamh = NULL;
10839 -                       log_error_write(srv, __FILE__, __LINE__, "s", "failed to release authenticator");
10840 -               }
10841 -               
10842 -               if (retval == PAM_SUCCESS) {
10843 -                       log_error_write(srv, __FILE__, __LINE__, "s", "Authenticated");
10844 -                       return 0;
10845 -               } else {
10846 -                       log_error_write(srv, __FILE__, __LINE__, "s", "Not Authenticated");
10847 -               }
10848 -#endif
10849 -       } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) { 
10850 +       } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
10851  #ifdef USE_LDAP
10852                 LDAP *ldap;
10853                 LDAPMessage *lm, *first;
10854 @@ -544,45 +507,45 @@
10855                 int ret;
10856                 char *attrs[] = { LDAP_NO_ATTRS, NULL };
10857                 size_t i;
10858 -               
10859 +
10860                 /* for now we stay synchronous */
10861 -               
10862 -               /* 
10863 +
10864 +               /*
10865                  * 1. connect anonymously (done in plugin init)
10866                  * 2. get DN for uid = username
10867                  * 3. auth against ldap server
10868                  * 4. (optional) check a field
10869                  * 5. disconnect
10870 -                * 
10871 +                *
10872                  */
10873 -               
10874 +
10875                 /* check username
10876 -                * 
10877 +                *
10878                  * we have to protect us againt username which modifies out filter in
10879                  * a unpleasant way
10880                  */
10881 -               
10882 +
10883                 for (i = 0; i < username->used - 1; i++) {
10884                         char c = username->ptr[i];
10885 -                       
10886 +
10887                         if (!isalpha(c) &&
10888                             !isdigit(c)) {
10889 -                               
10890 -                               log_error_write(srv, __FILE__, __LINE__, "sbd", 
10891 +
10892 +                               log_error_write(srv, __FILE__, __LINE__, "sbd",
10893                                         "ldap: invalid character (a-zA-Z0-9 allowed) in username:", username, i);
10894 -                               
10895 +
10896                                 return -1;
10897                         }
10898                 }
10899 -               
10900 -               
10901 -               
10902 +
10903 +
10904 +
10905                 /* build filter */
10906                 buffer_copy_string_buffer(p->ldap_filter, p->conf.ldap_filter_pre);
10907                 buffer_append_string_buffer(p->ldap_filter, username);
10908                 buffer_append_string_buffer(p->ldap_filter, p->conf.ldap_filter_post);
10909 -               
10910 -               
10911 +
10912 +
10913                 /* 2. */
10914                 if (p->conf.ldap == NULL ||
10915                     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))) {
10916 @@ -590,71 +553,71 @@
10917                                 return -1;
10918                         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))) {
10919  
10920 -                       log_error_write(srv, __FILE__, __LINE__, "sssb", 
10921 +                       log_error_write(srv, __FILE__, __LINE__, "sssb",
10922                                         "ldap:", ldap_err2string(ret), "filter:", p->ldap_filter);
10923 -                       
10924 +
10925                         return -1;
10926                         }
10927                 }
10928 -               
10929 +
10930                 if (NULL == (first = ldap_first_entry(p->conf.ldap, lm))) {
10931                         log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
10932 -                       
10933 +
10934                         ldap_msgfree(lm);
10935 -                       
10936 +
10937                         return -1;
10938                 }
10939 -               
10940 +
10941                 if (NULL == (dn = ldap_get_dn(p->conf.ldap, first))) {
10942                         log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
10943 -                       
10944 +
10945                         ldap_msgfree(lm);
10946 -                       
10947 +
10948                         return -1;
10949                 }
10950 -               
10951 +
10952                 ldap_msgfree(lm);
10953 -               
10954 -               
10955 +
10956 +
10957                 /* 3. */
10958                 if (NULL == (ldap = ldap_init(p->conf.auth_ldap_hostname->ptr, LDAP_PORT))) {
10959                         log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
10960                         return -1;
10961                 }
10962 -               
10963 +
10964                 ret = LDAP_VERSION3;
10965                 if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
10966                         log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
10967 -                       
10968 +
10969                         ldap_unbind_s(ldap);
10970 -                       
10971 +
10972                         return -1;
10973                 }
10974 -               
10975 +
10976                 if (p->conf.auth_ldap_starttls == 1) {
10977                         if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(ldap, NULL,  NULL))) {
10978                                 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
10979 -               
10980 +
10981                                 ldap_unbind_s(ldap);
10982 -                               
10983 +
10984                                 return -1;
10985                         }
10986                 }
10987  
10988 -               
10989 +
10990                 if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(ldap, dn, pw))) {
10991                         log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
10992 -                       
10993 +
10994                         ldap_unbind_s(ldap);
10995 -                       
10996 +
10997                         return -1;
10998                 }
10999 -               
11000 +
11001                 /* 5. */
11002                 ldap_unbind_s(ldap);
11003 -               
11004 +
11005                 /* everything worked, good, access granted */
11006 -               
11007 +
11008                 return 0;
11009  #endif
11010         }
11011 @@ -664,65 +627,65 @@
11012  int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
11013         buffer *username, *password;
11014         char *pw;
11015 -       
11016 +
11017         data_string *realm;
11018 -       
11019 +
11020         realm = (data_string *)array_get_element(req, "realm");
11021 -       
11022 +
11023         username = buffer_init();
11024         password = buffer_init();
11025 -       
11026 +
11027         base64_decode(username, realm_str);
11028 -       
11029 +
11030         /* r2 == user:password */
11031         if (NULL == (pw = strchr(username->ptr, ':'))) {
11032                 buffer_free(username);
11033 -               
11034 +
11035                 log_error_write(srv, __FILE__, __LINE__, "sb", ": is missing in", username);
11036 -               
11037 +
11038                 return 0;
11039         }
11040 -       
11041 +
11042         *pw++ = '\0';
11043 -       
11044 +
11045         username->used = pw - username->ptr;
11046 -       
11047 +
11048         /* copy password to r1 */
11049         if (http_auth_get_password(srv, p, username, realm->value, password)) {
11050                 buffer_free(username);
11051                 buffer_free(password);
11052 -               
11053 +
11054                 log_error_write(srv, __FILE__, __LINE__, "s", "get_password failed");
11055 -               
11056 +
11057                 return 0;
11058         }
11059 -       
11060 +
11061         /* password doesn't match */
11062         if (http_auth_basic_password_compare(srv, p, req, username, realm->value, password, pw)) {
11063                 log_error_write(srv, __FILE__, __LINE__, "sbb", "password doesn't match for", con->uri.path, username);
11064 -               
11065 +
11066                 buffer_free(username);
11067                 buffer_free(password);
11068 -               
11069 +
11070                 return 0;
11071         }
11072 -       
11073 +
11074         /* value is our allow-rules */
11075         if (http_auth_match_rules(srv, p, url->ptr, username->ptr, NULL, NULL)) {
11076                 buffer_free(username);
11077                 buffer_free(password);
11078 -               
11079 +
11080                 log_error_write(srv, __FILE__, __LINE__, "s", "rules didn't match");
11081 -               
11082 +
11083                 return 0;
11084         }
11085 -       
11086 +
11087         /* remember the username */
11088         buffer_copy_string_buffer(p->auth_user, username);
11089 -       
11090 +
11091         buffer_free(username);
11092         buffer_free(password);
11093 -       
11094 +
11095         return 1;
11096  }
11097  
11098 @@ -735,7 +698,7 @@
11099  int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
11100         char a1[256];
11101         char a2[256];
11102 -       
11103 +
11104         char *username;
11105         char *realm;
11106         char *nonce;
11107 @@ -745,18 +708,18 @@
11108         char *cnonce;
11109         char *nc;
11110         char *respons;
11111 -       
11112 +
11113         char *e, *c;
11114         const char *m = NULL;
11115         int i;
11116         buffer *password, *b, *username_buf, *realm_buf;
11117 -       
11118 +
11119         MD5_CTX Md5Ctx;
11120         HASH HA1;
11121         HASH HA2;
11122         HASH RespHash;
11123         HASHHEX HA2Hex;
11124 -       
11125 +
11126  
11127         /* init pointers */
11128  #define S(x) \
11129 @@ -771,11 +734,11 @@
11130                 { S("cnonce=") },
11131                 { S("nc=") },
11132                 { S("response=") },
11133 -               
11134 +
11135                 { NULL, 0, NULL }
11136         };
11137  #undef S
11138 -       
11139 +
11140         dkv[0].ptr = &username;
11141         dkv[1].ptr = &realm;
11142         dkv[2].ptr = &nonce;
11143 @@ -786,24 +749,24 @@
11144         dkv[7].ptr = &nc;
11145         dkv[8].ptr = &respons;
11146         dkv[9].ptr = NULL;
11147 -       
11148 +
11149         UNUSED(req);
11150 -       
11151 +
11152         for (i = 0; dkv[i].key; i++) {
11153                 *(dkv[i].ptr) = NULL;
11154         }
11155 -       
11156 -       
11157 +
11158 +
11159         if (p->conf.auth_backend != AUTH_BACKEND_HTDIGEST &&
11160             p->conf.auth_backend != AUTH_BACKEND_PLAIN) {
11161 -               log_error_write(srv, __FILE__, __LINE__, "s", 
11162 +               log_error_write(srv, __FILE__, __LINE__, "s",
11163                                 "digest: unsupported backend (only htdigest or plain)");
11164 -               
11165 +
11166                 return -1;
11167         }
11168 -       
11169 +
11170         b = buffer_init_string(realm_str);
11171 -       
11172 +
11173         /* parse credentials from client */
11174         for (c = b->ptr; *c; c++) {
11175                 /* skip whitespaces */
11176 @@ -812,18 +775,18 @@
11177  
11178                 for (i = 0; dkv[i].key; i++) {
11179                         if ((0 == strncmp(c, dkv[i].key, dkv[i].key_len))) {
11180 -                               if ((c[dkv[i].key_len] == '"') && 
11181 +                               if ((c[dkv[i].key_len] == '"') &&
11182                                     (NULL != (e = strchr(c + dkv[i].key_len + 1, '"')))) {
11183                                         /* value with "..." */
11184                                         *(dkv[i].ptr) = c + dkv[i].key_len + 1;
11185                                         c = e;
11186 -       
11187 +
11188                                         *e = '\0';
11189                                 } else if (NULL != (e = strchr(c + dkv[i].key_len, ','))) {
11190                                         /* value without "...", terminated by ',' */
11191                                         *(dkv[i].ptr) = c + dkv[i].key_len;
11192                                         c = e;
11193 -                                       
11194 +
11195                                         *e = '\0';
11196                                 } else {
11197                                         /* value without "...", terminated by EOL */
11198 @@ -833,7 +796,7 @@
11199                         }
11200                 }
11201         }
11202 -       
11203 +
11204         if (p->conf.auth_debug > 1) {
11205                 log_error_write(srv, __FILE__, __LINE__, "ss", "username", username);
11206                 log_error_write(srv, __FILE__, __LINE__, "ss", "realm", realm);
11207 @@ -845,22 +808,22 @@
11208                 log_error_write(srv, __FILE__, __LINE__, "ss", "nc", nc);
11209                 log_error_write(srv, __FILE__, __LINE__, "ss", "response", respons);
11210         }
11211 -       
11212 +
11213         /* check if everything is transmitted */
11214 -       if (!username || 
11215 +       if (!username ||
11216             !realm ||
11217             !nonce ||
11218             !uri ||
11219             (qop && (!nc || !cnonce)) ||
11220             !respons ) {
11221                 /* missing field */
11222 -               
11223 -               log_error_write(srv, __FILE__, __LINE__, "s", 
11224 +
11225 +               log_error_write(srv, __FILE__, __LINE__, "s",
11226                                 "digest: missing field");
11227                 return -1;
11228         }
11229  
11230 -       m = get_http_method_name(con->request.http_method);     
11231 +       m = get_http_method_name(con->request.http_method);
11232  
11233         /* password-string == HA1 */
11234         password = buffer_init();
11235 @@ -873,10 +836,10 @@
11236                 buffer_free(realm_buf);
11237                 return 0;
11238         }
11239 -       
11240 +
11241         buffer_free(username_buf);
11242         buffer_free(realm_buf);
11243 -       
11244 +
11245         if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
11246                 /* generate password from plain-text */
11247                 MD5_Init(&Md5Ctx);
11248 @@ -890,16 +853,16 @@
11249                 /* HA1 */
11250                 /* transform the 32-byte-hex-md5 to a 16-byte-md5 */
11251                 for (i = 0; i < HASHLEN; i++) {
11252 -                       HA1[i] = hex2int(password->ptr[i*2]) << 4; 
11253 -                       HA1[i] |= hex2int(password->ptr[i*2+1]); 
11254 +                       HA1[i] = hex2int(password->ptr[i*2]) << 4;
11255 +                       HA1[i] |= hex2int(password->ptr[i*2+1]);
11256                 }
11257         } else {
11258                 /* we already check that above */
11259                 SEGFAULT();
11260         }
11261 -       
11262 +
11263         buffer_free(password);
11264 -       
11265 +
11266         if (algorithm &&
11267             strcasecmp(algorithm, "md5-sess") == 0) {
11268                 MD5_Init(&Md5Ctx);
11269 @@ -910,9 +873,9 @@
11270                 MD5_Update(&Md5Ctx, (unsigned char *)cnonce, strlen(cnonce));
11271                 MD5_Final(HA1, &Md5Ctx);
11272         }
11273 -       
11274 +
11275         CvtHex(HA1, a1);
11276 -       
11277 +
11278         /* calculate H(A2) */
11279         MD5_Init(&Md5Ctx);
11280         MD5_Update(&Md5Ctx, (unsigned char *)m, strlen(m));
11281 @@ -924,7 +887,7 @@
11282         }
11283         MD5_Final(HA2, &Md5Ctx);
11284         CvtHex(HA2, HA2Hex);
11285 -       
11286 +
11287         /* calculate response */
11288         MD5_Init(&Md5Ctx);
11289         MD5_Update(&Md5Ctx, (unsigned char *)a1, HASHHEXLEN);
11290 @@ -942,39 +905,39 @@
11291         MD5_Update(&Md5Ctx, (unsigned char *)HA2Hex, HASHHEXLEN);
11292         MD5_Final(RespHash, &Md5Ctx);
11293         CvtHex(RespHash, a2);
11294 -       
11295 +
11296         if (0 != strcmp(a2, respons)) {
11297                 /* digest not ok */
11298 -               
11299 +
11300                 if (p->conf.auth_debug) {
11301 -                       log_error_write(srv, __FILE__, __LINE__, "sss", 
11302 +                       log_error_write(srv, __FILE__, __LINE__, "sss",
11303                                 "digest: digest mismatch", a2, respons);
11304                 }
11305 -               
11306 -               log_error_write(srv, __FILE__, __LINE__, "sss", 
11307 +
11308 +               log_error_write(srv, __FILE__, __LINE__, "sss",
11309                                 "digest: auth failed for", username, "wrong password");
11310 -               
11311 +
11312                 buffer_free(b);
11313                 return 0;
11314         }
11315 -       
11316 +
11317         /* value is our allow-rules */
11318         if (http_auth_match_rules(srv, p, url->ptr, username, NULL, NULL)) {
11319                 buffer_free(b);
11320 -               
11321 -               log_error_write(srv, __FILE__, __LINE__, "s", 
11322 +
11323 +               log_error_write(srv, __FILE__, __LINE__, "s",
11324                                 "digest: rules did match");
11325 -               
11326 +
11327                 return 0;
11328         }
11329 -       
11330 +
11331         /* remember the username */
11332         buffer_copy_string(p->auth_user, username);
11333 -       
11334 +
11335         buffer_free(b);
11336 -       
11337 +
11338         if (p->conf.auth_debug) {
11339 -               log_error_write(srv, __FILE__, __LINE__, "s", 
11340 +               log_error_write(srv, __FILE__, __LINE__, "s",
11341                                 "digest: auth ok");
11342         }
11343         return 1;
11344 @@ -985,23 +948,23 @@
11345         HASH h;
11346         MD5_CTX Md5Ctx;
11347         char hh[32];
11348 -       
11349 +
11350         UNUSED(p);
11351  
11352         /* generate shared-secret */
11353         MD5_Init(&Md5Ctx);
11354         MD5_Update(&Md5Ctx, (unsigned char *)fn->ptr, fn->used - 1);
11355         MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
11356 -       
11357 +
11358         /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
11359         ltostr(hh, srv->cur_ts);
11360         MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
11361         ltostr(hh, rand());
11362         MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
11363 -       
11364 +
11365         MD5_Final(h, &Md5Ctx);
11366 -       
11367 +
11368         CvtHex(h, out);
11369 -       
11370 +
11371         return 0;
11372  }
11373 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/http_auth.h lighttpd-1.4.12/src/http_auth.h
11374 --- lighttpd-1.4.11/src/http_auth.h     2005-08-14 17:12:31.000000000 +0300
11375 +++ lighttpd-1.4.12/src/http_auth.h     2006-07-11 21:23:40.000000000 +0300
11376 @@ -9,22 +9,26 @@
11377  # include <ldap.h>
11378  #endif
11379  
11380 -typedef enum { AUTH_BACKEND_UNSET, AUTH_BACKEND_PLAIN, 
11381 -               AUTH_BACKEND_LDAP, AUTH_BACKEND_HTPASSWD, 
11382 -               AUTH_BACKEND_HTDIGEST, AUTH_BACKEND_PAM } auth_backend_t;
11383 +typedef enum {
11384 +       AUTH_BACKEND_UNSET,
11385 +       AUTH_BACKEND_PLAIN,
11386 +       AUTH_BACKEND_LDAP,
11387 +       AUTH_BACKEND_HTPASSWD,
11388 +       AUTH_BACKEND_HTDIGEST
11389 +} auth_backend_t;
11390  
11391  typedef struct {
11392         /* auth */
11393         array  *auth_require;
11394 -       
11395 +
11396         buffer *auth_plain_groupfile;
11397         buffer *auth_plain_userfile;
11398 -       
11399 +
11400         buffer *auth_htdigest_userfile;
11401         buffer *auth_htpasswd_userfile;
11402 -       
11403 +
11404         buffer *auth_backend_conf;
11405 -       
11406 +
11407         buffer *auth_ldap_hostname;
11408         buffer *auth_ldap_basedn;
11409         buffer *auth_ldap_binddn;
11410 @@ -32,15 +36,15 @@
11411         buffer *auth_ldap_filter;
11412         buffer *auth_ldap_cafile;
11413         unsigned short auth_ldap_starttls;
11414 -       
11415 +
11416         unsigned short auth_debug;
11417 -       
11418 +
11419         /* generated */
11420         auth_backend_t auth_backend;
11421 -       
11422 +
11423  #ifdef USE_LDAP
11424         LDAP *ldap;
11425 -       
11426 +
11427         buffer *ldap_filter_pre;
11428         buffer *ldap_filter_post;
11429  #endif
11430 @@ -49,15 +53,15 @@
11431  typedef struct {
11432         PLUGIN_DATA;
11433         buffer *tmp_buf;
11434 -       
11435 +
11436         buffer *auth_user;
11437  
11438  #ifdef USE_LDAP
11439         buffer *ldap_filter;
11440  #endif
11441 -       
11442 +
11443         mod_auth_plugin_config **config_storage;
11444 -       
11445 +
11446         mod_auth_plugin_config conf; /* this is only used as long as no handler_ctx is setup */
11447  } mod_auth_plugin_data;
11448  
11449 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/http_auth_digest.h lighttpd-1.4.12/src/http_auth_digest.h
11450 --- lighttpd-1.4.11/src/http_auth_digest.h      2006-01-05 00:54:01.000000000 +0200
11451 +++ lighttpd-1.4.12/src/http_auth_digest.h      2006-07-11 21:23:40.000000000 +0300
11452 @@ -12,7 +12,7 @@
11453  #ifdef USE_OPENSSL
11454  #define IN const
11455  #else
11456 -#define IN 
11457 +#define IN
11458  #endif
11459  #define OUT
11460  
11461 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/http_chunk.c lighttpd-1.4.12/src/http_chunk.c
11462 --- lighttpd-1.4.11/src/http_chunk.c    2005-08-11 01:26:50.000000000 +0300
11463 +++ lighttpd-1.4.12/src/http_chunk.c    2006-07-11 21:23:40.000000000 +0300
11464 @@ -1,7 +1,7 @@
11465  /**
11466   * the HTTP chunk-API
11467 - * 
11468 - * 
11469 + *
11470 + *
11471   */
11472  
11473  #include <sys/types.h>
11474 @@ -9,7 +9,6 @@
11475  
11476  #include <stdlib.h>
11477  #include <fcntl.h>
11478 -#include <unistd.h>
11479  
11480  #include <stdio.h>
11481  #include <errno.h>
11482 @@ -23,19 +22,19 @@
11483  static int http_chunk_append_len(server *srv, connection *con, size_t len) {
11484         size_t i, olen = len, j;
11485         buffer *b;
11486 -       
11487 +
11488         b = srv->tmp_chunk_len;
11489 -       
11490 +
11491         if (len == 0) {
11492                 buffer_copy_string(b, "0");
11493         } else {
11494                 for (i = 0; i < 8 && len; i++) {
11495                         len >>= 4;
11496                 }
11497 -               
11498 +
11499                 /* i is the number of hex digits we have */
11500                 buffer_prepare_copy(b, i + 1);
11501 -               
11502 +
11503                 for (j = i-1, len = olen; j+1 > 0; j--) {
11504                         b->ptr[j] = (len & 0xf) + (((len & 0xf) <= 9) ? '0' : 'a' - 10);
11505                         len >>= 4;
11506 @@ -43,61 +42,61 @@
11507                 b->used = i;
11508                 b->ptr[b->used++] = '\0';
11509         }
11510 -               
11511 +
11512         buffer_append_string(b, "\r\n");
11513         chunkqueue_append_buffer(con->write_queue, b);
11514 -       
11515 +
11516         return 0;
11517  }
11518  
11519  
11520  int http_chunk_append_file(server *srv, connection *con, buffer *fn, off_t offset, off_t len) {
11521         chunkqueue *cq;
11522 -       
11523 +
11524         if (!con) return -1;
11525 -       
11526 +
11527         cq = con->write_queue;
11528 -       
11529 +
11530         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11531                 http_chunk_append_len(srv, con, len);
11532         }
11533 -       
11534 +
11535         chunkqueue_append_file(cq, fn, offset, len);
11536 -       
11537 +
11538         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && len > 0) {
11539                 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11540         }
11541 -       
11542 +
11543         return 0;
11544  }
11545  
11546  int http_chunk_append_buffer(server *srv, connection *con, buffer *mem) {
11547         chunkqueue *cq;
11548 -       
11549 +
11550         if (!con) return -1;
11551 -       
11552 +
11553         cq = con->write_queue;
11554 -       
11555 +
11556         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11557                 http_chunk_append_len(srv, con, mem->used - 1);
11558         }
11559 -       
11560 +
11561         chunkqueue_append_buffer(cq, mem);
11562 -       
11563 +
11564         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && mem->used > 0) {
11565                 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11566         }
11567 -       
11568 +
11569         return 0;
11570  }
11571  
11572  int http_chunk_append_mem(server *srv, connection *con, const char * mem, size_t len) {
11573         chunkqueue *cq;
11574 -       
11575 +
11576         if (!con) return -1;
11577 -       
11578 +
11579         cq = con->write_queue;
11580 -       
11581 +
11582         if (len == 0) {
11583                 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11584                         http_chunk_append_len(srv, con, 0);
11585 @@ -107,17 +106,17 @@
11586                 }
11587                 return 0;
11588         }
11589 -       
11590 +
11591         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11592                 http_chunk_append_len(srv, con, len - 1);
11593         }
11594 -       
11595 +
11596         chunkqueue_append_mem(cq, mem, len);
11597 -       
11598 +
11599         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11600                 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11601         }
11602 -       
11603 +
11604         return 0;
11605  }
11606  
11607 @@ -125,9 +124,9 @@
11608  off_t http_chunkqueue_length(server *srv, connection *con) {
11609         if (!con) {
11610                 log_error_write(srv, __FILE__, __LINE__, "s", "connection is NULL!!");
11611 -               
11612 +
11613                 return 0;
11614         }
11615 -       
11616 +
11617         return chunkqueue_length(con->write_queue);
11618  }
11619 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/http_resp.c lighttpd-1.4.12/src/http_resp.c
11620 --- lighttpd-1.4.11/src/http_resp.c     1970-01-01 03:00:00.000000000 +0300
11621 +++ lighttpd-1.4.12/src/http_resp.c     2006-07-11 21:23:40.000000000 +0300
11622 @@ -0,0 +1,263 @@
11623 +#include <string.h>
11624 +#include <stdlib.h>
11625 +#include <stdio.h>
11626 +#include <assert.h>
11627 +
11628 +#include "http_resp.h"
11629 +#include "http_resp_parser.h"
11630 +
11631 +/* declare prototypes for the parser */
11632 +void *http_resp_parserAlloc(void *(*mallocProc)(size_t));
11633 +void http_resp_parserFree(void *p,  void (*freeProc)(void*));
11634 +void http_resp_parserTrace(FILE *TraceFILE, char *zTracePrompt);
11635 +void http_resp_parser(void *, int, buffer *, http_resp_ctx_t *);
11636 +
11637 +typedef struct {
11638 +       chunkqueue *cq;
11639 +
11640 +       chunk *c; /* current chunk in the chunkqueue */
11641 +    size_t offset; /* current offset in current chunk */
11642 +
11643 +    chunk *lookup_c;
11644 +    size_t lookup_offset;
11645 +
11646 +    int is_key;
11647 +    int is_statusline;
11648 +} http_resp_tokenizer_t;
11649 +
11650 +http_resp *http_response_init(void) {
11651 +    http_resp *resp = calloc(1, sizeof(*resp));
11652 +
11653 +    resp->reason = buffer_init();
11654 +    resp->headers = array_init();
11655 +
11656 +    return resp;
11657 +}
11658 +
11659 +void http_response_reset(http_resp *resp) {
11660 +    if (!resp) return;
11661 +
11662 +    buffer_reset(resp->reason);
11663 +    array_reset(resp->headers);
11664 +
11665 +}
11666 +
11667 +void http_response_free(http_resp *resp) {
11668 +    if (!resp) return;
11669 +
11670 +    buffer_free(resp->reason);
11671 +    array_free(resp->headers);
11672 +
11673 +    free(resp);
11674 +}
11675 +
11676 +static int http_resp_get_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
11677 +    if (t->offset == t->c->mem->used - 1) {
11678 +        /* end of chunk, open next chunk */
11679 +
11680 +        if (!t->c->next) return -1;
11681 +
11682 +        t->c = t->c->next;
11683 +        t->offset = 0;
11684 +    }
11685 +
11686 +    *c = t->c->mem->ptr[t->offset++];
11687 +
11688 +    t->lookup_offset = t->offset;
11689 +    t->lookup_c = t->c;
11690 +
11691 +#if 0
11692 +    fprintf(stderr, "%s.%d: get: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->offset - 1);
11693 +#endif
11694 +
11695 +    return 0;
11696 +}
11697 +
11698 +static int http_resp_lookup_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
11699 +    if (t->lookup_offset == t->lookup_c->mem->used - 1) {
11700 +        /* end of chunk, open next chunk */
11701 +
11702 +        if (!t->lookup_c->next) return -1;
11703 +
11704 +        t->lookup_c = t->lookup_c->next;
11705 +        t->lookup_offset = 0;
11706 +    }
11707 +
11708 +    *c = t->lookup_c->mem->ptr[t->lookup_offset++];
11709 +#if 0
11710 +    fprintf(stderr, "%s.%d: lookup: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->lookup_offset - 1);
11711 +#endif
11712 +
11713 +    return 0;
11714 +}
11715 +
11716 +
11717 +static int http_resp_tokenizer(
11718 +    http_resp_tokenizer_t *t,
11719 +    int *token_id,
11720 +    buffer *token
11721 +) {
11722 +    unsigned char c;
11723 +    int tid = 0;
11724 +
11725 +    /* push the token to the parser */
11726 +
11727 +    while (tid == 0 && 0 == http_resp_get_next_char(t, &c)) {
11728 +        switch (c) {
11729 +        case ':':
11730 +            tid = TK_COLON;
11731 +
11732 +            t->is_key = 0;
11733 +
11734 +            break;
11735 +        case ' ':
11736 +        case '\t':
11737 +            /* ignore WS */
11738 +
11739 +            break;
11740 +        case '\r':
11741 +            if (0 != http_resp_lookup_next_char(t, &c)) return -1;
11742 +
11743 +            if (c == '\n') {
11744 +                tid = TK_CRLF;
11745 +
11746 +                t->c = t->lookup_c;
11747 +                t->offset = t->lookup_offset;
11748 +
11749 +                t->is_statusline = 0;
11750 +                t->is_key = 1;
11751 +            } else {
11752 +                fprintf(stderr, "%s.%d: CR with out LF\r\n", __FILE__, __LINE__);
11753 +                return -1;
11754 +            }
11755 +            break;
11756 +        case '\n':
11757 +            tid = TK_CRLF;
11758 +
11759 +            t->is_statusline = 0;
11760 +            t->is_key = 1;
11761 +
11762 +            break;
11763 +        default:
11764 +            while (c >= 32 && c != 127 && c != 255) {
11765 +                if (t->is_statusline) {
11766 +                       if (c == ':') {t->is_statusline = 0; break; } /* this is not a status line by a real header */
11767 +                    if (c == 32) break; /* the space is a splitter in the statusline */
11768 +                } else {
11769 +                    if (t->is_key) {
11770 +                        if (c == ':') break; /* the : is the splitter between key and value */
11771 +                    }
11772 +                }
11773 +                if (0 != http_resp_lookup_next_char(t, &c)) return -1;
11774 +            }
11775 +
11776 +            if (t->c == t->lookup_c &&
11777 +                t->offset == t->lookup_offset + 1) {
11778 +
11779 +                fprintf(stderr, "%s.%d: invalid char in string\n", __FILE__, __LINE__);
11780 +                return -1;
11781 +            }
11782 +
11783 +            tid = TK_STRING;
11784 +
11785 +            /* the lookup points to the first invalid char */
11786 +            t->lookup_offset--;
11787 +
11788 +            /* no overlapping string */
11789 +            if (t->c == t->lookup_c) {
11790 +                buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->lookup_offset - t->offset + 1);
11791 +            } else {
11792 +                /* first chunk */
11793 +                buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->c->mem->used - t->offset);
11794 +
11795 +                /* chunks in the middle */
11796 +                for (t->c = t->c->next; t->c != t->lookup_c; t->c = t->c->next) {
11797 +                    buffer_append_string_buffer(token, t->c->mem);
11798 +                    t->offset = t->c->mem->used - 1;
11799 +                }
11800 +
11801 +                /* last chunk */
11802 +                buffer_append_string_len(token, t->c->mem->ptr, t->lookup_offset);
11803 +            }
11804 +
11805 +            t->offset = t->lookup_offset;
11806 +
11807 +            break;
11808 +        }
11809 +       }
11810 +
11811 +    if (tid) {
11812 +               *token_id = tid;
11813 +
11814 +        return 1;
11815 +    }
11816 +
11817 +    return -1;
11818 +}
11819 +
11820 +parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *resp) {
11821 +    http_resp_tokenizer_t t;
11822 +       void *pParser = NULL;
11823 +       int token_id = 0;
11824 +       buffer *token = NULL;
11825 +       http_resp_ctx_t context;
11826 +    parse_status_t ret = PARSE_UNSET;
11827 +    int last_token_id = 0;
11828 +
11829 +       t.cq = cq;
11830 +    t.c = cq->first;
11831 +    t.offset = t.c->offset;
11832 +    t.is_key = 0;
11833 +    t.is_statusline = 1;
11834 +
11835 +       context.ok = 1;
11836 +    context.errmsg = buffer_init();
11837 +    context.resp = resp;
11838 +
11839 +       pParser = http_resp_parserAlloc( malloc );
11840 +       token = buffer_init();
11841 +    /* http_resp_parserTrace(stderr, "http-response: "); */
11842 +
11843 +       while((1 == http_resp_tokenizer(&t, &token_id, token)) && context.ok) {
11844 +               http_resp_parser(pParser, token_id, token, &context);
11845 +
11846 +               token = buffer_init();
11847 +
11848 +        if (last_token_id == TK_CRLF &&
11849 +            token_id == TK_CRLF) break;
11850 +
11851 +        last_token_id = token_id;
11852 +       }
11853 +
11854 +    /* oops, the parser failed */
11855 +    if (context.ok == 0) {
11856 +        ret = PARSE_ERROR;
11857 +
11858 +        fprintf(stderr, "%s.%d: parsing failed at: ...%20s\r\n",
11859 +            __FILE__, __LINE__, t.c->mem->ptr + t.offset);
11860 +    }
11861 +
11862 +       http_resp_parser(pParser, 0, token, &context);
11863 +       http_resp_parserFree(pParser, free );
11864 +
11865 +    if (context.ok == 0) {
11866 +        /* we are missing the some tokens */
11867 +
11868 +        if (ret == PARSE_UNSET) ret = PARSE_NEED_MORE;
11869 +    } else {
11870 +        chunk *c;
11871 +
11872 +        for (c = cq->first; c != t.c; c = c->next) {
11873 +            c->offset = c->mem->used - 1;
11874 +        }
11875 +
11876 +        c->offset = t.offset;
11877 +
11878 +        ret = PARSE_SUCCESS;
11879 +    }
11880 +
11881 +    buffer_free(token);
11882 +
11883 +    return ret;
11884 +}
11885 +
11886 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/http_resp.h lighttpd-1.4.12/src/http_resp.h
11887 --- lighttpd-1.4.11/src/http_resp.h     1970-01-01 03:00:00.000000000 +0300
11888 +++ lighttpd-1.4.12/src/http_resp.h     2006-07-11 21:23:40.000000000 +0300
11889 @@ -0,0 +1,34 @@
11890 +#ifndef _HTTP_RESP_H_
11891 +#define _HTTP_RESP_H_
11892 +
11893 +#include "array.h"
11894 +#include "chunk.h"
11895 +
11896 +typedef enum {
11897 +    PARSE_UNSET,
11898 +    PARSE_SUCCESS,
11899 +    PARSE_ERROR,
11900 +    PARSE_NEED_MORE
11901 +} parse_status_t;
11902 +
11903 +typedef struct {
11904 +    int protocol;   /* http/1.0, http/1.1 */
11905 +    int status;     /* e.g. 200 */
11906 +    buffer *reason; /* e.g. Ok */
11907 +    array *headers;
11908 +} http_resp;
11909 +
11910 +typedef struct {
11911 +       int     ok;
11912 +    buffer *errmsg;
11913 +
11914 +    http_resp *resp;
11915 +} http_resp_ctx_t;
11916 +
11917 +http_resp *http_response_init(void);
11918 +void http_response_free(http_resp *resp);
11919 +void http_response_reset(http_resp *resp);
11920 +
11921 +parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *http_response);
11922 +
11923 +#endif
11924 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/http_resp_parser.c lighttpd-1.4.12/src/http_resp_parser.c
11925 --- lighttpd-1.4.11/src/http_resp_parser.c      1970-01-01 03:00:00.000000000 +0300
11926 +++ lighttpd-1.4.12/src/http_resp_parser.c      2006-07-11 21:49:18.000000000 +0300
11927 @@ -0,0 +1,894 @@
11928 +/* Driver template for the LEMON parser generator.
11929 +** The author disclaims copyright to this source code.
11930 +*/
11931 +/* First off, code is include which follows the "include" declaration
11932 +** in the input file. */
11933 +#include <stdio.h>
11934 +#line 6 "./http_resp_parser.y"
11935 +
11936 +#include <assert.h>
11937 +#include <string.h>
11938 +#include "http_resp.h"
11939 +#include "keyvalue.h"
11940 +#include "array.h"
11941 +
11942 +#line 16 "http_resp_parser.c"
11943 +/* Next is all token values, in a form suitable for use by makeheaders.
11944 +** This section will be null unless lemon is run with the -m switch.
11945 +*/
11946 +/*
11947 +** These constants (all generated automatically by the parser generator)
11948 +** specify the various kinds of tokens (terminals) that the parser
11949 +** understands.
11950 +**
11951 +** Each symbol here is a terminal symbol in the grammar.
11952 +*/
11953 +/* Make sure the INTERFACE macro is defined.
11954 +*/
11955 +#ifndef INTERFACE
11956 +# define INTERFACE 1
11957 +#endif
11958 +/* The next thing included is series of defines which control
11959 +** various aspects of the generated parser.
11960 +**    YYCODETYPE         is the data type used for storing terminal
11961 +**                       and nonterminal numbers.  "unsigned char" is
11962 +**                       used if there are fewer than 250 terminals
11963 +**                       and nonterminals.  "int" is used otherwise.
11964 +**    YYNOCODE           is a number of type YYCODETYPE which corresponds
11965 +**                       to no legal terminal or nonterminal number.  This
11966 +**                       number is used to fill in empty slots of the hash
11967 +**                       table.
11968 +**    YYFALLBACK         If defined, this indicates that one or more tokens
11969 +**                       have fall-back values which should be used if the
11970 +**                       original value of the token will not parse.
11971 +**    YYACTIONTYPE       is the data type used for storing terminal
11972 +**                       and nonterminal numbers.  "unsigned char" is
11973 +**                       used if there are fewer than 250 rules and
11974 +**                       states combined.  "int" is used otherwise.
11975 +**    http_resp_parserTOKENTYPE     is the data type used for minor tokens given
11976 +**                       directly to the parser from the tokenizer.
11977 +**    YYMINORTYPE        is the data type used for all minor tokens.
11978 +**                       This is typically a union of many types, one of
11979 +**                       which is http_resp_parserTOKENTYPE.  The entry in the union
11980 +**                       for base tokens is called "yy0".
11981 +**    YYSTACKDEPTH       is the maximum depth of the parser's stack.
11982 +**    http_resp_parserARG_SDECL     A static variable declaration for the %extra_argument
11983 +**    http_resp_parserARG_PDECL     A parameter declaration for the %extra_argument
11984 +**    http_resp_parserARG_STORE     Code to store %extra_argument into yypParser
11985 +**    http_resp_parserARG_FETCH     Code to extract %extra_argument from yypParser
11986 +**    YYNSTATE           the combined number of states.
11987 +**    YYNRULE            the number of rules in the grammar
11988 +**    YYERRORSYMBOL      is the code number of the error symbol.  If not
11989 +**                       defined, then do no error processing.
11990 +*/
11991 +/* \ 1 */
11992 +#define YYCODETYPE unsigned char
11993 +#define YYNOCODE 12
11994 +#define YYACTIONTYPE unsigned char
11995 +#define http_resp_parserTOKENTYPE buffer *
11996 +typedef union {
11997 +  http_resp_parserTOKENTYPE yy0;
11998 +  http_resp * yy2;
11999 +  data_string * yy9;
12000 +  array * yy12;
12001 +  int yy20;
12002 +  int yy23;
12003 +} YYMINORTYPE;
12004 +#define YYSTACKDEPTH 100
12005 +#define http_resp_parserARG_SDECL http_resp_ctx_t *ctx;
12006 +#define http_resp_parserARG_PDECL ,http_resp_ctx_t *ctx
12007 +#define http_resp_parserARG_FETCH http_resp_ctx_t *ctx = yypParser->ctx
12008 +#define http_resp_parserARG_STORE yypParser->ctx = ctx
12009 +#define YYNSTATE 19
12010 +#define YYNRULE 9
12011 +#define YYERRORSYMBOL 4
12012 +#define YYERRSYMDT yy23
12013 +#define YY_NO_ACTION      (YYNSTATE+YYNRULE+2)
12014 +#define YY_ACCEPT_ACTION  (YYNSTATE+YYNRULE+1)
12015 +#define YY_ERROR_ACTION   (YYNSTATE+YYNRULE)
12016 +
12017 +/* Next are that tables used to determine what action to take based on the
12018 +** current state and lookahead token.  These tables are used to implement
12019 +** functions that take a state number and lookahead value and return an
12020 +** action integer.
12021 +**
12022 +** Suppose the action integer is N.  Then the action is determined as
12023 +** follows
12024 +**
12025 +**   0 <= N < YYNSTATE                  Shift N.  That is, push the lookahead
12026 +**                                      token onto the stack and goto state N.
12027 +**
12028 +**   YYNSTATE <= N < YYNSTATE+YYNRULE   Reduce by rule N-YYNSTATE.
12029 +**
12030 +**   N == YYNSTATE+YYNRULE              A syntax error has occurred.
12031 +**
12032 +**   N == YYNSTATE+YYNRULE+1            The parser accepts its input.
12033 +**
12034 +**   N == YYNSTATE+YYNRULE+2            No such action.  Denotes unused
12035 +**                                      slots in the yy_action[] table.
12036 +**
12037 +** The action table is constructed as a single large table named yy_action[].
12038 +** Given state S and lookahead X, the action is computed as
12039 +**
12040 +**      yy_action[ yy_shift_ofst[S] + X ]
12041 +**
12042 +** If the index value yy_shift_ofst[S]+X is out of range or if the value
12043 +** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
12044 +** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
12045 +** and that yy_default[S] should be used instead.
12046 +**
12047 +** The formula above is for computing the action when the lookahead is
12048 +** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
12049 +** a reduce action) then the yy_reduce_ofst[] array is used in place of
12050 +** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
12051 +** YY_SHIFT_USE_DFLT.
12052 +**
12053 +** The following are the tables generated in this section:
12054 +**
12055 +**  yy_action[]        A single table containing all actions.
12056 +**  yy_lookahead[]     A table containing the lookahead for each entry in
12057 +**                     yy_action.  Used to detect hash collisions.
12058 +**  yy_shift_ofst[]    For each state, the offset into yy_action for
12059 +**                     shifting terminals.
12060 +**  yy_reduce_ofst[]   For each state, the offset into yy_action for
12061 +**                     shifting non-terminals after a reduce.
12062 +**  yy_default[]       Default action for each state.
12063 +*/
12064 +static YYACTIONTYPE yy_action[] = {
12065 + /*     0 */     8,   29,   18,    1,   14,    2,    4,   11,   15,   12,
12066 + /*    10 */    14,   13,    4,   21,    5,   19,    3,    5,    6,    7,
12067 + /*    20 */     9,   17,   16,    4,   20,   22,   22,   10,
12068 +};
12069 +static YYCODETYPE yy_lookahead[] = {
12070 + /*     0 */     5,    6,    2,    8,    9,    1,    2,    1,    2,    8,
12071 + /*    10 */     9,    1,    2,    2,    3,    0,    9,    3,    2,    1,
12072 + /*    20 */     7,    2,    2,    2,    0,    2,   11,   10,
12073 +};
12074 +#define YY_SHIFT_USE_DFLT (-1)
12075 +static signed char yy_shift_ofst[] = {
12076 + /*     0 */     0,    4,   15,   -1,   14,   16,   18,   -1,   19,   20,
12077 + /*    10 */     6,   21,   10,   24,   -1,   -1,   -1,   23,   11,
12078 +};
12079 +#define YY_REDUCE_USE_DFLT (-6)
12080 +static signed char yy_reduce_ofst[] = {
12081 + /*     0 */    -5,    7,   -6,   -6,   -6,   -6,   -6,   -6,   13,   17,
12082 + /*    10 */    -6,    1,    7,   -6,   -6,   -6,   -6,   -6,   -6,
12083 +};
12084 +static YYACTIONTYPE yy_default[] = {
12085 + /*     0 */    28,   28,   28,   25,   28,   28,   28,   27,   28,   28,
12086 + /*    10 */    28,   28,   28,   28,   26,   24,   23,   28,   28,
12087 +};
12088 +#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
12089 +
12090 +/* The next table maps tokens into fallback tokens.  If a construct
12091 +** like the following:
12092 +**
12093 +**      %fallback ID X Y Z.
12094 +**
12095 +** appears in the grammer, then ID becomes a fallback token for X, Y,
12096 +** and Z.  Whenever one of the tokens X, Y, or Z is input to the parser
12097 +** but it does not parse, the type of the token is changed to ID and
12098 +** the parse is retried before an error is thrown.
12099 +*/
12100 +#ifdef YYFALLBACK
12101 +static const YYCODETYPE yyFallback[] = {
12102 +};
12103 +#endif /* YYFALLBACK */
12104 +
12105 +/* The following structure represents a single element of the
12106 +** parser's stack.  Information stored includes:
12107 +**
12108 +**   +  The state number for the parser at this level of the stack.
12109 +**
12110 +**   +  The value of the token stored at this level of the stack.
12111 +**      (In other words, the "major" token.)
12112 +**
12113 +**   +  The semantic value stored at this level of the stack.  This is
12114 +**      the information used by the action routines in the grammar.
12115 +**      It is sometimes called the "minor" token.
12116 +*/
12117 +struct yyStackEntry {
12118 +  int stateno;       /* The state-number */
12119 +  int major;         /* The major token value.  This is the code
12120 +                     ** number for the token at this stack level */
12121 +  YYMINORTYPE minor; /* The user-supplied minor token value.  This
12122 +                     ** is the value of the token  */
12123 +};
12124 +typedef struct yyStackEntry yyStackEntry;
12125 +
12126 +/* The state of the parser is completely contained in an instance of
12127 +** the following structure */
12128 +struct yyParser {
12129 +  int yyidx;                    /* Index of top element in stack */
12130 +  int yyerrcnt;                 /* Shifts left before out of the error */
12131 +  http_resp_parserARG_SDECL                /* A place to hold %extra_argument */
12132 +  yyStackEntry yystack[YYSTACKDEPTH];  /* The parser's stack */
12133 +};
12134 +typedef struct yyParser yyParser;
12135 +
12136 +#ifndef NDEBUG
12137 +#include <stdio.h>
12138 +static FILE *yyTraceFILE = 0;
12139 +static char *yyTracePrompt = 0;
12140 +#endif /* NDEBUG */
12141 +
12142 +#ifndef NDEBUG
12143 +/*
12144 +** Turn parser tracing on by giving a stream to which to write the trace
12145 +** and a prompt to preface each trace message.  Tracing is turned off
12146 +** by making either argument NULL
12147 +**
12148 +** Inputs:
12149 +** <ul>
12150 +** <li> A FILE* to which trace output should be written.
12151 +**      If NULL, then tracing is turned off.
12152 +** <li> A prefix string written at the beginning of every
12153 +**      line of trace output.  If NULL, then tracing is
12154 +**      turned off.
12155 +** </ul>
12156 +**
12157 +** Outputs:
12158 +** None.
12159 +*/
12160 +void http_resp_parserTrace(FILE *TraceFILE, char *zTracePrompt){
12161 +  yyTraceFILE = TraceFILE;
12162 +  yyTracePrompt = zTracePrompt;
12163 +  if( yyTraceFILE==0 ) yyTracePrompt = 0;
12164 +  else if( yyTracePrompt==0 ) yyTraceFILE = 0;
12165 +}
12166 +#endif /* NDEBUG */
12167 +
12168 +#ifndef NDEBUG
12169 +/* For tracing shifts, the names of all terminals and nonterminals
12170 +** are required.  The following table supplies these names */
12171 +static const char *yyTokenName[] = {
12172 +  "$",             "CRLF",          "STRING",        "COLON",       
12173 +  "error",         "protocol",      "response_hdr",  "number",      
12174 +  "headers",       "header",        "reason",      
12175 +};
12176 +#endif /* NDEBUG */
12177 +
12178 +#ifndef NDEBUG
12179 +/* For tracing reduce actions, the names of all rules are required.
12180 +*/
12181 +static const char *yyRuleName[] = {
12182 + /*   0 */ "response_hdr ::= headers CRLF",
12183 + /*   1 */ "response_hdr ::= protocol number reason CRLF headers CRLF",
12184 + /*   2 */ "protocol ::= STRING",
12185 + /*   3 */ "number ::= STRING",
12186 + /*   4 */ "reason ::= STRING",
12187 + /*   5 */ "reason ::= reason STRING",
12188 + /*   6 */ "headers ::= headers header",
12189 + /*   7 */ "headers ::= header",
12190 + /*   8 */ "header ::= STRING COLON STRING CRLF",
12191 +};
12192 +#endif /* NDEBUG */
12193 +
12194 +/*
12195 +** This function returns the symbolic name associated with a token
12196 +** value.
12197 +*/
12198 +const char *http_resp_parserTokenName(int tokenType){
12199 +#ifndef NDEBUG
12200 +  if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){
12201 +    return yyTokenName[tokenType];
12202 +  }else{
12203 +    return "Unknown";
12204 +  }
12205 +#else
12206 +  return "";
12207 +#endif
12208 +}
12209 +
12210 +/*
12211 +** This function allocates a new parser.
12212 +** The only argument is a pointer to a function which works like
12213 +** malloc.
12214 +**
12215 +** Inputs:
12216 +** A pointer to the function used to allocate memory.
12217 +**
12218 +** Outputs:
12219 +** A pointer to a parser.  This pointer is used in subsequent calls
12220 +** to http_resp_parser and http_resp_parserFree.
12221 +*/
12222 +void *http_resp_parserAlloc(void *(*mallocProc)(size_t)){
12223 +  yyParser *pParser;
12224 +  pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
12225 +  if( pParser ){
12226 +    pParser->yyidx = -1;
12227 +  }
12228 +  return pParser;
12229 +}
12230 +
12231 +/* The following function deletes the value associated with a
12232 +** symbol.  The symbol can be either a terminal or nonterminal.
12233 +** "yymajor" is the symbol code, and "yypminor" is a pointer to
12234 +** the value.
12235 +*/
12236 +static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){
12237 +  switch( yymajor ){
12238 +    /* Here is inserted the actions which take place when a
12239 +    ** terminal or non-terminal is destroyed.  This can happen
12240 +    ** when the symbol is popped from the stack during a
12241 +    ** reduce or during error processing or when a parser is
12242 +    ** being destroyed before it is finished parsing.
12243 +    **
12244 +    ** Note: during a reduce, the only symbols destroyed are those
12245 +    ** which appear on the RHS of the rule, but which are not used
12246 +    ** inside the C code.
12247 +    */
12248 +    case 1:
12249 +    case 2:
12250 +    case 3:
12251 +#line 23 "./http_resp_parser.y"
12252 +{ buffer_free((yypminor->yy0)); }
12253 +#line 326 "http_resp_parser.c"
12254 +      break;
12255 +    default:  break;   /* If no destructor action specified: do nothing */
12256 +  }
12257 +}
12258 +
12259 +/*
12260 +** Pop the parser's stack once.
12261 +**
12262 +** If there is a destructor routine associated with the token which
12263 +** is popped from the stack, then call it.
12264 +**
12265 +** Return the major token number for the symbol popped.
12266 +*/
12267 +static int yy_pop_parser_stack(yyParser *pParser){
12268 +  YYCODETYPE yymajor;
12269 +  yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
12270 +
12271 +  if( pParser->yyidx<0 ) return 0;
12272 +#ifndef NDEBUG
12273 +  if( yyTraceFILE && pParser->yyidx>=0 ){
12274 +    fprintf(yyTraceFILE,"%sPopping %s\n",
12275 +      yyTracePrompt,
12276 +      yyTokenName[yytos->major]);
12277 +  }
12278 +#endif
12279 +  yymajor = yytos->major;
12280 +  yy_destructor( yymajor, &yytos->minor);
12281 +  pParser->yyidx--;
12282 +  return yymajor;
12283 +}
12284 +
12285 +/*
12286 +** Deallocate and destroy a parser.  Destructors are all called for
12287 +** all stack elements before shutting the parser down.
12288 +**
12289 +** Inputs:
12290 +** <ul>
12291 +** <li>  A pointer to the parser.  This should be a pointer
12292 +**       obtained from http_resp_parserAlloc.
12293 +** <li>  A pointer to a function used to reclaim memory obtained
12294 +**       from malloc.
12295 +** </ul>
12296 +*/
12297 +void http_resp_parserFree(
12298 +  void *p,                    /* The parser to be deleted */
12299 +  void (*freeProc)(void*)     /* Function used to reclaim memory */
12300 +){
12301 +  yyParser *pParser = (yyParser*)p;
12302 +  if( pParser==0 ) return;
12303 +  while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
12304 +  (*freeProc)((void*)pParser);
12305 +}
12306 +
12307 +/*
12308 +** Find the appropriate action for a parser given the terminal
12309 +** look-ahead token iLookAhead.
12310 +**
12311 +** If the look-ahead token is YYNOCODE, then check to see if the action is
12312 +** independent of the look-ahead.  If it is, return the action, otherwise
12313 +** return YY_NO_ACTION.
12314 +*/
12315 +static int yy_find_shift_action(
12316 +  yyParser *pParser,        /* The parser */
12317 +  int iLookAhead            /* The look-ahead token */
12318 +){
12319 +  int i;
12320 +  int stateno = pParser->yystack[pParser->yyidx].stateno;
12321 +
12322 +  /* if( pParser->yyidx<0 ) return YY_NO_ACTION;  */
12323 +  i = yy_shift_ofst[stateno];
12324 +  if( i==YY_SHIFT_USE_DFLT ){
12325 +    return yy_default[stateno];
12326 +  }
12327 +  if( iLookAhead==YYNOCODE ){
12328 +    return YY_NO_ACTION;
12329 +  }
12330 +  i += iLookAhead;
12331 +  if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
12332 +#ifdef YYFALLBACK
12333 +    int iFallback;            /* Fallback token */
12334 +    if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
12335 +           && (iFallback = yyFallback[iLookAhead])!=0 ){
12336 +#ifndef NDEBUG
12337 +      if( yyTraceFILE ){
12338 +        fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
12339 +           yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
12340 +      }
12341 +#endif
12342 +      return yy_find_shift_action(pParser, iFallback);
12343 +    }
12344 +#endif
12345 +    return yy_default[stateno];
12346 +  }else{
12347 +    return yy_action[i];
12348 +  }
12349 +}
12350 +
12351 +/*
12352 +** Find the appropriate action for a parser given the non-terminal
12353 +** look-ahead token iLookAhead.
12354 +**
12355 +** If the look-ahead token is YYNOCODE, then check to see if the action is
12356 +** independent of the look-ahead.  If it is, return the action, otherwise
12357 +** return YY_NO_ACTION.
12358 +*/
12359 +static int yy_find_reduce_action(
12360 +  yyParser *pParser,        /* The parser */
12361 +  int iLookAhead            /* The look-ahead token */
12362 +){
12363 +  int i;
12364 +  int stateno = pParser->yystack[pParser->yyidx].stateno;
12365 +
12366 +  i = yy_reduce_ofst[stateno];
12367 +  if( i==YY_REDUCE_USE_DFLT ){
12368 +    return yy_default[stateno];
12369 +  }
12370 +  if( iLookAhead==YYNOCODE ){
12371 +    return YY_NO_ACTION;
12372 +  }
12373 +  i += iLookAhead;
12374 +  if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
12375 +    return yy_default[stateno];
12376 +  }else{
12377 +    return yy_action[i];
12378 +  }
12379 +}
12380 +
12381 +/*
12382 +** Perform a shift action.
12383 +*/
12384 +static void yy_shift(
12385 +  yyParser *yypParser,          /* The parser to be shifted */
12386 +  int yyNewState,               /* The new state to shift in */
12387 +  int yyMajor,                  /* The major token to shift in */
12388 +  YYMINORTYPE *yypMinor         /* Pointer ot the minor token to shift in */
12389 +){
12390 +  yyStackEntry *yytos;
12391 +  yypParser->yyidx++;
12392 +  if( yypParser->yyidx>=YYSTACKDEPTH ){
12393 +     http_resp_parserARG_FETCH;
12394 +     yypParser->yyidx--;
12395 +#ifndef NDEBUG
12396 +     if( yyTraceFILE ){
12397 +       fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
12398 +     }
12399 +#endif
12400 +     while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
12401 +     /* Here code is inserted which will execute if the parser
12402 +     ** stack every overflows */
12403 +     http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument var */
12404 +     return;
12405 +  }
12406 +  yytos = &yypParser->yystack[yypParser->yyidx];
12407 +  yytos->stateno = yyNewState;
12408 +  yytos->major = yyMajor;
12409 +  yytos->minor = *yypMinor;
12410 +#ifndef NDEBUG
12411 +  if( yyTraceFILE && yypParser->yyidx>0 ){
12412 +    int i;
12413 +    fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
12414 +    fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
12415 +    for(i=1; i<=yypParser->yyidx; i++)
12416 +      fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
12417 +    fprintf(yyTraceFILE,"\n");
12418 +  }
12419 +#endif
12420 +}
12421 +
12422 +/* The following table contains information about every rule that
12423 +** is used during the reduce.
12424 +*/
12425 +static struct {
12426 +  YYCODETYPE lhs;         /* Symbol on the left-hand side of the rule */
12427 +  unsigned char nrhs;     /* Number of right-hand side symbols in the rule */
12428 +} yyRuleInfo[] = {
12429 +  { 6, 2 },
12430 +  { 6, 6 },
12431 +  { 5, 1 },
12432 +  { 7, 1 },
12433 +  { 10, 1 },
12434 +  { 10, 2 },
12435 +  { 8, 2 },
12436 +  { 8, 1 },
12437 +  { 9, 4 },
12438 +};
12439 +
12440 +static void yy_accept(yyParser*);  /* Forward Declaration */
12441 +
12442 +/*
12443 +** Perform a reduce action and the shift that must immediately
12444 +** follow the reduce.
12445 +*/
12446 +static void yy_reduce(
12447 +  yyParser *yypParser,         /* The parser */
12448 +  int yyruleno                 /* Number of the rule by which to reduce */
12449 +){
12450 +  int yygoto;                     /* The next state */
12451 +  int yyact;                      /* The next action */
12452 +  YYMINORTYPE yygotominor;        /* The LHS of the rule reduced */
12453 +  yyStackEntry *yymsp;            /* The top of the parser's stack */
12454 +  int yysize;                     /* Amount to pop the stack */
12455 +  http_resp_parserARG_FETCH;
12456 +  yymsp = &yypParser->yystack[yypParser->yyidx];
12457 +#ifndef NDEBUG
12458 +  if( yyTraceFILE && yyruleno>=0
12459 +        && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
12460 +    fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
12461 +      yyRuleName[yyruleno]);
12462 +  }
12463 +#endif /* NDEBUG */
12464 +
12465 +  switch( yyruleno ){
12466 +  /* Beginning here are the reduction cases.  A typical example
12467 +  ** follows:
12468 +  **   case 0:
12469 +  **  #line <lineno> <grammarfile>
12470 +  **     { ... }           // User supplied code
12471 +  **  #line <lineno> <thisfile>
12472 +  **     break;
12473 +  */
12474 +      case 0:
12475 +#line 26 "./http_resp_parser.y"
12476 +{
12477 +    http_resp *resp = ctx->resp;
12478 +    data_string *ds;
12479
12480 +    resp->protocol = HTTP_VERSION_UNSET;
12481 +
12482 +    buffer_copy_string(resp->reason, ""); /* no reason */
12483 +    array_free(resp->headers);
12484 +    resp->headers = yymsp[-1].minor.yy12;
12485 +
12486 +    if (NULL == (ds = (data_string *)array_get_element(yymsp[-1].minor.yy12, "Status"))) { 
12487 +        resp->status = 0;
12488 +    } else {
12489 +        char *err;
12490 +        resp->status = strtol(ds->value->ptr, &err, 10);
12491 +    
12492 +        if (*err != '\0') {
12493 +            buffer_copy_string(ctx->errmsg, "expected a number: ");
12494 +            buffer_append_string_buffer(ctx->errmsg, ds->value);
12495 +        
12496 +            ctx->ok = 0;
12497 +        }
12498 +
12499 +    }
12500 +
12501 +    yymsp[-1].minor.yy12 = NULL;
12502 +}
12503 +#line 576 "http_resp_parser.c"
12504 +  yy_destructor(1,&yymsp[0].minor);
12505 +        break;
12506 +      case 1:
12507 +#line 54 "./http_resp_parser.y"
12508 +{
12509 +    http_resp *resp = ctx->resp;
12510 +    
12511 +    resp->status = yymsp[-4].minor.yy20;
12512 +    resp->protocol = yymsp[-5].minor.yy20;
12513 +    buffer_copy_string_buffer(resp->reason, yymsp[-3].minor.yy0);
12514 +    
12515 +    array_free(resp->headers);
12516 +    
12517 +    resp->headers = yymsp[-1].minor.yy12;
12518 +    
12519 +    yymsp[-1].minor.yy12 = NULL;
12520 +}
12521 +#line 594 "http_resp_parser.c"
12522 +  yy_destructor(1,&yymsp[-2].minor);
12523 +  yy_destructor(1,&yymsp[0].minor);
12524 +        break;
12525 +      case 2:
12526 +#line 68 "./http_resp_parser.y"
12527 +{
12528 +    if (buffer_is_equal_string(yymsp[0].minor.yy0, CONST_STR_LEN("HTTP/1.0"))) {
12529 +        yygotominor.yy20 = HTTP_VERSION_1_0;
12530 +    } else if (buffer_is_equal_string(yymsp[0].minor.yy0, CONST_STR_LEN("HTTP/1.1"))) {
12531 +        yygotominor.yy20 = HTTP_VERSION_1_1;
12532 +    } else {
12533 +        buffer_copy_string(ctx->errmsg, "unknown protocol: ");
12534 +        buffer_append_string_buffer(ctx->errmsg, yymsp[0].minor.yy0);
12535 +        
12536 +        ctx->ok = 0;
12537 +    }
12538 +}
12539 +#line 612 "http_resp_parser.c"
12540 +        break;
12541 +      case 3:
12542 +#line 81 "./http_resp_parser.y"
12543 +{
12544 +    char *err;
12545 +    yygotominor.yy20 = strtol(yymsp[0].minor.yy0->ptr, &err, 10);
12546 +    
12547 +    if (*err != '\0') {
12548 +        buffer_copy_string(ctx->errmsg, "expected a number: ");
12549 +        buffer_append_string_buffer(ctx->errmsg, yymsp[0].minor.yy0);
12550 +        
12551 +        ctx->ok = 0;
12552 +    }
12553 +}
12554 +#line 627 "http_resp_parser.c"
12555 +        break;
12556 +      case 4:
12557 +#line 93 "./http_resp_parser.y"
12558 +{
12559 +    buffer_copy_string_buffer(yygotominor.yy0, yymsp[0].minor.yy0);
12560 +}
12561 +#line 634 "http_resp_parser.c"
12562 +        break;
12563 +      case 5:
12564 +#line 97 "./http_resp_parser.y"
12565 +{
12566 +    yygotominor.yy0 = yymsp[-1].minor.yy0;
12567 +    
12568 +    buffer_append_string(yygotominor.yy0, " ");
12569 +    buffer_append_string_buffer(yygotominor.yy0, yymsp[0].minor.yy0);
12570 +    
12571 +    yymsp[-1].minor.yy0 = NULL;
12572 +}
12573 +#line 646 "http_resp_parser.c"
12574 +        break;
12575 +      case 6:
12576 +#line 106 "./http_resp_parser.y"
12577 +{
12578 +    yygotominor.yy12 = yymsp[-1].minor.yy12;
12579 +    
12580 +    array_insert_unique(yygotominor.yy12, (data_unset *)yymsp[0].minor.yy9);
12581 +    
12582 +    yymsp[-1].minor.yy12 = NULL;
12583 +}
12584 +#line 657 "http_resp_parser.c"
12585 +        break;
12586 +      case 7:
12587 +#line 114 "./http_resp_parser.y"
12588 +{
12589 +    yygotominor.yy12 = array_init();
12590 +
12591 +    array_insert_unique(yygotominor.yy12, (data_unset *)yymsp[0].minor.yy9);
12592 +}
12593 +#line 666 "http_resp_parser.c"
12594 +        break;
12595 +      case 8:
12596 +#line 119 "./http_resp_parser.y"
12597 +{
12598 +    yygotominor.yy9 = data_string_init();
12599 +    
12600 +    buffer_copy_string_buffer(yygotominor.yy9->key, yymsp[-3].minor.yy0);
12601 +    buffer_copy_string_buffer(yygotominor.yy9->value, yymsp[-1].minor.yy0);    
12602 +}
12603 +#line 676 "http_resp_parser.c"
12604 +  yy_destructor(3,&yymsp[-2].minor);
12605 +  yy_destructor(1,&yymsp[0].minor);
12606 +        break;
12607 +  };
12608 +  yygoto = yyRuleInfo[yyruleno].lhs;
12609 +  yysize = yyRuleInfo[yyruleno].nrhs;
12610 +  yypParser->yyidx -= yysize;
12611 +  yyact = yy_find_reduce_action(yypParser,yygoto);
12612 +  if( yyact < YYNSTATE ){
12613 +    yy_shift(yypParser,yyact,yygoto,&yygotominor);
12614 +  }else if( yyact == YYNSTATE + YYNRULE + 1 ){
12615 +    yy_accept(yypParser);
12616 +  }
12617 +}
12618 +
12619 +/*
12620 +** The following code executes when the parse fails
12621 +*/
12622 +static void yy_parse_failed(
12623 +  yyParser *yypParser           /* The parser */
12624 +){
12625 +  http_resp_parserARG_FETCH;
12626 +#ifndef NDEBUG
12627 +  if( yyTraceFILE ){
12628 +    fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
12629 +  }
12630 +#endif
12631 +  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
12632 +  /* Here code is inserted which will be executed whenever the
12633 +  ** parser fails */
12634 +#line 14 "./http_resp_parser.y"
12635 +
12636 +  ctx->ok = 0;
12637 +
12638 +#line 711 "http_resp_parser.c"
12639 +  http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12640 +}
12641 +
12642 +/*
12643 +** The following code executes when a syntax error first occurs.
12644 +*/
12645 +static void yy_syntax_error(
12646 +  yyParser *yypParser,           /* The parser */
12647 +  int yymajor,                   /* The major type of the error token */
12648 +  YYMINORTYPE yyminor            /* The minor type of the error token */
12649 +){
12650 +  http_resp_parserARG_FETCH;
12651 +#define TOKEN (yyminor.yy0)
12652 +  http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12653 +}
12654 +
12655 +/*
12656 +** The following is executed when the parser accepts
12657 +*/
12658 +static void yy_accept(
12659 +  yyParser *yypParser           /* The parser */
12660 +){
12661 +  http_resp_parserARG_FETCH;
12662 +#ifndef NDEBUG
12663 +  if( yyTraceFILE ){
12664 +    fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
12665 +  }
12666 +#endif
12667 +  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
12668 +  /* Here code is inserted which will be executed whenever the
12669 +  ** parser accepts */
12670 +  http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12671 +}
12672 +
12673 +/* The main parser program.
12674 +** The first argument is a pointer to a structure obtained from
12675 +** "http_resp_parserAlloc" which describes the current state of the parser.
12676 +** The second argument is the major token number.  The third is
12677 +** the minor token.  The fourth optional argument is whatever the
12678 +** user wants (and specified in the grammar) and is available for
12679 +** use by the action routines.
12680 +**
12681 +** Inputs:
12682 +** <ul>
12683 +** <li> A pointer to the parser (an opaque structure.)
12684 +** <li> The major token number.
12685 +** <li> The minor token number.
12686 +** <li> An option argument of a grammar-specified type.
12687 +** </ul>
12688 +**
12689 +** Outputs:
12690 +** None.
12691 +*/
12692 +void http_resp_parser(
12693 +  void *yyp,                   /* The parser */
12694 +  int yymajor,                 /* The major token code number */
12695 +  http_resp_parserTOKENTYPE yyminor       /* The value for the token */
12696 +  http_resp_parserARG_PDECL               /* Optional %extra_argument parameter */
12697 +){
12698 +  YYMINORTYPE yyminorunion;
12699 +  int yyact;            /* The parser action. */
12700 +  int yyendofinput;     /* True if we are at the end of input */
12701 +  int yyerrorhit = 0;   /* True if yymajor has invoked an error */
12702 +  yyParser *yypParser;  /* The parser */
12703 +
12704 +  /* (re)initialize the parser, if necessary */
12705 +  yypParser = (yyParser*)yyp;
12706 +  if( yypParser->yyidx<0 ){
12707 +    if( yymajor==0 ) return;
12708 +    yypParser->yyidx = 0;
12709 +    yypParser->yyerrcnt = -1;
12710 +    yypParser->yystack[0].stateno = 0;
12711 +    yypParser->yystack[0].major = 0;
12712 +  }
12713 +  yyminorunion.yy0 = yyminor;
12714 +  yyendofinput = (yymajor==0);
12715 +  http_resp_parserARG_STORE;
12716 +
12717 +#ifndef NDEBUG
12718 +  if( yyTraceFILE ){
12719 +    fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
12720 +  }
12721 +#endif
12722 +
12723 +  do{
12724 +    yyact = yy_find_shift_action(yypParser,yymajor);
12725 +    if( yyact<YYNSTATE ){
12726 +      yy_shift(yypParser,yyact,yymajor,&yyminorunion);
12727 +      yypParser->yyerrcnt--;
12728 +      if( yyendofinput && yypParser->yyidx>=0 ){
12729 +        yymajor = 0;
12730 +      }else{
12731 +        yymajor = YYNOCODE;
12732 +      }
12733 +    }else if( yyact < YYNSTATE + YYNRULE ){
12734 +      yy_reduce(yypParser,yyact-YYNSTATE);
12735 +    }else if( yyact == YY_ERROR_ACTION ){
12736 +      int yymx;
12737 +#ifndef NDEBUG
12738 +      if( yyTraceFILE ){
12739 +        fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
12740 +      }
12741 +#endif
12742 +#ifdef YYERRORSYMBOL
12743 +      /* A syntax error has occurred.
12744 +      ** The response to an error depends upon whether or not the
12745 +      ** grammar defines an error token "ERROR".
12746 +      **
12747 +      ** This is what we do if the grammar does define ERROR:
12748 +      **
12749 +      **  * Call the %syntax_error function.
12750 +      **
12751 +      **  * Begin popping the stack until we enter a state where
12752 +      **    it is legal to shift the error symbol, then shift
12753 +      **    the error symbol.
12754 +      **
12755 +      **  * Set the error count to three.
12756 +      **
12757 +      **  * Begin accepting and shifting new tokens.  No new error
12758 +      **    processing will occur until three tokens have been
12759 +      **    shifted successfully.
12760 +      **
12761 +      */
12762 +      if( yypParser->yyerrcnt<0 ){
12763 +        yy_syntax_error(yypParser,yymajor,yyminorunion);
12764 +      }
12765 +      yymx = yypParser->yystack[yypParser->yyidx].major;
12766 +      if( yymx==YYERRORSYMBOL || yyerrorhit ){
12767 +#ifndef NDEBUG
12768 +        if( yyTraceFILE ){
12769 +          fprintf(yyTraceFILE,"%sDiscard input token %s\n",
12770 +             yyTracePrompt,yyTokenName[yymajor]);
12771 +        }
12772 +#endif
12773 +        yy_destructor(yymajor,&yyminorunion);
12774 +        yymajor = YYNOCODE;
12775 +      }else{
12776 +         while(
12777 +          yypParser->yyidx >= 0 &&
12778 +          yymx != YYERRORSYMBOL &&
12779 +          (yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE
12780 +        ){
12781 +          yy_pop_parser_stack(yypParser);
12782 +        }
12783 +        if( yypParser->yyidx < 0 || yymajor==0 ){
12784 +          yy_destructor(yymajor,&yyminorunion);
12785 +          yy_parse_failed(yypParser);
12786 +          yymajor = YYNOCODE;
12787 +        }else if( yymx!=YYERRORSYMBOL ){
12788 +          YYMINORTYPE u2;
12789 +          u2.YYERRSYMDT = 0;
12790 +          yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
12791 +        }
12792 +      }
12793 +      yypParser->yyerrcnt = 3;
12794 +      yyerrorhit = 1;
12795 +#else  /* YYERRORSYMBOL is not defined */
12796 +      /* This is what we do if the grammar does not define ERROR:
12797 +      **
12798 +      **  * Report an error message, and throw away the input token.
12799 +      **
12800 +      **  * If the input token is $, then fail the parse.
12801 +      **
12802 +      ** As before, subsequent error messages are suppressed until
12803 +      ** three input tokens have been successfully shifted.
12804 +      */
12805 +      if( yypParser->yyerrcnt<=0 ){
12806 +        yy_syntax_error(yypParser,yymajor,yyminorunion);
12807 +      }
12808 +      yypParser->yyerrcnt = 3;
12809 +      yy_destructor(yymajor,&yyminorunion);
12810 +      if( yyendofinput ){
12811 +        yy_parse_failed(yypParser);
12812 +      }
12813 +      yymajor = YYNOCODE;
12814 +#endif
12815 +    }else{
12816 +      yy_accept(yypParser);
12817 +      yymajor = YYNOCODE;
12818 +    }
12819 +  }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
12820 +  return;
12821 +}
12822 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/inet_ntop_cache.c lighttpd-1.4.12/src/inet_ntop_cache.c
12823 --- lighttpd-1.4.11/src/inet_ntop_cache.c       2005-08-11 01:26:38.000000000 +0300
12824 +++ lighttpd-1.4.12/src/inet_ntop_cache.c       2006-07-11 21:23:40.000000000 +0300
12825 @@ -8,7 +8,7 @@
12826  #include "sys-socket.h"
12827  
12828  const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr) {
12829 -#ifdef HAVE_IPV6       
12830 +#ifdef HAVE_IPV6
12831         size_t ndx = 0, i;
12832         for (i = 0; i < INET_NTOP_CACHE_MAX; i++) {
12833                 if (srv->inet_ntop_cache[i].ts != 0) {
12834 @@ -20,31 +20,31 @@
12835                                    srv->inet_ntop_cache[i].addr.ipv4.s_addr == addr->ipv4.sin_addr.s_addr) {
12836                                 /* IPv4 found in cache */
12837                                 break;
12838 -                               
12839 +
12840                         }
12841                 }
12842         }
12843 -       
12844 +
12845         if (i == INET_NTOP_CACHE_MAX) {
12846                 /* not found in cache */
12847 -               
12848 +
12849                 i = ndx;
12850 -               inet_ntop(addr->plain.sa_family, 
12851 -                         addr->plain.sa_family == AF_INET6 ? 
12852 +               inet_ntop(addr->plain.sa_family,
12853 +                         addr->plain.sa_family == AF_INET6 ?
12854                           (const void *) &(addr->ipv6.sin6_addr) :
12855                           (const void *) &(addr->ipv4.sin_addr),
12856                           srv->inet_ntop_cache[i].b2, INET6_ADDRSTRLEN);
12857 -               
12858 +
12859                 srv->inet_ntop_cache[i].ts = srv->cur_ts;
12860                 srv->inet_ntop_cache[i].family = addr->plain.sa_family;
12861 -               
12862 +
12863                 if (srv->inet_ntop_cache[i].family == AF_INET) {
12864                         srv->inet_ntop_cache[i].addr.ipv4.s_addr = addr->ipv4.sin_addr.s_addr;
12865                 } else if (srv->inet_ntop_cache[i].family == AF_INET6) {
12866                         memcpy(srv->inet_ntop_cache[i].addr.ipv6.s6_addr, addr->ipv6.sin6_addr.s6_addr, 16);
12867                 }
12868         }
12869 -       
12870 +
12871         return srv->inet_ntop_cache[i].b2;
12872  #else
12873         UNUSED(srv);
12874 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/joblist.c lighttpd-1.4.12/src/joblist.c
12875 --- lighttpd-1.4.11/src/joblist.c       2005-08-11 01:26:41.000000000 +0300
12876 +++ lighttpd-1.4.12/src/joblist.c       2006-07-11 21:23:39.000000000 +0300
12877 @@ -7,7 +7,7 @@
12878  
12879  int joblist_append(server *srv, connection *con) {
12880         if (con->in_joblist) return 0;
12881 -       
12882 +
12883         if (srv->joblist->size == 0) {
12884                 srv->joblist->size  = 16;
12885                 srv->joblist->ptr   = malloc(sizeof(*srv->joblist->ptr) * srv->joblist->size);
12886 @@ -15,15 +15,15 @@
12887                 srv->joblist->size += 16;
12888                 srv->joblist->ptr   = realloc(srv->joblist->ptr, sizeof(*srv->joblist->ptr) * srv->joblist->size);
12889         }
12890 -       
12891 +
12892         srv->joblist->ptr[srv->joblist->used++] = con;
12893 -       
12894 +
12895         return 0;
12896  }
12897  
12898  void joblist_free(server *srv, connections *joblist) {
12899         UNUSED(srv);
12900 -               
12901 +
12902         free(joblist->ptr);
12903         free(joblist);
12904  }
12905 @@ -31,14 +31,14 @@
12906  connection *fdwaitqueue_unshift(server *srv, connections *fdwaitqueue) {
12907         connection *con;
12908         UNUSED(srv);
12909 -               
12910 -       
12911 +
12912 +
12913         if (fdwaitqueue->used == 0) return NULL;
12914 -       
12915 +
12916         con = fdwaitqueue->ptr[0];
12917 -       
12918 +
12919         memmove(fdwaitqueue->ptr, &(fdwaitqueue->ptr[1]), --fdwaitqueue->used * sizeof(*(fdwaitqueue->ptr)));
12920 -       
12921 +
12922         return con;
12923  }
12924  
12925 @@ -50,9 +50,9 @@
12926                 srv->fdwaitqueue->size += 16;
12927                 srv->fdwaitqueue->ptr   = realloc(srv->fdwaitqueue->ptr, sizeof(*(srv->fdwaitqueue->ptr)) * srv->fdwaitqueue->size);
12928         }
12929 -       
12930 +
12931         srv->fdwaitqueue->ptr[srv->fdwaitqueue->used++] = con;
12932 -       
12933 +
12934         return 0;
12935  }
12936  
12937 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/keyvalue.c lighttpd-1.4.12/src/keyvalue.c
12938 --- lighttpd-1.4.11/src/keyvalue.c      2006-03-02 16:08:06.000000000 +0200
12939 +++ lighttpd-1.4.12/src/keyvalue.c      2006-07-11 21:23:40.000000000 +0300
12940 @@ -87,7 +87,8 @@
12941         { 504, "Gateway Timeout" },
12942         { 505, "HTTP Version Not Supported" },
12943         { 507, "Insufficient Storage" }, /* WebDAV */
12944 -       
12945 +       { 509, "Bandwidth Limit exceeded" },
12946 +
12947         { -1, NULL }
12948  };
12949  
12950 @@ -102,12 +103,12 @@
12951         { 501, "501.html" },
12952         { 503, "503.html" },
12953         { 505, "505.html" },
12954 -       
12955 +
12956         { -1, NULL }
12957  };
12958  
12959  
12960 -const char *keyvalue_get_value(keyvalue *kv, int k) { 
12961 +const char *keyvalue_get_value(keyvalue *kv, int k) {
12962         int i;
12963         for (i = 0; kv[i].value; i++) {
12964                 if (kv[i].key == k) return kv[i].value;
12965 @@ -115,7 +116,7 @@
12966         return NULL;
12967  }
12968  
12969 -int keyvalue_get_key(keyvalue *kv, const char *s) { 
12970 +int keyvalue_get_key(keyvalue *kv, const char *s) {
12971         int i;
12972         for (i = 0; kv[i].value; i++) {
12973                 if (0 == strcmp(kv[i].value, s)) return kv[i].key;
12974 @@ -125,9 +126,9 @@
12975  
12976  keyvalue_buffer *keyvalue_buffer_init(void) {
12977         keyvalue_buffer *kvb;
12978 -       
12979 +
12980         kvb = calloc(1, sizeof(*kvb));
12981 -       
12982 +
12983         return kvb;
12984  }
12985  
12986 @@ -135,49 +136,49 @@
12987         size_t i;
12988         if (kvb->size == 0) {
12989                 kvb->size = 4;
12990 -               
12991 +
12992                 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
12993 -               
12994 +
12995                 for(i = 0; i < kvb->size; i++) {
12996                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
12997                 }
12998         } else if (kvb->used == kvb->size) {
12999                 kvb->size += 4;
13000 -               
13001 +
13002                 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
13003 -               
13004 +
13005                 for(i = kvb->used; i < kvb->size; i++) {
13006                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
13007                 }
13008         }
13009 -       
13010 +
13011         kvb->kv[kvb->used]->key = key;
13012         kvb->kv[kvb->used]->value = strdup(value);
13013 -       
13014 +
13015         kvb->used++;
13016 -       
13017 +
13018         return 0;
13019  }
13020  
13021  void keyvalue_buffer_free(keyvalue_buffer *kvb) {
13022         size_t i;
13023 -       
13024 +
13025         for (i = 0; i < kvb->size; i++) {
13026                 if (kvb->kv[i]->value) free(kvb->kv[i]->value);
13027                 free(kvb->kv[i]);
13028         }
13029 -       
13030 +
13031         if (kvb->kv) free(kvb->kv);
13032 -       
13033 +
13034         free(kvb);
13035  }
13036  
13037  
13038  s_keyvalue_buffer *s_keyvalue_buffer_init(void) {
13039         s_keyvalue_buffer *kvb;
13040 -       
13041 +
13042         kvb = calloc(1, sizeof(*kvb));
13043 -       
13044 +
13045         return kvb;
13046  }
13047  
13048 @@ -186,50 +187,50 @@
13049         if (kvb->size == 0) {
13050                 kvb->size = 4;
13051                 kvb->used = 0;
13052 -               
13053 +
13054                 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
13055 -               
13056 +
13057                 for(i = 0; i < kvb->size; i++) {
13058                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
13059                 }
13060         } else if (kvb->used == kvb->size) {
13061                 kvb->size += 4;
13062 -               
13063 +
13064                 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
13065 -               
13066 +
13067                 for(i = kvb->used; i < kvb->size; i++) {
13068                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
13069                 }
13070         }
13071 -       
13072 +
13073         kvb->kv[kvb->used]->key = key ? strdup(key) : NULL;
13074         kvb->kv[kvb->used]->value = strdup(value);
13075 -       
13076 +
13077         kvb->used++;
13078 -       
13079 +
13080         return 0;
13081  }
13082  
13083  void s_keyvalue_buffer_free(s_keyvalue_buffer *kvb) {
13084         size_t i;
13085 -       
13086 +
13087         for (i = 0; i < kvb->size; i++) {
13088                 if (kvb->kv[i]->key) free(kvb->kv[i]->key);
13089                 if (kvb->kv[i]->value) free(kvb->kv[i]->value);
13090                 free(kvb->kv[i]);
13091         }
13092 -       
13093 +
13094         if (kvb->kv) free(kvb->kv);
13095 -       
13096 +
13097         free(kvb);
13098  }
13099  
13100  
13101  httpauth_keyvalue_buffer *httpauth_keyvalue_buffer_init(void) {
13102         httpauth_keyvalue_buffer *kvb;
13103 -       
13104 +
13105         kvb = calloc(1, sizeof(*kvb));
13106 -       
13107 +
13108         return kvb;
13109  }
13110  
13111 @@ -237,42 +238,42 @@
13112         size_t i;
13113         if (kvb->size == 0) {
13114                 kvb->size = 4;
13115 -               
13116 +
13117                 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
13118 -               
13119 +
13120                 for(i = 0; i < kvb->size; i++) {
13121                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
13122                 }
13123         } else if (kvb->used == kvb->size) {
13124                 kvb->size += 4;
13125 -               
13126 +
13127                 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
13128 -               
13129 +
13130                 for(i = kvb->used; i < kvb->size; i++) {
13131                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
13132                 }
13133         }
13134 -       
13135 +
13136         kvb->kv[kvb->used]->key = strdup(key);
13137         kvb->kv[kvb->used]->realm = strdup(realm);
13138         kvb->kv[kvb->used]->type = type;
13139 -       
13140 +
13141         kvb->used++;
13142 -       
13143 +
13144         return 0;
13145  }
13146  
13147  void httpauth_keyvalue_buffer_free(httpauth_keyvalue_buffer *kvb) {
13148         size_t i;
13149 -       
13150 +
13151         for (i = 0; i < kvb->size; i++) {
13152                 if (kvb->kv[i]->key) free(kvb->kv[i]->key);
13153                 if (kvb->kv[i]->realm) free(kvb->kv[i]->realm);
13154                 free(kvb->kv[i]);
13155         }
13156 -       
13157 +
13158         if (kvb->kv) free(kvb->kv);
13159 -       
13160 +
13161         free(kvb);
13162  }
13163  
13164 @@ -306,9 +307,9 @@
13165  
13166  pcre_keyvalue_buffer *pcre_keyvalue_buffer_init(void) {
13167         pcre_keyvalue_buffer *kvb;
13168 -       
13169 +
13170         kvb = calloc(1, sizeof(*kvb));
13171 -       
13172 +
13173         return kvb;
13174  }
13175  
13176 @@ -319,46 +320,46 @@
13177         int erroff;
13178         pcre_keyvalue *kv;
13179  #endif
13180 -       
13181 +
13182         if (!key) return -1;
13183  
13184  #ifdef HAVE_PCRE_H
13185         if (kvb->size == 0) {
13186                 kvb->size = 4;
13187                 kvb->used = 0;
13188 -               
13189 +
13190                 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
13191 -               
13192 +
13193                 for(i = 0; i < kvb->size; i++) {
13194                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
13195                 }
13196         } else if (kvb->used == kvb->size) {
13197                 kvb->size += 4;
13198 -               
13199 +
13200                 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
13201 -               
13202 +
13203                 for(i = kvb->used; i < kvb->size; i++) {
13204                         kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
13205                 }
13206         }
13207 -       
13208 +
13209         kv = kvb->kv[kvb->used];
13210         if (NULL == (kv->key = pcre_compile(key,
13211                                           0, &errptr, &erroff, NULL))) {
13212 -               
13213 +
13214                 fprintf(stderr, "%s.%d: rexexp compilation error at %s\n", __FILE__, __LINE__, errptr);
13215                 return -1;
13216         }
13217  
13218 -       if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&  
13219 +       if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
13220                         errptr != NULL) {
13221                 return -1;
13222         }
13223 -       
13224 +
13225         kv->value = buffer_init_string(value);
13226 -       
13227 +
13228         kvb->used++;
13229 -       
13230 +
13231         return 0;
13232  #else
13233         UNUSED(kvb);
13234 @@ -380,9 +381,9 @@
13235                 if (kv->value) buffer_free(kv->value);
13236                 free(kv);
13237         }
13238 -       
13239 +
13240         if (kvb->kv) free(kvb->kv);
13241  #endif
13242 -       
13243 +
13244         free(kvb);
13245  }
13246 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/keyvalue.h lighttpd-1.4.12/src/keyvalue.h
13247 --- lighttpd-1.4.11/src/keyvalue.h      2006-03-02 16:08:06.000000000 +0200
13248 +++ lighttpd-1.4.12/src/keyvalue.h      2006-07-11 21:23:40.000000000 +0300
13249 @@ -9,19 +9,19 @@
13250  # include <pcre.h>
13251  #endif
13252  
13253 -typedef enum { 
13254 -       HTTP_METHOD_UNSET = -1, 
13255 -       HTTP_METHOD_GET, 
13256 -       HTTP_METHOD_POST, 
13257 -       HTTP_METHOD_HEAD, 
13258 -       HTTP_METHOD_OPTIONS, 
13259 +typedef enum {
13260 +       HTTP_METHOD_UNSET = -1,
13261 +       HTTP_METHOD_GET,
13262 +       HTTP_METHOD_POST,
13263 +       HTTP_METHOD_HEAD,
13264 +       HTTP_METHOD_OPTIONS,
13265         HTTP_METHOD_PROPFIND,  /* WebDAV */
13266 -       HTTP_METHOD_MKCOL, 
13267 -       HTTP_METHOD_PUT, 
13268 -       HTTP_METHOD_DELETE, 
13269 -       HTTP_METHOD_COPY, 
13270 -       HTTP_METHOD_MOVE, 
13271 -       HTTP_METHOD_PROPPATCH, 
13272 +       HTTP_METHOD_MKCOL,
13273 +       HTTP_METHOD_PUT,
13274 +       HTTP_METHOD_DELETE,
13275 +       HTTP_METHOD_COPY,
13276 +       HTTP_METHOD_MOVE,
13277 +       HTTP_METHOD_PROPPATCH,
13278         HTTP_METHOD_REPORT, /* DeltaV */
13279         HTTP_METHOD_CHECKOUT,
13280         HTTP_METHOD_CHECKIN,
13281 @@ -39,13 +39,13 @@
13282  
13283  typedef struct {
13284         int key;
13285 -       
13286 +
13287         char *value;
13288  } keyvalue;
13289  
13290  typedef struct {
13291         char *key;
13292 -       
13293 +
13294         char *value;
13295  } s_keyvalue;
13296  
13297 @@ -54,7 +54,7 @@
13298         pcre *key;
13299         pcre_extra *key_extra;
13300  #endif
13301 -       
13302 +
13303         buffer *value;
13304  } pcre_keyvalue;
13305  
13306 @@ -62,7 +62,7 @@
13307  
13308  typedef struct {
13309         char *key;
13310 -       
13311 +
13312         char *realm;
13313         httpauth_type type;
13314  } httpauth_keyvalue;
13315 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/lemon.c lighttpd-1.4.12/src/lemon.c
13316 --- lighttpd-1.4.11/src/lemon.c 2005-09-01 00:21:34.000000000 +0300
13317 +++ lighttpd-1.4.12/src/lemon.c 2006-07-11 21:23:40.000000000 +0300
13318 @@ -579,7 +579,7 @@
13319  */
13320  
13321  /* Find a precedence symbol of every rule in the grammar.
13322 -** 
13323 +**
13324  ** Those rules which have a precedence symbol coded in the input
13325  ** grammar using the "[symbol]" construct will already have the
13326  ** rp->precsym field filled.  Other rules take as their precedence
13327 @@ -869,7 +869,7 @@
13328        cfp->status = INCOMPLETE;
13329      }
13330    }
13331 -  
13332 +
13333    do{
13334      progress = 0;
13335      for(i=0; i<lemp->nstate; i++){
13336 @@ -900,7 +900,7 @@
13337    struct symbol *sp;
13338    struct rule *rp;
13339  
13340 -  /* Add all of the reduce actions 
13341 +  /* Add all of the reduce actions
13342    ** A reduce action is added for each element of the followset of
13343    ** a configuration which has its dot at the extreme right.
13344    */
13345 @@ -1017,7 +1017,7 @@
13346        apx->type = RD_RESOLVED;
13347      }
13348    }else{
13349 -    assert( 
13350 +    assert(
13351        apx->type==SH_RESOLVED ||
13352        apx->type==RD_RESOLVED ||
13353        apx->type==CONFLICT ||
13354 @@ -1350,7 +1350,7 @@
13355    OptInit(argv,options,stderr);
13356    if( version ){
13357       printf("Lemon version 1.0\n");
13358 -     exit(0); 
13359 +     exit(0);
13360    }
13361    if( OptNArgs() < 1 ){
13362      fprintf(stderr,"Exactly one filename argument is required.\n");
13363 @@ -2031,7 +2031,7 @@
13364      case IN_RHS:
13365        if( x[0]=='.' ){
13366          struct rule *rp;
13367 -        rp = (struct rule *)malloc( sizeof(struct rule) + 
13368 +        rp = (struct rule *)malloc( sizeof(struct rule) +
13369               sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs );
13370          if( rp==0 ){
13371            ErrorMsg(psp->filename,psp->tokenlineno,
13372 @@ -2546,7 +2546,7 @@
13373    return fp;
13374  }
13375  
13376 -/* Duplicate the input file without comments and without actions 
13377 +/* Duplicate the input file without comments and without actions
13378  ** on rules */
13379  void Reprint(lemp)
13380  struct lemon *lemp;
13381 @@ -2822,7 +2822,7 @@
13382  PRIVATE FILE *tplt_open(lemp)
13383  struct lemon *lemp;
13384  {
13385 -  
13386 +
13387    char buf[1000];
13388    FILE *in;
13389    char *tpltname;
13390 @@ -2930,7 +2930,7 @@
13391    return ret;
13392  }
13393  
13394 -/* 
13395 +/*
13396  ** Generate code which executes when the rule "rp" is reduced.  Write
13397  ** the code to "out".  Make sure lineno stays up-to-date.
13398  */
13399 @@ -3384,7 +3384,7 @@
13400  
13401    /* Output the yy_shift_ofst[] table */
13402    fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
13403 -  fprintf(out, "static %s yy_shift_ofst[] = {\n", 
13404 +  fprintf(out, "static %s yy_shift_ofst[] = {\n",
13405            minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++;
13406    n = lemp->nstate;
13407    for(i=j=0; i<n; i++){
13408 @@ -3405,7 +3405,7 @@
13409  
13410    /* Output the yy_reduce_ofst[] table */
13411    fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
13412 -  fprintf(out, "static %s yy_reduce_ofst[] = {\n", 
13413 +  fprintf(out, "static %s yy_reduce_ofst[] = {\n",
13414            minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++;
13415    n = lemp->nstate;
13416    for(i=j=0; i<n; i++){
13417 @@ -3480,7 +3480,7 @@
13418    tplt_xfer(lemp->name,in,out,&lineno);
13419  
13420    /* Generate code which executes every time a symbol is popped from
13421 -  ** the stack while processing errors or while destroying the parser. 
13422 +  ** the stack while processing errors or while destroying the parser.
13423    ** (In other words, generate the %destructor actions)
13424    */
13425    if( lemp->tokendest ){
13426 @@ -3522,7 +3522,7 @@
13427    tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno);
13428    tplt_xfer(lemp->name,in,out,&lineno);
13429  
13430 -  /* Generate the table of rule information 
13431 +  /* Generate the table of rule information
13432    **
13433    ** Note: This code depends on the fact that rules are number
13434    ** sequentually beginning with 0.
13435 @@ -3589,7 +3589,7 @@
13436      for(i=1; i<lemp->nterminal; i++){
13437        fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
13438      }
13439 -    fclose(out);  
13440 +    fclose(out);
13441    }
13442    return;
13443  }
13444 @@ -3630,7 +3630,7 @@
13445          rbest = rp;
13446        }
13447      }
13448
13449 +
13450      /* Do not make a default if the number of rules to default
13451      ** is not at least 2 */
13452      if( nbest<2 ) continue;
13453 @@ -3781,7 +3781,7 @@
13454    if( x1a ){
13455      x1a->size = 1024;
13456      x1a->count = 0;
13457 -    x1a->tbl = (x1node*)malloc( 
13458 +    x1a->tbl = (x1node*)malloc(
13459        (sizeof(x1node) + sizeof(x1node*))*1024 );
13460      if( x1a->tbl==0 ){
13461        free(x1a);
13462 @@ -3943,7 +3943,7 @@
13463    if( x2a ){
13464      x2a->size = 128;
13465      x2a->count = 0;
13466 -    x2a->tbl = (x2node*)malloc( 
13467 +    x2a->tbl = (x2node*)malloc(
13468        (sizeof(x2node) + sizeof(x2node*))*128 );
13469      if( x2a->tbl==0 ){
13470        free(x2a);
13471 @@ -4149,7 +4149,7 @@
13472    if( x3a ){
13473      x3a->size = 128;
13474      x3a->count = 0;
13475 -    x3a->tbl = (x3node*)malloc( 
13476 +    x3a->tbl = (x3node*)malloc(
13477        (sizeof(x3node) + sizeof(x3node*))*128 );
13478      if( x3a->tbl==0 ){
13479        free(x3a);
13480 @@ -4295,7 +4295,7 @@
13481    if( x4a ){
13482      x4a->size = 64;
13483      x4a->count = 0;
13484 -    x4a->tbl = (x4node*)malloc( 
13485 +    x4a->tbl = (x4node*)malloc(
13486        (sizeof(x4node) + sizeof(x4node*))*64 );
13487      if( x4a->tbl==0 ){
13488        free(x4a);
13489 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/lempar.c lighttpd-1.4.12/src/lempar.c
13490 --- lighttpd-1.4.11/src/lempar.c        2005-08-11 01:26:40.000000000 +0300
13491 +++ lighttpd-1.4.12/src/lempar.c        2006-07-11 21:23:39.000000000 +0300
13492 @@ -8,10 +8,10 @@
13493  /* Next is all token values, in a form suitable for use by makeheaders.
13494  ** This section will be null unless lemon is run with the -m switch.
13495  */
13496 -/* 
13497 +/*
13498  ** These constants (all generated automatically by the parser generator)
13499  ** specify the various kinds of tokens (terminals) that the parser
13500 -** understands. 
13501 +** understands.
13502  **
13503  ** Each symbol here is a terminal symbol in the grammar.
13504  */
13505 @@ -29,7 +29,7 @@
13506  **                       and nonterminals.  "int" is used otherwise.
13507  **    YYNOCODE           is a number of type YYCODETYPE which corresponds
13508  **                       to no legal terminal or nonterminal number.  This
13509 -**                       number is used to fill in empty slots of the hash 
13510 +**                       number is used to fill in empty slots of the hash
13511  **                       table.
13512  **    YYFALLBACK         If defined, this indicates that one or more tokens
13513  **                       have fall-back values which should be used if the
13514 @@ -38,7 +38,7 @@
13515  **                       and nonterminal numbers.  "unsigned char" is
13516  **                       used if there are fewer than 250 rules and
13517  **                       states combined.  "int" is used otherwise.
13518 -**    ParseTOKENTYPE     is the data type used for minor tokens given 
13519 +**    ParseTOKENTYPE     is the data type used for minor tokens given
13520  **                       directly to the parser from the tokenizer.
13521  **    YYMINORTYPE        is the data type used for all minor tokens.
13522  **                       This is typically a union of many types, one of
13523 @@ -62,7 +62,7 @@
13524  /* Next are that tables used to determine what action to take based on the
13525  ** current state and lookahead token.  These tables are used to implement
13526  ** functions that take a state number and lookahead value and return an
13527 -** action integer.  
13528 +** action integer.
13529  **
13530  ** Suppose the action integer is N.  Then the action is determined as
13531  ** follows
13532 @@ -87,7 +87,7 @@
13533  ** If the index value yy_shift_ofst[S]+X is out of range or if the value
13534  ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
13535  ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
13536 -** and that yy_default[S] should be used instead.  
13537 +** and that yy_default[S] should be used instead.
13538  **
13539  ** The formula above is for computing the action when the lookahead is
13540  ** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
13541 @@ -111,7 +111,7 @@
13542  
13543  /* The next table maps tokens into fallback tokens.  If a construct
13544  ** like the following:
13545 -** 
13546 +**
13547  **      %fallback ID X Y Z.
13548  **
13549  ** appears in the grammer, then ID becomes a fallback token for X, Y,
13550 @@ -163,10 +163,10 @@
13551  #endif /* NDEBUG */
13552  
13553  #ifndef NDEBUG
13554 -/* 
13555 +/*
13556  ** Turn parser tracing on by giving a stream to which to write the trace
13557  ** and a prompt to preface each trace message.  Tracing is turned off
13558 -** by making either argument NULL 
13559 +** by making either argument NULL
13560  **
13561  ** Inputs:
13562  ** <ul>
13563 @@ -191,7 +191,7 @@
13564  #ifndef NDEBUG
13565  /* For tracing shifts, the names of all terminals and nonterminals
13566  ** are required.  The following table supplies these names */
13567 -static const char *yyTokenName[] = { 
13568 +static const char *yyTokenName[] = {
13569  %%
13570  };
13571  #endif /* NDEBUG */
13572 @@ -220,7 +220,7 @@
13573  #endif
13574  }
13575  
13576 -/* 
13577 +/*
13578  ** This function allocates a new parser.
13579  ** The only argument is a pointer to a function which works like
13580  ** malloc.
13581 @@ -251,7 +251,7 @@
13582      /* Here is inserted the actions which take place when a
13583      ** terminal or non-terminal is destroyed.  This can happen
13584      ** when the symbol is popped from the stack during a
13585 -    ** reduce or during error processing or when a parser is 
13586 +    ** reduce or during error processing or when a parser is
13587      ** being destroyed before it is finished parsing.
13588      **
13589      ** Note: during a reduce, the only symbols destroyed are those
13590 @@ -289,7 +289,7 @@
13591    return yymajor;
13592  }
13593  
13594 -/* 
13595 +/*
13596  ** Deallocate and destroy a parser.  Destructors are all called for
13597  ** all stack elements before shutting the parser down.
13598  **
13599 @@ -325,7 +325,7 @@
13600  ){
13601    int i;
13602    int stateno = pParser->yystack[pParser->yyidx].stateno;
13603
13604 +
13605    /* if( pParser->yyidx<0 ) return YY_NO_ACTION;  */
13606    i = yy_shift_ofst[stateno];
13607    if( i==YY_SHIFT_USE_DFLT ){
13608 @@ -369,7 +369,7 @@
13609  ){
13610    int i;
13611    int stateno = pParser->yystack[pParser->yyidx].stateno;
13612
13613 +
13614    i = yy_reduce_ofst[stateno];
13615    if( i==YY_REDUCE_USE_DFLT ){
13616      return yy_default[stateno];
13617 @@ -455,7 +455,7 @@
13618    ParseARG_FETCH;
13619    yymsp = &yypParser->yystack[yypParser->yyidx];
13620  #ifndef NDEBUG
13621 -  if( yyTraceFILE && yyruleno>=0 
13622 +  if( yyTraceFILE && yyruleno>=0
13623          && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
13624      fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
13625        yyRuleName[yyruleno]);
13626 @@ -608,7 +608,7 @@
13627  #ifdef YYERRORSYMBOL
13628        /* A syntax error has occurred.
13629        ** The response to an error depends upon whether or not the
13630 -      ** grammar defines an error token "ERROR".  
13631 +      ** grammar defines an error token "ERROR".
13632        **
13633        ** This is what we do if the grammar does define ERROR:
13634        **
13635 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/log.c lighttpd-1.4.12/src/log.c
13636 --- lighttpd-1.4.11/src/log.c   2005-11-07 15:01:35.000000000 +0200
13637 +++ lighttpd-1.4.12/src/log.c   2006-07-11 21:23:40.000000000 +0300
13638 @@ -5,7 +5,6 @@
13639  #include <errno.h>
13640  #include <fcntl.h>
13641  #include <time.h>
13642 -#include <unistd.h>
13643  #include <string.h>
13644  #include <stdlib.h>
13645  
13646 @@ -16,6 +15,10 @@
13647  #include "config.h"
13648  #endif
13649  
13650 +#ifdef _WIN32
13651 +#undef HAVE_SYSLOG_H
13652 +#endif
13653 +
13654  #ifdef HAVE_SYSLOG_H
13655  #include <syslog.h>
13656  #endif
13657 @@ -23,6 +26,8 @@
13658  #include "log.h"
13659  #include "array.h"
13660  
13661 +#include "sys-files.h"
13662 +
13663  #ifdef HAVE_VALGRIND_VALGRIND_H
13664  #include <valgrind/valgrind.h>
13665  #endif
13666 @@ -31,38 +36,38 @@
13667  # define O_LARGEFILE 0
13668  #endif
13669  
13670 -/** 
13671 +/**
13672   * open the errorlog
13673 - * 
13674 + *
13675   * we have 3 possibilities:
13676   * - stderr (default)
13677 - * - syslog 
13678 + * - syslog
13679   * - logfile
13680 - * 
13681 + *
13682   * if the open failed, report to the user and die
13683 - * 
13684 + *
13685   */
13686  
13687  int log_error_open(server *srv) {
13688         int fd;
13689         int close_stderr = 1;
13690 -       
13691 +
13692  #ifdef HAVE_SYSLOG_H
13693         /* perhaps someone wants to use syslog() */
13694         openlog("lighttpd", LOG_CONS | LOG_PID, LOG_DAEMON);
13695  #endif
13696         srv->errorlog_mode = ERRORLOG_STDERR;
13697 -       
13698 +
13699         if (srv->srvconf.errorlog_use_syslog) {
13700                 srv->errorlog_mode = ERRORLOG_SYSLOG;
13701         } else if (!buffer_is_empty(srv->srvconf.errorlog_file)) {
13702                 const char *logfile = srv->srvconf.errorlog_file->ptr;
13703 -               
13704 +
13705                 if (-1 == (srv->errorlog_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
13706 -                       log_error_write(srv, __FILE__, __LINE__, "SSSS", 
13707 +                       log_error_write(srv, __FILE__, __LINE__, "SSSS",
13708                                         "opening errorlog '", logfile,
13709                                         "' failed: ", strerror(errno));
13710 -                       
13711 +
13712                         return -1;
13713                 }
13714  #ifdef FD_CLOEXEC
13715 @@ -71,15 +76,15 @@
13716  #endif
13717                 srv->errorlog_mode = ERRORLOG_FILE;
13718         }
13719 -       
13720 +
13721         log_error_write(srv, __FILE__, __LINE__, "s", "server started");
13722 -       
13723 +
13724  #ifdef HAVE_VALGRIND_VALGRIND_H
13725         /* don't close stderr for debugging purposes if run in valgrind */
13726         if (RUNNING_ON_VALGRIND) close_stderr = 0;
13727  #endif
13728         if (srv->errorlog_mode == ERRORLOG_STDERR) close_stderr = 0;
13729 -       
13730 +
13731         /* move stderr to /dev/null */
13732         if (close_stderr &&
13733             -1 != (fd = open("/dev/null", O_WRONLY))) {
13734 @@ -90,33 +95,33 @@
13735         return 0;
13736  }
13737  
13738 -/** 
13739 +/**
13740   * open the errorlog
13741 - * 
13742 + *
13743   * if the open failed, report to the user and die
13744   * if no filename is given, use syslog instead
13745 - * 
13746 + *
13747   */
13748  
13749  int log_error_cycle(server *srv) {
13750         /* only cycle if we are not in syslog-mode */
13751 -       
13752 +
13753         if (srv->errorlog_mode == ERRORLOG_FILE) {
13754                 const char *logfile = srv->srvconf.errorlog_file->ptr;
13755                 /* already check of opening time */
13756 -               
13757 +
13758                 int new_fd;
13759 -               
13760 +
13761                 if (-1 == (new_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
13762                         /* write to old log */
13763 -                       log_error_write(srv, __FILE__, __LINE__, "SSSSS", 
13764 +                       log_error_write(srv, __FILE__, __LINE__, "SSSSS",
13765                                         "cycling errorlog '", logfile,
13766                                         "' failed: ", strerror(errno),
13767                                         ", falling back to syslog()");
13768 -                       
13769 +
13770                         close(srv->errorlog_fd);
13771                         srv->errorlog_fd = -1;
13772 -#ifdef HAVE_SYSLOG_H   
13773 +#ifdef HAVE_SYSLOG_H
13774                         srv->errorlog_mode = ERRORLOG_SYSLOG;
13775  #endif
13776                 } else {
13777 @@ -125,15 +130,15 @@
13778                         srv->errorlog_fd = new_fd;
13779                 }
13780         }
13781 -       
13782 +
13783         log_error_write(srv, __FILE__, __LINE__, "s", "logfiles cycled");
13784 -       
13785 +
13786         return 0;
13787  }
13788  
13789  int log_error_close(server *srv) {
13790         log_error_write(srv, __FILE__, __LINE__, "s", "server stopped");
13791 -       
13792 +
13793         switch(srv->errorlog_mode) {
13794         case ERRORLOG_FILE:
13795                 close(srv->errorlog_fd);
13796 @@ -146,13 +151,13 @@
13797         case ERRORLOG_STDERR:
13798                 break;
13799         }
13800 -       
13801 +
13802         return 0;
13803  }
13804  
13805  int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) {
13806         va_list ap;
13807 -       
13808 +
13809         switch(srv->errorlog_mode) {
13810         case ERRORLOG_FILE:
13811         case ERRORLOG_STDERR:
13812 @@ -161,7 +166,7 @@
13813                         buffer_prepare_copy(srv->ts_debug_str, 255);
13814                         strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts)));
13815                         srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1;
13816 -                       
13817 +
13818                         srv->last_generated_debug_ts = srv->cur_ts;
13819                 }
13820  
13821 @@ -173,19 +178,19 @@
13822                 BUFFER_COPY_STRING_CONST(srv->errorlog_buf, "(");
13823                 break;
13824         }
13825 -       
13826 +
13827         buffer_append_string(srv->errorlog_buf, filename);
13828         BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ".");
13829         buffer_append_long(srv->errorlog_buf, line);
13830         BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ") ");
13831 -       
13832 -       
13833 +
13834 +
13835         for(va_start(ap, fmt); *fmt; fmt++) {
13836                 int d;
13837                 char *s;
13838                 buffer *b;
13839                 off_t o;
13840 -               
13841 +
13842                 switch(*fmt) {
13843                 case 's':           /* string */
13844                         s = va_arg(ap, char *);
13845 @@ -227,7 +232,7 @@
13846                         break;
13847                 case '(':
13848                 case ')':
13849 -               case '<':       
13850 +               case '<':
13851                 case '>':
13852                 case ',':
13853                 case ' ':
13854 @@ -236,7 +241,7 @@
13855                 }
13856         }
13857         va_end(ap);
13858 -       
13859 +
13860         switch(srv->errorlog_mode) {
13861         case ERRORLOG_FILE:
13862                 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
13863 @@ -246,11 +251,13 @@
13864                 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
13865                 write(STDERR_FILENO, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1);
13866                 break;
13867 +#ifdef HAVE_SYSLOG_H
13868         case ERRORLOG_SYSLOG:
13869                 syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr);
13870                 break;
13871 +#endif
13872         }
13873 -       
13874 +
13875         return 0;
13876  }
13877  
13878 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/log.h lighttpd-1.4.12/src/log.h
13879 --- lighttpd-1.4.11/src/log.h   2005-08-11 01:26:36.000000000 +0300
13880 +++ lighttpd-1.4.12/src/log.h   2006-07-11 21:23:40.000000000 +0300
13881 @@ -9,5 +9,5 @@
13882  int log_error_close(server *srv);
13883  int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...);
13884  int log_error_cycle(server *srv);
13885 -       
13886 +
13887  #endif
13888 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/md5.h lighttpd-1.4.12/src/md5.h
13889 --- lighttpd-1.4.11/src/md5.h   2005-11-17 16:20:40.000000000 +0200
13890 +++ lighttpd-1.4.12/src/md5.h   2006-07-11 21:23:40.000000000 +0300
13891 @@ -30,9 +30,15 @@
13892  # include <inttypes.h>
13893  #endif
13894  
13895 +#ifdef _WIN32
13896 +#define UINT4 unsigned __int32
13897 +#define UINT2 unsigned __int16
13898 +#define POINTER unsigned char *
13899 +#else
13900  #define UINT4 uint32_t
13901  #define UINT2 uint16_t
13902  #define POINTER unsigned char *
13903 +#endif
13904  
13905  /* MD5 context. */
13906  typedef struct {
13907 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_access.c lighttpd-1.4.12/src/mod_access.c
13908 --- lighttpd-1.4.11/src/mod_access.c    2006-01-14 19:44:54.000000000 +0200
13909 +++ lighttpd-1.4.12/src/mod_access.c    2006-07-11 21:23:40.000000000 +0300
13910 @@ -8,126 +8,125 @@
13911  
13912  #include "plugin.h"
13913  
13914 +#include "sys-strings.h"
13915 +
13916  typedef struct {
13917         array *access_deny;
13918  } plugin_config;
13919  
13920  typedef struct {
13921         PLUGIN_DATA;
13922 -       
13923 +
13924         plugin_config **config_storage;
13925 -       
13926 -       plugin_config conf; 
13927 +
13928 +       plugin_config conf;
13929  } plugin_data;
13930  
13931  INIT_FUNC(mod_access_init) {
13932         plugin_data *p;
13933 -       
13934 +
13935         p = calloc(1, sizeof(*p));
13936 -       
13937 +
13938         return p;
13939  }
13940  
13941  FREE_FUNC(mod_access_free) {
13942         plugin_data *p = p_d;
13943 -       
13944 +
13945         UNUSED(srv);
13946  
13947         if (!p) return HANDLER_GO_ON;
13948 -       
13949 +
13950         if (p->config_storage) {
13951                 size_t i;
13952                 for (i = 0; i < srv->config_context->used; i++) {
13953                         plugin_config *s = p->config_storage[i];
13954 -                       
13955 +
13956                         array_free(s->access_deny);
13957 -                       
13958 +
13959                         free(s);
13960                 }
13961                 free(p->config_storage);
13962         }
13963 -       
13964 +
13965         free(p);
13966 -       
13967 +
13968         return HANDLER_GO_ON;
13969  }
13970  
13971  SETDEFAULTS_FUNC(mod_access_set_defaults) {
13972         plugin_data *p = p_d;
13973         size_t i = 0;
13974 -       
13975 -       config_values_t cv[] = { 
13976 +
13977 +       config_values_t cv[] = {
13978                 { "url.access-deny",             NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
13979                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
13980         };
13981 -       
13982 +
13983         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
13984 -       
13985 +
13986         for (i = 0; i < srv->config_context->used; i++) {
13987                 plugin_config *s;
13988 -               
13989 +
13990                 s = calloc(1, sizeof(plugin_config));
13991                 s->access_deny    = array_init();
13992 -               
13993 +
13994                 cv[0].destination = s->access_deny;
13995 -               
13996 +
13997                 p->config_storage[i] = s;
13998 -       
13999 +
14000                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
14001                         return HANDLER_ERROR;
14002                 }
14003         }
14004 -       
14005 +
14006         return HANDLER_GO_ON;
14007  }
14008  
14009 -#define PATCH(x) \
14010 -       p->conf.x = s->x;
14011  static int mod_access_patch_connection(server *srv, connection *con, plugin_data *p) {
14012         size_t i, j;
14013         plugin_config *s = p->config_storage[0];
14014  
14015 -       PATCH(access_deny);
14016 -       
14017 +       PATCH_OPTION(access_deny);
14018 +
14019         /* skip the first, the global context */
14020         for (i = 1; i < srv->config_context->used; i++) {
14021                 data_config *dc = (data_config *)srv->config_context->data[i];
14022                 s = p->config_storage[i];
14023 -               
14024 +
14025                 /* condition didn't match */
14026                 if (!config_check_cond(srv, con, dc)) continue;
14027 -               
14028 +
14029                 /* merge config */
14030                 for (j = 0; j < dc->value->used; j++) {
14031                         data_unset *du = dc->value->data[j];
14032 -                       
14033 +
14034                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.access-deny"))) {
14035 -                               PATCH(access_deny);
14036 +                               PATCH_OPTION(access_deny);
14037                         }
14038                 }
14039         }
14040 -       
14041 +
14042         return 0;
14043  }
14044 -#undef PATCH
14045  
14046  URIHANDLER_FUNC(mod_access_uri_handler) {
14047         plugin_data *p = p_d;
14048         int s_len;
14049         size_t k;
14050 -       
14051 +
14052         if (con->uri.path->used == 0) return HANDLER_GO_ON;
14053 -       
14054 +
14055         mod_access_patch_connection(srv, con, p);
14056 -       
14057 +
14058         s_len = con->uri.path->used - 1;
14059 -       
14060 +
14061         for (k = 0; k < p->conf.access_deny->used; k++) {
14062                 data_string *ds = (data_string *)p->conf.access_deny->data[k];
14063                 int ct_len = ds->value->used - 1;
14064 -               
14065 +
14066                 if (ct_len > s_len) continue;
14067 -               
14068 +
14069                 if (ds->value->used == 0) continue;
14070  
14071                 /* if we have a case-insensitive FS we have to lower-case the URI here too */
14072 @@ -135,18 +134,18 @@
14073                 if (con->conf.force_lowercase_filenames) {
14074                         if (0 == strncasecmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
14075                                 con->http_status = 403;
14076 -                       
14077 +
14078                                 return HANDLER_FINISHED;
14079                         }
14080                 } else {
14081                         if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
14082                                 con->http_status = 403;
14083 -                       
14084 +
14085                                 return HANDLER_FINISHED;
14086                         }
14087                 }
14088         }
14089 -       
14090 +
14091         /* not found */
14092         return HANDLER_GO_ON;
14093  }
14094 @@ -155,13 +154,13 @@
14095  int mod_access_plugin_init(plugin *p) {
14096         p->version     = LIGHTTPD_VERSION_ID;
14097         p->name        = buffer_init_string("access");
14098 -       
14099 +
14100         p->init        = mod_access_init;
14101         p->set_defaults = mod_access_set_defaults;
14102         p->handle_uri_clean  = mod_access_uri_handler;
14103         p->cleanup     = mod_access_free;
14104 -       
14105 +
14106         p->data        = NULL;
14107 -       
14108 +
14109         return 0;
14110  }
14111 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_accesslog.c lighttpd-1.4.12/src/mod_accesslog.c
14112 --- lighttpd-1.4.11/src/mod_accesslog.c 2006-01-31 14:01:43.000000000 +0200
14113 +++ lighttpd-1.4.12/src/mod_accesslog.c 2006-07-11 21:23:40.000000000 +0300
14114 @@ -6,8 +6,7 @@
14115  #include <ctype.h>
14116  #include <stdlib.h>
14117  #include <string.h>
14118 -#include <fcntl.h>
14119 -#include <unistd.h>
14120 +#include <fcntl.h> /* only the defines on windows */
14121  #include <errno.h>
14122  #include <time.h>
14123  
14124 @@ -22,6 +21,7 @@
14125  #include "inet_ntop_cache.h"
14126  
14127  #include "sys-socket.h"
14128 +#include "sys-files.h"
14129  
14130  #ifdef HAVE_SYSLOG_H
14131  # include <syslog.h>
14132 @@ -29,7 +29,7 @@
14133  
14134  typedef struct {
14135         char key;
14136 -       enum { 
14137 +       enum {
14138                 FORMAT_UNSET,
14139                         FORMAT_UNSUPPORTED,
14140                         FORMAT_PERCENT,
14141 @@ -41,7 +41,7 @@
14142                         FORMAT_STATUS,
14143                         FORMAT_BYTES_OUT_NO_HEADER,
14144                         FORMAT_HEADER,
14145 -                       
14146 +
14147                         FORMAT_REMOTE_ADDR,
14148                         FORMAT_LOCAL_ADDR,
14149                         FORMAT_COOKIE,
14150 @@ -59,20 +59,20 @@
14151                         FORMAT_CONNECTION_STATUS,
14152                         FORMAT_BYTES_IN,
14153                         FORMAT_BYTES_OUT,
14154 -                       
14155 +
14156                         FORMAT_RESPONSE_HEADER
14157         } type;
14158  } format_mapping;
14159  
14160  /**
14161 - * 
14162 - * 
14163 + *
14164 + *
14165   * "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
14166 - * 
14167 + *
14168   */
14169  
14170 -const format_mapping fmap[] = 
14171 -{ 
14172 +const format_mapping fmap[] =
14173 +{
14174         { '%', FORMAT_PERCENT },
14175         { 'h', FORMAT_REMOTE_HOST },
14176         { 'l', FORMAT_REMOTE_IDENT },
14177 @@ -82,7 +82,7 @@
14178         { 's', FORMAT_STATUS },
14179         { 'b', FORMAT_BYTES_OUT_NO_HEADER },
14180         { 'i', FORMAT_HEADER },
14181 -       
14182 +
14183         { 'a', FORMAT_REMOTE_ADDR },
14184         { 'A', FORMAT_LOCAL_ADDR },
14185         { 'B', FORMAT_BYTES_OUT_NO_HEADER },
14186 @@ -103,23 +103,23 @@
14187         { 'X', FORMAT_CONNECTION_STATUS },
14188         { 'I', FORMAT_BYTES_IN },
14189         { 'O', FORMAT_BYTES_OUT },
14190 -       
14191 +
14192         { 'o', FORMAT_RESPONSE_HEADER },
14193 -       
14194 +
14195         { '\0', FORMAT_UNSET }
14196  };
14197  
14198  
14199  typedef struct {
14200         enum { FIELD_UNSET, FIELD_STRING, FIELD_FORMAT } type;
14201 -       
14202 +
14203         buffer *string;
14204         int field;
14205  } format_field;
14206  
14207  typedef struct {
14208         format_field **ptr;
14209 -       
14210 +
14211         size_t used;
14212         size_t size;
14213  } format_fields;
14214 @@ -128,39 +128,39 @@
14215         buffer *access_logfile;
14216         buffer *format;
14217         unsigned short use_syslog;
14218 -       
14219 -       
14220 +
14221 +
14222         int    log_access_fd;
14223         time_t last_generated_accesslog_ts;
14224         time_t *last_generated_accesslog_ts_ptr;
14225 -       
14226 -       
14227 +
14228 +
14229         buffer *access_logbuffer;
14230         buffer *ts_accesslog_str;
14231 -       
14232 +
14233         format_fields *parsed_format;
14234  } plugin_config;
14235  
14236  typedef struct {
14237         PLUGIN_DATA;
14238 -       
14239 +
14240         plugin_config **config_storage;
14241 -       plugin_config conf; 
14242 +       plugin_config conf;
14243  } plugin_data;
14244  
14245  INIT_FUNC(mod_accesslog_init) {
14246         plugin_data *p;
14247 -       
14248 +
14249         p = calloc(1, sizeof(*p));
14250 -       
14251 +
14252         return p;
14253  }
14254  
14255  int accesslog_parse_format(server *srv, format_fields *fields, buffer *format) {
14256         size_t i, j, k = 0, start = 0;
14257 -       
14258 +
14259         for (i = 0; i < format->used - 1; i++) {
14260 -               
14261 +
14262                 switch(format->ptr[i]) {
14263                 case '%':
14264                         if (start != i) {
14265 @@ -173,19 +173,19 @@
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 +
14284 +
14285                         /* we need a new field */
14286 -                       
14287 +
14288                         if (fields->size == 0) {
14289                                 fields->size = 16;
14290                                 fields->used = 0;
14291 @@ -194,43 +194,43 @@
14292                                 fields->size += 16;
14293                                 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
14294                         }
14295 -                       
14296 +
14297                         /* search for the terminating command */
14298                         switch (format->ptr[i+1]) {
14299                         case '>':
14300                         case '<':
14301                                 /* only for s */
14302 -                               
14303 +
14304                                 for (j = 0; fmap[j].key != '\0'; j++) {
14305                                         if (fmap[j].key != format->ptr[i+2]) continue;
14306 -                                       
14307 +
14308                                         /* found key */
14309 -                                               
14310 +
14311                                         fields->ptr[fields->used] = malloc(sizeof(format_fields));
14312                                         fields->ptr[fields->used]->type = FIELD_FORMAT;
14313                                         fields->ptr[fields->used]->field = fmap[j].type;
14314                                         fields->ptr[fields->used]->string = NULL;
14315 -                                       
14316 +
14317                                         fields->used++;
14318 -                                       
14319 +
14320                                         break;
14321                                 }
14322 -                               
14323 +
14324                                 if (fmap[j].key == '\0') {
14325                                         log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14326                                         return -1;
14327                                 }
14328 -                               
14329 +
14330                                 start = i + 3;
14331 -                               
14332 +
14333                                 break;
14334                         case '{':
14335                                 /* go forward to } */
14336 -                               
14337 +
14338                                 for (k = i+2; k < format->used - 1; k++) {
14339                                         if (format->ptr[k] == '}') break;
14340                                 }
14341 -                               
14342 +
14343                                 if (k == format->used - 1) {
14344                                         log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14345                                         return -1;
14346 @@ -239,62 +239,62 @@
14347                                         log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14348                                         return -1;
14349                                 }
14350 -                               
14351 +
14352                                 for (j = 0; fmap[j].key != '\0'; j++) {
14353                                         if (fmap[j].key != format->ptr[k+1]) continue;
14354 -                                       
14355 +
14356                                         /* found key */
14357 -                                               
14358 +
14359                                         fields->ptr[fields->used] = malloc(sizeof(format_fields));
14360                                         fields->ptr[fields->used]->type = FIELD_FORMAT;
14361                                         fields->ptr[fields->used]->field = fmap[j].type;
14362                                         fields->ptr[fields->used]->string = buffer_init();
14363 -                                       
14364 +
14365                                         buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + i + 2, k - (i + 2));
14366 -                                       
14367 +
14368                                         fields->used++;
14369 -                                       
14370 +
14371                                         break;
14372                                 }
14373 -                               
14374 +
14375                                 if (fmap[j].key == '\0') {
14376                                         log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14377                                         return -1;
14378                                 }
14379 -                               
14380 +
14381                                 start = k + 2;
14382 -                               
14383 +
14384                                 break;
14385                         default:
14386                                 for (j = 0; fmap[j].key != '\0'; j++) {
14387                                         if (fmap[j].key != format->ptr[i+1]) continue;
14388 -                                       
14389 +
14390                                         /* found key */
14391 -                                               
14392 +
14393                                         fields->ptr[fields->used] = malloc(sizeof(format_fields));
14394                                         fields->ptr[fields->used]->type = FIELD_FORMAT;
14395                                         fields->ptr[fields->used]->field = fmap[j].type;
14396                                         fields->ptr[fields->used]->string = NULL;
14397 -                                       
14398 +
14399                                         fields->used++;
14400 -                                       
14401 +
14402                                         break;
14403                                 }
14404 -                               
14405 +
14406                                 if (fmap[j].key == '\0') {
14407                                         log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
14408                                         return -1;
14409                                 }
14410 -                               
14411 +
14412                                 start = i + 2;
14413 -                               
14414 +
14415                                 break;
14416                         }
14417 -                       
14418 +
14419                         break;
14420                 }
14421         }
14422 -       
14423 +
14424         if (start < i) {
14425                 /* copy the string */
14426                 if (fields->size == 0) {
14427 @@ -305,32 +305,32 @@
14428                         fields->size += 16;
14429                         fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
14430                 }
14431 -               
14432 +
14433                 fields->ptr[fields->used] = malloc(sizeof(format_fields));
14434                 fields->ptr[fields->used]->type = FIELD_STRING;
14435                 fields->ptr[fields->used]->string = buffer_init();
14436 -               
14437 +
14438                 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
14439 -               
14440 +
14441                 fields->used++;
14442         }
14443 -       
14444 +
14445         return 0;
14446  }
14447  
14448  FREE_FUNC(mod_accesslog_free) {
14449         plugin_data *p = p_d;
14450         size_t i;
14451 -       
14452 +
14453         if (!p) return HANDLER_GO_ON;
14454 -       
14455 +
14456         if (p->config_storage) {
14457 -               
14458 +
14459                 for (i = 0; i < srv->config_context->used; i++) {
14460                         plugin_config *s = p->config_storage[i];
14461  
14462                         if (!s) continue;
14463 -                       
14464 +
14465                         if (s->access_logbuffer->used) {
14466                                 if (s->use_syslog) {
14467  # ifdef HAVE_SYSLOG_H
14468 @@ -342,14 +342,14 @@
14469                                         write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
14470                                 }
14471                         }
14472 -                       
14473 +
14474                         if (s->log_access_fd != -1) close(s->log_access_fd);
14475 -                       
14476 +
14477                         buffer_free(s->ts_accesslog_str);
14478                         buffer_free(s->access_logbuffer);
14479                         buffer_free(s->format);
14480                         buffer_free(s->access_logfile);
14481 -                       
14482 +
14483                         if (s->parsed_format) {
14484                                 size_t j;
14485                                 for (j = 0; j < s->parsed_format->used; j++) {
14486 @@ -359,36 +359,36 @@
14487                                 free(s->parsed_format->ptr);
14488                                 free(s->parsed_format);
14489                         }
14490 -                       
14491 +
14492                         free(s);
14493                 }
14494 -       
14495 +
14496                 free(p->config_storage);
14497         }
14498 -       
14499 +
14500         free(p);
14501 -       
14502 +
14503         return HANDLER_GO_ON;
14504  }
14505  
14506  SETDEFAULTS_FUNC(log_access_open) {
14507         plugin_data *p = p_d;
14508         size_t i = 0;
14509 -       
14510 -       config_values_t cv[] = { 
14511 +
14512 +       config_values_t cv[] = {
14513                 { "accesslog.filename",             NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
14514                 { "accesslog.use-syslog",           NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
14515                 { "accesslog.format",               NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
14516                 { NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
14517         };
14518 -       
14519 +
14520         if (!p) return HANDLER_ERROR;
14521 -       
14522 +
14523         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
14524 -       
14525 +
14526         for (i = 0; i < srv->config_context->used; i++) {
14527                 plugin_config *s;
14528 -               
14529 +
14530                 s = calloc(1, sizeof(plugin_config));
14531                 s->access_logfile = buffer_init();
14532                 s->format = buffer_init();
14533 @@ -397,44 +397,44 @@
14534                 s->log_access_fd = -1;
14535                 s->last_generated_accesslog_ts = 0;
14536                 s->last_generated_accesslog_ts_ptr = &(s->last_generated_accesslog_ts);
14537 -               
14538 -       
14539 +
14540 +
14541                 cv[0].destination = s->access_logfile;
14542                 cv[1].destination = &(s->use_syslog);
14543                 cv[2].destination = s->format;
14544 -       
14545 +
14546                 p->config_storage[i] = s;
14547 -               
14548 +
14549                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
14550                         return HANDLER_ERROR;
14551                 }
14552 -               
14553 +
14554                 if (i == 0 && buffer_is_empty(s->format)) {
14555                         /* set a default logfile string */
14556 -                       
14557 +
14558                         buffer_copy_string(s->format, "%h %V %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"");
14559                 }
14560 -               
14561 +
14562                 /* parse */
14563 -               
14564 +
14565                 if (s->format->used) {
14566                         s->parsed_format = calloc(1, sizeof(*(s->parsed_format)));
14567 -                       
14568 +
14569                         if (-1 == accesslog_parse_format(srv, s->parsed_format, s->format)) {
14570  
14571 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
14572 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
14573                                                 "parsing accesslog-definition failed:", s->format);
14574  
14575                                 return HANDLER_ERROR;
14576                         }
14577  #if 0
14578 -                       /* debugging */                 
14579 +                       /* debugging */
14580                         for (j = 0; j < s->parsed_format->used; j++) {
14581                                 switch (s->parsed_format->ptr[j]->type) {
14582                                 case FIELD_FORMAT:
14583 -                                       log_error_write(srv, __FILE__, __LINE__, "ssds", 
14584 +                                       log_error_write(srv, __FILE__, __LINE__, "ssds",
14585                                                         "config:", "format", s->parsed_format->ptr[j]->field,
14586 -                                                       s->parsed_format->ptr[j]->string ? 
14587 +                                                       s->parsed_format->ptr[j]->string ?
14588                                                         s->parsed_format->ptr[j]->string->ptr : "" );
14589                                         break;
14590                                 case FIELD_STRING:
14591 @@ -446,52 +446,52 @@
14592                         }
14593  #endif
14594                 }
14595 -               
14596 +
14597                 if (s->use_syslog) {
14598                         /* ignore the next checks */
14599                         continue;
14600                 }
14601 -               
14602 +
14603                 if (buffer_is_empty(s->access_logfile)) continue;
14604 -               
14605 +
14606                 if (s->access_logfile->ptr[0] == '|') {
14607  #ifdef HAVE_FORK
14608                         /* create write pipe and spawn process */
14609 -                       
14610 +
14611                         int to_log_fds[2];
14612                         pid_t pid;
14613 -                       
14614 +
14615                         if (pipe(to_log_fds)) {
14616                                 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno));
14617                                 return HANDLER_ERROR;
14618                         }
14619 -                       
14620 +
14621                         /* fork, execve */
14622                         switch (pid = fork()) {
14623 -                       case 0: 
14624 +                       case 0:
14625                                 /* child */
14626 -                               
14627 +
14628                                 close(STDIN_FILENO);
14629                                 dup2(to_log_fds[0], STDIN_FILENO);
14630                                 close(to_log_fds[0]);
14631                                 /* not needed */
14632                                 close(to_log_fds[1]);
14633 -                               
14634 +
14635                                 /* we don't need the client socket */
14636                                 for (i = 3; i < 256; i++) {
14637                                         close(i);
14638                                 }
14639 -                               
14640 -                               /* exec the log-process (skip the | ) 
14641 -                                * 
14642 +
14643 +                               /* exec the log-process (skip the | )
14644 +                                *
14645                                  */
14646 -                               
14647 +
14648                                 execl("/bin/sh", "sh", "-c", s->access_logfile->ptr + 1, NULL);
14649  
14650 -                               log_error_write(srv, __FILE__, __LINE__, "sss", 
14651 -                                               "spawning log-process failed: ", strerror(errno), 
14652 +                               log_error_write(srv, __FILE__, __LINE__, "sss",
14653 +                                               "spawning log-process failed: ", strerror(errno),
14654                                                 s->access_logfile->ptr + 1);
14655 -                               
14656 +
14657                                 exit(-1);
14658                                 break;
14659                         case -1:
14660 @@ -500,27 +500,28 @@
14661                                 break;
14662                         default:
14663                                 close(to_log_fds[0]);
14664 -                               
14665 +
14666                                 s->log_access_fd = to_log_fds[1];
14667 -                               
14668 +
14669                                 break;
14670                         }
14671  #else
14672                         return -1;
14673  #endif
14674 -               } else if (-1 == (s->log_access_fd = 
14675 +               } else if (-1 == (s->log_access_fd =
14676                                   open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
14677 -                       
14678 -                       log_error_write(srv, __FILE__, __LINE__, "ssb", 
14679 -                                       "opening access-log failed:", 
14680 +
14681 +                       log_error_write(srv, __FILE__, __LINE__, "ssb",
14682 +                                       "opening access-log failed:",
14683                                         strerror(errno), s->access_logfile);
14684 -                       
14685 +
14686                         return HANDLER_ERROR;
14687                 }
14688 +#ifndef _WIN32
14689                 fcntl(s->log_access_fd, F_SETFD, FD_CLOEXEC);
14690 -       
14691 +#endif
14692         }
14693 -       
14694 +
14695         return HANDLER_GO_ON;
14696  }
14697  
14698 @@ -529,7 +530,7 @@
14699         size_t i;
14700  
14701         if (!p->config_storage) return HANDLER_GO_ON;
14702 -               
14703 +
14704         for (i = 0; i < srv->config_context->used; i++) {
14705                 plugin_config *s = p->config_storage[i];
14706  
14707 @@ -544,90 +545,87 @@
14708                         } else if (s->log_access_fd != -1) {
14709                                 write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
14710                         }
14711 -                       
14712 +
14713                         buffer_reset(s->access_logbuffer);
14714                 }
14715 -               
14716 +
14717                 if (s->use_syslog == 0 &&
14718                     !buffer_is_empty(s->access_logfile) &&
14719                     s->access_logfile->ptr[0] != '|') {
14720 -                       
14721 +
14722                         close(s->log_access_fd);
14723 -                       
14724 -                       if (-1 == (s->log_access_fd = 
14725 +
14726 +                       if (-1 == (s->log_access_fd =
14727                                    open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
14728 -                               
14729 +
14730                                 log_error_write(srv, __FILE__, __LINE__, "ss", "cycling access-log failed:", strerror(errno));
14731 -                               
14732 +
14733                                 return HANDLER_ERROR;
14734                         }
14735                 }
14736         }
14737 -       
14738 +
14739         return HANDLER_GO_ON;
14740  }
14741  
14742 -#define PATCH(x) \
14743 -       p->conf.x = s->x;
14744  static int mod_accesslog_patch_connection(server *srv, connection *con, plugin_data *p) {
14745         size_t i, j;
14746         plugin_config *s = p->config_storage[0];
14747 -       
14748 -       PATCH(access_logfile);
14749 -       PATCH(format);
14750 -       PATCH(log_access_fd);
14751 -       PATCH(last_generated_accesslog_ts_ptr);
14752 -       PATCH(access_logbuffer);
14753 -       PATCH(ts_accesslog_str);
14754 -       PATCH(parsed_format);
14755 -       PATCH(use_syslog);
14756 -       
14757 +
14758 +       PATCH_OPTION(access_logfile);
14759 +       PATCH_OPTION(format);
14760 +       PATCH_OPTION(log_access_fd);
14761 +       PATCH_OPTION(last_generated_accesslog_ts_ptr);
14762 +       PATCH_OPTION(access_logbuffer);
14763 +       PATCH_OPTION(ts_accesslog_str);
14764 +       PATCH_OPTION(parsed_format);
14765 +       PATCH_OPTION(use_syslog);
14766 +
14767         /* skip the first, the global context */
14768         for (i = 1; i < srv->config_context->used; i++) {
14769                 data_config *dc = (data_config *)srv->config_context->data[i];
14770                 s = p->config_storage[i];
14771 -               
14772 +
14773                 /* condition didn't match */
14774                 if (!config_check_cond(srv, con, dc)) continue;
14775 -               
14776 +
14777                 /* merge config */
14778                 for (j = 0; j < dc->value->used; j++) {
14779                         data_unset *du = dc->value->data[j];
14780 -                       
14781 +
14782                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.filename"))) {
14783 -                               PATCH(access_logfile);
14784 -                               PATCH(log_access_fd);
14785 -                               PATCH(last_generated_accesslog_ts_ptr);
14786 -                               PATCH(access_logbuffer);
14787 -                               PATCH(ts_accesslog_str);
14788 +                               PATCH_OPTION(access_logfile);
14789 +                               PATCH_OPTION(log_access_fd);
14790 +                               PATCH_OPTION(last_generated_accesslog_ts_ptr);
14791 +                               PATCH_OPTION(access_logbuffer);
14792 +                               PATCH_OPTION(ts_accesslog_str);
14793                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.format"))) {
14794 -                               PATCH(format);
14795 -                               PATCH(parsed_format);
14796 +                               PATCH_OPTION(format);
14797 +                               PATCH_OPTION(parsed_format);
14798                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.use-syslog"))) {
14799 -                               PATCH(use_syslog);
14800 +                               PATCH_OPTION(use_syslog);
14801                         }
14802                 }
14803         }
14804 -       
14805 +
14806         return 0;
14807  }
14808 -#undef PATCH
14809  
14810  REQUESTDONE_FUNC(log_access_write) {
14811         plugin_data *p = p_d;
14812         buffer *b;
14813         size_t j;
14814 -       
14815 +
14816         int newts = 0;
14817         data_string *ds;
14818 -       
14819 +
14820         mod_accesslog_patch_connection(srv, con, p);
14821 -       
14822 +
14823         b = p->conf.access_logbuffer;
14824         if (b->used == 0) {
14825                 buffer_copy_string(b, "");
14826         }
14827 -       
14828 +
14829         for (j = 0; j < p->conf.parsed_format->used; j++) {
14830                 switch(p->conf.parsed_format->ptr[j]->type) {
14831                 case FIELD_STRING:
14832 @@ -636,14 +634,14 @@
14833                 case FIELD_FORMAT:
14834                         switch(p->conf.parsed_format->ptr[j]->field) {
14835                         case FORMAT_TIMESTAMP:
14836 -                               
14837 +
14838                                 /* cache the generated timestamp */
14839                                 if (srv->cur_ts != *(p->conf.last_generated_accesslog_ts_ptr)) {
14840                                         struct tm tm;
14841  #if defined(HAVE_STRUCT_TM_GMTOFF)
14842                                         long scd, hrs, min;
14843  #endif
14844 -               
14845 +
14846                                         buffer_prepare_copy(p->conf.ts_accesslog_str, 255);
14847  #if defined(HAVE_STRUCT_TM_GMTOFF)
14848  # ifdef HAVE_LOCALTIME_R
14849 @@ -653,17 +651,17 @@
14850                                         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)));
14851  # endif
14852                                         p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
14853 -                                       
14854 +
14855                                         buffer_append_string(p->conf.ts_accesslog_str, tm.tm_gmtoff >= 0 ? "+" : "-");
14856 -                                       
14857 +
14858                                         scd = abs(tm.tm_gmtoff);
14859                                         hrs = scd / 3600;
14860                                         min = (scd % 3600) / 60;
14861 -                                       
14862 +
14863                                         /* hours */
14864                                         if (hrs < 10) buffer_append_string(p->conf.ts_accesslog_str, "0");
14865                                         buffer_append_long(p->conf.ts_accesslog_str, hrs);
14866 -                                       
14867 +
14868                                         if (min < 10) buffer_append_string(p->conf.ts_accesslog_str, "0");
14869                                         buffer_append_long(p->conf.ts_accesslog_str, min);
14870                                         BUFFER_APPEND_STRING_CONST(p->conf.ts_accesslog_str, "]");
14871 @@ -676,20 +674,20 @@
14872  #endif
14873                                         p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
14874  #endif
14875 -                                       
14876 +
14877                                         *(p->conf.last_generated_accesslog_ts_ptr) = srv->cur_ts;
14878                                         newts = 1;
14879                                 }
14880 -                               
14881 +
14882                                 buffer_append_string_buffer(b, p->conf.ts_accesslog_str);
14883 -                               
14884 +
14885                                 break;
14886                         case FORMAT_REMOTE_HOST:
14887 -       
14888 +
14889                                 /* handle inet_ntop cache */
14890 -       
14891 +
14892                                 buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
14893 -                               
14894 +
14895                                 break;
14896                         case FORMAT_REMOTE_IDENT:
14897                                 /* ident */
14898 @@ -710,10 +708,10 @@
14899                         case FORMAT_STATUS:
14900                                 buffer_append_long(b, con->http_status);
14901                                 break;
14902 -       
14903 +
14904                         case FORMAT_BYTES_OUT_NO_HEADER:
14905                                 if (con->bytes_written > 0) {
14906 -                                       buffer_append_off_t(b, 
14907 +                                       buffer_append_off_t(b,
14908                                                             con->bytes_written - con->bytes_header <= 0 ? 0 : con->bytes_written - con->bytes_header);
14909                                 } else {
14910                                         BUFFER_APPEND_STRING_CONST(b, "-");
14911 @@ -772,7 +770,7 @@
14912                                 }
14913                                 break;
14914                         case FORMAT_REQUEST_PROTOCOL:
14915 -                               buffer_append_string(b, 
14916 +                               buffer_append_string(b,
14917                                                      con->request.http_version == HTTP_VERSION_1_1 ? "HTTP/1.1" : "HTTP/1.0");
14918                                 break;
14919                         case FORMAT_REQUEST_METHOD:
14920 @@ -801,7 +799,7 @@
14921                                  { 'D', FORMAT_TIME_USED_MS },
14922                                  { 'e', FORMAT_ENV },
14923                                  */
14924 -                               
14925 +
14926                                 break;
14927                         }
14928                         break;
14929 @@ -809,7 +807,7 @@
14930                         break;
14931                 }
14932         }
14933 -       
14934 +
14935         BUFFER_APPEND_STRING_CONST(b, "\n");
14936  
14937         if (p->conf.use_syslog ||  /* syslog doesn't cache */
14938 @@ -828,7 +826,7 @@
14939                 }
14940                 buffer_reset(b);
14941         }
14942 -       
14943 +
14944         return HANDLER_GO_ON;
14945  }
14946  
14947 @@ -836,15 +834,15 @@
14948  int mod_accesslog_plugin_init(plugin *p) {
14949         p->version     = LIGHTTPD_VERSION_ID;
14950         p->name        = buffer_init_string("accesslog");
14951 -       
14952 +
14953         p->init        = mod_accesslog_init;
14954         p->set_defaults= log_access_open;
14955         p->cleanup     = mod_accesslog_free;
14956 -       
14957 +
14958         p->handle_request_done  = log_access_write;
14959         p->handle_sighup        = log_access_cycle;
14960 -       
14961 +
14962         p->data        = NULL;
14963 -       
14964 +
14965         return 0;
14966  }
14967 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_alias.c lighttpd-1.4.12/src/mod_alias.c
14968 --- lighttpd-1.4.11/src/mod_alias.c     2006-03-01 23:18:51.000000000 +0200
14969 +++ lighttpd-1.4.12/src/mod_alias.c     2006-07-11 21:23:39.000000000 +0300
14970 @@ -8,6 +8,7 @@
14971  #include "buffer.h"
14972  
14973  #include "plugin.h"
14974 +#include "sys-strings.h"
14975  
14976  /* plugin config for all request/connections */
14977  typedef struct {
14978 @@ -16,44 +17,44 @@
14979  
14980  typedef struct {
14981         PLUGIN_DATA;
14982 -       
14983 +
14984         plugin_config **config_storage;
14985 -       
14986 -       plugin_config conf; 
14987 +
14988 +       plugin_config conf;
14989  } plugin_data;
14990  
14991  /* init the plugin data */
14992  INIT_FUNC(mod_alias_init) {
14993         plugin_data *p;
14994 -       
14995 +
14996         p = calloc(1, sizeof(*p));
14997 -       
14998 -       
14999 -       
15000 +
15001 +
15002 +
15003         return p;
15004  }
15005  
15006  /* detroy the plugin data */
15007  FREE_FUNC(mod_alias_free) {
15008         plugin_data *p = p_d;
15009 -       
15010 +
15011         if (!p) return HANDLER_GO_ON;
15012 -       
15013 +
15014         if (p->config_storage) {
15015                 size_t i;
15016 -               
15017 +
15018                 for (i = 0; i < srv->config_context->used; i++) {
15019                         plugin_config *s = p->config_storage[i];
15020 -                       
15021 +
15022                         array_free(s->alias);
15023 -                       
15024 +
15025                         free(s);
15026                 }
15027                 free(p->config_storage);
15028         }
15029 -       
15030 +
15031         free(p);
15032 -       
15033 +
15034         return HANDLER_GO_ON;
15035  }
15036  
15037 @@ -62,25 +63,25 @@
15038  SETDEFAULTS_FUNC(mod_alias_set_defaults) {
15039         plugin_data *p = p_d;
15040         size_t i = 0;
15041 -       
15042 -       config_values_t cv[] = { 
15043 +
15044 +       config_values_t cv[] = {
15045                 { "alias.url",                  NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
15046                 { NULL,                         NULL, T_CONFIG_UNSET,  T_CONFIG_SCOPE_UNSET }
15047         };
15048 -       
15049 +
15050         if (!p) return HANDLER_ERROR;
15051 -       
15052 +
15053         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
15054 -       
15055 +
15056         for (i = 0; i < srv->config_context->used; i++) {
15057                 plugin_config *s;
15058 -               
15059 +
15060                 s = calloc(1, sizeof(plugin_config));
15061 -               s->alias = array_init();        
15062 +               s->alias = array_init();
15063                 cv[0].destination = s->alias;
15064 -               
15065 +
15066                 p->config_storage[i] = s;
15067 -               
15068 +
15069                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
15070                         return HANDLER_ERROR;
15071                 }
15072 @@ -110,76 +111,73 @@
15073                         }
15074                 }
15075         }
15076 -       
15077 +
15078         return HANDLER_GO_ON;
15079  }
15080  
15081 -#define PATCH(x) \
15082 -       p->conf.x = s->x;
15083  static int mod_alias_patch_connection(server *srv, connection *con, plugin_data *p) {
15084         size_t i, j;
15085         plugin_config *s = p->config_storage[0];
15086 -       
15087 -       PATCH(alias);
15088 -       
15089 +
15090 +       PATCH_OPTION(alias);
15091 +
15092         /* skip the first, the global context */
15093         for (i = 1; i < srv->config_context->used; i++) {
15094                 data_config *dc = (data_config *)srv->config_context->data[i];
15095                 s = p->config_storage[i];
15096 -               
15097 +
15098                 /* condition didn't match */
15099                 if (!config_check_cond(srv, con, dc)) continue;
15100 -               
15101 +
15102                 /* merge config */
15103                 for (j = 0; j < dc->value->used; j++) {
15104                         data_unset *du = dc->value->data[j];
15105 -                       
15106 +
15107                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("alias.url"))) {
15108 -                               PATCH(alias);
15109 +                               PATCH_OPTION(alias);
15110                         }
15111                 }
15112         }
15113 -       
15114 +
15115         return 0;
15116  }
15117 -#undef PATCH
15118  
15119  PHYSICALPATH_FUNC(mod_alias_physical_handler) {
15120         plugin_data *p = p_d;
15121         int uri_len, basedir_len;
15122         char *uri_ptr;
15123         size_t k;
15124 -       
15125 +
15126         if (con->physical.path->used == 0) return HANDLER_GO_ON;
15127 -       
15128 +
15129         mod_alias_patch_connection(srv, con, p);
15130 -       
15131 +
15132         /* not to include the tailing slash */
15133         basedir_len = (con->physical.basedir->used - 1) - 1;
15134         uri_len = con->physical.path->used - 1 - basedir_len;
15135         uri_ptr = con->physical.path->ptr + basedir_len;
15136 -       
15137 +
15138         for (k = 0; k < p->conf.alias->used; k++) {
15139                 data_string *ds = (data_string *)p->conf.alias->data[k];
15140                 int alias_len = ds->key->used - 1;
15141 -               
15142 +
15143                 if (alias_len > uri_len) continue;
15144                 if (ds->key->used == 0) continue;
15145 -               
15146 +
15147                 if (0 == (con->conf.force_lowercase_filenames ?
15148                                         strncasecmp(uri_ptr, ds->key->ptr, alias_len) :
15149                                         strncmp(uri_ptr, ds->key->ptr, alias_len))) {
15150                         /* matched */
15151 -                       
15152 +
15153                         buffer_copy_string_buffer(con->physical.basedir, ds->value);
15154                         buffer_copy_string_buffer(srv->tmp_buf, ds->value);
15155                         buffer_append_string(srv->tmp_buf, uri_ptr + alias_len);
15156                         buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
15157 -                       
15158 +
15159                         return HANDLER_GO_ON;
15160                 }
15161         }
15162 -       
15163 +
15164         /* not found */
15165         return HANDLER_GO_ON;
15166  }
15167 @@ -189,13 +187,13 @@
15168  int mod_alias_plugin_init(plugin *p) {
15169         p->version     = LIGHTTPD_VERSION_ID;
15170         p->name        = buffer_init_string("alias");
15171 -       
15172 +
15173         p->init           = mod_alias_init;
15174         p->handle_physical= mod_alias_physical_handler;
15175         p->set_defaults   = mod_alias_set_defaults;
15176         p->cleanup        = mod_alias_free;
15177 -       
15178 +
15179         p->data        = NULL;
15180 -       
15181 +
15182         return 0;
15183  }
15184 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_auth.c lighttpd-1.4.12/src/mod_auth.c
15185 --- lighttpd-1.4.11/src/mod_auth.c      2006-02-15 20:01:31.000000000 +0200
15186 +++ lighttpd-1.4.12/src/mod_auth.c      2006-07-11 21:23:40.000000000 +0300
15187 @@ -5,168 +5,167 @@
15188  #include <string.h>
15189  #include <errno.h>
15190  #include <fcntl.h>
15191 -#include <unistd.h>
15192  
15193  #include "plugin.h"
15194  #include "http_auth.h"
15195  #include "log.h"
15196  #include "response.h"
15197  
15198 +#include "sys-strings.h"
15199 +#include "sys-files.h"
15200 +
15201  handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
15202  
15203  
15204  /**
15205   * the basic and digest auth framework
15206 - * 
15207 + *
15208   * - config handling
15209   * - protocol handling
15210 - * 
15211 - * http_auth.c 
15212 - * http_auth_digest.c 
15213 - * 
15214 + *
15215 + * http_auth.c
15216 + * http_auth_digest.c
15217 + *
15218   * do the real work
15219   */
15220  
15221  INIT_FUNC(mod_auth_init) {
15222         mod_auth_plugin_data *p;
15223 -       
15224 +
15225         p = calloc(1, sizeof(*p));
15226 -       
15227 +
15228         p->tmp_buf = buffer_init();
15229 -       
15230 +
15231         p->auth_user = buffer_init();
15232  #ifdef USE_LDAP
15233         p->ldap_filter = buffer_init();
15234  #endif
15235 -       
15236 +
15237         return p;
15238  }
15239  
15240  FREE_FUNC(mod_auth_free) {
15241         mod_auth_plugin_data *p = p_d;
15242 -       
15243 +
15244         UNUSED(srv);
15245  
15246         if (!p) return HANDLER_GO_ON;
15247 -       
15248 +
15249         buffer_free(p->tmp_buf);
15250         buffer_free(p->auth_user);
15251  #ifdef USE_LDAP
15252         buffer_free(p->ldap_filter);
15253  #endif
15254 -       
15255 +
15256         if (p->config_storage) {
15257                 size_t i;
15258                 for (i = 0; i < srv->config_context->used; i++) {
15259                         mod_auth_plugin_config *s = p->config_storage[i];
15260 -                       
15261 +
15262                         if (!s) continue;
15263 -                       
15264 +
15265                         array_free(s->auth_require);
15266                         buffer_free(s->auth_plain_groupfile);
15267                         buffer_free(s->auth_plain_userfile);
15268                         buffer_free(s->auth_htdigest_userfile);
15269                         buffer_free(s->auth_htpasswd_userfile);
15270                         buffer_free(s->auth_backend_conf);
15271 -                       
15272 +
15273                         buffer_free(s->auth_ldap_hostname);
15274                         buffer_free(s->auth_ldap_basedn);
15275                         buffer_free(s->auth_ldap_binddn);
15276                         buffer_free(s->auth_ldap_bindpw);
15277                         buffer_free(s->auth_ldap_filter);
15278                         buffer_free(s->auth_ldap_cafile);
15279 -                       
15280 +
15281  #ifdef USE_LDAP
15282                         buffer_free(s->ldap_filter_pre);
15283                         buffer_free(s->ldap_filter_post);
15284 -                       
15285 +
15286                         if (s->ldap) ldap_unbind_s(s->ldap);
15287  #endif
15288 -                       
15289 +
15290                         free(s);
15291                 }
15292                 free(p->config_storage);
15293         }
15294 -       
15295 +
15296         free(p);
15297 -       
15298 +
15299         return HANDLER_GO_ON;
15300  }
15301  
15302 -#define PATCH(x) \
15303 -       p->conf.x = s->x;
15304  static int mod_auth_patch_connection(server *srv, connection *con, mod_auth_plugin_data *p) {
15305         size_t i, j;
15306         mod_auth_plugin_config *s = p->config_storage[0];
15307  
15308 -       PATCH(auth_backend);
15309 -       PATCH(auth_plain_groupfile);
15310 -       PATCH(auth_plain_userfile);
15311 -       PATCH(auth_htdigest_userfile);
15312 -       PATCH(auth_htpasswd_userfile);
15313 -       PATCH(auth_require);
15314 -       PATCH(auth_debug);
15315 -       PATCH(auth_ldap_hostname);
15316 -       PATCH(auth_ldap_basedn);
15317 -       PATCH(auth_ldap_binddn);
15318 -       PATCH(auth_ldap_bindpw);
15319 -       PATCH(auth_ldap_filter);
15320 -       PATCH(auth_ldap_cafile);
15321 -       PATCH(auth_ldap_starttls);
15322 +       PATCH_OPTION(auth_backend);
15323 +       PATCH_OPTION(auth_plain_groupfile);
15324 +       PATCH_OPTION(auth_plain_userfile);
15325 +       PATCH_OPTION(auth_htdigest_userfile);
15326 +       PATCH_OPTION(auth_htpasswd_userfile);
15327 +       PATCH_OPTION(auth_require);
15328 +       PATCH_OPTION(auth_debug);
15329 +       PATCH_OPTION(auth_ldap_hostname);
15330 +       PATCH_OPTION(auth_ldap_basedn);
15331 +       PATCH_OPTION(auth_ldap_binddn);
15332 +       PATCH_OPTION(auth_ldap_bindpw);
15333 +       PATCH_OPTION(auth_ldap_filter);
15334 +       PATCH_OPTION(auth_ldap_cafile);
15335 +       PATCH_OPTION(auth_ldap_starttls);
15336  #ifdef USE_LDAP
15337 -       PATCH(ldap);
15338 -       PATCH(ldap_filter_pre);
15339 -       PATCH(ldap_filter_post);
15340 +       PATCH_OPTION(ldap);
15341 +       PATCH_OPTION(ldap_filter_pre);
15342 +       PATCH_OPTION(ldap_filter_post);
15343  #endif
15344 -       
15345 +
15346         /* skip the first, the global context */
15347         for (i = 1; i < srv->config_context->used; i++) {
15348                 data_config *dc = (data_config *)srv->config_context->data[i];
15349                 s = p->config_storage[i];
15350 -               
15351 +
15352                 /* condition didn't match */
15353                 if (!config_check_cond(srv, con, dc)) continue;
15354 -               
15355 +
15356                 /* merge config */
15357                 for (j = 0; j < dc->value->used; j++) {
15358                         data_unset *du = dc->value->data[j];
15359 -                       
15360 +
15361                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend"))) {
15362 -                               PATCH(auth_backend);
15363 +                               PATCH_OPTION(auth_backend);
15364                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.groupfile"))) {
15365 -                               PATCH(auth_plain_groupfile);
15366 +                               PATCH_OPTION(auth_plain_groupfile);
15367                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.userfile"))) {
15368 -                               PATCH(auth_plain_userfile);
15369 +                               PATCH_OPTION(auth_plain_userfile);
15370                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htdigest.userfile"))) {
15371 -                               PATCH(auth_htdigest_userfile);
15372 +                               PATCH_OPTION(auth_htdigest_userfile);
15373                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htpasswd.userfile"))) {
15374 -                               PATCH(auth_htpasswd_userfile);
15375 +                               PATCH_OPTION(auth_htpasswd_userfile);
15376                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.require"))) {
15377 -                               PATCH(auth_require);
15378 +                               PATCH_OPTION(auth_require);
15379                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.debug"))) {
15380 -                               PATCH(auth_debug);
15381 +                               PATCH_OPTION(auth_debug);
15382                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.hostname"))) {
15383 -                               PATCH(auth_ldap_hostname);
15384 +                               PATCH_OPTION(auth_ldap_hostname);
15385  #ifdef USE_LDAP
15386 -                               PATCH(ldap);
15387 -                               PATCH(ldap_filter_pre);
15388 -                               PATCH(ldap_filter_post);
15389 +                               PATCH_OPTION(ldap);
15390 +                               PATCH_OPTION(ldap_filter_pre);
15391 +                               PATCH_OPTION(ldap_filter_post);
15392  #endif
15393                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.base-dn"))) {
15394 -                               PATCH(auth_ldap_basedn);
15395 +                               PATCH_OPTION(auth_ldap_basedn);
15396                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.filter"))) {
15397 -                               PATCH(auth_ldap_filter);
15398 +                               PATCH_OPTION(auth_ldap_filter);
15399                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.ca-file"))) {
15400 -                               PATCH(auth_ldap_cafile);
15401 +                               PATCH_OPTION(auth_ldap_cafile);
15402                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.starttls"))) {
15403 -                               PATCH(auth_ldap_starttls);
15404 +                               PATCH_OPTION(auth_ldap_starttls);
15405                         }
15406                 }
15407         }
15408 -       
15409 +
15410         return 0;
15411  }
15412 -#undef PATCH
15413  
15414  static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
15415         size_t k;
15416 @@ -175,22 +174,22 @@
15417         data_string *ds;
15418         mod_auth_plugin_data *p = p_d;
15419         array *req;
15420 -       
15421 +
15422         /* select the right config */
15423         mod_auth_patch_connection(srv, con, p);
15424 -       
15425 +
15426         if (p->conf.auth_require == NULL) return HANDLER_GO_ON;
15427 -       
15428 +
15429         /*
15430          * AUTH
15431 -        *  
15432 +        *
15433          */
15434 -       
15435 +
15436         /* do we have to ask for auth ? */
15437 -       
15438 +
15439         auth_required = 0;
15440         auth_satisfied = 0;
15441 -       
15442 +
15443         /* search auth-directives for path */
15444         for (k = 0; k < p->conf.auth_require->used; k++) {
15445                 buffer *req = p->conf.auth_require->data[k]->key;
15446 @@ -212,31 +211,31 @@
15447                         }
15448                 }
15449         }
15450 -       
15451 +
15452         /* nothing to do for us */
15453         if (auth_required == 0) return HANDLER_GO_ON;
15454 -       
15455 +
15456         req = ((data_array *)(p->conf.auth_require->data[k]))->value;
15457 -       
15458 +
15459         /* try to get Authorization-header */
15460 -               
15461 +
15462         if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization"))) {
15463                 http_authorization = ds->value->ptr;
15464         }
15465 -       
15466 +
15467         if (ds && ds->value && ds->value->used) {
15468                 char *auth_realm;
15469                 data_string *method;
15470 -               
15471 +
15472                 method = (data_string *)array_get_element(req, "method");
15473 -               
15474 +
15475                 /* parse auth-header */
15476                 if (NULL != (auth_realm = strchr(http_authorization, ' '))) {
15477                         int auth_type_len = auth_realm - http_authorization;
15478 -                       
15479 +
15480                         if ((auth_type_len == 5) &&
15481                             (0 == strncmp(http_authorization, "Basic", auth_type_len))) {
15482 -                               
15483 +
15484                                 if (0 == strcmp(method->value->ptr, "basic")) {
15485                                         auth_satisfied = http_auth_basic_check(srv, con, p, req, con->uri.path, auth_realm+1);
15486                                 }
15487 @@ -245,43 +244,43 @@
15488                                 if (0 == strcmp(method->value->ptr, "digest")) {
15489                                         if (-1 == (auth_satisfied = http_auth_digest_check(srv, con, p, req, con->uri.path, auth_realm+1))) {
15490                                                 con->http_status = 400;
15491 -                                               
15492 +
15493                                                 /* a field was missing */
15494 -                                               
15495 +
15496                                                 return HANDLER_FINISHED;
15497                                         }
15498                                 }
15499                         } else {
15500 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
15501 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
15502                                                 "unknown authentification type:",
15503                                                 http_authorization);
15504                         }
15505                 }
15506         }
15507 -       
15508 +
15509         if (!auth_satisfied) {
15510                 data_string *method, *realm;
15511                 method = (data_string *)array_get_element(req, "method");
15512                 realm = (data_string *)array_get_element(req, "realm");
15513 -               
15514 +
15515                 con->http_status = 401;
15516 -                       
15517 +
15518                 if (0 == strcmp(method->value->ptr, "basic")) {
15519                         buffer_copy_string(p->tmp_buf, "Basic realm=\"");
15520                         buffer_append_string_buffer(p->tmp_buf, realm->value);
15521                         buffer_append_string(p->tmp_buf, "\"");
15522 -                       
15523 +
15524                         response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
15525                 } else if (0 == strcmp(method->value->ptr, "digest")) {
15526                         char hh[33];
15527                         http_auth_digest_generate_nonce(srv, p, srv->tmp_buf, hh);
15528 -                       
15529 +
15530                         buffer_copy_string(p->tmp_buf, "Digest realm=\"");
15531                         buffer_append_string_buffer(p->tmp_buf, realm->value);
15532                         buffer_append_string(p->tmp_buf, "\", nonce=\"");
15533                         buffer_append_string(p->tmp_buf, hh);
15534                         buffer_append_string(p->tmp_buf, "\", qop=\"auth\"");
15535 -                       
15536 +
15537                         response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
15538                 } else {
15539                         /* evil */
15540 @@ -289,18 +288,18 @@
15541                 return HANDLER_FINISHED;
15542         } else {
15543                 /* the REMOTE_USER header */
15544 -               
15545 +
15546                 buffer_copy_string_buffer(con->authed_user, p->auth_user);
15547         }
15548 -       
15549 +
15550         return HANDLER_GO_ON;
15551  }
15552  
15553  SETDEFAULTS_FUNC(mod_auth_set_defaults) {
15554         mod_auth_plugin_data *p = p_d;
15555         size_t i;
15556 -       
15557 -       config_values_t cv[] = { 
15558 +
15559 +       config_values_t cv[] = {
15560                 { "auth.backend",                   NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
15561                 { "auth.backend.plain.groupfile",   NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
15562                 { "auth.backend.plain.userfile",    NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
15563 @@ -317,7 +316,7 @@
15564                 { "auth.debug",                     NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },  /* 13 */
15565                 { NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
15566         };
15567 -       
15568 +
15569         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
15570  
15571         for (i = 0; i < srv->config_context->used; i++) {
15572 @@ -325,14 +324,14 @@
15573                 size_t n;
15574                 data_array *da;
15575                 array *ca;
15576 -               
15577 +
15578                 s = calloc(1, sizeof(mod_auth_plugin_config));
15579                 s->auth_plain_groupfile = buffer_init();
15580                 s->auth_plain_userfile = buffer_init();
15581                 s->auth_htdigest_userfile = buffer_init();
15582                 s->auth_htpasswd_userfile = buffer_init();
15583                 s->auth_backend_conf = buffer_init();
15584 -               
15585 +
15586                 s->auth_ldap_hostname = buffer_init();
15587                 s->auth_ldap_basedn = buffer_init();
15588                 s->auth_ldap_binddn = buffer_init();
15589 @@ -341,15 +340,15 @@
15590                 s->auth_ldap_cafile = buffer_init();
15591                 s->auth_ldap_starttls = 0;
15592                 s->auth_debug = 0;
15593 -               
15594 +
15595                 s->auth_require = array_init();
15596 -               
15597 +
15598  #ifdef USE_LDAP
15599                 s->ldap_filter_pre = buffer_init();
15600                 s->ldap_filter_post = buffer_init();
15601                 s->ldap = NULL;
15602  #endif
15603 -       
15604 +
15605                 cv[0].destination = s->auth_backend_conf;
15606                 cv[1].destination = s->auth_plain_groupfile;
15607                 cv[2].destination = s->auth_plain_userfile;
15608 @@ -364,14 +363,14 @@
15609                 cv[11].destination = s->auth_htdigest_userfile;
15610                 cv[12].destination = s->auth_htpasswd_userfile;
15611                 cv[13].destination = &(s->auth_debug);
15612 -               
15613 +
15614                 p->config_storage[i] = s;
15615                 ca = ((data_config *)srv->config_context->data[i])->value;
15616 -               
15617 +
15618                 if (0 != config_insert_values_global(srv, ca, cv)) {
15619                         return HANDLER_ERROR;
15620                 }
15621 -               
15622 +
15623                 if (s->auth_backend_conf->used) {
15624                         if (0 == strcmp(s->auth_backend_conf->ptr, "htpasswd")) {
15625                                 s->auth_backend = AUTH_BACKEND_HTPASSWD;
15626 @@ -383,31 +382,31 @@
15627                                 s->auth_backend = AUTH_BACKEND_LDAP;
15628                         } else {
15629                                 log_error_write(srv, __FILE__, __LINE__, "sb", "auth.backend not supported:", s->auth_backend_conf);
15630 -                               
15631 +
15632                                 return HANDLER_ERROR;
15633                         }
15634                 }
15635  
15636                 /* no auth.require for this section */
15637                 if (NULL == (da = (data_array *)array_get_element(ca, "auth.require"))) continue;
15638 -               
15639 +
15640                 if (da->type != TYPE_ARRAY) continue;
15641 -               
15642 +
15643                 for (n = 0; n < da->value->used; n++) {
15644                         size_t m;
15645                         data_array *da_file = (data_array *)da->value->data[n];
15646                         const char *method, *realm, *require;
15647 -                       
15648 +
15649                         if (da->value->data[n]->type != TYPE_ARRAY) {
15650 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
15651 -                                               "auth.require should contain an array as in:", 
15652 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
15653 +                                               "auth.require should contain an array as in:",
15654                                                 "auth.require = ( \"...\" => ( ..., ...) )");
15655  
15656                                 return HANDLER_ERROR;
15657                         }
15658 -                                       
15659 +
15660                         method = realm = require = NULL;
15661 -                                       
15662 +
15663                         for (m = 0; m < da_file->value->used; m++) {
15664                                 if (da_file->value->data[m]->type == TYPE_STRING) {
15665                                         if (0 == strcmp(da_file->value->data[m]->key->ptr, "method")) {
15666 @@ -417,8 +416,8 @@
15667                                         } else if (0 == strcmp(da_file->value->data[m]->key->ptr, "require")) {
15668                                                 require = ((data_string *)(da_file->value->data[m]))->value->ptr;
15669                                         } else {
15670 -                                               log_error_write(srv, __FILE__, __LINE__, "ssbs", 
15671 -                                                       "the field is unknown in:", 
15672 +                                               log_error_write(srv, __FILE__, __LINE__, "ssbs",
15673 +                                                       "the field is unknown in:",
15674                                                         "auth.require = ( \"...\" => ( ..., -> \"",
15675                                                         da_file->value->data[m]->key,
15676                                                         "\" <- => \"...\" ) )");
15677 @@ -426,19 +425,19 @@
15678                                                 return HANDLER_ERROR;
15679                                         }
15680                                 } else {
15681 -                                       log_error_write(srv, __FILE__, __LINE__, "ssbs", 
15682 -                                               "a string was expected for:", 
15683 +                                       log_error_write(srv, __FILE__, __LINE__, "ssbs",
15684 +                                               "a string was expected for:",
15685                                                 "auth.require = ( \"...\" => ( ..., -> \"",
15686                                                 da_file->value->data[m]->key,
15687                                                 "\" <- => \"...\" ) )");
15688 -                                       
15689 +
15690                                         return HANDLER_ERROR;
15691                                 }
15692                         }
15693 -                                       
15694 +
15695                         if (method == NULL) {
15696 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
15697 -                                               "the require field is missing in:", 
15698 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
15699 +                                               "the require field is missing in:",
15700                                                 "auth.require = ( \"...\" => ( ..., \"method\" => \"...\" ) )");
15701                                 return HANDLER_ERROR;
15702                         } else {
15703 @@ -450,60 +449,60 @@
15704                                         return HANDLER_ERROR;
15705                                 }
15706                         }
15707 -                       
15708 +
15709                         if (realm == NULL) {
15710 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
15711 -                                               "the require field is missing in:", 
15712 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
15713 +                                               "the require field is missing in:",
15714                                                 "auth.require = ( \"...\" => ( ..., \"realm\" => \"...\" ) )");
15715                                 return HANDLER_ERROR;
15716                         }
15717 -                       
15718 +
15719                         if (require == NULL) {
15720 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
15721 -                                               "the require field is missing in:", 
15722 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
15723 +                                               "the require field is missing in:",
15724                                                 "auth.require = ( \"...\" => ( ..., \"require\" => \"...\" ) )");
15725                                 return HANDLER_ERROR;
15726                         }
15727 -                       
15728 +
15729                         if (method && realm && require) {
15730                                 data_string *ds;
15731                                 data_array *a;
15732 -                               
15733 +
15734                                 a = data_array_init();
15735                                 buffer_copy_string_buffer(a->key, da_file->key);
15736 -                               
15737 +
15738                                 ds = data_string_init();
15739 -                               
15740 +
15741                                 buffer_copy_string(ds->key, "method");
15742                                 buffer_copy_string(ds->value, method);
15743 -                               
15744 +
15745                                 array_insert_unique(a->value, (data_unset *)ds);
15746 -                               
15747 +
15748                                 ds = data_string_init();
15749 -                               
15750 +
15751                                 buffer_copy_string(ds->key, "realm");
15752                                 buffer_copy_string(ds->value, realm);
15753 -                               
15754 +
15755                                 array_insert_unique(a->value, (data_unset *)ds);
15756 -                               
15757 +
15758                                 ds = data_string_init();
15759 -                               
15760 +
15761                                 buffer_copy_string(ds->key, "require");
15762                                 buffer_copy_string(ds->value, require);
15763 -                               
15764 +
15765                                 array_insert_unique(a->value, (data_unset *)ds);
15766 -                               
15767 +
15768                                 array_insert_unique(s->auth_require, (data_unset *)a);
15769                         }
15770                 }
15771 -       
15772 +
15773                 switch(s->auth_backend) {
15774                 case AUTH_BACKEND_PLAIN:
15775                         if (s->auth_plain_userfile->used) {
15776                                 int fd;
15777                                 /* try to read */
15778                                 if (-1 == (fd = open(s->auth_plain_userfile->ptr, O_RDONLY))) {
15779 -                                       log_error_write(srv, __FILE__, __LINE__, "sbss", 
15780 +                                       log_error_write(srv, __FILE__, __LINE__, "sbss",
15781                                                         "opening auth.backend.plain.userfile:", s->auth_plain_userfile,
15782                                                         "failed:", strerror(errno));
15783                                         return HANDLER_ERROR;
15784 @@ -516,7 +515,7 @@
15785                                 int fd;
15786                                 /* try to read */
15787                                 if (-1 == (fd = open(s->auth_htpasswd_userfile->ptr, O_RDONLY))) {
15788 -                                       log_error_write(srv, __FILE__, __LINE__, "sbss", 
15789 +                                       log_error_write(srv, __FILE__, __LINE__, "sbss",
15790                                                         "opening auth.backend.htpasswd.userfile:", s->auth_htpasswd_userfile,
15791                                                         "failed:", strerror(errno));
15792                                         return HANDLER_ERROR;
15793 @@ -529,7 +528,7 @@
15794                                 int fd;
15795                                 /* try to read */
15796                                 if (-1 == (fd = open(s->auth_htdigest_userfile->ptr, O_RDONLY))) {
15797 -                                       log_error_write(srv, __FILE__, __LINE__, "sbss", 
15798 +                                       log_error_write(srv, __FILE__, __LINE__, "sbss",
15799                                                         "opening auth.backend.htdigest.userfile:", s->auth_htdigest_userfile,
15800                                                         "failed:", strerror(errno));
15801                                         return HANDLER_ERROR;
15802 @@ -554,75 +553,75 @@
15803  handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s) {
15804  #ifdef USE_LDAP
15805                         int ret;
15806 -#if 0                  
15807 +#if 0
15808                         if (s->auth_ldap_basedn->used == 0) {
15809                                 log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.base-dn has to be set");
15810 -                               
15811 +
15812                                 return HANDLER_ERROR;
15813                         }
15814  #endif
15815 -                       
15816 +
15817                         if (s->auth_ldap_filter->used) {
15818                                 char *dollar;
15819 -                               
15820 +
15821                                 /* parse filter */
15822 -                       
15823 +
15824                                 if (NULL == (dollar = strchr(s->auth_ldap_filter->ptr, '$'))) {
15825                                         log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.filter is missing a replace-operator '$'");
15826 -                                       
15827 +
15828                                         return HANDLER_ERROR;
15829                                 }
15830 -                               
15831 +
15832                                 buffer_copy_string_len(s->ldap_filter_pre, s->auth_ldap_filter->ptr, dollar - s->auth_ldap_filter->ptr);
15833                                 buffer_copy_string(s->ldap_filter_post, dollar+1);
15834                         }
15835 -                       
15836 +
15837                         if (s->auth_ldap_hostname->used) {
15838                                 if (NULL == (s->ldap = ldap_init(s->auth_ldap_hostname->ptr, LDAP_PORT))) {
15839                                         log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
15840 -                                       
15841 +
15842                                         return HANDLER_ERROR;
15843                                 }
15844 -                               
15845 +
15846                                 ret = LDAP_VERSION3;
15847                                 if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(s->ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
15848                                         log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
15849 -                               
15850 +
15851                                         return HANDLER_ERROR;
15852                                 }
15853  
15854                                 if (s->auth_ldap_starttls) {
15855 -                                       /* if no CA file is given, it is ok, as we will use encryption 
15856 +                                       /* if no CA file is given, it is ok, as we will use encryption
15857                                          * if the server requires a CAfile it will tell us */
15858                                         if (!buffer_is_empty(s->auth_ldap_cafile)) {
15859 -                                               if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, 
15860 +                                               if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
15861                                                                                 s->auth_ldap_cafile->ptr))) {
15862 -                                                       log_error_write(srv, __FILE__, __LINE__, "ss", 
15863 +                                                       log_error_write(srv, __FILE__, __LINE__, "ss",
15864                                                                         "Loading CA certificate failed:", ldap_err2string(ret));
15865 -                                               
15866 +
15867                                                         return HANDLER_ERROR;
15868                                                 }
15869                                         }
15870 -       
15871 +
15872                                         if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(s->ldap, NULL,  NULL))) {
15873                                                 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
15874 -                                               
15875 +
15876                                                 return HANDLER_ERROR;
15877                                         }
15878                                 }
15879 -                               
15880 -                               
15881 +
15882 +
15883                                 /* 1. */
15884                                 if (s->auth_ldap_binddn->used) {
15885                                         if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, s->auth_ldap_binddn->ptr, s->auth_ldap_bindpw->ptr))) {
15886                                                 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
15887 -                                               
15888 +
15889                                                 return HANDLER_ERROR;
15890                                         }
15891                                 } else {
15892                                         if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, NULL, NULL))) {
15893                                                 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
15894 -                                               
15895 +
15896                                                 return HANDLER_ERROR;
15897                                         }
15898                                 }
15899 @@ -641,8 +640,8 @@
15900         p->set_defaults = mod_auth_set_defaults;
15901         p->handle_uri_clean = mod_auth_uri_handler;
15902         p->cleanup     = mod_auth_free;
15903 -       
15904 +
15905         p->data        = NULL;
15906 -       
15907 +
15908         return 0;
15909  }
15910 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_cgi.c lighttpd-1.4.12/src/mod_cgi.c
15911 --- lighttpd-1.4.11/src/mod_cgi.c       2006-02-22 15:15:10.000000000 +0200
15912 +++ lighttpd-1.4.12/src/mod_cgi.c       2006-07-11 21:23:39.000000000 +0300
15913 @@ -1,21 +1,8 @@
15914  #include <sys/types.h>
15915 -#ifdef __WIN32
15916 -#include <winsock2.h>
15917 -#else
15918 -#include <sys/socket.h>
15919 -#include <sys/wait.h>
15920 -#include <sys/mman.h>
15921 -
15922 -#include <netinet/in.h>
15923 -
15924 -#include <arpa/inet.h>
15925 -#endif
15926  
15927 -#include <unistd.h>
15928  #include <errno.h>
15929  #include <stdlib.h>
15930  #include <string.h>
15931 -#include <fdevent.h>
15932  #include <signal.h>
15933  #include <ctype.h>
15934  #include <assert.h>
15935 @@ -29,9 +16,16 @@
15936  #include "connections.h"
15937  #include "joblist.h"
15938  #include "http_chunk.h"
15939 +#include "fdevent.h"
15940  
15941  #include "plugin.h"
15942  
15943 +#include "sys-files.h"
15944 +#include "sys-mmap.h"
15945 +#include "sys-socket.h"
15946 +#include "sys-strings.h"
15947 +#include "sys-process.h"
15948 +
15949  #ifdef HAVE_SYS_FILIO_H
15950  # include <sys/filio.h>
15951  #endif
15952 @@ -40,11 +34,12 @@
15953  
15954  typedef struct {
15955         char **ptr;
15956 -       
15957 +
15958         size_t size;
15959         size_t used;
15960  } char_array;
15961  
15962 +#define pid_t int
15963  typedef struct {
15964         pid_t *ptr;
15965         size_t used;
15966 @@ -58,23 +53,23 @@
15967  typedef struct {
15968         PLUGIN_DATA;
15969         buffer_pid_t cgi_pid;
15970 -       
15971 +
15972         buffer *tmp_buf;
15973         buffer *parse_response;
15974 -       
15975 +
15976         plugin_config **config_storage;
15977 -       
15978 -       plugin_config conf; 
15979 +
15980 +       plugin_config conf;
15981  } plugin_data;
15982  
15983  typedef struct {
15984         pid_t pid;
15985         int fd;
15986         int fde_ndx; /* index into the fd-event buffer */
15987 -       
15988 +
15989         connection *remote_conn;  /* dumb pointer */
15990         plugin_data *plugin_data; /* dumb pointer */
15991 -       
15992 +
15993         buffer *response;
15994         buffer *response_header;
15995  } handler_ctx;
15996 @@ -83,17 +78,17 @@
15997         handler_ctx *hctx = calloc(1, sizeof(*hctx));
15998  
15999         assert(hctx);
16000 -       
16001 +
16002         hctx->response = buffer_init();
16003         hctx->response_header = buffer_init();
16004 -       
16005 +
16006         return hctx;
16007  }
16008  
16009  static void cgi_handler_ctx_free(handler_ctx *hctx) {
16010         buffer_free(hctx->response);
16011         buffer_free(hctx->response_header);
16012 -       
16013 +
16014         free(hctx);
16015  }
16016  
16017 @@ -101,14 +96,14 @@
16018  
16019  INIT_FUNC(mod_cgi_init) {
16020         plugin_data *p;
16021 -       
16022 +
16023         p = calloc(1, sizeof(*p));
16024  
16025         assert(p);
16026 -       
16027 +
16028         p->tmp_buf = buffer_init();
16029         p->parse_response = buffer_init();
16030 -       
16031 +
16032         return p;
16033  }
16034  
16035 @@ -116,62 +111,62 @@
16036  FREE_FUNC(mod_cgi_free) {
16037         plugin_data *p = p_d;
16038         buffer_pid_t *r = &(p->cgi_pid);
16039 -       
16040 +
16041         UNUSED(srv);
16042 -       
16043 +
16044         if (p->config_storage) {
16045                 size_t i;
16046                 for (i = 0; i < srv->config_context->used; i++) {
16047                         plugin_config *s = p->config_storage[i];
16048 -                       
16049 +
16050                         array_free(s->cgi);
16051 -                       
16052 +
16053                         free(s);
16054                 }
16055                 free(p->config_storage);
16056         }
16057 -       
16058 +
16059  
16060         if (r->ptr) free(r->ptr);
16061 -       
16062 +
16063         buffer_free(p->tmp_buf);
16064         buffer_free(p->parse_response);
16065 -       
16066 +
16067         free(p);
16068 -       
16069 +
16070         return HANDLER_GO_ON;
16071  }
16072  
16073  SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
16074         plugin_data *p = p_d;
16075         size_t i = 0;
16076 -       
16077 -       config_values_t cv[] = { 
16078 +
16079 +       config_values_t cv[] = {
16080                 { "cgi.assign",                  NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
16081                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET}
16082         };
16083  
16084         if (!p) return HANDLER_ERROR;
16085 -       
16086 +
16087         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
16088 -       
16089 +
16090         for (i = 0; i < srv->config_context->used; i++) {
16091                 plugin_config *s;
16092 -               
16093 +
16094                 s = calloc(1, sizeof(plugin_config));
16095                 assert(s);
16096 -               
16097 +
16098                 s->cgi    = array_init();
16099 -               
16100 +
16101                 cv[0].destination = s->cgi;
16102 -               
16103 +
16104                 p->config_storage[i] = s;
16105 -       
16106 +
16107                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
16108                         return HANDLER_ERROR;
16109                 }
16110         }
16111 -       
16112 +
16113         return HANDLER_GO_ON;
16114  }
16115  
16116 @@ -180,13 +175,13 @@
16117         int m = -1;
16118         size_t i;
16119         buffer_pid_t *r = &(p->cgi_pid);
16120 -       
16121 +
16122         UNUSED(srv);
16123  
16124         for (i = 0; i < r->used; i++) {
16125                 if (r->ptr[i] > m) m = r->ptr[i];
16126         }
16127 -       
16128 +
16129         if (r->size == 0) {
16130                 r->size = 16;
16131                 r->ptr = malloc(sizeof(*r->ptr) * r->size);
16132 @@ -194,31 +189,31 @@
16133                 r->size += 16;
16134                 r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
16135         }
16136 -       
16137 +
16138         r->ptr[r->used++] = pid;
16139 -       
16140 +
16141         return m;
16142  }
16143  
16144  static int cgi_pid_del(server *srv, plugin_data *p, pid_t pid) {
16145         size_t i;
16146         buffer_pid_t *r = &(p->cgi_pid);
16147 -       
16148 +
16149         UNUSED(srv);
16150  
16151         for (i = 0; i < r->used; i++) {
16152                 if (r->ptr[i] == pid) break;
16153         }
16154 -       
16155 +
16156         if (i != r->used) {
16157                 /* found */
16158 -               
16159 +
16160                 if (i != r->used - 1) {
16161                         r->ptr[i] = r->ptr[r->used - 1];
16162                 }
16163                 r->used--;
16164         }
16165 -       
16166 +
16167         return 0;
16168  }
16169  
16170 @@ -226,32 +221,32 @@
16171         char *ns;
16172         const char *s;
16173         int line = 0;
16174 -       
16175 +
16176         UNUSED(srv);
16177 -       
16178 +
16179         buffer_copy_string_buffer(p->parse_response, in);
16180 -       
16181 -       for (s = p->parse_response->ptr; 
16182 -            NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n'))); 
16183 +
16184 +       for (s = p->parse_response->ptr;
16185 +            NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
16186              s = ns + (eol == EOL_RN ? 2 : 1), line++) {
16187                 const char *key, *value;
16188                 int key_len;
16189                 data_string *ds;
16190 -               
16191 +
16192                 ns[0] = '\0';
16193 -               
16194 -               if (line == 0 && 
16195 +
16196 +               if (line == 0 &&
16197                     0 == strncmp(s, "HTTP/1.", 7)) {
16198                         /* non-parsed header ... we parse them anyway */
16199 -                       
16200 +
16201                         if ((s[7] == '1' ||
16202                              s[7] == '0') &&
16203                             s[8] == ' ') {
16204                                 int status;
16205                                 /* after the space should be a status code for us */
16206 -                               
16207 +
16208                                 status = strtol(s+9, NULL, 10);
16209 -                               
16210 +
16211                                 if (con->http_status >= 100 &&
16212                                     con->http_status < 1000) {
16213                                         /* we expected 3 digits and didn't got them */
16214 @@ -260,27 +255,27 @@
16215                                 }
16216                         }
16217                 } else {
16218 -               
16219 +
16220                         key = s;
16221                         if (NULL == (value = strchr(s, ':'))) {
16222                                 /* we expect: "<key>: <value>\r\n" */
16223                                 continue;
16224                         }
16225 -                       
16226 +
16227                         key_len = value - key;
16228                         value += 1;
16229 -                       
16230 +
16231                         /* skip LWS */
16232                         while (*value == ' ' || *value == '\t') value++;
16233 -                       
16234 +
16235                         if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
16236                                 ds = data_response_init();
16237                         }
16238                         buffer_copy_string_len(ds->key, key, key_len);
16239                         buffer_copy_string(ds->value, value);
16240 -                       
16241 +
16242                         array_insert_unique(con->response.headers, (data_unset *)ds);
16243 -                       
16244 +
16245                         switch(key_len) {
16246                         case 4:
16247                                 if (0 == strncasecmp(key, "Date", key_len)) {
16248 @@ -315,13 +310,13 @@
16249                         }
16250                 }
16251         }
16252 -       
16253 +
16254         /* CGI/1.1 rev 03 - 7.2.1.2 */
16255         if ((con->parsed_response & HTTP_LOCATION) &&
16256             !(con->parsed_response & HTTP_STATUS)) {
16257                 con->http_status = 302;
16258         }
16259 -       
16260 +
16261         return 0;
16262  }
16263  
16264 @@ -329,10 +324,10 @@
16265  static int cgi_demux_response(server *srv, handler_ctx *hctx) {
16266         plugin_data *p    = hctx->plugin_data;
16267         connection  *con  = hctx->remote_conn;
16268 -       
16269 +
16270         while(1) {
16271                 int n;
16272 -               
16273 +
16274                 buffer_prepare_copy(hctx->response, 1024);
16275                 if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
16276                         if (errno == EAGAIN || errno == EINTR) {
16277 @@ -343,125 +338,125 @@
16278                         log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
16279                         return FDEVENT_HANDLED_ERROR;
16280                 }
16281 -               
16282 +
16283                 if (n == 0) {
16284                         /* read finished */
16285 -                       
16286 +
16287                         con->file_finished = 1;
16288 -                       
16289 +
16290                         /* send final chunk */
16291                         http_chunk_append_mem(srv, con, NULL, 0);
16292                         joblist_append(srv, con);
16293 -                       
16294 +
16295                         return FDEVENT_HANDLED_FINISHED;
16296                 }
16297 -               
16298 +
16299                 hctx->response->ptr[n] = '\0';
16300                 hctx->response->used = n+1;
16301 -               
16302 +
16303                 /* split header from body */
16304 -               
16305 +
16306                 if (con->file_started == 0) {
16307                         char *c;
16308                         int in_header = 0;
16309                         int header_end = 0;
16310                         int cp, eol = EOL_UNSET;
16311                         size_t used = 0;
16312 -                       
16313 +
16314                         buffer_append_string_buffer(hctx->response_header, hctx->response);
16315 -                       
16316 +
16317                         /* nph (non-parsed headers) */
16318                         if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
16319 -                       
16320 +
16321                         /* search for the \r\n\r\n or \n\n in the string */
16322                         for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
16323                                 if (*c == ':') in_header = 1;
16324                                 else if (*c == '\n') {
16325                                         if (in_header == 0) {
16326                                                 /* got a response without a response header */
16327 -                                               
16328 +
16329                                                 c = NULL;
16330                                                 header_end = 1;
16331                                                 break;
16332                                         }
16333 -                                       
16334 +
16335                                         if (eol == EOL_UNSET) eol = EOL_N;
16336 -                                       
16337 +
16338                                         if (*(c+1) == '\n') {
16339                                                 header_end = 1;
16340                                                 break;
16341                                         }
16342 -                                       
16343 +
16344                                 } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
16345                                         if (in_header == 0) {
16346                                                 /* got a response without a response header */
16347 -                                               
16348 +
16349                                                 c = NULL;
16350                                                 header_end = 1;
16351                                                 break;
16352                                         }
16353 -                                       
16354 +
16355                                         if (eol == EOL_UNSET) eol = EOL_RN;
16356 -                                       
16357 +
16358                                         if (used > 3 &&
16359 -                                           *(c+2) == '\r' && 
16360 +                                           *(c+2) == '\r' &&
16361                                             *(c+3) == '\n') {
16362                                                 header_end = 1;
16363                                                 break;
16364                                         }
16365 -                                       
16366 +
16367                                         /* skip the \n */
16368                                         c++;
16369                                         cp++;
16370                                         used--;
16371                                 }
16372                         }
16373 -                       
16374 +
16375                         if (header_end) {
16376                                 if (c == NULL) {
16377                                         /* no header, but a body */
16378 -                                       
16379 +
16380                                         if (con->request.http_version == HTTP_VERSION_1_1) {
16381                                                 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
16382                                         }
16383 -                                       
16384 +
16385                                         http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
16386                                         joblist_append(srv, con);
16387                                 } else {
16388                                         size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
16389                                         size_t blen = hctx->response_header->used - hlen - 1;
16390 -                               
16391 +
16392                                         /* a small hack: terminate after at the second \r */
16393                                         hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
16394                                         hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';
16395 -                               
16396 +
16397                                         /* parse the response header */
16398                                         cgi_response_parse(srv, con, p, hctx->response_header, eol);
16399 -                                       
16400 +
16401                                         /* enable chunked-transfer-encoding */
16402                                         if (con->request.http_version == HTTP_VERSION_1_1 &&
16403                                             !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
16404                                                 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
16405                                         }
16406 -                                       
16407 +
16408                                         if ((hctx->response->used != hlen) && blen > 0) {
16409                                                 http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
16410                                                 joblist_append(srv, con);
16411                                         }
16412                                 }
16413 -                               
16414 +
16415                                 con->file_started = 1;
16416                         }
16417                 } else {
16418                         http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
16419                         joblist_append(srv, con);
16420                 }
16421 -               
16422 -#if 0          
16423 +
16424 +#if 0
16425                 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
16426  #endif
16427         }
16428 -       
16429 +
16430         return FDEVENT_HANDLED_NOT_FINISHED;
16431  }
16432  
16433 @@ -470,45 +465,46 @@
16434         pid_t pid;
16435         plugin_data *p;
16436         connection  *con;
16437 -       
16438 +
16439         if (NULL == hctx) return HANDLER_GO_ON;
16440 -       
16441 +
16442         p    = hctx->plugin_data;
16443         con  = hctx->remote_conn;
16444 -       
16445 +
16446         if (con->mode != p->id) return HANDLER_GO_ON;
16447  
16448 -#ifndef __WIN32
16449 -       
16450 +#ifndef _WIN32
16451 +
16452         /* the connection to the browser went away, but we still have a connection
16453 -        * to the CGI script 
16454 +        * to the CGI script
16455          *
16456          * close cgi-connection
16457          */
16458 -       
16459 +
16460         if (hctx->fd != -1) {
16461                 /* close connection to the cgi-script */
16462                 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
16463                 fdevent_unregister(srv->ev, hctx->fd);
16464 -               
16465 +
16466                 if (close(hctx->fd)) {
16467                         log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
16468                 }
16469 -               
16470 +
16471                 hctx->fd = -1;
16472                 hctx->fde_ndx = -1;
16473         }
16474 -       
16475 +
16476         pid = hctx->pid;
16477 -       
16478 +
16479         con->plugin_ctx[p->id] = NULL;
16480 -       
16481 +
16482         /* is this a good idea ? */
16483         cgi_handler_ctx_free(hctx);
16484 -       
16485 +
16486         /* if waitpid hasn't been called by response.c yet, do it here */
16487         if (pid) {
16488                 /* check if the CGI-script is already gone */
16489 +#ifndef _WIN32
16490                 switch(waitpid(pid, &status, WNOHANG)) {
16491                 case 0:
16492                         /* not finished yet */
16493 @@ -519,19 +515,19 @@
16494                 case -1:
16495                         /* */
16496                         if (errno == EINTR) break;
16497 -                       
16498 -                       /* 
16499 -                        * errno == ECHILD happens if _subrequest catches the process-status before 
16500 +
16501 +                       /*
16502 +                        * errno == ECHILD happens if _subrequest catches the process-status before
16503                          * we have read the response of the cgi process
16504 -                        * 
16505 +                        *
16506                          * -> catch status
16507                          * -> WAIT_FOR_EVENT
16508                          * -> read response
16509                          * -> we get here with waitpid == ECHILD
16510 -                        * 
16511 +                        *
16512                          */
16513                         if (errno == ECHILD) return HANDLER_GO_ON;
16514 -                       
16515 +
16516                         log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
16517                         return HANDLER_ERROR;
16518                 default:
16519 @@ -541,13 +537,13 @@
16520                                 con->http_status = 500;
16521                                 con->mode = DIRECT;
16522                         }
16523 -                               
16524 +
16525                         if (WIFEXITED(status)) {
16526  #if 0
16527                                 log_error_write(srv, __FILE__, __LINE__, "sd", "(debug) cgi exited fine, pid:", pid);
16528  #endif
16529                                 pid = 0;
16530 -                               
16531 +
16532                                 return HANDLER_GO_ON;
16533                         } else {
16534                                 log_error_write(srv, __FILE__, __LINE__, "sd", "cgi died, pid:", pid);
16535 @@ -555,20 +551,20 @@
16536                                 return HANDLER_GO_ON;
16537                         }
16538                 }
16539 -               
16540 -       
16541 +
16542 +
16543                 kill(pid, SIGTERM);
16544 -               
16545 +#endif
16546                 /* cgi-script is still alive, queue the PID for removal */
16547                 cgi_pid_add(srv, p, pid);
16548         }
16549 -#endif 
16550 +#endif
16551         return HANDLER_GO_ON;
16552  }
16553  
16554  static handler_t cgi_connection_close_callback(server *srv, connection *con, void *p_d) {
16555         plugin_data *p = p_d;
16556 -       
16557 +
16558         return cgi_connection_close(srv, con->plugin_ctx[p->id]);
16559  }
16560  
16561 @@ -577,43 +573,43 @@
16562         server      *srv  = (server *)s;
16563         handler_ctx *hctx = ctx;
16564         connection  *con  = hctx->remote_conn;
16565 -       
16566 +
16567         joblist_append(srv, con);
16568 -       
16569 +
16570         if (hctx->fd == -1) {
16571                 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "invalid cgi-fd");
16572 -               
16573 +
16574                 return HANDLER_ERROR;
16575         }
16576 -       
16577 +
16578         if (revents & FDEVENT_IN) {
16579                 switch (cgi_demux_response(srv, hctx)) {
16580                 case FDEVENT_HANDLED_NOT_FINISHED:
16581                         break;
16582                 case FDEVENT_HANDLED_FINISHED:
16583                         /* we are done */
16584 -                       
16585 +
16586  #if 0
16587                         log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "finished");
16588  #endif
16589                         cgi_connection_close(srv, hctx);
16590 -                       
16591 -                       /* if we get a IN|HUP and have read everything don't exec the close twice */ 
16592 +
16593 +                       /* if we get a IN|HUP and have read everything don't exec the close twice */
16594                         return HANDLER_FINISHED;
16595                 case FDEVENT_HANDLED_ERROR:
16596                         connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
16597                         con->http_status = 500;
16598                         con->mode = DIRECT;
16599 -                       
16600 +
16601                         log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: ");
16602                         break;
16603                 }
16604         }
16605 -       
16606 +
16607         if (revents & FDEVENT_OUT) {
16608                 /* nothing to do */
16609         }
16610 -       
16611 +
16612         /* perhaps this issue is already handled */
16613         if (revents & FDEVENT_HUP) {
16614                 /* check if we still have a unfinished header package which is a body in reality */
16615 @@ -623,54 +619,54 @@
16616                         http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
16617                         joblist_append(srv, con);
16618                 }
16619 -               
16620 +
16621                 if (con->file_finished == 0) {
16622                         http_chunk_append_mem(srv, con, NULL, 0);
16623                         joblist_append(srv, con);
16624                 }
16625 -               
16626 +
16627                 con->file_finished = 1;
16628 -               
16629 +
16630                 if (chunkqueue_is_empty(con->write_queue)) {
16631                         /* there is nothing left to write */
16632                         connection_set_state(srv, con, CON_STATE_RESPONSE_END);
16633                 } else {
16634                         /* used the write-handler to finish the request on demand */
16635 -                       
16636 +
16637                 }
16638 -               
16639 +
16640  # if 0
16641                 log_error_write(srv, __FILE__, __LINE__, "sddd", "got HUP from cgi", con->fd, hctx->fd, revents);
16642  # endif
16643 -               
16644 +
16645                 /* rtsigs didn't liked the close */
16646                 cgi_connection_close(srv, hctx);
16647         } else if (revents & FDEVENT_ERR) {
16648                 con->file_finished = 1;
16649 -               
16650 +
16651                 /* kill all connections to the cgi process */
16652                 cgi_connection_close(srv, hctx);
16653  #if 1
16654                 log_error_write(srv, __FILE__, __LINE__, "s", "cgi-FDEVENT_ERR");
16655 -#endif                 
16656 +#endif
16657                 return HANDLER_ERROR;
16658         }
16659 -       
16660 +
16661         return HANDLER_FINISHED;
16662  }
16663  
16664  
16665  static int cgi_env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
16666         char *dst;
16667 -       
16668 +
16669         if (!key || !val) return -1;
16670 -       
16671 +
16672         dst = malloc(key_len + val_len + 3);
16673         memcpy(dst, key, key_len);
16674         dst[key_len] = '=';
16675         /* add the \0 from the value */
16676         memcpy(dst + key_len + 1, val, val_len + 1);
16677 -       
16678 +
16679         if (env->size == 0) {
16680                 env->size = 16;
16681                 env->ptr = malloc(env->size * sizeof(*env->ptr));
16682 @@ -678,45 +674,45 @@
16683                 env->size += 16;
16684                 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
16685         }
16686 -       
16687 +
16688         env->ptr[env->used++] = dst;
16689 -       
16690 +
16691         return 0;
16692  }
16693  
16694  static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *cgi_handler) {
16695         pid_t pid;
16696 -       
16697 +
16698  #ifdef HAVE_IPV6
16699         char b2[INET6_ADDRSTRLEN + 1];
16700  #endif
16701 -       
16702 +
16703         int to_cgi_fds[2];
16704         int from_cgi_fds[2];
16705         struct stat st;
16706 -       
16707 -#ifndef __WIN32        
16708 -       
16709 +
16710 +#ifndef _WIN32
16711 +
16712         if (cgi_handler->used > 1) {
16713                 /* stat the exec file */
16714                 if (-1 == (stat(cgi_handler->ptr, &st))) {
16715 -                       log_error_write(srv, __FILE__, __LINE__, "sbss", 
16716 +                       log_error_write(srv, __FILE__, __LINE__, "sbss",
16717                                         "stat for cgi-handler", cgi_handler,
16718                                         "failed:", strerror(errno));
16719                         return -1;
16720                 }
16721         }
16722 -       
16723 +
16724         if (pipe(to_cgi_fds)) {
16725                 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
16726                 return -1;
16727         }
16728 -       
16729 +
16730         if (pipe(from_cgi_fds)) {
16731                 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
16732                 return -1;
16733         }
16734 -       
16735 +
16736         /* fork, execve */
16737         switch (pid = fork()) {
16738         case 0: {
16739 @@ -730,22 +726,22 @@
16740                 char *c;
16741                 const char *s;
16742                 server_socket *srv_sock = con->srv_socket;
16743 -               
16744 +
16745                 /* move stdout to from_cgi_fd[1] */
16746                 close(STDOUT_FILENO);
16747                 dup2(from_cgi_fds[1], STDOUT_FILENO);
16748                 close(from_cgi_fds[1]);
16749                 /* not needed */
16750                 close(from_cgi_fds[0]);
16751 -               
16752 +
16753                 /* move the stdin to to_cgi_fd[0] */
16754                 close(STDIN_FILENO);
16755                 dup2(to_cgi_fds[0], STDIN_FILENO);
16756                 close(to_cgi_fds[0]);
16757                 /* not needed */
16758                 close(to_cgi_fds[1]);
16759 -               
16760 -               /* HACK: 
16761 +
16762 +               /* HACK:
16763                  * this is not nice, but it works
16764                  *
16765                  * we feed the stderr of the CGI to our errorlog, if possible
16766 @@ -754,20 +750,20 @@
16767                         close(STDERR_FILENO);
16768                         dup2(srv->errorlog_fd, STDERR_FILENO);
16769                 }
16770 -               
16771 +
16772                 /* create environment */
16773                 env.ptr = NULL;
16774                 env.size = 0;
16775                 env.used = 0;
16776 -               
16777 +
16778                 cgi_env_add(&env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
16779  
16780                 if (!buffer_is_empty(con->server_name)) {
16781                         cgi_env_add(&env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
16782                 } else {
16783  #ifdef HAVE_IPV6
16784 -                       s = inet_ntop(srv_sock->addr.plain.sa_family, 
16785 -                                     srv_sock->addr.plain.sa_family == AF_INET6 ? 
16786 +                       s = inet_ntop(srv_sock->addr.plain.sa_family,
16787 +                                     srv_sock->addr.plain.sa_family == AF_INET6 ?
16788                                       (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
16789                                       (const void *) &(srv_sock->addr.ipv4.sin_addr),
16790                                       b2, sizeof(b2)-1);
16791 @@ -779,10 +775,10 @@
16792                 cgi_env_add(&env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
16793  
16794                 s = get_http_version_name(con->request.http_version);
16795 -               
16796 +
16797                 cgi_env_add(&env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
16798 -               
16799 -               ltostr(buf, 
16800 +
16801 +               ltostr(buf,
16802  #ifdef HAVE_IPV6
16803                         ntohs(srv_sock->addr.plain.sa_family == AF_INET6 ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
16804  #else
16805 @@ -790,10 +786,10 @@
16806  #endif
16807                         );
16808                 cgi_env_add(&env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
16809 -               
16810 +
16811  #ifdef HAVE_IPV6
16812 -               s = inet_ntop(srv_sock->addr.plain.sa_family, 
16813 -                             srv_sock->addr.plain.sa_family == AF_INET6 ? 
16814 +               s = inet_ntop(srv_sock->addr.plain.sa_family,
16815 +                             srv_sock->addr.plain.sa_family == AF_INET6 ?
16816                               (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
16817                               (const void *) &(srv_sock->addr.ipv4.sin_addr),
16818                               b2, sizeof(b2)-1);
16819 @@ -811,15 +807,18 @@
16820                 cgi_env_add(&env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200"));
16821                 if (!buffer_is_empty(con->uri.query)) {
16822                         cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query));
16823 +               } else {
16824 +                       /* set a empty QUERY_STRING */
16825 +                       cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
16826                 }
16827                 if (!buffer_is_empty(con->request.orig_uri)) {
16828                         cgi_env_add(&env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
16829                 }
16830 -               
16831 -               
16832 +
16833 +
16834  #ifdef HAVE_IPV6
16835 -               s = inet_ntop(con->dst_addr.plain.sa_family, 
16836 -                             con->dst_addr.plain.sa_family == AF_INET6 ? 
16837 +               s = inet_ntop(con->dst_addr.plain.sa_family,
16838 +                             con->dst_addr.plain.sa_family == AF_INET6 ?
16839                               (const void *) &(con->dst_addr.ipv6.sin6_addr) :
16840                               (const void *) &(con->dst_addr.ipv4.sin_addr),
16841                               b2, sizeof(b2)-1);
16842 @@ -828,7 +827,7 @@
16843  #endif
16844                 cgi_env_add(&env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
16845  
16846 -               ltostr(buf, 
16847 +               ltostr(buf,
16848  #ifdef HAVE_IPV6
16849                         ntohs(con->dst_addr.plain.sa_family == AF_INET6 ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
16850  #else
16851 @@ -836,19 +835,19 @@
16852  #endif
16853                         );
16854                 cgi_env_add(&env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
16855 -               
16856 +
16857                 if (!buffer_is_empty(con->authed_user)) {
16858                         cgi_env_add(&env, CONST_STR_LEN("REMOTE_USER"),
16859                                     CONST_BUF_LEN(con->authed_user));
16860                 }
16861 -               
16862 +
16863                 /* request.content_length < SSIZE_MAX, see request.c */
16864                 ltostr(buf, con->request.content_length);
16865                 cgi_env_add(&env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
16866                 cgi_env_add(&env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
16867                 cgi_env_add(&env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
16868                 cgi_env_add(&env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
16869 -               
16870 +
16871                 /* for valgrind */
16872                 if (NULL != (s = getenv("LD_PRELOAD"))) {
16873                         cgi_env_add(&env, CONST_STR_LEN("LD_PRELOAD"), s, strlen(s));
16874 @@ -863,24 +862,24 @@
16875                         cgi_env_add(&env, CONST_STR_LEN("SYSTEMROOT"), s, strlen(s));
16876                 }
16877  #endif
16878 -               
16879 +
16880                 for (n = 0; n < con->request.headers->used; n++) {
16881                         data_string *ds;
16882 -                       
16883 +
16884                         ds = (data_string *)con->request.headers->data[n];
16885 -                       
16886 +
16887                         if (ds->value->used && ds->key->used) {
16888                                 size_t j;
16889 -                               
16890 +
16891                                 buffer_reset(p->tmp_buf);
16892 -                               
16893 +
16894                                 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
16895                                         buffer_copy_string(p->tmp_buf, "HTTP_");
16896                                         p->tmp_buf->used--; /* strip \0 after HTTP_ */
16897                                 }
16898 -                               
16899 +
16900                                 buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
16901 -                               
16902 +
16903                                 for (j = 0; j < ds->key->used - 1; j++) {
16904                                         char cr = '_';
16905                                         if (light_isalpha(ds->key->ptr[j])) {
16906 @@ -893,46 +892,46 @@
16907                                         p->tmp_buf->ptr[p->tmp_buf->used++] = cr;
16908                                 }
16909                                 p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
16910 -                               
16911 +
16912                                 cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
16913                         }
16914                 }
16915 -               
16916 +
16917                 for (n = 0; n < con->environment->used; n++) {
16918                         data_string *ds;
16919 -                       
16920 +
16921                         ds = (data_string *)con->environment->data[n];
16922 -                       
16923 +
16924                         if (ds->value->used && ds->key->used) {
16925                                 size_t j;
16926 -                               
16927 +
16928                                 buffer_reset(p->tmp_buf);
16929 -                               
16930 +
16931                                 buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
16932 -                               
16933 +
16934                                 for (j = 0; j < ds->key->used - 1; j++) {
16935 -                                       p->tmp_buf->ptr[p->tmp_buf->used++] = 
16936 -                                               isalpha((unsigned char)ds->key->ptr[j]) ? 
16937 +                                       p->tmp_buf->ptr[p->tmp_buf->used++] =
16938 +                                               isalpha((unsigned char)ds->key->ptr[j]) ?
16939                                                 toupper((unsigned char)ds->key->ptr[j]) : '_';
16940                                 }
16941                                 p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
16942 -                               
16943 +
16944                                 cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
16945                         }
16946                 }
16947 -               
16948 +
16949                 if (env.size == env.used) {
16950                         env.size += 16;
16951                         env.ptr = realloc(env.ptr, env.size * sizeof(*env.ptr));
16952                 }
16953 -               
16954 +
16955                 env.ptr[env.used] = NULL;
16956 -               
16957 +
16958                 /* set up args */
16959                 argc = 3;
16960                 args = malloc(sizeof(*args) * argc);
16961                 i = 0;
16962 -               
16963 +
16964                 if (cgi_handler->used > 1) {
16965                         args[i++] = cgi_handler->ptr;
16966                 }
16967 @@ -942,7 +941,7 @@
16968                 /* search for the last / */
16969                 if (NULL != (c = strrchr(con->physical.path->ptr, '/'))) {
16970                         *c = '\0';
16971 -                       
16972 +
16973                         /* change to the physical directory */
16974                         if (-1 == chdir(con->physical.path->ptr)) {
16975                                 log_error_write(srv, __FILE__, __LINE__, "ssb", "chdir failed:", strerror(errno), con->physical.path);
16976 @@ -954,12 +953,12 @@
16977                 for (i = 3; i < 256; i++) {
16978                         if (i != srv->errorlog_fd) close(i);
16979                 }
16980 -               
16981 +
16982                 /* exec the cgi */
16983                 execve(args[0], args, env.ptr);
16984 -               
16985 +
16986                 log_error_write(srv, __FILE__, __LINE__, "sss", "CGI failed:", strerror(errno), args[0]);
16987 -               
16988 +
16989                 /* */
16990                 SEGFAULT();
16991                 break;
16992 @@ -974,11 +973,11 @@
16993  
16994                 close(from_cgi_fds[1]);
16995                 close(to_cgi_fds[0]);
16996 -               
16997 +
16998                 if (con->request.content_length) {
16999                         chunkqueue *cq = con->request_content_queue;
17000                         chunk *c;
17001 -               
17002 +
17003                         assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
17004  
17005                         /* there is content to send */
17006 @@ -993,16 +992,16 @@
17007                                                 if (-1 == c->file.fd &&  /* open the file if not already open */
17008                                                     -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
17009                                                         log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
17010 -                                       
17011 +
17012                                                         close(from_cgi_fds[0]);
17013                                                         close(to_cgi_fds[1]);
17014                                                         return -1;
17015                                                 }
17016  
17017                                                 c->file.mmap.length = c->file.length;
17018 -                               
17019 +
17020                                                 if (MAP_FAILED == (c->file.mmap.start = mmap(0,  c->file.mmap.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
17021 -                                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ", 
17022 +                                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
17023                                                                         strerror(errno), c->file.name,  c->file.fd);
17024  
17025                                                         close(from_cgi_fds[0]);
17026 @@ -1012,7 +1011,7 @@
17027  
17028                                                 close(c->file.fd);
17029                                                 c->file.fd = -1;
17030 -       
17031 +
17032                                                 /* chunk_reset() or chunk_free() will cleanup for us */
17033                                         }
17034  
17035 @@ -1020,7 +1019,7 @@
17036                                                 switch(errno) {
17037                                                 case ENOSPC:
17038                                                         con->http_status = 507;
17039 -               
17040 +
17041                                                         break;
17042                                                 default:
17043                                                         con->http_status = 403;
17044 @@ -1033,7 +1032,7 @@
17045                                                 switch(errno) {
17046                                                 case ENOSPC:
17047                                                         con->http_status = 507;
17048 -               
17049 +
17050                                                         break;
17051                                                 default:
17052                                                         con->http_status = 403;
17053 @@ -1056,103 +1055,100 @@
17054                 }
17055  
17056                 close(to_cgi_fds[1]);
17057 -                               
17058 +
17059                 /* register PID and wait for them asyncronously */
17060                 con->mode = p->id;
17061                 buffer_reset(con->physical.path);
17062 -               
17063 +
17064                 hctx = cgi_handler_ctx_init();
17065 -               
17066 +
17067                 hctx->remote_conn = con;
17068                 hctx->plugin_data = p;
17069                 hctx->pid = pid;
17070                 hctx->fd = from_cgi_fds[0];
17071                 hctx->fde_ndx = -1;
17072 -               
17073 +
17074                 con->plugin_ctx[p->id] = hctx;
17075 -               
17076 +
17077                 fdevent_register(srv->ev, hctx->fd, cgi_handle_fdevent, hctx);
17078                 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
17079 -               
17080 +
17081                 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
17082                         log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
17083 -                       
17084 +
17085                         fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
17086                         fdevent_unregister(srv->ev, hctx->fd);
17087 -                       
17088 +
17089                         log_error_write(srv, __FILE__, __LINE__, "sd", "cgi close:", hctx->fd);
17090 -                       
17091 +
17092                         close(hctx->fd);
17093 -                       
17094 +
17095                         cgi_handler_ctx_free(hctx);
17096 -                       
17097 +
17098                         con->plugin_ctx[p->id] = NULL;
17099 -                       
17100 +
17101                         return -1;
17102                 }
17103 -               
17104 +
17105                 break;
17106         }
17107         }
17108 -       
17109 +
17110         return 0;
17111  #else
17112         return -1;
17113  #endif
17114  }
17115  
17116 -#define PATCH(x) \
17117 -       p->conf.x = s->x;
17118  static int mod_cgi_patch_connection(server *srv, connection *con, plugin_data *p) {
17119         size_t i, j;
17120         plugin_config *s = p->config_storage[0];
17121 -       
17122 -       PATCH(cgi);
17123 -       
17124 +
17125 +       PATCH_OPTION(cgi);
17126 +
17127         /* skip the first, the global context */
17128         for (i = 1; i < srv->config_context->used; i++) {
17129                 data_config *dc = (data_config *)srv->config_context->data[i];
17130                 s = p->config_storage[i];
17131 -               
17132 +
17133                 /* condition didn't match */
17134                 if (!config_check_cond(srv, con, dc)) continue;
17135 -               
17136 +
17137                 /* merge config */
17138                 for (j = 0; j < dc->value->used; j++) {
17139                         data_unset *du = dc->value->data[j];
17140 -                       
17141 +
17142                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.assign"))) {
17143 -                               PATCH(cgi);
17144 +                               PATCH_OPTION(cgi);
17145                         }
17146                 }
17147         }
17148 -       
17149 +
17150         return 0;
17151  }
17152 -#undef PATCH
17153  
17154  URIHANDLER_FUNC(cgi_is_handled) {
17155         size_t k, s_len;
17156         plugin_data *p = p_d;
17157         buffer *fn = con->physical.path;
17158 -       
17159 +
17160         if (fn->used == 0) return HANDLER_GO_ON;
17161 -       
17162 +
17163         mod_cgi_patch_connection(srv, con, p);
17164 -       
17165 +
17166         s_len = fn->used - 1;
17167 -       
17168 +
17169         for (k = 0; k < p->conf.cgi->used; k++) {
17170                 data_string *ds = (data_string *)p->conf.cgi->data[k];
17171                 size_t ct_len = ds->key->used - 1;
17172 -               
17173 +
17174                 if (ds->key->used == 0) continue;
17175                 if (s_len < ct_len) continue;
17176 -               
17177 +
17178                 if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
17179                         if (cgi_create_env(srv, con, p, ds->value)) {
17180                                 con->http_status = 500;
17181 -                               
17182 +
17183                                 buffer_reset(con->physical.path);
17184                                 return HANDLER_FINISHED;
17185                         }
17186 @@ -1160,7 +1156,7 @@
17187                         break;
17188                 }
17189         }
17190 -       
17191 +
17192         return HANDLER_GO_ON;
17193  }
17194  
17195 @@ -1168,11 +1164,11 @@
17196         plugin_data *p = p_d;
17197         size_t ndx;
17198         /* the trigger handle only cares about lonely PID which we have to wait for */
17199 -#ifndef __WIN32
17200 +#ifndef _WIN32
17201  
17202         for (ndx = 0; ndx < p->cgi_pid.used; ndx++) {
17203                 int status;
17204 -               
17205 +
17206                 switch(waitpid(p->cgi_pid.ptr[ndx], &status, WNOHANG)) {
17207                 case 0:
17208                         /* not finished yet */
17209 @@ -1182,7 +1178,7 @@
17210                         break;
17211                 case -1:
17212                         log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
17213 -                       
17214 +
17215                         return HANDLER_ERROR;
17216                 default:
17217  
17218 @@ -1193,16 +1189,16 @@
17219                         } else {
17220                                 log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
17221                         }
17222 -                       
17223 +
17224                         cgi_pid_del(srv, p, p->cgi_pid.ptr[ndx]);
17225 -                       /* del modified the buffer structure 
17226 +                       /* del modified the buffer structure
17227                          * and copies the last entry to the current one
17228                          * -> recheck the current index
17229                          */
17230                         ndx--;
17231                 }
17232         }
17233 -#endif 
17234 +#endif
17235         return HANDLER_GO_ON;
17236  }
17237  
17238 @@ -1210,15 +1206,15 @@
17239         int status;
17240         plugin_data *p = p_d;
17241         handler_ctx *hctx = con->plugin_ctx[p->id];
17242 -       
17243 +
17244         if (con->mode != p->id) return HANDLER_GO_ON;
17245         if (NULL == hctx) return HANDLER_GO_ON;
17246 -       
17247 +
17248  #if 0
17249         log_error_write(srv, __FILE__, __LINE__, "sdd", "subrequest, pid =", hctx, hctx->pid);
17250 -#endif 
17251 +#endif
17252         if (hctx->pid == 0) return HANDLER_FINISHED;
17253 -#ifndef __WIN32        
17254 +#ifndef _WIN32
17255         switch(waitpid(hctx->pid, &status, WNOHANG)) {
17256         case 0:
17257                 /* we only have for events here if we don't have the header yet,
17258 @@ -1228,61 +1224,61 @@
17259                 return HANDLER_WAIT_FOR_EVENT;
17260         case -1:
17261                 if (errno == EINTR) return HANDLER_WAIT_FOR_EVENT;
17262 -               
17263 +
17264                 if (errno == ECHILD && con->file_started == 0) {
17265                         /*
17266 -                        * second round but still not response 
17267 +                        * second round but still not response
17268                          */
17269 -                       return HANDLER_WAIT_FOR_EVENT; 
17270 +                       return HANDLER_WAIT_FOR_EVENT;
17271                 }
17272 -               
17273 +
17274                 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
17275                 con->mode = DIRECT;
17276                 con->http_status = 500;
17277 -               
17278 +
17279                 hctx->pid = 0;
17280 -               
17281 +
17282                 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
17283                 fdevent_unregister(srv->ev, hctx->fd);
17284 -               
17285 +
17286                 if (close(hctx->fd)) {
17287                         log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
17288                 }
17289 -               
17290 +
17291                 cgi_handler_ctx_free(hctx);
17292 -               
17293 +
17294                 con->plugin_ctx[p->id] = NULL;
17295 -               
17296 +
17297                 return HANDLER_FINISHED;
17298         default:
17299 -               /* cgi process exited cleanly 
17300 -                * 
17301 -                * check if we already got the response 
17302 +               /* cgi process exited cleanly
17303 +                *
17304 +                * check if we already got the response
17305                  */
17306 -               
17307 +
17308                 if (!con->file_started) return HANDLER_WAIT_FOR_EVENT;
17309 -               
17310 +
17311                 if (WIFEXITED(status)) {
17312                         /* nothing */
17313                 } else {
17314                         log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
17315 -                       
17316 +
17317                         con->mode = DIRECT;
17318                         con->http_status = 500;
17319 -                       
17320 +
17321                 }
17322 -               
17323 +
17324                 hctx->pid = 0;
17325 -               
17326 +
17327                 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
17328                 fdevent_unregister(srv->ev, hctx->fd);
17329 -               
17330 +
17331                 if (close(hctx->fd)) {
17332                         log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
17333                 }
17334 -               
17335 +
17336                 cgi_handler_ctx_free(hctx);
17337 -               
17338 +
17339                 con->plugin_ctx[p->id] = NULL;
17340                 return HANDLER_FINISHED;
17341         }
17342 @@ -1306,8 +1302,8 @@
17343         p->init           = mod_cgi_init;
17344         p->cleanup        = mod_cgi_free;
17345         p->set_defaults   = mod_fastcgi_set_defaults;
17346 -       
17347 +
17348         p->data        = NULL;
17349 -       
17350 +
17351         return 0;
17352  }
17353 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_cml.c lighttpd-1.4.12/src/mod_cml.c
17354 --- lighttpd-1.4.11/src/mod_cml.c       2006-01-30 13:51:48.000000000 +0200
17355 +++ lighttpd-1.4.12/src/mod_cml.c       2006-07-11 21:23:39.000000000 +0300
17356 @@ -4,7 +4,6 @@
17357  #include <stdlib.h>
17358  #include <string.h>
17359  #include <errno.h>
17360 -#include <unistd.h>
17361  #include <stdio.h>
17362  
17363  #include "buffer.h"
17364 @@ -20,50 +19,50 @@
17365  /* init the plugin data */
17366  INIT_FUNC(mod_cml_init) {
17367         plugin_data *p;
17368 -       
17369 +
17370         p = calloc(1, sizeof(*p));
17371 -       
17372 +
17373         p->basedir         = buffer_init();
17374         p->baseurl         = buffer_init();
17375         p->trigger_handler = buffer_init();
17376 -       
17377 +
17378         return p;
17379  }
17380  
17381  /* detroy the plugin data */
17382  FREE_FUNC(mod_cml_free) {
17383         plugin_data *p = p_d;
17384 -       
17385 +
17386         UNUSED(srv);
17387  
17388         if (!p) return HANDLER_GO_ON;
17389 -       
17390 +
17391         if (p->config_storage) {
17392                 size_t i;
17393                 for (i = 0; i < srv->config_context->used; i++) {
17394                         plugin_config *s = p->config_storage[i];
17395 -                       
17396 +
17397                         buffer_free(s->ext);
17398 -                       
17399 +
17400                         buffer_free(s->mc_namespace);
17401                         buffer_free(s->power_magnet);
17402                         array_free(s->mc_hosts);
17403 -                       
17404 +
17405  #if defined(HAVE_MEMCACHE_H)
17406                         if (s->mc) mc_free(s->mc);
17407  #endif
17408 -                       
17409 +
17410                         free(s);
17411                 }
17412                 free(p->config_storage);
17413         }
17414 -       
17415 +
17416         buffer_free(p->trigger_handler);
17417         buffer_free(p->basedir);
17418         buffer_free(p->baseurl);
17419 -       
17420 +
17421         free(p);
17422 -       
17423 +
17424         return HANDLER_GO_ON;
17425  }
17426  
17427 @@ -72,22 +71,22 @@
17428  SETDEFAULTS_FUNC(mod_cml_set_defaults) {
17429         plugin_data *p = p_d;
17430         size_t i = 0;
17431 -       
17432 -       config_values_t cv[] = { 
17433 +
17434 +       config_values_t cv[] = {
17435                 { "cml.extension",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
17436                 { "cml.memcache-hosts",         NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },        /* 1 */
17437                 { "cml.memcache-namespace",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
17438                 { "cml.power-magnet",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 3 */
17439                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
17440         };
17441 -       
17442 +
17443         if (!p) return HANDLER_ERROR;
17444 -       
17445 +
17446         p->config_storage = malloc(srv->config_context->used * sizeof(specific_config *));
17447 -       
17448 +
17449         for (i = 0; i < srv->config_context->used; i++) {
17450                 plugin_config *s;
17451 -               
17452 +
17453                 s = malloc(sizeof(plugin_config));
17454                 s->ext    = buffer_init();
17455                 s->mc_hosts       = array_init();
17456 @@ -96,87 +95,84 @@
17457  #if defined(HAVE_MEMCACHE_H)
17458                 s->mc = NULL;
17459  #endif
17460 -               
17461 +
17462                 cv[0].destination = s->ext;
17463                 cv[1].destination = s->mc_hosts;
17464                 cv[2].destination = s->mc_namespace;
17465                 cv[3].destination = s->power_magnet;
17466 -               
17467 +
17468                 p->config_storage[i] = s;
17469 -       
17470 +
17471                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
17472                         return HANDLER_ERROR;
17473                 }
17474 -               
17475 +
17476                 if (s->mc_hosts->used) {
17477  #if defined(HAVE_MEMCACHE_H)
17478                         size_t k;
17479                         s->mc = mc_new();
17480 -               
17481 +
17482                         for (k = 0; k < s->mc_hosts->used; k++) {
17483                                 data_string *ds = (data_string *)s->mc_hosts->data[k];
17484 -                               
17485 +
17486                                 if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
17487 -                                       log_error_write(srv, __FILE__, __LINE__, "sb", 
17488 -                                                       "connection to host failed:", 
17489 +                                       log_error_write(srv, __FILE__, __LINE__, "sb",
17490 +                                                       "connection to host failed:",
17491                                                         ds->value);
17492 -                                       
17493 +
17494                                         return HANDLER_ERROR;
17495                                 }
17496                         }
17497  #else
17498 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
17499 +                       log_error_write(srv, __FILE__, __LINE__, "s",
17500                                         "memcache support is not compiled in but cml.memcache-hosts is set, aborting");
17501                         return HANDLER_ERROR;
17502  #endif
17503                 }
17504         }
17505 -       
17506 +
17507         return HANDLER_GO_ON;
17508  }
17509  
17510 -#define PATCH(x) \
17511 -       p->conf.x = s->x;
17512  static int mod_cml_patch_connection(server *srv, connection *con, plugin_data *p) {
17513         size_t i, j;
17514         plugin_config *s = p->config_storage[0];
17515 -       
17516 -       PATCH(ext);
17517 +
17518 +       PATCH_OPTION(ext);
17519  #if defined(HAVE_MEMCACHE_H)
17520 -       PATCH(mc);
17521 +       PATCH_OPTION(mc);
17522  #endif
17523 -       PATCH(mc_namespace);
17524 -       PATCH(power_magnet);
17525 -       
17526 +       PATCH_OPTION(mc_namespace);
17527 +       PATCH_OPTION(power_magnet);
17528 +
17529         /* skip the first, the global context */
17530         for (i = 1; i < srv->config_context->used; i++) {
17531                 data_config *dc = (data_config *)srv->config_context->data[i];
17532                 s = p->config_storage[i];
17533 -               
17534 +
17535                 /* condition didn't match */
17536                 if (!config_check_cond(srv, con, dc)) continue;
17537 -               
17538 +
17539                 /* merge config */
17540                 for (j = 0; j < dc->value->used; j++) {
17541                         data_unset *du = dc->value->data[j];
17542 -                       
17543 +
17544                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.extension"))) {
17545 -                               PATCH(ext);
17546 +                               PATCH_OPTION(ext);
17547                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-hosts"))) {
17548  #if defined(HAVE_MEMCACHE_H)
17549 -                               PATCH(mc);
17550 +                               PATCH_OPTION(mc);
17551  #endif
17552                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-namespace"))) {
17553 -                               PATCH(mc_namespace);
17554 +                               PATCH_OPTION(mc_namespace);
17555                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.power-magnet"))) {
17556 -                               PATCH(power_magnet);
17557 +                               PATCH_OPTION(power_magnet);
17558                         }
17559                 }
17560         }
17561 -       
17562 +
17563         return 0;
17564  }
17565 -#undef PATCH
17566  
17567  int cache_call_lua(server *srv, connection *con, plugin_data *p, buffer *cml_file) {
17568         buffer *b;
17569 @@ -187,57 +183,57 @@
17570         b = p->baseurl;
17571         buffer_copy_string_buffer(b, con->uri.path);
17572         for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
17573 -       
17574 +
17575         if (*c == '/') {
17576                 b->used = c - b->ptr + 2;
17577                 *(c+1) = '\0';
17578         }
17579 -       
17580 +
17581         b = p->basedir;
17582         buffer_copy_string_buffer(b, con->physical.path);
17583         for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
17584 -       
17585 +
17586         if (*c == '/') {
17587                 b->used = c - b->ptr + 2;
17588                 *(c+1) = '\0';
17589         }
17590 -       
17591 +
17592  
17593         /* prepare variables
17594          *   - cookie-based
17595          *   - get-param-based
17596          */
17597 -       
17598 +
17599         return cache_parse_lua(srv, con, p, cml_file);
17600 -       
17601 +
17602  }
17603  
17604  URIHANDLER_FUNC(mod_cml_power_magnet) {
17605         plugin_data *p = p_d;
17606 -       
17607 +
17608         mod_cml_patch_connection(srv, con, p);
17609 -       
17610 +
17611         buffer_reset(p->basedir);
17612         buffer_reset(p->baseurl);
17613         buffer_reset(p->trigger_handler);
17614  
17615         if (buffer_is_empty(p->conf.power_magnet)) return HANDLER_GO_ON;
17616 -       
17617 -       /* 
17618 +
17619 +       /*
17620          * power-magnet:
17621          * cml.power-magnet = server.docroot + "/rewrite.cml"
17622          *
17623          * is called on EACH request, take the original REQUEST_URI and modifies the
17624 -        * request header as neccesary. 
17625 +        * request header as neccesary.
17626          *
17627          * First use:
17628          * if file_exists("/maintainance.html") {
17629          *   output_include = ( "/maintainance.html" )
17630 -        *   return CACHE_HIT 
17631 +        *   return CACHE_HIT
17632          * }
17633          *
17634          * as we only want to rewrite HTML like requests we should cover it in a conditional
17635 -        * 
17636 +        *
17637          * */
17638  
17639         switch(cache_call_lua(srv, con, p, p->conf.power_magnet)) {
17640 @@ -266,20 +262,20 @@
17641  
17642  URIHANDLER_FUNC(mod_cml_is_handled) {
17643         plugin_data *p = p_d;
17644 -       
17645 +
17646         if (buffer_is_empty(con->physical.path)) return HANDLER_ERROR;
17647 -       
17648 +
17649         mod_cml_patch_connection(srv, con, p);
17650 -       
17651 +
17652         buffer_reset(p->basedir);
17653         buffer_reset(p->baseurl);
17654         buffer_reset(p->trigger_handler);
17655  
17656         if (buffer_is_empty(p->conf.ext)) return HANDLER_GO_ON;
17657 -       
17658 +
17659         if (!buffer_is_equal_right_len(con->physical.path, p->conf.ext, p->conf.ext->used - 1)) {
17660                 return HANDLER_GO_ON;
17661 -       } 
17662 +       }
17663  
17664         switch(cache_call_lua(srv, con, p, con->physical.path)) {
17665         case -1:
17666 @@ -311,15 +307,15 @@
17667  int mod_cml_plugin_init(plugin *p) {
17668         p->version     = LIGHTTPD_VERSION_ID;
17669         p->name        = buffer_init_string("cache");
17670 -       
17671 +
17672         p->init        = mod_cml_init;
17673         p->cleanup     = mod_cml_free;
17674         p->set_defaults  = mod_cml_set_defaults;
17675 -       
17676 +
17677         p->handle_subrequest_start = mod_cml_is_handled;
17678         p->handle_physical         = mod_cml_power_magnet;
17679 -       
17680 +
17681         p->data        = NULL;
17682 -       
17683 +
17684         return 0;
17685  }
17686 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_cml.h lighttpd-1.4.12/src/mod_cml.h
17687 --- lighttpd-1.4.11/src/mod_cml.h       2006-01-30 13:51:35.000000000 +0200
17688 +++ lighttpd-1.4.12/src/mod_cml.h       2006-07-11 21:23:39.000000000 +0300
17689 @@ -16,10 +16,10 @@
17690  
17691  typedef struct {
17692         buffer *ext;
17693 -       
17694 +
17695         array  *mc_hosts;
17696         buffer *mc_namespace;
17697 -#if defined(HAVE_MEMCACHE_H) 
17698 +#if defined(HAVE_MEMCACHE_H)
17699         struct memcache *mc;
17700  #endif
17701         buffer *power_magnet;
17702 @@ -27,15 +27,15 @@
17703  
17704  typedef struct {
17705         PLUGIN_DATA;
17706 -       
17707 +
17708         buffer *basedir;
17709         buffer *baseurl;
17710 -       
17711 +
17712         buffer *trigger_handler;
17713 -       
17714 +
17715         plugin_config **config_storage;
17716 -       
17717 -       plugin_config conf; 
17718 +
17719 +       plugin_config conf;
17720  } plugin_data;
17721  
17722  int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn);
17723 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_cml_funcs.c lighttpd-1.4.12/src/mod_cml_funcs.c
17724 --- lighttpd-1.4.11/src/mod_cml_funcs.c 2005-11-17 16:15:08.000000000 +0200
17725 +++ lighttpd-1.4.12/src/mod_cml_funcs.c 2006-07-11 21:23:40.000000000 +0300
17726 @@ -4,8 +4,7 @@
17727  #include <stdlib.h>
17728  #include <string.h>
17729  #include <errno.h>
17730 -#include <unistd.h>
17731 -#include <dirent.h>
17732 +
17733  #include <stdio.h>
17734  
17735  #include "buffer.h"
17736 @@ -13,6 +12,7 @@
17737  #include "log.h"
17738  #include "plugin.h"
17739  #include "response.h"
17740 +#include "sys-files.h"
17741  
17742  #include "mod_cml.h"
17743  #include "mod_cml_funcs.h"
17744 @@ -30,7 +30,7 @@
17745  #ifdef USE_OPENSSL
17746  #define IN const
17747  #else
17748 -#define IN 
17749 +#define IN
17750  #endif
17751  #define OUT
17752  
17753 @@ -42,29 +42,29 @@
17754         buffer b;
17755         char hex[33];
17756         int n = lua_gettop(L);
17757 -       
17758 +
17759         b.ptr = hex;
17760         b.used = 0;
17761         b.size = sizeof(hex);
17762 -       
17763 +
17764         if (n != 1) {
17765                 lua_pushstring(L, "md5: expected one argument");
17766                 lua_error(L);
17767         }
17768 -       
17769 +
17770         if (!lua_isstring(L, 1)) {
17771                 lua_pushstring(L, "md5: argument has to be a string");
17772                 lua_error(L);
17773         }
17774 -       
17775 +
17776         MD5_Init(&Md5Ctx);
17777         MD5_Update(&Md5Ctx, (unsigned char *)lua_tostring(L, 1), lua_strlen(L, 1));
17778         MD5_Final(HA1, &Md5Ctx);
17779 -       
17780 +
17781         buffer_copy_string_hex(&b, (char *)HA1, 16);
17782 -       
17783 +
17784         lua_pushstring(L, b.ptr);
17785 -       
17786 +
17787         return 1;
17788  }
17789  
17790 @@ -72,37 +72,37 @@
17791  int f_file_mtime(lua_State *L) {
17792         struct stat st;
17793         int n = lua_gettop(L);
17794 -       
17795 +
17796         if (n != 1) {
17797                 lua_pushstring(L, "file_mtime: expected one argument");
17798                 lua_error(L);
17799         }
17800 -       
17801 +
17802         if (!lua_isstring(L, 1)) {
17803                 lua_pushstring(L, "file_mtime: argument has to be a string");
17804                 lua_error(L);
17805         }
17806 -       
17807 +
17808         if (-1 == stat(lua_tostring(L, 1), &st)) {
17809                 lua_pushnil(L);
17810                 return 1;
17811         }
17812 -       
17813 +
17814         lua_pushnumber(L, st.st_mtime);
17815 -       
17816 +
17817         return 1;
17818  }
17819 -
17820 +#ifndef _WIN32
17821  int f_dir_files_iter(lua_State *L) {
17822         DIR *d;
17823         struct dirent *de;
17824 -       
17825 +
17826         d = lua_touserdata(L, lua_upvalueindex(1));
17827 -       
17828 +
17829         if (NULL == (de = readdir(d))) {
17830                 /* EOF */
17831                 closedir(d);
17832 -               
17833 +
17834                 return 0;
17835         } else {
17836                 lua_pushstring(L, de->d_name);
17837 @@ -113,75 +113,75 @@
17838  int f_dir_files(lua_State *L) {
17839         DIR *d;
17840         int n = lua_gettop(L);
17841 -       
17842 +
17843         if (n != 1) {
17844                 lua_pushstring(L, "dir_files: expected one argument");
17845                 lua_error(L);
17846         }
17847 -       
17848 +
17849         if (!lua_isstring(L, 1)) {
17850                 lua_pushstring(L, "dir_files: argument has to be a string");
17851                 lua_error(L);
17852         }
17853 -       
17854 -       /* check if there is a valid DIR handle on the stack */ 
17855 +
17856 +       /* check if there is a valid DIR handle on the stack */
17857         if (NULL == (d = opendir(lua_tostring(L, 1)))) {
17858                 lua_pushnil(L);
17859                 return 1;
17860         }
17861 -       
17862 +
17863         /* push d into registry */
17864         lua_pushlightuserdata(L, d);
17865         lua_pushcclosure(L, f_dir_files_iter, 1);
17866 -       
17867 +
17868         return 1;
17869  }
17870 -
17871 +#endif
17872  int f_file_isreg(lua_State *L) {
17873         struct stat st;
17874         int n = lua_gettop(L);
17875 -       
17876 +
17877         if (n != 1) {
17878                 lua_pushstring(L, "file_isreg: expected one argument");
17879                 lua_error(L);
17880         }
17881 -       
17882 +
17883         if (!lua_isstring(L, 1)) {
17884                 lua_pushstring(L, "file_isreg: argument has to be a string");
17885                 lua_error(L);
17886         }
17887 -       
17888 +
17889         if (-1 == stat(lua_tostring(L, 1), &st)) {
17890                 lua_pushnil(L);
17891                 return 1;
17892         }
17893 -       
17894 +
17895         lua_pushnumber(L, S_ISREG(st.st_mode));
17896 -       
17897 +
17898         return 1;
17899  }
17900  
17901  int f_file_isdir(lua_State *L) {
17902         struct stat st;
17903         int n = lua_gettop(L);
17904 -       
17905 +
17906         if (n != 1) {
17907                 lua_pushstring(L, "file_isreg: expected one argument");
17908                 lua_error(L);
17909         }
17910 -       
17911 +
17912         if (!lua_isstring(L, 1)) {
17913                 lua_pushstring(L, "file_isreg: argument has to be a string");
17914                 lua_error(L);
17915         }
17916 -       
17917 +
17918         if (-1 == stat(lua_tostring(L, 1), &st)) {
17919                 lua_pushnil(L);
17920                 return 1;
17921         }
17922 -       
17923 +
17924         lua_pushnumber(L, S_ISDIR(st.st_mode));
17925 -       
17926 +
17927         return 1;
17928  }
17929  
17930 @@ -192,33 +192,33 @@
17931         char *r;
17932         int n = lua_gettop(L);
17933         struct memcache *mc;
17934 -       
17935 +
17936         if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17937                 lua_pushstring(L, "where is my userdata ?");
17938                 lua_error(L);
17939         }
17940 -       
17941 +
17942         mc = lua_touserdata(L, lua_upvalueindex(1));
17943 -       
17944 +
17945         if (n != 1) {
17946                 lua_pushstring(L, "expected one argument");
17947                 lua_error(L);
17948         }
17949 -       
17950 +
17951         if (!lua_isstring(L, 1)) {
17952                 lua_pushstring(L, "argument has to be a string");
17953                 lua_error(L);
17954         }
17955 -       
17956 -       if (NULL == (r = mc_aget(mc, 
17957 +
17958 +       if (NULL == (r = mc_aget(mc,
17959                                  lua_tostring(L, 1), lua_strlen(L, 1)))) {
17960 -                               
17961 +
17962                 lua_pushboolean(L, 0);
17963                 return 1;
17964         }
17965 -       
17966 +
17967         free(r);
17968 -       
17969 +
17970         lua_pushboolean(L, 1);
17971         return 1;
17972  }
17973 @@ -226,74 +226,74 @@
17974  int f_memcache_get_string(lua_State *L) {
17975         char *r;
17976         int n = lua_gettop(L);
17977 -       
17978 +
17979         struct memcache *mc;
17980 -       
17981 +
17982         if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
17983                 lua_pushstring(L, "where is my userdata ?");
17984                 lua_error(L);
17985         }
17986 -       
17987 +
17988         mc = lua_touserdata(L, lua_upvalueindex(1));
17989 -       
17990 -       
17991 +
17992 +
17993         if (n != 1) {
17994                 lua_pushstring(L, "expected one argument");
17995                 lua_error(L);
17996         }
17997 -       
17998 +
17999         if (!lua_isstring(L, 1)) {
18000                 lua_pushstring(L, "argument has to be a string");
18001                 lua_error(L);
18002         }
18003 -       
18004 -       if (NULL == (r = mc_aget(mc, 
18005 +
18006 +       if (NULL == (r = mc_aget(mc,
18007                                  lua_tostring(L, 1), lua_strlen(L, 1)))) {
18008                 lua_pushnil(L);
18009                 return 1;
18010         }
18011 -       
18012 +
18013         lua_pushstring(L, r);
18014 -       
18015 +
18016         free(r);
18017 -       
18018 +
18019         return 1;
18020  }
18021  
18022  int f_memcache_get_long(lua_State *L) {
18023         char *r;
18024         int n = lua_gettop(L);
18025 -       
18026 +
18027         struct memcache *mc;
18028 -       
18029 +
18030         if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
18031                 lua_pushstring(L, "where is my userdata ?");
18032                 lua_error(L);
18033         }
18034 -       
18035 +
18036         mc = lua_touserdata(L, lua_upvalueindex(1));
18037 -       
18038 -       
18039 +
18040 +
18041         if (n != 1) {
18042                 lua_pushstring(L, "expected one argument");
18043                 lua_error(L);
18044         }
18045 -       
18046 +
18047         if (!lua_isstring(L, 1)) {
18048                 lua_pushstring(L, "argument has to be a string");
18049                 lua_error(L);
18050         }
18051 -       
18052 -       if (NULL == (r = mc_aget(mc, 
18053 +
18054 +       if (NULL == (r = mc_aget(mc,
18055                                  lua_tostring(L, 1), lua_strlen(L, 1)))) {
18056                 lua_pushnil(L);
18057                 return 1;
18058         }
18059 -       
18060 +
18061         lua_pushnumber(L, strtol(r, NULL, 10));
18062 -       
18063 +
18064         free(r);
18065 -       
18066 +
18067         return 1;
18068  }
18069  #endif
18070 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_cml_lua.c lighttpd-1.4.12/src/mod_cml_lua.c
18071 --- lighttpd-1.4.11/src/mod_cml_lua.c   2006-01-30 13:56:40.000000000 +0200
18072 +++ lighttpd-1.4.12/src/mod_cml_lua.c   2006-07-11 21:23:40.000000000 +0300
18073 @@ -23,7 +23,7 @@
18074  #ifdef USE_OPENSSL
18075  #define IN const
18076  #else
18077 -#define IN 
18078 +#define IN
18079  #endif
18080  #define OUT
18081  
18082 @@ -31,6 +31,7 @@
18083  
18084  #include <lua.h>
18085  #include <lualib.h>
18086 +#include <lauxlib.h>
18087  
18088  typedef struct {
18089         stream st;
18090 @@ -39,11 +40,11 @@
18091  
18092  static const char * load_file(lua_State *L, void *data, size_t *size) {
18093         readme *rm = data;
18094 -       
18095 +
18096         UNUSED(L);
18097 -       
18098 +
18099         if (rm->done) return 0;
18100 -       
18101 +
18102         *size = rm->st.size;
18103         rm->done = 1;
18104         return rm->st.start;
18105 @@ -51,47 +52,47 @@
18106  
18107  static int lua_to_c_get_string(lua_State *L, const char *varname, buffer *b) {
18108         int curelem;
18109 -       
18110 +
18111         lua_pushstring(L, varname);
18112 -       
18113 +
18114         curelem = lua_gettop(L);
18115         lua_gettable(L, LUA_GLOBALSINDEX);
18116 -       
18117 +
18118         /* it should be a table */
18119         if (!lua_isstring(L, curelem)) {
18120                 lua_settop(L, curelem - 1);
18121 -               
18122 +
18123                 return -1;
18124         }
18125 -       
18126 +
18127         buffer_copy_string(b, lua_tostring(L, curelem));
18128 -       
18129 +
18130         lua_pop(L, 1);
18131 -       
18132 +
18133         assert(curelem - 1 == lua_gettop(L));
18134 -       
18135 +
18136         return 0;
18137  }
18138  
18139  static int lua_to_c_is_table(lua_State *L, const char *varname) {
18140         int curelem;
18141 -       
18142 +
18143         lua_pushstring(L, varname);
18144 -       
18145 +
18146         curelem = lua_gettop(L);
18147         lua_gettable(L, LUA_GLOBALSINDEX);
18148 -       
18149 +
18150         /* it should be a table */
18151         if (!lua_istable(L, curelem)) {
18152                 lua_settop(L, curelem - 1);
18153 -               
18154 +
18155                 return 0;
18156         }
18157 -       
18158 +
18159         lua_settop(L, curelem - 1);
18160 -       
18161 +
18162         assert(curelem - 1 == lua_gettop(L));
18163 -       
18164 +
18165         return 1;
18166  }
18167  
18168 @@ -99,7 +100,7 @@
18169         lua_pushlstring(L, key, key_len);
18170         lua_pushlstring(L, val, val_len);
18171         lua_settable(L, tbl);
18172 -       
18173 +
18174         return 0;
18175  }
18176  
18177 @@ -108,21 +109,21 @@
18178         size_t is_key = 1;
18179         size_t i;
18180         char *key = NULL, *val = NULL;
18181 -       
18182 +
18183         key = qrystr->ptr;
18184 -       
18185 +
18186         /* we need the \0 */
18187         for (i = 0; i < qrystr->used; i++) {
18188                 switch(qrystr->ptr[i]) {
18189                 case '=':
18190                         if (is_key) {
18191                                 val = qrystr->ptr + i + 1;
18192 -                               
18193 +
18194                                 qrystr->ptr[i] = '\0';
18195 -                               
18196 +
18197                                 is_key = 0;
18198                         }
18199 -                       
18200 +
18201                         break;
18202                 case '&':
18203                 case '\0': /* fin symbol */
18204 @@ -131,19 +132,19 @@
18205  
18206                                 /* terminate the value */
18207                                 qrystr->ptr[i] = '\0';
18208 -                               
18209 -                               c_to_lua_push(L, tbl, 
18210 +
18211 +                               c_to_lua_push(L, tbl,
18212                                               key, strlen(key),
18213                                               val, strlen(val));
18214                         }
18215 -                       
18216 +
18217                         key = qrystr->ptr + i + 1;
18218                         val = NULL;
18219                         is_key = 1;
18220                         break;
18221                 }
18222         }
18223 -       
18224 +
18225         return 0;
18226  }
18227  #if 0
18228 @@ -151,21 +152,21 @@
18229         data_unset *d;
18230  
18231         UNUSED(srv);
18232 -       
18233 +
18234         if (NULL != (d = array_get_element(con->request.headers, "Cookie"))) {
18235                 data_string *ds = (data_string *)d;
18236                 size_t key = 0, value = 0;
18237                 size_t is_key = 1, is_sid = 0;
18238                 size_t i;
18239 -               
18240 +
18241                 /* found COOKIE */
18242                 if (!DATA_IS_STRING(d)) return -1;
18243                 if (ds->value->used == 0) return -1;
18244 -                       
18245 +
18246                 if (ds->value->ptr[0] == '\0' ||
18247                     ds->value->ptr[0] == '=' ||
18248                     ds->value->ptr[0] == ';') return -1;
18249 -               
18250 +
18251                 buffer_reset(p->session_id);
18252                 for (i = 0; i < ds->value->used; i++) {
18253                         switch(ds->value->ptr[i]) {
18254 @@ -176,16 +177,16 @@
18255                                                 is_sid = 1;
18256                                         }
18257                                         value = i + 1;
18258 -                               
18259 +
18260                                         is_key = 0;
18261                                 }
18262 -                               
18263 +
18264                                 break;
18265                         case ';':
18266                                 if (is_sid) {
18267                                         buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);
18268                                 }
18269 -                               
18270 +
18271                                 is_sid = 0;
18272                                 key = i + 1;
18273                                 value = 0;
18274 @@ -204,48 +205,43 @@
18275                         }
18276                 }
18277         }
18278 -       
18279 +
18280         return 0;
18281  }
18282  #endif
18283  
18284  int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) {
18285 -       lua_State *L; 
18286 +       lua_State *L;
18287         readme rm;
18288         int ret = -1;
18289         buffer *b = buffer_init();
18290         int header_tbl = 0;
18291 -       
18292 +
18293         rm.done = 0;
18294         stream_open(&rm.st, fn);
18295 -       
18296 +
18297         /* push the lua file to the interpreter and see what happends */
18298 -       L = lua_open();
18299 -       
18300 -       luaopen_base(L);
18301 -       luaopen_table(L);
18302 -       luaopen_string(L);
18303 -       luaopen_math(L);
18304 -       luaopen_io(L);
18305 -       
18306 +       L = luaL_newstate();
18307 +       luaL_openlibs(L);
18308 +
18309         /* register functions */
18310         lua_register(L, "md5", f_crypto_md5);
18311         lua_register(L, "file_mtime", f_file_mtime);
18312         lua_register(L, "file_isreg", f_file_isreg);
18313         lua_register(L, "file_isdir", f_file_isreg);
18314         lua_register(L, "dir_files", f_dir_files);
18315 -       
18316 +
18317  #ifdef HAVE_MEMCACHE_H
18318         lua_pushliteral(L, "memcache_get_long");
18319         lua_pushlightuserdata(L, p->conf.mc);
18320         lua_pushcclosure(L, f_memcache_get_long, 1);
18321         lua_settable(L, LUA_GLOBALSINDEX);
18322 -       
18323 +
18324         lua_pushliteral(L, "memcache_get_string");
18325         lua_pushlightuserdata(L, p->conf.mc);
18326         lua_pushcclosure(L, f_memcache_get_string, 1);
18327         lua_settable(L, LUA_GLOBALSINDEX);
18328 -       
18329 +
18330         lua_pushliteral(L, "memcache_exists");
18331         lua_pushlightuserdata(L, p->conf.mc);
18332         lua_pushcclosure(L, f_memcache_exists, 1);
18333 @@ -255,11 +251,11 @@
18334         lua_pushliteral(L, "request");
18335         lua_newtable(L);
18336         lua_settable(L, LUA_GLOBALSINDEX);
18337 -       
18338 +
18339         lua_pushliteral(L, "request");
18340         header_tbl = lua_gettop(L);
18341         lua_gettable(L, LUA_GLOBALSINDEX);
18342 -       
18343 +
18344         c_to_lua_push(L, header_tbl, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
18345         c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
18346         c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
18347 @@ -267,84 +263,84 @@
18348         if (!buffer_is_empty(con->request.pathinfo)) {
18349                 c_to_lua_push(L, header_tbl, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
18350         }
18351 -       
18352 +
18353         c_to_lua_push(L, header_tbl, CONST_STR_LEN("CWD"), CONST_BUF_LEN(p->basedir));
18354         c_to_lua_push(L, header_tbl, CONST_STR_LEN("BASEURL"), CONST_BUF_LEN(p->baseurl));
18355 -       
18356 +
18357         /* register GET parameter */
18358         lua_pushliteral(L, "get");
18359         lua_newtable(L);
18360         lua_settable(L, LUA_GLOBALSINDEX);
18361 -       
18362 +
18363         lua_pushliteral(L, "get");
18364         header_tbl = lua_gettop(L);
18365         lua_gettable(L, LUA_GLOBALSINDEX);
18366 -       
18367 +
18368         buffer_copy_string_buffer(b, con->uri.query);
18369         cache_export_get_params(L, header_tbl, b);
18370         buffer_reset(b);
18371  
18372 -       /* 2 default constants */       
18373 +       /* 2 default constants */
18374         lua_pushliteral(L, "CACHE_HIT");
18375         lua_pushboolean(L, 0);
18376         lua_settable(L, LUA_GLOBALSINDEX);
18377 -       
18378 +
18379         lua_pushliteral(L, "CACHE_MISS");
18380         lua_pushboolean(L, 1);
18381         lua_settable(L, LUA_GLOBALSINDEX);
18382 -       
18383 +
18384         /* load lua program */
18385         if (lua_load(L, load_file, &rm, fn->ptr) || lua_pcall(L,0,1,0)) {
18386                 log_error_write(srv, __FILE__, __LINE__, "s",
18387                                 lua_tostring(L,-1));
18388 -               
18389 +
18390                 goto error;
18391         }
18392 -       
18393 +
18394         /* get return value */
18395         ret = (int)lua_tonumber(L, -1);
18396         lua_pop(L, 1);
18397 -       
18398 -       /* fetch the data from lua */ 
18399 +
18400 +       /* fetch the data from lua */
18401         lua_to_c_get_string(L, "trigger_handler", p->trigger_handler);
18402 -       
18403 +
18404         if (0 == lua_to_c_get_string(L, "output_contenttype", b)) {
18405                 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(b));
18406         }
18407 -       
18408 +
18409         if (ret == 0) {
18410                 /* up to now it is a cache-hit, check if all files exist */
18411 -               
18412 +
18413                 int curelem;
18414                 time_t mtime = 0;
18415 -       
18416 +
18417                 if (!lua_to_c_is_table(L, "output_include")) {
18418                         log_error_write(srv, __FILE__, __LINE__, "s",
18419                                 "output_include is missing or not a table");
18420                         ret = -1;
18421 -               
18422 +
18423                         goto error;
18424                 }
18425 -               
18426 +
18427                 lua_pushstring(L, "output_include");
18428 -               
18429 +
18430                 curelem = lua_gettop(L);
18431                 lua_gettable(L, LUA_GLOBALSINDEX);
18432  
18433                 /* HOW-TO build a etag ?
18434 -                * as we don't just have one file we have to take the stat() 
18435 +                * as we don't just have one file we have to take the stat()
18436                  * from all base files, merge them and build the etag from
18437                  * it later.
18438 -                * 
18439 +                *
18440                  * The mtime of the content is the mtime of the freshest base file
18441 -                * 
18442 +                *
18443                  * */
18444 -               
18445 +
18446                 lua_pushnil(L);  /* first key */
18447                 while (lua_next(L, curelem) != 0) {
18448                         stat_cache_entry *sce = NULL;
18449                         /* key' is at index -2 and value' at index -1 */
18450 -                       
18451 +
18452                         if (lua_isstring(L, -1)) {
18453                                 const char *s = lua_tostring(L, -1);
18454  
18455 @@ -364,18 +360,18 @@
18456                                                 /* a file is missing, call the handler to generate it */
18457                                                 if (!buffer_is_empty(p->trigger_handler)) {
18458                                                         ret = 1; /* cache-miss */
18459 -                                                       
18460 +
18461                                                         log_error_write(srv, __FILE__, __LINE__, "s",
18462                                                                         "a file is missing, calling handler");
18463 -                                                       
18464 +
18465                                                         break;
18466                                                 } else {
18467                                                         /* handler not set -> 500 */
18468                                                         ret = -1;
18469 -                                                       
18470 +
18471                                                         log_error_write(srv, __FILE__, __LINE__, "s",
18472                                                                         "a file missing and no handler set");
18473 -                                                       
18474 +
18475                                                         break;
18476                                                 }
18477                                                 break;
18478 @@ -393,12 +389,12 @@
18479                                                 "not a string");
18480                                 break;
18481                         }
18482 -               
18483 +
18484                         lua_pop(L, 1);  /* removes value'; keeps key' for next iteration */
18485                 }
18486 -               
18487 +
18488                 lua_settop(L, curelem - 1);
18489 -               
18490 +
18491                 if (ret == 0) {
18492                         data_string *ds;
18493                         char timebuf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
18494 @@ -410,9 +406,9 @@
18495  
18496                         /* no Last-Modified specified */
18497                         if ((mtime) && (NULL == ds)) {
18498 -               
18499 +
18500                                 strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&mtime));
18501 -                               
18502 +
18503                                 response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), timebuf, sizeof(timebuf) - 1);
18504  
18505  
18506 @@ -428,9 +424,9 @@
18507                                 tbuf.used = 0;
18508                                 tbuf.ptr = NULL;
18509                         }
18510 -                       
18511 +
18512                         if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, &tbuf)) {
18513 -                               /* ok, the client already has our content, 
18514 +                               /* ok, the client already has our content,
18515                                  * no need to send it again */
18516  
18517                                 chunkqueue_reset(con->write_queue);
18518 @@ -440,24 +436,24 @@
18519                         chunkqueue_reset(con->write_queue);
18520                 }
18521         }
18522 -       
18523 +
18524         if (ret == 1 && !buffer_is_empty(p->trigger_handler)) {
18525                 /* cache-miss */
18526                 buffer_copy_string_buffer(con->uri.path, p->baseurl);
18527                 buffer_append_string_buffer(con->uri.path, p->trigger_handler);
18528 -       
18529 +
18530                 buffer_copy_string_buffer(con->physical.path, p->basedir);
18531                 buffer_append_string_buffer(con->physical.path, p->trigger_handler);
18532 -               
18533 +
18534                 chunkqueue_reset(con->write_queue);
18535         }
18536 -       
18537 +
18538  error:
18539         lua_close(L);
18540 -       
18541 +
18542         stream_close(&rm.st);
18543         buffer_free(b);
18544 -       
18545 +
18546         return ret /* cache-error */;
18547  }
18548  #else
18549 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_compress.c lighttpd-1.4.12/src/mod_compress.c
18550 --- lighttpd-1.4.11/src/mod_compress.c  2005-11-18 13:49:14.000000000 +0200
18551 +++ lighttpd-1.4.12/src/mod_compress.c  2006-07-11 21:23:40.000000000 +0300
18552 @@ -2,7 +2,6 @@
18553  #include <sys/stat.h>
18554  
18555  #include <fcntl.h>
18556 -#include <unistd.h>
18557  #include <ctype.h>
18558  #include <stdlib.h>
18559  #include <string.h>
18560 @@ -14,6 +13,7 @@
18561  #include "buffer.h"
18562  #include "response.h"
18563  #include "stat_cache.h"
18564 +#include "http_chunk.h"
18565  
18566  #include "plugin.h"
18567  
18568 @@ -33,6 +33,7 @@
18569  #endif
18570  
18571  #include "sys-mmap.h"
18572 +#include "sys-files.h"
18573  
18574  /* request: accept-encoding */
18575  #define HTTP_ACCEPT_ENCODING_IDENTITY BV(0)
18576 @@ -55,97 +56,127 @@
18577         PLUGIN_DATA;
18578         buffer *ofn;
18579         buffer *b;
18580 -       
18581 +
18582         plugin_config **config_storage;
18583 -       plugin_config conf; 
18584 +       plugin_config conf;
18585  } plugin_data;
18586  
18587  INIT_FUNC(mod_compress_init) {
18588         plugin_data *p;
18589 -       
18590 +
18591         p = calloc(1, sizeof(*p));
18592 -       
18593 +
18594         p->ofn = buffer_init();
18595         p->b = buffer_init();
18596 -       
18597 +
18598         return p;
18599  }
18600  
18601  FREE_FUNC(mod_compress_free) {
18602         plugin_data *p = p_d;
18603 -       
18604 +
18605         UNUSED(srv);
18606  
18607         if (!p) return HANDLER_GO_ON;
18608 -       
18609 +
18610         buffer_free(p->ofn);
18611         buffer_free(p->b);
18612 -       
18613 +
18614         if (p->config_storage) {
18615                 size_t i;
18616                 for (i = 0; i < srv->config_context->used; i++) {
18617                         plugin_config *s = p->config_storage[i];
18618  
18619                         if (!s) continue;
18620 -                       
18621 +
18622                         array_free(s->compress);
18623                         buffer_free(s->compress_cache_dir);
18624 -                       
18625 +
18626                         free(s);
18627                 }
18628                 free(p->config_storage);
18629         }
18630 -       
18631 -       
18632 +
18633 +
18634         free(p);
18635 -       
18636 +
18637         return HANDLER_GO_ON;
18638  }
18639  
18640 +void mkdir_recursive(const char *dir) {
18641 +
18642 +       char dir_copy[256];
18643 +       char *p = dir_copy;
18644 +
18645 +       if (!dir || !dir[0])
18646 +               return;
18647 +
18648 +       strncpy(dir_copy, dir, sizeof(dir_copy) / sizeof(dir_copy[0]));
18649 +
18650 +       while ((p = strchr(p + 1, '/')) != NULL) {
18651 +
18652 +               *p = '\0';
18653 +               if ((mkdir(dir_copy, 0700) != 0) && (errno != EEXIST))
18654 +                       return;
18655 +
18656 +               *p++ = '/';
18657 +       }
18658 +
18659 +       mkdir(dir, 0700);
18660 +}
18661 +
18662  SETDEFAULTS_FUNC(mod_compress_setdefaults) {
18663         plugin_data *p = p_d;
18664         size_t i = 0;
18665 -       
18666 -       config_values_t cv[] = { 
18667 +
18668 +       config_values_t cv[] = {
18669                 { "compress.cache-dir",             NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
18670                 { "compress.filetype",              NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
18671                 { "compress.max-filesize",          NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
18672                 { NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
18673         };
18674 -       
18675 +
18676         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
18677 -       
18678 +
18679         for (i = 0; i < srv->config_context->used; i++) {
18680                 plugin_config *s;
18681 -               
18682 +
18683                 s = calloc(1, sizeof(plugin_config));
18684                 s->compress_cache_dir = buffer_init();
18685                 s->compress = array_init();
18686                 s->compress_max_filesize = 0;
18687 -               
18688 +
18689                 cv[0].destination = s->compress_cache_dir;
18690                 cv[1].destination = s->compress;
18691                 cv[2].destination = &(s->compress_max_filesize);
18692 -               
18693 +
18694                 p->config_storage[i] = s;
18695 -       
18696 +
18697                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
18698                         return HANDLER_ERROR;
18699                 }
18700 -               
18701 +
18702                 if (!buffer_is_empty(s->compress_cache_dir)) {
18703                         struct stat st;
18704                         if (0 != stat(s->compress_cache_dir->ptr, &st)) {
18705 -                               log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir", 
18706 +
18707 +                               log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, attempting to create",
18708                                                 s->compress_cache_dir, strerror(errno));
18709 -                               
18710 -                               return HANDLER_ERROR;
18711 +                               mkdir_recursive(s->compress_cache_dir->ptr);
18712 +
18713 +                               if (0 != stat(s->compress_cache_dir->ptr, &st)) {
18714 +
18715 +                                       log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, create failed",
18716 +                                                                       s->compress_cache_dir, strerror(errno));
18717 +
18718 +                                       return HANDLER_ERROR;
18719 +                               }
18720                         }
18721                 }
18722         }
18723 -       
18724 +
18725         return HANDLER_GO_ON;
18726 -       
18727 +
18728  }
18729  
18730  #ifdef USE_ZLIB
18731 @@ -153,32 +184,32 @@
18732         unsigned char *c;
18733         unsigned long crc;
18734         z_stream z;
18735 -       
18736 +
18737         UNUSED(srv);
18738         UNUSED(con);
18739  
18740         z.zalloc = Z_NULL;
18741         z.zfree = Z_NULL;
18742         z.opaque = Z_NULL;
18743 -       
18744 -       if (Z_OK != deflateInit2(&z, 
18745 +
18746 +       if (Z_OK != deflateInit2(&z,
18747                                  Z_DEFAULT_COMPRESSION,
18748 -                                Z_DEFLATED, 
18749 +                                Z_DEFLATED,
18750                                  -MAX_WBITS,  /* supress zlib-header */
18751                                  8,
18752                                  Z_DEFAULT_STRATEGY)) {
18753                 return -1;
18754         }
18755 -               
18756 +
18757         z.next_in = (unsigned char *)start;
18758         z.avail_in = st_size;
18759         z.total_in = 0;
18760 -               
18761 -                       
18762 +
18763 +
18764         buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12 + 18);
18765 -               
18766 +
18767         /* write gzip header */
18768 -               
18769 +
18770         c = (unsigned char *)p->b->ptr;
18771         c[0] = 0x1f;
18772         c[1] = 0x8b;
18773 @@ -190,24 +221,24 @@
18774         c[7] = (mtime >> 24) & 0xff;
18775         c[8] = 0x00; /* extra flags */
18776         c[9] = 0x03; /* UNIX */
18777 -       
18778 +
18779         p->b->used = 10;
18780         z.next_out = (unsigned char *)p->b->ptr + p->b->used;
18781         z.avail_out = p->b->size - p->b->used - 8;
18782         z.total_out = 0;
18783 -       
18784 +
18785         if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
18786                 deflateEnd(&z);
18787                 return -1;
18788         }
18789 -       
18790 +
18791         /* trailer */
18792         p->b->used += z.total_out;
18793 -       
18794 +
18795         crc = generate_crc32c(start, st_size);
18796 -               
18797 +
18798         c = (unsigned char *)p->b->ptr + p->b->used;
18799 -               
18800 +
18801         c[0] = (crc >>  0) & 0xff;
18802         c[1] = (crc >>  8) & 0xff;
18803         c[2] = (crc >> 16) & 0xff;
18804 @@ -221,51 +252,51 @@
18805         if (Z_OK != deflateEnd(&z)) {
18806                 return -1;
18807         }
18808 -       
18809 +
18810         return 0;
18811  }
18812  
18813  static int deflate_file_to_buffer_deflate(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
18814         z_stream z;
18815 -       
18816 +
18817         UNUSED(srv);
18818         UNUSED(con);
18819  
18820         z.zalloc = Z_NULL;
18821         z.zfree = Z_NULL;
18822         z.opaque = Z_NULL;
18823 -       
18824 -       if (Z_OK != deflateInit2(&z, 
18825 +
18826 +       if (Z_OK != deflateInit2(&z,
18827                                  Z_DEFAULT_COMPRESSION,
18828 -                                Z_DEFLATED, 
18829 +                                Z_DEFLATED,
18830                                  -MAX_WBITS,  /* supress zlib-header */
18831                                  8,
18832                                  Z_DEFAULT_STRATEGY)) {
18833                 return -1;
18834         }
18835 -               
18836 +
18837         z.next_in = start;
18838         z.avail_in = st_size;
18839         z.total_in = 0;
18840 -               
18841 +
18842         buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12);
18843 -       
18844 +
18845         z.next_out = (unsigned char *)p->b->ptr;
18846         z.avail_out = p->b->size;
18847         z.total_out = 0;
18848 -       
18849 +
18850         if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
18851                 deflateEnd(&z);
18852                 return -1;
18853         }
18854 -       
18855 +
18856         /* trailer */
18857         p->b->used += z.total_out;
18858 -       
18859 +
18860         if (Z_OK != deflateEnd(&z)) {
18861                 return -1;
18862         }
18863 -       
18864 +
18865         return 0;
18866  }
18867  
18868 @@ -274,48 +305,48 @@
18869  #ifdef USE_BZ2LIB
18870  static int deflate_file_to_buffer_bzip2(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
18871         bz_stream bz;
18872 -       
18873 +
18874         UNUSED(srv);
18875         UNUSED(con);
18876  
18877         bz.bzalloc = NULL;
18878         bz.bzfree = NULL;
18879         bz.opaque = NULL;
18880 -       
18881 -       if (BZ_OK != BZ2_bzCompressInit(&bz, 
18882 +
18883 +       if (BZ_OK != BZ2_bzCompressInit(&bz,
18884                                         9, /* blocksize = 900k */
18885                                         0, /* no output */
18886                                         0)) { /* workFactor: default */
18887                 return -1;
18888         }
18889 -               
18890 +
18891         bz.next_in = (char *)start;
18892         bz.avail_in = st_size;
18893         bz.total_in_lo32 = 0;
18894         bz.total_in_hi32 = 0;
18895 -               
18896 +
18897         buffer_prepare_copy(p->b, (bz.avail_in * 1.1) + 12);
18898 -       
18899 +
18900         bz.next_out = p->b->ptr;
18901         bz.avail_out = p->b->size;
18902         bz.total_out_lo32 = 0;
18903         bz.total_out_hi32 = 0;
18904 -       
18905 +
18906         if (BZ_STREAM_END != BZ2_bzCompress(&bz, BZ_FINISH)) {
18907                 BZ2_bzCompressEnd(&bz);
18908                 return -1;
18909         }
18910 -       
18911 +
18912         /* file is too large for now */
18913         if (bz.total_out_hi32) return -1;
18914 -       
18915 +
18916         /* trailer */
18917         p->b->used = bz.total_out_lo32;
18918 -       
18919 +
18920         if (BZ_OK != BZ2_bzCompressEnd(&bz)) {
18921                 return -1;
18922         }
18923 -       
18924 +
18925         return 0;
18926  }
18927  #endif
18928 @@ -326,47 +357,50 @@
18929         void *start;
18930         const char *filename = fn->ptr;
18931         ssize_t r;
18932 -       
18933 +       stat_cache_entry *compressed_sce = NULL;
18934 +
18935 +       if (buffer_is_empty(p->conf.compress_cache_dir)) return -1;
18936 +
18937         /* overflow */
18938         if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
18939 -       
18940 -       /* don't mmap files > 128Mb 
18941 -        * 
18942 +
18943 +       /* don't mmap files > 128Mb
18944 +        *
18945          * we could use a sliding window, but currently there is no need for it
18946          */
18947 -       
18948 +
18949         if (sce->st.st_size > 128 * 1024 * 1024) return -1;
18950 -       
18951 +
18952         buffer_reset(p->ofn);
18953         buffer_copy_string_buffer(p->ofn, p->conf.compress_cache_dir);
18954 -       BUFFER_APPEND_SLASH(p->ofn);
18955 -       
18956 +       PATHNAME_APPEND_SLASH(p->ofn);
18957 +
18958         if (0 == strncmp(con->physical.path->ptr, con->physical.doc_root->ptr, con->physical.doc_root->used-1)) {
18959                 size_t offset = p->ofn->used - 1;
18960                 char *dir, *nextdir;
18961 -               
18962 +
18963                 buffer_append_string(p->ofn, con->physical.path->ptr + con->physical.doc_root->used - 1);
18964 -               
18965 +
18966                 buffer_copy_string_buffer(p->b, p->ofn);
18967 -               
18968 +
18969                 /* mkdir -p ... */
18970                 for (dir = p->b->ptr + offset; NULL != (nextdir = strchr(dir, '/')); dir = nextdir + 1) {
18971                         *nextdir = '\0';
18972 -                       
18973 +
18974                         if (-1 == mkdir(p->b->ptr, 0700)) {
18975                                 if (errno != EEXIST) {
18976                                         log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cache-directory", p->b, "failed", strerror(errno));
18977 -                                       
18978 +
18979                                         return -1;
18980                                 }
18981                         }
18982 -                       
18983 +
18984                         *nextdir = '/';
18985                 }
18986         } else {
18987                 buffer_append_string_buffer(p->ofn, con->uri.path);
18988         }
18989 -       
18990 +
18991         switch(type) {
18992         case HTTP_ACCEPT_ENCODING_GZIP:
18993                 buffer_append_string(p->ofn, "-gzip-");
18994 @@ -381,55 +415,64 @@
18995                 log_error_write(srv, __FILE__, __LINE__, "sd", "unknown compression type", type);
18996                 return -1;
18997         }
18998 -       
18999 +
19000         buffer_append_string_buffer(p->ofn, sce->etag);
19001 -       
19002 +
19003 +
19004 +       if (HANDLER_ERROR != stat_cache_get_entry(srv, con, p->ofn, &compressed_sce)) {
19005 +               /* file exists */
19006 +
19007 +               http_chunk_append_file(srv, con, p->ofn, 0, compressed_sce->st.st_size);
19008 +               con->file_finished = 1;
19009 +
19010 +               return 0;
19011 +       }
19012 +
19013         if (-1 == (ofd = open(p->ofn->ptr, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600))) {
19014                 if (errno == EEXIST) {
19015                         /* cache-entry exists */
19016 -#if 0
19017 -                       log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache hit");
19018 -#endif
19019 -                       buffer_copy_string_buffer(con->physical.path, p->ofn);
19020 -                       
19021 -                       return 0;
19022 +
19023                 }
19024 -               
19025 -               log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cachefile", p->ofn, "failed", strerror(errno));
19026 -               
19027 +
19028 +               log_error_write(srv, __FILE__, __LINE__, "sbss",
19029 +                               "creating cachefile", p->ofn,
19030 +                               "failed", strerror(errno));
19031 +
19032                 return -1;
19033         }
19034 -#if 0
19035 -       log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache miss");
19036 -#endif 
19037 +
19038         if (-1 == (ifd = open(filename, O_RDONLY | O_BINARY))) {
19039 -               log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
19040 -               
19041 +               log_error_write(srv, __FILE__, __LINE__, "sbss",
19042 +                               "opening plain-file", fn,
19043 +                               "failed", strerror(errno));
19044 +
19045                 close(ofd);
19046 -               
19047 +
19048                 return -1;
19049         }
19050 -       
19051 -       
19052 +
19053 +
19054         if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
19055 -               log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
19056 -               
19057 +               log_error_write(srv, __FILE__, __LINE__, "sbss",
19058 +                               "mmaping", fn,
19059 +                               "failed", strerror(errno));
19060 +
19061                 close(ofd);
19062                 close(ifd);
19063                 return -1;
19064         }
19065 -       
19066 +
19067         switch(type) {
19068  #ifdef USE_ZLIB
19069 -       case HTTP_ACCEPT_ENCODING_GZIP: 
19070 +       case HTTP_ACCEPT_ENCODING_GZIP:
19071                 ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
19072                 break;
19073 -       case HTTP_ACCEPT_ENCODING_DEFLATE: 
19074 +       case HTTP_ACCEPT_ENCODING_DEFLATE:
19075                 ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
19076                 break;
19077  #endif
19078  #ifdef USE_BZ2LIB
19079 -       case HTTP_ACCEPT_ENCODING_BZIP2: 
19080 +       case HTTP_ACCEPT_ENCODING_BZIP2:
19081                 ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
19082                 break;
19083  #endif
19084 @@ -437,26 +480,27 @@
19085                 ret = -1;
19086                 break;
19087         }
19088 -       
19089 +
19090         if (-1 == (r = write(ofd, p->b->ptr, p->b->used))) {
19091 -               munmap(start, sce->st.st_size); 
19092 +               munmap(start, sce->st.st_size);
19093                 close(ofd);
19094                 close(ifd);
19095                 return -1;
19096         }
19097 -       
19098 +
19099         if ((size_t)r != p->b->used) {
19100 -               
19101 +
19102         }
19103 -               
19104 +
19105         munmap(start, sce->st.st_size);
19106         close(ofd);
19107         close(ifd);
19108 -       
19109 +
19110         if (ret != 0) return -1;
19111 -       
19112 -       buffer_copy_string_buffer(con->physical.path, p->ofn);
19113 -       
19114 +
19115 +       http_chunk_append_file(srv, con, p->ofn, 0, r);
19116 +       con->file_finished = 1;
19117 +
19118         return 0;
19119  }
19120  
19121 @@ -465,43 +509,44 @@
19122         int ret = -1;
19123         void *start;
19124         buffer *b;
19125 -       
19126 +
19127         /* overflow */
19128         if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
19129 -       
19130 +
19131         /* don't mmap files > 128M
19132 -        * 
19133 +        *
19134          * we could use a sliding window, but currently there is no need for it
19135          */
19136 -       
19137 +
19138         if (sce->st.st_size > 128 * 1024 * 1024) return -1;
19139 -       
19140 -       
19141 +
19142         if (-1 == (ifd = open(fn->ptr, O_RDONLY | O_BINARY))) {
19143                 log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
19144 -               
19145 +
19146                 return -1;
19147         }
19148 -       
19149 -       
19150 -       if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
19151 +
19152 +       start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0);
19153 +
19154 +       close(ifd);
19155 +
19156 +       if (MAP_FAILED == start) {
19157                 log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
19158 -               
19159 -               close(ifd);
19160 +
19161                 return -1;
19162         }
19163 -       
19164 +
19165         switch(type) {
19166  #ifdef USE_ZLIB
19167 -       case HTTP_ACCEPT_ENCODING_GZIP: 
19168 +       case HTTP_ACCEPT_ENCODING_GZIP:
19169                 ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
19170                 break;
19171 -       case HTTP_ACCEPT_ENCODING_DEFLATE: 
19172 +       case HTTP_ACCEPT_ENCODING_DEFLATE:
19173                 ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
19174                 break;
19175  #endif
19176  #ifdef USE_BZ2LIB
19177 -       case HTTP_ACCEPT_ENCODING_BZIP2: 
19178 +       case HTTP_ACCEPT_ENCODING_BZIP2:
19179                 ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
19180                 break;
19181  #endif
19182 @@ -509,69 +554,64 @@
19183                 ret = -1;
19184                 break;
19185         }
19186 -               
19187 +
19188         munmap(start, sce->st.st_size);
19189 -       close(ifd);
19190 -       
19191 +
19192         if (ret != 0) return -1;
19193 -       
19194 +
19195         chunkqueue_reset(con->write_queue);
19196         b = chunkqueue_get_append_buffer(con->write_queue);
19197         buffer_copy_memory(b, p->b->ptr, p->b->used + 1);
19198 -       
19199 +
19200         buffer_reset(con->physical.path);
19201 -       
19202 +
19203         con->file_finished = 1;
19204         con->file_started  = 1;
19205 -       
19206 +
19207         return 0;
19208  }
19209  
19210 -
19211 -#define PATCH(x) \
19212 -       p->conf.x = s->x;
19213  static int mod_compress_patch_connection(server *srv, connection *con, plugin_data *p) {
19214         size_t i, j;
19215         plugin_config *s = p->config_storage[0];
19216  
19217 -       PATCH(compress_cache_dir);
19218 -       PATCH(compress);
19219 -       PATCH(compress_max_filesize);
19220 -       
19221 +       PATCH_OPTION(compress_cache_dir);
19222 +       PATCH_OPTION(compress);
19223 +       PATCH_OPTION(compress_max_filesize);
19224 +
19225         /* skip the first, the global context */
19226         for (i = 1; i < srv->config_context->used; i++) {
19227                 data_config *dc = (data_config *)srv->config_context->data[i];
19228                 s = p->config_storage[i];
19229 -               
19230 +
19231                 /* condition didn't match */
19232                 if (!config_check_cond(srv, con, dc)) continue;
19233 -               
19234 +
19235                 /* merge config */
19236                 for (j = 0; j < dc->value->used; j++) {
19237                         data_unset *du = dc->value->data[j];
19238 -                       
19239 +
19240                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.cache-dir"))) {
19241 -                               PATCH(compress_cache_dir);
19242 +                               PATCH_OPTION(compress_cache_dir);
19243                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.filetype"))) {
19244 -                               PATCH(compress);
19245 +                               PATCH_OPTION(compress);
19246                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.max-filesize"))) {
19247 -                               PATCH(compress_max_filesize);
19248 +                               PATCH_OPTION(compress_max_filesize);
19249                         }
19250                 }
19251         }
19252 -       
19253 +
19254         return 0;
19255  }
19256 -#undef PATCH
19257  
19258  PHYSICALPATH_FUNC(mod_compress_physical) {
19259         plugin_data *p = p_d;
19260         size_t m;
19261         off_t max_fsize;
19262         stat_cache_entry *sce = NULL;
19263 -       
19264 +
19265         /* only GET and POST can get compressed */
19266 -       if (con->request.http_method != HTTP_METHOD_GET && 
19267 +       if (con->request.http_method != HTTP_METHOD_GET &&
19268             con->request.http_method != HTTP_METHOD_POST) {
19269                 return HANDLER_GO_ON;
19270         }
19271 @@ -579,46 +619,49 @@
19272         if (buffer_is_empty(con->physical.path)) {
19273                 return HANDLER_GO_ON;
19274         }
19275 -       
19276 +
19277         mod_compress_patch_connection(srv, con, p);
19278 -       
19279 +
19280         max_fsize = p->conf.compress_max_filesize;
19281  
19282         stat_cache_get_entry(srv, con, con->physical.path, &sce);
19283  
19284         /* don't compress files that are too large as we need to much time to handle them */
19285         if (max_fsize && (sce->st.st_size >> 10) > max_fsize) return HANDLER_GO_ON;
19286 -               
19287 +
19288 +       /* compressing the file might lead to larger files instead */
19289 +       if (sce->st.st_size < 128) return HANDLER_GO_ON;
19290 +
19291         /* check if mimetype is in compress-config */
19292         for (m = 0; m < p->conf.compress->used; m++) {
19293                 data_string *compress_ds = (data_string *)p->conf.compress->data[m];
19294 -                       
19295 +
19296                 if (!compress_ds) {
19297                         log_error_write(srv, __FILE__, __LINE__, "sbb", "evil", con->physical.path, con->uri.path);
19298 -                       
19299 +
19300                         return HANDLER_GO_ON;
19301                 }
19302 -               
19303 +
19304                 if (buffer_is_equal(compress_ds->value, sce->content_type)) {
19305                         /* mimetype found */
19306                         data_string *ds;
19307 -                               
19308 +
19309                         /* the response might change according to Accept-Encoding */
19310                         response_header_insert(srv, con, CONST_STR_LEN("Vary"), CONST_STR_LEN("Accept-Encoding"));
19311 -                               
19312 +
19313                         if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Accept-Encoding"))) {
19314                                 int accept_encoding = 0;
19315                                 char *value = ds->value->ptr;
19316                                 int srv_encodings = 0;
19317                                 int matched_encodings = 0;
19318 -                               
19319 +
19320                                 /* get client side support encodings */
19321                                 if (NULL != strstr(value, "gzip")) accept_encoding |= HTTP_ACCEPT_ENCODING_GZIP;
19322                                 if (NULL != strstr(value, "deflate")) accept_encoding |= HTTP_ACCEPT_ENCODING_DEFLATE;
19323                                 if (NULL != strstr(value, "compress")) accept_encoding |= HTTP_ACCEPT_ENCODING_COMPRESS;
19324                                 if (NULL != strstr(value, "bzip2")) accept_encoding |= HTTP_ACCEPT_ENCODING_BZIP2;
19325                                 if (NULL != strstr(value, "identity")) accept_encoding |= HTTP_ACCEPT_ENCODING_IDENTITY;
19326 -                               
19327 +
19328                                 /* get server side supported ones */
19329  #ifdef USE_BZ2LIB
19330                                 srv_encodings |= HTTP_ACCEPT_ENCODING_BZIP2;
19331 @@ -627,18 +670,31 @@
19332                                 srv_encodings |= HTTP_ACCEPT_ENCODING_GZIP;
19333                                 srv_encodings |= HTTP_ACCEPT_ENCODING_DEFLATE;
19334  #endif
19335 -                               
19336 +
19337                                 /* find matching entries */
19338                                 matched_encodings = accept_encoding & srv_encodings;
19339 -                               
19340 +
19341                                 if (matched_encodings) {
19342                                         const char *dflt_gzip = "gzip";
19343                                         const char *dflt_deflate = "deflate";
19344                                         const char *dflt_bzip2 = "bzip2";
19345 -                                       
19346 +
19347                                         const char *compression_name = NULL;
19348                                         int compression_type = 0;
19349 -                                       
19350 +                                       buffer *mtime;
19351 +
19352 +                                       mtime = strftime_cache_get(srv, sce->st.st_mtime);
19353 +                                       etag_mutate(con->physical.etag, sce->etag);
19354 +
19355 +                                       response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
19356 +                                       response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
19357 +
19358 +                                       /* perhaps we don't even have to compress the file as the browser still has the
19359 +                                        * current version */
19360 +                                       if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
19361 +                                               return HANDLER_FINISHED;
19362 +                                       }
19363 +
19364                                         /* select best matching encoding */
19365                                         if (matched_encodings & HTTP_ACCEPT_ENCODING_BZIP2) {
19366                                                 compression_type = HTTP_ACCEPT_ENCODING_BZIP2;
19367 @@ -650,31 +706,21 @@
19368                                                 compression_type = HTTP_ACCEPT_ENCODING_DEFLATE;
19369                                                 compression_name = dflt_deflate;
19370                                         }
19371 -                                       
19372 -                                       /* deflate it */
19373 -                                       if (p->conf.compress_cache_dir->used) {
19374 -                                               if (0 == deflate_file_to_file(srv, con, p,
19375 -                                                                             con->physical.path, sce, compression_type)) {
19376 -                                                       buffer *mtime;
19377 -                                                       
19378 -                                                       response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
19379 -                                                       
19380 -                                                       mtime = strftime_cache_get(srv, sce->st.st_mtime);
19381 -                                                       response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
19382 -
19383 -                                                       etag_mutate(con->physical.etag, sce->etag);
19384 -                                                       response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
19385 -
19386 -                                                       response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
19387 -
19388 -                                                       return HANDLER_GO_ON;
19389 -                                               }
19390 -                                       } else if (0 == deflate_file_to_buffer(srv, con, p,
19391 -                                                                              con->physical.path, sce, compression_type)) {
19392 -                                                       
19393 -                                               response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
19394 -                                               response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
19395 -                                               
19396 +
19397 +                                       /* deflate it to file (cached) or to memory */
19398 +                                       if (0 == deflate_file_to_file(srv, con, p,
19399 +                                                       con->physical.path, sce, compression_type) ||
19400 +                                           0 == deflate_file_to_buffer(srv, con, p,
19401 +                                                       con->physical.path, sce, compression_type)) {
19402 +
19403 +                                               response_header_overwrite(srv, con,
19404 +                                                               CONST_STR_LEN("Content-Encoding"),
19405 +                                                               compression_name, strlen(compression_name));
19406 +
19407 +                                               response_header_overwrite(srv, con,
19408 +                                                               CONST_STR_LEN("Content-Type"),
19409 +                                                               CONST_BUF_LEN(sce->content_type));
19410 +
19411                                                 return HANDLER_FINISHED;
19412                                         }
19413                                         break;
19414 @@ -682,20 +728,20 @@
19415                         }
19416                 }
19417         }
19418 -       
19419 +
19420         return HANDLER_GO_ON;
19421  }
19422  
19423  int mod_compress_plugin_init(plugin *p) {
19424         p->version     = LIGHTTPD_VERSION_ID;
19425         p->name        = buffer_init_string("compress");
19426 -       
19427 +
19428         p->init        = mod_compress_init;
19429         p->set_defaults = mod_compress_setdefaults;
19430         p->handle_subrequest_start  = mod_compress_physical;
19431         p->cleanup     = mod_compress_free;
19432 -       
19433 +
19434         p->data        = NULL;
19435 -       
19436 +
19437         return 0;
19438  }
19439 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_dirlisting.c lighttpd-1.4.12/src/mod_dirlisting.c
19440 --- lighttpd-1.4.11/src/mod_dirlisting.c        2006-01-13 00:00:45.000000000 +0200
19441 +++ lighttpd-1.4.12/src/mod_dirlisting.c        2006-07-11 21:23:40.000000000 +0300
19442 @@ -1,11 +1,9 @@
19443  #include <ctype.h>
19444  #include <stdlib.h>
19445  #include <string.h>
19446 -#include <dirent.h>
19447  #include <assert.h>
19448  #include <errno.h>
19449  #include <stdio.h>
19450 -#include <unistd.h>
19451  #include <time.h>
19452  
19453  #include "base.h"
19454 @@ -31,6 +29,9 @@
19455  #include <attr/attributes.h>
19456  #endif
19457  
19458 +#include "sys-files.h"
19459 +#include "sys-strings.h"
19460 +
19461  /* plugin config for all request/connections */
19462  
19463  typedef struct {
19464 @@ -54,7 +55,7 @@
19465         unsigned short hide_readme_file;
19466         unsigned short show_header;
19467         unsigned short hide_header_file;
19468 -       
19469 +
19470         excludes_buffer *excludes;
19471  
19472         buffer *external_css;
19473 @@ -63,13 +64,13 @@
19474  
19475  typedef struct {
19476         PLUGIN_DATA;
19477 -       
19478 +
19479         buffer *tmp_buf;
19480         buffer *content_charset;
19481 -       
19482 +
19483         plugin_config **config_storage;
19484 -       
19485 -       plugin_config conf; 
19486 +
19487 +       plugin_config conf;
19488  } plugin_data;
19489  
19490  excludes_buffer *excludes_buffer_init(void) {
19491 @@ -146,44 +147,44 @@
19492  /* init the plugin data */
19493  INIT_FUNC(mod_dirlisting_init) {
19494         plugin_data *p;
19495 -       
19496 +
19497         p = calloc(1, sizeof(*p));
19498  
19499         p->tmp_buf = buffer_init();
19500         p->content_charset = buffer_init();
19501 -       
19502 +
19503         return p;
19504  }
19505  
19506  /* detroy the plugin data */
19507  FREE_FUNC(mod_dirlisting_free) {
19508         plugin_data *p = p_d;
19509 -       
19510 +
19511         UNUSED(srv);
19512  
19513         if (!p) return HANDLER_GO_ON;
19514 -       
19515 +
19516         if (p->config_storage) {
19517                 size_t i;
19518                 for (i = 0; i < srv->config_context->used; i++) {
19519                         plugin_config *s = p->config_storage[i];
19520 -                       
19521 +
19522                         if (!s) continue;
19523 -                       
19524 +
19525                         excludes_buffer_free(s->excludes);
19526                         buffer_free(s->external_css);
19527                         buffer_free(s->encoding);
19528 -                       
19529 +
19530                         free(s);
19531                 }
19532                 free(p->config_storage);
19533         }
19534 -       
19535 +
19536         buffer_free(p->tmp_buf);
19537         buffer_free(p->content_charset);
19538 -       
19539 +
19540         free(p);
19541 -       
19542 +
19543         return HANDLER_GO_ON;
19544  }
19545  
19546 @@ -215,10 +216,10 @@
19547                         if (0 != excludes_buffer_append(s->excludes,
19548                                     ((data_string *)(da->value->data[j]))->value)) {
19549  #ifdef HAVE_PCRE_H
19550 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
19551 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
19552                                                 "pcre-compile failed for", ((data_string *)(da->value->data[j]))->value);
19553  #else
19554 -                               log_error_write(srv, __FILE__, __LINE__, "s", 
19555 +                               log_error_write(srv, __FILE__, __LINE__, "s",
19556                                                 "pcre support is missing, please install libpcre and the headers");
19557  #endif
19558                         }
19559 @@ -233,8 +234,8 @@
19560  SETDEFAULTS_FUNC(mod_dirlisting_set_defaults) {
19561         plugin_data *p = p_d;
19562         size_t i = 0;
19563 -       
19564 -       config_values_t cv[] = { 
19565 +
19566 +       config_values_t cv[] = {
19567                 { "dir-listing.exclude",          NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION },   /* 0 */
19568                 { "dir-listing.activate",         NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
19569                 { "dir-listing.hide-dotfiles",    NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
19570 @@ -245,18 +246,18 @@
19571                 { "dir-listing.show-header",      NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
19572                 { "dir-listing.hide-header-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
19573                 { "server.dir-listing",           NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
19574 -               
19575 +
19576                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
19577         };
19578 -       
19579 +
19580         if (!p) return HANDLER_ERROR;
19581 -       
19582 +
19583         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
19584 -       
19585 +
19586         for (i = 0; i < srv->config_context->used; i++) {
19587                 plugin_config *s;
19588                 array *ca;
19589 -               
19590 +
19591                 s = calloc(1, sizeof(plugin_config));
19592                 s->excludes = excludes_buffer_init();
19593                 s->dir_listing = 0;
19594 @@ -267,7 +268,7 @@
19595                 s->show_header = 0;
19596                 s->hide_header_file = 0;
19597                 s->encoding = buffer_init();
19598 -               
19599 +
19600                 cv[0].destination = s->excludes;
19601                 cv[1].destination = &(s->dir_listing);
19602                 cv[2].destination = &(s->hide_dot_files);
19603 @@ -292,60 +293,57 @@
19604         return HANDLER_GO_ON;
19605  }
19606  
19607 -#define PATCH(x) \
19608 -       p->conf.x = s->x;
19609  static int mod_dirlisting_patch_connection(server *srv, connection *con, plugin_data *p) {
19610         size_t i, j;
19611         plugin_config *s = p->config_storage[0];
19612  
19613 -       PATCH(dir_listing);
19614 -       PATCH(external_css);
19615 -       PATCH(hide_dot_files);
19616 -       PATCH(encoding);
19617 -       PATCH(show_readme);
19618 -       PATCH(hide_readme_file);
19619 -       PATCH(show_header);
19620 -       PATCH(hide_header_file);
19621 -       PATCH(excludes);
19622 -       
19623 +       PATCH_OPTION(dir_listing);
19624 +       PATCH_OPTION(external_css);
19625 +       PATCH_OPTION(hide_dot_files);
19626 +       PATCH_OPTION(encoding);
19627 +       PATCH_OPTION(show_readme);
19628 +       PATCH_OPTION(hide_readme_file);
19629 +       PATCH_OPTION(show_header);
19630 +       PATCH_OPTION(hide_header_file);
19631 +       PATCH_OPTION(excludes);
19632 +
19633         /* skip the first, the global context */
19634         for (i = 1; i < srv->config_context->used; i++) {
19635                 data_config *dc = (data_config *)srv->config_context->data[i];
19636                 s = p->config_storage[i];
19637 -               
19638 +
19639                 /* condition didn't match */
19640                 if (!config_check_cond(srv, con, dc)) continue;
19641 -               
19642 +
19643                 /* merge config */
19644                 for (j = 0; j < dc->value->used; j++) {
19645                         data_unset *du = dc->value->data[j];
19646 -                       
19647 +
19648                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.activate")) ||
19649                             buffer_is_equal_string(du->key, CONST_STR_LEN("server.dir-listing"))) {
19650 -                               PATCH(dir_listing);
19651 +                               PATCH_OPTION(dir_listing);
19652                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-dotfiles"))) {
19653 -                               PATCH(hide_dot_files);
19654 +                               PATCH_OPTION(hide_dot_files);
19655                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.external-css"))) {
19656 -                               PATCH(external_css);
19657 +                               PATCH_OPTION(external_css);
19658                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.encoding"))) {
19659 -                               PATCH(encoding);
19660 +                               PATCH_OPTION(encoding);
19661                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-readme"))) {
19662 -                               PATCH(show_readme);
19663 +                               PATCH_OPTION(show_readme);
19664                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-readme-file"))) {
19665 -                               PATCH(hide_readme_file);
19666 +                               PATCH_OPTION(hide_readme_file);
19667                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-header"))) {
19668 -                               PATCH(show_header);
19669 +                               PATCH_OPTION(show_header);
19670                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-header-file"))) {
19671 -                               PATCH(hide_header_file);
19672 +                               PATCH_OPTION(hide_header_file);
19673                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.excludes"))) {
19674 -                               PATCH(excludes);
19675 +                               PATCH_OPTION(excludes);
19676                         }
19677                 }
19678         }
19679 -       
19680 +
19681         return 0;
19682  }
19683 -#undef PATCH
19684  
19685  typedef struct {
19686         size_t  namelen;
19687 @@ -432,7 +430,7 @@
19688  
19689  static void http_list_directory_header(server *srv, connection *con, plugin_data *p, buffer *out) {
19690         UNUSED(srv);
19691 -       
19692 +
19693         BUFFER_APPEND_STRING_CONST(out,
19694                 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
19695                 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n"
19696 @@ -492,11 +490,11 @@
19697         if (p->conf.show_header) {
19698                 stream s;
19699                 /* if we have a HEADER file, display it in <pre class="header"></pre> */
19700 -               
19701 +
19702                 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
19703 -               BUFFER_APPEND_SLASH(p->tmp_buf);
19704 +               PATHNAME_APPEND_SLASH(p->tmp_buf);
19705                 BUFFER_APPEND_STRING_CONST(p->tmp_buf, "HEADER.txt");
19706 -               
19707 +
19708                 if (-1 != stream_open(&s, p->tmp_buf)) {
19709                         BUFFER_APPEND_STRING_CONST(out, "<pre class=\"header\">");
19710                         buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
19711 @@ -531,21 +529,21 @@
19712  
19713  static void http_list_directory_footer(server *srv, connection *con, plugin_data *p, buffer *out) {
19714         UNUSED(srv);
19715 -       
19716 +
19717         BUFFER_APPEND_STRING_CONST(out,
19718                 "</tbody>\n"
19719                 "</table>\n"
19720                 "</div>\n"
19721         );
19722 -       
19723 +
19724         if (p->conf.show_readme) {
19725                 stream s;
19726                 /* if we have a README file, display it in <pre class="readme"></pre> */
19727 -               
19728 +
19729                 buffer_copy_string_buffer(p->tmp_buf,  con->physical.path);
19730 -               BUFFER_APPEND_SLASH(p->tmp_buf);
19731 +               PATHNAME_APPEND_SLASH(p->tmp_buf);
19732                 BUFFER_APPEND_STRING_CONST(p->tmp_buf, "README.txt");
19733 -               
19734 +
19735                 if (-1 != stream_open(&s, p->tmp_buf)) {
19736                         BUFFER_APPEND_STRING_CONST(out, "<pre class=\"readme\">");
19737                         buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
19738 @@ -553,7 +551,7 @@
19739                 }
19740                 stream_close(&s);
19741         }
19742 -       
19743 +
19744         BUFFER_APPEND_STRING_CONST(out,
19745                 "<div class=\"foot\">"
19746         );
19747 @@ -595,7 +593,7 @@
19748  #endif
19749  
19750         if (dir->used == 0) return -1;
19751 -       
19752 +
19753         i = dir->used - 1;
19754  
19755  #ifdef HAVE_PATHCONF
19756 @@ -606,19 +604,24 @@
19757                 name_max = 256; /* stupid default */
19758  #endif
19759         }
19760 -#elif defined __WIN32
19761 +#elif defined _WIN32
19762         name_max = FILENAME_MAX;
19763  #else
19764         name_max = NAME_MAX;
19765  #endif
19766 -       
19767 +
19768         path = malloc(dir->used + name_max);
19769         assert(path);
19770         strcpy(path, dir->ptr);
19771 +#ifdef _WIN32
19772 +    /* append \*.* to the path and keep the \ as part of the pathname */
19773 +    strcat(path, "\\*.*");
19774 +    i++;
19775 +#endif
19776         path_file = path + i;
19777  
19778         if (NULL == (dp = opendir(path))) {
19779 -               log_error_write(srv, __FILE__, __LINE__, "sbs", 
19780 +               log_error_write(srv, __FILE__, __LINE__, "sbs",
19781                         "opendir failed:", dir, strerror(errno));
19782  
19783                 free(path);
19784 @@ -633,7 +636,7 @@
19785         assert(files.ent);
19786         files.size = DIRLIST_BLOB_SIZE;
19787         files.used = 0;
19788 -       
19789 +
19790         while ((dent = readdir(dp)) != NULL) {
19791                 unsigned short exclude_match = 0;
19792  
19793 @@ -686,15 +689,17 @@
19794  #endif
19795  
19796                 i = strlen(dent->d_name);
19797 -               
19798 +
19799                 /* NOTE: the manual says, d_name is never more than NAME_MAX
19800                  *       so this should actually not be a buffer-overflow-risk
19801                  */
19802                 if (i > (size_t)name_max) continue;
19803 -               
19804 +
19805                 memcpy(path_file, dent->d_name, i + 1);
19806 -               if (stat(path, &st) != 0)
19807 +               if (stat(path, &st) != 0) {
19808 +            fprintf(stderr, "%s.%d: %s, %s\r\n", __FILE__, __LINE__, path, strerror(errno));
19809                         continue;
19810 +        }
19811  
19812                 list = &files;
19813                 if (S_ISDIR(st.st_mode))
19814 @@ -740,7 +745,7 @@
19815  #else
19816                 strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", localtime(&(tmp->mtime)));
19817  #endif
19818 -               
19819 +
19820                 BUFFER_APPEND_STRING_CONST(out, "<tr><td class=\"n\"><a href=\"");
19821                 buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_REL_URI_PART);
19822                 BUFFER_APPEND_STRING_CONST(out, "/\">");
19823 @@ -758,7 +763,7 @@
19824  
19825                 content_type = NULL;
19826  #ifdef HAVE_XATTR
19827 -               
19828 +
19829                 if (con->conf.use_xattr) {
19830                         memcpy(path_file, DIRLIST_ENT_NAME(tmp), tmp->namelen + 1);
19831                         attrlen = sizeof(attrval) - 1;
19832 @@ -768,7 +773,7 @@
19833                         }
19834                 }
19835  #endif
19836 -               
19837 +
19838                 if (content_type == NULL) {
19839                         content_type = "application/octet-stream";
19840                         for (k = 0; k < con->conf.mimetypes->used; k++) {
19841 @@ -788,7 +793,7 @@
19842                                 }
19843                         }
19844                 }
19845 -                       
19846 +
19847  #ifdef HAVE_LOCALTIME_R
19848                 localtime_r(&(tmp->mtime), &tm);
19849                 strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", &tm);
19850 @@ -837,36 +842,36 @@
19851  URIHANDLER_FUNC(mod_dirlisting_subrequest) {
19852         plugin_data *p = p_d;
19853         stat_cache_entry *sce = NULL;
19854 -       
19855 +
19856         UNUSED(srv);
19857 -       
19858 +
19859         if (con->physical.path->used == 0) return HANDLER_GO_ON;
19860         if (con->uri.path->used == 0) return HANDLER_GO_ON;
19861         if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
19862 -       
19863 +
19864         mod_dirlisting_patch_connection(srv, con, p);
19865  
19866         if (!p->conf.dir_listing) return HANDLER_GO_ON;
19867 -       
19868 +
19869         if (con->conf.log_request_handling) {
19870                 log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling the request as Dir-Listing");
19871                 log_error_write(srv, __FILE__, __LINE__,  "sb", "URI          :", con->uri.path);
19872         }
19873 -       
19874 +
19875         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
19876                 fprintf(stderr, "%s.%d: %s\n", __FILE__, __LINE__, con->physical.path->ptr);
19877                 SEGFAULT();
19878         }
19879 -       
19880 +
19881         if (!S_ISDIR(sce->st.st_mode)) return HANDLER_GO_ON;
19882 -       
19883 +
19884         if (http_list_directory(srv, con, p, con->physical.path)) {
19885                 /* dirlisting failed */
19886                 con->http_status = 403;
19887         }
19888 -       
19889 +
19890         buffer_reset(con->physical.path);
19891 -       
19892 +
19893         /* not found */
19894         return HANDLER_FINISHED;
19895  }
19896 @@ -876,13 +881,13 @@
19897  int mod_dirlisting_plugin_init(plugin *p) {
19898         p->version     = LIGHTTPD_VERSION_ID;
19899         p->name        = buffer_init_string("dirlisting");
19900 -       
19901 +
19902         p->init        = mod_dirlisting_init;
19903         p->handle_subrequest_start  = mod_dirlisting_subrequest;
19904         p->set_defaults  = mod_dirlisting_set_defaults;
19905         p->cleanup     = mod_dirlisting_free;
19906 -       
19907 +
19908         p->data        = NULL;
19909 -       
19910 +
19911         return 0;
19912  }
19913 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_evasive.c lighttpd-1.4.12/src/mod_evasive.c
19914 --- lighttpd-1.4.11/src/mod_evasive.c   2006-01-04 15:24:51.000000000 +0200
19915 +++ lighttpd-1.4.12/src/mod_evasive.c   2006-07-11 21:23:40.000000000 +0300
19916 @@ -31,100 +31,97 @@
19917  
19918  typedef struct {
19919         PLUGIN_DATA;
19920 -       
19921 +
19922         plugin_config **config_storage;
19923 -       
19924 -       plugin_config conf; 
19925 +
19926 +       plugin_config conf;
19927  } plugin_data;
19928  
19929  INIT_FUNC(mod_evasive_init) {
19930         plugin_data *p;
19931 -       
19932 +
19933         p = calloc(1, sizeof(*p));
19934 -       
19935 +
19936         return p;
19937  }
19938  
19939  FREE_FUNC(mod_evasive_free) {
19940         plugin_data *p = p_d;
19941 -       
19942 +
19943         UNUSED(srv);
19944  
19945         if (!p) return HANDLER_GO_ON;
19946 -       
19947 +
19948         if (p->config_storage) {
19949                 size_t i;
19950                 for (i = 0; i < srv->config_context->used; i++) {
19951                         plugin_config *s = p->config_storage[i];
19952 -                                               
19953 +
19954                         free(s);
19955                 }
19956                 free(p->config_storage);
19957         }
19958 -       
19959 +
19960         free(p);
19961 -       
19962 +
19963         return HANDLER_GO_ON;
19964  }
19965  
19966  SETDEFAULTS_FUNC(mod_evasive_set_defaults) {
19967         plugin_data *p = p_d;
19968         size_t i = 0;
19969 -       
19970 -       config_values_t cv[] = { 
19971 +
19972 +       config_values_t cv[] = {
19973                 { "evasive.max-conns-per-ip",    NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
19974                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
19975         };
19976 -       
19977 +
19978         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
19979 -       
19980 +
19981         for (i = 0; i < srv->config_context->used; i++) {
19982                 plugin_config *s;
19983 -               
19984 +
19985                 s = calloc(1, sizeof(plugin_config));
19986                 s->max_conns       = 0;
19987 -               
19988 +
19989                 cv[0].destination = &(s->max_conns);
19990 -               
19991 +
19992                 p->config_storage[i] = s;
19993 -       
19994 +
19995                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
19996                         return HANDLER_ERROR;
19997                 }
19998         }
19999 -       
20000 +
20001         return HANDLER_GO_ON;
20002  }
20003  
20004 -#define PATCH(x) \
20005 -       p->conf.x = s->x;
20006  static int mod_evasive_patch_connection(server *srv, connection *con, plugin_data *p) {
20007         size_t i, j;
20008         plugin_config *s = p->config_storage[0];
20009  
20010 -       PATCH(max_conns);
20011 -       
20012 +       PATCH_OPTION(max_conns);
20013 +
20014         /* skip the first, the global context */
20015         for (i = 1; i < srv->config_context->used; i++) {
20016                 data_config *dc = (data_config *)srv->config_context->data[i];
20017                 s = p->config_storage[i];
20018 -               
20019 +
20020                 /* condition didn't match */
20021                 if (!config_check_cond(srv, con, dc)) continue;
20022 -               
20023 +
20024                 /* merge config */
20025                 for (j = 0; j < dc->value->used; j++) {
20026                         data_unset *du = dc->value->data[j];
20027 -                       
20028 +
20029                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("evasive.max-conns-per-ip"))) {
20030 -                               PATCH(max_conns);
20031 +                               PATCH_OPTION(max_conns);
20032                         }
20033                 }
20034         }
20035 -       
20036 +
20037         return 0;
20038  }
20039 -#undef PATCH
20040  
20041  URIHANDLER_FUNC(mod_evasive_uri_handler) {
20042         plugin_data *p = p_d;
20043 @@ -132,10 +129,10 @@
20044         size_t j;
20045  
20046         if (con->uri.path->used == 0) return HANDLER_GO_ON;
20047 -       
20048 +
20049         mod_evasive_patch_connection(srv, con, p);
20050 -       
20051 -       /* no limit set, nothing to block */    
20052 +
20053 +       /* no limit set, nothing to block */
20054         if (p->conf.max_conns == 0) return HANDLER_GO_ON;
20055  
20056         for (j = 0; j < srv->conns->used; j++) {
20057 @@ -147,7 +144,7 @@
20058                 if (c->dst_addr.ipv4.sin_addr.s_addr == con->dst_addr.ipv4.sin_addr.s_addr &&
20059                     c->state > CON_STATE_REQUEST_END) {
20060                         conns_by_ip++;
20061 -       
20062 +
20063                         if (conns_by_ip > p->conf.max_conns) {
20064                                 log_error_write(srv, __FILE__, __LINE__, "ss",
20065                                         inet_ntop_cache_get_ip(srv, &(con->dst_addr)),
20066 @@ -158,7 +155,7 @@
20067                         }
20068                 }
20069         }
20070 -       
20071 +
20072         return HANDLER_GO_ON;
20073  }
20074  
20075 @@ -166,13 +163,13 @@
20076  int mod_evasive_plugin_init(plugin *p) {
20077         p->version     = LIGHTTPD_VERSION_ID;
20078         p->name        = buffer_init_string("evasive");
20079 -       
20080 +
20081         p->init        = mod_evasive_init;
20082         p->set_defaults = mod_evasive_set_defaults;
20083         p->handle_uri_clean  = mod_evasive_uri_handler;
20084         p->cleanup     = mod_evasive_free;
20085 -       
20086 +
20087         p->data        = NULL;
20088 -       
20089 +
20090         return 0;
20091  }
20092 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_evhost.c lighttpd-1.4.12/src/mod_evhost.c
20093 --- lighttpd-1.4.11/src/mod_evhost.c    2005-08-17 10:42:03.000000000 +0300
20094 +++ lighttpd-1.4.12/src/mod_evhost.c    2006-07-11 21:23:39.000000000 +0300
20095 @@ -7,10 +7,12 @@
20096  #include "response.h"
20097  #include "stat_cache.h"
20098  
20099 +#include "sys-files.h"
20100 +
20101  typedef struct {
20102         /* unparsed pieces */
20103         buffer *path_pieces_raw;
20104 -       
20105 +
20106         /* pieces for path creation */
20107         size_t len;
20108         buffer **path_pieces;
20109 @@ -21,14 +23,14 @@
20110         buffer *tmp_buf;
20111  
20112         plugin_config **config_storage;
20113 -       plugin_config conf; 
20114 +       plugin_config conf;
20115  } plugin_data;
20116  
20117  INIT_FUNC(mod_evhost_init) {
20118         plugin_data *p;
20119 -       
20120 +
20121         p = calloc(1, sizeof(*p));
20122 -       
20123 +
20124         p->tmp_buf = buffer_init();
20125  
20126         return p;
20127 @@ -36,34 +38,34 @@
20128  
20129  FREE_FUNC(mod_evhost_free) {
20130         plugin_data *p = p_d;
20131 -       
20132 +
20133         UNUSED(srv);
20134  
20135         if (!p) return HANDLER_GO_ON;
20136 -       
20137 +
20138         if (p->config_storage) {
20139                 size_t i;
20140                 for (i = 0; i < srv->config_context->used; i++) {
20141                         plugin_config *s = p->config_storage[i];
20142  
20143                         if (!s) continue;
20144 -                       
20145 +
20146                         if(s->path_pieces) {
20147                                 size_t j;
20148                                 for (j = 0; j < s->len; j++) {
20149                                         buffer_free(s->path_pieces[j]);
20150                                 }
20151 -                               
20152 +
20153                                 free(s->path_pieces);
20154                         }
20155 -                       
20156 +
20157                         buffer_free(s->path_pieces_raw);
20158 -                       
20159 +
20160                         free(s);
20161                 }
20162                 free(p->config_storage);
20163         }
20164 -       
20165 +
20166         buffer_free(p->tmp_buf);
20167  
20168         free(p);
20169 @@ -73,30 +75,30 @@
20170  
20171  static void mod_evhost_parse_pattern(plugin_config *s) {
20172         char *ptr = s->path_pieces_raw->ptr,*pos;
20173 -       
20174 +
20175         s->path_pieces = NULL;
20176 -       
20177 +
20178         for(pos=ptr;*ptr;ptr++) {
20179                 if(*ptr == '%') {
20180                         s->path_pieces = realloc(s->path_pieces,(s->len+2) * sizeof(*s->path_pieces));
20181                         s->path_pieces[s->len] = buffer_init();
20182                         s->path_pieces[s->len+1] = buffer_init();
20183 -                       
20184 +
20185                         buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos);
20186                         pos = ptr + 2;
20187 -                       
20188 +
20189                         buffer_copy_string_len(s->path_pieces[s->len+1],ptr++,2);
20190 -                       
20191 +
20192                         s->len += 2;
20193                 }
20194         }
20195 -       
20196 +
20197         if(*pos != '\0') {
20198                 s->path_pieces = realloc(s->path_pieces,(s->len+1) * sizeof(*s->path_pieces));
20199                 s->path_pieces[s->len] = buffer_init();
20200 -               
20201 +
20202                 buffer_append_memory(s->path_pieces[s->len],pos,ptr-pos);
20203 -               
20204 +
20205                 s->len += 1;
20206         }
20207  }
20208 @@ -104,9 +106,9 @@
20209  SETDEFAULTS_FUNC(mod_evhost_set_defaults) {
20210         plugin_data *p = p_d;
20211         size_t i;
20212 -       
20213 +
20214         /**
20215 -        * 
20216 +        *
20217          * #
20218          * # define a pattern for the host url finding
20219          * # %% => % sign
20220 @@ -117,39 +119,39 @@
20221          * # %4 => subdomain 2 name
20222          * #
20223          * evhost.path-pattern = "/home/ckruse/dev/www/%3/htdocs/"
20224 -        * 
20225 +        *
20226          */
20227 -       
20228 -       config_values_t cv[] = { 
20229 +
20230 +       config_values_t cv[] = {
20231                 { "evhost.path-pattern",            NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
20232                 { NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
20233         };
20234 -       
20235 +
20236         if (!p) return HANDLER_ERROR;
20237 -       
20238 +
20239         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
20240 -       
20241 +
20242         for (i = 0; i < srv->config_context->used; i++) {
20243                 plugin_config *s;
20244 -               
20245 +
20246                 s = calloc(1, sizeof(plugin_config));
20247                 s->path_pieces_raw = buffer_init();
20248                 s->path_pieces     = NULL;
20249                 s->len             = 0;
20250 -       
20251 +
20252                 cv[0].destination = s->path_pieces_raw;
20253 -               
20254 +
20255                 p->config_storage[i] = s;
20256 -               
20257 +
20258                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value,  cv)) {
20259                         return HANDLER_ERROR;
20260                 }
20261 -               
20262 +
20263                 if (s->path_pieces_raw->used != 0) {
20264                         mod_evhost_parse_pattern(s);
20265                 }
20266         }
20267 -       
20268 +
20269         return HANDLER_GO_ON;
20270  }
20271  
20272 @@ -158,7 +160,7 @@
20273   * - %0 - full hostname (authority w/o port)
20274   * - %1 - tld
20275   * - %2 - domain.tld
20276 - * - %3 - 
20277 + * - %3 -
20278   */
20279  
20280  static int mod_evhost_parse_host(connection *con,array *host) {
20281 @@ -168,7 +170,7 @@
20282         int first = 1;
20283         data_string *ds;
20284         int i;
20285 -       
20286 +
20287         /* first, find the domain + tld */
20288         for(;ptr > con->uri.authority->ptr;ptr--) {
20289                 if(*ptr == '.') {
20290 @@ -179,18 +181,18 @@
20291                         first = 1;
20292                 }
20293         }
20294 -       
20295 +
20296         ds = data_string_init();
20297         buffer_copy_string(ds->key,"%0");
20298 -       
20299 +
20300         /* if we stopped at a dot, skip the dot */
20301         if (*ptr == '.') ptr++;
20302         buffer_copy_string_len(ds->value, ptr, colon-ptr);
20303 -       
20304 +
20305         array_insert_unique(host,(data_unset *)ds);
20306 -       
20307 +
20308         /* if the : is not the start of the authority, go on parsing the hostname */
20309 -       
20310 +
20311         if (colon != con->uri.authority->ptr) {
20312                 for(ptr = colon - 1, i = 1; ptr > con->uri.authority->ptr; ptr--) {
20313                         if(*ptr == '.') {
20314 @@ -200,59 +202,55 @@
20315                                         buffer_copy_string(ds->key,"%");
20316                                         buffer_append_long(ds->key, i++);
20317                                         buffer_copy_string_len(ds->value,ptr+1,colon-ptr-1);
20318 -                                       
20319 +
20320                                         array_insert_unique(host,(data_unset *)ds);
20321                                 }
20322                                 colon = ptr;
20323                         }
20324                 }
20325 -               
20326 +
20327                 /* if the . is not the first charactor of the hostname */
20328                 if (colon != ptr) {
20329                         ds = data_string_init();
20330                         buffer_copy_string(ds->key,"%");
20331                         buffer_append_long(ds->key, i++);
20332                         buffer_copy_string_len(ds->value,ptr,colon-ptr);
20333 -                       
20334 +
20335                         array_insert_unique(host,(data_unset *)ds);
20336                 }
20337         }
20338 -       
20339 +
20340         return 0;
20341  }
20342  
20343 -#define PATCH(x) \
20344 -       p->conf.x = s->x;
20345  static int mod_evhost_patch_connection(server *srv, connection *con, plugin_data *p) {
20346         size_t i, j;
20347         plugin_config *s = p->config_storage[0];
20348 -       
20349 -       PATCH(path_pieces);
20350 -       PATCH(len);
20351 -       
20352 +
20353 +       PATCH_OPTION(path_pieces);
20354 +       PATCH_OPTION(len);
20355 +
20356         /* skip the first, the global context */
20357         for (i = 1; i < srv->config_context->used; i++) {
20358                 data_config *dc = (data_config *)srv->config_context->data[i];
20359                 s = p->config_storage[i];
20360 -               
20361 +
20362                 /* condition didn't match */
20363                 if (!config_check_cond(srv, con, dc)) continue;
20364 -               
20365 +
20366                 /* merge config */
20367                 for (j = 0; j < dc->value->used; j++) {
20368                         data_unset *du = dc->value->data[j];
20369 -                       
20370 +
20371                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("evhost.path-pattern"))) {
20372 -                               PATCH(path_pieces);
20373 -                               PATCH(len);
20374 +                               PATCH_OPTION(path_pieces);
20375 +                               PATCH_OPTION(len);
20376                         }
20377                 }
20378         }
20379 -       
20380 +
20381         return 0;
20382  }
20383 -#undef PATCH
20384 -
20385  
20386  static handler_t mod_evhost_uri_handler(server *srv, connection *con, void *p_d) {
20387         plugin_data *p = p_d;
20388 @@ -261,29 +259,29 @@
20389         register char *ptr;
20390         int not_good = 0;
20391         stat_cache_entry *sce = NULL;
20392 -       
20393 +
20394         /* not authority set */
20395         if (con->uri.authority->used == 0) return HANDLER_GO_ON;
20396 -       
20397 +
20398         mod_evhost_patch_connection(srv, con, p);
20399 -       
20400 +
20401         /* missing even default(global) conf */
20402         if (0 == p->conf.len) {
20403                 return HANDLER_GO_ON;
20404         }
20405  
20406         parsed_host = array_init();
20407 -       
20408 +
20409         mod_evhost_parse_host(con, parsed_host);
20410 -       
20411 +
20412         /* build document-root */
20413         buffer_reset(p->tmp_buf);
20414 -       
20415 +
20416         for (i = 0; i < p->conf.len; i++) {
20417                 ptr = p->conf.path_pieces[i]->ptr;
20418                 if (*ptr == '%') {
20419                         data_string *ds;
20420 -                       
20421 +
20422                         if (*(ptr+1) == '%') {
20423                                 /* %% */
20424                                 BUFFER_APPEND_STRING_CONST(p->tmp_buf,"%");
20425 @@ -298,11 +296,11 @@
20426                         buffer_append_string_buffer(p->tmp_buf,p->conf.path_pieces[i]);
20427                 }
20428         }
20429 -       
20430 -       BUFFER_APPEND_SLASH(p->tmp_buf);
20431 -       
20432 +
20433 +       PATHNAME_APPEND_SLASH(p->tmp_buf);
20434 +
20435         array_free(parsed_host);
20436 -       
20437 +
20438         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
20439                 log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
20440                 not_good = 1;
20441 @@ -310,11 +308,11 @@
20442                 log_error_write(srv, __FILE__, __LINE__, "sb", "not a directory:", p->tmp_buf);
20443                 not_good = 1;
20444         }
20445 -       
20446 +
20447         if (!not_good) {
20448                 buffer_copy_string_buffer(con->physical.doc_root, p->tmp_buf);
20449         }
20450 -       
20451 +
20452         return HANDLER_GO_ON;
20453  }
20454  
20455 @@ -325,9 +323,9 @@
20456         p->set_defaults            = mod_evhost_set_defaults;
20457         p->handle_docroot          = mod_evhost_uri_handler;
20458         p->cleanup                 = mod_evhost_free;
20459 -       
20460 +
20461         p->data                    = NULL;
20462 -       
20463 +
20464         return 0;
20465  }
20466  
20467 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_expire.c lighttpd-1.4.12/src/mod_expire.c
20468 --- lighttpd-1.4.11/src/mod_expire.c    2005-11-03 09:52:13.000000000 +0200
20469 +++ lighttpd-1.4.12/src/mod_expire.c    2006-07-11 21:23:40.000000000 +0300
20470 @@ -12,8 +12,8 @@
20471  #include "stat_cache.h"
20472  
20473  /**
20474 - * this is a expire module for a lighttpd 
20475 - * 
20476 + * this is a expire module for a lighttpd
20477 + *
20478   * set 'Expires:' HTTP Headers on demand
20479   */
20480  
20481 @@ -27,51 +27,51 @@
20482  
20483  typedef struct {
20484         PLUGIN_DATA;
20485 -       
20486 +
20487         buffer *expire_tstmp;
20488 -       
20489 +
20490         plugin_config **config_storage;
20491 -       
20492 -       plugin_config conf; 
20493 +
20494 +       plugin_config conf;
20495  } plugin_data;
20496  
20497  /* init the plugin data */
20498  INIT_FUNC(mod_expire_init) {
20499         plugin_data *p;
20500 -       
20501 +
20502         p = calloc(1, sizeof(*p));
20503 -       
20504 +
20505         p->expire_tstmp = buffer_init();
20506 -       
20507 +
20508         buffer_prepare_copy(p->expire_tstmp, 255);
20509 -       
20510 +
20511         return p;
20512  }
20513  
20514  /* detroy the plugin data */
20515  FREE_FUNC(mod_expire_free) {
20516         plugin_data *p = p_d;
20517 -       
20518 +
20519         UNUSED(srv);
20520  
20521         if (!p) return HANDLER_GO_ON;
20522 -       
20523 +
20524         buffer_free(p->expire_tstmp);
20525 -       
20526 +
20527         if (p->config_storage) {
20528                 size_t i;
20529                 for (i = 0; i < srv->config_context->used; i++) {
20530                         plugin_config *s = p->config_storage[i];
20531 -                       
20532 +
20533                         array_free(s->expire_url);
20534 -                       
20535 +
20536                         free(s);
20537                 }
20538                 free(p->config_storage);
20539         }
20540 -       
20541 +
20542         free(p);
20543 -       
20544 +
20545         return HANDLER_GO_ON;
20546  }
20547  
20548 @@ -79,25 +79,25 @@
20549         char *ts;
20550         int type = -1;
20551         int retts = 0;
20552 -               
20553 +
20554         UNUSED(p);
20555  
20556 -       /* 
20557 +       /*
20558          * parse
20559 -        * 
20560 +        *
20561          * '(access|modification) [plus] {<num> <type>}*'
20562 -        * 
20563 +        *
20564          * e.g. 'access 1 years'
20565          */
20566 -       
20567 +
20568         if (expire->used == 0) {
20569 -               log_error_write(srv, __FILE__, __LINE__, "s", 
20570 +               log_error_write(srv, __FILE__, __LINE__, "s",
20571                                 "empty:");
20572                 return -1;
20573         }
20574 -       
20575 +
20576         ts = expire->ptr;
20577 -       
20578 +
20579         if (0 == strncmp(ts, "access ", 7)) {
20580                 type  = 0;
20581                 ts   += 7;
20582 @@ -110,39 +110,39 @@
20583                                 "invalid <base>:", ts);
20584                 return -1;
20585         }
20586 -       
20587 +
20588         if (0 == strncmp(ts, "plus ", 5)) {
20589                 /* skip the optional plus */
20590                 ts   += 5;
20591         }
20592 -       
20593 +
20594         /* the rest is just <number> (years|months|days|hours|minutes|seconds) */
20595         while (1) {
20596                 char *space, *err;
20597                 int num;
20598 -               
20599 +
20600                 if (NULL == (space = strchr(ts, ' '))) {
20601 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
20602 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
20603                                         "missing space after <num>:", ts);
20604                         return -1;
20605                 }
20606 -               
20607 +
20608                 num = strtol(ts, &err, 10);
20609                 if (*err != ' ') {
20610 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
20611 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
20612                                         "missing <type> after <num>:", ts);
20613                         return -1;
20614                 }
20615 -               
20616 +
20617                 ts = space + 1;
20618 -               
20619 +
20620                 if (NULL != (space = strchr(ts, ' '))) {
20621                         int slen;
20622                         /* */
20623 -                       
20624 +
20625                         slen = space - ts;
20626 -                       
20627 -                       if (slen == 5 && 
20628 +
20629 +                       if (slen == 5 &&
20630                             0 == strncmp(ts, "years", slen)) {
20631                                 num *= 60 * 60 * 24 * 30 * 12;
20632                         } else if (slen == 6 &&
20633 @@ -161,13 +161,13 @@
20634                                    0 == strncmp(ts, "seconds", slen)) {
20635                                 num *= 1;
20636                         } else {
20637 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
20638 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
20639                                                 "unknown type:", ts);
20640                                 return -1;
20641                         }
20642 -                       
20643 +
20644                         retts += num;
20645 -                       
20646 +
20647                         ts = space + 1;
20648                 } else {
20649                         if (0 == strcmp(ts, "years")) {
20650 @@ -183,19 +183,19 @@
20651                         } else if (0 == strcmp(ts, "seconds")) {
20652                                 num *= 1;
20653                         } else {
20654 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
20655 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
20656                                                 "unknown type:", ts);
20657                                 return -1;
20658                         }
20659 -                       
20660 +
20661                         retts += num;
20662 -                       
20663 +
20664                         break;
20665                 }
20666         }
20667 -       
20668 +
20669         if (offset != NULL) *offset = retts;
20670 -       
20671 +
20672         return type;
20673  }
20674  
20675 @@ -205,102 +205,99 @@
20676  SETDEFAULTS_FUNC(mod_expire_set_defaults) {
20677         plugin_data *p = p_d;
20678         size_t i = 0, k;
20679 -       
20680 -       config_values_t cv[] = { 
20681 +
20682 +       config_values_t cv[] = {
20683                 { "expire.url",                 NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
20684                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
20685         };
20686 -       
20687 +
20688         if (!p) return HANDLER_ERROR;
20689 -       
20690 +
20691         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
20692 -       
20693 +
20694         for (i = 0; i < srv->config_context->used; i++) {
20695                 plugin_config *s;
20696 -               
20697 +
20698                 s = calloc(1, sizeof(plugin_config));
20699                 s->expire_url    = array_init();
20700 -               
20701 +
20702                 cv[0].destination = s->expire_url;
20703 -               
20704 +
20705                 p->config_storage[i] = s;
20706 -       
20707 +
20708                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
20709                         return HANDLER_ERROR;
20710                 }
20711 -       
20712 +
20713                 for (k = 0; k < s->expire_url->used; k++) {
20714                         data_string *ds = (data_string *)s->expire_url->data[k];
20715 -                       
20716 +
20717                         /* parse lines */
20718                         if (-1 == mod_expire_get_offset(srv, p, ds->value, NULL)) {
20719 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
20720 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
20721                                                 "parsing expire.url failed:", ds->value);
20722                                 return HANDLER_ERROR;
20723                         }
20724                 }
20725         }
20726 -       
20727 -       
20728 +
20729 +
20730         return HANDLER_GO_ON;
20731  }
20732  
20733 -#define PATCH(x) \
20734 -       p->conf.x = s->x;
20735  static int mod_expire_patch_connection(server *srv, connection *con, plugin_data *p) {
20736         size_t i, j;
20737         plugin_config *s = p->config_storage[0];
20738 -       
20739 -       PATCH(expire_url);
20740 -       
20741 +
20742 +       PATCH_OPTION(expire_url);
20743 +
20744         /* skip the first, the global context */
20745         for (i = 1; i < srv->config_context->used; i++) {
20746                 data_config *dc = (data_config *)srv->config_context->data[i];
20747                 s = p->config_storage[i];
20748 -               
20749 +
20750                 /* condition didn't match */
20751                 if (!config_check_cond(srv, con, dc)) continue;
20752 -               
20753 +
20754                 /* merge config */
20755                 for (j = 0; j < dc->value->used; j++) {
20756                         data_unset *du = dc->value->data[j];
20757 -                       
20758 +
20759                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("expire.url"))) {
20760 -                               PATCH(expire_url);
20761 +                               PATCH_OPTION(expire_url);
20762                         }
20763                 }
20764         }
20765 -       
20766 +
20767         return 0;
20768  }
20769 -#undef PATCH
20770  
20771  URIHANDLER_FUNC(mod_expire_path_handler) {
20772         plugin_data *p = p_d;
20773         int s_len;
20774         size_t k;
20775 -       
20776 +
20777         if (con->uri.path->used == 0) return HANDLER_GO_ON;
20778 -       
20779 +
20780         mod_expire_patch_connection(srv, con, p);
20781 -       
20782 +
20783         s_len = con->uri.path->used - 1;
20784 -       
20785 +
20786         for (k = 0; k < p->conf.expire_url->used; k++) {
20787                 data_string *ds = (data_string *)p->conf.expire_url->data[k];
20788                 int ct_len = ds->key->used - 1;
20789 -               
20790 +
20791                 if (ct_len > s_len) continue;
20792                 if (ds->key->used == 0) continue;
20793 -               
20794 +
20795                 if (0 == strncmp(con->uri.path->ptr, ds->key->ptr, ct_len)) {
20796                         int ts;
20797                         time_t t;
20798                         size_t len;
20799                         stat_cache_entry *sce = NULL;
20800 -               
20801 +
20802                         stat_cache_get_entry(srv, con, con->physical.path, &sce);
20803 -                       
20804 +
20805                         switch(mod_expire_get_offset(srv, p, ds->value, &ts)) {
20806                         case 0:
20807                                 /* access */
20808 @@ -308,38 +305,38 @@
20809                                 break;
20810                         case 1:
20811                                 /* modification */
20812 -                               
20813 +
20814                                 t = (ts + sce->st.st_mtime);
20815                                 break;
20816                         default:
20817                                 /* -1 is handled at parse-time */
20818                                 break;
20819                         }
20820 -                       
20821 -                       
20822 -                       if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1, 
20823 +
20824 +
20825 +                       if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1,
20826                                            "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(t))))) {
20827                                 /* could not set expire header, out of mem */
20828 -                               
20829 +
20830                                 return HANDLER_GO_ON;
20831 -                               
20832 +
20833                         }
20834 -                           
20835 +
20836                         p->expire_tstmp->used = len + 1;
20837 -               
20838 -                       /* HTTP/1.0 */  
20839 +
20840 +                       /* HTTP/1.0 */
20841                         response_header_overwrite(srv, con, CONST_STR_LEN("Expires"), CONST_BUF_LEN(p->expire_tstmp));
20842  
20843 -                       /* HTTP/1.1 */  
20844 +                       /* HTTP/1.1 */
20845                         buffer_copy_string(p->expire_tstmp, "max-age=");
20846                         buffer_append_long(p->expire_tstmp, ts);
20847 -                       
20848 +
20849                         response_header_overwrite(srv, con, CONST_STR_LEN("Cache-Control"), CONST_BUF_LEN(p->expire_tstmp));
20850 -                       
20851 +
20852                         return HANDLER_GO_ON;
20853                 }
20854         }
20855 -       
20856 +
20857         /* not found */
20858         return HANDLER_GO_ON;
20859  }
20860 @@ -349,13 +346,13 @@
20861  int mod_expire_plugin_init(plugin *p) {
20862         p->version     = LIGHTTPD_VERSION_ID;
20863         p->name        = buffer_init_string("expire");
20864 -       
20865 +
20866         p->init        = mod_expire_init;
20867         p->handle_subrequest_start = mod_expire_path_handler;
20868         p->set_defaults  = mod_expire_set_defaults;
20869         p->cleanup     = mod_expire_free;
20870 -       
20871 +
20872         p->data        = NULL;
20873 -       
20874 +
20875         return 0;
20876  }
20877 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_fastcgi.c lighttpd-1.4.12/src/mod_fastcgi.c
20878 --- lighttpd-1.4.11/src/mod_fastcgi.c   2006-03-09 13:18:39.000000000 +0200
20879 +++ lighttpd-1.4.12/src/mod_fastcgi.c   2006-07-11 21:23:40.000000000 +0300
20880 @@ -1,5 +1,4 @@
20881  #include <sys/types.h>
20882 -#include <unistd.h>
20883  #include <errno.h>
20884  #include <fcntl.h>
20885  #include <string.h>
20886 @@ -24,7 +23,7 @@
20887  #include "inet_ntop_cache.h"
20888  #include "stat_cache.h"
20889  
20890 -#include <fastcgi.h>
20891 +#include "fastcgi.h"
20892  #include <stdio.h>
20893  
20894  #ifdef HAVE_SYS_FILIO_H
20895 @@ -32,7 +31,11 @@
20896  #endif
20897  
20898  #include "sys-socket.h"
20899 +#include "sys-files.h"
20900 +#include "sys-strings.h"
20901 +#include "sys-process.h"
20902  
20903 +#include "http_resp.h"
20904  
20905  #ifndef UNIX_PATH_MAX
20906  # define UNIX_PATH_MAX 108
20907 @@ -45,14 +48,13 @@
20908  #include <sys/wait.h>
20909  #endif
20910  
20911 -
20912  /*
20913 - * 
20914 + *
20915   * TODO:
20916 - * 
20917 + *
20918   * - add timeout for a connect to a non-fastcgi process
20919   *   (use state_timestamp + state)
20920 - * 
20921 + *
20922   */
20923  
20924  typedef struct fcgi_proc {
20925 @@ -61,7 +63,7 @@
20926         unsigned port;  /* config.port + pno */
20927  
20928         buffer *connection_name; /* either tcp:<host>:<port> or unix:<socket> for debuggin purposes */
20929 -       
20930 +
20931         pid_t pid;   /* PID of the spawned process (0 if not spawned locally) */
20932  
20933  
20934 @@ -70,20 +72,20 @@
20935         time_t last_used; /* see idle_timeout */
20936         size_t requests;  /* see max_requests */
20937         struct fcgi_proc *prev, *next; /* see first */
20938 -       
20939 +
20940         time_t disabled_until; /* this proc is disabled until, use something else until than */
20941 -       
20942 +
20943         int is_local;
20944  
20945 -       enum { 
20946 +       enum {
20947                 PROC_STATE_UNSET,    /* init-phase */
20948                 PROC_STATE_RUNNING,  /* alive */
20949 -               PROC_STATE_OVERLOADED, /* listen-queue is full, 
20950 +               PROC_STATE_OVERLOADED, /* listen-queue is full,
20951                                           don't send something to this proc for the next 2 seconds */
20952                 PROC_STATE_DIED_WAIT_FOR_PID, /* */
20953                 PROC_STATE_DIED,     /* marked as dead, should be restarted */
20954                 PROC_STATE_KILLED    /* was killed as we don't have the load anymore */
20955 -       } state; 
20956 +       } state;
20957  } fcgi_proc;
20958  
20959  typedef struct {
20960 @@ -94,20 +96,20 @@
20961          * sorted by lowest load
20962          *
20963          * whenever a job is done move it up in the list
20964 -        * until it is sorted, move it down as soon as the 
20965 +        * until it is sorted, move it down as soon as the
20966          * job is started
20967          */
20968 -       fcgi_proc *first; 
20969 -       fcgi_proc *unused_procs; 
20970 +       fcgi_proc *first;
20971 +       fcgi_proc *unused_procs;
20972  
20973 -       /* 
20974 +       /*
20975          * spawn at least min_procs, at max_procs.
20976          *
20977 -        * as soon as the load of the first entry 
20978 +        * as soon as the load of the first entry
20979          * is max_load_per_proc we spawn a new one
20980 -        * and add it to the first entry and give it 
20981 +        * and add it to the first entry and give it
20982          * the load
20983 -        * 
20984 +        *
20985          */
20986  
20987         unsigned short min_procs;
20988 @@ -119,44 +121,44 @@
20989  
20990         /*
20991          * kick the process from the list if it was not
20992 -        * used for idle_timeout until min_procs is 
20993 +        * used for idle_timeout until min_procs is
20994          * reached. this helps to get the processlist
20995          * small again we had a small peak load.
20996          *
20997          */
20998 -       
20999 +
21000         unsigned short idle_timeout;
21001 -       
21002 +
21003         /*
21004          * time after a disabled remote connection is tried to be re-enabled
21005 -        * 
21006 -        * 
21007 +        *
21008 +        *
21009          */
21010 -       
21011 +
21012         unsigned short disable_time;
21013  
21014         /*
21015          * same fastcgi processes get a little bit larger
21016 -        * than wanted. max_requests_per_proc kills a 
21017 +        * than wanted. max_requests_per_proc kills a
21018          * process after a number of handled requests.
21019          *
21020          */
21021         size_t max_requests_per_proc;
21022 -       
21023 +
21024  
21025         /* config */
21026  
21027 -       /* 
21028 -        * host:port 
21029 +       /*
21030 +        * host:port
21031          *
21032 -        * if host is one of the local IP adresses the 
21033 +        * if host is one of the local IP adresses the
21034          * whole connection is local
21035          *
21036          * if tcp/ip should be used host AND port have
21037 -        * to be specified 
21038 -        * 
21039 -        */ 
21040 -       buffer *host; 
21041 +        * to be specified
21042 +        *
21043 +        */
21044 +       buffer *host;
21045         unsigned short port;
21046  
21047         /*
21048 @@ -169,7 +171,7 @@
21049          */
21050         buffer *unixsocket;
21051  
21052 -       /* if socket is local we can start the fastcgi 
21053 +       /* if socket is local we can start the fastcgi
21054          * process ourself
21055          *
21056          * bin-path is the path to the binary
21057 @@ -177,19 +179,19 @@
21058          * check min_procs and max_procs for the number
21059          * of process to start-up
21060          */
21061 -       buffer *bin_path; 
21062 -       
21063 -       /* bin-path is set bin-environment is taken to 
21064 +       buffer *bin_path;
21065 +
21066 +       /* bin-path is set bin-environment is taken to
21067          * create the environement before starting the
21068          * FastCGI process
21069 -        * 
21070 +        *
21071          */
21072         array *bin_env;
21073 -       
21074 +
21075         array *bin_env_copy;
21076 -       
21077 +
21078         /*
21079 -        * docroot-translation between URL->phys and the 
21080 +        * docroot-translation between URL->phys and the
21081          * remote host
21082          *
21083          * reasons:
21084 @@ -208,7 +210,7 @@
21085         unsigned short mode;
21086  
21087         /*
21088 -        * check_local tell you if the phys file is stat()ed 
21089 +        * check_local tell you if the phys file is stat()ed
21090          * or not. FastCGI doesn't care if the service is
21091          * remote. If the web-server side doesn't contain
21092          * the fastcgi-files we should not stat() for them
21093 @@ -218,11 +220,11 @@
21094  
21095         /*
21096          * append PATH_INFO to SCRIPT_FILENAME
21097 -        * 
21098 +        *
21099          * php needs this if cgi.fix_pathinfo is provied
21100 -        * 
21101 +        *
21102          */
21103 -       
21104 +
21105         unsigned short break_scriptfilename_for_php;
21106  
21107         /*
21108 @@ -231,12 +233,12 @@
21109          *
21110          */
21111         unsigned short allow_xsendfile;
21112 -               
21113 +
21114         ssize_t load; /* replace by host->load */
21115  
21116         size_t max_id; /* corresponds most of the time to
21117         num_procs.
21118 -       
21119 +
21120         only if a process is killed max_id waits for the process itself
21121         to die and decrements its afterwards */
21122  
21123 @@ -245,17 +247,17 @@
21124  
21125  /*
21126   * one extension can have multiple hosts assigned
21127 - * one host can spawn additional processes on the same 
21128 + * one host can spawn additional processes on the same
21129   *   socket (if we control it)
21130   *
21131   * ext -> host -> procs
21132   *    1:n     1:n
21133   *
21134 - * if the fastcgi process is remote that whole goes down 
21135 + * if the fastcgi process is remote that whole goes down
21136   * to
21137   *
21138   * ext -> host -> procs
21139 - *    1:n     1:1 
21140 + *    1:n     1:1
21141   *
21142   * in case of PHP and FCGI_CHILDREN we have again a procs
21143   * but we don't control it directly.
21144 @@ -268,7 +270,7 @@
21145         int note_is_sent;
21146  
21147         fcgi_extension_host **hosts;
21148 -       
21149 +
21150         size_t used;
21151         size_t size;
21152  } fcgi_extension;
21153 @@ -282,10 +284,10 @@
21154  
21155  
21156  typedef struct {
21157 -       fcgi_exts *exts; 
21158 +       fcgi_exts *exts;
21159  
21160         array *ext_mapping;
21161 -       
21162 +
21163         int debug;
21164  } plugin_config;
21165  
21166 @@ -297,7 +299,7 @@
21167  
21168  typedef struct {
21169         char **ptr;
21170 -       
21171 +
21172         size_t size;
21173         size_t used;
21174  } char_array;
21175 @@ -306,44 +308,44 @@
21176  typedef struct {
21177         PLUGIN_DATA;
21178         buffer_uint fcgi_request_id;
21179 -       
21180 +
21181         buffer *fcgi_env;
21182 -       
21183 +
21184         buffer *path;
21185 -       buffer *parse_response;
21186  
21187         buffer *statuskey;
21188 -       
21189 +
21190 +       http_resp *resp;
21191 +
21192         plugin_config **config_storage;
21193 -       
21194 +
21195         plugin_config conf; /* this is only used as long as no handler_ctx is setup */
21196  } plugin_data;
21197  
21198  /* connection specific data */
21199 -typedef enum { 
21200 +typedef enum {
21201         FCGI_STATE_UNSET,
21202 -       FCGI_STATE_INIT, 
21203 -       FCGI_STATE_CONNECT_DELAYED, 
21204 -       FCGI_STATE_PREPARE_WRITE, 
21205 -       FCGI_STATE_WRITE, 
21206 -       FCGI_STATE_READ 
21207 +       FCGI_STATE_INIT,
21208 +       FCGI_STATE_CONNECT_DELAYED,
21209 +       FCGI_STATE_PREPARE_WRITE,
21210 +       FCGI_STATE_WRITE,
21211 +       FCGI_STATE_READ
21212  } fcgi_connection_state_t;
21213  
21214  typedef struct {
21215         fcgi_proc *proc;
21216         fcgi_extension_host *host;
21217         fcgi_extension *ext;
21218 -       
21219 +
21220         fcgi_connection_state_t state;
21221         time_t   state_timestamp;
21222 -       
21223 +
21224         int      reconnects; /* number of reconnect attempts */
21225 -       
21226 -       chunkqueue *rb; /* read queue */
21227 +
21228 +       chunkqueue *rb; /* the raw fcgi read-queue */
21229 +       chunkqueue *http_rb; /* the decoded read-queue for http-parsing */
21230         chunkqueue *wb; /* write queue */
21231 -       
21232 -       buffer   *response_header;
21233 -       
21234 +
21235         size_t    request_id;
21236         int       fd;        /* fd to the fastcgi process */
21237         int       fde_ndx;   /* index into the fd-event buffer */
21238 @@ -352,9 +354,9 @@
21239         int       got_proc;
21240  
21241         int       send_content_body;
21242 -       
21243 +
21244         plugin_config conf;
21245 -       
21246 +
21247         connection *remote_conn;  /* dumb pointer */
21248         plugin_data *plugin_data; /* dumb pointer */
21249  } handler_ctx;
21250 @@ -380,7 +382,7 @@
21251         return di;
21252  }
21253  
21254 -/* dummies of the statistic framework functions 
21255 +/* dummies of the statistic framework functions
21256   * they will be moved to a statistics.c later */
21257  int status_counter_inc(server *srv, const char *s, size_t len) {
21258         data_integer *di = status_counter_get_counter(srv, s, len);
21259 @@ -429,7 +431,7 @@
21260         CLEAN(".connected");
21261         CLEAN(".load");
21262  
21263 -#undef CLEAN   
21264 +#undef CLEAN
21265  
21266  #define CLEAN(x) \
21267         fastcgi_status_copy_procname(b, host, NULL); \
21268 @@ -438,33 +440,32 @@
21269  
21270         CLEAN(".load");
21271  
21272 -#undef CLEAN   
21273 +#undef CLEAN
21274  
21275         return 0;
21276  }
21277  
21278  static handler_ctx * handler_ctx_init() {
21279         handler_ctx * hctx;
21280 -       
21281 +
21282         hctx = calloc(1, sizeof(*hctx));
21283         assert(hctx);
21284 -       
21285 +
21286         hctx->fde_ndx = -1;
21287 -       
21288 -       hctx->response_header = buffer_init();
21289 -       
21290 +
21291         hctx->request_id = 0;
21292         hctx->state = FCGI_STATE_INIT;
21293         hctx->proc = NULL;
21294 -       
21295 +
21296         hctx->fd = -1;
21297 -       
21298 +
21299         hctx->reconnects = 0;
21300         hctx->send_content_body = 1;
21301  
21302         hctx->rb = chunkqueue_init();
21303 +       hctx->http_rb = chunkqueue_init();
21304         hctx->wb = chunkqueue_init();
21305 -       
21306 +
21307         return hctx;
21308  }
21309  
21310 @@ -473,10 +474,9 @@
21311                 hctx->host->load--;
21312                 hctx->host = NULL;
21313         }
21314 -       
21315 -       buffer_free(hctx->response_header);
21316  
21317         chunkqueue_free(hctx->rb);
21318 +       chunkqueue_free(hctx->http_rb);
21319         chunkqueue_free(hctx->wb);
21320  
21321         free(hctx);
21322 @@ -488,21 +488,21 @@
21323         f = calloc(1, sizeof(*f));
21324         f->unixsocket = buffer_init();
21325         f->connection_name = buffer_init();
21326 -       
21327 +
21328         f->prev = NULL;
21329         f->next = NULL;
21330 -       
21331 +
21332         return f;
21333  }
21334  
21335  void fastcgi_process_free(fcgi_proc *f) {
21336         if (!f) return;
21337 -       
21338 +
21339         fastcgi_process_free(f->next);
21340 -       
21341 +
21342         buffer_free(f->unixsocket);
21343         buffer_free(f->connection_name);
21344 -       
21345 +
21346         free(f);
21347  }
21348  
21349 @@ -519,13 +519,13 @@
21350         f->bin_env = array_init();
21351         f->bin_env_copy = array_init();
21352         f->strip_request_uri = buffer_init();
21353 -       
21354 +
21355         return f;
21356  }
21357  
21358  void fastcgi_host_free(fcgi_extension_host *h) {
21359         if (!h) return;
21360 -       
21361 +
21362         buffer_free(h->id);
21363         buffer_free(h->host);
21364         buffer_free(h->unixsocket);
21365 @@ -534,49 +534,49 @@
21366         buffer_free(h->strip_request_uri);
21367         array_free(h->bin_env);
21368         array_free(h->bin_env_copy);
21369 -       
21370 +
21371         fastcgi_process_free(h->first);
21372         fastcgi_process_free(h->unused_procs);
21373 -       
21374 +
21375         free(h);
21376 -       
21377 +
21378  }
21379  
21380  fcgi_exts *fastcgi_extensions_init() {
21381         fcgi_exts *f;
21382  
21383         f = calloc(1, sizeof(*f));
21384 -       
21385 +
21386         return f;
21387  }
21388  
21389  void fastcgi_extensions_free(fcgi_exts *f) {
21390         size_t i;
21391 -       
21392 +
21393         if (!f) return;
21394 -       
21395 +
21396         for (i = 0; i < f->used; i++) {
21397                 fcgi_extension *fe;
21398                 size_t j;
21399 -               
21400 +
21401                 fe = f->exts[i];
21402 -               
21403 +
21404                 for (j = 0; j < fe->used; j++) {
21405                         fcgi_extension_host *h;
21406 -                       
21407 +
21408                         h = fe->hosts[j];
21409 -                       
21410 +
21411                         fastcgi_host_free(h);
21412                 }
21413 -               
21414 +
21415                 buffer_free(fe->key);
21416                 free(fe->hosts);
21417 -               
21418 +
21419                 free(fe);
21420         }
21421 -       
21422 +
21423         free(f->exts);
21424 -       
21425 +
21426         free(f);
21427  }
21428  
21429 @@ -625,24 +625,25 @@
21430                 assert(fe->hosts);
21431         }
21432  
21433 -       fe->hosts[fe->used++] = fh; 
21434 +       fe->hosts[fe->used++] = fh;
21435  
21436         return 0;
21437 -       
21438 +
21439  }
21440  
21441  INIT_FUNC(mod_fastcgi_init) {
21442         plugin_data *p;
21443 -       
21444 +
21445         p = calloc(1, sizeof(*p));
21446 -       
21447 +
21448         p->fcgi_env = buffer_init();
21449 -       
21450 +
21451         p->path = buffer_init();
21452 -       p->parse_response = buffer_init();
21453 +
21454 +       p->resp = http_response_init();
21455  
21456         p->statuskey = buffer_init();
21457 -       
21458 +
21459         return p;
21460  }
21461  
21462 @@ -650,81 +651,82 @@
21463  FREE_FUNC(mod_fastcgi_free) {
21464         plugin_data *p = p_d;
21465         buffer_uint *r = &(p->fcgi_request_id);
21466 -       
21467 +
21468         UNUSED(srv);
21469  
21470         if (r->ptr) free(r->ptr);
21471 -       
21472 +
21473         buffer_free(p->fcgi_env);
21474         buffer_free(p->path);
21475 -       buffer_free(p->parse_response);
21476         buffer_free(p->statuskey);
21477 -       
21478 +
21479 +       http_response_free(p->resp);
21480 +
21481         if (p->config_storage) {
21482                 size_t i, j, n;
21483                 for (i = 0; i < srv->config_context->used; i++) {
21484                         plugin_config *s = p->config_storage[i];
21485                         fcgi_exts *exts;
21486 -                       
21487 +
21488                         if (!s) continue;
21489 -                       
21490 +
21491                         exts = s->exts;
21492  
21493                         for (j = 0; j < exts->used; j++) {
21494                                 fcgi_extension *ex;
21495 -                               
21496 +
21497                                 ex = exts->exts[j];
21498 -                               
21499 +
21500                                 for (n = 0; n < ex->used; n++) {
21501                                         fcgi_proc *proc;
21502                                         fcgi_extension_host *host;
21503 -                                       
21504 +
21505                                         host = ex->hosts[n];
21506 -                                       
21507 +
21508                                         for (proc = host->first; proc; proc = proc->next) {
21509                                                 if (proc->pid != 0) kill(proc->pid, SIGTERM);
21510 -                                               
21511 -                                               if (proc->is_local && 
21512 +
21513 +                                               if (proc->is_local &&
21514                                                     !buffer_is_empty(proc->unixsocket)) {
21515                                                         unlink(proc->unixsocket->ptr);
21516                                                 }
21517                                         }
21518 -                                       
21519 +
21520                                         for (proc = host->unused_procs; proc; proc = proc->next) {
21521                                                 if (proc->pid != 0) kill(proc->pid, SIGTERM);
21522 -                                               
21523 -                                               if (proc->is_local && 
21524 +
21525 +                                               if (proc->is_local &&
21526                                                     !buffer_is_empty(proc->unixsocket)) {
21527                                                         unlink(proc->unixsocket->ptr);
21528                                                 }
21529                                         }
21530                                 }
21531                         }
21532 -                       
21533 +
21534                         fastcgi_extensions_free(s->exts);
21535                         array_free(s->ext_mapping);
21536 -                       
21537 +
21538                         free(s);
21539                 }
21540                 free(p->config_storage);
21541         }
21542 -       
21543 +
21544         free(p);
21545 -       
21546 +
21547         return HANDLER_GO_ON;
21548  }
21549  
21550  static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
21551         char *dst;
21552 -       
21553 +
21554         if (!key || !val) return -1;
21555 -       
21556 +
21557         dst = malloc(key_len + val_len + 3);
21558         memcpy(dst, key, key_len);
21559         dst[key_len] = '=';
21560         /* add the \0 from the value */
21561         memcpy(dst + key_len + 1, val, val_len + 1);
21562 -       
21563 +
21564         if (env->size == 0) {
21565                 env->size = 16;
21566                 env->ptr = malloc(env->size * sizeof(*env->ptr));
21567 @@ -732,9 +734,9 @@
21568                 env->size += 16;
21569                 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
21570         }
21571 -       
21572 +
21573         env->ptr[env->used++] = dst;
21574 -       
21575 +
21576         return 0;
21577  }
21578  
21579 @@ -753,15 +755,15 @@
21580                         if (env->size == 0) {
21581                                 env->size = 16;
21582                                 env->ptr = malloc(env->size * sizeof(*env->ptr));
21583 -                       } else if (env->size == env->used) { 
21584 +                       } else if (env->size == env->used) {
21585                                 env->size += 16;
21586                                 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
21587                         }
21588 -                       
21589 +
21590                         b->ptr[i] = '\0';
21591  
21592                         env->ptr[env->used++] = start;
21593 -                       
21594 +
21595                         start = b->ptr + i + 1;
21596                         break;
21597                 default:
21598 @@ -794,7 +796,7 @@
21599         return 0;
21600  }
21601  
21602 -static int fcgi_spawn_connection(server *srv, 
21603 +static int fcgi_spawn_connection(server *srv,
21604                                  plugin_data *p,
21605                                  fcgi_extension_host *host,
21606                                  fcgi_proc *proc) {
21607 @@ -806,31 +808,27 @@
21608  #endif
21609         struct sockaddr_in fcgi_addr_in;
21610         struct sockaddr *fcgi_addr;
21611 -       
21612 +
21613         socklen_t servlen;
21614 -       
21615 +
21616  #ifndef HAVE_FORK
21617         return -1;
21618  #endif
21619 -       
21620 +
21621         if (p->conf.debug) {
21622                 log_error_write(srv, __FILE__, __LINE__, "sdb",
21623                                 "new proc, socket:", proc->port, proc->unixsocket);
21624         }
21625 -               
21626 +
21627         if (!buffer_is_empty(proc->unixsocket)) {
21628                 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
21629 -               
21630 +
21631  #ifdef HAVE_SYS_UN_H
21632                 fcgi_addr_un.sun_family = AF_UNIX;
21633                 strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
21634 -               
21635 -#ifdef SUN_LEN
21636 +
21637                 servlen = SUN_LEN(&fcgi_addr_un);
21638 -#else
21639 -               /* stevens says: */
21640 -               servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
21641 -#endif
21642 +
21643                 socket_type = AF_UNIX;
21644                 fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
21645  
21646 @@ -844,108 +842,108 @@
21647  #endif
21648         } else {
21649                 fcgi_addr_in.sin_family = AF_INET;
21650 -               
21651 +
21652                 if (buffer_is_empty(host->host)) {
21653                         fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
21654                 } else {
21655                         struct hostent *he;
21656 -                       
21657 +
21658                         /* set a usefull default */
21659                         fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
21660 -                       
21661 -                       
21662 +
21663 +
21664                         if (NULL == (he = gethostbyname(host->host->ptr))) {
21665 -                               log_error_write(srv, __FILE__, __LINE__, 
21666 -                                               "sdb", "gethostbyname failed: ", 
21667 +                               log_error_write(srv, __FILE__, __LINE__,
21668 +                                               "sdb", "gethostbyname failed: ",
21669                                                 h_errno, host->host);
21670                                 return -1;
21671                         }
21672 -                       
21673 +
21674                         if (he->h_addrtype != AF_INET) {
21675                                 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
21676                                 return -1;
21677                         }
21678 -                       
21679 +
21680                         if (he->h_length != sizeof(struct in_addr)) {
21681                                 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
21682                                 return -1;
21683                         }
21684 -                       
21685 +
21686                         memcpy(&(fcgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
21687 -                       
21688 +
21689                 }
21690                 fcgi_addr_in.sin_port = htons(proc->port);
21691                 servlen = sizeof(fcgi_addr_in);
21692 -               
21693 +
21694                 socket_type = AF_INET;
21695                 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
21696 -               
21697 +
21698                 buffer_copy_string(proc->connection_name, "tcp:");
21699                 buffer_append_string_buffer(proc->connection_name, host->host);
21700                 buffer_append_string(proc->connection_name, ":");
21701                 buffer_append_long(proc->connection_name, proc->port);
21702         }
21703 -       
21704 +
21705         if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
21706 -               log_error_write(srv, __FILE__, __LINE__, "ss", 
21707 +               log_error_write(srv, __FILE__, __LINE__, "ss",
21708                                 "failed:", strerror(errno));
21709                 return -1;
21710         }
21711 -       
21712 +
21713         if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
21714                 /* server is not up, spawn in  */
21715                 pid_t child;
21716                 int val;
21717 -               
21718 -               if (errno != ENOENT && 
21719 +
21720 +               if (errno != ENOENT &&
21721                     !buffer_is_empty(proc->unixsocket)) {
21722                         unlink(proc->unixsocket->ptr);
21723                 }
21724 -               
21725 +
21726                 close(fcgi_fd);
21727 -               
21728 +
21729                 /* reopen socket */
21730                 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
21731 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
21732 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
21733                                 "socket failed:", strerror(errno));
21734                         return -1;
21735                 }
21736 -               
21737 +
21738                 val = 1;
21739                 if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
21740 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
21741 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
21742                                         "socketsockopt failed:", strerror(errno));
21743                         return -1;
21744                 }
21745 -               
21746 +
21747                 /* create socket */
21748                 if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
21749 -                       log_error_write(srv, __FILE__, __LINE__, "sbs", 
21750 -                               "bind failed for:", 
21751 +                       log_error_write(srv, __FILE__, __LINE__, "sbs",
21752 +                               "bind failed for:",
21753                                 proc->connection_name,
21754                                 strerror(errno));
21755                         return -1;
21756                 }
21757 -               
21758 +
21759                 if (-1 == listen(fcgi_fd, 1024)) {
21760 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
21761 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
21762                                 "listen failed:", strerror(errno));
21763                         return -1;
21764                 }
21765 -               
21766 -#ifdef HAVE_FORK       
21767 +
21768 +#ifndef _WIN32
21769                 switch ((child = fork())) {
21770                 case 0: {
21771                         size_t i = 0;
21772                         char *c;
21773                         char_array env;
21774                         char_array arg;
21775 -                       
21776 +
21777                         /* create environment */
21778                         env.ptr = NULL;
21779                         env.size = 0;
21780                         env.used = 0;
21781 -                       
21782 +
21783                         arg.ptr = NULL;
21784                         arg.size = 0;
21785                         arg.used = 0;
21786 @@ -955,18 +953,18 @@
21787                                 dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
21788                                 close(fcgi_fd);
21789                         }
21790 -                       
21791 +
21792                         /* we don't need the client socket */
21793                         for (i = 3; i < 256; i++) {
21794                                 close(i);
21795                         }
21796 -                       
21797 +
21798                         /* build clean environment */
21799                         if (host->bin_env_copy->used) {
21800                                 for (i = 0; i < host->bin_env_copy->used; i++) {
21801                                         data_string *ds = (data_string *)host->bin_env_copy->data[i];
21802                                         char *ge;
21803 -                                       
21804 +
21805                                         if (NULL != (ge = getenv(ds->value->ptr))) {
21806                                                 env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
21807                                         }
21808 @@ -974,39 +972,39 @@
21809                         } else {
21810                                 for (i = 0; environ[i]; i++) {
21811                                         char *eq;
21812 -                                       
21813 +
21814                                         if (NULL != (eq = strchr(environ[i], '='))) {
21815                                                 env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
21816                                         }
21817                                 }
21818                         }
21819 -                       
21820 +
21821                         /* create environment */
21822                         for (i = 0; i < host->bin_env->used; i++) {
21823                                 data_string *ds = (data_string *)host->bin_env->data[i];
21824 -                               
21825 +
21826                                 env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
21827                         }
21828 -                       
21829 +
21830                         for (i = 0; i < env.used; i++) {
21831                                 /* search for PHP_FCGI_CHILDREN */
21832                                 if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
21833                         }
21834 -                       
21835 +
21836                         /* not found, add a default */
21837                         if (i == env.used) {
21838                                 env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
21839                         }
21840 -                       
21841 +
21842                         env.ptr[env.used] = NULL;
21843  
21844                         parse_binpath(&arg, host->bin_path);
21845 -                       
21846 +
21847                         /* chdir into the base of the bin-path,
21848                          * search for the last / */
21849                         if (NULL != (c = strrchr(arg.ptr[0], '/'))) {
21850                                 *c = '\0';
21851 -                       
21852 +
21853                                 /* change to the physical directory */
21854                                 if (-1 == chdir(arg.ptr[0])) {
21855                                         *c = '/';
21856 @@ -1018,12 +1016,12 @@
21857  
21858                         /* exec the cgi */
21859                         execve(arg.ptr[0], arg.ptr, env.ptr);
21860 -                       
21861 -                       log_error_write(srv, __FILE__, __LINE__, "sbs", 
21862 +
21863 +                       log_error_write(srv, __FILE__, __LINE__, "sbs",
21864                                         "execve failed for:", host->bin_path, strerror(errno));
21865 -                       
21866 +
21867                         exit(errno);
21868 -                       
21869 +
21870                         break;
21871                 }
21872                 case -1:
21873 @@ -1031,17 +1029,17 @@
21874                         break;
21875                 default:
21876                         /* father */
21877 -                       
21878 +
21879                         /* wait */
21880                         select(0, NULL, NULL, NULL, &tv);
21881 -                       
21882 +
21883                         switch (waitpid(child, &status, WNOHANG)) {
21884                         case 0:
21885                                 /* child still running after timeout, good */
21886                                 break;
21887                         case -1:
21888                                 /* no PID found ? should never happen */
21889 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
21890 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
21891                                                 "pid not found:", strerror(errno));
21892                                 return -1;
21893                         default:
21894 @@ -1049,10 +1047,10 @@
21895                                                 "the fastcgi-backend", host->bin_path, "failed to start:");
21896                                 /* the child should not terminate at all */
21897                                 if (WIFEXITED(status)) {
21898 -                                       log_error_write(srv, __FILE__, __LINE__, "sdb", 
21899 -                                                       "child exited with status", 
21900 +                                       log_error_write(srv, __FILE__, __LINE__, "sdb",
21901 +                                                       "child exited with status",
21902                                                         WEXITSTATUS(status), host->bin_path);
21903 -                                       log_error_write(srv, __FILE__, __LINE__, "s", 
21904 +                                       log_error_write(srv, __FILE__, __LINE__, "s",
21905                                                         "if you try do run PHP as FastCGI backend make sure you use the FastCGI enabled version.\n"
21906                                                         "You can find out if it is the right one by executing 'php -v' and it should display '(cgi-fcgi)' "
21907                                                         "in the output, NOT (cgi) NOR (cli)\n"
21908 @@ -1060,8 +1058,8 @@
21909                                         log_error_write(srv, __FILE__, __LINE__, "s",
21910                                                         "If this is PHP on Gentoo add fastcgi to the USE flags");
21911                                 } else if (WIFSIGNALED(status)) {
21912 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
21913 -                                                       "terminated by signal:", 
21914 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
21915 +                                                       "terminated by signal:",
21916                                                         WTERMSIG(status));
21917  
21918                                         if (WTERMSIG(status) == 11) {
21919 @@ -1071,8 +1069,8 @@
21920                                                                 "If this is PHP try to remove the byte-code caches for now and try again.");
21921                                         }
21922                                 } else {
21923 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
21924 -                                                       "child died somehow:", 
21925 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
21926 +                                                       "child died somehow:",
21927                                                         status);
21928                                 }
21929                                 return -1;
21930 @@ -1082,26 +1080,26 @@
21931                         proc->pid = child;
21932                         proc->last_used = srv->cur_ts;
21933                         proc->is_local = 1;
21934 -                                               
21935 +
21936                         break;
21937                 }
21938  #endif
21939         } else {
21940                 proc->is_local = 0;
21941                 proc->pid = 0;
21942 -               
21943 +
21944                 if (p->conf.debug) {
21945                         log_error_write(srv, __FILE__, __LINE__, "sb",
21946                                         "(debug) socket is already used, won't spawn:",
21947                                         proc->connection_name);
21948                 }
21949         }
21950 -       
21951 +
21952         proc->state = PROC_STATE_RUNNING;
21953         host->active_procs++;
21954 -       
21955 +
21956         close(fcgi_fd);
21957 -       
21958 +
21959         return 0;
21960  }
21961  
21962 @@ -1111,93 +1109,93 @@
21963         data_unset *du;
21964         size_t i = 0;
21965         buffer *fcgi_mode = buffer_init();
21966 -       
21967 -       config_values_t cv[] = { 
21968 +
21969 +       config_values_t cv[] = {
21970                 { "fastcgi.server",              NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
21971                 { "fastcgi.debug",               NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
21972                 { "fastcgi.map-extensions",      NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
21973                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
21974         };
21975 -       
21976 +
21977         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
21978 -       
21979 +
21980         for (i = 0; i < srv->config_context->used; i++) {
21981                 plugin_config *s;
21982                 array *ca;
21983 -               
21984 +
21985                 s = malloc(sizeof(plugin_config));
21986                 s->exts          = fastcgi_extensions_init();
21987                 s->debug         = 0;
21988                 s->ext_mapping   = array_init();
21989 -               
21990 +
21991                 cv[0].destination = s->exts;
21992                 cv[1].destination = &(s->debug);
21993                 cv[2].destination = s->ext_mapping;
21994 -               
21995 +
21996                 p->config_storage[i] = s;
21997                 ca = ((data_config *)srv->config_context->data[i])->value;
21998 -       
21999 +
22000                 if (0 != config_insert_values_global(srv, ca, cv)) {
22001                         return HANDLER_ERROR;
22002                 }
22003 -               
22004 -               /* 
22005 +
22006 +               /*
22007                  * <key> = ( ... )
22008                  */
22009 -               
22010 +
22011                 if (NULL != (du = array_get_element(ca, "fastcgi.server"))) {
22012                         size_t j;
22013                         data_array *da = (data_array *)du;
22014 -                       
22015 +
22016                         if (du->type != TYPE_ARRAY) {
22017 -                               log_error_write(srv, __FILE__, __LINE__, "sss", 
22018 +                               log_error_write(srv, __FILE__, __LINE__, "sss",
22019                                                 "unexpected type for key: ", "fastcgi.server", "array of strings");
22020 -                               
22021 +
22022                                 return HANDLER_ERROR;
22023                         }
22024 -                       
22025 -                       
22026 -                       /* 
22027 -                        * fastcgi.server = ( "<ext>" => ( ... ), 
22028 +
22029 +
22030 +                       /*
22031 +                        * fastcgi.server = ( "<ext>" => ( ... ),
22032                          *                    "<ext>" => ( ... ) )
22033                          */
22034 -                       
22035 +
22036                         for (j = 0; j < da->value->used; j++) {
22037                                 size_t n;
22038                                 data_array *da_ext = (data_array *)da->value->data[j];
22039 -                               
22040 +
22041                                 if (da->value->data[j]->type != TYPE_ARRAY) {
22042 -                                       log_error_write(srv, __FILE__, __LINE__, "sssbs", 
22043 -                                                       "unexpected type for key: ", "fastcgi.server", 
22044 +                                       log_error_write(srv, __FILE__, __LINE__, "sssbs",
22045 +                                                       "unexpected type for key: ", "fastcgi.server",
22046                                                         "[", da->value->data[j]->key, "](string)");
22047 -                                       
22048 +
22049                                         return HANDLER_ERROR;
22050                                 }
22051 -                               
22052 -                               /* 
22053 -                                * da_ext->key == name of the extension 
22054 +
22055 +                               /*
22056 +                                * da_ext->key == name of the extension
22057                                  */
22058 -                               
22059 -                               /* 
22060 -                                * fastcgi.server = ( "<ext>" => 
22061 -                                *                     ( "<host>" => ( ... ), 
22062 +
22063 +                               /*
22064 +                                * fastcgi.server = ( "<ext>" =>
22065 +                                *                     ( "<host>" => ( ... ),
22066                                  *                       "<host>" => ( ... )
22067 -                                *                     ), 
22068 +                                *                     ),
22069                                  *                    "<ext>" => ... )
22070                                  */
22071 -                                       
22072 +
22073                                 for (n = 0; n < da_ext->value->used; n++) {
22074                                         data_array *da_host = (data_array *)da_ext->value->data[n];
22075 -                                       
22076 +
22077                                         fcgi_extension_host *host;
22078 -                                       
22079 -                                       config_values_t fcv[] = { 
22080 +
22081 +                                       config_values_t fcv[] = {
22082                                                 { "host",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
22083                                                 { "docroot",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
22084                                                 { "mode",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
22085                                                 { "socket",            NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 3 */
22086                                                 { "bin-path",          NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 4 */
22087 -                                               
22088 +
22089                                                 { "check-local",       NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },      /* 5 */
22090                                                 { "port",              NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 6 */
22091                                                 { "min-procs-not-working",         NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 7 this is broken for now */
22092 @@ -1205,28 +1203,28 @@
22093                                                 { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 9 */
22094                                                 { "idle-timeout",      NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 10 */
22095                                                 { "disable-time",      NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 11 */
22096 -                                               
22097 +
22098                                                 { "bin-environment",   NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },        /* 12 */
22099                                                 { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },     /* 13 */
22100 -                                               
22101 +
22102                                                 { "broken-scriptfilename", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },  /* 14 */
22103                                                 { "allow-x-send-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },      /* 15 */
22104                                                 { "strip-request-uri",  NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },      /* 16 */
22105 -                                               
22106 +
22107                                                 { NULL,                NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
22108                                         };
22109 -                                       
22110 +
22111                                         if (da_host->type != TYPE_ARRAY) {
22112 -                                               log_error_write(srv, __FILE__, __LINE__, "ssSBS", 
22113 -                                                               "unexpected type for key:", 
22114 -                                                               "fastcgi.server", 
22115 +                                               log_error_write(srv, __FILE__, __LINE__, "ssSBS",
22116 +                                                               "unexpected type for key:",
22117 +                                                               "fastcgi.server",
22118                                                                 "[", da_host->key, "](string)");
22119 -                                               
22120 +
22121                                                 return HANDLER_ERROR;
22122                                         }
22123 -                                       
22124 +
22125                                         host = fastcgi_host_init();
22126 -                                       
22127 +
22128                                         buffer_copy_string_buffer(host->id, da_host->key);
22129  
22130                                         host->check_local  = 1;
22131 @@ -1238,13 +1236,13 @@
22132                                         host->disable_time = 60;
22133                                         host->break_scriptfilename_for_php = 0;
22134                                         host->allow_xsendfile = 0; /* handle X-LIGHTTPD-send-file */
22135 -                                       
22136 +
22137                                         fcv[0].destination = host->host;
22138                                         fcv[1].destination = host->docroot;
22139                                         fcv[2].destination = fcgi_mode;
22140                                         fcv[3].destination = host->unixsocket;
22141                                         fcv[4].destination = host->bin_path;
22142 -                                       
22143 +
22144                                         fcv[5].destination = &(host->check_local);
22145                                         fcv[6].destination = &(host->port);
22146                                         fcv[7].destination = &(host->min_procs);
22147 @@ -1252,35 +1250,35 @@
22148                                         fcv[9].destination = &(host->max_load_per_proc);
22149                                         fcv[10].destination = &(host->idle_timeout);
22150                                         fcv[11].destination = &(host->disable_time);
22151 -                                       
22152 +
22153                                         fcv[12].destination = host->bin_env;
22154                                         fcv[13].destination = host->bin_env_copy;
22155                                         fcv[14].destination = &(host->break_scriptfilename_for_php);
22156                                         fcv[15].destination = &(host->allow_xsendfile);
22157                                         fcv[16].destination = host->strip_request_uri;
22158 -                                       
22159 +
22160                                         if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
22161                                                 return HANDLER_ERROR;
22162                                         }
22163 -                                                       
22164 -                                       if ((!buffer_is_empty(host->host) || host->port) && 
22165 +
22166 +                                       if ((!buffer_is_empty(host->host) || host->port) &&
22167                                             !buffer_is_empty(host->unixsocket)) {
22168 -                                               log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", 
22169 +                                               log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
22170                                                                 "either host/port or socket have to be set in:",
22171 -                                                               da->key, "= (", 
22172 +                                                               da->key, "= (",
22173                                                                 da_ext->key, " => (",
22174                                                                 da_host->key, " ( ...");
22175  
22176                                                 return HANDLER_ERROR;
22177                                         }
22178 -                                       
22179 +
22180                                         if (!buffer_is_empty(host->unixsocket)) {
22181                                                 /* unix domain socket */
22182 -                                               
22183 +
22184                                                 if (host->unixsocket->used > UNIX_PATH_MAX - 2) {
22185 -                                                       log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", 
22186 +                                                       log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
22187                                                                         "unixsocket is too long in:",
22188 -                                                                       da->key, "= (", 
22189 +                                                                       da->key, "= (",
22190                                                                         da_ext->key, " => (",
22191                                                                         da_host->key, " ( ...");
22192  
22193 @@ -1288,37 +1286,37 @@
22194                                                 }
22195                                         } else {
22196                                                 /* tcp/ip */
22197 -                                               
22198 -                                               if (buffer_is_empty(host->host) && 
22199 +
22200 +                                               if (buffer_is_empty(host->host) &&
22201                                                     buffer_is_empty(host->bin_path)) {
22202 -                                                       log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", 
22203 +                                                       log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
22204                                                                         "host or binpath have to be set in:",
22205 -                                                                       da->key, "= (", 
22206 +                                                                       da->key, "= (",
22207                                                                         da_ext->key, " => (",
22208                                                                         da_host->key, " ( ...");
22209 -                                                       
22210 +
22211                                                         return HANDLER_ERROR;
22212                                                 } else if (host->port == 0) {
22213 -                                                       log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", 
22214 +                                                       log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
22215                                                                         "port has to be set in:",
22216 -                                                                       da->key, "= (", 
22217 +                                                                       da->key, "= (",
22218                                                                         da_ext->key, " => (",
22219                                                                         da_host->key, " ( ...");
22220  
22221                                                         return HANDLER_ERROR;
22222                                                 }
22223                                         }
22224 -                                               
22225 -                                       if (!buffer_is_empty(host->bin_path)) { 
22226 +
22227 +                                       if (!buffer_is_empty(host->bin_path)) {
22228                                                 /* a local socket + self spawning */
22229                                                 size_t pno;
22230  
22231                                                 /* HACK:  just to make sure the adaptive spawing is disabled */
22232                                                 host->min_procs = host->max_procs;
22233 -                                               
22234 +
22235                                                 if (host->min_procs > host->max_procs) host->max_procs = host->min_procs;
22236                                                 if (host->max_load_per_proc < 1) host->max_load_per_proc = 0;
22237 -                                               
22238 +
22239                                                 if (s->debug) {
22240                                                         log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd",
22241                                                                         "--- fastcgi spawning local",
22242 @@ -1328,7 +1326,7 @@
22243                                                                         "\n\tmin-procs:", host->min_procs,
22244                                                                         "\n\tmax-procs:", host->max_procs);
22245                                                 }
22246 -                                               
22247 +
22248                                                 for (pno = 0; pno < host->min_procs; pno++) {
22249                                                         fcgi_proc *proc;
22250  
22251 @@ -1343,7 +1341,7 @@
22252                                                                 buffer_append_string(proc->unixsocket, "-");
22253                                                                 buffer_append_long(proc->unixsocket, pno);
22254                                                         }
22255 -                                                       
22256 +
22257                                                         if (s->debug) {
22258                                                                 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
22259                                                                                 "--- fastcgi spawning",
22260 @@ -1351,7 +1349,7 @@
22261                                                                                 "\n\tsocket", host->unixsocket,
22262                                                                                 "\n\tcurrent:", pno, "/", host->min_procs);
22263                                                         }
22264 -                                                       
22265 +
22266                                                         if (fcgi_spawn_connection(srv, p, host, proc)) {
22267                                                                 log_error_write(srv, __FILE__, __LINE__, "s",
22268                                                                                 "[ERROR]: spawning fcgi failed.");
22269 @@ -1359,35 +1357,35 @@
22270                                                         }
22271  
22272                                                         fastcgi_status_init(srv, p->statuskey, host, proc);
22273 -                                                       
22274 +
22275                                                         proc->next = host->first;
22276                                                         if (host->first)        host->first->prev = proc;
22277 -                                                       
22278 +
22279                                                         host->first = proc;
22280                                                 }
22281                                         } else {
22282                                                 fcgi_proc *proc;
22283 -                                               
22284 +
22285                                                 proc = fastcgi_process_init();
22286                                                 proc->id = host->num_procs++;
22287                                                 host->max_id++;
22288                                                 host->active_procs++;
22289                                                 proc->state = PROC_STATE_RUNNING;
22290 -                                               
22291 +
22292                                                 if (buffer_is_empty(host->unixsocket)) {
22293                                                         proc->port = host->port;
22294                                                 } else {
22295                                                         buffer_copy_string_buffer(proc->unixsocket, host->unixsocket);
22296                                                 }
22297 -                                               
22298 +
22299                                                 fastcgi_status_init(srv, p->statuskey, host, proc);
22300  
22301                                                 host->first = proc;
22302 -                                               
22303 +
22304                                                 host->min_procs = 1;
22305                                                 host->max_procs = 1;
22306                                         }
22307 -                                       
22308 +
22309                                         if (!buffer_is_empty(fcgi_mode)) {
22310                                                 if (strcmp(fcgi_mode->ptr, "responder") == 0) {
22311                                                         host->mode = FCGI_RESPONDER;
22312 @@ -1411,16 +1409,16 @@
22313                         }
22314                 }
22315         }
22316 -       
22317 +
22318         buffer_free(fcgi_mode);
22319 -       
22320 +
22321         return HANDLER_GO_ON;
22322  }
22323  
22324  static int fcgi_set_state(server *srv, handler_ctx *hctx, fcgi_connection_state_t state) {
22325         hctx->state = state;
22326         hctx->state_timestamp = srv->cur_ts;
22327 -       
22328 +
22329         return 0;
22330  }
22331  
22332 @@ -1429,13 +1427,13 @@
22333         size_t m = 0;
22334         size_t i;
22335         buffer_uint *r = &(p->fcgi_request_id);
22336 -       
22337 +
22338         UNUSED(srv);
22339  
22340         for (i = 0; i < r->used; i++) {
22341                 if (r->ptr[i] > m) m = r->ptr[i];
22342         }
22343 -       
22344 +
22345         if (r->size == 0) {
22346                 r->size = 16;
22347                 r->ptr = malloc(sizeof(*r->ptr) * r->size);
22348 @@ -1443,54 +1441,54 @@
22349                 r->size += 16;
22350                 r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
22351         }
22352 -       
22353 +
22354         r->ptr[r->used++] = ++m;
22355 -       
22356 +
22357         return m;
22358  }
22359  
22360  static int fcgi_requestid_del(server *srv, plugin_data *p, size_t request_id) {
22361         size_t i;
22362         buffer_uint *r = &(p->fcgi_request_id);
22363 -       
22364 +
22365         UNUSED(srv);
22366  
22367         for (i = 0; i < r->used; i++) {
22368                 if (r->ptr[i] == request_id) break;
22369         }
22370 -       
22371 +
22372         if (i != r->used) {
22373                 /* found */
22374 -               
22375 +
22376                 if (i != r->used - 1) {
22377                         r->ptr[i] = r->ptr[r->used - 1];
22378                 }
22379                 r->used--;
22380         }
22381 -       
22382 +
22383         return 0;
22384  }
22385  void fcgi_connection_close(server *srv, handler_ctx *hctx) {
22386         plugin_data *p;
22387         connection  *con;
22388 -       
22389 +
22390         if (NULL == hctx) return;
22391 -       
22392 +
22393         p    = hctx->plugin_data;
22394         con  = hctx->remote_conn;
22395 -       
22396 +
22397         if (con->mode != p->id) {
22398                 WP();
22399                 return;
22400         }
22401 -       
22402 +
22403         if (hctx->fd != -1) {
22404                 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
22405                 fdevent_unregister(srv->ev, hctx->fd);
22406                 close(hctx->fd);
22407                 srv->cur_fds--;
22408         }
22409 -       
22410 +
22411         if (hctx->request_id != 0) {
22412                 fcgi_requestid_del(srv, p, hctx->request_id);
22413         }
22414 @@ -1499,7 +1497,7 @@
22415                 if (hctx->got_proc) {
22416                         /* after the connect the process gets a load */
22417                         hctx->proc->load--;
22418 -                       
22419 +
22420                         status_counter_dec(srv, CONST_STR_LEN("fastcgi.active-requests"));
22421  
22422                         fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
22423 @@ -1509,39 +1507,39 @@
22424  
22425                         if (p->conf.debug) {
22426                                 log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
22427 -                                               "released proc:", 
22428 -                                               "pid:", hctx->proc->pid, 
22429 -                                               "socket:", hctx->proc->connection_name, 
22430 +                                               "released proc:",
22431 +                                               "pid:", hctx->proc->pid,
22432 +                                               "socket:", hctx->proc->connection_name,
22433                                                 "load:", hctx->proc->load);
22434                         }
22435                 }
22436         }
22437  
22438 -       
22439 +
22440         handler_ctx_free(hctx);
22441 -       con->plugin_ctx[p->id] = NULL;  
22442 +       con->plugin_ctx[p->id] = NULL;
22443  }
22444  
22445  static int fcgi_reconnect(server *srv, handler_ctx *hctx) {
22446         plugin_data *p    = hctx->plugin_data;
22447 -       
22448 -       /* child died 
22449 -        * 
22450 -        * 1. 
22451 -        * 
22452 +
22453 +       /* child died
22454 +        *
22455 +        * 1.
22456 +        *
22457          * connect was ok, connection was accepted
22458          * but the php accept loop checks after the accept if it should die or not.
22459 -        * 
22460 -        * if yes we can only detect it at a write() 
22461 -        * 
22462 +        *
22463 +        * if yes we can only detect it at a write()
22464 +        *
22465          * next step is resetting this attemp and setup a connection again
22466 -        * 
22467 +        *
22468          * if we have more then 5 reconnects for the same request, die
22469 -        * 
22470 -        * 2. 
22471 -        * 
22472 +        *
22473 +        * 2.
22474 +        *
22475          * we have a connection but the child died by some other reason
22476 -        * 
22477 +        *
22478          */
22479  
22480         if (hctx->fd != -1) {
22481 @@ -1551,59 +1549,59 @@
22482                 srv->cur_fds--;
22483                 hctx->fd = -1;
22484         }
22485 -       
22486 +
22487         fcgi_requestid_del(srv, p, hctx->request_id);
22488 -       
22489 +
22490         fcgi_set_state(srv, hctx, FCGI_STATE_INIT);
22491 -       
22492 +
22493         hctx->request_id = 0;
22494         hctx->reconnects++;
22495 -       
22496 +
22497         if (p->conf.debug > 2) {
22498                 if (hctx->proc) {
22499                         log_error_write(srv, __FILE__, __LINE__, "sdb",
22500 -                                       "release proc for reconnect:", 
22501 +                                       "release proc for reconnect:",
22502                                         hctx->proc->pid, hctx->proc->connection_name);
22503                 } else {
22504                         log_error_write(srv, __FILE__, __LINE__, "sb",
22505 -                                       "release proc for reconnect:", 
22506 +                                       "release proc for reconnect:",
22507                                         hctx->host->unixsocket);
22508                 }
22509         }
22510  
22511 -       if (hctx->proc && hctx->got_proc) {     
22512 +       if (hctx->proc && hctx->got_proc) {
22513                 hctx->proc->load--;
22514         }
22515  
22516         /* perhaps another host gives us more luck */
22517         hctx->host->load--;
22518         hctx->host = NULL;
22519 -       
22520 +
22521         return 0;
22522  }
22523  
22524  
22525  static handler_t fcgi_connection_reset(server *srv, connection *con, void *p_d) {
22526         plugin_data *p = p_d;
22527 -       
22528 +
22529         fcgi_connection_close(srv, con->plugin_ctx[p->id]);
22530 -       
22531 +
22532         return HANDLER_GO_ON;
22533  }
22534  
22535  
22536  static int fcgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
22537         size_t len;
22538 -       
22539 +
22540         if (!key || !val) return -1;
22541 -       
22542 +
22543         len = key_len + val_len;
22544 -       
22545 +
22546         len += key_len > 127 ? 4 : 1;
22547         len += val_len > 127 ? 4 : 1;
22548 -       
22549 +
22550         buffer_prepare_append(env, len);
22551 -       
22552 +
22553         if (key_len > 127) {
22554                 env->ptr[env->used++] = ((key_len >> 24) & 0xff) | 0x80;
22555                 env->ptr[env->used++] = (key_len >> 16) & 0xff;
22556 @@ -1612,7 +1610,7 @@
22557         } else {
22558                 env->ptr[env->used++] = (key_len >> 0) & 0xff;
22559         }
22560 -       
22561 +
22562         if (val_len > 127) {
22563                 env->ptr[env->used++] = ((val_len >> 24) & 0xff) | 0x80;
22564                 env->ptr[env->used++] = (val_len >> 16) & 0xff;
22565 @@ -1621,12 +1619,12 @@
22566         } else {
22567                 env->ptr[env->used++] = (val_len >> 0) & 0xff;
22568         }
22569 -       
22570 +
22571         memcpy(env->ptr + env->used, key, key_len);
22572         env->used += key_len;
22573         memcpy(env->ptr + env->used, val, val_len);
22574         env->used += val_len;
22575 -       
22576 +
22577         return 0;
22578  }
22579  
22580 @@ -1639,11 +1637,11 @@
22581         header->contentLengthB1 = (contentLength >> 8) & 0xff;
22582         header->paddingLength = paddingLength;
22583         header->reserved = 0;
22584 -       
22585 +
22586         return 0;
22587  }
22588  /**
22589 - * 
22590 + *
22591   * returns
22592   *   -1 error
22593   *    0 connected
22594 @@ -1665,26 +1663,23 @@
22595         struct sockaddr_un fcgi_addr_un;
22596  #endif
22597         socklen_t servlen;
22598 -       
22599 +
22600         fcgi_extension_host *host = hctx->host;
22601         fcgi_proc *proc   = hctx->proc;
22602         int fcgi_fd       = hctx->fd;
22603 -       
22604 +
22605         memset(&fcgi_addr, 0, sizeof(fcgi_addr));
22606 -       
22607 +
22608         if (!buffer_is_empty(proc->unixsocket)) {
22609  #ifdef HAVE_SYS_UN_H
22610                 /* use the unix domain socket */
22611                 fcgi_addr_un.sun_family = AF_UNIX;
22612                 strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
22613 -#ifdef SUN_LEN
22614 +
22615                 servlen = SUN_LEN(&fcgi_addr_un);
22616 -#else
22617 -               /* stevens says: */
22618 -               servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
22619 -#endif
22620 +
22621                 fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
22622 -       
22623 +
22624                 if (buffer_is_empty(proc->connection_name)) {
22625                         /* on remote spawing we have to set the connection-name now */
22626                         buffer_copy_string(proc->connection_name, "unix:");
22627 @@ -1695,16 +1690,18 @@
22628  #endif
22629         } else {
22630                 fcgi_addr_in.sin_family = AF_INET;
22631 +
22632                 if (0 == inet_aton(host->host->ptr, &(fcgi_addr_in.sin_addr))) {
22633 -                       log_error_write(srv, __FILE__, __LINE__, "sbs", 
22634 -                                       "converting IP-adress failed for", host->host, 
22635 +                       log_error_write(srv, __FILE__, __LINE__, "sbs",
22636 +                                       "converting IP-adress failed for", host->host,
22637                                         "\nBe sure to specify an IP address here");
22638 -                       
22639 +
22640                         return -1;
22641                 }
22642 +
22643                 fcgi_addr_in.sin_port = htons(proc->port);
22644                 servlen = sizeof(fcgi_addr_in);
22645 -               
22646 +
22647                 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
22648  
22649                 if (buffer_is_empty(proc->connection_name)) {
22650 @@ -1715,20 +1712,20 @@
22651                         buffer_append_long(proc->connection_name, proc->port);
22652                 }
22653         }
22654 -       
22655 +
22656         if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
22657 -               if (errno == EINPROGRESS || 
22658 +               if (errno == EINPROGRESS ||
22659                     errno == EALREADY ||
22660                     errno == EINTR) {
22661                         if (hctx->conf.debug > 2) {
22662 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
22663 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
22664                                         "connect delayed, will continue later:", proc->connection_name);
22665                         }
22666 -                       
22667 +
22668                         return CONNECTION_DELAYED;
22669                 } else if (errno == EAGAIN) {
22670                         if (hctx->conf.debug) {
22671 -                               log_error_write(srv, __FILE__, __LINE__, "sbsd", 
22672 +                               log_error_write(srv, __FILE__, __LINE__, "sbsd",
22673                                         "This means that the you have more incoming requests than your fastcgi-backend can handle in parallel. "
22674                                         "Perhaps it helps to spawn more fastcgi backend or php-children, if not decrease server.max-connections."
22675                                         "The load for this fastcgi backend", proc->connection_name, "is", proc->load);
22676 @@ -1736,8 +1733,8 @@
22677  
22678                         return CONNECTION_OVERLOADED;
22679                 } else {
22680 -                       log_error_write(srv, __FILE__, __LINE__, "sssb", 
22681 -                                       "connect failed:", 
22682 +                       log_error_write(srv, __FILE__, __LINE__, "sssb",
22683 +                                       "connect failed:",
22684                                         strerror(errno), "on",
22685                                         proc->connection_name);
22686  
22687 @@ -1747,7 +1744,7 @@
22688  
22689         hctx->reconnects = 0;
22690         if (hctx->conf.debug > 1) {
22691 -               log_error_write(srv, __FILE__, __LINE__, "sd", 
22692 +               log_error_write(srv, __FILE__, __LINE__, "sd",
22693                                 "connect succeeded: ", fcgi_fd);
22694         }
22695  
22696 @@ -1756,21 +1753,21 @@
22697  
22698  static int fcgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
22699         size_t i;
22700 -       
22701 +
22702         for (i = 0; i < con->request.headers->used; i++) {
22703                 data_string *ds;
22704 -               
22705 +
22706                 ds = (data_string *)con->request.headers->data[i];
22707 -               
22708 +
22709                 if (ds->value->used && ds->key->used) {
22710                         size_t j;
22711                         buffer_reset(srv->tmp_buf);
22712 -                       
22713 +
22714                         if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
22715                                 BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
22716                                 srv->tmp_buf->used--;
22717                         }
22718 -                       
22719 +
22720                         buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
22721                         for (j = 0; j < ds->key->used - 1; j++) {
22722                                 char c = '_';
22723 @@ -1784,20 +1781,20 @@
22724                                 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
22725                         }
22726                         srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
22727 -                       
22728 +
22729                         fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
22730                 }
22731         }
22732 -       
22733 +
22734         for (i = 0; i < con->environment->used; i++) {
22735                 data_string *ds;
22736 -               
22737 +
22738                 ds = (data_string *)con->environment->data[i];
22739 -               
22740 +
22741                 if (ds->value->used && ds->key->used) {
22742                         size_t j;
22743                         buffer_reset(srv->tmp_buf);
22744 -                       
22745 +
22746                         buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
22747                         for (j = 0; j < ds->key->used - 1; j++) {
22748                                 char c = '_';
22749 @@ -1811,11 +1808,11 @@
22750                                 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
22751                         }
22752                         srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
22753 -                       
22754 +
22755                         fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
22756                 }
22757         }
22758 -       
22759 +
22760         return 0;
22761  }
22762  
22763 @@ -1824,24 +1821,24 @@
22764         FCGI_BeginRequestRecord beginRecord;
22765         FCGI_Header header;
22766         buffer *b;
22767 -       
22768 +
22769         char buf[32];
22770         const char *s;
22771  #ifdef HAVE_IPV6
22772         char b2[INET6_ADDRSTRLEN + 1];
22773  #endif
22774 -       
22775 +
22776         plugin_data *p    = hctx->plugin_data;
22777         fcgi_extension_host *host= hctx->host;
22778  
22779         connection *con   = hctx->remote_conn;
22780         server_socket *srv_sock = con->srv_socket;
22781 -       
22782 +
22783         sock_addr our_addr;
22784         socklen_t our_addr_len;
22785 -       
22786 +
22787         /* send FCGI_BEGIN_REQUEST */
22788 -       
22789 +
22790         fcgi_header(&(beginRecord.header), FCGI_BEGIN_REQUEST, request_id, sizeof(beginRecord.body), 0);
22791         beginRecord.body.roleB0 = host->mode;
22792         beginRecord.body.roleB1 = 0;
22793 @@ -1849,21 +1846,21 @@
22794         memset(beginRecord.body.reserved, 0, sizeof(beginRecord.body.reserved));
22795  
22796         b = chunkqueue_get_append_buffer(hctx->wb);
22797 -       
22798 +
22799         buffer_copy_memory(b, (const char *)&beginRecord, sizeof(beginRecord));
22800 -       
22801 +
22802         /* send FCGI_PARAMS */
22803         buffer_prepare_copy(p->fcgi_env, 1024);
22804  
22805  
22806         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
22807 -       
22808 +
22809         if (con->server_name->used) {
22810                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
22811         } else {
22812  #ifdef HAVE_IPV6
22813 -               s = inet_ntop(srv_sock->addr.plain.sa_family, 
22814 -                             srv_sock->addr.plain.sa_family == AF_INET6 ? 
22815 +               s = inet_ntop(srv_sock->addr.plain.sa_family,
22816 +                             srv_sock->addr.plain.sa_family == AF_INET6 ?
22817                               (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
22818                               (const void *) &(srv_sock->addr.ipv4.sin_addr),
22819                               b2, sizeof(b2)-1);
22820 @@ -1872,50 +1869,50 @@
22821  #endif
22822                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
22823         }
22824 -       
22825 +
22826         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
22827 -       
22828 -       ltostr(buf, 
22829 +
22830 +       ltostr(buf,
22831  #ifdef HAVE_IPV6
22832                ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
22833  #else
22834                ntohs(srv_sock->addr.ipv4.sin_port)
22835  #endif
22836                );
22837 -       
22838 +
22839         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
22840 -       
22841 +
22842         /* get the server-side of the connection to the client */
22843         our_addr_len = sizeof(our_addr);
22844 -       
22845 +
22846         if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
22847                 s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
22848         } else {
22849                 s = inet_ntop_cache_get_ip(srv, &(our_addr));
22850         }
22851         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
22852 -       
22853 -       ltostr(buf, 
22854 +
22855 +       ltostr(buf,
22856  #ifdef HAVE_IPV6
22857                ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
22858  #else
22859                ntohs(con->dst_addr.ipv4.sin_port)
22860  #endif
22861                );
22862 -       
22863 +
22864         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
22865 -       
22866 +
22867         s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
22868         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
22869 -       
22870 +
22871         if (!buffer_is_empty(con->authed_user)) {
22872                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_USER"),
22873                              CONST_BUF_LEN(con->authed_user));
22874         }
22875 -       
22876 +
22877         if (con->request.content_length > 0 && host->mode != FCGI_AUTHORIZER) {
22878                 /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
22879 -               
22880 +
22881                 /* request.content_length < SSIZE_MAX, see request.c */
22882                 ltostr(buf, con->request.content_length);
22883                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
22884 @@ -1930,12 +1927,12 @@
22885                  */
22886  
22887                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
22888 -               
22889 +
22890                 if (!buffer_is_empty(con->request.pathinfo)) {
22891                         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
22892 -                       
22893 +
22894                         /* PATH_TRANSLATED is only defined if PATH_INFO is set */
22895 -                       
22896 +
22897                         if (!buffer_is_empty(host->docroot)) {
22898                                 buffer_copy_string_buffer(p->path, host->docroot);
22899                         } else {
22900 @@ -1957,27 +1954,27 @@
22901          */
22902  
22903         if (!buffer_is_empty(host->docroot)) {
22904 -               /* 
22905 -                * rewrite SCRIPT_FILENAME 
22906 -                * 
22907 +               /*
22908 +                * rewrite SCRIPT_FILENAME
22909 +                *
22910                  */
22911 -               
22912 +
22913                 buffer_copy_string_buffer(p->path, host->docroot);
22914                 buffer_append_string_buffer(p->path, con->uri.path);
22915 -               
22916 +
22917                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
22918                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
22919         } else {
22920                 buffer_copy_string_buffer(p->path, con->physical.path);
22921 -               
22922 -               /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself 
22923 -                * 
22924 +
22925 +               /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself
22926 +                *
22927                  * see src/sapi/cgi_main.c, init_request_info()
22928                  */
22929                 if (host->break_scriptfilename_for_php) {
22930                         buffer_append_string_buffer(p->path, con->request.pathinfo);
22931                 }
22932 -               
22933 +
22934                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
22935                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
22936         }
22937 @@ -1987,7 +1984,7 @@
22938                 /**
22939                  * /app1/index/list
22940                  *
22941 -                * stripping /app1 or /app1/ should lead to 
22942 +                * stripping /app1 or /app1/ should lead to
22943                  *
22944                  * /index/list
22945                  *
22946 @@ -2001,7 +1998,7 @@
22947                     0 == strncmp(con->request.orig_uri->ptr, host->strip_request_uri->ptr, host->strip_request_uri->used - 1)) {
22948                         /* the left is the same */
22949  
22950 -                       fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"), 
22951 +                       fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"),
22952                                         con->request.orig_uri->ptr + (host->strip_request_uri->used - 2),
22953                                         con->request.orig_uri->used - (host->strip_request_uri->used - 2));
22954                 } else {
22955 @@ -2018,26 +2015,26 @@
22956         } else {
22957                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
22958         }
22959 -       
22960 +
22961         s = get_http_method_name(con->request.http_method);
22962         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
22963         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
22964         s = get_http_version_name(con->request.http_version);
22965         fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
22966 -       
22967 +
22968  #ifdef USE_OPENSSL
22969         if (srv_sock->is_ssl) {
22970                 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
22971         }
22972  #endif
22973 -       
22974 -       
22975 +
22976 +
22977         fcgi_env_add_request_headers(srv, con, p);
22978 -       
22979 +
22980         fcgi_header(&(header), FCGI_PARAMS, request_id, p->fcgi_env->used, 0);
22981         buffer_append_memory(b, (const char *)&header, sizeof(header));
22982         buffer_append_memory(b, (const char *)p->fcgi_env->ptr, p->fcgi_env->used);
22983 -       
22984 +
22985         fcgi_header(&(header), FCGI_PARAMS, request_id, 0, 0);
22986         buffer_append_memory(b, (const char *)&header, sizeof(header));
22987  
22988 @@ -2057,7 +2054,7 @@
22989  
22990                         /* we announce toWrite octects
22991                          * now take all the request_content chunk that we need to fill this request
22992 -                        * */   
22993 +                        * */
22994  
22995                         b = chunkqueue_get_append_buffer(hctx->wb);
22996                         fcgi_header(&(header), FCGI_STDIN, request_id, weWant, 0);
22997 @@ -2080,16 +2077,16 @@
22998                                         if (weHave > weWant - written) weHave = weWant - written;
22999  
23000                                         if (p->conf.debug > 10) {
23001 -                                               fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n", 
23002 -                                                               __FILE__, __LINE__, 
23003 -                                                               weHave, 
23004 -                                                               req_c->offset, 
23005 -                                                               req_c->file.length, 
23006 +                                               fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n",
23007 +                                                               __FILE__, __LINE__,
23008 +                                                               weHave,
23009 +                                                               req_c->offset,
23010 +                                                               req_c->file.length,
23011                                                                 req_c->file.name->ptr);
23012                                         }
23013  
23014                                         assert(weHave != 0);
23015 -                                       
23016 +
23017                                         chunkqueue_append_file(hctx->wb, req_c->file.name, req_c->offset, weHave);
23018  
23019                                         req_c->offset += weHave;
23020 @@ -2104,7 +2101,7 @@
23021                                          * - we reference the tempfile from the request-content-queue several times
23022                                          *   if the req_c is larger than FCGI_MAX_LENGTH
23023                                          * - we can't simply cleanup the request-content-queue as soon as possible
23024 -                                        *   as it would remove the tempfiles 
23025 +                                        *   as it would remove the tempfiles
23026                                          * - the idea is to 'steal' the tempfiles and attach the is_temp flag to the last
23027                                          *   referencing chunk of the fastcgi-write-queue
23028                                          *
23029 @@ -2141,7 +2138,7 @@
23030                                         req_c->offset += weHave;
23031                                         req_cq->bytes_out += weHave;
23032                                         written += weHave;
23033 -                                       
23034 +
23035                                         hctx->wb->bytes_in += weHave;
23036  
23037                                         if (req_c->offset == req_c->mem->used - 1) {
23038 @@ -2155,12 +2152,12 @@
23039                                         break;
23040                                 }
23041                         }
23042 -                       
23043 +
23044                         b->used++; /* add virtual \0 */
23045                         offset += weWant;
23046                 }
23047         }
23048 -       
23049 +
23050         b = chunkqueue_get_append_buffer(hctx->wb);
23051         /* terminate STDIN */
23052         fcgi_header(&(header), FCGI_STDIN, request_id, 0, 0);
23053 @@ -2175,118 +2172,19 @@
23054                 if ((i+1) % 16 == 0) {
23055                         size_t j;
23056                         for (j = i-15; j <= i; j++) {
23057 -                               fprintf(stderr, "%c", 
23058 +                               fprintf(stderr, "%c",
23059                                         isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.');
23060                         }
23061                         fprintf(stderr, "\n");
23062                 }
23063         }
23064  #endif
23065 -       
23066 -       return 0;
23067 -}
23068 -
23069 -static int fcgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
23070 -       char *s, *ns;
23071 -       
23072 -       handler_ctx *hctx = con->plugin_ctx[p->id];
23073 -       fcgi_extension_host *host= hctx->host;
23074 -       
23075 -       UNUSED(srv);
23076  
23077 -       buffer_copy_string_buffer(p->parse_response, in);
23078 -       
23079 -       /* search for \n */
23080 -       for (s = p->parse_response->ptr; NULL != (ns = strchr(s, '\n')); s = ns + 1) {
23081 -               char *key, *value;
23082 -               int key_len;
23083 -               data_string *ds;
23084 -               
23085 -               /* a good day. Someone has read the specs and is sending a \r\n to us */
23086 -               
23087 -               if (ns > p->parse_response->ptr &&
23088 -                   *(ns-1) == '\r') {
23089 -                       *(ns-1) = '\0';
23090 -               }
23091 -               
23092 -               ns[0] = '\0';
23093 -               
23094 -               key = s;
23095 -               if (NULL == (value = strchr(s, ':'))) {
23096 -                       /* we expect: "<key>: <value>\n" */
23097 -                       continue;
23098 -               }
23099 -               
23100 -               key_len = value - key;
23101 -               
23102 -               value++;
23103 -               /* strip WS */
23104 -               while (*value == ' ' || *value == '\t') value++;
23105 -               
23106 -               if (host->mode != FCGI_AUTHORIZER ||
23107 -                   !(con->http_status == 0 ||
23108 -                     con->http_status == 200)) {
23109 -                       /* authorizers shouldn't affect the response headers sent back to the client */
23110 -                       
23111 -                       /* don't forward Status: */
23112 -                       if (0 != strncasecmp(key, "Status", key_len)) {
23113 -                               if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
23114 -                                       ds = data_response_init();
23115 -                               }
23116 -                               buffer_copy_string_len(ds->key, key, key_len);
23117 -                               buffer_copy_string(ds->value, value);
23118 -                               
23119 -                               array_insert_unique(con->response.headers, (data_unset *)ds);
23120 -                       }
23121 -               }
23122 -               
23123 -               switch(key_len) {
23124 -               case 4:
23125 -                       if (0 == strncasecmp(key, "Date", key_len)) {
23126 -                               con->parsed_response |= HTTP_DATE;
23127 -                       }
23128 -                       break;
23129 -               case 6:
23130 -                       if (0 == strncasecmp(key, "Status", key_len)) {
23131 -                               con->http_status = strtol(value, NULL, 10);
23132 -                               con->parsed_response |= HTTP_STATUS;
23133 -                       }
23134 -                       break;
23135 -               case 8:
23136 -                       if (0 == strncasecmp(key, "Location", key_len)) {
23137 -                               con->parsed_response |= HTTP_LOCATION;
23138 -                       }
23139 -                       break;
23140 -               case 10:
23141 -                       if (0 == strncasecmp(key, "Connection", key_len)) {
23142 -                               con->response.keep_alive = (0 == strcasecmp(value, "Keep-Alive")) ? 1 : 0;
23143 -                               con->parsed_response |= HTTP_CONNECTION;
23144 -                       }
23145 -                       break;
23146 -               case 14:
23147 -                       if (0 == strncasecmp(key, "Content-Length", key_len)) {
23148 -                               con->response.content_length = strtol(value, NULL, 10);
23149 -                               con->parsed_response |= HTTP_CONTENT_LENGTH;
23150 -                               
23151 -                               if (con->response.content_length < 0) con->response.content_length = 0;
23152 -                       }
23153 -                       break;
23154 -               default:
23155 -                       break;
23156 -               }
23157 -       }
23158 -       
23159 -       /* CGI/1.1 rev 03 - 7.2.1.2 */
23160 -       if ((con->parsed_response & HTTP_LOCATION) &&
23161 -           !(con->parsed_response & HTTP_STATUS)) {
23162 -               con->http_status = 302;
23163 -       }
23164 -       
23165         return 0;
23166  }
23167  
23168  typedef struct {
23169 -       buffer  *b; 
23170 +       buffer  *b;
23171         size_t   len;
23172         int      type;
23173         int      padding;
23174 @@ -2327,9 +2225,9 @@
23175                 return -1;
23176         }
23177  
23178 -       /* we have at least a header, now check how much me have to fetch */ 
23179 +       /* we have at least a header, now check how much me have to fetch */
23180         header = (FCGI_Header *)(packet->b->ptr);
23181 -                       
23182 +
23183         packet->len = (header->contentLengthB0 | (header->contentLengthB1 << 8)) + header->paddingLength;
23184         packet->request_id = (header->requestIdB0 | (header->requestIdB1 << 8));
23185         packet->type = header->type;
23186 @@ -2348,7 +2246,7 @@
23187                         size_t weHave = c->mem->used - c->offset - offset - 1;
23188  
23189                         if (weHave > weWant) weHave = weWant;
23190 -                                               
23191 +
23192                         buffer_append_string_len(packet->b, c->mem->ptr + c->offset + offset, weHave);
23193  
23194                         /* we only skipped the first 8 bytes as they are the fcgi header */
23195 @@ -2380,65 +2278,37 @@
23196         }
23197  
23198         chunkqueue_remove_finished_chunks(hctx->rb);
23199 -       
23200 +
23201         return 0;
23202  }
23203  
23204  static int fcgi_demux_response(server *srv, handler_ctx *hctx) {
23205         int fin = 0;
23206 -       int toread;
23207 -       ssize_t r;
23208 -       
23209 +
23210         plugin_data *p    = hctx->plugin_data;
23211         connection *con   = hctx->remote_conn;
23212 -       int fcgi_fd       = hctx->fd;
23213         fcgi_extension_host *host= hctx->host;
23214         fcgi_proc *proc   = hctx->proc;
23215 -       
23216 -       /* 
23217 -        * check how much we have to read 
23218 -        */
23219 -       if (ioctl(hctx->fd, FIONREAD, &toread)) {
23220 -               log_error_write(srv, __FILE__, __LINE__, "sd", 
23221 -                               "unexpected end-of-file (perhaps the fastcgi process died):",
23222 -                               fcgi_fd);
23223 -               return -1;
23224 -       }
23225 -       
23226 -       /* init read-buffer */
23227 -       
23228 -       if (toread > 0) {
23229 -               buffer *b;
23230 -
23231 -               b = chunkqueue_get_append_buffer(hctx->rb);
23232 -               buffer_prepare_copy(b, toread + 1);
23233 -
23234 -               /* append to read-buffer */
23235 -               if (-1 == (r = read(hctx->fd, b->ptr, toread))) {
23236 -                       log_error_write(srv, __FILE__, __LINE__, "sds", 
23237 -                                       "unexpected end-of-file (perhaps the fastcgi process died):",
23238 -                                       fcgi_fd, strerror(errno));
23239 -                       return -1;
23240 -               }
23241 -               
23242 -               /* this should be catched by the b > 0 above */
23243 -               assert(r);
23244  
23245 -               b->used = r + 1; /* one extra for the fake \0 */
23246 -               b->ptr[b->used - 1] = '\0';
23247 -       } else {
23248 -               log_error_write(srv, __FILE__, __LINE__, "ssdsb", 
23249 +       switch(srv->network_backend_read(srv, con, hctx->fd, hctx->rb)) {
23250 +       case NETWORK_STATUS_WAIT_FOR_EVENT:
23251 +               /* we are only triggered when there is a event */
23252 +               log_error_write(srv, __FILE__, __LINE__, "ssdsb",
23253                                 "unexpected end-of-file (perhaps the fastcgi process died):",
23254                                 "pid:", proc->pid,
23255                                 "socket:", proc->connection_name);
23256 -               
23257 +               return -1;
23258 +       case NETWORK_STATUS_SUCCESS:
23259 +               break;
23260 +       default:
23261 +               log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi-read failed");
23262                 return -1;
23263         }
23264  
23265         /*
23266          * parse the fastcgi packets and forward the content to the write-queue
23267          *
23268 -        */     
23269 +        */
23270         while (fin == 0) {
23271                 fastcgi_response_packet packet;
23272  
23273 @@ -2454,92 +2324,135 @@
23274  
23275                         /* is the header already finished */
23276                         if (0 == con->file_started) {
23277 -                               char *c;
23278 -                               size_t blen;
23279 -                               data_string *ds;
23280 -                                       
23281 -                               /* search for header terminator 
23282 -                                * 
23283 -                                * if we start with \r\n check if last packet terminated with \r\n
23284 -                                * if we start with \n check if last packet terminated with \n
23285 -                                * search for \r\n\r\n
23286 -                                * search for \n\n
23287 -                                */
23288 -
23289 -                               if (hctx->response_header->used == 0) {
23290 -                                       buffer_copy_string_buffer(hctx->response_header, packet.b);
23291 -                               } else {
23292 -                                       buffer_append_string_buffer(hctx->response_header, packet.b);
23293 -                               }
23294 -
23295 -                               if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\r\n\r\n")))) {
23296 -                                       blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 4;
23297 -                                       hctx->response_header->used = (c - hctx->response_header->ptr) + 3;
23298 -                                       c += 4; /* point the the start of the response */
23299 -                               } else if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\n\n")))) {
23300 -                                       blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 2;
23301 -                                       hctx->response_header->used = c - hctx->response_header->ptr + 2;
23302 -                                       c += 2; /* point the the start of the response */
23303 -                               } else {
23304 -                                       /* no luck, no header found */
23305 +                               int have_content_length = 0;
23306 +                               int need_more = 0;
23307 +                               size_t i;
23308 +
23309 +                               /* append the current packet to the chunk queue */
23310 +                               chunkqueue_append_buffer(hctx->http_rb, packet.b);
23311 +                               http_response_reset(p->resp);
23312 +
23313 +                               switch(http_response_parse_cq(hctx->http_rb, p->resp)) {
23314 +                               case PARSE_ERROR:
23315 +                                       /* parsing the response header failed */
23316 +
23317 +                                       con->http_status = 502; /* Bad Gateway */
23318 +
23319 +                                       return 1;
23320 +                               case PARSE_NEED_MORE:
23321 +                                       need_more = 1;
23322 +                                       break; /* leave the loop */
23323 +                               case PARSE_SUCCESS:
23324                                         break;
23325 +                               default:
23326 +                                       /* should not happen */
23327 +                                       SEGFAULT();
23328                                 }
23329  
23330 -                               /* parse the response header */
23331 -                               fcgi_response_parse(srv, con, p, hctx->response_header);
23332 +                               if (need_more) break;
23333  
23334 -                               con->file_started = 1;
23335 +                               chunkqueue_remove_finished_chunks(hctx->http_rb);
23336  
23337 -                               if (host->mode == FCGI_AUTHORIZER &&
23338 -                                   (con->http_status == 0 ||
23339 -                                    con->http_status == 200)) {
23340 -                                       /* a authorizer with approved the static request, ignore the content here */
23341 -                                       hctx->send_content_body = 0;
23342 -                               }
23343 -
23344 -                               if (host->allow_xsendfile &&
23345 -                                   NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-LIGHTTPD-send-file"))) {
23346 -                                       stat_cache_entry *sce;
23347 -
23348 -                                       if (HANDLER_ERROR != stat_cache_get_entry(srv, con, ds->value, &sce)) {
23349 -                                               /* found */
23350 -
23351 -                                               http_chunk_append_file(srv, con, ds->value, 0, sce->st.st_size);
23352 -                                               hctx->send_content_body = 0; /* ignore the content */
23353 -                                               joblist_append(srv, con);
23354 +                               con->http_status = p->resp->status;
23355 +
23356 +                               /* handle the header fields */
23357 +                               if (host->mode == FCGI_AUTHORIZER) {
23358 +                                       /* auth mode is a bit different */
23359 +
23360 +                                       if (con->http_status == 0 ||
23361 +                                           con->http_status == 200) {
23362 +                                               /* a authorizer with approved the static request, ignore the content here */
23363 +                                               hctx->send_content_body = 0;
23364                                         }
23365                                 }
23366  
23367 +                               /* copy the http-headers */
23368 +                               for (i = 0; i < p->resp->headers->used; i++) {
23369 +                                       const char *ign[] = { "Status", NULL };
23370 +                                       size_t j;
23371 +                                       data_string *ds;
23372 +
23373 +                                       data_string *header = (data_string *)p->resp->headers->data[i];
23374 +
23375 +                                       /* ignore all headers in AUTHORIZER mode */
23376 +                                       if (host->mode == FCGI_AUTHORIZER) continue;
23377 +
23378 +                                       /* some headers are ignored by default */
23379 +                                       for (j = 0; ign[j]; j++) {
23380 +                                               if (0 == strcasecmp(ign[j], header->key->ptr)) break;
23381 +                                       }
23382 +                                       if (ign[j]) continue;
23383 +
23384 +                                       if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) {
23385 +                                               /* CGI/1.1 rev 03 - 7.2.1.2 */
23386 +                                               con->http_status = 302;
23387 +                                       } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) {
23388 +                                               have_content_length = 1;
23389 +                                       } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-Sendfile")) || 
23390 +                                                  0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-LIGHTTPD-send-file"))) {
23391 +                                               
23392 +                                               stat_cache_entry *sce;
23393                                                 
23394 -                               if (hctx->send_content_body && blen > 1) {                                              
23395 -                                       /* enable chunked-transfer-encoding */
23396 +                                               if (host->allow_xsendfile &&
23397 +                                                   HANDLER_ERROR != stat_cache_get_entry(srv, con, header->value, &sce)) {
23398 +                                                       http_chunk_append_file(srv, con, header->value, 0, sce->st.st_size);
23399 +                                                       hctx->send_content_body = 0; /* ignore the content */
23400 +                                       
23401 +                                                       joblist_append(srv, con);
23402 +                                               }
23403 +
23404 +                                               continue; /* ignore header */
23405 +                                       }
23406 +                                       
23407 +                                       if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
23408 +                                               ds = data_response_init();
23409 +                                       }
23410 +                                       buffer_copy_string_buffer(ds->key, header->key);
23411 +                                       buffer_copy_string_buffer(ds->value, header->value);
23412 +
23413 +                                       array_insert_unique(con->response.headers, (data_unset *)ds);
23414 +                               }
23415 +
23416 +                               /* header is complete ... go on with the body */
23417 +
23418 +                               con->file_started = 1;
23419 +
23420 +                               if (hctx->send_content_body) {
23421 +                                       chunk *c = hctx->http_rb->first;
23422 +
23423 +                                       /* if we don't have a content-length enable chunked encoding 
23424 +                                        * if possible
23425 +                                        * 
23426 +                                        * TODO: move this to a later stage in the filter-queue
23427 +                                        *  */
23428                                         if (con->request.http_version == HTTP_VERSION_1_1 &&
23429 -                                           !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
23430 +                                           !have_content_length) {
23431                                                 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
23432                                         }
23433  
23434 -                                       http_chunk_append_mem(srv, con, c, blen);
23435 +                                       /* copy the rest of the data */
23436 +                                       for (c = hctx->http_rb->first; c; c = c->next) {
23437 +                                               if (c->mem->used > 1) {
23438 +                                                       http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
23439 +                                                       c->offset = c->mem->used - 1;
23440 +                                               }
23441 +                                       }
23442 +                                       chunkqueue_remove_finished_chunks(hctx->http_rb);
23443                                         joblist_append(srv, con);
23444                                 }
23445                         } else if (hctx->send_content_body && packet.b->used > 1) {
23446 -                               if (con->request.http_version == HTTP_VERSION_1_1 &&
23447 -                                   !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
23448 -                                       /* enable chunked-transfer-encoding */
23449 -                                       con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
23450 -                               }
23451 -
23452                                 http_chunk_append_mem(srv, con, packet.b->ptr, packet.b->used);
23453                                 joblist_append(srv, con);
23454                         }
23455                         break;
23456                 case FCGI_STDERR:
23457 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
23458 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
23459                                         "FastCGI-stderr:", packet.b);
23460 -                       
23461 +
23462                         break;
23463                 case FCGI_END_REQUEST:
23464                         con->file_finished = 1;
23465 -                       
23466 +
23467                         if (host->mode != FCGI_AUTHORIZER ||
23468                             !(con->http_status == 0 ||
23469                               con->http_status == 200)) {
23470 @@ -2547,39 +2460,39 @@
23471                                 http_chunk_append_mem(srv, con, NULL, 0);
23472                                 joblist_append(srv, con);
23473                         }
23474 -                       
23475 +
23476                         fin = 1;
23477                         break;
23478                 default:
23479 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
23480 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
23481                                         "FastCGI: header.type not handled: ", packet.type);
23482                         break;
23483                 }
23484                 buffer_free(packet.b);
23485         }
23486 -       
23487 +
23488         return fin;
23489  }
23490  
23491  static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_host *host) {
23492         fcgi_proc *proc;
23493 -       
23494 +
23495         for (proc = host->first; proc; proc = proc->next) {
23496                 int status;
23497  
23498                 if (p->conf.debug > 2) {
23499 -                       log_error_write(srv, __FILE__, __LINE__,  "sbdddd", 
23500 -                                       "proc:", 
23501 +                       log_error_write(srv, __FILE__, __LINE__,  "sbdddd",
23502 +                                       "proc:",
23503                                         proc->connection_name,
23504                                         proc->state,
23505                                         proc->is_local,
23506                                         proc->load,
23507                                         proc->pid);
23508                 }
23509 -               
23510 -               /* 
23511 +
23512 +               /*
23513                  * if the remote side is overloaded, we check back after <n> seconds
23514 -                * 
23515 +                *
23516                  */
23517                 switch (proc->state) {
23518                 case PROC_STATE_KILLED:
23519 @@ -2592,13 +2505,13 @@
23520                         break;
23521                 case PROC_STATE_OVERLOADED:
23522                         if (srv->cur_ts <= proc->disabled_until) break;
23523 -                       
23524 +
23525                         proc->state = PROC_STATE_RUNNING;
23526                         host->active_procs++;
23527 -                       
23528 -                       log_error_write(srv, __FILE__, __LINE__,  "sbdb", 
23529 -                                       "fcgi-server re-enabled:", 
23530 -                                       host->host, host->port, 
23531 +
23532 +                       log_error_write(srv, __FILE__, __LINE__,  "sbdb",
23533 +                                       "fcgi-server re-enabled:",
23534 +                                       host->host, host->port,
23535                                         host->unixsocket);
23536                         break;
23537                 case PROC_STATE_DIED_WAIT_FOR_PID:
23538 @@ -2606,7 +2519,7 @@
23539                         if (!proc->is_local) break;
23540  
23541                         /* the child should not terminate at all */
23542 -                       
23543 +#ifndef _WIN32
23544                         switch(waitpid(proc->pid, &status, WNOHANG)) {
23545                         case 0:
23546                                 /* child is still alive */
23547 @@ -2616,45 +2529,45 @@
23548                         default:
23549                                 if (WIFEXITED(status)) {
23550  #if 0
23551 -                                       log_error_write(srv, __FILE__, __LINE__, "sdsd", 
23552 +                                       log_error_write(srv, __FILE__, __LINE__, "sdsd",
23553                                                         "child exited, pid:", proc->pid,
23554                                                         "status:", WEXITSTATUS(status));
23555  #endif
23556                                 } else if (WIFSIGNALED(status)) {
23557 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
23558 -                                                       "child signaled:", 
23559 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
23560 +                                                       "child signaled:",
23561                                                         WTERMSIG(status));
23562                                 } else {
23563 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
23564 -                                                       "child died somehow:", 
23565 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
23566 +                                                       "child died somehow:",
23567                                                         status);
23568                                 }
23569 -                               
23570 +
23571                                 proc->state = PROC_STATE_DIED;
23572                                 break;
23573                         }
23574 -
23575 +#endif
23576                         /* fall through if we have a dead proc now */
23577                         if (proc->state != PROC_STATE_DIED) break;
23578  
23579                 case PROC_STATE_DIED:
23580 -                       /* local proc get restarted by us, 
23581 +                       /* local proc get restarted by us,
23582                          * remote ones hopefully by the admin */
23583 -                       
23584 +
23585                         if (proc->is_local) {
23586                                 /* we still have connections bound to this proc,
23587                                  * let them terminate first */
23588                                 if (proc->load != 0) break;
23589 -                       
23590 +
23591                                 /* restart the child */
23592 -                               
23593 +
23594                                 if (p->conf.debug) {
23595                                         log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
23596                                                         "--- fastcgi spawning",
23597                                                         "\n\tsocket", proc->connection_name,
23598                                                         "\n\tcurrent:", 1, "/", host->min_procs);
23599                                 }
23600 -                               
23601 +
23602                                 if (fcgi_spawn_connection(srv, p, host, proc)) {
23603                                         log_error_write(srv, __FILE__, __LINE__, "s",
23604                                                         "ERROR: spawning fcgi failed.");
23605 @@ -2662,18 +2575,18 @@
23606                                 }
23607                         } else {
23608                                 if (srv->cur_ts <= proc->disabled_until) break;
23609 -                       
23610 +
23611                                 proc->state = PROC_STATE_RUNNING;
23612                                 host->active_procs++;
23613 -                       
23614 -                               log_error_write(srv, __FILE__, __LINE__,  "sb", 
23615 -                                               "fcgi-server re-enabled:", 
23616 +
23617 +                               log_error_write(srv, __FILE__, __LINE__,  "sb",
23618 +                                               "fcgi-server re-enabled:",
23619                                                 proc->connection_name);
23620                         }
23621                         break;
23622                 }
23623         }
23624 -       
23625 +
23626         return 0;
23627  }
23628  
23629 @@ -2682,19 +2595,19 @@
23630         fcgi_extension_host *host= hctx->host;
23631         connection *con   = hctx->remote_conn;
23632         fcgi_proc  *proc;
23633 -       
23634 +
23635         int ret;
23636  
23637 -       /* sanity check */      
23638 +       /* sanity check */
23639         if (!host ||
23640             ((!host->host->used || !host->port) && !host->unixsocket->used)) {
23641 -               log_error_write(srv, __FILE__, __LINE__, "sxddd", 
23642 +               log_error_write(srv, __FILE__, __LINE__, "sxddd",
23643                                 "write-req: error",
23644                                 host,
23645                                 host->host->used,
23646                                 host->port,
23647                                 host->unixsocket->used);
23648 -                       
23649 +
23650                 hctx->proc->disabled_until = srv->cur_ts + 10;
23651                 hctx->proc->state = PROC_STATE_DIED;
23652  
23653 @@ -2705,12 +2618,12 @@
23654         if (hctx->state == FCGI_STATE_CONNECT_DELAYED) {
23655                 int socket_error;
23656                 socklen_t socket_error_len = sizeof(socket_error);
23657 -                       
23658 +
23659                 /* try to finish the connect() */
23660                 if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
23661 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
23662 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
23663                                         "getsockopt failed:", strerror(errno));
23664 -                       
23665 +
23666                         hctx->proc->disabled_until = srv->cur_ts + 10;
23667                         hctx->proc->state = PROC_STATE_DIED;
23668  
23669 @@ -2719,12 +2632,12 @@
23670                 if (socket_error != 0) {
23671                         if (!hctx->proc->is_local || p->conf.debug) {
23672                                 /* local procs get restarted */
23673 -                               
23674 +
23675                                 log_error_write(srv, __FILE__, __LINE__, "sssb",
23676 -                                               "establishing connection failed:", strerror(socket_error), 
23677 +                                               "establishing connection failed:", strerror(socket_error),
23678                                                 "socket:", hctx->proc->connection_name);
23679                         }
23680 -       
23681 +
23682                         hctx->proc->disabled_until = srv->cur_ts + 5;
23683  
23684                         if (hctx->proc->is_local) {
23685 @@ -2732,17 +2645,17 @@
23686                         } else {
23687                                 hctx->proc->state = PROC_STATE_DIED;
23688                         }
23689 -       
23690 +
23691                         hctx->proc->state = PROC_STATE_DIED;
23692 -               
23693 +
23694                         fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
23695                         buffer_append_string(p->statuskey, ".died");
23696  
23697                         status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
23698 -               
23699 +
23700                         return HANDLER_ERROR;
23701                 }
23702 -               /* go on with preparing the request */ 
23703 +               /* go on with preparing the request */
23704                 hctx->state = FCGI_STATE_PREPARE_WRITE;
23705         }
23706  
23707 @@ -2755,14 +2668,14 @@
23708                 /* do we have a running process for this host (max-procs) ? */
23709                 hctx->proc = NULL;
23710  
23711 -               for (proc = hctx->host->first; 
23712 -                    proc && proc->state != PROC_STATE_RUNNING; 
23713 +               for (proc = hctx->host->first;
23714 +                    proc && proc->state != PROC_STATE_RUNNING;
23715                      proc = proc->next);
23716 -                       
23717 +
23718                 /* all childs are dead */
23719                 if (proc == NULL) {
23720                         hctx->fde_ndx = -1;
23721 -               
23722 +
23723                         return HANDLER_ERROR;
23724                 }
23725  
23726 @@ -2775,50 +2688,50 @@
23727                 }
23728  
23729                 ret = host->unixsocket->used ? AF_UNIX : AF_INET;
23730 -               
23731 +
23732                 if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
23733                         if (errno == EMFILE ||
23734                             errno == EINTR) {
23735 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
23736 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
23737                                                 "wait for fd at connection:", con->fd);
23738 -                               
23739 +
23740                                 return HANDLER_WAIT_FOR_FD;
23741                         }
23742 -                       
23743 -                       log_error_write(srv, __FILE__, __LINE__, "ssdd", 
23744 +
23745 +                       log_error_write(srv, __FILE__, __LINE__, "ssdd",
23746                                         "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
23747                         return HANDLER_ERROR;
23748                 }
23749                 hctx->fde_ndx = -1;
23750 -               
23751 +
23752                 srv->cur_fds++;
23753 -               
23754 +
23755                 fdevent_register(srv->ev, hctx->fd, fcgi_handle_fdevent, hctx);
23756 -               
23757 +
23758                 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
23759 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
23760 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
23761                                         "fcntl failed:", strerror(errno));
23762 -                       
23763 +
23764                         return HANDLER_ERROR;
23765                 }
23766 -                       
23767 +
23768                 if (hctx->proc->is_local) {
23769                         hctx->pid = hctx->proc->pid;
23770                 }
23771 -                       
23772 +
23773                 switch (fcgi_establish_connection(srv, hctx)) {
23774                 case CONNECTION_DELAYED:
23775                         /* connection is in progress, wait for an event and call getsockopt() below */
23776 -                       
23777 +
23778                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23779 -                       
23780 +
23781                         fcgi_set_state(srv, hctx, FCGI_STATE_CONNECT_DELAYED);
23782                         return HANDLER_WAIT_FOR_EVENT;
23783                 case CONNECTION_OVERLOADED:
23784                         /* cool down the backend, it is overloaded
23785                          * -> EAGAIN */
23786  
23787 -                       log_error_write(srv, __FILE__, __LINE__, "ssdsd", 
23788 +                       log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23789                                 "backend is overloaded, we disable it for a 2 seconds and send the request to another backend instead:",
23790                                 "reconnects:", hctx->reconnects,
23791                                 "load:", host->load);
23792 @@ -2831,7 +2744,7 @@
23793                         buffer_append_string(p->statuskey, ".overloaded");
23794  
23795                         status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
23796 -                       
23797 +
23798                         return HANDLER_ERROR;
23799                 case CONNECTION_DEAD:
23800                         /* we got a hard error from the backend like
23801 @@ -2840,19 +2753,19 @@
23802                          *
23803                          * for check if the host is back in 5 seconds
23804                          *  */
23805 -                       
23806 +
23807                         hctx->proc->disabled_until = srv->cur_ts + 5;
23808                         if (hctx->proc->is_local) {
23809                                 hctx->proc->state = PROC_STATE_DIED_WAIT_FOR_PID;
23810                         } else {
23811                                 hctx->proc->state = PROC_STATE_DIED;
23812                         }
23813 -       
23814 -                       log_error_write(srv, __FILE__, __LINE__, "ssdsd", 
23815 +
23816 +                       log_error_write(srv, __FILE__, __LINE__, "ssdsd",
23817                                 "backend died, we disable it for a 5 seconds and send the request to another backend instead:",
23818                                 "reconnects:", hctx->reconnects,
23819                                 "load:", host->load);
23820 -       
23821 +
23822                         fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
23823                         buffer_append_string(p->statuskey, ".died");
23824  
23825 @@ -2863,19 +2776,19 @@
23826                         /* everything is ok, go on */
23827  
23828                         fcgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
23829 -                       
23830 +
23831                         break;
23832                 case CONNECTION_UNSET:
23833                         break;
23834                 }
23835 -               
23836 +
23837         case FCGI_STATE_PREPARE_WRITE:
23838                 /* ok, we have the connection */
23839 -               
23840 +
23841                 hctx->proc->load++;
23842                 hctx->proc->last_used = srv->cur_ts;
23843                 hctx->got_proc = 1;
23844 -       
23845 +
23846                 status_counter_inc(srv, CONST_STR_LEN("fastcgi.requests"));
23847                 status_counter_inc(srv, CONST_STR_LEN("fastcgi.active-requests"));
23848  
23849 @@ -2898,9 +2811,9 @@
23850  
23851                 if (p->conf.debug) {
23852                         log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
23853 -                                       "got proc:", 
23854 -                                       "pid:", hctx->proc->pid, 
23855 -                                       "socket:", hctx->proc->connection_name, 
23856 +                                       "got proc:",
23857 +                                       "pid:", hctx->proc->pid,
23858 +                                       "socket:", hctx->proc->connection_name,
23859                                         "load:", hctx->proc->load);
23860                 }
23861  
23862 @@ -2908,62 +2821,63 @@
23863                 if (hctx->request_id == 0) {
23864                         hctx->request_id = fcgi_requestid_new(srv, p);
23865                 } else {
23866 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
23867 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
23868                                         "fcgi-request is already in use:", hctx->request_id);
23869                 }
23870 -               
23871 +
23872                 /* fall through */
23873                 fcgi_create_env(srv, hctx, hctx->request_id);
23874 -               
23875 +
23876                 fcgi_set_state(srv, hctx, FCGI_STATE_WRITE);
23877 -               
23878 +
23879                 /* fall through */
23880         case FCGI_STATE_WRITE:
23881 -               ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); 
23882 +               ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
23883  
23884                 chunkqueue_remove_finished_chunks(hctx->wb);
23885 -               
23886 +
23887                 if (ret < 0) {
23888                         switch(errno) {
23889                         case ENOTCONN:
23890 -                               /* the connection got dropped after accept() 
23891 -                                * 
23892 -                                * this is most of the time a PHP which dies 
23893 +                               /* the connection got dropped after accept()
23894 +                                *
23895 +                                * this is most of the time a PHP which dies
23896                                  * after PHP_FCGI_MAX_REQUESTS
23897 -                                * 
23898 -                                */ 
23899 +                                *
23900 +                                */
23901                                 if (hctx->wb->bytes_out == 0 &&
23902                                     hctx->reconnects < 5) {
23903 -                                       usleep(10000); /* take away the load of the webserver 
23904 -                                                       * to let the php a chance to restart 
23905 +#ifndef _WIN32
23906 +                                       usleep(10000); /* take away the load of the webserver
23907 +                                                       * to let the php a chance to restart
23908                                                         */
23909 -                                       
23910 +#endif
23911                                         fcgi_reconnect(srv, hctx);
23912 -                               
23913 +
23914                                         return HANDLER_WAIT_FOR_FD;
23915                                 }
23916 -                               
23917 +
23918                                 /* not reconnected ... why
23919 -                                * 
23920 +                                *
23921                                  * far@#lighttpd report this for FreeBSD
23922 -                                * 
23923 +                                *
23924                                  */
23925 -                               
23926 -                               log_error_write(srv, __FILE__, __LINE__, "ssdsd", 
23927 +
23928 +                               log_error_write(srv, __FILE__, __LINE__, "ssosd",
23929                                                 "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
23930                                                 "write-offset:", hctx->wb->bytes_out,
23931                                                 "reconnect attempts:", hctx->reconnects);
23932 -                               
23933 +
23934                                 return HANDLER_ERROR;
23935                         case EAGAIN:
23936                         case EINTR:
23937                                 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23938 -                               
23939 +
23940                                 return HANDLER_WAIT_FOR_EVENT;
23941                         default:
23942 -                               log_error_write(srv, __FILE__, __LINE__, "ssd", 
23943 +                               log_error_write(srv, __FILE__, __LINE__, "ssd",
23944                                                 "write failed:", strerror(errno), errno);
23945 -                               
23946 +
23947                                 return HANDLER_ERROR;
23948                         }
23949                 }
23950 @@ -2975,7 +2889,7 @@
23951                         fcgi_set_state(srv, hctx, FCGI_STATE_READ);
23952                 } else {
23953                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
23954 -                               
23955 +
23956                         return HANDLER_WAIT_FOR_EVENT;
23957                 }
23958  
23959 @@ -2987,7 +2901,7 @@
23960                 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
23961                 return HANDLER_ERROR;
23962         }
23963 -       
23964 +
23965         return HANDLER_WAIT_FOR_EVENT;
23966  }
23967  
23968 @@ -2996,18 +2910,18 @@
23969   * */
23970  SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) {
23971         plugin_data *p = p_d;
23972 -       
23973 +
23974         handler_ctx *hctx = con->plugin_ctx[p->id];
23975         fcgi_proc *proc;
23976         fcgi_extension_host *host;
23977 -       
23978 +
23979         if (NULL == hctx) return HANDLER_GO_ON;
23980 -       
23981 +
23982         /* not my job */
23983         if (con->mode != p->id) return HANDLER_GO_ON;
23984  
23985         /* we don't have a host yet, choose one
23986 -        * -> this happens in the first round 
23987 +        * -> this happens in the first round
23988          *    and when the host died and we have to select a new one */
23989         if (hctx->host == NULL) {
23990                 size_t k;
23991 @@ -3016,23 +2930,23 @@
23992                 /* get best server */
23993                 for (k = 0, ndx = -1; k < hctx->ext->used; k++) {
23994                         host = hctx->ext->hosts[k];
23995 -               
23996 +
23997                         /* we should have at least one proc that can do something */
23998                         if (host->active_procs == 0) continue;
23999  
24000                         if (used == -1 || host->load < used) {
24001                                 used = host->load;
24002 -                       
24003 +
24004                                 ndx = k;
24005                         }
24006                 }
24007 -       
24008 +
24009                 /* found a server */
24010                 if (ndx == -1) {
24011                         /* all hosts are down */
24012  
24013                         fcgi_connection_close(srv, hctx);
24014 -                       
24015 +
24016                         con->http_status = 500;
24017                         con->mode = DIRECT;
24018  
24019 @@ -3040,16 +2954,16 @@
24020                 }
24021  
24022                 host = hctx->ext->hosts[ndx];
24023 -               
24024 -               /* 
24025 -                * if check-local is disabled, use the uri.path handler 
24026 -                * 
24027 +
24028 +               /*
24029 +                * if check-local is disabled, use the uri.path handler
24030 +                *
24031                  */
24032 -               
24033 +
24034                 /* init handler-context */
24035                 hctx->host = host;
24036  
24037 -               /* we put a connection on this host, move the other new connections to other hosts 
24038 +               /* we put a connection on this host, move the other new connections to other hosts
24039                  *
24040                  * as soon as hctx->host is unassigned, decrease the load again */
24041                 hctx->host->load++;
24042 @@ -3063,7 +2977,7 @@
24043         case HANDLER_ERROR:
24044                 proc = hctx->proc;
24045                 host = hctx->host;
24046 -               
24047 +
24048                 if (hctx->state == FCGI_STATE_INIT ||
24049                     hctx->state == FCGI_STATE_CONNECT_DELAYED) {
24050                         if (proc) host->active_procs--;
24051 @@ -3078,7 +2992,7 @@
24052                                 return HANDLER_WAIT_FOR_FD;
24053                         } else {
24054                                 fcgi_connection_close(srv, hctx);
24055 -                       
24056 +
24057                                 buffer_reset(con->physical.path);
24058                                 con->mode = DIRECT;
24059                                 con->http_status = 500;
24060 @@ -3088,12 +3002,12 @@
24061                         }
24062                 } else {
24063                         fcgi_connection_close(srv, hctx);
24064 -                       
24065 +
24066                         buffer_reset(con->physical.path);
24067                         con->mode = DIRECT;
24068                         con->http_status = 503;
24069                         joblist_append(srv, con); /* really ? */
24070 -                       
24071 +
24072                         return HANDLER_FINISHED;
24073                 }
24074         case HANDLER_WAIT_FOR_EVENT:
24075 @@ -3115,7 +3029,7 @@
24076         handler_ctx *hctx = ctx;
24077         connection  *con  = hctx->remote_conn;
24078         plugin_data *p    = hctx->plugin_data;
24079 -       
24080 +
24081         fcgi_proc *proc   = hctx->proc;
24082         fcgi_extension_host *host= hctx->host;
24083  
24084 @@ -3125,8 +3039,8 @@
24085                 case 0:
24086                         break;
24087                 case 1:
24088 -                       
24089 -                       if (host->mode == FCGI_AUTHORIZER && 
24090 +
24091 +                       if (host->mode == FCGI_AUTHORIZER &&
24092                             (con->http_status == 200 ||
24093                              con->http_status == 0)) {
24094                                 /*
24095 @@ -3136,26 +3050,26 @@
24096                                  */
24097  
24098                                 buffer_copy_string_buffer(con->physical.doc_root, host->docroot);
24099 -                               
24100 +
24101                                 buffer_copy_string_buffer(con->physical.path, host->docroot);
24102                                 buffer_append_string_buffer(con->physical.path, con->uri.path);
24103                                 fcgi_connection_close(srv, hctx);
24104 -                               
24105 +
24106                                 con->mode = DIRECT;
24107                                 con->file_started = 1; /* fcgi_extension won't touch the request afterwards */
24108                         } else {
24109                                 /* we are done */
24110                                 fcgi_connection_close(srv, hctx);
24111                         }
24112 -                       
24113 +
24114                         joblist_append(srv, con);
24115                         return HANDLER_FINISHED;
24116                 case -1:
24117                         if (proc->pid && proc->state != PROC_STATE_DIED) {
24118                                 int status;
24119 -                               
24120 +
24121                                 /* only fetch the zombie if it is not already done */
24122 -                               
24123 +#ifndef _WIN32
24124                                 switch(waitpid(proc->pid, &status, WNOHANG)) {
24125                                 case 0:
24126                                         /* child is still alive */
24127 @@ -3165,60 +3079,61 @@
24128                                 default:
24129                                         /* the child should not terminate at all */
24130                                         if (WIFEXITED(status)) {
24131 -                                               log_error_write(srv, __FILE__, __LINE__, "sdsd", 
24132 +                                               log_error_write(srv, __FILE__, __LINE__, "sdsd",
24133                                                                 "child exited, pid:", proc->pid,
24134                                                                 "status:", WEXITSTATUS(status));
24135                                         } else if (WIFSIGNALED(status)) {
24136 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
24137 -                                                               "child signaled:", 
24138 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
24139 +                                                               "child signaled:",
24140                                                                 WTERMSIG(status));
24141                                         } else {
24142 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
24143 -                                                               "child died somehow:", 
24144 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
24145 +                                                               "child died somehow:",
24146                                                                 status);
24147                                         }
24148 -                                       
24149 +
24150                                         if (p->conf.debug) {
24151                                                 log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
24152                                                                 "--- fastcgi spawning",
24153                                                                 "\n\tsocket", proc->connection_name,
24154                                                                 "\n\tcurrent:", 1, "/", host->min_procs);
24155                                         }
24156 -                                       
24157 +
24158                                         if (fcgi_spawn_connection(srv, p, host, proc)) {
24159                                                 /* respawning failed, retry later */
24160                                                 proc->state = PROC_STATE_DIED;
24161  
24162 -                                               log_error_write(srv, __FILE__, __LINE__, "s", 
24163 +                                               log_error_write(srv, __FILE__, __LINE__, "s",
24164                                                                 "respawning failed, will retry later");
24165                                         }
24166 -                                       
24167 +
24168                                         break;
24169                                 }
24170 +#endif
24171                         }
24172  
24173                         if (con->file_started == 0) {
24174                                 /* nothing has been send out yet, try to use another child */
24175 -                               
24176 +
24177                                 if (hctx->wb->bytes_out == 0 &&
24178                                     hctx->reconnects < 5) {
24179                                         fcgi_reconnect(srv, hctx);
24180 -                                       
24181 -                                       log_error_write(srv, __FILE__, __LINE__, "ssbsbs", 
24182 +
24183 +                                       log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
24184                                                 "response not received, request not sent",
24185 -                                               "on socket:", proc->connection_name, 
24186 +                                               "on socket:", proc->connection_name,
24187                                                 "for", con->uri.path, ", reconnecting");
24188 -                                       
24189 +
24190                                         return HANDLER_WAIT_FOR_FD;
24191                                 }
24192 -                       
24193 -                               log_error_write(srv, __FILE__, __LINE__, "sosbsbs", 
24194 +
24195 +                               log_error_write(srv, __FILE__, __LINE__, "sosbsbs",
24196                                                 "response not received, request sent:", hctx->wb->bytes_out,
24197 -                                               "on socket:", proc->connection_name, 
24198 +                                               "on socket:", proc->connection_name,
24199                                                 "for", con->uri.path, ", closing connection");
24200 -                               
24201 +
24202                                 fcgi_connection_close(srv, hctx);
24203 -                               
24204 +
24205                                 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
24206                                 buffer_reset(con->physical.path);
24207                                 con->http_status = 500;
24208 @@ -3226,76 +3141,76 @@
24209                         } else {
24210                                 /* response might have been already started, kill the connection */
24211                                 fcgi_connection_close(srv, hctx);
24212 -                               
24213 -                               log_error_write(srv, __FILE__, __LINE__, "ssbsbs", 
24214 +
24215 +                               log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
24216                                                 "response already sent out, but backend returned error",
24217 -                                               "on socket:", proc->connection_name, 
24218 +                                               "on socket:", proc->connection_name,
24219                                                 "for", con->uri.path, ", terminating connection");
24220 -                               
24221 +
24222                                 connection_set_state(srv, con, CON_STATE_ERROR);
24223                         }
24224  
24225                         /* */
24226 -                       
24227 -                       
24228 +
24229 +
24230                         joblist_append(srv, con);
24231                         return HANDLER_FINISHED;
24232                 }
24233         }
24234 -       
24235 +
24236         if (revents & FDEVENT_OUT) {
24237                 if (hctx->state == FCGI_STATE_CONNECT_DELAYED ||
24238                     hctx->state == FCGI_STATE_WRITE) {
24239                         /* we are allowed to send something out
24240 -                        * 
24241 +                        *
24242                          * 1. in a unfinished connect() call
24243                          * 2. in a unfinished write() call (long POST request)
24244                          */
24245                         return mod_fastcgi_handle_subrequest(srv, con, p);
24246                 } else {
24247 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
24248 -                                       "got a FDEVENT_OUT and didn't know why:", 
24249 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
24250 +                                       "got a FDEVENT_OUT and didn't know why:",
24251                                         hctx->state);
24252                 }
24253         }
24254 -       
24255 +
24256         /* perhaps this issue is already handled */
24257         if (revents & FDEVENT_HUP) {
24258                 if (hctx->state == FCGI_STATE_CONNECT_DELAYED) {
24259                         /* getoptsock will catch this one (right ?)
24260 -                        * 
24261 -                        * if we are in connect we might get a EINPROGRESS 
24262 -                        * in the first call and a FDEVENT_HUP in the 
24263 +                        *
24264 +                        * if we are in connect we might get a EINPROGRESS
24265 +                        * in the first call and a FDEVENT_HUP in the
24266                          * second round
24267 -                        * 
24268 +                        *
24269                          * FIXME: as it is a bit ugly.
24270 -                        * 
24271 +                        *
24272                          */
24273                         return mod_fastcgi_handle_subrequest(srv, con, p);
24274                 } else if (hctx->state == FCGI_STATE_READ &&
24275                            hctx->proc->port == 0) {
24276                         /* FIXME:
24277 -                        * 
24278 +                        *
24279                          * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket
24280                          * even if the FCGI_FIN packet is not received yet
24281                          */
24282                 } else {
24283 -                       log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd", 
24284 -                                       "error: unexpected close of fastcgi connection for", 
24285 +                       log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
24286 +                                       "error: unexpected close of fastcgi connection for",
24287                                         con->uri.path,
24288 -                                       "(no fastcgi process on host:", 
24289 +                                       "(no fastcgi process on host:",
24290                                         host->host,
24291 -                                       ", port: ", 
24292 +                                       ", port: ",
24293                                         host->port,
24294                                         " ?)",
24295                                         hctx->state);
24296 -                       
24297 +
24298                         connection_set_state(srv, con, CON_STATE_ERROR);
24299                         fcgi_connection_close(srv, hctx);
24300                         joblist_append(srv, con);
24301                 }
24302         } else if (revents & FDEVENT_ERR) {
24303 -               log_error_write(srv, __FILE__, __LINE__, "s", 
24304 +               log_error_write(srv, __FILE__, __LINE__, "s",
24305                                 "fcgi: got a FDEVENT_ERR. Don't know why.");
24306                 /* kill all connections to the fastcgi process */
24307  
24308 @@ -3304,45 +3219,42 @@
24309                 fcgi_connection_close(srv, hctx);
24310                 joblist_append(srv, con);
24311         }
24312 -       
24313 +
24314         return HANDLER_FINISHED;
24315  }
24316 -#define PATCH(x) \
24317 -       p->conf.x = s->x;
24318 +
24319  static int fcgi_patch_connection(server *srv, connection *con, plugin_data *p) {
24320         size_t i, j;
24321         plugin_config *s = p->config_storage[0];
24322 -       
24323 -       PATCH(exts);
24324 -       PATCH(debug);
24325 -       PATCH(ext_mapping);
24326 -       
24327 +
24328 +       PATCH_OPTION(exts);
24329 +       PATCH_OPTION(debug);
24330 +       PATCH_OPTION(ext_mapping);
24331 +
24332         /* skip the first, the global context */
24333         for (i = 1; i < srv->config_context->used; i++) {
24334                 data_config *dc = (data_config *)srv->config_context->data[i];
24335                 s = p->config_storage[i];
24336 -               
24337 +
24338                 /* condition didn't match */
24339                 if (!config_check_cond(srv, con, dc)) continue;
24340 -               
24341 +
24342                 /* merge config */
24343                 for (j = 0; j < dc->value->used; j++) {
24344                         data_unset *du = dc->value->data[j];
24345 -                       
24346 +
24347                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.server"))) {
24348 -                               PATCH(exts);
24349 +                               PATCH_OPTION(exts);
24350                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.debug"))) {
24351 -                               PATCH(debug);
24352 +                               PATCH_OPTION(debug);
24353                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.map-extensions"))) {
24354 -                               PATCH(ext_mapping);
24355 +                               PATCH_OPTION(ext_mapping);
24356                         }
24357                 }
24358         }
24359 -       
24360 +
24361         return 0;
24362  }
24363 -#undef PATCH
24364 -
24365  
24366  static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
24367         plugin_data *p = p_d;
24368 @@ -3351,16 +3263,16 @@
24369         buffer *fn;
24370         fcgi_extension *extension = NULL;
24371         fcgi_extension_host *host = NULL;
24372 -       
24373 +
24374         /* Possibly, we processed already this request */
24375         if (con->file_started == 1) return HANDLER_GO_ON;
24376  
24377         fn = uri_path_handler ? con->uri.path : con->physical.path;
24378  
24379         if (buffer_is_empty(fn)) return HANDLER_GO_ON;
24380 -       
24381 +
24382         s_len = fn->used - 1;
24383 -       
24384 +
24385         fcgi_patch_connection(srv, con, p);
24386  
24387         /* fastcgi.map-extensions maps extensions to existing fastcgi.server entries
24388 @@ -3368,24 +3280,24 @@
24389          * fastcgi.map-extensions = ( ".php3" => ".php" )
24390          *
24391          * fastcgi.server = ( ".php" => ... )
24392 -        * 
24393 +        *
24394          * */
24395  
24396         /* check if extension-mapping matches */
24397         for (k = 0; k < p->conf.ext_mapping->used; k++) {
24398                 data_string *ds = (data_string *)p->conf.ext_mapping->data[k];
24399                 size_t ct_len; /* length of the config entry */
24400 -               
24401 +
24402                 if (ds->key->used == 0) continue;
24403 -               
24404 +
24405                 ct_len = ds->key->used - 1;
24406 -               
24407 +
24408                 if (s_len < ct_len) continue;
24409 -               
24410 +
24411                 /* found a mapping */
24412                 if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
24413                         /* check if we know the extension */
24414 -                       
24415 +
24416                         /* we can reuse k here */
24417                         for (k = 0; k < p->conf.exts->used; k++) {
24418                                 extension = p->conf.exts->exts[k];
24419 @@ -3407,15 +3319,15 @@
24420                 /* check if extension matches */
24421                 for (k = 0; k < p->conf.exts->used; k++) {
24422                         size_t ct_len; /* length of the config entry */
24423 -               
24424 +
24425                         extension = p->conf.exts->exts[k];
24426 -               
24427 +
24428                         if (extension->key->used == 0) continue;
24429 -               
24430 +
24431                         ct_len = extension->key->used - 1;
24432 -               
24433 +
24434                         if (s_len < ct_len) continue;
24435 -               
24436 +
24437                         /* check extension in the form "/fcgi_pattern" */
24438                         if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
24439                                 break;
24440 @@ -3441,10 +3353,10 @@
24441                         continue;
24442                 }
24443  
24444 -               /* we found one host that is alive */ 
24445 +               /* we found one host that is alive */
24446                 break;
24447         }
24448 -       
24449 +
24450         if (!host) {
24451                 /* sorry, we don't have a server alive for this ext */
24452                 buffer_reset(con->physical.path);
24453 @@ -3459,72 +3371,72 @@
24454                                         "on", extension->key,
24455                                         "are down.");
24456                 }
24457 -               
24458 +
24459                 return HANDLER_FINISHED;
24460         }
24461  
24462         /* a note about no handler is not sent yey */
24463         extension->note_is_sent = 0;
24464  
24465 -       /* 
24466 -        * if check-local is disabled, use the uri.path handler 
24467 -        * 
24468 +       /*
24469 +        * if check-local is disabled, use the uri.path handler
24470 +        *
24471          */
24472 -       
24473 +
24474         /* init handler-context */
24475         if (uri_path_handler) {
24476                 if (host->check_local == 0) {
24477                         handler_ctx *hctx;
24478                         char *pathinfo;
24479 -                       
24480 +
24481                         hctx = handler_ctx_init();
24482 -                       
24483 +
24484                         hctx->remote_conn      = con;
24485                         hctx->plugin_data      = p;
24486                         hctx->proc             = NULL;
24487                         hctx->ext              = extension;
24488 -       
24489 +
24490  
24491                         hctx->conf.exts        = p->conf.exts;
24492                         hctx->conf.debug       = p->conf.debug;
24493 -                               
24494 +
24495                         con->plugin_ctx[p->id] = hctx;
24496 -                               
24497 +
24498                         con->mode = p->id;
24499 -                               
24500 +
24501                         if (con->conf.log_request_handling) {
24502 -                               log_error_write(srv, __FILE__, __LINE__, "s", 
24503 +                               log_error_write(srv, __FILE__, __LINE__, "s",
24504                                 "handling it in mod_fastcgi");
24505                         }
24506 -                               
24507 -                       /* the prefix is the SCRIPT_NAME, 
24508 +
24509 +                       /* the prefix is the SCRIPT_NAME,
24510                          * everthing from start to the next slash
24511                          * this is important for check-local = "disable"
24512 -                        * 
24513 +                        *
24514                          * if prefix = /admin.fcgi
24515 -                        * 
24516 +                        *
24517                          * /admin.fcgi/foo/bar
24518 -                        * 
24519 +                        *
24520                          * SCRIPT_NAME = /admin.fcgi
24521                          * PATH_INFO   = /foo/bar
24522 -                        * 
24523 +                        *
24524                          * if prefix = /fcgi-bin/
24525 -                        * 
24526 +                        *
24527                          * /fcgi-bin/foo/bar
24528 -                        * 
24529 +                        *
24530                          * SCRIPT_NAME = /fcgi-bin/foo
24531                          * PATH_INFO   = /bar
24532 -                        * 
24533 +                        *
24534                          */
24535 -                       
24536 +
24537                         /* the rewrite is only done for /prefix/? matches */
24538                         if (extension->key->ptr[0] == '/' &&
24539                             con->uri.path->used > extension->key->used &&
24540                             NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) {
24541 -                               /* rewrite uri.path and pathinfo */ 
24542 -                               
24543 +                               /* rewrite uri.path and pathinfo */
24544 +
24545                                 buffer_copy_string(con->request.pathinfo, pathinfo);
24546 -                               
24547 +
24548                                 con->uri.path->used -= con->request.pathinfo->used - 1;
24549                                 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
24550                         }
24551 @@ -3532,19 +3444,19 @@
24552         } else {
24553                 handler_ctx *hctx;
24554                 hctx = handler_ctx_init();
24555 -               
24556 +
24557                 hctx->remote_conn      = con;
24558                 hctx->plugin_data      = p;
24559                 hctx->proc             = NULL;
24560                 hctx->ext              = extension;
24561 -               
24562 +
24563                 hctx->conf.exts        = p->conf.exts;
24564                 hctx->conf.debug       = p->conf.debug;
24565 -               
24566 +
24567                 con->plugin_ctx[p->id] = hctx;
24568 -               
24569 +
24570                 con->mode = p->id;
24571 -               
24572 +
24573                 if (con->conf.log_request_handling) {
24574                         log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
24575                 }
24576 @@ -3566,19 +3478,19 @@
24577  JOBLIST_FUNC(mod_fastcgi_handle_joblist) {
24578         plugin_data *p = p_d;
24579         handler_ctx *hctx = con->plugin_ctx[p->id];
24580 -       
24581 +
24582         if (hctx == NULL) return HANDLER_GO_ON;
24583  
24584         if (hctx->fd != -1) {
24585                 switch (hctx->state) {
24586                 case FCGI_STATE_READ:
24587                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
24588 -                       
24589 +
24590                         break;
24591                 case FCGI_STATE_CONNECT_DELAYED:
24592                 case FCGI_STATE_WRITE:
24593                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
24594 -                       
24595 +
24596                         break;
24597                 case FCGI_STATE_INIT:
24598                         /* at reconnect */
24599 @@ -3595,7 +3507,7 @@
24600  
24601  static handler_t fcgi_connection_close_callback(server *srv, connection *con, void *p_d) {
24602         plugin_data *p = p_d;
24603 -       
24604 +
24605         fcgi_connection_close(srv, con->plugin_ctx[p->id]);
24606  
24607         return HANDLER_GO_ON;
24608 @@ -3604,16 +3516,39 @@
24609  TRIGGER_FUNC(mod_fastcgi_handle_trigger) {
24610         plugin_data *p = p_d;
24611         size_t i, j, n;
24612 -       
24613 -       
24614 +
24615 +
24616         /* perhaps we should kill a connect attempt after 10-15 seconds
24617 -        * 
24618 +        *
24619          * currently we wait for the TCP timeout which is on Linux 180 seconds
24620 -        * 
24621 -        * 
24622 -        * 
24623 +        *
24624          */
24625  
24626 +       for (i = 0; i < srv->conns->used; i++) {
24627 +               connection *con = srv->conns->ptr[i];
24628 +               handler_ctx *hctx = con->plugin_ctx[p->id];
24629 +
24630 +               /* if a connection is ours and is in handle-req for more than max-request-time
24631 +                * kill the connection */
24632 +
24633 +               if (con->mode != p->id) continue;
24634 +               if (con->state != CON_STATE_HANDLE_REQUEST) continue;
24635 +               if (srv->cur_ts < con->request_start + 60) continue;
24636 +
24637 +               /* the request is waiting for a FCGI_STDOUT since 60 seconds */
24638 +
24639 +               /* kill the connection */
24640 +
24641 +               log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi backend didn't responded after 60 seconds");
24642 +
24643 +               fcgi_connection_close(srv, hctx);
24644 +
24645 +               con->mode = DIRECT;
24646 +               con->http_status = 500;
24647 +
24648 +               joblist_append(srv, con);
24649 +       }
24650 +
24651         /* check all childs if they are still up */
24652  
24653         for (i = 0; i < srv->config_context->used; i++) {
24654 @@ -3628,45 +3563,45 @@
24655                         fcgi_extension *ex;
24656  
24657                         ex = exts->exts[j];
24658 -                       
24659 +
24660                         for (n = 0; n < ex->used; n++) {
24661 -                               
24662 +
24663                                 fcgi_proc *proc;
24664                                 unsigned long sum_load = 0;
24665                                 fcgi_extension_host *host;
24666 -                               
24667 +
24668                                 host = ex->hosts[n];
24669 -                               
24670 +
24671                                 fcgi_restart_dead_procs(srv, p, host);
24672 -                               
24673 +
24674                                 for (proc = host->first; proc; proc = proc->next) {
24675                                         sum_load += proc->load;
24676                                 }
24677 -                               
24678 +
24679                                 if (host->num_procs &&
24680                                     host->num_procs < host->max_procs &&
24681                                     (sum_load / host->num_procs) > host->max_load_per_proc) {
24682                                         /* overload, spawn new child */
24683                                         if (p->conf.debug) {
24684 -                                               log_error_write(srv, __FILE__, __LINE__, "s", 
24685 +                                               log_error_write(srv, __FILE__, __LINE__, "s",
24686                                                                 "overload detected, spawning a new child");
24687                                         }
24688 -                                       
24689 +
24690                                         for (proc = host->unused_procs; proc && proc->pid != 0; proc = proc->next);
24691 -                                       
24692 +
24693                                         if (proc) {
24694                                                 if (proc == host->unused_procs) host->unused_procs = proc->next;
24695 -                                               
24696 +
24697                                                 if (proc->next) proc->next->prev = NULL;
24698 -                                               
24699 +
24700                                                 host->max_id++;
24701                                         } else {
24702                                                 proc = fastcgi_process_init();
24703                                                 proc->id = host->max_id++;
24704                                         }
24705 -                                       
24706 +
24707                                         host->num_procs++;
24708 -                                       
24709 +
24710                                         if (buffer_is_empty(host->unixsocket)) {
24711                                                 proc->port = host->port + proc->id;
24712                                         } else {
24713 @@ -3674,13 +3609,13 @@
24714                                                 buffer_append_string(proc->unixsocket, "-");
24715                                                 buffer_append_long(proc->unixsocket, proc->id);
24716                                         }
24717 -                                       
24718 +
24719                                         if (fcgi_spawn_connection(srv, p, host, proc)) {
24720                                                 log_error_write(srv, __FILE__, __LINE__, "s",
24721                                                                 "ERROR: spawning fcgi failed.");
24722                                                 return HANDLER_ERROR;
24723                                         }
24724 -                                       
24725 +
24726                                         proc->prev = NULL;
24727                                         proc->next = host->first;
24728                                         if (host->first) {
24729 @@ -3688,56 +3623,56 @@
24730                                         }
24731                                         host->first = proc;
24732                                 }
24733 -                               
24734 +
24735                                 for (proc = host->first; proc; proc = proc->next) {
24736                                         if (proc->load != 0) break;
24737                                         if (host->num_procs <= host->min_procs) break;
24738                                         if (proc->pid == 0) continue;
24739 -                                       
24740 +
24741                                         if (srv->cur_ts - proc->last_used > host->idle_timeout) {
24742                                                 /* a proc is idling for a long time now,
24743                                                  * terminated it */
24744 -                                               
24745 +
24746                                                 if (p->conf.debug) {
24747 -                                                       log_error_write(srv, __FILE__, __LINE__, "ssbsd", 
24748 -                                                                       "idle-timeout reached, terminating child:", 
24749 -                                                                       "socket:", proc->connection_name, 
24750 +                                                       log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24751 +                                                                       "idle-timeout reached, terminating child:",
24752 +                                                                       "socket:", proc->connection_name,
24753                                                                         "pid", proc->pid);
24754                                                 }
24755 -                                               
24756 -                                               
24757 +
24758 +
24759                                                 if (proc->next) proc->next->prev = proc->prev;
24760                                                 if (proc->prev) proc->prev->next = proc->next;
24761 -                                               
24762 +
24763                                                 if (proc->prev == NULL) host->first = proc->next;
24764 -                                               
24765 +
24766                                                 proc->prev = NULL;
24767                                                 proc->next = host->unused_procs;
24768 -                                               
24769 +
24770                                                 if (host->unused_procs) host->unused_procs->prev = proc;
24771                                                 host->unused_procs = proc;
24772 -                                               
24773 +
24774                                                 kill(proc->pid, SIGTERM);
24775 -                                               
24776 +
24777                                                 proc->state = PROC_STATE_KILLED;
24778 -                                               
24779 -                                               log_error_write(srv, __FILE__, __LINE__, "ssbsd", 
24780 -                                                                       "killed:", 
24781 -                                                                       "socket:", proc->connection_name, 
24782 +
24783 +                                               log_error_write(srv, __FILE__, __LINE__, "ssbsd",
24784 +                                                                       "killed:",
24785 +                                                                       "socket:", proc->connection_name,
24786                                                                         "pid", proc->pid);
24787 -                                               
24788 +
24789                                                 host->num_procs--;
24790 -                                               
24791 +
24792                                                 /* proc is now in unused, let the next second handle the next process */
24793                                                 break;
24794 -                                       }       
24795 +                                       }
24796                                 }
24797 -                               
24798 +
24799                                 for (proc = host->unused_procs; proc; proc = proc->next) {
24800                                         int status;
24801 -                                       
24802 +
24803                                         if (proc->pid == 0) continue;
24804 -                                       
24805 +#ifndef _WIN32
24806                                         switch (waitpid(proc->pid, &status, WNOHANG)) {
24807                                         case 0:
24808                                                 /* child still running after timeout, good */
24809 @@ -3745,10 +3680,10 @@
24810                                         case -1:
24811                                                 if (errno != EINTR) {
24812                                                         /* no PID found ? should never happen */
24813 -                                                       log_error_write(srv, __FILE__, __LINE__, "sddss", 
24814 +                                                       log_error_write(srv, __FILE__, __LINE__, "sddss",
24815                                                                         "pid ", proc->pid, proc->state,
24816                                                                         "not found:", strerror(errno));
24817 -                                                       
24818 +
24819  #if 0
24820                                                         if (errno == ECHILD) {
24821                                                                 /* someone else has cleaned up for us */
24822 @@ -3762,25 +3697,26 @@
24823                                                 /* the child should not terminate at all */
24824                                                 if (WIFEXITED(status)) {
24825                                                         if (proc->state != PROC_STATE_KILLED) {
24826 -                                                               log_error_write(srv, __FILE__, __LINE__, "sdb", 
24827 -                                                                               "child exited:", 
24828 +                                                               log_error_write(srv, __FILE__, __LINE__, "sdb",
24829 +                                                                               "child exited:",
24830                                                                                 WEXITSTATUS(status), proc->connection_name);
24831                                                         }
24832                                                 } else if (WIFSIGNALED(status)) {
24833                                                         if (WTERMSIG(status) != SIGTERM) {
24834 -                                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
24835 -                                                                               "child signaled:", 
24836 +                                                               log_error_write(srv, __FILE__, __LINE__, "sd",
24837 +                                                                               "child signaled:",
24838                                                                                 WTERMSIG(status));
24839                                                         }
24840                                                 } else {
24841 -                                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
24842 -                                                                       "child died somehow:", 
24843 +                                                       log_error_write(srv, __FILE__, __LINE__, "sd",
24844 +                                                                       "child died somehow:",
24845                                                                         status);
24846                                                 }
24847                                                 proc->pid = 0;
24848                                                 proc->state = PROC_STATE_UNSET;
24849                                                 host->max_id--;
24850                                         }
24851 +#endif
24852                                 }
24853                         }
24854                 }
24855 @@ -3804,8 +3740,8 @@
24856         p->handle_subrequest       = mod_fastcgi_handle_subrequest;
24857         p->handle_joblist          = mod_fastcgi_handle_joblist;
24858         p->handle_trigger          = mod_fastcgi_handle_trigger;
24859 -       
24860 +
24861         p->data         = NULL;
24862 -       
24863 +
24864         return 0;
24865  }
24866 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_flv_streaming.c lighttpd-1.4.12/src/mod_flv_streaming.c
24867 --- lighttpd-1.4.11/src/mod_flv_streaming.c     2006-03-07 14:06:26.000000000 +0200
24868 +++ lighttpd-1.4.12/src/mod_flv_streaming.c     2006-07-11 21:23:40.000000000 +0300
24869 @@ -23,35 +23,35 @@
24870  
24871  typedef struct {
24872         PLUGIN_DATA;
24873 -       
24874 +
24875         buffer *query_str;
24876         array *get_params;
24877 -       
24878 +
24879         plugin_config **config_storage;
24880 -       
24881 -       plugin_config conf; 
24882 +
24883 +       plugin_config conf;
24884  } plugin_data;
24885  
24886  /* init the plugin data */
24887  INIT_FUNC(mod_flv_streaming_init) {
24888         plugin_data *p;
24889 -       
24890 +
24891         p = calloc(1, sizeof(*p));
24892 -       
24893 +
24894         p->query_str = buffer_init();
24895         p->get_params = array_init();
24896 -       
24897 +
24898         return p;
24899  }
24900  
24901  /* detroy the plugin data */
24902  FREE_FUNC(mod_flv_streaming_free) {
24903         plugin_data *p = p_d;
24904 -       
24905 +
24906         UNUSED(srv);
24907  
24908         if (!p) return HANDLER_GO_ON;
24909 -       
24910 +
24911         if (p->config_storage) {
24912                 size_t i;
24913  
24914 @@ -59,19 +59,19 @@
24915                         plugin_config *s = p->config_storage[i];
24916  
24917                         if (!s) continue;
24918 -                       
24919 +
24920                         array_free(s->extensions);
24921 -                       
24922 +
24923                         free(s);
24924                 }
24925                 free(p->config_storage);
24926         }
24927 -       
24928 +
24929         buffer_free(p->query_str);
24930         array_free(p->get_params);
24931 -       
24932 +
24933         free(p);
24934 -       
24935 +
24936         return HANDLER_GO_ON;
24937  }
24938  
24939 @@ -80,83 +80,80 @@
24940  SETDEFAULTS_FUNC(mod_flv_streaming_set_defaults) {
24941         plugin_data *p = p_d;
24942         size_t i = 0;
24943 -       
24944 -       config_values_t cv[] = { 
24945 +
24946 +       config_values_t cv[] = {
24947                 { "flv-streaming.extensions",   NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
24948                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
24949         };
24950 -       
24951 +
24952         if (!p) return HANDLER_ERROR;
24953 -       
24954 +
24955         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
24956 -       
24957 +
24958         for (i = 0; i < srv->config_context->used; i++) {
24959                 plugin_config *s;
24960 -               
24961 +
24962                 s = calloc(1, sizeof(plugin_config));
24963                 s->extensions     = array_init();
24964 -               
24965 +
24966                 cv[0].destination = s->extensions;
24967 -               
24968 +
24969                 p->config_storage[i] = s;
24970 -       
24971 +
24972                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
24973                         return HANDLER_ERROR;
24974                 }
24975         }
24976 -       
24977 +
24978         return HANDLER_GO_ON;
24979  }
24980  
24981 -#define PATCH(x) \
24982 -       p->conf.x = s->x;
24983  static int mod_flv_streaming_patch_connection(server *srv, connection *con, plugin_data *p) {
24984         size_t i, j;
24985         plugin_config *s = p->config_storage[0];
24986 -       
24987 -       PATCH(extensions);
24988 -       
24989 +
24990 +       PATCH_OPTION(extensions);
24991 +
24992         /* skip the first, the global context */
24993         for (i = 1; i < srv->config_context->used; i++) {
24994                 data_config *dc = (data_config *)srv->config_context->data[i];
24995                 s = p->config_storage[i];
24996 -               
24997 +
24998                 /* condition didn't match */
24999                 if (!config_check_cond(srv, con, dc)) continue;
25000 -               
25001 +
25002                 /* merge config */
25003                 for (j = 0; j < dc->value->used; j++) {
25004                         data_unset *du = dc->value->data[j];
25005 -                       
25006 +
25007                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("flv-streaming.extensions"))) {
25008 -                               PATCH(extensions);
25009 +                               PATCH_OPTION(extensions);
25010                         }
25011                 }
25012         }
25013 -       
25014 +
25015         return 0;
25016  }
25017 -#undef PATCH
25018  
25019 -static int split_get_params(server *srv, connection *con, array *get_params, buffer *qrystr) {
25020 +static int split_get_params(array *get_params, buffer *qrystr) {
25021         size_t is_key = 1;
25022         size_t i;
25023         char *key = NULL, *val = NULL;
25024 -       
25025 +
25026         key = qrystr->ptr;
25027 -       
25028 +
25029         /* we need the \0 */
25030         for (i = 0; i < qrystr->used; i++) {
25031                 switch(qrystr->ptr[i]) {
25032                 case '=':
25033                         if (is_key) {
25034                                 val = qrystr->ptr + i + 1;
25035 -                               
25036 +
25037                                 qrystr->ptr[i] = '\0';
25038 -                               
25039 +
25040                                 is_key = 0;
25041                         }
25042 -                       
25043 +
25044                         break;
25045                 case '&':
25046                 case '\0': /* fin symbol */
25047 @@ -167,7 +164,7 @@
25048                                 /* terminate the value */
25049                                 qrystr->ptr[i] = '\0';
25050  
25051 -                               if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
25052 +                               if (NULL == (ds = (data_string *)array_get_unused_element(get_params, TYPE_STRING))) {
25053                                         ds = data_string_init();
25054                                 }
25055                                 buffer_copy_string_len(ds->key, key, strlen(key));
25056 @@ -175,14 +172,14 @@
25057  
25058                                 array_insert_unique(get_params, (data_unset *)ds);
25059                         }
25060 -                       
25061 +
25062                         key = qrystr->ptr + i + 1;
25063                         val = NULL;
25064                         is_key = 1;
25065                         break;
25066                 }
25067         }
25068 -       
25069 +
25070         return 0;
25071  }
25072  
25073 @@ -190,34 +187,34 @@
25074         plugin_data *p = p_d;
25075         int s_len;
25076         size_t k;
25077 -       
25078 +
25079         UNUSED(srv);
25080  
25081         if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON;
25082 -       
25083 +
25084         mod_flv_streaming_patch_connection(srv, con, p);
25085  
25086         s_len = con->physical.path->used - 1;
25087 -       
25088 +
25089         for (k = 0; k < p->conf.extensions->used; k++) {
25090                 data_string *ds = (data_string *)p->conf.extensions->data[k];
25091                 int ct_len = ds->value->used - 1;
25092 -               
25093 +
25094                 if (ct_len > s_len) continue;
25095                 if (ds->value->used == 0) continue;
25096 -               
25097 +
25098                 if (0 == strncmp(con->physical.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
25099                         data_string *get_param;
25100                         stat_cache_entry *sce = NULL;
25101                         buffer *b;
25102                         int start;
25103                         char *err = NULL;
25104 -                       /* if there is a start=[0-9]+ in the header use it as start, 
25105 +                       /* if there is a start=[0-9]+ in the header use it as start,
25106                          * otherwise send the full file */
25107  
25108                         array_reset(p->get_params);
25109                         buffer_copy_string_buffer(p->query_str, con->uri.query);
25110 -                       split_get_params(srv, con, p->get_params, p->query_str);
25111 +                       split_get_params(p->get_params, p->query_str);
25112  
25113                         if (NULL == (get_param = (data_string *)array_get_element(p->get_params, "start"))) {
25114                                 return HANDLER_GO_ON;
25115 @@ -256,7 +253,7 @@
25116                         return HANDLER_FINISHED;
25117                 }
25118         }
25119 -       
25120 +
25121         /* not found */
25122         return HANDLER_GO_ON;
25123  }
25124 @@ -266,13 +263,13 @@
25125  int mod_flv_streaming_plugin_init(plugin *p) {
25126         p->version     = LIGHTTPD_VERSION_ID;
25127         p->name        = buffer_init_string("flv_streaming");
25128 -       
25129 +
25130         p->init        = mod_flv_streaming_init;
25131         p->handle_physical = mod_flv_streaming_path_handler;
25132         p->set_defaults  = mod_flv_streaming_set_defaults;
25133         p->cleanup     = mod_flv_streaming_free;
25134 -       
25135 +
25136         p->data        = NULL;
25137 -       
25138 +
25139         return 0;
25140  }
25141 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_indexfile.c lighttpd-1.4.12/src/mod_indexfile.c
25142 --- lighttpd-1.4.11/src/mod_indexfile.c 2005-09-30 01:08:53.000000000 +0300
25143 +++ lighttpd-1.4.12/src/mod_indexfile.c 2006-07-11 21:23:40.000000000 +0300
25144 @@ -20,51 +20,51 @@
25145  
25146  typedef struct {
25147         PLUGIN_DATA;
25148 -       
25149 +
25150         buffer *tmp_buf;
25151 -       
25152 +
25153         plugin_config **config_storage;
25154 -       
25155 -       plugin_config conf; 
25156 +
25157 +       plugin_config conf;
25158  } plugin_data;
25159  
25160  /* init the plugin data */
25161  INIT_FUNC(mod_indexfile_init) {
25162         plugin_data *p;
25163 -       
25164 +
25165         p = calloc(1, sizeof(*p));
25166 -       
25167 +
25168         p->tmp_buf = buffer_init();
25169 -       
25170 +
25171         return p;
25172  }
25173  
25174  /* detroy the plugin data */
25175  FREE_FUNC(mod_indexfile_free) {
25176         plugin_data *p = p_d;
25177 -       
25178 +
25179         UNUSED(srv);
25180  
25181         if (!p) return HANDLER_GO_ON;
25182 -       
25183 +
25184         if (p->config_storage) {
25185                 size_t i;
25186                 for (i = 0; i < srv->config_context->used; i++) {
25187                         plugin_config *s = p->config_storage[i];
25188  
25189                         if (!s) continue;
25190 -                       
25191 +
25192                         array_free(s->indexfiles);
25193 -                       
25194 +
25195                         free(s);
25196                 }
25197                 free(p->config_storage);
25198         }
25199 -       
25200 +
25201         buffer_free(p->tmp_buf);
25202 -       
25203 +
25204         free(p);
25205 -       
25206 +
25207         return HANDLER_GO_ON;
25208  }
25209  
25210 @@ -73,131 +73,128 @@
25211  SETDEFAULTS_FUNC(mod_indexfile_set_defaults) {
25212         plugin_data *p = p_d;
25213         size_t i = 0;
25214 -       
25215 -       config_values_t cv[] = { 
25216 +
25217 +       config_values_t cv[] = {
25218                 { "index-file.names",           NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
25219                 { "server.indexfiles",          NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
25220                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
25221         };
25222 -       
25223 +
25224         if (!p) return HANDLER_ERROR;
25225 -       
25226 +
25227         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
25228 -       
25229 +
25230         for (i = 0; i < srv->config_context->used; i++) {
25231                 plugin_config *s;
25232 -               
25233 +
25234                 s = calloc(1, sizeof(plugin_config));
25235                 s->indexfiles    = array_init();
25236 -               
25237 +
25238                 cv[0].destination = s->indexfiles;
25239                 cv[1].destination = s->indexfiles; /* old name for [0] */
25240 -               
25241 +
25242                 p->config_storage[i] = s;
25243 -       
25244 +
25245                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
25246                         return HANDLER_ERROR;
25247                 }
25248         }
25249 -       
25250 +
25251         return HANDLER_GO_ON;
25252  }
25253  
25254 -#define PATCH(x) \
25255 -       p->conf.x = s->x;
25256  static int mod_indexfile_patch_connection(server *srv, connection *con, plugin_data *p) {
25257         size_t i, j;
25258         plugin_config *s = p->config_storage[0];
25259 -       
25260 -       PATCH(indexfiles);
25261 -       
25262 +
25263 +       PATCH_OPTION(indexfiles);
25264 +
25265         /* skip the first, the global context */
25266         for (i = 1; i < srv->config_context->used; i++) {
25267                 data_config *dc = (data_config *)srv->config_context->data[i];
25268                 s = p->config_storage[i];
25269 -               
25270 +
25271                 /* condition didn't match */
25272                 if (!config_check_cond(srv, con, dc)) continue;
25273 -               
25274 +
25275                 /* merge config */
25276                 for (j = 0; j < dc->value->used; j++) {
25277                         data_unset *du = dc->value->data[j];
25278 -                       
25279 +
25280                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.indexfiles"))) {
25281 -                               PATCH(indexfiles);
25282 +                               PATCH_OPTION(indexfiles);
25283                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("index-file.names"))) {
25284 -                               PATCH(indexfiles);
25285 +                               PATCH_OPTION(indexfiles);
25286                         }
25287                 }
25288         }
25289 -       
25290 +
25291         return 0;
25292  }
25293 -#undef PATCH
25294  
25295  URIHANDLER_FUNC(mod_indexfile_subrequest) {
25296         plugin_data *p = p_d;
25297         size_t k;
25298         stat_cache_entry *sce = NULL;
25299 -       
25300 +
25301         if (con->uri.path->used == 0) return HANDLER_GO_ON;
25302         if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
25303 -       
25304 +
25305         mod_indexfile_patch_connection(srv, con, p);
25306 -       
25307 +
25308         if (con->conf.log_request_handling) {
25309                 log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling the request as Indexfile");
25310                 log_error_write(srv, __FILE__, __LINE__,  "sb", "URI          :", con->uri.path);
25311         }
25312 -       
25313 +
25314         /* indexfile */
25315         for (k = 0; k < p->conf.indexfiles->used; k++) {
25316                 data_string *ds = (data_string *)p->conf.indexfiles->data[k];
25317 -               
25318 +
25319                 if (ds->value && ds->value->ptr[0] == '/') {
25320 -                       /* if the index-file starts with a prefix as use this file as 
25321 +                       /* if the index-file starts with a prefix as use this file as
25322                          * index-generator */
25323                         buffer_copy_string_buffer(p->tmp_buf, con->physical.doc_root);
25324                 } else {
25325                         buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
25326                 }
25327                 buffer_append_string_buffer(p->tmp_buf, ds->value);
25328 -               
25329 +
25330                 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
25331                         if (errno == EACCES) {
25332                                 con->http_status = 403;
25333                                 buffer_reset(con->physical.path);
25334 -                               
25335 +
25336                                 return HANDLER_FINISHED;
25337                         }
25338 -                       
25339 +
25340                         if (errno != ENOENT &&
25341                             errno != ENOTDIR) {
25342                                 /* we have no idea what happend. let's tell the user so. */
25343 -                               
25344 +
25345                                 con->http_status = 500;
25346 -                               
25347 +
25348                                 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
25349                                                 "file not found ... or so: ", strerror(errno),
25350                                                 con->uri.path,
25351                                                 "->", con->physical.path);
25352 -                               
25353 +
25354                                 buffer_reset(con->physical.path);
25355 -                               
25356 +
25357                                 return HANDLER_FINISHED;
25358                         }
25359                         continue;
25360                 }
25361 -                       
25362 +
25363                 /* rewrite uri.path to the real path (/ -> /index.php) */
25364                 buffer_append_string_buffer(con->uri.path, ds->value);
25365                 buffer_copy_string_buffer(con->physical.path, p->tmp_buf);
25366 -               
25367 +
25368                 /* fce is already set up a few lines above */
25369 -               
25370 +
25371                 return HANDLER_GO_ON;
25372         }
25373 -       
25374 +
25375         /* not found */
25376         return HANDLER_GO_ON;
25377  }
25378 @@ -207,13 +204,13 @@
25379  int mod_indexfile_plugin_init(plugin *p) {
25380         p->version     = LIGHTTPD_VERSION_ID;
25381         p->name        = buffer_init_string("indexfile");
25382 -       
25383 +
25384         p->init        = mod_indexfile_init;
25385         p->handle_subrequest_start = mod_indexfile_subrequest;
25386         p->set_defaults  = mod_indexfile_set_defaults;
25387         p->cleanup     = mod_indexfile_free;
25388 -       
25389 +
25390         p->data        = NULL;
25391 -       
25392 +
25393         return 0;
25394  }
25395 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_mysql_vhost.c lighttpd-1.4.12/src/mod_mysql_vhost.c
25396 --- lighttpd-1.4.11/src/mod_mysql_vhost.c       2006-01-14 20:35:10.000000000 +0200
25397 +++ lighttpd-1.4.12/src/mod_mysql_vhost.c       2006-07-11 21:23:40.000000000 +0300
25398 @@ -1,13 +1,18 @@
25399 -#include <unistd.h>
25400  #include <stdio.h>
25401  #include <errno.h>
25402  #include <fcntl.h>
25403 -#include <strings.h>
25404 +#include <string.h>
25405  
25406  #ifdef HAVE_CONFIG_H
25407  #include "config.h"
25408  #endif
25409  
25410 +#ifdef HAVE_MYSQL_H 
25411 +# ifdef HAVE_LIBMYSQL
25412 +#  define HAVE_MYSQL
25413 +# endif
25414 +#endif
25415 +
25416  #ifdef HAVE_MYSQL
25417  #include <mysql.h>
25418  #endif
25419 @@ -16,61 +21,40 @@
25420  #include "log.h"
25421  
25422  #include "stat_cache.h"
25423 -#ifdef DEBUG_MOD_MYSQL_VHOST
25424 -#define DEBUG
25425 -#endif
25426 +#include "sys-files.h"
25427  
25428 -/*
25429 - * Plugin for lighttpd to use MySQL 
25430 - *   for domain to directory lookups,
25431 - *   i.e virtual hosts (vhosts).
25432 - *   
25433 - * Optionally sets fcgi_offset and fcgi_arg 
25434 - *   in preparation for fcgi.c to handle 
25435 - *   per-user fcgi chroot jails.
25436 - *
25437 - * /ada@riksnet.se 2004-12-06
25438 - */
25439 +#include "mod_sql_vhost_core.h"
25440  
25441  #ifdef HAVE_MYSQL
25442 +
25443 +#define CORE_PLUGIN "mod_sql_vhost_core"
25444 +
25445  typedef struct {
25446         MYSQL   *mysql;
25447 -       
25448 -       buffer  *mydb;
25449 -       buffer  *myuser;
25450 -       buffer  *mypass;
25451 -       buffer  *mysock;
25452 -       
25453 -       buffer  *hostname;
25454 -       unsigned short port;
25455 -       
25456 +
25457         buffer  *mysql_pre;
25458         buffer  *mysql_post;
25459 +
25460 +       mod_sql_vhost_core_plugin_config *core;
25461  } plugin_config;
25462  
25463  /* global plugin data */
25464  typedef struct {
25465         PLUGIN_DATA;
25466 -       
25467 +
25468         buffer  *tmp_buf;
25469 -       
25470 +
25471         plugin_config **config_storage;
25472 -       
25473 -       plugin_config conf; 
25474 +
25475 +       plugin_config conf;
25476  } plugin_data;
25477  
25478 -/* per connection plugin data */
25479 -typedef struct {
25480 -       buffer  *server_name;
25481 -       buffer  *document_root;
25482 -       buffer  *fcgi_arg;
25483 -       unsigned fcgi_offset;
25484 -} plugin_connection_data;
25485 +SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost); 
25486  
25487  /* init the plugin data */
25488  INIT_FUNC(mod_mysql_vhost_init) {
25489         plugin_data *p;
25490 -       
25491 +
25492         p = calloc(1, sizeof(*p));
25493  
25494         p->tmp_buf = buffer_init();
25495 @@ -83,144 +67,77 @@
25496         plugin_data *p = p_d;
25497  
25498         UNUSED(srv);
25499 -       
25500 -#ifdef DEBUG
25501 -       log_error_write(srv, __FILE__, __LINE__, "ss", 
25502 -               "mod_mysql_vhost_cleanup", p ? "yes" : "NO");
25503 -#endif
25504 +
25505         if (!p) return HANDLER_GO_ON;
25506 -       
25507 +
25508         if (p->config_storage) {
25509                 size_t i;
25510                 for (i = 0; i < srv->config_context->used; i++) {
25511                         plugin_config *s = p->config_storage[i];
25512  
25513                         if (!s) continue;
25514 -                       
25515 +
25516                         mysql_close(s->mysql);
25517 -                       
25518 -                       buffer_free(s->mydb);
25519 -                       buffer_free(s->myuser);
25520 -                       buffer_free(s->mypass);
25521 -                       buffer_free(s->mysock);
25522 +
25523                         buffer_free(s->mysql_pre);
25524                         buffer_free(s->mysql_post);
25525 -                       
25526 +
25527                         free(s);
25528                 }
25529                 free(p->config_storage);
25530         }
25531         buffer_free(p->tmp_buf);
25532 -       
25533 -       free(p);
25534  
25535 -       return HANDLER_GO_ON;
25536 -}
25537 -
25538 -/* handle the plugin per connection data */
25539 -static void* mod_mysql_vhost_connection_data(server *srv, connection *con, void *p_d)
25540 -{
25541 -       plugin_data *p = p_d;
25542 -       plugin_connection_data *c = con->plugin_ctx[p->id];
25543 -
25544 -       UNUSED(srv);
25545 -
25546 -#ifdef DEBUG
25547 -        log_error_write(srv, __FILE__, __LINE__, "ss", 
25548 -               "mod_mysql_connection_data", c ? "old" : "NEW");
25549 -#endif
25550 -
25551 -       if (c) return c;
25552 -       c = calloc(1, sizeof(*c));
25553 -
25554 -       c->server_name = buffer_init();
25555 -       c->document_root = buffer_init();
25556 -       c->fcgi_arg = buffer_init();
25557 -       c->fcgi_offset = 0;
25558 -
25559 -       return con->plugin_ctx[p->id] = c;
25560 -}
25561 -
25562 -/* destroy the plugin per connection data */
25563 -CONNECTION_FUNC(mod_mysql_vhost_handle_connection_close) {
25564 -       plugin_data *p = p_d;
25565 -       plugin_connection_data *c = con->plugin_ctx[p->id];
25566 -
25567 -       UNUSED(srv);
25568 -
25569 -#ifdef DEBUG
25570 -       log_error_write(srv, __FILE__, __LINE__, "ss", 
25571 -               "mod_mysql_vhost_handle_connection_close", c ? "yes" : "NO");
25572 -#endif
25573 -       
25574 -       if (!c) return HANDLER_GO_ON;
25575 -
25576 -       buffer_free(c->server_name);
25577 -       buffer_free(c->document_root);
25578 -       buffer_free(c->fcgi_arg);
25579 -       c->fcgi_offset = 0;
25580 -
25581 -       free(c);
25582 +       free(p);
25583  
25584 -       con->plugin_ctx[p->id] = NULL;
25585         return HANDLER_GO_ON;
25586  }
25587  
25588  /* set configuration values */
25589  SERVER_FUNC(mod_mysql_vhost_set_defaults) {
25590         plugin_data *p = p_d;
25591 +       mod_sql_vhost_core_plugin_data *core_config;
25592  
25593 -       char *qmark;
25594         size_t i = 0;
25595  
25596 -       config_values_t cv[] = {
25597 -               { "mysql-vhost.db",     NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER },
25598 -               { "mysql-vhost.user",   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER },
25599 -               { "mysql-vhost.pass",   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER },
25600 -               { "mysql-vhost.sock",   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER },
25601 -               { "mysql-vhost.sql",    NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER },
25602 -               { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER },
25603 -               { "mysql-vhost.port",   NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_SERVER },
25604 -                { NULL,                        NULL, T_CONFIG_UNSET,   T_CONFIG_SCOPE_UNSET }
25605 -        };
25606 -       
25607 +       /* our very own plugin storage, one entry for each conditional
25608 +        * 
25609 +        * srv->config_context->used is the number of conditionals
25610 +        * */
25611         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
25612 -       
25613 +
25614 +       /* get the config of the core-plugin */
25615 +       core_config = plugin_get_config(srv, CORE_PLUGIN);
25616 +
25617 +
25618 +       /* walk through all conditionals and check for assignments */
25619         for (i = 0; i < srv->config_context->used; i++) {
25620                 plugin_config *s;
25621                 buffer *sel;
25622 -               
25623 -               
25624 +               char *qmark;
25625 +
25626 +               /* get the config from the core plugin for this conditional-context */
25627                 s = calloc(1, sizeof(plugin_config));
25628 -               s->mydb = buffer_init();
25629 -               s->myuser = buffer_init();
25630 -               s->mypass = buffer_init();
25631 -               s->mysock = buffer_init();
25632 -               s->hostname = buffer_init();
25633 -               s->port   = 0;               /* default port for mysql */
25634 -               sel = buffer_init();
25635 -               s->mysql = NULL;
25636 +
25637 +               s->core = core_config->config_storage[i];
25638                 
25639 +               s->mysql = NULL;
25640 +
25641                 s->mysql_pre = buffer_init();
25642                 s->mysql_post = buffer_init();
25643 -               
25644 -               cv[0].destination = s->mydb;
25645 -               cv[1].destination = s->myuser;
25646 -               cv[2].destination = s->mypass;
25647 -               cv[3].destination = s->mysock;
25648 -               cv[4].destination = sel;
25649 -               cv[5].destination = s->hostname;
25650 -               cv[6].destination = &(s->port);
25651 -               
25652 +
25653                 p->config_storage[i] = s;
25654 -               
25655 -               if (config_insert_values_global(srv, 
25656 -                       ((data_config *)srv->config_context->data[i])->value,
25657 -                       cv)) return HANDLER_ERROR;
25658 -               
25659 -               s->mysql_pre = buffer_init();
25660 -               s->mysql_post = buffer_init();
25661 -               
25662 +
25663 +               /* check if we are the plugin for this backend */
25664 +               if (!buffer_is_equal_string(s->core->backend, CONST_STR_LEN("mysql"))) continue;
25665 +
25666 +               /* attach us to the core-plugin */
25667 +               s->core->backend_data = p;
25668 +               s->core->get_vhost = mod_mysql_vhost_get_vhost;
25669 +
25670 +               sel = buffer_init();
25671 +               buffer_copy_string_buffer(sel, s->core->select_vhost);
25672 +
25673                 if (sel->used && (qmark = index(sel->ptr, '?'))) {
25674                         *qmark = '\0';
25675                         buffer_copy_string(s->mysql_pre, sel->ptr);
25676 @@ -228,35 +145,35 @@
25677                 } else {
25678                         buffer_copy_string_buffer(s->mysql_pre, sel);
25679                 }
25680 -               
25681 +
25682                 /* required:
25683                  * - username
25684 -                * - database 
25685 -                * 
25686 +                * - database
25687 +                *
25688                  * optional:
25689                  * - password, default: empty
25690                  * - socket, default: mysql default
25691                  * - hostname, if set overrides socket
25692                  * - port, default: 3306
25693                  */
25694 -               
25695 +
25696                 /* all have to be set */
25697 -               if (!(buffer_is_empty(s->myuser) ||
25698 -                     buffer_is_empty(s->mydb))) {
25699 +               if (!(buffer_is_empty(s->core->user) ||
25700 +                     buffer_is_empty(s->core->db))) {
25701  
25702                         int fd;
25703 -               
25704 +
25705                         if (NULL == (s->mysql = mysql_init(NULL))) {
25706                                 log_error_write(srv, __FILE__, __LINE__, "s", "mysql_init() failed, exiting...");
25707 -                               
25708 +
25709                                 return HANDLER_ERROR;
25710                         }
25711 -#define FOO(x) (s->x->used ? s->x->ptr : NULL)
25712 -                       
25713 -                       if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(myuser), FOO(mypass), 
25714 -                                               FOO(mydb), s->port, FOO(mysock), 0)) {
25715 +#define FOO(x) (s->core->x->used ? s->core->x->ptr : NULL)
25716 +
25717 +                       if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(user), FOO(pass),
25718 +                                               FOO(db), s->core->port, FOO(sock), 0)) {
25719                                 log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(s->mysql));
25720 -                               
25721 +
25722                                 return HANDLER_ERROR;
25723                         }
25724  #undef FOO
25725 @@ -265,61 +182,47 @@
25726                         /* otherwise we cannot be sure that mysql is fd i-1 */
25727                         if (-1 == (fd = open("/dev/null", 0))) {
25728                                 close(fd);
25729 -                               fcntl(fd-1, F_SETFD, FD_CLOEXEC); 
25730 +                               fcntl(fd-1, F_SETFD, FD_CLOEXEC);
25731                         }
25732                 }
25733         }
25734 -       
25735 -       
25736 +
25737 +
25738  
25739          return HANDLER_GO_ON;
25740  }
25741  
25742 -#define PATCH(x) \
25743 -       p->conf.x = s->x;
25744  static int mod_mysql_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
25745 -       size_t i, j;
25746 +       size_t i;
25747         plugin_config *s = p->config_storage[0];
25748 -       
25749 -       PATCH(mysql_pre);
25750 -       PATCH(mysql_post);
25751 -#ifdef HAVE_MYSQL
25752 -       PATCH(mysql);
25753 -#endif
25754 -       
25755 +
25756 +       PATCH_OPTION(mysql_pre);
25757 +       PATCH_OPTION(mysql_post);
25758 +       PATCH_OPTION(mysql);
25759 +
25760         /* skip the first, the global context */
25761         for (i = 1; i < srv->config_context->used; i++) {
25762                 data_config *dc = (data_config *)srv->config_context->data[i];
25763                 s = p->config_storage[i];
25764 -               
25765 +
25766                 /* condition didn't match */
25767                 if (!config_check_cond(srv, con, dc)) continue;
25768 -               
25769 -               /* merge config */
25770 -               for (j = 0; j < dc->value->used; j++) {
25771 -                       data_unset *du = dc->value->data[j];
25772 -                       
25773 -                       if (buffer_is_equal_string(du->key, CONST_STR_LEN("mysql-vhost.sql"))) {
25774 -                               PATCH(mysql_pre);
25775 -                               PATCH(mysql_post);
25776 -                       }
25777 -               }
25778 -               
25779 +
25780                 if (s->mysql) {
25781 -                       PATCH(mysql);
25782 +                       PATCH_OPTION(mysql);
25783 +                       PATCH_OPTION(mysql_pre);
25784 +                       PATCH_OPTION(mysql_post);
25785                 }
25786         }
25787 -       
25788 +
25789         return 0;
25790  }
25791 -#undef PATCH
25792  
25793 -
25794 -/* handle document root request */
25795 -CONNECTION_FUNC(mod_mysql_vhost_handle_docroot) {
25796 +/**
25797 + * get the vhost info from the database 
25798 + */
25799 +SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost) {
25800         plugin_data *p = p_d;
25801 -       plugin_connection_data *c;
25802 -       stat_cache_entry *sce;
25803  
25804         unsigned  cols;
25805         MYSQL_ROW row;
25806 @@ -332,13 +235,6 @@
25807  
25808         if (!p->conf.mysql) return HANDLER_GO_ON;
25809  
25810 -       /* sets up connection data if not done yet */
25811 -       c = mod_mysql_vhost_connection_data(srv, con, p_d);
25812 -
25813 -       /* check if cached this connection */
25814 -       if (c->server_name->used && /* con->uri.authority->used && */
25815 -            buffer_is_equal(c->server_name, con->uri.authority)) goto GO_ON;
25816 -
25817         /* build and run SQL query */
25818         buffer_copy_string_buffer(p->tmp_buf, p->conf.mysql_pre);
25819         if (p->conf.mysql_post->used) {
25820 @@ -347,77 +243,43 @@
25821         }
25822         if (mysql_query(p->conf.mysql, p->tmp_buf->ptr)) {
25823                 log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(p->conf.mysql));
25824 -               goto ERR500;
25825 +
25826 +               mysql_free_result(result);
25827 +               return HANDLER_GO_ON;
25828         }
25829         result = mysql_store_result(p->conf.mysql);
25830         cols = mysql_num_fields(result);
25831         row = mysql_fetch_row(result);
25832 +
25833         if (!row || cols < 1) {
25834                 /* no such virtual host */
25835                 mysql_free_result(result);
25836                 return HANDLER_GO_ON;
25837         }
25838  
25839 -       /* sanity check that really is a directory */
25840 -       buffer_copy_string(p->tmp_buf, row[0]);
25841 -       BUFFER_APPEND_SLASH(p->tmp_buf);
25842 -
25843 -       if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
25844 -               log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
25845 -               goto ERR500;
25846 -       }
25847 -        if (!S_ISDIR(sce->st.st_mode)) {
25848 -               log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->tmp_buf);
25849 -               goto ERR500;
25850 -       }
25851 +       buffer_copy_string(docroot, row[0]);
25852  
25853 -       /* cache the data */
25854 -       buffer_copy_string_buffer(c->server_name, con->uri.authority);
25855 -       buffer_copy_string_buffer(c->document_root, p->tmp_buf);
25856 -
25857 -       /* fcgi_offset and fcgi_arg are optional */
25858 -       if (cols > 1 && row[1]) {
25859 -               c->fcgi_offset = atoi(row[1]);
25860 -               
25861 -               if (cols > 2 && row[2]) {
25862 -                       buffer_copy_string(c->fcgi_arg, row[2]);
25863 -               } else {
25864 -                       c->fcgi_arg->used = 0;
25865 -               }
25866 -       } else {
25867 -               c->fcgi_offset = c->fcgi_arg->used = 0;
25868 -       }
25869         mysql_free_result(result);
25870  
25871 -       /* fix virtual server and docroot */
25872 -GO_ON: buffer_copy_string_buffer(con->server_name, c->server_name);
25873 -       buffer_copy_string_buffer(con->physical.doc_root, c->document_root);
25874 -
25875 -#ifdef DEBUG
25876 -       log_error_write(srv, __FILE__, __LINE__, "sbbdb", 
25877 -               result ? "NOT CACHED" : "cached", 
25878 -               con->server_name, con->physical.doc_root,
25879 -               c->fcgi_offset, c->fcgi_arg);
25880 -#endif
25881 -       return HANDLER_GO_ON;   
25882 -
25883 -ERR500:        if (result) mysql_free_result(result);
25884 -       con->http_status = 500; /* Internal Error */
25885 -       return HANDLER_FINISHED;
25886 +       return HANDLER_GO_ON;
25887  }
25888  
25889  /* this function is called at dlopen() time and inits the callbacks */
25890  int mod_mysql_vhost_plugin_init(plugin *p) {
25891 +       data_string *ds;
25892 +       
25893         p->version     = LIGHTTPD_VERSION_ID;
25894         p->name                         = buffer_init_string("mysql_vhost");
25895  
25896         p->init                         = mod_mysql_vhost_init;
25897         p->cleanup                      = mod_mysql_vhost_cleanup;
25898 -       p->handle_request_done          = mod_mysql_vhost_handle_connection_close;
25899  
25900         p->set_defaults                 = mod_mysql_vhost_set_defaults;
25901 -       p->handle_docroot               = mod_mysql_vhost_handle_docroot;
25902         
25903 +       ds = data_string_init();
25904 +       buffer_copy_string(ds->value, CORE_PLUGIN);
25905 +       array_insert_unique(p->required_plugins, (data_unset *)ds);
25906 +
25907         return 0;
25908  }
25909  #else
25910 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_proxy.c lighttpd-1.4.12/src/mod_proxy.c
25911 --- lighttpd-1.4.11/src/mod_proxy.c     2006-01-31 13:01:22.000000000 +0200
25912 +++ lighttpd-1.4.12/src/mod_proxy.c     2006-07-11 21:23:40.000000000 +0300
25913 @@ -1,6 +1,5 @@
25914  #include <sys/types.h>
25915  
25916 -#include <unistd.h>
25917  #include <errno.h>
25918  #include <fcntl.h>
25919  #include <string.h>
25920 @@ -23,6 +22,9 @@
25921  
25922  #include "inet_ntop_cache.h"
25923  #include "crc32.h"
25924 +#include "network.h"
25925 +
25926 +#include "http_resp.h"
25927  
25928  #include <stdio.h>
25929  
25930 @@ -31,6 +33,8 @@
25931  #endif
25932  
25933  #include "sys-socket.h"
25934 +#include "sys-files.h"
25935 +#include "sys-strings.h"
25936  
25937  #define data_proxy data_fastcgi
25938  #define data_proxy_init data_fastcgi_init
25939 @@ -38,16 +42,16 @@
25940  #define PROXY_RETRY_TIMEOUT 60
25941  
25942  /**
25943 - * 
25944 - * the proxy module is based on the fastcgi module 
25945 - * 
25946 + *
25947 + * the proxy module is based on the fastcgi module
25948 + *
25949   * 28.06.2004 Jan Kneschke     The first release
25950   * 01.07.2004 Evgeny Rodichev  Several bugfixes and cleanups
25951   *            - co-ordinate up- and downstream flows correctly (proxy_demux_response
25952   *              and proxy_handle_fdevent)
25953   *            - correctly transfer upstream http_response_status;
25954   *            - some unused structures removed.
25955 - * 
25956 + *
25957   * TODO:      - delay upstream read if write_queue is too large
25958   *              (to prevent memory eating, like in apache). Shoud be
25959   *              configurable).
25960 @@ -66,26 +70,31 @@
25961         int debug;
25962  
25963         proxy_balance_t balance;
25964 +
25965 +       array *last_used_backends; /* "extension" : last_used_backend */
25966  } plugin_config;
25967  
25968  typedef struct {
25969         PLUGIN_DATA;
25970 -       
25971 +
25972         buffer *parse_response;
25973         buffer *balance_buf;
25974 -       
25975 +
25976 +       array *ignore_headers;
25977 +
25978         plugin_config **config_storage;
25979 -       
25980 +
25981         plugin_config conf;
25982  } plugin_data;
25983  
25984 -typedef enum { 
25985 -       PROXY_STATE_INIT, 
25986 -       PROXY_STATE_CONNECT, 
25987 -       PROXY_STATE_PREPARE_WRITE, 
25988 -       PROXY_STATE_WRITE, 
25989 -       PROXY_STATE_READ, 
25990 -       PROXY_STATE_ERROR 
25991 +typedef enum {
25992 +       PROXY_STATE_INIT,
25993 +       PROXY_STATE_CONNECT,
25994 +       PROXY_STATE_PREPARE_WRITE,
25995 +       PROXY_STATE_WRITE,
25996 +    PROXY_STATE_RESPONSE_HEADER,
25997 +    PROXY_STATE_RESPONSE_CONTENT,
25998 +       PROXY_STATE_ERROR
25999  } proxy_connection_state_t;
26000  
26001  enum { PROXY_STDOUT, PROXY_END_REQUEST };
26002 @@ -93,19 +102,20 @@
26003  typedef struct {
26004         proxy_connection_state_t state;
26005         time_t state_timestamp;
26006 -       
26007 +
26008         data_proxy *host;
26009 -       
26010 +
26011         buffer *response;
26012         buffer *response_header;
26013  
26014         chunkqueue *wb;
26015 -       
26016 +    chunkqueue *rb;
26017 +
26018         int fd; /* fd to the proxy process */
26019         int fde_ndx; /* index into the fd-event buffer */
26020  
26021         size_t path_info_offset; /* start of path_info in uri.path */
26022 -       
26023 +
26024         connection *remote_conn;  /* dump pointer */
26025         plugin_data *plugin_data; /* dump pointer */
26026  } handler_ctx;
26027 @@ -116,21 +126,22 @@
26028  
26029  static handler_ctx * handler_ctx_init() {
26030         handler_ctx * hctx;
26031 -       
26032 +
26033  
26034         hctx = calloc(1, sizeof(*hctx));
26035 -       
26036 +
26037         hctx->state = PROXY_STATE_INIT;
26038         hctx->host = NULL;
26039 -       
26040 +
26041         hctx->response = buffer_init();
26042         hctx->response_header = buffer_init();
26043  
26044         hctx->wb = chunkqueue_init();
26045 +    hctx->rb = chunkqueue_init();
26046  
26047         hctx->fd = -1;
26048         hctx->fde_ndx = -1;
26049 -       
26050 +
26051         return hctx;
26052  }
26053  
26054 @@ -138,47 +149,70 @@
26055         buffer_free(hctx->response);
26056         buffer_free(hctx->response_header);
26057         chunkqueue_free(hctx->wb);
26058 -       
26059 +    chunkqueue_free(hctx->rb);
26060 +
26061         free(hctx);
26062  }
26063  
26064  INIT_FUNC(mod_proxy_init) {
26065         plugin_data *p;
26066 -       
26067 +       size_t i;
26068 +
26069 +       char *hop2hop_headers[] = {
26070 +               "Connection",
26071 +               "Keep-Alive",
26072 +               "Host",
26073 +               NULL
26074 +       };
26075 +
26076         p = calloc(1, sizeof(*p));
26077 -       
26078 +
26079         p->parse_response = buffer_init();
26080         p->balance_buf = buffer_init();
26081 -       
26082 +       p->ignore_headers = array_init();
26083 +
26084 +       for (i = 0; hop2hop_headers[i]; i++) {
26085 +               data_string *ds;
26086 +
26087 +               if (NULL == (ds = (data_string *)array_get_unused_element(p->ignore_headers, TYPE_STRING))) {
26088 +                       ds = data_string_init();
26089 +               }
26090 +
26091 +               buffer_copy_string(ds->value, hop2hop_headers[i]);
26092 +               array_insert_unique(p->ignore_headers, (data_unset *)ds);
26093 +       }
26094 +
26095         return p;
26096  }
26097  
26098  
26099  FREE_FUNC(mod_proxy_free) {
26100         plugin_data *p = p_d;
26101 -       
26102 +
26103         UNUSED(srv);
26104  
26105         buffer_free(p->parse_response);
26106         buffer_free(p->balance_buf);
26107 -       
26108 +
26109         if (p->config_storage) {
26110                 size_t i;
26111                 for (i = 0; i < srv->config_context->used; i++) {
26112                         plugin_config *s = p->config_storage[i];
26113 -                       
26114 +
26115                         if (s) {
26116 -                       
26117                                 array_free(s->extensions);
26118 -                       
26119 +                               array_free(s->last_used_backends);
26120 +
26121                                 free(s);
26122                         }
26123                 }
26124                 free(p->config_storage);
26125         }
26126 -       
26127 +
26128 +       free(p->ignore_headers);
26129 +
26130         free(p);
26131 -       
26132 +
26133         return HANDLER_GO_ON;
26134  }
26135  
26136 @@ -186,37 +220,38 @@
26137         plugin_data *p = p_d;
26138         data_unset *du;
26139         size_t i = 0;
26140 -       
26141 -       config_values_t cv[] = { 
26142 +
26143 +       config_values_t cv[] = {
26144                 { "proxy.server",              NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
26145                 { "proxy.debug",               NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
26146                 { "proxy.balance",             NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },      /* 2 */
26147                 { NULL,                        NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
26148         };
26149 -       
26150 +
26151         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
26152 -       
26153 +
26154         for (i = 0; i < srv->config_context->used; i++) {
26155                 plugin_config *s;
26156                 array *ca;
26157 -               
26158 +
26159                 s = malloc(sizeof(plugin_config));
26160 -               s->extensions    = array_init();
26161 +               s->extensions         = array_init();
26162 +               s->last_used_backends = array_init();
26163                 s->debug         = 0;
26164 -               
26165 +
26166                 cv[0].destination = s->extensions;
26167                 cv[1].destination = &(s->debug);
26168                 cv[2].destination = p->balance_buf;
26169  
26170                 buffer_reset(p->balance_buf);
26171 -               
26172 +
26173                 p->config_storage[i] = s;
26174                 ca = ((data_config *)srv->config_context->data[i])->value;
26175 -       
26176 +
26177                 if (0 != config_insert_values_global(srv, ca, cv)) {
26178                         return HANDLER_ERROR;
26179                 }
26180 -       
26181 +
26182                 if (buffer_is_empty(p->balance_buf)) {
26183                         s->balance = PROXY_BALANCE_FAIR;
26184                 } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("fair"))) {
26185 @@ -226,7 +261,7 @@
26186                 } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("hash"))) {
26187                         s->balance = PROXY_BALANCE_HASH;
26188                 } else {
26189 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
26190 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
26191                                         "proxy.balance has to be one of: fair, round-robin, hash, but not:", p->balance_buf);
26192                         return HANDLER_ERROR;
26193                 }
26194 @@ -234,91 +269,91 @@
26195                 if (NULL != (du = array_get_element(ca, "proxy.server"))) {
26196                         size_t j;
26197                         data_array *da = (data_array *)du;
26198 -                       
26199 +
26200                         if (du->type != TYPE_ARRAY) {
26201 -                               log_error_write(srv, __FILE__, __LINE__, "sss", 
26202 +                               log_error_write(srv, __FILE__, __LINE__, "sss",
26203                                                 "unexpected type for key: ", "proxy.server", "array of strings");
26204 -                               
26205 +
26206                                 return HANDLER_ERROR;
26207                         }
26208 -                       
26209 -                       /* 
26210 +
26211 +                       /*
26212                          * proxy.server = ( "<ext>" => ...,
26213                          *                  "<ext>" => ... )
26214                          */
26215 -                       
26216 +
26217                         for (j = 0; j < da->value->used; j++) {
26218                                 data_array *da_ext = (data_array *)da->value->data[j];
26219                                 size_t n;
26220 -                               
26221 +
26222                                 if (da_ext->type != TYPE_ARRAY) {
26223 -                                       log_error_write(srv, __FILE__, __LINE__, "sssbs", 
26224 -                                                       "unexpected type for key: ", "proxy.server", 
26225 +                                       log_error_write(srv, __FILE__, __LINE__, "sssbs",
26226 +                                                       "unexpected type for key: ", "proxy.server",
26227                                                         "[", da->value->data[j]->key, "](string)");
26228 -                                       
26229 +
26230                                         return HANDLER_ERROR;
26231                                 }
26232 -                               
26233 -                               /* 
26234 -                                * proxy.server = ( "<ext>" => 
26235 -                                *                     ( "<host>" => ( ... ), 
26236 +
26237 +                               /*
26238 +                                * proxy.server = ( "<ext>" =>
26239 +                                *                     ( "<host>" => ( ... ),
26240                                  *                       "<host>" => ( ... )
26241 -                                *                     ), 
26242 +                                *                     ),
26243                                  *                    "<ext>" => ... )
26244                                  */
26245 -                               
26246 +
26247                                 for (n = 0; n < da_ext->value->used; n++) {
26248                                         data_array *da_host = (data_array *)da_ext->value->data[n];
26249 -                                       
26250 +
26251                                         data_proxy *df;
26252                                         data_array *dfa;
26253 -                                       
26254 -                                       config_values_t pcv[] = { 
26255 +
26256 +                                       config_values_t pcv[] = {
26257                                                 { "host",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },      /* 0 */
26258                                                 { "port",              NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
26259                                                 { NULL,                NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
26260                                         };
26261 -                                       
26262 +
26263                                         if (da_host->type != TYPE_ARRAY) {
26264 -                                               log_error_write(srv, __FILE__, __LINE__, "ssSBS", 
26265 -                                                               "unexpected type for key:", 
26266 -                                                               "proxy.server", 
26267 +                                               log_error_write(srv, __FILE__, __LINE__, "ssSBS",
26268 +                                                               "unexpected type for key:",
26269 +                                                               "proxy.server",
26270                                                                 "[", da_ext->value->data[n]->key, "](string)");
26271 -                                               
26272 +
26273                                                 return HANDLER_ERROR;
26274                                         }
26275 -                                       
26276 +
26277                                         df = data_proxy_init();
26278 -                                       
26279 +
26280                                         df->port = 80;
26281 -                                       
26282 +
26283                                         buffer_copy_string_buffer(df->key, da_host->key);
26284 -                                       
26285 +
26286                                         pcv[0].destination = df->host;
26287                                         pcv[1].destination = &(df->port);
26288 -                                       
26289 +
26290                                         if (0 != config_insert_values_internal(srv, da_host->value, pcv)) {
26291                                                 return HANDLER_ERROR;
26292                                         }
26293 -                                       
26294 +
26295                                         if (buffer_is_empty(df->host)) {
26296 -                                               log_error_write(srv, __FILE__, __LINE__, "sbbbs", 
26297 -                                                               "missing key (string):", 
26298 +                                               log_error_write(srv, __FILE__, __LINE__, "sbbbs",
26299 +                                                               "missing key (string):",
26300                                                                 da->key,
26301                                                                 da_ext->key,
26302                                                                 da_host->key,
26303                                                                 "host");
26304 -                                               
26305 +
26306                                                 return HANDLER_ERROR;
26307                                         }
26308 -                                       
26309 +
26310                                         /* if extension already exists, take it */
26311 -                                       
26312 +
26313                                         if (NULL == (dfa = (data_array *)array_get_element(s->extensions, da_ext->key->ptr))) {
26314                                                 dfa = data_array_init();
26315 -                                               
26316 +
26317                                                 buffer_copy_string_buffer(dfa->key, da_ext->key);
26318 -                                               
26319 +
26320                                                 array_insert_unique(dfa->value, (data_unset *)df);
26321                                                 array_insert_unique(s->extensions, (data_unset *)dfa);
26322                                         } else {
26323 @@ -328,19 +363,19 @@
26324                         }
26325                 }
26326         }
26327 -       
26328 +
26329         return HANDLER_GO_ON;
26330  }
26331  
26332  void proxy_connection_close(server *srv, handler_ctx *hctx) {
26333         plugin_data *p;
26334         connection *con;
26335 -       
26336 +
26337         if (NULL == hctx) return;
26338 -       
26339 +
26340         p    = hctx->plugin_data;
26341         con  = hctx->remote_conn;
26342 -       
26343 +
26344         if (hctx->fd != -1) {
26345                 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26346                 fdevent_unregister(srv->ev, hctx->fd);
26347 @@ -348,47 +383,56 @@
26348                 close(hctx->fd);
26349                 srv->cur_fds--;
26350         }
26351 -       
26352 +
26353         handler_ctx_free(hctx);
26354 -       con->plugin_ctx[p->id] = NULL;  
26355 +       con->plugin_ctx[p->id] = NULL;
26356  }
26357  
26358  static int proxy_establish_connection(server *srv, handler_ctx *hctx) {
26359         struct sockaddr *proxy_addr;
26360         struct sockaddr_in proxy_addr_in;
26361         socklen_t servlen;
26362 -       
26363 +
26364         plugin_data *p    = hctx->plugin_data;
26365         data_proxy *host= hctx->host;
26366         int proxy_fd       = hctx->fd;
26367 -       
26368 +
26369         memset(&proxy_addr, 0, sizeof(proxy_addr));
26370 -       
26371 +
26372         proxy_addr_in.sin_family = AF_INET;
26373         proxy_addr_in.sin_addr.s_addr = inet_addr(host->host->ptr);
26374         proxy_addr_in.sin_port = htons(host->port);
26375         servlen = sizeof(proxy_addr_in);
26376 -               
26377 +
26378         proxy_addr = (struct sockaddr *) &proxy_addr_in;
26379 -       
26380 +
26381         if (-1 == connect(proxy_fd, proxy_addr, servlen)) {
26382 -               if (errno == EINPROGRESS || errno == EALREADY) {
26383 +#ifdef _WIN32
26384 +        errno = WSAGetLastError();
26385 +#endif
26386 +        switch(errno) {
26387 +#ifdef _WIN32
26388 +        case WSAEWOULDBLOCK:
26389 +#endif
26390 +        case EINPROGRESS:
26391 +        case EALREADY:
26392                         if (p->conf.debug) {
26393 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
26394 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
26395                                                 "connect delayed:", proxy_fd);
26396                         }
26397 -                       
26398 +
26399                         return 1;
26400 -               } else {
26401 -                       
26402 -                       log_error_write(srv, __FILE__, __LINE__, "sdsd", 
26403 +               default:
26404 +
26405 +                       log_error_write(srv, __FILE__, __LINE__, "sdsd",
26406                                         "connect failed:", proxy_fd, strerror(errno), errno);
26407 -                       
26408 +
26409                         return -1;
26410                 }
26411         }
26412 +    fprintf(stderr, "%s.%d: connected fd = %d\r\n", __FILE__, __LINE__, proxy_fd);
26413         if (p->conf.debug) {
26414 -               log_error_write(srv, __FILE__, __LINE__, "sd", 
26415 +               log_error_write(srv, __FILE__, __LINE__, "sd",
26416                                 "connect succeeded: ", proxy_fd);
26417         }
26418  
26419 @@ -422,25 +466,26 @@
26420  
26421  static int proxy_create_env(server *srv, handler_ctx *hctx) {
26422         size_t i;
26423 -       
26424 +
26425         connection *con   = hctx->remote_conn;
26426 +       plugin_data *p    = hctx->plugin_data;
26427         buffer *b;
26428 -       
26429 +
26430         /* build header */
26431  
26432         b = chunkqueue_get_append_buffer(hctx->wb);
26433 -       
26434 +
26435         /* request line */
26436         buffer_copy_string(b, get_http_method_name(con->request.http_method));
26437         BUFFER_APPEND_STRING_CONST(b, " ");
26438 -       
26439 +
26440         buffer_append_string_buffer(b, con->request.uri);
26441         BUFFER_APPEND_STRING_CONST(b, " HTTP/1.0\r\n");
26442  
26443         proxy_append_header(con, "X-Forwarded-For", (char *)inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
26444 -       /* http_host is NOT is just a pointer to a buffer 
26445 +       /* http_host is NOT is just a pointer to a buffer
26446          * which is NULL if it is not set */
26447 -       if (con->request.http_host && 
26448 +       if (con->request.http_host &&
26449             !buffer_is_empty(con->request.http_host)) {
26450                 proxy_set_header(con, "X-Host", con->request.http_host->ptr);
26451         }
26452 @@ -449,24 +494,26 @@
26453         /* request header */
26454         for (i = 0; i < con->request.headers->used; i++) {
26455                 data_string *ds;
26456 -               
26457 +
26458                 ds = (data_string *)con->request.headers->data[i];
26459 -               
26460 +
26461                 if (ds->value->used && ds->key->used) {
26462 -                       if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue;
26463 -                       
26464 +
26465 +                       /* don't copy hop-to-hop headers */
26466 +                       if (array_get_element(p->ignore_headers, ds->key->ptr)) continue;
26467 +
26468                         buffer_append_string_buffer(b, ds->key);
26469                         BUFFER_APPEND_STRING_CONST(b, ": ");
26470                         buffer_append_string_buffer(b, ds->value);
26471                         BUFFER_APPEND_STRING_CONST(b, "\r\n");
26472                 }
26473         }
26474 -       
26475 +
26476         BUFFER_APPEND_STRING_CONST(b, "\r\n");
26477 -       
26478 +
26479         hctx->wb->bytes_in += b->used - 1;
26480         /* body */
26481 -       
26482 +
26483         if (con->request.content_length) {
26484                 chunkqueue *req_cq = con->request_content_queue;
26485                 chunk *req_c;
26486 @@ -479,7 +526,7 @@
26487  
26488                         /* we announce toWrite octects
26489                          * now take all the request_content chunk that we need to fill this request
26490 -                        * */   
26491 +                        * */
26492  
26493                         switch (req_c->type) {
26494                         case FILE_CHUNK:
26495 @@ -507,223 +554,125 @@
26496  
26497                                 req_c->offset += weHave;
26498                                 req_cq->bytes_out += weHave;
26499 -                               
26500 +
26501                                 hctx->wb->bytes_in += weHave;
26502  
26503                                 break;
26504                         default:
26505                                 break;
26506                         }
26507 -                       
26508 +
26509                         offset += weHave;
26510                 }
26511  
26512         }
26513 -       
26514 +
26515         return 0;
26516  }
26517  
26518  static int proxy_set_state(server *srv, handler_ctx *hctx, proxy_connection_state_t state) {
26519         hctx->state = state;
26520         hctx->state_timestamp = srv->cur_ts;
26521 -       
26522 +
26523         return 0;
26524  }
26525  
26526  
26527 -static int proxy_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
26528 -       char *s, *ns;
26529 -       int http_response_status = -1;
26530 -       
26531 -       UNUSED(srv);
26532 +static void chunkqueue_print(chunkqueue *cq) {
26533 +    chunk *c;
26534  
26535 -       /* \r\n -> \0\0 */
26536 -       
26537 -       buffer_copy_string_buffer(p->parse_response, in);
26538 -       
26539 -       for (s = p->parse_response->ptr; NULL != (ns = strstr(s, "\r\n")); s = ns + 2) {
26540 -               char *key, *value;
26541 -               int key_len;
26542 -               data_string *ds;
26543 -               int copy_header;
26544 -               
26545 -               ns[0] = '\0';
26546 -               ns[1] = '\0';
26547 -
26548 -               if (-1 == http_response_status) {
26549 -                       /* The first line of a Response message is the Status-Line */
26550 -
26551 -                       for (key=s; *key && *key != ' '; key++);
26552 -
26553 -                       if (*key) {
26554 -                               http_response_status = (int) strtol(key, NULL, 10);
26555 -                               if (http_response_status <= 0) http_response_status = 502;
26556 -                       } else {
26557 -                               http_response_status = 502;
26558 -                       }
26559 -
26560 -                       con->http_status = http_response_status;
26561 -                       con->parsed_response |= HTTP_STATUS;
26562 -                       continue;
26563 -               }
26564 -               
26565 -               if (NULL == (value = strchr(s, ':'))) {
26566 -                       /* now we expect: "<key>: <value>\n" */
26567 -
26568 -                       continue;
26569 -               }
26570 -
26571 -               key = s;
26572 -               key_len = value - key;
26573 -               
26574 -               value++;
26575 -               /* strip WS */
26576 -               while (*value == ' ' || *value == '\t') value++;
26577 -               
26578 -               copy_header = 1;
26579 -               
26580 -               switch(key_len) {
26581 -               case 4:
26582 -                       if (0 == strncasecmp(key, "Date", key_len)) {
26583 -                               con->parsed_response |= HTTP_DATE;
26584 -                       }
26585 -                       break;
26586 -               case 8:
26587 -                       if (0 == strncasecmp(key, "Location", key_len)) {
26588 -                               con->parsed_response |= HTTP_LOCATION;
26589 -                       }
26590 -                       break;
26591 -               case 10:
26592 -                       if (0 == strncasecmp(key, "Connection", key_len)) {
26593 -                               copy_header = 0;
26594 -                       }
26595 -                       break;
26596 -               case 14:
26597 -                       if (0 == strncasecmp(key, "Content-Length", key_len)) {
26598 -                               con->response.content_length = strtol(value, NULL, 10);
26599 -                               con->parsed_response |= HTTP_CONTENT_LENGTH;
26600 -                       }
26601 -                       break;
26602 -               default:
26603 -                       break;
26604 -               }
26605 -
26606 -               if (copy_header) {
26607 -                       if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
26608 -                               ds = data_response_init();
26609 -                       }
26610 -                       buffer_copy_string_len(ds->key, key, key_len);
26611 -                       buffer_copy_string(ds->value, value);
26612 -                       
26613 -                       array_insert_unique(con->response.headers, (data_unset *)ds);
26614 -               }
26615 -       }
26616 -       
26617 -       return 0;
26618 +    for (c = cq->first; c; c = c->next) {
26619 +        fprintf(stderr, "%s", c->mem->ptr + c->offset);
26620 +    }
26621 +    fprintf(stderr, "\r\n");
26622  }
26623  
26624 -
26625  static int proxy_demux_response(server *srv, handler_ctx *hctx) {
26626 -       int fin = 0;
26627 -       int b;
26628 -       ssize_t r;
26629 -       
26630         plugin_data *p    = hctx->plugin_data;
26631         connection *con   = hctx->remote_conn;
26632         int proxy_fd       = hctx->fd;
26633 -       
26634 -       /* check how much we have to read */
26635 -       if (ioctl(hctx->fd, FIONREAD, &b)) {
26636 -               log_error_write(srv, __FILE__, __LINE__, "sd", 
26637 -                               "ioctl failed: ",
26638 -                               proxy_fd);
26639 -               return -1;
26640 -       }
26641 -
26642 +    chunkqueue *next_queue = NULL;
26643 +    chunk *c = NULL;
26644  
26645 -       if (p->conf.debug) {
26646 -               log_error_write(srv, __FILE__, __LINE__, "sd",
26647 -                              "proxy - have to read:", b);
26648 -       }
26649 -
26650 -       if (b > 0) {
26651 -               if (hctx->response->used == 0) {
26652 -                       /* avoid too small buffer */
26653 -                       buffer_prepare_append(hctx->response, b + 1);
26654 -                       hctx->response->used = 1;
26655 -               } else {
26656 -                       buffer_prepare_append(hctx->response, hctx->response->used + b);
26657 -               }
26658 -               
26659 -               if (-1 == (r = read(hctx->fd, hctx->response->ptr + hctx->response->used - 1, b))) {
26660 -                       log_error_write(srv, __FILE__, __LINE__, "sds", 
26661 -                                       "unexpected end-of-file (perhaps the proxy process died):",
26662 -                                       proxy_fd, strerror(errno));
26663 -                       return -1;
26664 -               }
26665 -               
26666 -               /* this should be catched by the b > 0 above */
26667 -               assert(r);
26668 -               
26669 -               hctx->response->used += r;
26670 -               hctx->response->ptr[hctx->response->used - 1] = '\0';
26671 -
26672 -#if 0
26673 -               log_error_write(srv, __FILE__, __LINE__, "sdsbs", 
26674 -                               "demux: Response buffer len", hctx->response->used, ":", hctx->response, ":");
26675 -#endif
26676 -
26677 -               if (0 == con->got_response) {
26678 -                       con->got_response = 1;
26679 -                       buffer_prepare_copy(hctx->response_header, 128);
26680 -               }
26681 -                               
26682 -               if (0 == con->file_started) {
26683 -                       char *c;
26684 -                               
26685 -                       /* search for the \r\n\r\n in the string */
26686 -                       if (NULL != (c = buffer_search_string_len(hctx->response, "\r\n\r\n", 4))) {
26687 -                               size_t hlen = c - hctx->response->ptr + 4;
26688 -                               size_t blen = hctx->response->used - hlen - 1;
26689 -                               /* found */
26690 -                               
26691 -                               buffer_append_string_len(hctx->response_header, hctx->response->ptr, c - hctx->response->ptr + 4);
26692 -#if 0
26693 -                               log_error_write(srv, __FILE__, __LINE__, "sb", "Header:", hctx->response_header);
26694 -#endif
26695 -                               /* parse the response header */
26696 -                               proxy_response_parse(srv, con, p, hctx->response_header);
26697 -                                       
26698 -                               /* enable chunked-transfer-encoding */
26699 -                               if (con->request.http_version == HTTP_VERSION_1_1 &&
26700 -                                   !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
26701 -                                       con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
26702 -                               }
26703 -                                       
26704 -                               con->file_started = 1;
26705 -                               if (blen) {
26706 -                                       http_chunk_append_mem(srv, con, c + 4, blen + 1);
26707 -                                       joblist_append(srv, con);
26708 -                               }
26709 -                               hctx->response->used = 0;
26710 -                       }
26711 -               } else {
26712 -                       http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
26713 -                       joblist_append(srv, con);
26714 -                       hctx->response->used = 0;
26715 -               }
26716 -               
26717 -       } else {
26718 -               /* reading from upstream done */
26719 +    switch(srv->network_backend_read(srv, con, proxy_fd, hctx->rb)) {
26720 +    case NETWORK_STATUS_SUCCESS:
26721 +        /* we got content */
26722 +        break;
26723 +    case NETWORK_STATUS_CONNECTION_CLOSE:
26724 +        /* we are done, get out of here */
26725                 con->file_finished = 1;
26726 -               
26727 +
26728 +        /* close the chunk-queue with a empty chunk */
26729                 http_chunk_append_mem(srv, con, NULL, 0);
26730                 joblist_append(srv, con);
26731 -               
26732 -               fin = 1;
26733 +
26734 +        return 1;
26735 +    default:
26736 +        /* oops */
26737 +        return -1;
26738 +    }
26739 +
26740 +    /* looks like we got some content
26741 +    *
26742 +    * split off the header from the incoming stream
26743 +    */
26744 +
26745 +    if (hctx->state == PROXY_STATE_RESPONSE_HEADER) {
26746 +        http_resp *resp = http_response_init();
26747 +
26748 +        /* the response header is not fully received yet,
26749 +        *
26750 +        * extract the http-response header from the rb-cq
26751 +        */
26752 +        fprintf(stderr, "%s.%d: network-read\r\n", __FILE__, __LINE__);
26753 +        chunkqueue_print(hctx->rb);
26754 +
26755 +        switch (http_response_parse_cq(hctx->rb, resp)) {
26756 +        case PARSE_ERROR:
26757 +            /* parsing failed */
26758 +
26759 +            con->http_status = 502; /* Bad Gateway */
26760 +            return 1;
26761 +        case PARSE_NEED_MORE:
26762 +            return 0;
26763 +        case PARSE_SUCCESS:
26764 +            con->http_status = resp->status;
26765 +
26766 +            fprintf(stderr, "%s.%d: parsing done\r\n", __FILE__, __LINE__);
26767 +            chunkqueue_print(hctx->rb);
26768 +
26769 +            con->file_started = 1;
26770 +
26771 +            hctx->state = PROXY_STATE_RESPONSE_CONTENT;
26772 +            break;
26773 +        }
26774 +    }
26775 +
26776 +    /* FIXME: pass the response-header to the other plugins to
26777 +    * setup the filter-queue
26778 +    *
26779 +    * - use next-queue instead of con->write_queue
26780 +    */
26781 +
26782 +    next_queue = con->write_queue;
26783 +
26784 +    assert(hctx->state == PROXY_STATE_RESPONSE_CONTENT);
26785 +
26786 +    /* FIXME: if we have a content-length or chunked-encoding
26787 +    * handle it.
26788 +    *
26789 +    * for now we wait for EOF on the socket */
26790 +
26791 +    /* copy the content to the next cq */
26792 +    for (c = hctx->rb->first; c; c = c->next) {
26793 +        http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
26794 +
26795 +        c->offset = c->mem->used - 1;
26796         }
26797 -       
26798 -       return fin;
26799 +
26800 +    chunkqueue_remove_finished_chunks(hctx->rb);
26801 +
26802 +       return 0;
26803  }
26804  
26805  
26806 @@ -731,12 +680,12 @@
26807         data_proxy *host= hctx->host;
26808         plugin_data *p    = hctx->plugin_data;
26809         connection *con   = hctx->remote_conn;
26810 -       
26811 +
26812         int ret;
26813 -       
26814 -       if (!host || 
26815 +
26816 +       if (!host ||
26817             (!host->host->used || !host->port)) return -1;
26818 -       
26819 +
26820         switch(hctx->state) {
26821         case PROXY_STATE_INIT:
26822                 if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) {
26823 @@ -744,19 +693,19 @@
26824                         return HANDLER_ERROR;
26825                 }
26826                 hctx->fde_ndx = -1;
26827 -               
26828 +
26829                 srv->cur_fds++;
26830 -               
26831 +
26832                 fdevent_register(srv->ev, hctx->fd, proxy_handle_fdevent, hctx);
26833 -               
26834 +
26835                 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
26836                         log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
26837 -                       
26838 +
26839                         return HANDLER_ERROR;
26840                 }
26841 -               
26842 +
26843                 /* fall through */
26844 -               
26845 +
26846         case PROXY_STATE_CONNECT:
26847                 /* try to finish the connect() */
26848                 if (hctx->state == PROXY_STATE_INIT) {
26849 @@ -764,16 +713,16 @@
26850                         switch (proxy_establish_connection(srv, hctx)) {
26851                         case 1:
26852                                 proxy_set_state(srv, hctx, PROXY_STATE_CONNECT);
26853 -                               
26854 +
26855                                 /* connection is in progress, wait for an event and call getsockopt() below */
26856 -                               
26857 +
26858                                 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26859 -                               
26860 +
26861                                 return HANDLER_WAIT_FOR_EVENT;
26862                         case -1:
26863                                 /* if ECONNREFUSED choose another connection -> FIXME */
26864                                 hctx->fde_ndx = -1;
26865 -                               
26866 +
26867                                 return HANDLER_ERROR;
26868                         default:
26869                                 /* everything is ok, go on */
26870 @@ -782,152 +731,152 @@
26871                 } else {
26872                         int socket_error;
26873                         socklen_t socket_error_len = sizeof(socket_error);
26874 -               
26875 -                       /* we don't need it anymore */  
26876 +
26877 +                       /* we don't need it anymore */
26878                         fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26879  
26880                         /* try to finish the connect() */
26881                         if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
26882 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
26883 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
26884                                                 "getsockopt failed:", strerror(errno));
26885 -                               
26886 +
26887                                 return HANDLER_ERROR;
26888                         }
26889                         if (socket_error != 0) {
26890                                 log_error_write(srv, __FILE__, __LINE__, "ss",
26891 -                                               "establishing connection failed:", strerror(socket_error), 
26892 +                                               "establishing connection failed:", strerror(socket_error),
26893                                                 "port:", hctx->host->port);
26894 -                               
26895 +
26896                                 return HANDLER_ERROR;
26897                         }
26898                         if (p->conf.debug) {
26899 -                               log_error_write(srv, __FILE__, __LINE__,  "s", "proxy - connect - delayed success"); 
26900 +                               log_error_write(srv, __FILE__, __LINE__,  "s", "proxy - connect - delayed success");
26901                         }
26902 +            fprintf(stderr, "%s.%d: connected fd = %d\r\n", __FILE__, __LINE__, hctx->fd);
26903                 }
26904 -               
26905 +
26906                 proxy_set_state(srv, hctx, PROXY_STATE_PREPARE_WRITE);
26907                 /* fall through */
26908         case PROXY_STATE_PREPARE_WRITE:
26909                 proxy_create_env(srv, hctx);
26910 -               
26911 +
26912                 proxy_set_state(srv, hctx, PROXY_STATE_WRITE);
26913 -               
26914 +
26915                 /* fall through */
26916         case PROXY_STATE_WRITE:;
26917 -               ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); 
26918 +               ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
26919  
26920                 chunkqueue_remove_finished_chunks(hctx->wb);
26921  
26922 -               if (-1 == ret) {
26923 -                       if (errno != EAGAIN &&
26924 -                           errno != EINTR) {
26925 -                               log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
26926 -                               
26927 -                               return HANDLER_ERROR;
26928 -                       } else {
26929 -                               fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26930 +               switch(ret) {
26931 +        case NETWORK_STATUS_FATAL_ERROR:
26932 +                       log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
26933  
26934 -                               return HANDLER_WAIT_FOR_EVENT;
26935 -                       }
26936 +                       return HANDLER_ERROR;
26937 +        case NETWORK_STATUS_WAIT_FOR_EVENT:
26938 +
26939 +                       fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26940 +
26941 +                       return HANDLER_WAIT_FOR_EVENT;
26942                 }
26943  
26944                 if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
26945 -                       proxy_set_state(srv, hctx, PROXY_STATE_READ);
26946 +                       proxy_set_state(srv, hctx, PROXY_STATE_RESPONSE_HEADER);
26947  
26948                         fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
26949                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
26950                 } else {
26951                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
26952 -                               
26953 +
26954                         return HANDLER_WAIT_FOR_EVENT;
26955                 }
26956 -               
26957 +
26958                 return HANDLER_WAIT_FOR_EVENT;
26959 -       case PROXY_STATE_READ:
26960 +       case PROXY_STATE_RESPONSE_HEADER:
26961                 /* waiting for a response */
26962 +
26963                 return HANDLER_WAIT_FOR_EVENT;
26964         default:
26965                 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
26966                 return HANDLER_ERROR;
26967         }
26968 -       
26969 +
26970         return HANDLER_GO_ON;
26971  }
26972  
26973 -#define PATCH(x) \
26974 -       p->conf.x = s->x;
26975  static int mod_proxy_patch_connection(server *srv, connection *con, plugin_data *p) {
26976         size_t i, j;
26977         plugin_config *s = p->config_storage[0];
26978 -       
26979 -       PATCH(extensions);
26980 -       PATCH(debug);
26981 -       PATCH(balance);
26982 -       
26983 +
26984 +       PATCH_OPTION(extensions);
26985 +       PATCH_OPTION(debug);
26986 +       PATCH_OPTION(balance);
26987 +       PATCH_OPTION(last_used_backends);
26988 +
26989         /* skip the first, the global context */
26990         for (i = 1; i < srv->config_context->used; i++) {
26991                 data_config *dc = (data_config *)srv->config_context->data[i];
26992                 s = p->config_storage[i];
26993 -               
26994 +
26995                 /* condition didn't match */
26996                 if (!config_check_cond(srv, con, dc)) continue;
26997 -               
26998 +
26999                 /* merge config */
27000                 for (j = 0; j < dc->value->used; j++) {
27001                         data_unset *du = dc->value->data[j];
27002 -                       
27003 +
27004                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.server"))) {
27005 -                               PATCH(extensions);
27006 +                               PATCH_OPTION(extensions);
27007                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.debug"))) {
27008 -                               PATCH(debug);
27009 +                               PATCH_OPTION(debug);
27010                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.balance"))) {
27011 -                               PATCH(balance);
27012 +                               PATCH_OPTION(balance);
27013 +                               PATCH_OPTION(last_used_backends);
27014                         }
27015                 }
27016         }
27017 -       
27018 +
27019         return 0;
27020  }
27021 -#undef PATCH
27022  
27023  SUBREQUEST_FUNC(mod_proxy_handle_subrequest) {
27024         plugin_data *p = p_d;
27025 -       
27026 +
27027         handler_ctx *hctx = con->plugin_ctx[p->id];
27028         data_proxy *host;
27029 -       
27030 +
27031         if (NULL == hctx) return HANDLER_GO_ON;
27032  
27033         mod_proxy_patch_connection(srv, con, p);
27034 -       
27035 +
27036         host = hctx->host;
27037 -       
27038 +
27039         /* not my job */
27040         if (con->mode != p->id) return HANDLER_GO_ON;
27041 -       
27042 +
27043         /* ok, create the request */
27044         switch(proxy_write_request(srv, hctx)) {
27045         case HANDLER_ERROR:
27046 -               log_error_write(srv, __FILE__, __LINE__,  "sbdd", "proxy-server disabled:", 
27047 +               log_error_write(srv, __FILE__, __LINE__,  "sbdd", "proxy-server disabled:",
27048                                 host->host,
27049                                 host->port,
27050                                 hctx->fd);
27051 -               
27052 +
27053                 /* disable this server */
27054                 host->is_disabled = 1;
27055                 host->disable_ts = srv->cur_ts;
27056 -               
27057 +
27058                 proxy_connection_close(srv, hctx);
27059 -       
27060 -               /* reset the enviroment and restart the sub-request */  
27061 +
27062 +               /* reset the enviroment and restart the sub-request */
27063                 buffer_reset(con->physical.path);
27064                 con->mode = DIRECT;
27065  
27066                 joblist_append(srv, con);
27067  
27068 -               /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop 
27069 -                * and hope that the childs will be restarted 
27070 -                * 
27071 +               /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
27072 +                * and hope that the childs will be restarted
27073 +                *
27074                  */
27075  
27076                 return HANDLER_WAIT_FOR_FD;
27077 @@ -938,7 +887,7 @@
27078         default:
27079                 break;
27080         }
27081 -       
27082 +
27083         if (con->file_started == 1) {
27084                 return HANDLER_FINISHED;
27085         } else {
27086 @@ -951,13 +900,14 @@
27087         handler_ctx *hctx = ctx;
27088         connection  *con  = hctx->remote_conn;
27089         plugin_data *p    = hctx->plugin_data;
27090 -       
27091 -       
27092 +
27093 +
27094         if ((revents & FDEVENT_IN) &&
27095 -           hctx->state == PROXY_STATE_READ) {
27096 +        (hctx->state == PROXY_STATE_RESPONSE_HEADER ||
27097 +         hctx->state == PROXY_STATE_RESPONSE_CONTENT)) {
27098  
27099                 if (p->conf.debug) {
27100 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
27101 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
27102                                         "proxy: fdevent-in", hctx->state);
27103                 }
27104  
27105 @@ -966,10 +916,10 @@
27106                         break;
27107                 case 1:
27108                         hctx->host->usage--;
27109 -                       
27110 +
27111                         /* we are done */
27112                         proxy_connection_close(srv, hctx);
27113 -                       
27114 +
27115                         joblist_append(srv, con);
27116                         return HANDLER_FINISHED;
27117                 case -1:
27118 @@ -982,53 +932,53 @@
27119                                 /* response might have been already started, kill the connection */
27120                                 connection_set_state(srv, con, CON_STATE_ERROR);
27121                         }
27122 -                       
27123 +
27124                         joblist_append(srv, con);
27125                         return HANDLER_FINISHED;
27126                 }
27127         }
27128 -       
27129 +
27130         if (revents & FDEVENT_OUT) {
27131                 if (p->conf.debug) {
27132 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
27133 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
27134                                         "proxy: fdevent-out", hctx->state);
27135                 }
27136  
27137                 if (hctx->state == PROXY_STATE_CONNECT ||
27138                     hctx->state == PROXY_STATE_WRITE) {
27139                         /* we are allowed to send something out
27140 -                        * 
27141 +                        *
27142                          * 1. in a unfinished connect() call
27143                          * 2. in a unfinished write() call (long POST request)
27144                          */
27145                         return mod_proxy_handle_subrequest(srv, con, p);
27146                 } else {
27147 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
27148 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
27149                                         "proxy: out", hctx->state);
27150                 }
27151         }
27152 -       
27153 +
27154         /* perhaps this issue is already handled */
27155         if (revents & FDEVENT_HUP) {
27156                 if (p->conf.debug) {
27157 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
27158 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
27159                                         "proxy: fdevent-hup", hctx->state);
27160                 }
27161 -               
27162 +
27163                 if (hctx->state == PROXY_STATE_CONNECT) {
27164                         /* connect() -> EINPROGRESS -> HUP */
27165 -                       
27166 +
27167                         /**
27168 -                        * what is proxy is doing if it can't reach the next hop ? 
27169 -                        * 
27170 +                        * what is proxy is doing if it can't reach the next hop ?
27171 +                        *
27172                          */
27173 -                       
27174 +
27175                         proxy_connection_close(srv, hctx);
27176                         joblist_append(srv, con);
27177 -                       
27178 +
27179                         con->http_status = 503;
27180                         con->mode = DIRECT;
27181 -                       
27182 +
27183                         return HANDLER_FINISHED;
27184                 }
27185  
27186 @@ -1038,13 +988,13 @@
27187                 joblist_append(srv, con);
27188         } else if (revents & FDEVENT_ERR) {
27189                 /* kill all connections to the proxy process */
27190 -               
27191 +
27192                 log_error_write(srv, __FILE__, __LINE__, "sd", "proxy-FDEVENT_ERR, but no HUP", revents);
27193  
27194                 joblist_append(srv, con);
27195                 proxy_connection_close(srv, hctx);
27196         }
27197 -       
27198 +
27199         return HANDLER_FINISHED;
27200  }
27201  
27202 @@ -1058,44 +1008,49 @@
27203         buffer *fn;
27204         data_array *extension = NULL;
27205         size_t path_info_offset;
27206 -       
27207 +       data_integer *last_used_backend;
27208 +       data_proxy *host = NULL;
27209 +       handler_ctx *hctx = NULL;
27210 +
27211 +       array *backends = NULL;
27212 +
27213         /* Possibly, we processed already this request */
27214         if (con->file_started == 1) return HANDLER_GO_ON;
27215 -       
27216 +
27217         mod_proxy_patch_connection(srv, con, p);
27218 -       
27219 +
27220         fn = con->uri.path;
27221  
27222         if (fn->used == 0) {
27223                 return HANDLER_ERROR;
27224         }
27225 -       
27226 +
27227         s_len = fn->used - 1;
27228 -       
27229 -       
27230 +
27231 +
27232         path_info_offset = 0;
27233  
27234 -       if (p->conf.debug) {    
27235 +       if (p->conf.debug) {
27236                 log_error_write(srv, __FILE__, __LINE__,  "s", "proxy - start");
27237         }
27238  
27239         /* check if extension matches */
27240         for (k = 0; k < p->conf.extensions->used; k++) {
27241                 size_t ct_len;
27242 -               
27243 +
27244                 extension = (data_array *)p->conf.extensions->data[k];
27245 -               
27246 +
27247                 if (extension->key->used == 0) continue;
27248 -               
27249 +
27250                 ct_len = extension->key->used - 1;
27251 -               
27252 +
27253                 if (s_len < ct_len) continue;
27254 -               
27255 +
27256                 /* check extension in the form "/proxy_pattern" */
27257                 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
27258                         if (s_len > ct_len + 1) {
27259                                 char *pi_offset;
27260 -                               
27261 +
27262                                 if (0 != (pi_offset = strchr(fn->ptr + ct_len + 1, '/'))) {
27263                                         path_info_offset = pi_offset - fn->ptr;
27264                                 }
27265 @@ -1106,12 +1061,14 @@
27266                         break;
27267                 }
27268         }
27269 -       
27270 +
27271         if (k == p->conf.extensions->used) {
27272                 return HANDLER_GO_ON;
27273         }
27274  
27275 -       if (p->conf.debug) {    
27276 +       backends = extension->value;
27277 +
27278 +       if (p->conf.debug) {
27279                 log_error_write(srv, __FILE__, __LINE__,  "s", "proxy - ext found");
27280         }
27281  
27282 @@ -1120,34 +1077,34 @@
27283                 /* hash balancing */
27284  
27285                 if (p->conf.debug) {
27286 -                       log_error_write(srv, __FILE__, __LINE__,  "sd", 
27287 -                                       "proxy - used hash balancing, hosts:", extension->value->used);
27288 +                       log_error_write(srv, __FILE__, __LINE__,  "sd",
27289 +                                       "proxy - used hash balancing, hosts:", backends->used);
27290                 }
27291  
27292 -               for (k = 0, ndx = -1, last_max = ULONG_MAX; k < extension->value->used; k++) {
27293 -                       data_proxy *host = (data_proxy *)extension->value->data[k];
27294 +               for (k = 0, ndx = -1, last_max = ULONG_MAX; k < backends->used; k++) {
27295                         unsigned long cur_max;
27296  
27297 -                       if (host->is_disabled) continue;
27298 -                       
27299 +                       data_proxy *cur = (data_proxy *)backends->data[k];
27300 +
27301 +                       if (cur->is_disabled) continue;
27302 +
27303                         cur_max = generate_crc32c(CONST_BUF_LEN(con->uri.path)) +
27304 -                               generate_crc32c(CONST_BUF_LEN(host->host)) + /* we can cache this */
27305 +                               generate_crc32c(CONST_BUF_LEN(cur->host)) + /* we can cache this */
27306                                 generate_crc32c(CONST_BUF_LEN(con->uri.authority));
27307 -                       
27308 +
27309                         if (p->conf.debug) {
27310 -                               log_error_write(srv, __FILE__, __LINE__,  "sbbbd", 
27311 +                               log_error_write(srv, __FILE__, __LINE__,  "sbbbd",
27312                                                 "proxy - election:",
27313                                                 con->uri.path,
27314 -                                               host->host,
27315 +                                               cur->host,
27316                                                 con->uri.authority,
27317                                                 cur_max);
27318                         }
27319  
27320 -                       if ((last_max == ULONG_MAX) || /* first round */
27321 -                           (cur_max > last_max)) {
27322 +                       if (host == NULL || (cur_max > last_max)) {
27323                                 last_max = cur_max;
27324  
27325 -                               ndx = k;
27326 +                               host = cur;
27327                         }
27328                 }
27329  
27330 @@ -1155,19 +1112,20 @@
27331         case PROXY_BALANCE_FAIR:
27332                 /* fair balancing */
27333                 if (p->conf.debug) {
27334 -                       log_error_write(srv, __FILE__, __LINE__,  "s", 
27335 +                       log_error_write(srv, __FILE__, __LINE__,  "s",
27336                                         "proxy - used fair balancing");
27337                 }
27338  
27339 -               for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
27340 -                       data_proxy *host = (data_proxy *)extension->value->data[k];
27341 -               
27342 -                       if (host->is_disabled) continue;
27343 -
27344 -                       if (host->usage < max_usage) {
27345 -                               max_usage = host->usage;
27346 -                       
27347 -                               ndx = k;
27348 +               /* try to find the host with the lowest load */
27349 +               for (k = 0, max_usage = 0; k < backends->used; k++) {
27350 +                       data_proxy *cur = (data_proxy *)backends->data[k];
27351 +
27352 +                       if (cur->is_disabled) continue;
27353 +
27354 +                       if (NULL == host || cur->usage < max_usage) {
27355 +                               max_usage = cur->usage;
27356 +
27357 +                               host = cur;
27358                         }
27359                 }
27360  
27361 @@ -1175,89 +1133,100 @@
27362         case PROXY_BALANCE_RR:
27363                 /* round robin */
27364                 if (p->conf.debug) {
27365 -                       log_error_write(srv, __FILE__, __LINE__,  "s", 
27366 +                       log_error_write(srv, __FILE__, __LINE__,  "s",
27367                                         "proxy - used round-robin balancing");
27368                 }
27369  
27370                 /* just to be sure */
27371 -               assert(extension->value->used < INT_MAX);
27372 -               
27373 -               for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
27374 -                       data_proxy *host = (data_proxy *)extension->value->data[k];
27375 -               
27376 -                       if (host->is_disabled) continue;
27377 -
27378 -                       /* first usable ndx */
27379 -                       if (max_usage == INT_MAX) {
27380 -                               max_usage = k;
27381 -                       }
27382 +               assert(backends->used < INT_MAX);
27383  
27384 -                       /* get next ndx */
27385 -                       if ((int)k > host->last_used_ndx) {
27386 -                               ndx = k;
27387 -                               host->last_used_ndx = k;
27388 +               /* send each request to another host:
27389 +                *
27390 +                * e.g.:
27391 +                *
27392 +                * if we have three hosts it is
27393 +                *
27394 +                * 1 .. 2 .. 3 .. 1 .. 2 .. 3
27395 +                *
27396 +                **/
27397  
27398 -                               break;
27399 -                       }
27400 +               /* walk through the list */
27401 +               last_used_backend = (data_integer *)array_get_element(p->conf.last_used_backends, extension->key->ptr);
27402 +
27403 +               if (NULL == last_used_backend) {
27404 +                       last_used_backend = data_integer_init();
27405 +
27406 +                       buffer_copy_string_buffer(last_used_backend->key, extension->key);
27407 +                       last_used_backend->value = 0;
27408 +
27409 +                       array_insert_unique(p->conf.last_used_backends, (data_unset *)last_used_backend);
27410 +               }
27411 +
27412 +               /* scan all but the last host to see if they are up
27413 +                * take the first running host */
27414 +               for (k = last_used_backend->value + 1; (int)(k % backends->used) != last_used_backend->value; k++) {
27415 +                       data_proxy *cur = (data_proxy *)backends->data[k % backends->used];
27416 +
27417 +                       if (cur->is_disabled) continue;
27418 +
27419 +                       host = cur;
27420 +
27421 +                       last_used_backend->value = k;
27422 +
27423 +                       break;
27424                 }
27425 -               
27426 -               /* didn't found a higher id, wrap to the start */
27427 -               if (ndx != -1 && max_usage != INT_MAX) {
27428 -                       ndx = max_usage;
27429 +
27430 +               if (NULL == host) {
27431 +                       /* we found nothing better, fallback to the last used backend
27432 +                        * and check if it is still up */
27433 +                       host = (data_proxy *)backends->data[last_used_backend->value];
27434 +
27435 +                       if (host->is_disabled) host = NULL;
27436                 }
27437  
27438                 break;
27439         default:
27440                 break;
27441         }
27442 -       
27443 -       /* found a server */
27444 -       if (ndx != -1) {
27445 -               data_proxy *host = (data_proxy *)extension->value->data[ndx];
27446 -               
27447 -               /* 
27448 -                * if check-local is disabled, use the uri.path handler 
27449 -                * 
27450 -                */
27451 -               
27452 -               /* init handler-context */
27453 -               handler_ctx *hctx;
27454 -               hctx = handler_ctx_init();
27455 -                               
27456 -               hctx->path_info_offset = path_info_offset;
27457 -               hctx->remote_conn      = con;
27458 -               hctx->plugin_data      = p;
27459 -               hctx->host             = host;
27460 -                               
27461 -               con->plugin_ctx[p->id] = hctx;
27462 -               
27463 -               host->usage++;
27464 -               
27465 -               con->mode = p->id;
27466 -               
27467 -               if (p->conf.debug) {
27468 -                       log_error_write(srv, __FILE__, __LINE__,  "sbd", 
27469 -                                       "proxy - found a host",
27470 -                                       host->host, host->port);
27471 -               }
27472  
27473 -               return HANDLER_GO_ON;
27474 -       } else {
27475 -               /* no handler found */
27476 +       /* we havn't found a host */
27477 +       if (NULL == host) {
27478                 con->http_status = 500;
27479 -               
27480 -               log_error_write(srv, __FILE__, __LINE__,  "sb", 
27481 -                               "no proxy-handler found for:", 
27482 +
27483 +               log_error_write(srv, __FILE__, __LINE__,  "sb",
27484 +                               "no proxy-handler found for:",
27485                                 fn);
27486 -               
27487 +
27488                 return HANDLER_FINISHED;
27489         }
27490 +
27491 +       /* init handler-context */
27492 +       hctx = handler_ctx_init();
27493 +
27494 +       hctx->path_info_offset = path_info_offset;
27495 +       hctx->remote_conn      = con;
27496 +       hctx->plugin_data      = p;
27497 +       hctx->host             = host;
27498 +
27499 +       con->plugin_ctx[p->id] = hctx;
27500 +
27501 +       host->usage++;
27502 +
27503 +       /* we handle this request */
27504 +       con->mode = p->id;
27505 +
27506 +       if (p->conf.debug) {
27507 +               log_error_write(srv, __FILE__, __LINE__,  "sbd",
27508 +                               "proxy - found a host",
27509 +                               host->host, host->port);
27510 +       }
27511 +
27512         return HANDLER_GO_ON;
27513  }
27514  
27515  static handler_t mod_proxy_connection_close_callback(server *srv, connection *con, void *p_d) {
27516         plugin_data *p = p_d;
27517 -       
27518 +
27519         proxy_connection_close(srv, con->plugin_ctx[p->id]);
27520  
27521         return HANDLER_GO_ON;
27522 @@ -1276,11 +1245,11 @@
27523                 size_t i, n, k;
27524                 for (i = 0; i < srv->config_context->used; i++) {
27525                         plugin_config *s = p->config_storage[i];
27526 -                       
27527 -                       if (!s) continue; 
27528 +
27529 +                       if (!s) continue;
27530  
27531                         /* get the extensions for all configs */
27532 -                       
27533 +
27534                         for (k = 0; k < s->extensions->used; k++) {
27535                                 data_array *extension = (data_array *)s->extensions->data[k];
27536  
27537 @@ -1290,8 +1259,8 @@
27538  
27539                                         if (!host->is_disabled ||
27540                                             srv->cur_ts - host->disable_ts < 5) continue;
27541 -                       
27542 -                                       log_error_write(srv, __FILE__, __LINE__,  "sbd", 
27543 +
27544 +                                       log_error_write(srv, __FILE__, __LINE__,  "sbd",
27545                                                         "proxy - re-enabled:",
27546                                                         host->host, host->port);
27547  
27548 @@ -1317,8 +1286,8 @@
27549         p->handle_uri_clean        = mod_proxy_check_extension;
27550         p->handle_subrequest       = mod_proxy_handle_subrequest;
27551         p->handle_trigger          = mod_proxy_trigger;
27552 -       
27553 +
27554         p->data         = NULL;
27555 -       
27556 +
27557         return 0;
27558  }
27559 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_redirect.c lighttpd-1.4.12/src/mod_redirect.c
27560 --- lighttpd-1.4.11/src/mod_redirect.c  2006-02-08 15:38:06.000000000 +0200
27561 +++ lighttpd-1.4.12/src/mod_redirect.c  2006-07-11 21:23:40.000000000 +0300
27562 @@ -22,35 +22,35 @@
27563         PLUGIN_DATA;
27564         buffer *match_buf;
27565         buffer *location;
27566 -       
27567 +
27568         plugin_config **config_storage;
27569 -       
27570 -       plugin_config conf; 
27571 +
27572 +       plugin_config conf;
27573  } plugin_data;
27574  
27575  INIT_FUNC(mod_redirect_init) {
27576         plugin_data *p;
27577 -       
27578 +
27579         p = calloc(1, sizeof(*p));
27580 -       
27581 +
27582         p->match_buf = buffer_init();
27583         p->location = buffer_init();
27584 -       
27585 +
27586         return p;
27587  }
27588  
27589  FREE_FUNC(mod_redirect_free) {
27590         plugin_data *p = p_d;
27591 -       
27592 +
27593         if (!p) return HANDLER_GO_ON;
27594  
27595         if (p->config_storage) {
27596                 size_t i;
27597                 for (i = 0; i < srv->config_context->used; i++) {
27598                         plugin_config *s = p->config_storage[i];
27599 -                       
27600 +
27601                         pcre_keyvalue_buffer_free(s->redirect);
27602 -                       
27603 +
27604                         free(s);
27605                 }
27606                 free(p->config_storage);
27607 @@ -59,9 +59,9 @@
27608  
27609         buffer_free(p->match_buf);
27610         buffer_free(p->location);
27611 -       
27612 +
27613         free(p);
27614 -       
27615 +
27616         return HANDLER_GO_ON;
27617  }
27618  
27619 @@ -69,195 +69,137 @@
27620         plugin_data *p = p_d;
27621         data_unset *du;
27622         size_t i = 0;
27623 -       
27624 -       config_values_t cv[] = { 
27625 +
27626 +       config_values_t cv[] = {
27627                 { "url.redirect",               NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
27628                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
27629         };
27630 -       
27631 +
27632         if (!p) return HANDLER_ERROR;
27633 -       
27634 +
27635         /* 0 */
27636         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
27637 -       
27638 +
27639         for (i = 0; i < srv->config_context->used; i++) {
27640                 plugin_config *s;
27641                 size_t j;
27642                 array *ca;
27643                 data_array *da = (data_array *)du;
27644 -               
27645 +
27646                 s = calloc(1, sizeof(plugin_config));
27647                 s->redirect   = pcre_keyvalue_buffer_init();
27648 -               
27649 +
27650                 cv[0].destination = s->redirect;
27651 -               
27652 +
27653                 p->config_storage[i] = s;
27654                 ca = ((data_config *)srv->config_context->data[i])->value;
27655 -       
27656 +
27657                 if (0 != config_insert_values_global(srv, ca, cv)) {
27658                         return HANDLER_ERROR;
27659                 }
27660 -               
27661 +
27662                 if (NULL == (du = array_get_element(ca, "url.redirect"))) {
27663                         /* no url.redirect defined */
27664                         continue;
27665                 }
27666 -               
27667 +
27668                 if (du->type != TYPE_ARRAY) {
27669 -                       log_error_write(srv, __FILE__, __LINE__, "sss", 
27670 +                       log_error_write(srv, __FILE__, __LINE__, "sss",
27671                                         "unexpected type for key: ", "url.redirect", "array of strings");
27672 -                       
27673 +
27674                         return HANDLER_ERROR;
27675                 }
27676 -               
27677 +
27678                 da = (data_array *)du;
27679 -                               
27680 +
27681                 for (j = 0; j < da->value->used; j++) {
27682                         if (da->value->data[j]->type != TYPE_STRING) {
27683 -                               log_error_write(srv, __FILE__, __LINE__, "sssbs", 
27684 -                                               "unexpected type for key: ", 
27685 -                                               "url.redirect", 
27686 +                               log_error_write(srv, __FILE__, __LINE__, "sssbs",
27687 +                                               "unexpected type for key: ",
27688 +                                               "url.redirect",
27689                                                 "[", da->value->data[j]->key, "](string)");
27690 -                               
27691 +
27692                                 return HANDLER_ERROR;
27693                         }
27694 -                               
27695 -                       if (0 != pcre_keyvalue_buffer_append(s->redirect, 
27696 +
27697 +                       if (0 != pcre_keyvalue_buffer_append(s->redirect,
27698                                                              ((data_string *)(da->value->data[j]))->key->ptr,
27699                                                              ((data_string *)(da->value->data[j]))->value->ptr)) {
27700 -                                       
27701 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
27702 +
27703 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
27704                                                 "pcre-compile failed for", da->value->data[j]->key);
27705                         }
27706                 }
27707         }
27708 -       
27709 +
27710         return HANDLER_GO_ON;
27711  }
27712  #ifdef HAVE_PCRE_H
27713  static int mod_redirect_patch_connection(server *srv, connection *con, plugin_data *p) {
27714         size_t i, j;
27715         plugin_config *s = p->config_storage[0];
27716 -       
27717 +
27718         p->conf.redirect = s->redirect;
27719 -       
27720 +
27721         /* skip the first, the global context */
27722         for (i = 1; i < srv->config_context->used; i++) {
27723                 data_config *dc = (data_config *)srv->config_context->data[i];
27724                 s = p->config_storage[i];
27725 -               
27726 +
27727                 /* condition didn't match */
27728                 if (!config_check_cond(srv, con, dc)) continue;
27729 -               
27730 +
27731                 /* merge config */
27732                 for (j = 0; j < dc->value->used; j++) {
27733                         data_unset *du = dc->value->data[j];
27734 -                       
27735 +
27736                         if (0 == strcmp(du->key->ptr, "url.redirect")) {
27737                                 p->conf.redirect = s->redirect;
27738                                 p->conf.context = dc;
27739                         }
27740                 }
27741         }
27742 -       
27743 +
27744         return 0;
27745  }
27746  #endif
27747  static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_data) {
27748  #ifdef HAVE_PCRE_H
27749         plugin_data *p = p_data;
27750 -       size_t i;
27751 +       int i;
27752  
27753 -       /* 
27754 +       /*
27755          * REWRITE URL
27756 -        * 
27757 +        *
27758          * e.g. redirect /base/ to /index.php?section=base
27759 -        * 
27760 +        *
27761          */
27762 -       
27763 +
27764         mod_redirect_patch_connection(srv, con, p);
27765 -       
27766 +
27767         buffer_copy_string_buffer(p->match_buf, con->request.uri);
27768 -       
27769 -       for (i = 0; i < p->conf.redirect->used; i++) {
27770 -               pcre *match;
27771 -               pcre_extra *extra;
27772 -               const char *pattern;
27773 -               size_t pattern_len;
27774 -               int n;
27775 -               pcre_keyvalue *kv = p->conf.redirect->kv[i];
27776 -# define N 10
27777 -               int ovec[N * 3];
27778 -               
27779 -               match       = kv->key;
27780 -               extra       = kv->key_extra;
27781 -               pattern     = kv->value->ptr;
27782 -               pattern_len = kv->value->used - 1;
27783 -               
27784 -               if ((n = pcre_exec(match, extra, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
27785 -                       if (n != PCRE_ERROR_NOMATCH) {
27786 -                               log_error_write(srv, __FILE__, __LINE__, "sd",
27787 -                                               "execution error while matching: ", n);
27788 -                               return HANDLER_ERROR;
27789 -                       }
27790 -               } else {
27791 -                       const char **list;
27792 -                       size_t start, end;
27793 -                       size_t k;
27794 -                       
27795 -                       /* it matched */
27796 -                       pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
27797 -                       
27798 -                       /* search for $[0-9] */
27799 -                       
27800 -                       buffer_reset(p->location);
27801 -                       
27802 -                       start = 0; end = pattern_len;
27803 -                       for (k = 0; k < pattern_len; k++) {
27804 -                               if ((pattern[k] == '$' || pattern[k] == '%') &&
27805 -                                   isdigit((unsigned char)pattern[k + 1])) {
27806 -                                       /* got one */
27807 -                                       
27808 -                                       size_t num = pattern[k + 1] - '0';
27809 -                                       
27810 -                                       end = k;
27811 -                                       
27812 -                                       buffer_append_string_len(p->location, pattern + start, end - start);
27813 -                                       
27814 -                                       if (pattern[k] == '$') {
27815 -                                               /* n is always > 0 */
27816 -                                               if (num < (size_t)n) {
27817 -                                                       buffer_append_string(p->location, list[num]);
27818 -                                               }
27819 -                                       } else {
27820 -                                               config_append_cond_match_buffer(con, p->conf.context, p->location, num);
27821 -                                       }
27822 -                                       
27823 -                                       k++;
27824 -                                       start = k + 1;
27825 -                               } 
27826 -                       }
27827 -                       
27828 -                       buffer_append_string_len(p->location, pattern + start, pattern_len - start);
27829 -                       
27830 -                       pcre_free(list);
27831 -                       
27832 -                       response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
27833 -                       
27834 -                       con->http_status = 301;
27835 -                       con->file_finished = 1;
27836 -                       
27837 -                       return HANDLER_FINISHED;
27838 -               }
27839 +       i = config_exec_pcre_keyvalue_buffer(con, p->conf.redirect, p->conf.context, p->match_buf, p->location);
27840 +
27841 +       if (i >= 0) {
27842 +               response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
27843 +
27844 +               con->http_status = 301;
27845 +               con->file_finished = 1;
27846 +
27847 +               return HANDLER_FINISHED;
27848 +       }
27849 +       else if (i != PCRE_ERROR_NOMATCH) {
27850 +               log_error_write(srv, __FILE__, __LINE__, "s",
27851 +                               "execution error while matching", i);
27852         }
27853  #undef N
27854 -               
27855 +
27856  #else
27857         UNUSED(srv);
27858         UNUSED(con);
27859         UNUSED(p_data);
27860  #endif
27861 -       
27862 +
27863         return HANDLER_GO_ON;
27864  }
27865  
27866 @@ -265,13 +207,13 @@
27867  int mod_redirect_plugin_init(plugin *p) {
27868         p->version     = LIGHTTPD_VERSION_ID;
27869         p->name        = buffer_init_string("redirect");
27870 -       
27871 +
27872         p->init        = mod_redirect_init;
27873         p->handle_uri_clean  = mod_redirect_uri_handler;
27874         p->set_defaults  = mod_redirect_set_defaults;
27875         p->cleanup     = mod_redirect_free;
27876 -       
27877 +
27878         p->data        = NULL;
27879 -       
27880 +
27881         return 0;
27882  }
27883 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_rewrite.c lighttpd-1.4.12/src/mod_rewrite.c
27884 --- lighttpd-1.4.11/src/mod_rewrite.c   2005-09-29 20:59:10.000000000 +0300
27885 +++ lighttpd-1.4.12/src/mod_rewrite.c   2006-07-11 21:23:39.000000000 +0300
27886 @@ -13,24 +13,8 @@
27887  #endif
27888  
27889  typedef struct {
27890 -#ifdef HAVE_PCRE_H
27891 -       pcre *key;
27892 -#endif
27893 -       
27894 -       buffer *value;
27895 -       
27896 -       int once;
27897 -} rewrite_rule;
27898 -
27899 -typedef struct {
27900 -       rewrite_rule **ptr;
27901 -       
27902 -       size_t used;
27903 -       size_t size;
27904 -} rewrite_rule_buffer;
27905 -
27906 -typedef struct {
27907 -       rewrite_rule_buffer *rewrite;
27908 +       pcre_keyvalue_buffer *rewrite;
27909 +       buffer *once;
27910         data_config *context; /* to which apply me */
27911  } plugin_config;
27912  
27913 @@ -42,20 +26,20 @@
27914  typedef struct {
27915         PLUGIN_DATA;
27916         buffer *match_buf;
27917 -       
27918 +
27919         plugin_config **config_storage;
27920 -       
27921 -       plugin_config conf; 
27922 +
27923 +       plugin_config conf;
27924  } plugin_data;
27925  
27926  static handler_ctx * handler_ctx_init() {
27927         handler_ctx * hctx;
27928 -       
27929 +
27930         hctx = calloc(1, sizeof(*hctx));
27931 -       
27932 +
27933         hctx->state = REWRITE_STATE_UNSET;
27934         hctx->loops = 0;
27935 -       
27936 +
27937         return hctx;
27938  }
27939  
27940 @@ -63,207 +47,136 @@
27941         free(hctx);
27942  }
27943  
27944 -rewrite_rule_buffer *rewrite_rule_buffer_init(void) {
27945 -       rewrite_rule_buffer *kvb;
27946 -       
27947 -       kvb = calloc(1, sizeof(*kvb));
27948 -       
27949 -       return kvb;
27950 -}
27951 -
27952 -int rewrite_rule_buffer_append(rewrite_rule_buffer *kvb, buffer *key, buffer *value, int once) {
27953 -#ifdef HAVE_PCRE_H
27954 -       size_t i;
27955 -       const char *errptr;
27956 -       int erroff;
27957 -       
27958 -       if (!key) return -1;
27959 -
27960 -       if (kvb->size == 0) {
27961 -               kvb->size = 4;
27962 -               kvb->used = 0;
27963 -               
27964 -               kvb->ptr = malloc(kvb->size * sizeof(*kvb->ptr));
27965 -               
27966 -               for(i = 0; i < kvb->size; i++) {
27967 -                       kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
27968 -               }
27969 -       } else if (kvb->used == kvb->size) {
27970 -               kvb->size += 4;
27971 -               
27972 -               kvb->ptr = realloc(kvb->ptr, kvb->size * sizeof(*kvb->ptr));
27973 -               
27974 -               for(i = kvb->used; i < kvb->size; i++) {
27975 -                       kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
27976 -               }
27977 -       }
27978 -       
27979 -       if (NULL == (kvb->ptr[kvb->used]->key = pcre_compile(key->ptr,
27980 -                                                           0, &errptr, &erroff, NULL))) {
27981 -               
27982 -               return -1;
27983 -       }
27984 -       
27985 -       kvb->ptr[kvb->used]->value = buffer_init();
27986 -       buffer_copy_string_buffer(kvb->ptr[kvb->used]->value, value);
27987 -       kvb->ptr[kvb->used]->once = once;
27988 -       
27989 -       kvb->used++;
27990 -       
27991 -       return 0;
27992 -#else
27993 -       UNUSED(kvb);
27994 -       UNUSED(value);
27995 -       UNUSED(once);
27996 -       UNUSED(key);
27997 -
27998 -       return -1;
27999 -#endif
28000 -}
28001 -
28002 -void rewrite_rule_buffer_free(rewrite_rule_buffer *kvb) {
28003 -#ifdef HAVE_PCRE_H
28004 -       size_t i;
28005 -
28006 -       for (i = 0; i < kvb->size; i++) {
28007 -               if (kvb->ptr[i]->key) pcre_free(kvb->ptr[i]->key);
28008 -               if (kvb->ptr[i]->value) buffer_free(kvb->ptr[i]->value);
28009 -               free(kvb->ptr[i]);
28010 -       }
28011 -       
28012 -       if (kvb->ptr) free(kvb->ptr);
28013 -#endif
28014 -       
28015 -       free(kvb);
28016 -}
28017 -
28018  
28019  INIT_FUNC(mod_rewrite_init) {
28020         plugin_data *p;
28021 -       
28022 +
28023         p = calloc(1, sizeof(*p));
28024 -       
28025 +
28026         p->match_buf = buffer_init();
28027 -       
28028 +
28029         return p;
28030  }
28031  
28032  FREE_FUNC(mod_rewrite_free) {
28033         plugin_data *p = p_d;
28034 -       
28035 +
28036         UNUSED(srv);
28037  
28038         if (!p) return HANDLER_GO_ON;
28039 -       
28040 +
28041         buffer_free(p->match_buf);
28042         if (p->config_storage) {
28043                 size_t i;
28044                 for (i = 0; i < srv->config_context->used; i++) {
28045                         plugin_config *s = p->config_storage[i];
28046 -                       rewrite_rule_buffer_free(s->rewrite);
28047 -                       
28048 +                       pcre_keyvalue_buffer_free(s->rewrite);
28049 +                       buffer_free(s->once);
28050 +
28051                         free(s);
28052                 }
28053                 free(p->config_storage);
28054         }
28055 -       
28056 +
28057         free(p);
28058 -       
28059 +
28060         return HANDLER_GO_ON;
28061  }
28062  
28063  static int parse_config_entry(server *srv, plugin_config *s, array *ca, const char *option, int once) {
28064         data_unset *du;
28065 -       
28066 +
28067         if (NULL != (du = array_get_element(ca, option))) {
28068                 data_array *da = (data_array *)du;
28069                 size_t j;
28070 -               
28071 +
28072                 if (du->type != TYPE_ARRAY) {
28073 -                       log_error_write(srv, __FILE__, __LINE__, "sss", 
28074 +                       log_error_write(srv, __FILE__, __LINE__, "sss",
28075                                         "unexpected type for key: ", option, "array of strings");
28076 -                       
28077 +
28078                         return HANDLER_ERROR;
28079                 }
28080 -               
28081 +
28082                 da = (data_array *)du;
28083 -               
28084 +
28085                 for (j = 0; j < da->value->used; j++) {
28086                         if (da->value->data[j]->type != TYPE_STRING) {
28087 -                               log_error_write(srv, __FILE__, __LINE__, "sssbs", 
28088 -                                               "unexpected type for key: ", 
28089 -                                               option, 
28090 +                               log_error_write(srv, __FILE__, __LINE__, "sssbs",
28091 +                                               "unexpected type for key: ",
28092 +                                               option,
28093                                                 "[", da->value->data[j]->key, "](string)");
28094 -                               
28095 +
28096                                 return HANDLER_ERROR;
28097                         }
28098 -                       
28099 -                       if (0 != rewrite_rule_buffer_append(s->rewrite, 
28100 -                                                           ((data_string *)(da->value->data[j]))->key,
28101 -                                                           ((data_string *)(da->value->data[j]))->value,
28102 -                                                           once)) {
28103 +
28104 +                       if (0 != pcre_keyvalue_buffer_append(s->rewrite,
28105 +                                                           ((data_string *)(da->value->data[j]))->key->ptr,
28106 +                                                           ((data_string *)(da->value->data[j]))->value->ptr)) {
28107  #ifdef HAVE_PCRE_H
28108 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
28109 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
28110                                                 "pcre-compile failed for", da->value->data[j]->key);
28111  #else
28112 -                               log_error_write(srv, __FILE__, __LINE__, "s", 
28113 +                               log_error_write(srv, __FILE__, __LINE__, "s",
28114                                                 "pcre support is missing, please install libpcre and the headers");
28115  #endif
28116                         }
28117 +
28118 +                       if (once) {
28119 +                               buffer_append_string_len(s->once, CONST_STR_LEN("1"));
28120 +                       } else {
28121 +                               buffer_append_string_len(s->once, CONST_STR_LEN("0"));
28122 +                       }
28123                 }
28124         }
28125 -       
28126 +
28127         return 0;
28128  }
28129  
28130  SETDEFAULTS_FUNC(mod_rewrite_set_defaults) {
28131         plugin_data *p = p_d;
28132         size_t i = 0;
28133 -       
28134 -       config_values_t cv[] = { 
28135 +
28136 +       config_values_t cv[] = {
28137                 { "url.rewrite-repeat",        NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
28138                 { "url.rewrite-once",          NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
28139 -               
28140 -               /* old names, still supported 
28141 -                * 
28142 +
28143 +               /* old names, still supported
28144 +                *
28145                  * url.rewrite remapped to url.rewrite-once
28146                  * url.rewrite-final    is url.rewrite-once
28147 -                * 
28148 +                *
28149                  */
28150                 { "url.rewrite",               NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
28151                 { "url.rewrite-final",         NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
28152                 { NULL,                        NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
28153         };
28154 -       
28155 +
28156         if (!p) return HANDLER_ERROR;
28157 -       
28158 +
28159         /* 0 */
28160         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
28161 -       
28162 +
28163         for (i = 0; i < srv->config_context->used; i++) {
28164                 plugin_config *s;
28165                 array *ca;
28166 -               
28167 +
28168                 s = calloc(1, sizeof(plugin_config));
28169 -               s->rewrite   = rewrite_rule_buffer_init();
28170 -               
28171 -               cv[0].destination = s->rewrite;
28172 -               cv[1].destination = s->rewrite;
28173 -               cv[2].destination = s->rewrite;
28174 -               
28175 +               s->rewrite   = pcre_keyvalue_buffer_init();
28176 +               s->once      = buffer_init();
28177 +
28178                 p->config_storage[i] = s;
28179                 ca = ((data_config *)srv->config_context->data[i])->value;
28180 -       
28181 +
28182                 if (0 != config_insert_values_global(srv, ca, cv)) {
28183                         return HANDLER_ERROR;
28184                 }
28185 -               
28186 +
28187                 parse_config_entry(srv, s, ca, "url.rewrite-once",   1);
28188                 parse_config_entry(srv, s, ca, "url.rewrite-final",  1);
28189                 parse_config_entry(srv, s, ca, "url.rewrite",        1);
28190                 parse_config_entry(srv, s, ca, "url.rewrite-repeat", 0);
28191         }
28192 -       
28193 +
28194         return HANDLER_GO_ON;
28195  }
28196  #ifdef HAVE_PCRE_H
28197 @@ -271,157 +184,107 @@
28198         size_t i, j;
28199         plugin_config *s = p->config_storage[0];
28200         p->conf.rewrite = s->rewrite;
28201 -       
28202 +       p->conf.once    = s->once;
28203 +
28204         /* skip the first, the global context */
28205         for (i = 1; i < srv->config_context->used; i++) {
28206                 data_config *dc = (data_config *)srv->config_context->data[i];
28207                 s = p->config_storage[i];
28208 -               
28209 +
28210                 if (COMP_HTTP_URL == dc->comp) continue;
28211 -               
28212 +
28213                 /* condition didn't match */
28214                 if (!config_check_cond(srv, con, dc)) continue;
28215 -               
28216 +
28217                 /* merge config */
28218                 for (j = 0; j < dc->value->used; j++) {
28219                         data_unset *du = dc->value->data[j];
28220 -                       
28221 +
28222                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite"))) {
28223                                 p->conf.rewrite = s->rewrite;
28224 +                               p->conf.once    = s->once;
28225                                 p->conf.context = dc;
28226                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-once"))) {
28227                                 p->conf.rewrite = s->rewrite;
28228 +                               p->conf.once    = s->once;
28229                                 p->conf.context = dc;
28230                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-repeat"))) {
28231                                 p->conf.rewrite = s->rewrite;
28232 +                               p->conf.once    = s->once;
28233                                 p->conf.context = dc;
28234                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-final"))) {
28235                                 p->conf.rewrite = s->rewrite;
28236 +                               p->conf.once    = s->once;
28237                                 p->conf.context = dc;
28238                         }
28239                 }
28240         }
28241 -       
28242 +
28243         return 0;
28244  }
28245  #endif
28246  URIHANDLER_FUNC(mod_rewrite_con_reset) {
28247         plugin_data *p = p_d;
28248 -       
28249 +
28250         UNUSED(srv);
28251 -       
28252 +
28253         if (con->plugin_ctx[p->id]) {
28254                 handler_ctx_free(con->plugin_ctx[p->id]);
28255                 con->plugin_ctx[p->id] = NULL;
28256         }
28257 -       
28258 +
28259         return HANDLER_GO_ON;
28260  }
28261  
28262  URIHANDLER_FUNC(mod_rewrite_uri_handler) {
28263  #ifdef HAVE_PCRE_H
28264         plugin_data *p = p_d;
28265 -       size_t i;
28266 +       int i;
28267         handler_ctx *hctx;
28268  
28269 -       /* 
28270 +       /*
28271          * REWRITE URL
28272 -        * 
28273 +        *
28274          * e.g. rewrite /base/ to /index.php?section=base
28275 -        * 
28276 +        *
28277          */
28278 -       
28279 +
28280         if (con->plugin_ctx[p->id]) {
28281                 hctx = con->plugin_ctx[p->id];
28282 -               
28283 +
28284                 if (hctx->loops++ > 100) {
28285 -                       log_error_write(srv, __FILE__, __LINE__,  "s",  
28286 +                       log_error_write(srv, __FILE__, __LINE__,  "s",
28287                                         "ENDLESS LOOP IN rewrite-rule DETECTED ... aborting request, perhaps you want to use url.rewrite-once instead of url.rewrite-repeat");
28288 -                       
28289 +
28290                         return HANDLER_ERROR;
28291                 }
28292 -               
28293 +
28294                 if (hctx->state == REWRITE_STATE_FINISHED) return HANDLER_GO_ON;
28295         }
28296 -       
28297 +
28298         mod_rewrite_patch_connection(srv, con, p);
28299  
28300         if (!p->conf.rewrite) return HANDLER_GO_ON;
28301 -       
28302 +
28303         buffer_copy_string_buffer(p->match_buf, con->request.uri);
28304 -       
28305 -       for (i = 0; i < p->conf.rewrite->used; i++) {
28306 -               pcre *match;
28307 -               const char *pattern;
28308 -               size_t pattern_len;
28309 -               int n;
28310 -               rewrite_rule *rule = p->conf.rewrite->ptr[i];
28311 -# define N 10
28312 -               int ovec[N * 3];
28313 -               
28314 -               match       = rule->key;
28315 -               pattern     = rule->value->ptr;
28316 -               pattern_len = rule->value->used - 1;
28317 -               
28318 -               if ((n = pcre_exec(match, NULL, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
28319 -                       if (n != PCRE_ERROR_NOMATCH) {
28320 -                               log_error_write(srv, __FILE__, __LINE__, "sd",
28321 -                                               "execution error while matching: ", n);
28322 -                               return HANDLER_ERROR;
28323 -                       }
28324 -               } else {
28325 -                       const char **list;
28326 -                       size_t start, end;
28327 -                       size_t k;
28328 -                       
28329 -                       /* it matched */
28330 -                       pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
28331 -                       
28332 -                       /* search for $[0-9] */
28333 -                       
28334 -                       buffer_reset(con->request.uri);
28335 -                       
28336 -                       start = 0; end = pattern_len;
28337 -                       for (k = 0; k < pattern_len; k++) {
28338 -                               if ((pattern[k] == '$' || pattern[k] == '%') &&
28339 -                                   isdigit((unsigned char)pattern[k + 1])) {
28340 -                                       /* got one */
28341 -                                       
28342 -                                       size_t num = pattern[k + 1] - '0';
28343 -                                       
28344 -                                       end = k;
28345 -                                       
28346 -                                       buffer_append_string_len(con->request.uri, pattern + start, end - start);
28347 -                                       
28348 -                                       if (pattern[k] == '$') {
28349 -                                               /* n is always > 0 */
28350 -                                               if (num < (size_t)n) {
28351 -                                                       buffer_append_string(con->request.uri, list[num]);
28352 -                                               }
28353 -                                       } else {
28354 -                                               config_append_cond_match_buffer(con, p->conf.context, con->request.uri, num);
28355 -                                       }
28356 -                                       
28357 -                                       k++;
28358 -                                       start = k + 1;
28359 -                               } 
28360 -                       }
28361 -                       
28362 -                       buffer_append_string_len(con->request.uri, pattern + start, pattern_len - start);
28363 -                       
28364 -                       pcre_free(list);
28365 -                       
28366 -                       hctx = handler_ctx_init();
28367 -                               
28368 -                       con->plugin_ctx[p->id] = hctx;
28369 -                       
28370 -                       if (rule->once) hctx->state = REWRITE_STATE_FINISHED;
28371 -                       
28372 -                       return HANDLER_COMEBACK;
28373 -               }
28374 +       i = config_exec_pcre_keyvalue_buffer(con, p->conf.rewrite, p->conf.context, p->match_buf, con->request.uri);
28375 +
28376 +       if (i >= 0) {
28377 +               hctx = handler_ctx_init();
28378 +
28379 +               con->plugin_ctx[p->id] = hctx;
28380 +
28381 +               if (p->conf.once->ptr[i] == '1')
28382 +                       hctx->state = REWRITE_STATE_FINISHED;
28383 +
28384 +               return HANDLER_COMEBACK;
28385 +       }
28386 +       else if (i != PCRE_ERROR_NOMATCH) {
28387 +               log_error_write(srv, __FILE__, __LINE__, "s",
28388 +                               "execution error while matching", i);
28389         }
28390  #undef N
28391 -               
28392 +
28393  #else
28394         UNUSED(srv);
28395         UNUSED(con);
28396 @@ -434,17 +297,17 @@
28397  int mod_rewrite_plugin_init(plugin *p) {
28398         p->version     = LIGHTTPD_VERSION_ID;
28399         p->name        = buffer_init_string("rewrite");
28400 -       
28401 +
28402         p->init        = mod_rewrite_init;
28403         /* it has to stay _raw as we are matching on uri + querystring
28404          */
28405 -       
28406 +
28407         p->handle_uri_raw = mod_rewrite_uri_handler;
28408         p->set_defaults = mod_rewrite_set_defaults;
28409         p->cleanup     = mod_rewrite_free;
28410         p->connection_reset = mod_rewrite_con_reset;
28411 -       
28412 +
28413         p->data        = NULL;
28414 -       
28415 +
28416         return 0;
28417  }
28418 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_rrdtool.c lighttpd-1.4.12/src/mod_rrdtool.c
28419 --- lighttpd-1.4.11/src/mod_rrdtool.c   2005-08-22 01:52:24.000000000 +0300
28420 +++ lighttpd-1.4.12/src/mod_rrdtool.c   2006-07-11 21:23:40.000000000 +0300
28421 @@ -5,7 +5,6 @@
28422  #include <stdlib.h>
28423  #include <stdio.h>
28424  #include <string.h>
28425 -#include <unistd.h>
28426  #include <errno.h>
28427  #include <time.h>
28428  
28429 @@ -20,10 +19,14 @@
28430  /* no need for waitpid if we don't have fork */
28431  #include <sys/wait.h>
28432  #endif
28433 +
28434 +#include "sys-files.h"
28435 +#include "sys-process.h"
28436 +
28437  typedef struct {
28438         buffer *path_rrdtool_bin;
28439         buffer *path_rrd;
28440 -       
28441 +
28442         double requests, *requests_ptr;
28443         double bytes_written, *bytes_written_ptr;
28444         double bytes_read, *bytes_read_ptr;
28445 @@ -31,84 +34,84 @@
28446  
28447  typedef struct {
28448         PLUGIN_DATA;
28449 -       
28450 +
28451         buffer *cmd;
28452         buffer *resp;
28453 -       
28454 +
28455         int read_fd, write_fd;
28456         pid_t rrdtool_pid;
28457 -       
28458 +
28459         int rrdtool_running;
28460 -       
28461 +
28462         plugin_config **config_storage;
28463         plugin_config conf;
28464  } plugin_data;
28465  
28466  INIT_FUNC(mod_rrd_init) {
28467         plugin_data *p;
28468 -       
28469 +
28470         p = calloc(1, sizeof(*p));
28471 -       
28472 +
28473         p->resp = buffer_init();
28474         p->cmd = buffer_init();
28475 -       
28476 +
28477         return p;
28478  }
28479  
28480  FREE_FUNC(mod_rrd_free) {
28481         plugin_data *p = p_d;
28482         size_t i;
28483 -       
28484 +
28485         if (!p) return HANDLER_GO_ON;
28486 -       
28487 +
28488         if (p->config_storage) {
28489                 for (i = 0; i < srv->config_context->used; i++) {
28490                         plugin_config *s = p->config_storage[i];
28491 -                       
28492 +
28493                         buffer_free(s->path_rrdtool_bin);
28494                         buffer_free(s->path_rrd);
28495 -                       
28496 +
28497                         free(s);
28498                 }
28499         }
28500         buffer_free(p->cmd);
28501         buffer_free(p->resp);
28502 -       
28503 +
28504         free(p->config_storage);
28505 -       
28506 +
28507         if (p->rrdtool_pid) {
28508                 int status;
28509                 close(p->read_fd);
28510                 close(p->write_fd);
28511 -#ifdef HAVE_FORK       
28512 +#ifdef HAVE_FORK
28513                 /* collect status */
28514                 waitpid(p->rrdtool_pid, &status, 0);
28515  #endif
28516         }
28517 -       
28518 +
28519         free(p);
28520 -       
28521 +
28522         return HANDLER_GO_ON;
28523  }
28524  
28525  int mod_rrd_create_pipe(server *srv, plugin_data *p) {
28526         pid_t pid;
28527 -       
28528 +
28529         int to_rrdtool_fds[2];
28530         int from_rrdtool_fds[2];
28531 -#ifdef HAVE_FORK       
28532 +#ifdef HAVE_FORK
28533         if (pipe(to_rrdtool_fds)) {
28534 -               log_error_write(srv, __FILE__, __LINE__, "ss", 
28535 +               log_error_write(srv, __FILE__, __LINE__, "ss",
28536                                 "pipe failed: ", strerror(errno));
28537                 return -1;
28538         }
28539 -       
28540 +
28541         if (pipe(from_rrdtool_fds)) {
28542 -               log_error_write(srv, __FILE__, __LINE__, "ss", 
28543 +               log_error_write(srv, __FILE__, __LINE__, "ss",
28544                                 "pipe failed: ", strerror(errno));
28545                 return -1;
28546         }
28547 -       
28548 +
28549         /* fork, execve */
28550         switch (pid = fork()) {
28551         case 0: {
28552 @@ -117,33 +120,33 @@
28553                 int argc;
28554                 int i = 0;
28555                 char *dash = "-";
28556 -               
28557 +
28558                 /* move stdout to from_rrdtool_fd[1] */
28559                 close(STDOUT_FILENO);
28560                 dup2(from_rrdtool_fds[1], STDOUT_FILENO);
28561                 close(from_rrdtool_fds[1]);
28562                 /* not needed */
28563                 close(from_rrdtool_fds[0]);
28564 -               
28565 +
28566                 /* move the stdin to to_rrdtool_fd[0] */
28567                 close(STDIN_FILENO);
28568                 dup2(to_rrdtool_fds[0], STDIN_FILENO);
28569                 close(to_rrdtool_fds[0]);
28570                 /* not needed */
28571                 close(to_rrdtool_fds[1]);
28572 -               
28573 +
28574                 close(STDERR_FILENO);
28575 -               
28576 +
28577                 if (srv->errorlog_mode == ERRORLOG_FILE) {
28578                         dup2(srv->errorlog_fd, STDERR_FILENO);
28579                         close(srv->errorlog_fd);
28580                 }
28581 -               
28582 +
28583                 /* set up args */
28584                 argc = 3;
28585                 args = malloc(sizeof(*args) * argc);
28586                 i = 0;
28587 -               
28588 +
28589                 args[i++] = p->conf.path_rrdtool_bin->ptr;
28590                 args[i++] = dash;
28591                 args[i++] = NULL;
28592 @@ -152,12 +155,12 @@
28593                 for (i = 3; i < 256; i++) {
28594                         close(i);
28595                 }
28596 -               
28597 +
28598                 /* exec the cgi */
28599                 execv(args[0], args);
28600 -               
28601 +
28602                 log_error_write(srv, __FILE__, __LINE__, "sss", "spawing rrdtool failed: ", strerror(errno), args[0]);
28603 -               
28604 +
28605                 /* */
28606                 SEGFAULT();
28607                 break;
28608 @@ -168,19 +171,19 @@
28609                 break;
28610         default: {
28611                 /* father */
28612 -               
28613 +
28614                 close(from_rrdtool_fds[1]);
28615                 close(to_rrdtool_fds[0]);
28616 -               
28617 +
28618                 /* register PID and wait for them asyncronously */
28619                 p->write_fd = to_rrdtool_fds[1];
28620                 p->read_fd = from_rrdtool_fds[0];
28621                 p->rrdtool_pid = pid;
28622 -               
28623 +
28624                 break;
28625         }
28626         }
28627 -       
28628 +
28629         return 0;
28630  #else
28631         return -1;
28632 @@ -189,19 +192,19 @@
28633  
28634  static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s) {
28635         struct stat st;
28636 -       
28637 +
28638         /* check if DB already exists */
28639         if (0 == stat(s->path_rrd->ptr, &st)) {
28640                 /* check if it is plain file */
28641                 if (!S_ISREG(st.st_mode)) {
28642 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
28643 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
28644                                         "not a regular file:", s->path_rrd);
28645                         return HANDLER_ERROR;
28646                 }
28647         } else {
28648                 int r ;
28649                 /* create a new one */
28650 -               
28651 +
28652                 BUFFER_COPY_STRING_CONST(p->cmd, "create ");
28653                 buffer_append_string_buffer(p->cmd, s->path_rrd);
28654                 buffer_append_string(p->cmd, " --step 60 ");
28655 @@ -220,158 +223,155 @@
28656                 buffer_append_string(p->cmd, "RRA:MIN:0.5:6:700 ");
28657                 buffer_append_string(p->cmd, "RRA:MIN:0.5:24:775 ");
28658                 buffer_append_string(p->cmd, "RRA:MIN:0.5:288:797\n");
28659 -               
28660 +
28661                 if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
28662 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
28663 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
28664                                 "rrdtool-write: failed", strerror(errno));
28665 -                       
28666 +
28667                         return HANDLER_ERROR;
28668                 }
28669 -               
28670 +
28671                 buffer_prepare_copy(p->resp, 4096);
28672                 if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
28673 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
28674 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
28675                                 "rrdtool-read: failed", strerror(errno));
28676 -                       
28677 +
28678                         return HANDLER_ERROR;
28679                 }
28680 -               
28681 +
28682                 p->resp->used = r;
28683 -               
28684 +
28685                 if (p->resp->ptr[0] != 'O' ||
28686                     p->resp->ptr[1] != 'K') {
28687 -                       log_error_write(srv, __FILE__, __LINE__, "sbb", 
28688 +                       log_error_write(srv, __FILE__, __LINE__, "sbb",
28689                                 "rrdtool-response:", p->cmd, p->resp);
28690 -                       
28691 +
28692                         return HANDLER_ERROR;
28693                 }
28694         }
28695 -       
28696 +
28697         return HANDLER_GO_ON;
28698  }
28699  
28700 -#define PATCH(x) \
28701 -       p->conf.x = s->x;
28702  static int mod_rrd_patch_connection(server *srv, connection *con, plugin_data *p) {
28703         size_t i, j;
28704         plugin_config *s = p->config_storage[0];
28705 -       
28706 -       PATCH(path_rrdtool_bin);
28707 -       PATCH(path_rrd);
28708 -       
28709 +
28710 +       PATCH_OPTION(path_rrdtool_bin);
28711 +       PATCH_OPTION(path_rrd);
28712 +
28713         p->conf.bytes_written_ptr = &(s->bytes_written);
28714         p->conf.bytes_read_ptr = &(s->bytes_read);
28715         p->conf.requests_ptr = &(s->requests);
28716 -       
28717 +
28718         /* skip the first, the global context */
28719         for (i = 1; i < srv->config_context->used; i++) {
28720                 data_config *dc = (data_config *)srv->config_context->data[i];
28721                 s = p->config_storage[i];
28722 -               
28723 +
28724                 /* condition didn't match */
28725                 if (!config_check_cond(srv, con, dc)) continue;
28726 -               
28727 +
28728                 /* merge config */
28729                 for (j = 0; j < dc->value->used; j++) {
28730                         data_unset *du = dc->value->data[j];
28731 -                       
28732 +
28733                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("rrdtool.db-name"))) {
28734 -                               PATCH(path_rrd);
28735 +                               PATCH_OPTION(path_rrd);
28736                                 /* get pointers to double values */
28737 -                               
28738 +
28739                                 p->conf.bytes_written_ptr = &(s->bytes_written);
28740                                 p->conf.bytes_read_ptr = &(s->bytes_read);
28741                                 p->conf.requests_ptr = &(s->requests);
28742                         }
28743                 }
28744         }
28745 -       
28746 +
28747         return 0;
28748  }
28749 -#undef PATCH
28750  
28751  SETDEFAULTS_FUNC(mod_rrd_set_defaults) {
28752         plugin_data *p = p_d;
28753         size_t i;
28754 -       
28755 -       config_values_t cv[] = { 
28756 +
28757 +       config_values_t cv[] = {
28758                 { "rrdtool.binary",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
28759                 { "rrdtool.db-name",             NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
28760                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
28761         };
28762 -       
28763 +
28764         if (!p) return HANDLER_ERROR;
28765 -       
28766 +
28767         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
28768 -       
28769 +
28770         for (i = 0; i < srv->config_context->used; i++) {
28771                 plugin_config *s;
28772 -               
28773 +
28774                 s = calloc(1, sizeof(plugin_config));
28775                 s->path_rrdtool_bin = buffer_init();
28776                 s->path_rrd = buffer_init();
28777                 s->requests = 0;
28778                 s->bytes_written = 0;
28779                 s->bytes_read = 0;
28780 -               
28781 +
28782                 cv[0].destination = s->path_rrdtool_bin;
28783                 cv[1].destination = s->path_rrd;
28784 -               
28785 +
28786                 p->config_storage[i] = s;
28787 -       
28788 +
28789                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
28790                         return HANDLER_ERROR;
28791                 }
28792 -               
28793 +
28794                 if (i > 0 && !buffer_is_empty(s->path_rrdtool_bin)) {
28795                         /* path_rrdtool_bin is a global option */
28796 -                       
28797 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
28798 +
28799 +                       log_error_write(srv, __FILE__, __LINE__, "s",
28800                                         "rrdtool.binary can only be set as a global option.");
28801 -                       
28802 +
28803                         return HANDLER_ERROR;
28804                 }
28805 -               
28806 +
28807         }
28808 -       
28809 +
28810         p->conf.path_rrdtool_bin = p->config_storage[0]->path_rrdtool_bin;
28811         p->rrdtool_running = 0;
28812 -       
28813 +
28814         /* check for dir */
28815 -       
28816 +
28817         if (buffer_is_empty(p->conf.path_rrdtool_bin)) {
28818 -               log_error_write(srv, __FILE__, __LINE__, "s", 
28819 +               log_error_write(srv, __FILE__, __LINE__, "s",
28820                                 "rrdtool.binary has to be set");
28821                 return HANDLER_ERROR;
28822         }
28823 -       
28824 +
28825         /* open the pipe to rrdtool */
28826         if (mod_rrd_create_pipe(srv, p)) {
28827                 return HANDLER_ERROR;
28828         }
28829 -       
28830 +
28831         p->rrdtool_running = 1;
28832 -               
28833 +
28834         return HANDLER_GO_ON;
28835  }
28836  
28837  TRIGGER_FUNC(mod_rrd_trigger) {
28838         plugin_data *p = p_d;
28839         size_t i;
28840 -       
28841 +
28842         if (!p->rrdtool_running) return HANDLER_GO_ON;
28843         if ((srv->cur_ts % 60) != 0) return HANDLER_GO_ON;
28844 -       
28845 +
28846         for (i = 0; i < srv->config_context->used; i++) {
28847                 plugin_config *s = p->config_storage[i];
28848                 int r;
28849 -               
28850 +
28851                 if (buffer_is_empty(s->path_rrd)) continue;
28852 -       
28853 +
28854                 /* write the data down every minute */
28855 -               
28856 +
28857                 if (HANDLER_GO_ON != mod_rrdtool_create_rrd(srv, p, s)) return HANDLER_ERROR;
28858 -               
28859 +
28860                 BUFFER_COPY_STRING_CONST(p->cmd, "update ");
28861                 buffer_append_string_buffer(p->cmd, s->path_rrd);
28862                 BUFFER_APPEND_STRING_CONST(p->cmd, " N:");
28863 @@ -381,69 +381,69 @@
28864                 BUFFER_APPEND_STRING_CONST(p->cmd, ":");
28865                 buffer_append_long(p->cmd, s->requests);
28866                 BUFFER_APPEND_STRING_CONST(p->cmd, "\n");
28867 -               
28868 +
28869                 if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
28870                         p->rrdtool_running = 0;
28871 -                       
28872 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
28873 +
28874 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
28875                                         "rrdtool-write: failed", strerror(errno));
28876 -                       
28877 +
28878                         return HANDLER_ERROR;
28879                 }
28880 -               
28881 +
28882                 buffer_prepare_copy(p->resp, 4096);
28883                 if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
28884                         p->rrdtool_running = 0;
28885 -                       
28886 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
28887 +
28888 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
28889                                         "rrdtool-read: failed", strerror(errno));
28890 -                       
28891 +
28892                         return HANDLER_ERROR;
28893                 }
28894 -               
28895 +
28896                 p->resp->used = r;
28897 -               
28898 +
28899                 if (p->resp->ptr[0] != 'O' ||
28900                     p->resp->ptr[1] != 'K') {
28901                         p->rrdtool_running = 0;
28902 -                       
28903 -                       log_error_write(srv, __FILE__, __LINE__, "sbb", 
28904 +
28905 +                       log_error_write(srv, __FILE__, __LINE__, "sbb",
28906                                         "rrdtool-response:", p->cmd, p->resp);
28907 -                       
28908 +
28909                         return HANDLER_ERROR;
28910                 }
28911                 s->requests = 0;
28912                 s->bytes_written = 0;
28913                 s->bytes_read = 0;
28914         }
28915 -       
28916 +
28917         return HANDLER_GO_ON;
28918  }
28919  
28920  REQUESTDONE_FUNC(mod_rrd_account) {
28921         plugin_data *p = p_d;
28922 -       
28923 +
28924         mod_rrd_patch_connection(srv, con, p);
28925 -       
28926 +
28927         *(p->conf.requests_ptr)      += 1;
28928         *(p->conf.bytes_written_ptr) += con->bytes_written;
28929         *(p->conf.bytes_read_ptr)    += con->bytes_read;
28930 -       
28931 +
28932         return HANDLER_GO_ON;
28933  }
28934  
28935  int mod_rrdtool_plugin_init(plugin *p) {
28936         p->version     = LIGHTTPD_VERSION_ID;
28937         p->name        = buffer_init_string("rrd");
28938 -       
28939 +
28940         p->init        = mod_rrd_init;
28941         p->cleanup     = mod_rrd_free;
28942         p->set_defaults= mod_rrd_set_defaults;
28943 -       
28944 +
28945         p->handle_trigger      = mod_rrd_trigger;
28946         p->handle_request_done = mod_rrd_account;
28947 -       
28948 +
28949         p->data        = NULL;
28950 -       
28951 +
28952         return 0;
28953  }
28954 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_scgi.c lighttpd-1.4.12/src/mod_scgi.c
28955 --- lighttpd-1.4.11/src/mod_scgi.c      2006-03-04 17:15:26.000000000 +0200
28956 +++ lighttpd-1.4.12/src/mod_scgi.c      2006-07-11 21:23:40.000000000 +0300
28957 @@ -1,5 +1,4 @@
28958  #include <sys/types.h>
28959 -#include <unistd.h>
28960  #include <errno.h>
28961  #include <fcntl.h>
28962  #include <string.h>
28963 @@ -30,7 +29,9 @@
28964  #endif
28965  
28966  #include "sys-socket.h"
28967 -
28968 +#include "sys-files.h"
28969 +#include "sys-strings.h"
28970 +#include "sys-process.h"
28971  
28972  #ifndef UNIX_PATH_MAX
28973  # define UNIX_PATH_MAX 108
28974 @@ -46,30 +47,29 @@
28975  enum {EOL_UNSET, EOL_N, EOL_RN};
28976  
28977  /*
28978 - * 
28979 + *
28980   * TODO:
28981 - * 
28982 + *
28983   * - add timeout for a connect to a non-scgi process
28984   *   (use state_timestamp + state)
28985 - * 
28986 + *
28987   */
28988  
28989  typedef struct scgi_proc {
28990         size_t id; /* id will be between 1 and max_procs */
28991         buffer *socket; /* config.socket + "-" + id */
28992         unsigned port;  /* config.port + pno */
28993 -       
28994 -       pid_t pid;   /* PID of the spawned process (0 if not spawned locally) */
28995  
28996 +       pid_t pid;   /* PID of the spawned process (0 if not spawned locally) */
28997  
28998         size_t load; /* number of requests waiting on this process */
28999  
29000         time_t last_used; /* see idle_timeout */
29001         size_t requests;  /* see max_requests */
29002         struct scgi_proc *prev, *next; /* see first */
29003 -       
29004 +
29005         time_t disable_ts; /* replace by host->something */
29006 -       
29007 +
29008         int is_local;
29009  
29010         enum { PROC_STATE_UNSET,            /* init-phase */
29011 @@ -78,7 +78,7 @@
29012                         PROC_STATE_KILLED,  /* was killed as we don't have the load anymore */
29013                         PROC_STATE_DIED,    /* marked as dead, should be restarted */
29014                         PROC_STATE_DISABLED /* proc disabled as it resulted in an error */
29015 -       } state; 
29016 +       } state;
29017  } scgi_proc;
29018  
29019  typedef struct {
29020 @@ -86,20 +86,20 @@
29021          * sorted by lowest load
29022          *
29023          * whenever a job is done move it up in the list
29024 -        * until it is sorted, move it down as soon as the 
29025 +        * until it is sorted, move it down as soon as the
29026          * job is started
29027          */
29028 -       scgi_proc *first; 
29029 -       scgi_proc *unused_procs; 
29030 +       scgi_proc *first;
29031 +       scgi_proc *unused_procs;
29032  
29033 -       /* 
29034 +       /*
29035          * spawn at least min_procs, at max_procs.
29036          *
29037 -        * as soon as the load of the first entry 
29038 +        * as soon as the load of the first entry
29039          * is max_load_per_proc we spawn a new one
29040 -        * and add it to the first entry and give it 
29041 +        * and add it to the first entry and give it
29042          * the load
29043 -        * 
29044 +        *
29045          */
29046  
29047         unsigned short min_procs;
29048 @@ -111,44 +111,44 @@
29049  
29050         /*
29051          * kick the process from the list if it was not
29052 -        * used for idle_timeout until min_procs is 
29053 +        * used for idle_timeout until min_procs is
29054          * reached. this helps to get the processlist
29055          * small again we had a small peak load.
29056          *
29057          */
29058 -       
29059 +
29060         unsigned short idle_timeout;
29061 -       
29062 +
29063         /*
29064          * time after a disabled remote connection is tried to be re-enabled
29065 -        * 
29066 -        * 
29067 +        *
29068 +        *
29069          */
29070 -       
29071 +
29072         unsigned short disable_time;
29073  
29074         /*
29075          * same scgi processes get a little bit larger
29076 -        * than wanted. max_requests_per_proc kills a 
29077 +        * than wanted. max_requests_per_proc kills a
29078          * process after a number of handled requests.
29079          *
29080          */
29081         size_t max_requests_per_proc;
29082 -       
29083 +
29084  
29085         /* config */
29086  
29087 -       /* 
29088 -        * host:port 
29089 +       /*
29090 +        * host:port
29091          *
29092 -        * if host is one of the local IP adresses the 
29093 +        * if host is one of the local IP adresses the
29094          * whole connection is local
29095          *
29096          * if tcp/ip should be used host AND port have
29097 -        * to be specified 
29098 -        * 
29099 -        */ 
29100 -       buffer *host; 
29101 +        * to be specified
29102 +        *
29103 +        */
29104 +       buffer *host;
29105         unsigned short port;
29106  
29107         /*
29108 @@ -161,7 +161,7 @@
29109          */
29110         buffer *unixsocket;
29111  
29112 -       /* if socket is local we can start the scgi 
29113 +       /* if socket is local we can start the scgi
29114          * process ourself
29115          *
29116          * bin-path is the path to the binary
29117 @@ -169,19 +169,19 @@
29118          * check min_procs and max_procs for the number
29119          * of process to start-up
29120          */
29121 -       buffer *bin_path; 
29122 -       
29123 -       /* bin-path is set bin-environment is taken to 
29124 +       buffer *bin_path;
29125 +
29126 +       /* bin-path is set bin-environment is taken to
29127          * create the environement before starting the
29128          * FastCGI process
29129 -        * 
29130 +        *
29131          */
29132         array *bin_env;
29133 -       
29134 +
29135         array *bin_env_copy;
29136 -       
29137 +
29138         /*
29139 -        * docroot-translation between URL->phys and the 
29140 +        * docroot-translation between URL->phys and the
29141          * remote host
29142          *
29143          * reasons:
29144 @@ -192,7 +192,7 @@
29145         buffer *docroot;
29146  
29147         /*
29148 -        * check_local tell you if the phys file is stat()ed 
29149 +        * check_local tell you if the phys file is stat()ed
29150          * or not. FastCGI doesn't care if the service is
29151          * remote. If the web-server side doesn't contain
29152          * the scgi-files we should not stat() for them
29153 @@ -202,33 +202,33 @@
29154  
29155         /*
29156          * append PATH_INFO to SCRIPT_FILENAME
29157 -        * 
29158 +        *
29159          * php needs this if cgi.fix_pathinfo is provied
29160 -        * 
29161 +        *
29162          */
29163 -       
29164 +
29165         ssize_t load; /* replace by host->load */
29166  
29167         size_t max_id; /* corresponds most of the time to
29168         num_procs.
29169 -       
29170 +
29171         only if a process is killed max_id waits for the process itself
29172         to die and decrements its afterwards */
29173  } scgi_extension_host;
29174  
29175  /*
29176   * one extension can have multiple hosts assigned
29177 - * one host can spawn additional processes on the same 
29178 + * one host can spawn additional processes on the same
29179   *   socket (if we control it)
29180   *
29181   * ext -> host -> procs
29182   *    1:n     1:n
29183   *
29184 - * if the scgi process is remote that whole goes down 
29185 + * if the scgi process is remote that whole goes down
29186   * to
29187   *
29188   * ext -> host -> procs
29189 - *    1:n     1:1 
29190 + *    1:n     1:1
29191   *
29192   * in case of PHP and FCGI_CHILDREN we have again a procs
29193   * but we don't control it directly.
29194 @@ -239,7 +239,7 @@
29195         buffer *key; /* like .php */
29196  
29197         scgi_extension_host **hosts;
29198 -       
29199 +
29200         size_t used;
29201         size_t size;
29202  } scgi_extension;
29203 @@ -253,14 +253,14 @@
29204  
29205  
29206  typedef struct {
29207 -       scgi_exts *exts; 
29208 -       
29209 +       scgi_exts *exts;
29210 +
29211         int debug;
29212  } plugin_config;
29213  
29214  typedef struct {
29215         char **ptr;
29216 -       
29217 +
29218         size_t size;
29219         size_t used;
29220  } char_array;
29221 @@ -268,52 +268,51 @@
29222  /* generic plugin data, shared between all connections */
29223  typedef struct {
29224         PLUGIN_DATA;
29225 -       
29226 +
29227         buffer *scgi_env;
29228 -       
29229 +
29230         buffer *path;
29231         buffer *parse_response;
29232 -       
29233 +
29234         plugin_config **config_storage;
29235 -       
29236 +
29237         plugin_config conf; /* this is only used as long as no handler_ctx is setup */
29238  } plugin_data;
29239  
29240  /* connection specific data */
29241 -typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE, 
29242 -               FCGI_STATE_WRITE, FCGI_STATE_READ 
29243 +typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE,
29244 +               FCGI_STATE_WRITE, FCGI_STATE_READ
29245  } scgi_connection_state_t;
29246  
29247  typedef struct {
29248 -       buffer  *response; 
29249 +       buffer  *response;
29250         size_t   response_len;
29251         int      response_type;
29252         int      response_padding;
29253 -       
29254 +
29255         scgi_proc *proc;
29256         scgi_extension_host *host;
29257 -       
29258 +
29259         scgi_connection_state_t state;
29260         time_t   state_timestamp;
29261 -       
29262 +
29263         int      reconnects; /* number of reconnect attempts */
29264 -       
29265 +
29266         read_buffer *rb;
29267         chunkqueue *wb;
29268 -       
29269 +
29270         buffer   *response_header;
29271 -       
29272 +
29273         int       delayed;   /* flag to mark that the connect() is delayed */
29274 -       
29275 +
29276         size_t    request_id;
29277         int       fd;        /* fd to the scgi process */
29278         int       fde_ndx;   /* index into the fd-event buffer */
29279 -
29280         pid_t     pid;
29281         int       got_proc;
29282 -       
29283 +
29284         plugin_config conf;
29285 -       
29286 +
29287         connection *remote_conn;  /* dumb pointer */
29288         plugin_data *plugin_data; /* dumb pointer */
29289  } handler_ctx;
29290 @@ -328,28 +327,28 @@
29291  
29292  static handler_ctx * handler_ctx_init() {
29293         handler_ctx * hctx;
29294 -       
29295 +
29296         hctx = calloc(1, sizeof(*hctx));
29297         assert(hctx);
29298 -       
29299 +
29300         hctx->fde_ndx = -1;
29301 -       
29302 +
29303         hctx->response = buffer_init();
29304         hctx->response_header = buffer_init();
29305 -       
29306 +
29307         hctx->request_id = 0;
29308         hctx->state = FCGI_STATE_INIT;
29309         hctx->proc = NULL;
29310 -       
29311 +
29312         hctx->response_len = 0;
29313         hctx->response_type = 0;
29314         hctx->response_padding = 0;
29315         hctx->fd = -1;
29316 -       
29317 +
29318         hctx->reconnects = 0;
29319  
29320         hctx->wb = chunkqueue_init();
29321 -       
29322 +
29323         return hctx;
29324  }
29325  
29326 @@ -358,12 +357,12 @@
29327         buffer_free(hctx->response_header);
29328  
29329         chunkqueue_free(hctx->wb);
29330 -       
29331 +
29332         if (hctx->rb) {
29333                 if (hctx->rb->ptr) free(hctx->rb->ptr);
29334                 free(hctx->rb);
29335         }
29336 -       
29337 +
29338         free(hctx);
29339  }
29340  
29341 @@ -372,20 +371,20 @@
29342  
29343         f = calloc(1, sizeof(*f));
29344         f->socket = buffer_init();
29345 -       
29346 +
29347         f->prev = NULL;
29348         f->next = NULL;
29349 -       
29350 +
29351         return f;
29352  }
29353  
29354  void scgi_process_free(scgi_proc *f) {
29355         if (!f) return;
29356 -       
29357 +
29358         scgi_process_free(f->next);
29359 -       
29360 +
29361         buffer_free(f->socket);
29362 -       
29363 +
29364         free(f);
29365  }
29366  
29367 @@ -400,62 +399,62 @@
29368         f->bin_path = buffer_init();
29369         f->bin_env = array_init();
29370         f->bin_env_copy = array_init();
29371 -       
29372 +
29373         return f;
29374  }
29375  
29376  void scgi_host_free(scgi_extension_host *h) {
29377         if (!h) return;
29378 -       
29379 +
29380         buffer_free(h->host);
29381         buffer_free(h->unixsocket);
29382         buffer_free(h->docroot);
29383         buffer_free(h->bin_path);
29384         array_free(h->bin_env);
29385         array_free(h->bin_env_copy);
29386 -       
29387 +
29388         scgi_process_free(h->first);
29389         scgi_process_free(h->unused_procs);
29390 -       
29391 +
29392         free(h);
29393 -       
29394 +
29395  }
29396  
29397  scgi_exts *scgi_extensions_init() {
29398         scgi_exts *f;
29399  
29400         f = calloc(1, sizeof(*f));
29401 -       
29402 +
29403         return f;
29404  }
29405  
29406  void scgi_extensions_free(scgi_exts *f) {
29407         size_t i;
29408 -       
29409 +
29410         if (!f) return;
29411 -       
29412 +
29413         for (i = 0; i < f->used; i++) {
29414                 scgi_extension *fe;
29415                 size_t j;
29416 -               
29417 +
29418                 fe = f->exts[i];
29419 -               
29420 +
29421                 for (j = 0; j < fe->used; j++) {
29422                         scgi_extension_host *h;
29423 -                       
29424 +
29425                         h = fe->hosts[j];
29426 -                       
29427 +
29428                         scgi_host_free(h);
29429                 }
29430 -               
29431 +
29432                 buffer_free(fe->key);
29433                 free(fe->hosts);
29434 -               
29435 +
29436                 free(fe);
29437         }
29438 -       
29439 +
29440         free(f->exts);
29441 -       
29442 +
29443         free(f);
29444  }
29445  
29446 @@ -504,99 +503,103 @@
29447                 assert(fe->hosts);
29448         }
29449  
29450 -       fe->hosts[fe->used++] = fh; 
29451 +       fe->hosts[fe->used++] = fh;
29452  
29453         return 0;
29454 -       
29455 +
29456  }
29457  
29458  INIT_FUNC(mod_scgi_init) {
29459         plugin_data *p;
29460 -       
29461 +
29462         p = calloc(1, sizeof(*p));
29463 -       
29464 +
29465         p->scgi_env = buffer_init();
29466 -       
29467 +
29468         p->path = buffer_init();
29469         p->parse_response = buffer_init();
29470 -       
29471 +
29472         return p;
29473  }
29474  
29475  
29476  FREE_FUNC(mod_scgi_free) {
29477         plugin_data *p = p_d;
29478 -       
29479 +
29480         UNUSED(srv);
29481  
29482         buffer_free(p->scgi_env);
29483         buffer_free(p->path);
29484         buffer_free(p->parse_response);
29485 -       
29486 +
29487         if (p->config_storage) {
29488                 size_t i, j, n;
29489                 for (i = 0; i < srv->config_context->used; i++) {
29490                         plugin_config *s = p->config_storage[i];
29491                         scgi_exts *exts;
29492 -                       
29493 +
29494                         if (!s) continue;
29495 -                       
29496 +
29497                         exts = s->exts;
29498  
29499                         for (j = 0; j < exts->used; j++) {
29500                                 scgi_extension *ex;
29501 -                               
29502 +
29503                                 ex = exts->exts[j];
29504 -                               
29505 +
29506                                 for (n = 0; n < ex->used; n++) {
29507                                         scgi_proc *proc;
29508                                         scgi_extension_host *host;
29509 -                                       
29510 +
29511                                         host = ex->hosts[n];
29512 -                                       
29513 +
29514                                         for (proc = host->first; proc; proc = proc->next) {
29515 +#ifndef _WIN32
29516                                                 if (proc->pid != 0) kill(proc->pid, SIGTERM);
29517 -                                               
29518 -                                               if (proc->is_local && 
29519 +#endif
29520 +
29521 +                                               if (proc->is_local &&
29522                                                     !buffer_is_empty(proc->socket)) {
29523                                                         unlink(proc->socket->ptr);
29524                                                 }
29525                                         }
29526 -                                       
29527 +
29528                                         for (proc = host->unused_procs; proc; proc = proc->next) {
29529 +#ifndef _WIN32
29530                                                 if (proc->pid != 0) kill(proc->pid, SIGTERM);
29531 -                                               
29532 -                                               if (proc->is_local && 
29533 +#endif
29534 +
29535 +                                               if (proc->is_local &&
29536                                                     !buffer_is_empty(proc->socket)) {
29537                                                         unlink(proc->socket->ptr);
29538                                                 }
29539                                         }
29540                                 }
29541                         }
29542 -                       
29543 +
29544                         scgi_extensions_free(s->exts);
29545 -                       
29546 +
29547                         free(s);
29548                 }
29549                 free(p->config_storage);
29550         }
29551 -       
29552 +
29553         free(p);
29554 -       
29555 +
29556         return HANDLER_GO_ON;
29557  }
29558  
29559  static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
29560         char *dst;
29561 -       
29562 +
29563         if (!key || !val) return -1;
29564 -       
29565 +
29566         dst = malloc(key_len + val_len + 3);
29567         memcpy(dst, key, key_len);
29568         dst[key_len] = '=';
29569         /* add the \0 from the value */
29570         memcpy(dst + key_len + 1, val, val_len + 1);
29571 -       
29572 +
29573         if (env->size == 0) {
29574                 env->size = 16;
29575                 env->ptr = malloc(env->size * sizeof(*env->ptr));
29576 @@ -604,13 +607,13 @@
29577                 env->size += 16;
29578                 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
29579         }
29580 -       
29581 +
29582         env->ptr[env->used++] = dst;
29583 -       
29584 +
29585         return 0;
29586  }
29587  
29588 -static int scgi_spawn_connection(server *srv, 
29589 +static int scgi_spawn_connection(server *srv,
29590                                  plugin_data *p,
29591                                  scgi_extension_host *host,
29592                                  scgi_proc *proc) {
29593 @@ -622,31 +625,27 @@
29594  #endif
29595         struct sockaddr_in scgi_addr_in;
29596         struct sockaddr *scgi_addr;
29597 -       
29598 +
29599         socklen_t servlen;
29600 -       
29601 +
29602  #ifndef HAVE_FORK
29603         return -1;
29604  #endif
29605 -       
29606 +
29607         if (p->conf.debug) {
29608                 log_error_write(srv, __FILE__, __LINE__, "sdb",
29609                                 "new proc, socket:", proc->port, proc->socket);
29610         }
29611 -               
29612 +
29613         if (!buffer_is_empty(proc->socket)) {
29614                 memset(&scgi_addr, 0, sizeof(scgi_addr));
29615 -               
29616 +
29617  #ifdef HAVE_SYS_UN_H
29618                 scgi_addr_un.sun_family = AF_UNIX;
29619                 strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
29620 -               
29621 -#ifdef SUN_LEN
29622 +
29623                 servlen = SUN_LEN(&scgi_addr_un);
29624 -#else
29625 -               /* stevens says: */
29626 -               servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
29627 -#endif
29628 +
29629                 socket_type = AF_UNIX;
29630                 scgi_addr = (struct sockaddr *) &scgi_addr_un;
29631  #else
29632 @@ -656,115 +655,115 @@
29633  #endif
29634         } else {
29635                 scgi_addr_in.sin_family = AF_INET;
29636 -               
29637 +
29638                 if (buffer_is_empty(host->host)) {
29639                         scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
29640                 } else {
29641                         struct hostent *he;
29642 -                       
29643 +
29644                         /* set a usefull default */
29645                         scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
29646 -                       
29647 -                       
29648 +
29649 +
29650                         if (NULL == (he = gethostbyname(host->host->ptr))) {
29651 -                               log_error_write(srv, __FILE__, __LINE__, 
29652 -                                               "sdb", "gethostbyname failed: ", 
29653 +                               log_error_write(srv, __FILE__, __LINE__,
29654 +                                               "sdb", "gethostbyname failed: ",
29655                                                 h_errno, host->host);
29656                                 return -1;
29657                         }
29658 -                       
29659 +
29660                         if (he->h_addrtype != AF_INET) {
29661                                 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
29662                                 return -1;
29663                         }
29664 -                       
29665 +
29666                         if (he->h_length != sizeof(struct in_addr)) {
29667                                 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
29668                                 return -1;
29669                         }
29670 -                       
29671 +
29672                         memcpy(&(scgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
29673 -                       
29674 +
29675                 }
29676                 scgi_addr_in.sin_port = htons(proc->port);
29677                 servlen = sizeof(scgi_addr_in);
29678 -               
29679 +
29680                 socket_type = AF_INET;
29681                 scgi_addr = (struct sockaddr *) &scgi_addr_in;
29682         }
29683 -       
29684 +
29685         if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
29686 -               log_error_write(srv, __FILE__, __LINE__, "ss", 
29687 +               log_error_write(srv, __FILE__, __LINE__, "ss",
29688                                 "failed:", strerror(errno));
29689                 return -1;
29690         }
29691 -       
29692 +
29693         if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
29694                 /* server is not up, spawn in  */
29695                 pid_t child;
29696                 int val;
29697 -               
29698 +
29699                 if (!buffer_is_empty(proc->socket)) {
29700                         unlink(proc->socket->ptr);
29701                 }
29702 -               
29703 +
29704                 close(scgi_fd);
29705 -               
29706 +
29707                 /* reopen socket */
29708                 if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
29709 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
29710 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
29711                                 "socket failed:", strerror(errno));
29712                         return -1;
29713                 }
29714 -               
29715 +
29716                 val = 1;
29717                 if (setsockopt(scgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
29718 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
29719 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
29720                                         "socketsockopt failed:", strerror(errno));
29721                         return -1;
29722                 }
29723 -               
29724 +
29725                 /* create socket */
29726                 if (-1 == bind(scgi_fd, scgi_addr, servlen)) {
29727 -                       log_error_write(srv, __FILE__, __LINE__, "sbds", 
29728 -                               "bind failed for:", 
29729 -                               proc->socket, 
29730 -                               proc->port, 
29731 +                       log_error_write(srv, __FILE__, __LINE__, "sbds",
29732 +                               "bind failed for:",
29733 +                               proc->socket,
29734 +                               proc->port,
29735                                 strerror(errno));
29736                         return -1;
29737                 }
29738 -               
29739 +
29740                 if (-1 == listen(scgi_fd, 1024)) {
29741 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
29742 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
29743                                 "listen failed:", strerror(errno));
29744                         return -1;
29745                 }
29746 -               
29747 -#ifdef HAVE_FORK       
29748 +
29749 +#ifdef HAVE_FORK
29750                 switch ((child = fork())) {
29751                 case 0: {
29752                         buffer *b;
29753                         size_t i = 0;
29754                         int fd = 0;
29755                         char_array env;
29756 -                       
29757 -                       
29758 +
29759 +
29760                         /* create environment */
29761                         env.ptr = NULL;
29762                         env.size = 0;
29763                         env.used = 0;
29764 -                       
29765 +
29766                         /* we don't need the client socket */
29767                         for (fd = 3; fd < 256; fd++) {
29768                                 if (fd != 2 && fd != scgi_fd) close(fd);
29769                         }
29770 -                       
29771 +
29772                         /* build clean environment */
29773                         if (host->bin_env_copy->used) {
29774                                 for (i = 0; i < host->bin_env_copy->used; i++) {
29775                                         data_string *ds = (data_string *)host->bin_env_copy->data[i];
29776                                         char *ge;
29777 -                                       
29778 +
29779                                         if (NULL != (ge = getenv(ds->value->ptr))) {
29780                                                 env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
29781                                         }
29782 @@ -772,44 +771,44 @@
29783                         } else {
29784                                 for (i = 0; environ[i]; i++) {
29785                                         char *eq;
29786 -                                       
29787 +
29788                                         if (NULL != (eq = strchr(environ[i], '='))) {
29789                                                 env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
29790                                         }
29791                                 }
29792                         }
29793 -                       
29794 +
29795                         /* create environment */
29796                         for (i = 0; i < host->bin_env->used; i++) {
29797                                 data_string *ds = (data_string *)host->bin_env->data[i];
29798 -                               
29799 +
29800                                 env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
29801                         }
29802 -                       
29803 +
29804                         for (i = 0; i < env.used; i++) {
29805                                 /* search for PHP_FCGI_CHILDREN */
29806                                 if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
29807                         }
29808 -                       
29809 +
29810                         /* not found, add a default */
29811                         if (i == env.used) {
29812                                 env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
29813                         }
29814 -                       
29815 +
29816                         env.ptr[env.used] = NULL;
29817 -                       
29818 +
29819                         b = buffer_init();
29820                         buffer_copy_string(b, "exec ");
29821                         buffer_append_string_buffer(b, host->bin_path);
29822 -                       
29823 +
29824                         /* exec the cgi */
29825                         execle("/bin/sh", "sh", "-c", b->ptr, NULL, env.ptr);
29826 -                       
29827 -                       log_error_write(srv, __FILE__, __LINE__, "sbs", 
29828 +
29829 +                       log_error_write(srv, __FILE__, __LINE__, "sbs",
29830                                         "execl failed for:", host->bin_path, strerror(errno));
29831 -                       
29832 +
29833                         exit(errno);
29834 -                       
29835 +
29836                         break;
29837                 }
29838                 case -1:
29839 @@ -817,32 +816,32 @@
29840                         break;
29841                 default:
29842                         /* father */
29843 -                       
29844 +
29845                         /* wait */
29846                         select(0, NULL, NULL, NULL, &tv);
29847 -                       
29848 +
29849                         switch (waitpid(child, &status, WNOHANG)) {
29850                         case 0:
29851                                 /* child still running after timeout, good */
29852                                 break;
29853                         case -1:
29854                                 /* no PID found ? should never happen */
29855 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
29856 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
29857                                                 "pid not found:", strerror(errno));
29858                                 return -1;
29859                         default:
29860                                 /* the child should not terminate at all */
29861                                 if (WIFEXITED(status)) {
29862 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
29863 -                                                       "child exited (is this a SCGI binary ?):", 
29864 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
29865 +                                                       "child exited (is this a SCGI binary ?):",
29866                                                         WEXITSTATUS(status));
29867                                 } else if (WIFSIGNALED(status)) {
29868 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
29869 -                                                       "child signaled:", 
29870 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
29871 +                                                       "child signaled:",
29872                                                         WTERMSIG(status));
29873                                 } else {
29874 -                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
29875 -                                                       "child died somehow:", 
29876 +                                       log_error_write(srv, __FILE__, __LINE__, "sd",
29877 +                                                       "child died somehow:",
29878                                                         status);
29879                                 }
29880                                 return -1;
29881 @@ -852,26 +851,26 @@
29882                         proc->pid = child;
29883                         proc->last_used = srv->cur_ts;
29884                         proc->is_local = 1;
29885 -                                               
29886 +
29887                         break;
29888                 }
29889  #endif
29890         } else {
29891                 proc->is_local = 0;
29892                 proc->pid = 0;
29893 -               
29894 +
29895                 if (p->conf.debug) {
29896                         log_error_write(srv, __FILE__, __LINE__, "sb",
29897                                         "(debug) socket is already used, won't spawn:",
29898                                         proc->socket);
29899                 }
29900         }
29901 -       
29902 +
29903         proc->state = PROC_STATE_RUNNING;
29904         host->active_procs++;
29905 -       
29906 +
29907         close(scgi_fd);
29908 -       
29909 +
29910         return 0;
29911  }
29912  
29913 @@ -880,89 +879,89 @@
29914         plugin_data *p = p_d;
29915         data_unset *du;
29916         size_t i = 0;
29917 -       
29918 -       config_values_t cv[] = { 
29919 +
29920 +       config_values_t cv[] = {
29921                 { "scgi.server",              NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
29922                 { "scgi.debug",               NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
29923                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
29924         };
29925 -       
29926 +
29927         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
29928 -       
29929 +
29930         for (i = 0; i < srv->config_context->used; i++) {
29931                 plugin_config *s;
29932                 array *ca;
29933 -               
29934 +
29935                 s = malloc(sizeof(plugin_config));
29936                 s->exts          = scgi_extensions_init();
29937                 s->debug         = 0;
29938 -               
29939 +
29940                 cv[0].destination = s->exts;
29941                 cv[1].destination = &(s->debug);
29942 -               
29943 +
29944                 p->config_storage[i] = s;
29945                 ca = ((data_config *)srv->config_context->data[i])->value;
29946 -       
29947 +
29948                 if (0 != config_insert_values_global(srv, ca, cv)) {
29949                         return HANDLER_ERROR;
29950                 }
29951 -               
29952 -               /* 
29953 +
29954 +               /*
29955                  * <key> = ( ... )
29956                  */
29957 -               
29958 +
29959                 if (NULL != (du = array_get_element(ca, "scgi.server"))) {
29960                         size_t j;
29961                         data_array *da = (data_array *)du;
29962 -                       
29963 +
29964                         if (du->type != TYPE_ARRAY) {
29965 -                               log_error_write(srv, __FILE__, __LINE__, "sss", 
29966 +                               log_error_write(srv, __FILE__, __LINE__, "sss",
29967                                                 "unexpected type for key: ", "scgi.server", "array of strings");
29968 -                               
29969 +
29970                                 return HANDLER_ERROR;
29971                         }
29972 -                       
29973 -                       
29974 -                       /* 
29975 -                        * scgi.server = ( "<ext>" => ( ... ), 
29976 +
29977 +
29978 +                       /*
29979 +                        * scgi.server = ( "<ext>" => ( ... ),
29980                          *                    "<ext>" => ( ... ) )
29981                          */
29982 -                       
29983 +
29984                         for (j = 0; j < da->value->used; j++) {
29985                                 size_t n;
29986                                 data_array *da_ext = (data_array *)da->value->data[j];
29987 -                               
29988 +
29989                                 if (da->value->data[j]->type != TYPE_ARRAY) {
29990 -                                       log_error_write(srv, __FILE__, __LINE__, "sssbs", 
29991 -                                                       "unexpected type for key: ", "scgi.server", 
29992 +                                       log_error_write(srv, __FILE__, __LINE__, "sssbs",
29993 +                                                       "unexpected type for key: ", "scgi.server",
29994                                                         "[", da->value->data[j]->key, "](string)");
29995 -                                       
29996 +
29997                                         return HANDLER_ERROR;
29998                                 }
29999 -                               
30000 -                               /* 
30001 -                                * da_ext->key == name of the extension 
30002 +
30003 +                               /*
30004 +                                * da_ext->key == name of the extension
30005                                  */
30006 -                               
30007 -                               /* 
30008 -                                * scgi.server = ( "<ext>" => 
30009 -                                *                     ( "<host>" => ( ... ), 
30010 +
30011 +                               /*
30012 +                                * scgi.server = ( "<ext>" =>
30013 +                                *                     ( "<host>" => ( ... ),
30014                                  *                       "<host>" => ( ... )
30015 -                                *                     ), 
30016 +                                *                     ),
30017                                  *                    "<ext>" => ... )
30018                                  */
30019 -                                       
30020 +
30021                                 for (n = 0; n < da_ext->value->used; n++) {
30022                                         data_array *da_host = (data_array *)da_ext->value->data[n];
30023 -                                       
30024 +
30025                                         scgi_extension_host *df;
30026 -                                       
30027 -                                       config_values_t fcv[] = { 
30028 +
30029 +                                       config_values_t fcv[] = {
30030                                                 { "host",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
30031                                                 { "docroot",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
30032                                                 { "socket",            NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
30033                                                 { "bin-path",          NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 3 */
30034 -                                               
30035 +
30036                                                 { "check-local",       NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },      /* 4 */
30037                                                 { "port",              NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 5 */
30038                                                 { "min-procs-not-working",         NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 7 this is broken for now */
30039 @@ -970,37 +969,37 @@
30040                                                 { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 8 */
30041                                                 { "idle-timeout",      NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 9 */
30042                                                 { "disable-time",      NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 10 */
30043 -                                               
30044 +
30045                                                 { "bin-environment",   NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },        /* 11 */
30046                                                 { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },     /* 12 */
30047 -                                               
30048 -                                               
30049 +
30050 +
30051                                                 { NULL,                NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
30052                                         };
30053 -                                       
30054 +
30055                                         if (da_host->type != TYPE_ARRAY) {
30056 -                                               log_error_write(srv, __FILE__, __LINE__, "ssSBS", 
30057 -                                                               "unexpected type for key:", 
30058 -                                                               "scgi.server", 
30059 +                                               log_error_write(srv, __FILE__, __LINE__, "ssSBS",
30060 +                                                               "unexpected type for key:",
30061 +                                                               "scgi.server",
30062                                                                 "[", da_host->key, "](string)");
30063 -                                               
30064 +
30065                                                 return HANDLER_ERROR;
30066                                         }
30067 -                                       
30068 +
30069                                         df = scgi_host_init();
30070 -                                       
30071 +
30072                                         df->check_local  = 1;
30073                                         df->min_procs    = 4;
30074                                         df->max_procs    = 4;
30075                                         df->max_load_per_proc = 1;
30076                                         df->idle_timeout = 60;
30077                                         df->disable_time = 60;
30078 -                                       
30079 +
30080                                         fcv[0].destination = df->host;
30081                                         fcv[1].destination = df->docroot;
30082                                         fcv[2].destination = df->unixsocket;
30083                                         fcv[3].destination = df->bin_path;
30084 -                                       
30085 +
30086                                         fcv[4].destination = &(df->check_local);
30087                                         fcv[5].destination = &(df->port);
30088                                         fcv[6].destination = &(df->min_procs);
30089 @@ -1008,47 +1007,47 @@
30090                                         fcv[8].destination = &(df->max_load_per_proc);
30091                                         fcv[9].destination = &(df->idle_timeout);
30092                                         fcv[10].destination = &(df->disable_time);
30093 -                                       
30094 +
30095                                         fcv[11].destination = df->bin_env;
30096                                         fcv[12].destination = df->bin_env_copy;
30097 -                                       
30098 -                                       
30099 +
30100 +
30101                                         if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
30102                                                 return HANDLER_ERROR;
30103                                         }
30104 -                                                       
30105 -                                       if ((!buffer_is_empty(df->host) || df->port) && 
30106 +
30107 +                                       if ((!buffer_is_empty(df->host) || df->port) &&
30108                                             !buffer_is_empty(df->unixsocket)) {
30109 -                                               log_error_write(srv, __FILE__, __LINE__, "s", 
30110 +                                               log_error_write(srv, __FILE__, __LINE__, "s",
30111                                                                 "either host+port or socket");
30112 -                                               
30113 +
30114                                                 return HANDLER_ERROR;
30115                                         }
30116 -                                       
30117 +
30118                                         if (!buffer_is_empty(df->unixsocket)) {
30119                                                 /* unix domain socket */
30120 -                                               
30121 +
30122                                                 if (df->unixsocket->used > UNIX_PATH_MAX - 2) {
30123 -                                                       log_error_write(srv, __FILE__, __LINE__, "s", 
30124 +                                                       log_error_write(srv, __FILE__, __LINE__, "s",
30125                                                                         "path of the unixdomain socket is too large");
30126                                                         return HANDLER_ERROR;
30127                                                 }
30128                                         } else {
30129                                                 /* tcp/ip */
30130 -                                               
30131 -                                               if (buffer_is_empty(df->host) && 
30132 +
30133 +                                               if (buffer_is_empty(df->host) &&
30134                                                     buffer_is_empty(df->bin_path)) {
30135 -                                                       log_error_write(srv, __FILE__, __LINE__, "sbbbs", 
30136 -                                                                       "missing key (string):", 
30137 +                                                       log_error_write(srv, __FILE__, __LINE__, "sbbbs",
30138 +                                                                       "missing key (string):",
30139                                                                         da->key,
30140                                                                         da_ext->key,
30141                                                                         da_host->key,
30142                                                                         "host");
30143 -                                                       
30144 +
30145                                                         return HANDLER_ERROR;
30146                                                 } else if (df->port == 0) {
30147 -                                                       log_error_write(srv, __FILE__, __LINE__, "sbbbs", 
30148 -                                                                       "missing key (short):", 
30149 +                                                       log_error_write(srv, __FILE__, __LINE__, "sbbbs",
30150 +                                                                       "missing key (short):",
30151                                                                         da->key,
30152                                                                         da_ext->key,
30153                                                                         da_host->key,
30154 @@ -1056,14 +1055,14 @@
30155                                                         return HANDLER_ERROR;
30156                                                 }
30157                                         }
30158 -                                               
30159 -                                       if (!buffer_is_empty(df->bin_path)) { 
30160 +
30161 +                                       if (!buffer_is_empty(df->bin_path)) {
30162                                                 /* a local socket + self spawning */
30163                                                 size_t pno;
30164 -                                               
30165 +
30166                                                 if (df->min_procs > df->max_procs) df->max_procs = df->min_procs;
30167                                                 if (df->max_load_per_proc < 1) df->max_load_per_proc = 0;
30168 -                                               
30169 +
30170                                                 if (s->debug) {
30171                                                         log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd",
30172                                                                         "--- scgi spawning local",
30173 @@ -1073,7 +1072,7 @@
30174                                                                         "\n\tmin-procs:", df->min_procs,
30175                                                                         "\n\tmax-procs:", df->max_procs);
30176                                                 }
30177 -                                               
30178 +
30179                                                 for (pno = 0; pno < df->min_procs; pno++) {
30180                                                         scgi_proc *proc;
30181  
30182 @@ -1088,7 +1087,7 @@
30183                                                                 buffer_append_string(proc->socket, "-");
30184                                                                 buffer_append_long(proc->socket, pno);
30185                                                         }
30186 -                                                       
30187 +
30188                                                         if (s->debug) {
30189                                                                 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
30190                                                                                 "--- scgi spawning",
30191 @@ -1096,53 +1095,53 @@
30192                                                                                 "\n\tsocket", df->unixsocket,
30193                                                                                 "\n\tcurrent:", pno, "/", df->min_procs);
30194                                                         }
30195 -                                                       
30196 +
30197                                                         if (scgi_spawn_connection(srv, p, df, proc)) {
30198                                                                 log_error_write(srv, __FILE__, __LINE__, "s",
30199                                                                                 "[ERROR]: spawning fcgi failed.");
30200                                                                 return HANDLER_ERROR;
30201                                                         }
30202 -                                                       
30203 +
30204                                                         proc->next = df->first;
30205                                                         if (df->first)  df->first->prev = proc;
30206 -                                                       
30207 +
30208                                                         df->first = proc;
30209                                                 }
30210                                         } else {
30211                                                 scgi_proc *fp;
30212 -                                               
30213 +
30214                                                 fp = scgi_process_init();
30215                                                 fp->id = df->num_procs++;
30216                                                 df->max_id++;
30217                                                 df->active_procs++;
30218                                                 fp->state = PROC_STATE_RUNNING;
30219 -                                               
30220 +
30221                                                 if (buffer_is_empty(df->unixsocket)) {
30222                                                         fp->port = df->port;
30223                                                 } else {
30224                                                         buffer_copy_string_buffer(fp->socket, df->unixsocket);
30225                                                 }
30226 -                                               
30227 +
30228                                                 df->first = fp;
30229 -                                               
30230 +
30231                                                 df->min_procs = 1;
30232                                                 df->max_procs = 1;
30233                                         }
30234 -                                       
30235 +
30236                                         /* if extension already exists, take it */
30237                                         scgi_extension_insert(s->exts, da_ext->key, df);
30238                                 }
30239                         }
30240                 }
30241         }
30242 -       
30243 +
30244         return HANDLER_GO_ON;
30245  }
30246  
30247  static int scgi_set_state(server *srv, handler_ctx *hctx, scgi_connection_state_t state) {
30248         hctx->state = state;
30249         hctx->state_timestamp = srv->cur_ts;
30250 -       
30251 +
30252         return 0;
30253  }
30254  
30255 @@ -1150,34 +1149,34 @@
30256  void scgi_connection_cleanup(server *srv, handler_ctx *hctx) {
30257         plugin_data *p;
30258         connection  *con;
30259 -       
30260 +
30261         if (NULL == hctx) return;
30262 -       
30263 +
30264         p    = hctx->plugin_data;
30265         con  = hctx->remote_conn;
30266 -       
30267 +
30268         if (con->mode != p->id) {
30269                 WP();
30270                 return;
30271         }
30272 -       
30273 +
30274         if (hctx->fd != -1) {
30275                 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
30276                 fdevent_unregister(srv->ev, hctx->fd);
30277                 close(hctx->fd);
30278                 srv->cur_fds--;
30279         }
30280 -       
30281 +
30282         if (hctx->host && hctx->proc) {
30283                 hctx->host->load--;
30284 -               
30285 +
30286                 if (hctx->got_proc) {
30287                         /* after the connect the process gets a load */
30288                         hctx->proc->load--;
30289 -                       
30290 +
30291                         if (p->conf.debug) {
30292                                 log_error_write(srv, __FILE__, __LINE__, "sddb",
30293 -                                               "release proc:", 
30294 +                                               "release proc:",
30295                                                 hctx->fd,
30296                                                 hctx->proc->pid, hctx->proc->socket);
30297                         }
30298 @@ -1186,87 +1185,87 @@
30299                 scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
30300         }
30301  
30302 -       
30303 +
30304         handler_ctx_free(hctx);
30305 -       con->plugin_ctx[p->id] = NULL;  
30306 +       con->plugin_ctx[p->id] = NULL;
30307  }
30308  
30309  static int scgi_reconnect(server *srv, handler_ctx *hctx) {
30310         plugin_data *p    = hctx->plugin_data;
30311 -       
30312 -       /* child died 
30313 -        * 
30314 -        * 1. 
30315 -        * 
30316 +
30317 +       /* child died
30318 +        *
30319 +        * 1.
30320 +        *
30321          * connect was ok, connection was accepted
30322          * but the php accept loop checks after the accept if it should die or not.
30323 -        * 
30324 -        * if yes we can only detect it at a write() 
30325 -        * 
30326 +        *
30327 +        * if yes we can only detect it at a write()
30328 +        *
30329          * next step is resetting this attemp and setup a connection again
30330 -        * 
30331 +        *
30332          * if we have more then 5 reconnects for the same request, die
30333 -        * 
30334 -        * 2. 
30335 -        * 
30336 +        *
30337 +        * 2.
30338 +        *
30339          * we have a connection but the child died by some other reason
30340 -        * 
30341 +        *
30342          */
30343 -       
30344 +
30345         fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
30346         fdevent_unregister(srv->ev, hctx->fd);
30347         close(hctx->fd);
30348         srv->cur_fds--;
30349 -       
30350 +
30351         scgi_set_state(srv, hctx, FCGI_STATE_INIT);
30352 -       
30353 +
30354         hctx->request_id = 0;
30355         hctx->reconnects++;
30356 -       
30357 +
30358         if (p->conf.debug) {
30359                 log_error_write(srv, __FILE__, __LINE__, "sddb",
30360 -                               "release proc:", 
30361 +                               "release proc:",
30362                                 hctx->fd,
30363                                 hctx->proc->pid, hctx->proc->socket);
30364         }
30365 -       
30366 +
30367         hctx->proc->load--;
30368         scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
30369 -       
30370 +
30371         return 0;
30372  }
30373  
30374  
30375  static handler_t scgi_connection_reset(server *srv, connection *con, void *p_d) {
30376         plugin_data *p = p_d;
30377 -       
30378 +
30379         scgi_connection_cleanup(srv, con->plugin_ctx[p->id]);
30380 -       
30381 +
30382         return HANDLER_GO_ON;
30383  }
30384  
30385  
30386  static int scgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
30387         size_t len;
30388 -       
30389 +
30390         if (!key || !val) return -1;
30391 -       
30392 +
30393         len = key_len + val_len + 2;
30394 -       
30395 +
30396         buffer_prepare_append(env, len);
30397  
30398 -       /* include the NUL */   
30399 +       /* include the NUL */
30400         memcpy(env->ptr + env->used, key, key_len + 1);
30401         env->used += key_len + 1;
30402         memcpy(env->ptr + env->used, val, val_len + 1);
30403         env->used += val_len + 1;
30404 -       
30405 +
30406         return 0;
30407  }
30408  
30409  
30410  /**
30411 - * 
30412 + *
30413   * returns
30414   *   -1 error
30415   *    0 connected
30416 @@ -1280,24 +1279,21 @@
30417         struct sockaddr_un scgi_addr_un;
30418  #endif
30419         socklen_t servlen;
30420 -       
30421 +
30422         scgi_extension_host *host = hctx->host;
30423         scgi_proc *proc   = hctx->proc;
30424         int scgi_fd       = hctx->fd;
30425 -       
30426 +
30427         memset(&scgi_addr, 0, sizeof(scgi_addr));
30428 -       
30429 +
30430         if (!buffer_is_empty(proc->socket)) {
30431  #ifdef HAVE_SYS_UN_H
30432                 /* use the unix domain socket */
30433                 scgi_addr_un.sun_family = AF_UNIX;
30434                 strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
30435 -#ifdef SUN_LEN
30436 +               
30437                 servlen = SUN_LEN(&scgi_addr_un);
30438 -#else
30439 -               /* stevens says: */
30440 -               servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
30441 -#endif
30442 +
30443                 scgi_addr = (struct sockaddr *) &scgi_addr_un;
30444  #else
30445                 return -1;
30446 @@ -1305,105 +1301,105 @@
30447         } else {
30448                 scgi_addr_in.sin_family = AF_INET;
30449                 if (0 == inet_aton(host->host->ptr, &(scgi_addr_in.sin_addr))) {
30450 -                       log_error_write(srv, __FILE__, __LINE__, "sbs", 
30451 -                                       "converting IP-adress failed for", host->host, 
30452 +                       log_error_write(srv, __FILE__, __LINE__, "sbs",
30453 +                                       "converting IP-adress failed for", host->host,
30454                                         "\nBe sure to specify an IP address here");
30455 -                       
30456 +
30457                         return -1;
30458                 }
30459                 scgi_addr_in.sin_port = htons(proc->port);
30460                 servlen = sizeof(scgi_addr_in);
30461 -               
30462 +
30463                 scgi_addr = (struct sockaddr *) &scgi_addr_in;
30464         }
30465 -       
30466 +
30467         if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
30468 -               if (errno == EINPROGRESS || 
30469 +               if (errno == EINPROGRESS ||
30470                     errno == EALREADY ||
30471                     errno == EINTR) {
30472                         if (hctx->conf.debug) {
30473 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
30474 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
30475                                                 "connect delayed, will continue later:", scgi_fd);
30476                         }
30477 -                       
30478 +
30479                         return 1;
30480                 } else {
30481 -                       log_error_write(srv, __FILE__, __LINE__, "sdsddb", 
30482 -                                       "connect failed:", scgi_fd, 
30483 +                       log_error_write(srv, __FILE__, __LINE__, "sdsddb",
30484 +                                       "connect failed:", scgi_fd,
30485                                         strerror(errno), errno,
30486                                         proc->port, proc->socket);
30487  
30488                         if (errno == EAGAIN) {
30489                                 /* this is Linux only */
30490 -                               
30491 -                               log_error_write(srv, __FILE__, __LINE__, "s", 
30492 +
30493 +                               log_error_write(srv, __FILE__, __LINE__, "s",
30494                                                 "If this happend on Linux: You have been run out of local ports. "
30495                                                 "Check the manual, section Performance how to handle this.");
30496 -                       } 
30497 -                       
30498 +                       }
30499 +
30500                         return -1;
30501                 }
30502         }
30503         if (hctx->conf.debug > 1) {
30504 -               log_error_write(srv, __FILE__, __LINE__, "sd", 
30505 +               log_error_write(srv, __FILE__, __LINE__, "sd",
30506                                 "connect succeeded: ", scgi_fd);
30507         }
30508  
30509  
30510 -       
30511 +
30512         return 0;
30513  }
30514  
30515  static int scgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
30516         size_t i;
30517 -       
30518 +
30519         for (i = 0; i < con->request.headers->used; i++) {
30520                 data_string *ds;
30521 -               
30522 +
30523                 ds = (data_string *)con->request.headers->data[i];
30524 -               
30525 +
30526                 if (ds->value->used && ds->key->used) {
30527                         size_t j;
30528                         buffer_reset(srv->tmp_buf);
30529 -                       
30530 +
30531                         if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
30532                                 BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
30533                                 srv->tmp_buf->used--;
30534                         }
30535 -                       
30536 +
30537                         buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
30538                         for (j = 0; j < ds->key->used - 1; j++) {
30539 -                               srv->tmp_buf->ptr[srv->tmp_buf->used++] = 
30540 -                                       light_isalpha(ds->key->ptr[j]) ? 
30541 +                               srv->tmp_buf->ptr[srv->tmp_buf->used++] =
30542 +                                       light_isalpha(ds->key->ptr[j]) ?
30543                                         ds->key->ptr[j] & ~32 : '_';
30544                         }
30545                         srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
30546 -                       
30547 +
30548                         scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
30549                 }
30550         }
30551 -       
30552 +
30553         for (i = 0; i < con->environment->used; i++) {
30554                 data_string *ds;
30555 -               
30556 +
30557                 ds = (data_string *)con->environment->data[i];
30558 -               
30559 +
30560                 if (ds->value->used && ds->key->used) {
30561                         size_t j;
30562                         buffer_reset(srv->tmp_buf);
30563 -                       
30564 +
30565                         buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
30566                         for (j = 0; j < ds->key->used - 1; j++) {
30567 -                               srv->tmp_buf->ptr[srv->tmp_buf->used++] = 
30568 -                                       isalpha((unsigned char)ds->key->ptr[j]) ? 
30569 +                               srv->tmp_buf->ptr[srv->tmp_buf->used++] =
30570 +                                       isalpha((unsigned char)ds->key->ptr[j]) ?
30571                                         toupper((unsigned char)ds->key->ptr[j]) : '_';
30572                         }
30573                         srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
30574 -                       
30575 +
30576                         scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
30577                 }
30578         }
30579 -       
30580 +
30581         return 0;
30582  }
30583  
30584 @@ -1415,20 +1411,20 @@
30585         char b2[INET6_ADDRSTRLEN + 1];
30586  #endif
30587         buffer *b;
30588 -       
30589 +
30590         plugin_data *p    = hctx->plugin_data;
30591         scgi_extension_host *host= hctx->host;
30592  
30593         connection *con   = hctx->remote_conn;
30594         server_socket *srv_sock = con->srv_socket;
30595 -       
30596 +
30597         sock_addr our_addr;
30598         socklen_t our_addr_len;
30599 -       
30600 +
30601         buffer_prepare_copy(p->scgi_env, 1024);
30602  
30603         /* CGI-SPEC 6.1.2, FastCGI spec 6.3 and SCGI spec */
30604 -               
30605 +
30606         /* request.content_length < SSIZE_MAX, see request.c */
30607         ltostr(buf, con->request.content_length);
30608         scgi_env_add(p->scgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
30609 @@ -1436,13 +1432,13 @@
30610  
30611  
30612         scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
30613 -       
30614 +
30615         if (con->server_name->used) {
30616                 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
30617         } else {
30618  #ifdef HAVE_IPV6
30619 -               s = inet_ntop(srv_sock->addr.plain.sa_family, 
30620 -                             srv_sock->addr.plain.sa_family == AF_INET6 ? 
30621 +               s = inet_ntop(srv_sock->addr.plain.sa_family,
30622 +                             srv_sock->addr.plain.sa_family == AF_INET6 ?
30623                               (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
30624                               (const void *) &(srv_sock->addr.ipv4.sin_addr),
30625                               b2, sizeof(b2)-1);
30626 @@ -1451,47 +1447,47 @@
30627  #endif
30628                 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
30629         }
30630 -       
30631 +
30632         scgi_env_add(p->scgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
30633 -       
30634 -       ltostr(buf, 
30635 +
30636 +       ltostr(buf,
30637  #ifdef HAVE_IPV6
30638                ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
30639  #else
30640                ntohs(srv_sock->addr.ipv4.sin_port)
30641  #endif
30642                );
30643 -       
30644 +
30645         scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
30646 -       
30647 +
30648         /* get the server-side of the connection to the client */
30649         our_addr_len = sizeof(our_addr);
30650 -       
30651 +
30652         if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
30653                 s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
30654         } else {
30655                 s = inet_ntop_cache_get_ip(srv, &(our_addr));
30656         }
30657         scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
30658 -       
30659 -       ltostr(buf, 
30660 +
30661 +       ltostr(buf,
30662  #ifdef HAVE_IPV6
30663                ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
30664  #else
30665                ntohs(con->dst_addr.ipv4.sin_port)
30666  #endif
30667                );
30668 -       
30669 +
30670         scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
30671 -       
30672 +
30673         s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
30674         scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
30675 -       
30676 +
30677         if (!buffer_is_empty(con->authed_user)) {
30678                 scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_USER"),
30679                              CONST_BUF_LEN(con->authed_user));
30680         }
30681 -       
30682 +
30683  
30684         /*
30685          * SCRIPT_NAME, PATH_INFO and PATH_TRANSLATED according to
30686 @@ -1500,12 +1496,12 @@
30687          */
30688  
30689         scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
30690 -               
30691 +
30692         if (!buffer_is_empty(con->request.pathinfo)) {
30693                 scgi_env_add(p->scgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
30694 -               
30695 +
30696                 /* PATH_TRANSLATED is only defined if PATH_INFO is set */
30697 -               
30698 +
30699                 if (!buffer_is_empty(host->docroot)) {
30700                         buffer_copy_string_buffer(p->path, host->docroot);
30701                 } else {
30702 @@ -1526,19 +1522,19 @@
30703          */
30704  
30705         if (!buffer_is_empty(host->docroot)) {
30706 -               /* 
30707 -                * rewrite SCRIPT_FILENAME 
30708 -                * 
30709 +               /*
30710 +                * rewrite SCRIPT_FILENAME
30711 +                *
30712                  */
30713 -               
30714 +
30715                 buffer_copy_string_buffer(p->path, host->docroot);
30716                 buffer_append_string_buffer(p->path, con->uri.path);
30717 -               
30718 +
30719                 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
30720                 scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
30721         } else {
30722                 buffer_copy_string_buffer(p->path, con->physical.path);
30723 -               
30724 +
30725                 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
30726                 scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
30727         }
30728 @@ -1551,30 +1547,30 @@
30729         } else {
30730                 scgi_env_add(p->scgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
30731         }
30732 -       
30733 +
30734         s = get_http_method_name(con->request.http_method);
30735         scgi_env_add(p->scgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
30736         scgi_env_add(p->scgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
30737         s = get_http_version_name(con->request.http_version);
30738         scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
30739 -       
30740 +
30741  #ifdef USE_OPENSSL
30742         if (srv_sock->is_ssl) {
30743                 scgi_env_add(p->scgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
30744         }
30745  #endif
30746 -       
30747 +
30748         scgi_env_add_request_headers(srv, con, p);
30749  
30750         b = chunkqueue_get_append_buffer(hctx->wb);
30751 -       
30752 +
30753         buffer_append_long(b, p->scgi_env->used);
30754         buffer_append_string_len(b, CONST_STR_LEN(":"));
30755         buffer_append_string_len(b, (const char *)p->scgi_env->ptr, p->scgi_env->used);
30756         buffer_append_string_len(b, CONST_STR_LEN(","));
30757  
30758         hctx->wb->bytes_in += b->used - 1;
30759 -       
30760 +
30761         if (con->request.content_length) {
30762                 chunkqueue *req_cq = con->request_content_queue;
30763                 chunk *req_c;
30764 @@ -1587,7 +1583,7 @@
30765  
30766                         /* we announce toWrite octects
30767                          * now take all the request_content chunk that we need to fill this request
30768 -                        * */   
30769 +                        * */
30770  
30771                         switch (req_c->type) {
30772                         case FILE_CHUNK:
30773 @@ -1615,32 +1611,32 @@
30774  
30775                                 req_c->offset += weHave;
30776                                 req_cq->bytes_out += weHave;
30777 -                               
30778 +
30779                                 hctx->wb->bytes_in += weHave;
30780  
30781                                 break;
30782                         default:
30783                                 break;
30784                         }
30785 -                       
30786 +
30787                         offset += weHave;
30788                 }
30789         }
30790 -       
30791 +
30792  #if 0
30793         for (i = 0; i < hctx->write_buffer->used; i++) {
30794                 fprintf(stderr, "%02x ", hctx->write_buffer->ptr[i]);
30795                 if ((i+1) % 16 == 0) {
30796                         size_t j;
30797                         for (j = i-15; j <= i; j++) {
30798 -                               fprintf(stderr, "%c", 
30799 +                               fprintf(stderr, "%c",
30800                                         isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.');
30801                         }
30802                         fprintf(stderr, "\n");
30803                 }
30804         }
30805  #endif
30806 -       
30807 +
30808         return 0;
30809  }
30810  
30811 @@ -1648,32 +1644,32 @@
30812         char *ns;
30813         const char *s;
30814         int line = 0;
30815 -       
30816 +
30817         UNUSED(srv);
30818 -       
30819 +
30820         buffer_copy_string_buffer(p->parse_response, in);
30821 -       
30822 -       for (s = p->parse_response->ptr; 
30823 -            NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n'))); 
30824 +
30825 +       for (s = p->parse_response->ptr;
30826 +            NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
30827              s = ns + (eol == EOL_RN ? 2 : 1), line++) {
30828                 const char *key, *value;
30829                 int key_len;
30830                 data_string *ds;
30831 -               
30832 +
30833                 ns[0] = '\0';
30834 -               
30835 -               if (line == 0 && 
30836 +
30837 +               if (line == 0 &&
30838                     0 == strncmp(s, "HTTP/1.", 7)) {
30839                         /* non-parsed header ... we parse them anyway */
30840 -                       
30841 +
30842                         if ((s[7] == '1' ||
30843                              s[7] == '0') &&
30844                             s[8] == ' ') {
30845                                 int status;
30846                                 /* after the space should be a status code for us */
30847 -                               
30848 +
30849                                 status = strtol(s+9, NULL, 10);
30850 -                               
30851 +
30852                                 if (con->http_status >= 100 &&
30853                                     con->http_status < 1000) {
30854                                         /* we expected 3 digits and didn't got them */
30855 @@ -1682,27 +1678,27 @@
30856                                 }
30857                         }
30858                 } else {
30859 -               
30860 +
30861                         key = s;
30862                         if (NULL == (value = strchr(s, ':'))) {
30863                                 /* we expect: "<key>: <value>\r\n" */
30864                                 continue;
30865                         }
30866 -                       
30867 +
30868                         key_len = value - key;
30869                         value += 1;
30870 -                       
30871 +
30872                         /* skip LWS */
30873                         while (*value == ' ' || *value == '\t') value++;
30874 -                       
30875 +
30876                         if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
30877                                 ds = data_response_init();
30878                         }
30879                         buffer_copy_string_len(ds->key, key, key_len);
30880                         buffer_copy_string(ds->value, value);
30881 -                       
30882 +
30883                         array_insert_unique(con->response.headers, (data_unset *)ds);
30884 -                       
30885 +
30886                         switch(key_len) {
30887                         case 4:
30888                                 if (0 == strncasecmp(key, "Date", key_len)) {
30889 @@ -1737,13 +1733,13 @@
30890                         }
30891                 }
30892         }
30893 -       
30894 +
30895         /* CGI/1.1 rev 03 - 7.2.1.2 */
30896         if ((con->parsed_response & HTTP_LOCATION) &&
30897             !(con->parsed_response & HTTP_STATUS)) {
30898                 con->http_status = 302;
30899         }
30900 -       
30901 +
30902         return 0;
30903  }
30904  
30905 @@ -1751,10 +1747,10 @@
30906  static int scgi_demux_response(server *srv, handler_ctx *hctx) {
30907         plugin_data *p    = hctx->plugin_data;
30908         connection  *con  = hctx->remote_conn;
30909 -       
30910 +
30911         while(1) {
30912                 int n;
30913 -               
30914 +
30915                 buffer_prepare_copy(hctx->response, 1024);
30916                 if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
30917                         if (errno == EAGAIN || errno == EINTR) {
30918 @@ -1765,143 +1761,143 @@
30919                         log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
30920                         return -1;
30921                 }
30922 -               
30923 +
30924                 if (n == 0) {
30925                         /* read finished */
30926 -                       
30927 +
30928                         con->file_finished = 1;
30929 -                       
30930 +
30931                         /* send final chunk */
30932                         http_chunk_append_mem(srv, con, NULL, 0);
30933                         joblist_append(srv, con);
30934 -                       
30935 +
30936                         return 1;
30937                 }
30938 -               
30939 +
30940                 hctx->response->ptr[n] = '\0';
30941                 hctx->response->used = n+1;
30942 -               
30943 +
30944                 /* split header from body */
30945 -               
30946 +
30947                 if (con->file_started == 0) {
30948                         char *c;
30949                         int in_header = 0;
30950                         int header_end = 0;
30951                         int cp, eol = EOL_UNSET;
30952                         size_t used = 0;
30953 -                       
30954 +
30955                         buffer_append_string_buffer(hctx->response_header, hctx->response);
30956 -                       
30957 +
30958                         /* nph (non-parsed headers) */
30959                         if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
30960 -                       
30961 +
30962                         /* search for the \r\n\r\n or \n\n in the string */
30963                         for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
30964                                 if (*c == ':') in_header = 1;
30965                                 else if (*c == '\n') {
30966                                         if (in_header == 0) {
30967                                                 /* got a response without a response header */
30968 -                                               
30969 +
30970                                                 c = NULL;
30971                                                 header_end = 1;
30972                                                 break;
30973                                         }
30974 -                                       
30975 +
30976                                         if (eol == EOL_UNSET) eol = EOL_N;
30977 -                                       
30978 +
30979                                         if (*(c+1) == '\n') {
30980                                                 header_end = 1;
30981                                                 break;
30982                                         }
30983 -                                       
30984 +
30985                                 } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
30986                                         if (in_header == 0) {
30987                                                 /* got a response without a response header */
30988 -                                               
30989 +
30990                                                 c = NULL;
30991                                                 header_end = 1;
30992                                                 break;
30993                                         }
30994 -                                       
30995 +
30996                                         if (eol == EOL_UNSET) eol = EOL_RN;
30997 -                                       
30998 +
30999                                         if (used > 3 &&
31000 -                                           *(c+2) == '\r' && 
31001 +                                           *(c+2) == '\r' &&
31002                                             *(c+3) == '\n') {
31003                                                 header_end = 1;
31004                                                 break;
31005                                         }
31006 -                                       
31007 +
31008                                         /* skip the \n */
31009                                         c++;
31010                                         cp++;
31011                                         used--;
31012                                 }
31013                         }
31014 -                       
31015 +
31016                         if (header_end) {
31017                                 if (c == NULL) {
31018                                         /* no header, but a body */
31019 -                                       
31020 +
31021                                         if (con->request.http_version == HTTP_VERSION_1_1) {
31022                                                 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
31023                                         }
31024 -                                       
31025 +
31026                                         http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
31027                                         joblist_append(srv, con);
31028                                 } else {
31029                                         size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
31030                                         size_t blen = hctx->response_header->used - hlen - 1;
31031 -                               
31032 +
31033                                         /* a small hack: terminate after at the second \r */
31034                                         hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
31035                                         hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';
31036 -                               
31037 +
31038                                         /* parse the response header */
31039                                         scgi_response_parse(srv, con, p, hctx->response_header, eol);
31040 -                                       
31041 +
31042                                         /* enable chunked-transfer-encoding */
31043                                         if (con->request.http_version == HTTP_VERSION_1_1 &&
31044                                             !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
31045                                                 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
31046                                         }
31047 -                                       
31048 +
31049                                         if ((hctx->response->used != hlen) && blen > 0) {
31050                                                 http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
31051                                                 joblist_append(srv, con);
31052                                         }
31053                                 }
31054 -                               
31055 +
31056                                 con->file_started = 1;
31057                         }
31058                 } else {
31059                         http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
31060                         joblist_append(srv, con);
31061                 }
31062 -               
31063 -#if 0          
31064 +
31065 +#if 0
31066                 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
31067  #endif
31068         }
31069 -       
31070 +
31071         return 0;
31072  }
31073  
31074  
31075  int scgi_proclist_sort_up(server *srv, scgi_extension_host *host, scgi_proc *proc) {
31076         scgi_proc *p;
31077 -       
31078 +
31079         UNUSED(srv);
31080 -       
31081 -       /* we have been the smallest of the current list 
31082 -        * and we want to insert the node sorted as soon 
31083 +
31084 +       /* we have been the smallest of the current list
31085 +        * and we want to insert the node sorted as soon
31086          * possible
31087          *
31088 -        * 1 0 0 0 1 1 1 
31089 -        * |      ^ 
31090 +        * 1 0 0 0 1 1 1
31091 +        * |      ^
31092          * |      |
31093          * +------+
31094 -        * 
31095 +        *
31096          */
31097  
31098         /* nothing to sort, only one element */
31099 @@ -1909,9 +1905,9 @@
31100  
31101         for (p = proc; p->next && p->next->load < proc->load; p = p->next);
31102  
31103 -       /* no need to move something 
31104 +       /* no need to move something
31105          *
31106 -        * 1 2 2 2 3 3 3 
31107 +        * 1 2 2 2 3 3 3
31108          * ^
31109          * |
31110          * +
31111 @@ -1930,16 +1926,16 @@
31112  
31113         if (proc->prev) proc->prev->next = proc->next;
31114         if (proc->next) proc->next->prev = proc->prev;
31115 -       
31116 +
31117         /* proc should be right of p */
31118 -       
31119 +
31120         proc->next = p->next;
31121         proc->prev = p;
31122         if (p->next) p->next->prev = proc;
31123         p->next = proc;
31124  #if 0
31125         for(p = host->first; p; p = p->next) {
31126 -               log_error_write(srv, __FILE__, __LINE__, "dd", 
31127 +               log_error_write(srv, __FILE__, __LINE__, "dd",
31128                                 p->pid, p->load);
31129         }
31130  #else
31131 @@ -1951,21 +1947,21 @@
31132  
31133  int scgi_proclist_sort_down(server *srv, scgi_extension_host *host, scgi_proc *proc) {
31134         scgi_proc *p;
31135 -       
31136 +
31137         UNUSED(srv);
31138 -       
31139 -       /* we have been the smallest of the current list 
31140 -        * and we want to insert the node sorted as soon 
31141 +
31142 +       /* we have been the smallest of the current list
31143 +        * and we want to insert the node sorted as soon
31144          * possible
31145          *
31146 -        *  0 0 0 0 1 0 1 
31147 +        *  0 0 0 0 1 0 1
31148          * ^          |
31149          * |          |
31150          * +----------+
31151          *
31152          *
31153          * the basic is idea is:
31154 -        * - the last active scgi process should be still 
31155 +        * - the last active scgi process should be still
31156          *   in ram and is not swapped out yet
31157          * - processes that are not reused will be killed
31158          *   after some time by the trigger-handler
31159 @@ -1975,7 +1971,7 @@
31160          *   ice-cold processes are propably unused since more
31161          *   than 'unused-timeout', are swaped out and won't be
31162          *   reused in the next seconds anyway.
31163 -        * 
31164 +        *
31165          */
31166  
31167         /* nothing to sort, only one element */
31168 @@ -1984,16 +1980,16 @@
31169         for (p = host->first; p != proc && p->load < proc->load; p = p->next);
31170  
31171  
31172 -       /* no need to move something 
31173 +       /* no need to move something
31174          *
31175 -        * 1 2 2 2 3 3 3 
31176 +        * 1 2 2 2 3 3 3
31177          * ^
31178          * |
31179          * +
31180          *
31181          */
31182         if (p == proc) return 0;
31183 -       
31184 +
31185         /* we have to move left. If we are already the first element
31186          * we are done */
31187         if (host->first == proc) return 0;
31188 @@ -2009,9 +2005,9 @@
31189         p->prev = proc;
31190  
31191         if (proc->prev == NULL) host->first = proc;
31192 -#if 0  
31193 +#if 0
31194         for(p = host->first; p; p = p->next) {
31195 -               log_error_write(srv, __FILE__, __LINE__, "dd", 
31196 +               log_error_write(srv, __FILE__, __LINE__, "dd",
31197                                 p->pid, p->load);
31198         }
31199  #else
31200 @@ -2023,41 +2019,42 @@
31201  
31202  static int scgi_restart_dead_procs(server *srv, plugin_data *p, scgi_extension_host *host) {
31203         scgi_proc *proc;
31204 -       
31205 +
31206         for (proc = host->first; proc; proc = proc->next) {
31207                 if (p->conf.debug) {
31208 -                       log_error_write(srv, __FILE__, __LINE__,  "sbdbdddd", 
31209 -                                       "proc:", 
31210 -                                       host->host, proc->port, 
31211 +                       log_error_write(srv, __FILE__, __LINE__,  "sbdbdddd",
31212 +                                       "proc:",
31213 +                                       host->host, proc->port,
31214                                         proc->socket,
31215                                         proc->state,
31216                                         proc->is_local,
31217                                         proc->load,
31218                                         proc->pid);
31219                 }
31220 -               
31221 +
31222                 if (0 == proc->is_local) {
31223 -                       /* 
31224 -                        * external servers might get disabled 
31225 -                        * 
31226 -                        * enable the server again, perhaps it is back again 
31227 +                       /*
31228 +                        * external servers might get disabled
31229 +                        *
31230 +                        * enable the server again, perhaps it is back again
31231                          */
31232 -                       
31233 +
31234                         if ((proc->state == PROC_STATE_DISABLED) &&
31235                             (srv->cur_ts - proc->disable_ts > host->disable_time)) {
31236                                 proc->state = PROC_STATE_RUNNING;
31237                                 host->active_procs++;
31238 -                               
31239 -                               log_error_write(srv, __FILE__, __LINE__,  "sbdb", 
31240 -                                               "fcgi-server re-enabled:", 
31241 -                                               host->host, host->port, 
31242 +
31243 +                               log_error_write(srv, __FILE__, __LINE__,  "sbdb",
31244 +                                               "fcgi-server re-enabled:",
31245 +                                               host->host, host->port,
31246                                                 host->unixsocket);
31247                         }
31248                 } else {
31249                         /* the child should not terminate at all */
31250                         int status;
31251 -                       
31252 +
31253                         if (proc->state == PROC_STATE_DIED_WAIT_FOR_PID) {
31254 +#ifndef _WIN32
31255                                 switch(waitpid(proc->pid, &status, WNOHANG)) {
31256                                 case 0:
31257                                         /* child is still alive */
31258 @@ -2067,33 +2064,34 @@
31259                                 default:
31260                                         if (WIFEXITED(status)) {
31261  #if 0
31262 -                                               log_error_write(srv, __FILE__, __LINE__, "sdsd", 
31263 +                                               log_error_write(srv, __FILE__, __LINE__, "sdsd",
31264                                                                 "child exited, pid:", proc->pid,
31265                                                                 "status:", WEXITSTATUS(status));
31266  #endif
31267                                         } else if (WIFSIGNALED(status)) {
31268 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
31269 -                                                               "child signaled:", 
31270 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
31271 +                                                               "child signaled:",
31272                                                                 WTERMSIG(status));
31273                                         } else {
31274 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
31275 -                                                               "child died somehow:", 
31276 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
31277 +                                                               "child died somehow:",
31278                                                                 status);
31279                                         }
31280 -                                       
31281 +
31282                                         proc->state = PROC_STATE_DIED;
31283                                         break;
31284                                 }
31285 +#endif
31286                         }
31287 -                       
31288 -                       /* 
31289 +
31290 +                       /*
31291                          * local servers might died, but we restart them
31292 -                        * 
31293 +                        *
31294                          */
31295                         if (proc->state == PROC_STATE_DIED &&
31296                             proc->load == 0) {
31297                                 /* restart the child */
31298 -                               
31299 +
31300                                 if (p->conf.debug) {
31301                                         log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
31302                                                         "--- scgi spawning",
31303 @@ -2101,18 +2099,18 @@
31304                                                         "\n\tsocket", host->unixsocket,
31305                                                         "\n\tcurrent:", 1, "/", host->min_procs);
31306                                 }
31307 -                               
31308 +
31309                                 if (scgi_spawn_connection(srv, p, host, proc)) {
31310                                         log_error_write(srv, __FILE__, __LINE__, "s",
31311                                                         "ERROR: spawning fcgi failed.");
31312                                         return HANDLER_ERROR;
31313                                 }
31314 -                               
31315 +
31316                                 scgi_proclist_sort_down(srv, host, proc);
31317                         }
31318                 }
31319         }
31320 -       
31321 +
31322         return 0;
31323  }
31324  
31325 @@ -2121,13 +2119,13 @@
31326         plugin_data *p    = hctx->plugin_data;
31327         scgi_extension_host *host= hctx->host;
31328         connection *con   = hctx->remote_conn;
31329 -       
31330 +
31331         int ret;
31332  
31333 -       /* sanity check */      
31334 +       /* sanity check */
31335         if (!host ||
31336             ((!host->host->used || !host->port) && !host->unixsocket->used)) {
31337 -               log_error_write(srv, __FILE__, __LINE__, "sxddd", 
31338 +               log_error_write(srv, __FILE__, __LINE__, "sxddd",
31339                                 "write-req: error",
31340                                 host,
31341                                 host->host->used,
31342 @@ -2135,179 +2133,180 @@
31343                                 host->unixsocket->used);
31344                 return HANDLER_ERROR;
31345         }
31346 -       
31347 +
31348  
31349         switch(hctx->state) {
31350         case FCGI_STATE_INIT:
31351                 ret = host->unixsocket->used ? AF_UNIX : AF_INET;
31352 -               
31353 +
31354                 if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
31355                         if (errno == EMFILE ||
31356                             errno == EINTR) {
31357 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
31358 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
31359                                                 "wait for fd at connection:", con->fd);
31360 -                               
31361 +
31362                                 return HANDLER_WAIT_FOR_FD;
31363                         }
31364 -                       
31365 -                       log_error_write(srv, __FILE__, __LINE__, "ssdd", 
31366 +
31367 +                       log_error_write(srv, __FILE__, __LINE__, "ssdd",
31368                                         "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
31369                         return HANDLER_ERROR;
31370                 }
31371                 hctx->fde_ndx = -1;
31372 -               
31373 +
31374                 srv->cur_fds++;
31375 -               
31376 +
31377                 fdevent_register(srv->ev, hctx->fd, scgi_handle_fdevent, hctx);
31378 -               
31379 +
31380                 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
31381 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
31382 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
31383                                         "fcntl failed: ", strerror(errno));
31384 -                       
31385 +
31386                         return HANDLER_ERROR;
31387                 }
31388 -               
31389 +
31390                 /* fall through */
31391         case FCGI_STATE_CONNECT:
31392                 if (hctx->state == FCGI_STATE_INIT) {
31393 -                       for (hctx->proc = hctx->host->first; 
31394 -                            hctx->proc && hctx->proc->state != PROC_STATE_RUNNING; 
31395 +                       for (hctx->proc = hctx->host->first;
31396 +                            hctx->proc && hctx->proc->state != PROC_STATE_RUNNING;
31397                              hctx->proc = hctx->proc->next);
31398 -                       
31399 +
31400                         /* all childs are dead */
31401                         if (hctx->proc == NULL) {
31402                                 hctx->fde_ndx = -1;
31403 -                               
31404 +
31405                                 return HANDLER_ERROR;
31406                         }
31407 -                       
31408 +
31409                         if (hctx->proc->is_local) {
31410                                 hctx->pid = hctx->proc->pid;
31411                         }
31412 -                       
31413 +
31414                         switch (scgi_establish_connection(srv, hctx)) {
31415                         case 1:
31416                                 scgi_set_state(srv, hctx, FCGI_STATE_CONNECT);
31417 -                               
31418 +
31419                                 /* connection is in progress, wait for an event and call getsockopt() below */
31420 -                               
31421 +
31422                                 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31423 -                               
31424 +
31425                                 return HANDLER_WAIT_FOR_EVENT;
31426                         case -1:
31427                                 /* if ECONNREFUSED choose another connection -> FIXME */
31428                                 hctx->fde_ndx = -1;
31429 -                               
31430 +
31431                                 return HANDLER_ERROR;
31432                         default:
31433                                 /* everything is ok, go on */
31434                                 break;
31435                         }
31436  
31437 -                       
31438 +
31439                 } else {
31440                         int socket_error;
31441                         socklen_t socket_error_len = sizeof(socket_error);
31442 -                       
31443 +
31444                         /* try to finish the connect() */
31445                         if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
31446 -                               log_error_write(srv, __FILE__, __LINE__, "ss", 
31447 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
31448                                                 "getsockopt failed:", strerror(errno));
31449 -                               
31450 +
31451                                 return HANDLER_ERROR;
31452                         }
31453                         if (socket_error != 0) {
31454                                 if (!hctx->proc->is_local || p->conf.debug) {
31455                                         /* local procs get restarted */
31456 -                                       
31457 +
31458                                         log_error_write(srv, __FILE__, __LINE__, "ss",
31459 -                                                       "establishing connection failed:", strerror(socket_error), 
31460 +                                                       "establishing connection failed:", strerror(socket_error),
31461                                                         "port:", hctx->proc->port);
31462                                 }
31463 -                               
31464 +
31465                                 return HANDLER_ERROR;
31466                         }
31467                 }
31468 -               
31469 +
31470                 /* ok, we have the connection */
31471 -               
31472 +
31473                 hctx->proc->load++;
31474                 hctx->proc->last_used = srv->cur_ts;
31475                 hctx->got_proc = 1;
31476 -               
31477 +
31478                 if (p->conf.debug) {
31479                         log_error_write(srv, __FILE__, __LINE__, "sddbdd",
31480 -                                       "got proc:", 
31481 +                                       "got proc:",
31482                                         hctx->fd,
31483 -                                       hctx->proc->pid, 
31484 -                                       hctx->proc->socket, 
31485 +                                       hctx->proc->pid,
31486 +                                       hctx->proc->socket,
31487                                         hctx->proc->port,
31488                                         hctx->proc->load);
31489                 }
31490  
31491                 /* move the proc-list entry down the list */
31492                 scgi_proclist_sort_up(srv, hctx->host, hctx->proc);
31493 -               
31494 +
31495                 scgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
31496                 /* fall through */
31497         case FCGI_STATE_PREPARE_WRITE:
31498                 scgi_create_env(srv, hctx);
31499 -               
31500 +
31501                 scgi_set_state(srv, hctx, FCGI_STATE_WRITE);
31502 -               
31503 +
31504                 /* fall through */
31505         case FCGI_STATE_WRITE:
31506 -               ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); 
31507 +               ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
31508  
31509                 chunkqueue_remove_finished_chunks(hctx->wb);
31510 -       
31511 +
31512                 if (-1 == ret) {
31513                         if (errno == ENOTCONN) {
31514 -                               /* the connection got dropped after accept() 
31515 -                                * 
31516 -                                * this is most of the time a PHP which dies 
31517 +                               /* the connection got dropped after accept()
31518 +                                *
31519 +                                * this is most of the time a PHP which dies
31520                                  * after PHP_FCGI_MAX_REQUESTS
31521 -                                * 
31522 -                                */ 
31523 +                                *
31524 +                                */
31525                                 if (hctx->wb->bytes_out == 0 &&
31526                                     hctx->reconnects < 5) {
31527 -                                       usleep(10000); /* take away the load of the webserver 
31528 -                                                       * to let the php a chance to restart 
31529 +#ifndef _WIN32
31530 +                                       usleep(10000); /* take away the load of the webserver
31531 +                                                       * to let the php a chance to restart
31532                                                         */
31533 -                                       
31534 +#endif
31535                                         scgi_reconnect(srv, hctx);
31536 -                               
31537 +
31538                                         return HANDLER_WAIT_FOR_FD;
31539                                 }
31540 -                               
31541 +
31542                                 /* not reconnected ... why
31543 -                                * 
31544 +                                *
31545                                  * far@#lighttpd report this for FreeBSD
31546 -                                * 
31547 +                                *
31548                                  */
31549 -                               
31550 -                               log_error_write(srv, __FILE__, __LINE__, "ssdsd", 
31551 +
31552 +                               log_error_write(srv, __FILE__, __LINE__, "ssosd",
31553                                                 "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
31554                                                 "write-offset:", hctx->wb->bytes_out,
31555                                                 "reconnect attempts:", hctx->reconnects);
31556 -                               
31557 +
31558                                 return HANDLER_ERROR;
31559                         }
31560 -                       
31561 +
31562                         if ((errno != EAGAIN) &&
31563                             (errno != EINTR)) {
31564 -                               
31565 -                               log_error_write(srv, __FILE__, __LINE__, "ssd", 
31566 +
31567 +                               log_error_write(srv, __FILE__, __LINE__, "ssd",
31568                                                 "write failed:", strerror(errno), errno);
31569 -                               
31570 +
31571                                 return HANDLER_ERROR;
31572                         } else {
31573                                 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31574 -                               
31575 +
31576                                 return HANDLER_WAIT_FOR_EVENT;
31577                         }
31578                 }
31579 -               
31580 +
31581                 if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
31582                         /* we don't need the out event anymore */
31583                         fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
31584 @@ -2315,10 +2314,10 @@
31585                         scgi_set_state(srv, hctx, FCGI_STATE_READ);
31586                 } else {
31587                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
31588 -                       
31589 +
31590                         return HANDLER_WAIT_FOR_EVENT;
31591                 }
31592 -               
31593 +
31594                 break;
31595         case FCGI_STATE_READ:
31596                 /* waiting for a response */
31597 @@ -2327,67 +2326,67 @@
31598                 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
31599                 return HANDLER_ERROR;
31600         }
31601 -       
31602 +
31603         return HANDLER_WAIT_FOR_EVENT;
31604  }
31605  
31606  SUBREQUEST_FUNC(mod_scgi_handle_subrequest) {
31607         plugin_data *p = p_d;
31608 -       
31609 +
31610         handler_ctx *hctx = con->plugin_ctx[p->id];
31611         scgi_proc *proc;
31612         scgi_extension_host *host;
31613 -       
31614 +
31615         if (NULL == hctx) return HANDLER_GO_ON;
31616 -       
31617 +
31618         /* not my job */
31619         if (con->mode != p->id) return HANDLER_GO_ON;
31620 -       
31621 +
31622         /* ok, create the request */
31623         switch(scgi_write_request(srv, hctx)) {
31624         case HANDLER_ERROR:
31625                 proc = hctx->proc;
31626                 host = hctx->host;
31627 -               
31628 -               if (proc && 
31629 +
31630 +               if (proc &&
31631                     0 == proc->is_local &&
31632                     proc->state != PROC_STATE_DISABLED) {
31633                         /* only disable remote servers as we don't manage them*/
31634 -                       
31635 -                       log_error_write(srv, __FILE__, __LINE__,  "sbdb", "fcgi-server disabled:", 
31636 +
31637 +                       log_error_write(srv, __FILE__, __LINE__,  "sbdb", "fcgi-server disabled:",
31638                                         host->host,
31639                                         proc->port,
31640                                         proc->socket);
31641 -                       
31642 +
31643                         /* disable this server */
31644                         proc->disable_ts = srv->cur_ts;
31645                         proc->state = PROC_STATE_DISABLED;
31646                         host->active_procs--;
31647                 }
31648 -               
31649 +
31650                 if (hctx->state == FCGI_STATE_INIT ||
31651                     hctx->state == FCGI_STATE_CONNECT) {
31652 -                       /* connect() or getsockopt() failed, 
31653 -                        * restart the request-handling 
31654 +                       /* connect() or getsockopt() failed,
31655 +                        * restart the request-handling
31656                          */
31657                         if (proc && proc->is_local) {
31658  
31659                                 if (p->conf.debug) {
31660 -                                       log_error_write(srv, __FILE__, __LINE__,  "sbdb", "connect() to scgi failed, restarting the request-handling:", 
31661 +                                       log_error_write(srv, __FILE__, __LINE__,  "sbdb", "connect() to scgi failed, restarting the request-handling:",
31662                                                         host->host,
31663                                                         proc->port,
31664                                                         proc->socket);
31665                                 }
31666  
31667 -                               /* 
31668 +                               /*
31669                                  * several hctx might reference the same proc
31670 -                                * 
31671 +                                *
31672                                  * Only one of them should mark the proc as dead all the other
31673                                  * ones should just take a new one.
31674 -                                * 
31675 +                                *
31676                                  * If a new proc was started with the old struct this might lead
31677                                  * the mark a perfect proc as dead otherwise
31678 -                                * 
31679 +                                *
31680                                  */
31681                                 if (proc->state == PROC_STATE_RUNNING &&
31682                                     hctx->pid == proc->pid) {
31683 @@ -2395,25 +2394,25 @@
31684                                 }
31685                         }
31686                         scgi_restart_dead_procs(srv, p, host);
31687 -                       
31688 +
31689                         scgi_connection_cleanup(srv, hctx);
31690 -                       
31691 +
31692                         buffer_reset(con->physical.path);
31693                         con->mode = DIRECT;
31694                         joblist_append(srv, con);
31695 -                       
31696 -                       /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop 
31697 -                        * and hope that the childs will be restarted 
31698 -                        * 
31699 +
31700 +                       /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
31701 +                        * and hope that the childs will be restarted
31702 +                        *
31703                          */
31704                         return HANDLER_WAIT_FOR_FD;
31705                 } else {
31706                         scgi_connection_cleanup(srv, hctx);
31707 -                       
31708 +
31709                         buffer_reset(con->physical.path);
31710                         con->mode = DIRECT;
31711                         con->http_status = 503;
31712 -                       
31713 +
31714                         return HANDLER_FINISHED;
31715                 }
31716         case HANDLER_WAIT_FOR_EVENT:
31717 @@ -2433,23 +2432,23 @@
31718  static handler_t scgi_connection_close(server *srv, handler_ctx *hctx) {
31719         plugin_data *p;
31720         connection  *con;
31721 -       
31722 +
31723         if (NULL == hctx) return HANDLER_GO_ON;
31724 -       
31725 +
31726         p    = hctx->plugin_data;
31727         con  = hctx->remote_conn;
31728 -       
31729 +
31730         if (con->mode != p->id) return HANDLER_GO_ON;
31731 -       
31732 -       log_error_write(srv, __FILE__, __LINE__, "ssdsd", 
31733 -                       "emergency exit: scgi:", 
31734 +
31735 +       log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31736 +                       "emergency exit: scgi:",
31737                         "connection-fd:", con->fd,
31738                         "fcgi-fd:", hctx->fd);
31739 -       
31740 -       
31741 -       
31742 +
31743 +
31744 +
31745         scgi_connection_cleanup(srv, hctx);
31746 -       
31747 +
31748         return HANDLER_FINISHED;
31749  }
31750  
31751 @@ -2459,7 +2458,7 @@
31752         handler_ctx *hctx = ctx;
31753         connection  *con  = hctx->remote_conn;
31754         plugin_data *p    = hctx->plugin_data;
31755 -       
31756 +
31757         scgi_proc *proc   = hctx->proc;
31758         scgi_extension_host *host= hctx->host;
31759  
31760 @@ -2471,15 +2470,15 @@
31761                 case 1:
31762                         /* we are done */
31763                         scgi_connection_cleanup(srv, hctx);
31764 -                       
31765 +
31766                         joblist_append(srv, con);
31767                         return HANDLER_FINISHED;
31768                 case -1:
31769                         if (proc->pid && proc->state != PROC_STATE_DIED) {
31770                                 int status;
31771 -                               
31772 +
31773                                 /* only fetch the zombie if it is not already done */
31774 -                               
31775 +#ifndef _WIN32
31776                                 switch(waitpid(proc->pid, &status, WNOHANG)) {
31777                                 case 0:
31778                                         /* child is still alive */
31779 @@ -2489,19 +2488,19 @@
31780                                 default:
31781                                         /* the child should not terminate at all */
31782                                         if (WIFEXITED(status)) {
31783 -                                               log_error_write(srv, __FILE__, __LINE__, "sdsd", 
31784 +                                               log_error_write(srv, __FILE__, __LINE__, "sdsd",
31785                                                                 "child exited, pid:", proc->pid,
31786                                                                 "status:", WEXITSTATUS(status));
31787                                         } else if (WIFSIGNALED(status)) {
31788 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
31789 -                                                               "child signaled:", 
31790 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
31791 +                                                               "child signaled:",
31792                                                                 WTERMSIG(status));
31793                                         } else {
31794 -                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
31795 -                                                               "child died somehow:", 
31796 +                                               log_error_write(srv, __FILE__, __LINE__, "sd",
31797 +                                                               "child died somehow:",
31798                                                                 status);
31799                                         }
31800 -                                       
31801 +
31802                                         if (p->conf.debug) {
31803                                                 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
31804                                                                 "--- scgi spawning",
31805 @@ -2509,40 +2508,41 @@
31806                                                                 "\n\tsocket", host->unixsocket,
31807                                                                 "\n\tcurrent:", 1, "/", host->min_procs);
31808                                         }
31809 -                                       
31810 +
31811                                         if (scgi_spawn_connection(srv, p, host, proc)) {
31812                                                 /* child died */
31813                                                 proc->state = PROC_STATE_DIED;
31814                                         } else {
31815                                                 scgi_proclist_sort_down(srv, host, proc);
31816                                         }
31817 -                                       
31818 +
31819                                         break;
31820                                 }
31821 +#endif
31822                         }
31823  
31824                         if (con->file_started == 0) {
31825                                 /* nothing has been send out yet, try to use another child */
31826 -                               
31827 +
31828                                 if (hctx->wb->bytes_out == 0 &&
31829                                     hctx->reconnects < 5) {
31830                                         scgi_reconnect(srv, hctx);
31831 -                                       
31832 -                                       log_error_write(srv, __FILE__, __LINE__, "sdsdsd", 
31833 +
31834 +                                       log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
31835                                                 "response not sent, request not sent, reconnection.",
31836                                                 "connection-fd:", con->fd,
31837                                                 "fcgi-fd:", hctx->fd);
31838 -                                       
31839 +
31840                                         return HANDLER_WAIT_FOR_FD;
31841                                 }
31842 -                               
31843 -                               log_error_write(srv, __FILE__, __LINE__, "sdsdsd", 
31844 +
31845 +                               log_error_write(srv, __FILE__, __LINE__, "sosdsd",
31846                                                 "response not sent, request sent:", hctx->wb->bytes_out,
31847                                                 "connection-fd:", con->fd,
31848                                                 "fcgi-fd:", hctx->fd);
31849 -                               
31850 +
31851                                 scgi_connection_cleanup(srv, hctx);
31852 -                               
31853 +
31854                                 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
31855                                 buffer_reset(con->physical.path);
31856                                 con->http_status = 500;
31857 @@ -2550,76 +2550,76 @@
31858                         } else {
31859                                 /* response might have been already started, kill the connection */
31860                                 scgi_connection_cleanup(srv, hctx);
31861 -                               
31862 -                               log_error_write(srv, __FILE__, __LINE__, "ssdsd", 
31863 +
31864 +                               log_error_write(srv, __FILE__, __LINE__, "ssdsd",
31865                                                 "response already sent out, termination connection",
31866                                                 "connection-fd:", con->fd,
31867                                                 "fcgi-fd:", hctx->fd);
31868 -                               
31869 +
31870                                 connection_set_state(srv, con, CON_STATE_ERROR);
31871                         }
31872  
31873                         /* */
31874 -                       
31875 -                       
31876 +
31877 +
31878                         joblist_append(srv, con);
31879                         return HANDLER_FINISHED;
31880                 }
31881         }
31882 -       
31883 +
31884         if (revents & FDEVENT_OUT) {
31885                 if (hctx->state == FCGI_STATE_CONNECT ||
31886                     hctx->state == FCGI_STATE_WRITE) {
31887                         /* we are allowed to send something out
31888 -                        * 
31889 +                        *
31890                          * 1. in a unfinished connect() call
31891                          * 2. in a unfinished write() call (long POST request)
31892                          */
31893                         return mod_scgi_handle_subrequest(srv, con, p);
31894                 } else {
31895 -                       log_error_write(srv, __FILE__, __LINE__, "sd", 
31896 -                                       "got a FDEVENT_OUT and didn't know why:", 
31897 +                       log_error_write(srv, __FILE__, __LINE__, "sd",
31898 +                                       "got a FDEVENT_OUT and didn't know why:",
31899                                         hctx->state);
31900                 }
31901         }
31902 -       
31903 +
31904         /* perhaps this issue is already handled */
31905         if (revents & FDEVENT_HUP) {
31906                 if (hctx->state == FCGI_STATE_CONNECT) {
31907                         /* getoptsock will catch this one (right ?)
31908 -                        * 
31909 -                        * if we are in connect we might get a EINPROGRESS 
31910 -                        * in the first call and a FDEVENT_HUP in the 
31911 +                        *
31912 +                        * if we are in connect we might get a EINPROGRESS
31913 +                        * in the first call and a FDEVENT_HUP in the
31914                          * second round
31915 -                        * 
31916 +                        *
31917                          * FIXME: as it is a bit ugly.
31918 -                        * 
31919 +                        *
31920                          */
31921                         return mod_scgi_handle_subrequest(srv, con, p);
31922                 } else if (hctx->state == FCGI_STATE_READ &&
31923                            hctx->proc->port == 0) {
31924                         /* FIXME:
31925 -                        * 
31926 +                        *
31927                          * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket
31928                          * even if the FCGI_FIN packet is not received yet
31929                          */
31930                 } else {
31931 -                       log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd", 
31932 -                                       "error: unexpected close of scgi connection for", 
31933 +                       log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
31934 +                                       "error: unexpected close of scgi connection for",
31935                                         con->uri.path,
31936 -                                       "(no scgi process on host: ", 
31937 +                                       "(no scgi process on host: ",
31938                                         host->host,
31939 -                                       ", port: ", 
31940 +                                       ", port: ",
31941                                         host->port,
31942                                         " ?)",
31943                                         hctx->state);
31944 -                       
31945 +
31946                         connection_set_state(srv, con, CON_STATE_ERROR);
31947                         scgi_connection_close(srv, hctx);
31948                         joblist_append(srv, con);
31949                 }
31950         } else if (revents & FDEVENT_ERR) {
31951 -               log_error_write(srv, __FILE__, __LINE__, "s", 
31952 +               log_error_write(srv, __FILE__, __LINE__, "s",
31953                                 "fcgi: got a FDEVENT_ERR. Don't know why.");
31954                 /* kill all connections to the scgi process */
31955  
31956 @@ -2628,42 +2628,39 @@
31957                 scgi_connection_close(srv, hctx);
31958                 joblist_append(srv, con);
31959         }
31960 -       
31961 +
31962         return HANDLER_FINISHED;
31963  }
31964 -#define PATCH(x) \
31965 -       p->conf.x = s->x;
31966 +
31967  static int scgi_patch_connection(server *srv, connection *con, plugin_data *p) {
31968         size_t i, j;
31969         plugin_config *s = p->config_storage[0];
31970 -       
31971 -       PATCH(exts);
31972 -       PATCH(debug);
31973 -       
31974 +
31975 +       PATCH_OPTION(exts);
31976 +       PATCH_OPTION(debug);
31977 +
31978         /* skip the first, the global context */
31979         for (i = 1; i < srv->config_context->used; i++) {
31980                 data_config *dc = (data_config *)srv->config_context->data[i];
31981                 s = p->config_storage[i];
31982 -               
31983 +
31984                 /* condition didn't match */
31985                 if (!config_check_cond(srv, con, dc)) continue;
31986 -               
31987 +
31988                 /* merge config */
31989                 for (j = 0; j < dc->value->used; j++) {
31990                         data_unset *du = dc->value->data[j];
31991 -                       
31992 +
31993                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.server"))) {
31994 -                               PATCH(exts);
31995 +                               PATCH_OPTION(exts);
31996                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.debug"))) {
31997 -                               PATCH(debug);
31998 +                               PATCH_OPTION(debug);
31999                         }
32000                 }
32001         }
32002 -       
32003 +
32004         return 0;
32005  }
32006 -#undef PATCH
32007 -
32008  
32009  static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
32010         plugin_data *p = p_d;
32011 @@ -2673,30 +2670,30 @@
32012         size_t k;
32013         buffer *fn;
32014         scgi_extension *extension = NULL;
32015 -       
32016 +
32017         /* Possibly, we processed already this request */
32018         if (con->file_started == 1) return HANDLER_GO_ON;
32019 -       
32020 +
32021         fn = uri_path_handler ? con->uri.path : con->physical.path;
32022  
32023         if (buffer_is_empty(fn)) return HANDLER_GO_ON;
32024  
32025         s_len = fn->used - 1;
32026 -       
32027 +
32028         scgi_patch_connection(srv, con, p);
32029  
32030         /* check if extension matches */
32031         for (k = 0; k < p->conf.exts->used; k++) {
32032                 size_t ct_len;
32033 -               
32034 +
32035                 extension = p->conf.exts->exts[k];
32036 -               
32037 +
32038                 if (extension->key->used == 0) continue;
32039 -               
32040 +
32041                 ct_len = extension->key->used - 1;
32042 -               
32043 +
32044                 if (s_len < ct_len) continue;
32045 -               
32046 +
32047                 /* check extension in the form "/scgi_pattern" */
32048                 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
32049                         break;
32050 @@ -2710,17 +2707,17 @@
32051         if (k == p->conf.exts->used) {
32052                 return HANDLER_GO_ON;
32053         }
32054 -       
32055 +
32056         /* get best server */
32057         for (k = 0, ndx = -1; k < extension->used; k++) {
32058                 scgi_extension_host *host = extension->hosts[k];
32059 -               
32060 +
32061                 /* we should have at least one proc that can do somthing */
32062                 if (host->active_procs == 0) continue;
32063  
32064                 if (used == -1 || host->load < used) {
32065                         used = host->load;
32066 -                       
32067 +
32068                         ndx = k;
32069                 }
32070         }
32071 @@ -2728,12 +2725,12 @@
32072         /* found a server */
32073         if (ndx != -1) {
32074                 scgi_extension_host *host = extension->hosts[ndx];
32075 -               
32076 -               /* 
32077 -                * if check-local is disabled, use the uri.path handler 
32078 -                * 
32079 +
32080 +               /*
32081 +                * if check-local is disabled, use the uri.path handler
32082 +                *
32083                  */
32084 -               
32085 +
32086                 /* init handler-context */
32087                 if (uri_path_handler) {
32088                         if (host->check_local == 0) {
32089 @@ -2741,7 +2738,7 @@
32090                                 char *pathinfo;
32091  
32092                                 hctx = handler_ctx_init();
32093 -                               
32094 +
32095                                 hctx->remote_conn      = con;
32096                                 hctx->plugin_data      = p;
32097                                 hctx->host             = host;
32098 @@ -2749,45 +2746,45 @@
32099  
32100                                 hctx->conf.exts        = p->conf.exts;
32101                                 hctx->conf.debug       = p->conf.debug;
32102 -                               
32103 +
32104                                 con->plugin_ctx[p->id] = hctx;
32105 -                               
32106 +
32107                                 host->load++;
32108 -                               
32109 +
32110                                 con->mode = p->id;
32111  
32112                                 if (con->conf.log_request_handling) {
32113                                         log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_scgi");
32114                                 }
32115  
32116 -                               /* the prefix is the SCRIPT_NAME, 
32117 +                               /* the prefix is the SCRIPT_NAME,
32118                                  * everthing from start to the next slash
32119                                  * this is important for check-local = "disable"
32120 -                                * 
32121 +                                *
32122                                  * if prefix = /admin.fcgi
32123 -                                * 
32124 +                                *
32125                                  * /admin.fcgi/foo/bar
32126 -                                * 
32127 +                                *
32128                                  * SCRIPT_NAME = /admin.fcgi
32129                                  * PATH_INFO   = /foo/bar
32130 -                                * 
32131 +                                *
32132                                  * if prefix = /fcgi-bin/
32133 -                                * 
32134 +                                *
32135                                  * /fcgi-bin/foo/bar
32136 -                                * 
32137 +                                *
32138                                  * SCRIPT_NAME = /fcgi-bin/foo
32139                                  * PATH_INFO   = /bar
32140 -                                * 
32141 +                                *
32142                                  */
32143 -                               
32144 +
32145                                 /* the rewrite is only done for /prefix/? matches */
32146                                 if (extension->key->ptr[0] == '/' &&
32147                                     con->uri.path->used > extension->key->used &&
32148                                     NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) {
32149 -                                       /* rewrite uri.path and pathinfo */ 
32150 -                                       
32151 +                                       /* rewrite uri.path and pathinfo */
32152 +
32153                                         buffer_copy_string(con->request.pathinfo, pathinfo);
32154 -                                       
32155 +
32156                                         con->uri.path->used -= con->request.pathinfo->used - 1;
32157                                         con->uri.path->ptr[con->uri.path->used - 1] = '\0';
32158                                 }
32159 @@ -2796,21 +2793,21 @@
32160                 } else {
32161                         handler_ctx *hctx;
32162                         hctx = handler_ctx_init();
32163 -                       
32164 +
32165                         hctx->remote_conn      = con;
32166                         hctx->plugin_data      = p;
32167                         hctx->host             = host;
32168                         hctx->proc             = NULL;
32169 -                       
32170 +
32171                         hctx->conf.exts        = p->conf.exts;
32172                         hctx->conf.debug       = p->conf.debug;
32173 -                       
32174 +
32175                         con->plugin_ctx[p->id] = hctx;
32176 -                       
32177 +
32178                         host->load++;
32179 -                       
32180 +
32181                         con->mode = p->id;
32182 -                       
32183 +
32184                         if (con->conf.log_request_handling) {
32185                                 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
32186                         }
32187 @@ -2821,11 +2818,11 @@
32188                 /* no handler found */
32189                 buffer_reset(con->physical.path);
32190                 con->http_status = 500;
32191 -               
32192 -               log_error_write(srv, __FILE__, __LINE__,  "sb", 
32193 -                               "no fcgi-handler found for:", 
32194 +
32195 +               log_error_write(srv, __FILE__, __LINE__,  "sb",
32196 +                               "no fcgi-handler found for:",
32197                                 fn);
32198 -               
32199 +
32200                 return HANDLER_FINISHED;
32201         }
32202         return HANDLER_GO_ON;
32203 @@ -2844,19 +2841,19 @@
32204  JOBLIST_FUNC(mod_scgi_handle_joblist) {
32205         plugin_data *p = p_d;
32206         handler_ctx *hctx = con->plugin_ctx[p->id];
32207 -       
32208 +
32209         if (hctx == NULL) return HANDLER_GO_ON;
32210  
32211         if (hctx->fd != -1) {
32212                 switch (hctx->state) {
32213                 case FCGI_STATE_READ:
32214                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
32215 -                       
32216 +
32217                         break;
32218                 case FCGI_STATE_CONNECT:
32219                 case FCGI_STATE_WRITE:
32220                         fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
32221 -                       
32222 +
32223                         break;
32224                 case FCGI_STATE_INIT:
32225                         /* at reconnect */
32226 @@ -2873,21 +2870,21 @@
32227  
32228  static handler_t scgi_connection_close_callback(server *srv, connection *con, void *p_d) {
32229         plugin_data *p = p_d;
32230 -       
32231 +
32232         return scgi_connection_close(srv, con->plugin_ctx[p->id]);
32233  }
32234  
32235  TRIGGER_FUNC(mod_scgi_handle_trigger) {
32236         plugin_data *p = p_d;
32237         size_t i, j, n;
32238 -       
32239 -       
32240 +
32241 +
32242         /* perhaps we should kill a connect attempt after 10-15 seconds
32243 -        * 
32244 +        *
32245          * currently we wait for the TCP timeout which is on Linux 180 seconds
32246 -        * 
32247 -        * 
32248 -        * 
32249 +        *
32250 +        *
32251 +        *
32252          */
32253  
32254         /* check all childs if they are still up */
32255 @@ -2904,47 +2901,47 @@
32256                         scgi_extension *ex;
32257  
32258                         ex = exts->exts[j];
32259 -                       
32260 +
32261                         for (n = 0; n < ex->used; n++) {
32262 -                               
32263 +
32264                                 scgi_proc *proc;
32265                                 unsigned long sum_load = 0;
32266                                 scgi_extension_host *host;
32267 -                               
32268 +
32269                                 host = ex->hosts[n];
32270 -                               
32271 +
32272                                 scgi_restart_dead_procs(srv, p, host);
32273 -                               
32274 +
32275                                 for (proc = host->first; proc; proc = proc->next) {
32276                                         sum_load += proc->load;
32277                                 }
32278 -                               
32279 +
32280                                 if (host->num_procs &&
32281                                     host->num_procs < host->max_procs &&
32282                                     (sum_load / host->num_procs) > host->max_load_per_proc) {
32283                                         /* overload, spawn new child */
32284                                         scgi_proc *fp = NULL;
32285 -                                       
32286 +
32287                                         if (p->conf.debug) {
32288 -                                               log_error_write(srv, __FILE__, __LINE__, "s", 
32289 +                                               log_error_write(srv, __FILE__, __LINE__, "s",
32290                                                                 "overload detected, spawning a new child");
32291                                         }
32292 -                                       
32293 +
32294                                         for (fp = host->unused_procs; fp && fp->pid != 0; fp = fp->next);
32295 -                                       
32296 +
32297                                         if (fp) {
32298                                                 if (fp == host->unused_procs) host->unused_procs = fp->next;
32299 -                                               
32300 +
32301                                                 if (fp->next) fp->next->prev = NULL;
32302 -                                               
32303 +
32304                                                 host->max_id++;
32305                                         } else {
32306                                                 fp = scgi_process_init();
32307                                                 fp->id = host->max_id++;
32308                                         }
32309 -                                       
32310 +
32311                                         host->num_procs++;
32312 -                                       
32313 +
32314                                         if (buffer_is_empty(host->unixsocket)) {
32315                                                 fp->port = host->port + fp->id;
32316                                         } else {
32317 @@ -2952,13 +2949,13 @@
32318                                                 buffer_append_string(fp->socket, "-");
32319                                                 buffer_append_long(fp->socket, fp->id);
32320                                         }
32321 -                                       
32322 +
32323                                         if (scgi_spawn_connection(srv, p, host, fp)) {
32324                                                 log_error_write(srv, __FILE__, __LINE__, "s",
32325                                                                 "ERROR: spawning fcgi failed.");
32326                                                 return HANDLER_ERROR;
32327                                         }
32328 -                                       
32329 +
32330                                         fp->prev = NULL;
32331                                         fp->next = host->first;
32332                                         if (host->first) {
32333 @@ -2966,56 +2963,57 @@
32334                                         }
32335                                         host->first = fp;
32336                                 }
32337 -                               
32338 +
32339                                 for (proc = host->first; proc; proc = proc->next) {
32340                                         if (proc->load != 0) break;
32341                                         if (host->num_procs <= host->min_procs) break;
32342                                         if (proc->pid == 0) continue;
32343 -                                       
32344 +#ifndef _WIN32
32345                                         if (srv->cur_ts - proc->last_used > host->idle_timeout) {
32346                                                 /* a proc is idling for a long time now,
32347                                                  * terminated it */
32348 -                                               
32349 +
32350                                                 if (p->conf.debug) {
32351 -                                                       log_error_write(srv, __FILE__, __LINE__, "ssbsd", 
32352 -                                                                       "idle-timeout reached, terminating child:", 
32353 -                                                                       "socket:", proc->socket, 
32354 +                                                       log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32355 +                                                                       "idle-timeout reached, terminating child:",
32356 +                                                                       "socket:", proc->socket,
32357                                                                         "pid", proc->pid);
32358                                                 }
32359 -                                               
32360 -                                               
32361 +
32362 +
32363                                                 if (proc->next) proc->next->prev = proc->prev;
32364                                                 if (proc->prev) proc->prev->next = proc->next;
32365 -                                               
32366 +
32367                                                 if (proc->prev == NULL) host->first = proc->next;
32368 -                                               
32369 +
32370                                                 proc->prev = NULL;
32371                                                 proc->next = host->unused_procs;
32372 -                                               
32373 +
32374                                                 if (host->unused_procs) host->unused_procs->prev = proc;
32375                                                 host->unused_procs = proc;
32376 -                                               
32377 +
32378                                                 kill(proc->pid, SIGTERM);
32379 -                                               
32380 +
32381                                                 proc->state = PROC_STATE_KILLED;
32382 -                                               
32383 -                                               log_error_write(srv, __FILE__, __LINE__, "ssbsd", 
32384 -                                                                       "killed:", 
32385 -                                                                       "socket:", proc->socket, 
32386 +
32387 +                                               log_error_write(srv, __FILE__, __LINE__, "ssbsd",
32388 +                                                                       "killed:",
32389 +                                                                       "socket:", proc->socket,
32390                                                                         "pid", proc->pid);
32391 -                                               
32392 +
32393                                                 host->num_procs--;
32394 -                                               
32395 +
32396                                                 /* proc is now in unused, let the next second handle the next process */
32397                                                 break;
32398 -                                       }       
32399 +                                       }
32400 +#endif
32401                                 }
32402 -                               
32403 +
32404                                 for (proc = host->unused_procs; proc; proc = proc->next) {
32405                                         int status;
32406 -                                       
32407 +
32408                                         if (proc->pid == 0) continue;
32409 -                                       
32410 +#ifndef _WIN32
32411                                         switch (waitpid(proc->pid, &status, WNOHANG)) {
32412                                         case 0:
32413                                                 /* child still running after timeout, good */
32414 @@ -3023,10 +3021,10 @@
32415                                         case -1:
32416                                                 if (errno != EINTR) {
32417                                                         /* no PID found ? should never happen */
32418 -                                                       log_error_write(srv, __FILE__, __LINE__, "sddss", 
32419 +                                                       log_error_write(srv, __FILE__, __LINE__, "sddss",
32420                                                                         "pid ", proc->pid, proc->state,
32421                                                                         "not found:", strerror(errno));
32422 -                                                       
32423 +
32424  #if 0
32425                                                         if (errno == ECHILD) {
32426                                                                 /* someone else has cleaned up for us */
32427 @@ -3040,25 +3038,26 @@
32428                                                 /* the child should not terminate at all */
32429                                                 if (WIFEXITED(status)) {
32430                                                         if (proc->state != PROC_STATE_KILLED) {
32431 -                                                               log_error_write(srv, __FILE__, __LINE__, "sdb", 
32432 -                                                                               "child exited:", 
32433 +                                                               log_error_write(srv, __FILE__, __LINE__, "sdb",
32434 +                                                                               "child exited:",
32435                                                                                 WEXITSTATUS(status), proc->socket);
32436                                                         }
32437                                                 } else if (WIFSIGNALED(status)) {
32438                                                         if (WTERMSIG(status) != SIGTERM) {
32439 -                                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
32440 -                                                                               "child signaled:", 
32441 +                                                               log_error_write(srv, __FILE__, __LINE__, "sd",
32442 +                                                                               "child signaled:",
32443                                                                                 WTERMSIG(status));
32444                                                         }
32445                                                 } else {
32446 -                                                       log_error_write(srv, __FILE__, __LINE__, "sd", 
32447 -                                                                       "child died somehow:", 
32448 +                                                       log_error_write(srv, __FILE__, __LINE__, "sd",
32449 +                                                                       "child died somehow:",
32450                                                                         status);
32451                                                 }
32452                                                 proc->pid = 0;
32453                                                 proc->state = PROC_STATE_UNSET;
32454                                                 host->max_id--;
32455                                         }
32456 +#endif
32457                                 }
32458                         }
32459                 }
32460 @@ -3082,8 +3081,8 @@
32461         p->handle_subrequest       = mod_scgi_handle_subrequest;
32462         p->handle_joblist          = mod_scgi_handle_joblist;
32463         p->handle_trigger          = mod_scgi_handle_trigger;
32464 -       
32465 +
32466         p->data         = NULL;
32467 -       
32468 +
32469         return 0;
32470  }
32471 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_secure_download.c lighttpd-1.4.12/src/mod_secure_download.c
32472 --- lighttpd-1.4.11/src/mod_secure_download.c   2005-12-14 14:37:29.000000000 +0200
32473 +++ lighttpd-1.4.12/src/mod_secure_download.c   2006-07-11 21:23:39.000000000 +0300
32474 @@ -25,7 +25,7 @@
32475  #ifdef USE_OPENSSL
32476  #define IN const
32477  #else
32478 -#define IN 
32479 +#define IN
32480  #endif
32481  #define OUT
32482  
32483 @@ -36,28 +36,28 @@
32484         buffer *doc_root;
32485         buffer *secret;
32486         buffer *uri_prefix;
32487 -       
32488 +
32489         unsigned short timeout;
32490  } plugin_config;
32491  
32492  typedef struct {
32493         PLUGIN_DATA;
32494 -       
32495 +
32496         buffer *md5;
32497 -       
32498 +
32499         plugin_config **config_storage;
32500 -       
32501 -       plugin_config conf; 
32502 +
32503 +       plugin_config conf;
32504  } plugin_data;
32505  
32506  /* init the plugin data */
32507  INIT_FUNC(mod_secdownload_init) {
32508         plugin_data *p;
32509 -       
32510 +
32511         p = calloc(1, sizeof(*p));
32512 -       
32513 +
32514         p->md5 = buffer_init();
32515 -       
32516 +
32517         return p;
32518  }
32519  
32520 @@ -65,27 +65,27 @@
32521  FREE_FUNC(mod_secdownload_free) {
32522         plugin_data *p = p_d;
32523         UNUSED(srv);
32524 -       
32525 +
32526         if (!p) return HANDLER_GO_ON;
32527 -       
32528 +
32529         if (p->config_storage) {
32530                 size_t i;
32531                 for (i = 0; i < srv->config_context->used; i++) {
32532                         plugin_config *s = p->config_storage[i];
32533 -                       
32534 +
32535                         buffer_free(s->secret);
32536                         buffer_free(s->doc_root);
32537                         buffer_free(s->uri_prefix);
32538 -                       
32539 +
32540                         free(s);
32541                 }
32542                 free(p->config_storage);
32543         }
32544 -       
32545 +
32546         buffer_free(p->md5);
32547 -       
32548 +
32549         free(p);
32550 -       
32551 +
32552         return HANDLER_GO_ON;
32553  }
32554  
32555 @@ -94,107 +94,103 @@
32556  SETDEFAULTS_FUNC(mod_secdownload_set_defaults) {
32557         plugin_data *p = p_d;
32558         size_t i = 0;
32559 -       
32560 -       config_values_t cv[] = { 
32561 +
32562 +       config_values_t cv[] = {
32563                 { "secdownload.secret",            NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
32564                 { "secdownload.document-root",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
32565                 { "secdownload.uri-prefix",        NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
32566                 { "secdownload.timeout",           NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 3 */
32567                 { NULL,                            NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
32568         };
32569 -       
32570 +
32571         if (!p) return HANDLER_ERROR;
32572 -       
32573 +
32574         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32575 -       
32576 +
32577         for (i = 0; i < srv->config_context->used; i++) {
32578                 plugin_config *s;
32579 -               
32580 +
32581                 s = calloc(1, sizeof(plugin_config));
32582                 s->secret        = buffer_init();
32583                 s->doc_root      = buffer_init();
32584                 s->uri_prefix    = buffer_init();
32585                 s->timeout       = 60;
32586 -               
32587 +
32588                 cv[0].destination = s->secret;
32589                 cv[1].destination = s->doc_root;
32590                 cv[2].destination = s->uri_prefix;
32591                 cv[3].destination = &(s->timeout);
32592 -               
32593 +
32594                 p->config_storage[i] = s;
32595 -       
32596 +
32597                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
32598                         return HANDLER_ERROR;
32599                 }
32600         }
32601 -       
32602 +
32603         return HANDLER_GO_ON;
32604  }
32605  
32606  /**
32607   * checks if the supplied string is a MD5 string
32608 - * 
32609 + *
32610   * @param str a possible MD5 string
32611   * @return if the supplied string is a valid MD5 string 1 is returned otherwise 0
32612   */
32613  
32614  int is_hex_len(const char *str, size_t len) {
32615         size_t i;
32616 -       
32617 +
32618         if (NULL == str) return 0;
32619 -       
32620 +
32621         for (i = 0; i < len && *str; i++, str++) {
32622                 /* illegal characters */
32623                 if (!((*str >= '0' && *str <= '9') ||
32624                       (*str >= 'a' && *str <= 'f') ||
32625 -                     (*str >= 'A' && *str <= 'F')) 
32626 +                     (*str >= 'A' && *str <= 'F'))
32627                     ) {
32628                         return 0;
32629                 }
32630         }
32631 -       
32632 +
32633         return i == len;
32634  }
32635  
32636 -#define PATCH(x) \
32637 -       p->conf.x = s->x;
32638  static int mod_secdownload_patch_connection(server *srv, connection *con, plugin_data *p) {
32639         size_t i, j;
32640         plugin_config *s = p->config_storage[0];
32641 -       
32642 -       PATCH(secret);
32643 -       PATCH(doc_root);
32644 -       PATCH(uri_prefix);
32645 -       PATCH(timeout);
32646 -       
32647 +
32648 +       PATCH_OPTION(secret);
32649 +       PATCH_OPTION(doc_root);
32650 +       PATCH_OPTION(uri_prefix);
32651 +       PATCH_OPTION(timeout);
32652 +
32653         /* skip the first, the global context */
32654         for (i = 1; i < srv->config_context->used; i++) {
32655                 data_config *dc = (data_config *)srv->config_context->data[i];
32656                 s = p->config_storage[i];
32657 -               
32658 +
32659                 /* condition didn't match */
32660                 if (!config_check_cond(srv, con, dc)) continue;
32661 -               
32662 +
32663                 /* merge config */
32664                 for (j = 0; j < dc->value->used; j++) {
32665                         data_unset *du = dc->value->data[j];
32666 -                       
32667 +
32668                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.secret"))) {
32669 -                               PATCH(secret);
32670 +                               PATCH_OPTION(secret);
32671                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.document-root"))) {
32672 -                               PATCH(doc_root);
32673 +                               PATCH_OPTION(doc_root);
32674                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.uri-prefix"))) {
32675 -                               PATCH(uri_prefix);
32676 +                               PATCH_OPTION(uri_prefix);
32677                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.timeout"))) {
32678 -                               PATCH(timeout);
32679 +                               PATCH_OPTION(timeout);
32680                         }
32681                 }
32682         }
32683 -       
32684 +
32685         return 0;
32686  }
32687 -#undef PATCH
32688 -
32689  
32690  URIHANDLER_FUNC(mod_secdownload_uri_handler) {
32691         plugin_data *p = p_d;
32692 @@ -203,88 +199,88 @@
32693         const char *rel_uri, *ts_str, *md5_str;
32694         time_t ts = 0;
32695         size_t i;
32696 -       
32697 +
32698         if (con->uri.path->used == 0) return HANDLER_GO_ON;
32699 -       
32700 +
32701         mod_secdownload_patch_connection(srv, con, p);
32702  
32703         if (buffer_is_empty(p->conf.uri_prefix)) return HANDLER_GO_ON;
32704 -       
32705 +
32706         if (buffer_is_empty(p->conf.secret)) {
32707                 log_error_write(srv, __FILE__, __LINE__, "s",
32708                                 "secdownload.secret has to be set");
32709                 return HANDLER_ERROR;
32710         }
32711 -       
32712 +
32713         if (buffer_is_empty(p->conf.doc_root)) {
32714                 log_error_write(srv, __FILE__, __LINE__, "s",
32715                                 "secdownload.document-root has to be set");
32716                 return HANDLER_ERROR;
32717         }
32718 -       
32719 -       /* 
32720 +
32721 +       /*
32722          *  /<uri-prefix>[a-f0-9]{32}/[a-f0-9]{8}/<rel-path>
32723          */
32724 -       
32725 +
32726         if (0 != strncmp(con->uri.path->ptr, p->conf.uri_prefix->ptr, p->conf.uri_prefix->used - 1)) return HANDLER_GO_ON;
32727 -       
32728 +
32729         md5_str = con->uri.path->ptr + p->conf.uri_prefix->used - 1;
32730 -       
32731 +
32732         if (!is_hex_len(md5_str, 32)) return HANDLER_GO_ON;
32733         if (*(md5_str + 32) != '/') return HANDLER_GO_ON;
32734 -       
32735 +
32736         ts_str = md5_str + 32 + 1;
32737 -       
32738 +
32739         if (!is_hex_len(ts_str, 8)) return HANDLER_GO_ON;
32740         if (*(ts_str + 8) != '/') return HANDLER_GO_ON;
32741 -       
32742 +
32743         for (i = 0; i < 8; i++) {
32744                 ts = (ts << 4) + hex2int(*(ts_str + i));
32745         }
32746 -       
32747 +
32748         /* timed-out */
32749 -       if (srv->cur_ts - ts > p->conf.timeout || 
32750 +       if (srv->cur_ts - ts > p->conf.timeout ||
32751             srv->cur_ts - ts < -p->conf.timeout) {
32752                 con->http_status = 408;
32753 -               
32754 +
32755                 return HANDLER_FINISHED;
32756         }
32757 -       
32758 +
32759         rel_uri = ts_str + 8;
32760 -       
32761 -       /* checking MD5 
32762 -        * 
32763 +
32764 +       /* checking MD5
32765 +        *
32766          * <secret><rel-path><timestamp-hex>
32767          */
32768 -       
32769 +
32770         buffer_copy_string_buffer(p->md5, p->conf.secret);
32771         buffer_append_string(p->md5, rel_uri);
32772         buffer_append_string_len(p->md5, ts_str, 8);
32773 -       
32774 +
32775         MD5_Init(&Md5Ctx);
32776         MD5_Update(&Md5Ctx, (unsigned char *)p->md5->ptr, p->md5->used - 1);
32777         MD5_Final(HA1, &Md5Ctx);
32778 -       
32779 +
32780         buffer_copy_string_hex(p->md5, (char *)HA1, 16);
32781 -       
32782 +
32783         if (0 != strncmp(md5_str, p->md5->ptr, 32)) {
32784                 con->http_status = 403;
32785 -               
32786 -               log_error_write(srv, __FILE__, __LINE__, "sss", 
32787 +
32788 +               log_error_write(srv, __FILE__, __LINE__, "sss",
32789                                 "md5 invalid:",
32790                                 md5_str, p->md5->ptr);
32791 -               
32792 +
32793                 return HANDLER_FINISHED;
32794         }
32795 -       
32796 +
32797         /* starting with the last / we should have relative-path to the docroot
32798          */
32799 -       
32800 +
32801         buffer_copy_string_buffer(con->physical.doc_root, p->conf.doc_root);
32802         buffer_copy_string(con->physical.rel_path, rel_uri);
32803         buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
32804         buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
32805 -       
32806 +
32807         return HANDLER_GO_ON;
32808  }
32809  
32810 @@ -293,13 +289,13 @@
32811  int mod_secdownload_plugin_init(plugin *p) {
32812         p->version     = LIGHTTPD_VERSION_ID;
32813         p->name        = buffer_init_string("secdownload");
32814 -       
32815 +
32816         p->init        = mod_secdownload_init;
32817         p->handle_physical  = mod_secdownload_uri_handler;
32818         p->set_defaults  = mod_secdownload_set_defaults;
32819         p->cleanup     = mod_secdownload_free;
32820 -       
32821 +
32822         p->data        = NULL;
32823 -       
32824 +
32825         return 0;
32826  }
32827 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_setenv.c lighttpd-1.4.12/src/mod_setenv.c
32828 --- lighttpd-1.4.11/src/mod_setenv.c    2006-01-14 20:33:12.000000000 +0200
32829 +++ lighttpd-1.4.12/src/mod_setenv.c    2006-07-11 21:23:40.000000000 +0300
32830 @@ -18,25 +18,25 @@
32831  typedef struct {
32832         array *request_header;
32833         array *response_header;
32834 -       
32835 +
32836         array *environment;
32837  } plugin_config;
32838  
32839  typedef struct {
32840         PLUGIN_DATA;
32841 -       
32842 +
32843         plugin_config **config_storage;
32844 -       
32845 -       plugin_config conf; 
32846 +
32847 +       plugin_config conf;
32848  } plugin_data;
32849  
32850  static handler_ctx * handler_ctx_init() {
32851         handler_ctx * hctx;
32852 -       
32853 +
32854         hctx = calloc(1, sizeof(*hctx));
32855 -       
32856 +
32857         hctx->handled = 0;
32858 -       
32859 +
32860         return hctx;
32861  }
32862  
32863 @@ -48,36 +48,36 @@
32864  /* init the plugin data */
32865  INIT_FUNC(mod_setenv_init) {
32866         plugin_data *p;
32867 -       
32868 +
32869         p = calloc(1, sizeof(*p));
32870 -       
32871 +
32872         return p;
32873  }
32874  
32875  /* detroy the plugin data */
32876  FREE_FUNC(mod_setenv_free) {
32877         plugin_data *p = p_d;
32878 -       
32879 +
32880         UNUSED(srv);
32881  
32882         if (!p) return HANDLER_GO_ON;
32883 -       
32884 +
32885         if (p->config_storage) {
32886                 size_t i;
32887                 for (i = 0; i < srv->config_context->used; i++) {
32888                         plugin_config *s = p->config_storage[i];
32889 -                       
32890 +
32891                         array_free(s->request_header);
32892                         array_free(s->response_header);
32893                         array_free(s->environment);
32894 -                       
32895 +
32896                         free(s);
32897                 }
32898                 free(p->config_storage);
32899         }
32900 -       
32901 +
32902         free(p);
32903 -       
32904 +
32905         return HANDLER_GO_ON;
32906  }
32907  
32908 @@ -86,86 +86,83 @@
32909  SETDEFAULTS_FUNC(mod_setenv_set_defaults) {
32910         plugin_data *p = p_d;
32911         size_t i = 0;
32912 -       
32913 -       config_values_t cv[] = { 
32914 +
32915 +       config_values_t cv[] = {
32916                 { "setenv.add-request-header",  NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
32917                 { "setenv.add-response-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
32918                 { "setenv.add-environment",     NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
32919                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
32920         };
32921 -       
32922 +
32923         if (!p) return HANDLER_ERROR;
32924 -       
32925 +
32926         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32927 -       
32928 +
32929         for (i = 0; i < srv->config_context->used; i++) {
32930                 plugin_config *s;
32931 -               
32932 +
32933                 s = calloc(1, sizeof(plugin_config));
32934                 s->request_header   = array_init();
32935                 s->response_header  = array_init();
32936                 s->environment      = array_init();
32937 -               
32938 +
32939                 cv[0].destination = s->request_header;
32940                 cv[1].destination = s->response_header;
32941                 cv[2].destination = s->environment;
32942 -               
32943 +
32944                 p->config_storage[i] = s;
32945 -       
32946 +
32947                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
32948                         return HANDLER_ERROR;
32949                 }
32950         }
32951 -       
32952 +
32953         return HANDLER_GO_ON;
32954  }
32955  
32956 -#define PATCH(x) \
32957 -       p->conf.x = s->x;
32958  static int mod_setenv_patch_connection(server *srv, connection *con, plugin_data *p) {
32959         size_t i, j;
32960         plugin_config *s = p->config_storage[0];
32961 -       
32962 -       PATCH(request_header);
32963 -       PATCH(response_header);
32964 -       PATCH(environment);
32965 -       
32966 +
32967 +       PATCH_OPTION(request_header);
32968 +       PATCH_OPTION(response_header);
32969 +       PATCH_OPTION(environment);
32970 +
32971         /* skip the first, the global context */
32972         for (i = 1; i < srv->config_context->used; i++) {
32973                 data_config *dc = (data_config *)srv->config_context->data[i];
32974                 s = p->config_storage[i];
32975 -               
32976 +
32977                 /* condition didn't match */
32978                 if (!config_check_cond(srv, con, dc)) continue;
32979 -               
32980 +
32981                 /* merge config */
32982                 for (j = 0; j < dc->value->used; j++) {
32983                         data_unset *du = dc->value->data[j];
32984 -                       
32985 +
32986                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-request-header"))) {
32987 -                               PATCH(request_header);
32988 +                               PATCH_OPTION(request_header);
32989                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-response-header"))) {
32990 -                               PATCH(response_header);
32991 +                               PATCH_OPTION(response_header);
32992                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-environment"))) {
32993 -                               PATCH(environment);
32994 +                               PATCH_OPTION(environment);
32995                         }
32996                 }
32997         }
32998 -       
32999 +
33000         return 0;
33001  }
33002 -#undef PATCH
33003  
33004  URIHANDLER_FUNC(mod_setenv_uri_handler) {
33005         plugin_data *p = p_d;
33006         size_t k;
33007         handler_ctx *hctx;
33008 -       
33009 +
33010         if (con->plugin_ctx[p->id]) {
33011                 hctx = con->plugin_ctx[p->id];
33012         } else {
33013                 hctx = handler_ctx_init();
33014 -                               
33015 +
33016                 con->plugin_ctx[p->id] = hctx;
33017         }
33018  
33019 @@ -180,52 +177,52 @@
33020         for (k = 0; k < p->conf.request_header->used; k++) {
33021                 data_string *ds = (data_string *)p->conf.request_header->data[k];
33022                 data_string *ds_dst;
33023 -               
33024 +
33025                 if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
33026                         ds_dst = data_string_init();
33027                 }
33028 -               
33029 +
33030                 buffer_copy_string_buffer(ds_dst->key, ds->key);
33031                 buffer_copy_string_buffer(ds_dst->value, ds->value);
33032 -               
33033 +
33034                 array_insert_unique(con->request.headers, (data_unset *)ds_dst);
33035         }
33036 -       
33037 +
33038         for (k = 0; k < p->conf.environment->used; k++) {
33039                 data_string *ds = (data_string *)p->conf.environment->data[k];
33040                 data_string *ds_dst;
33041 -               
33042 +
33043                 if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
33044                         ds_dst = data_string_init();
33045                 }
33046 -               
33047 +
33048                 buffer_copy_string_buffer(ds_dst->key, ds->key);
33049                 buffer_copy_string_buffer(ds_dst->value, ds->value);
33050 -               
33051 +
33052                 array_insert_unique(con->environment, (data_unset *)ds_dst);
33053         }
33054 -       
33055 +
33056         for (k = 0; k < p->conf.response_header->used; k++) {
33057                 data_string *ds = (data_string *)p->conf.response_header->data[k];
33058 -               
33059 +
33060                 response_header_insert(srv, con, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
33061         }
33062 -       
33063 +
33064         /* not found */
33065         return HANDLER_GO_ON;
33066  }
33067  
33068  REQUESTDONE_FUNC(mod_setenv_reset) {
33069         plugin_data *p = p_d;
33070 -       
33071 +
33072         UNUSED(srv);
33073 -       
33074 +
33075         if (con->plugin_ctx[p->id]) {
33076                 handler_ctx_free(con->plugin_ctx[p->id]);
33077                 con->plugin_ctx[p->id] = NULL;
33078         }
33079  
33080 -       return HANDLER_GO_ON;   
33081 +       return HANDLER_GO_ON;
33082  }
33083  
33084  /* this function is called at dlopen() time and inits the callbacks */
33085 @@ -233,15 +230,15 @@
33086  int mod_setenv_plugin_init(plugin *p) {
33087         p->version     = LIGHTTPD_VERSION_ID;
33088         p->name        = buffer_init_string("setenv");
33089 -       
33090 +
33091         p->init        = mod_setenv_init;
33092         p->handle_uri_clean  = mod_setenv_uri_handler;
33093         p->set_defaults  = mod_setenv_set_defaults;
33094         p->cleanup     = mod_setenv_free;
33095 -       
33096 +
33097         p->handle_request_done  = mod_setenv_reset;
33098  
33099         p->data        = NULL;
33100 -       
33101 +
33102         return 0;
33103  }
33104 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_simple_vhost.c lighttpd-1.4.12/src/mod_simple_vhost.c
33105 --- lighttpd-1.4.11/src/mod_simple_vhost.c      2005-11-18 15:16:13.000000000 +0200
33106 +++ lighttpd-1.4.12/src/mod_simple_vhost.c      2006-07-11 21:23:40.000000000 +0300
33107 @@ -10,6 +10,8 @@
33108  
33109  #include "plugin.h"
33110  
33111 +#include "sys-files.h"
33112 +
33113  #ifdef HAVE_CONFIG_H
33114  #include "config.h"
33115  #endif
33116 @@ -18,7 +20,7 @@
33117         buffer *server_root;
33118         buffer *default_host;
33119         buffer *document_root;
33120 -       
33121 +
33122         buffer *docroot_cache_key;
33123         buffer *docroot_cache_value;
33124         buffer *docroot_cache_servername;
33125 @@ -28,138 +30,138 @@
33126  
33127  typedef struct {
33128         PLUGIN_DATA;
33129 -       
33130 +
33131         buffer *doc_root;
33132 -       
33133 +
33134         plugin_config **config_storage;
33135 -       plugin_config conf; 
33136 +       plugin_config conf;
33137  } plugin_data;
33138  
33139  INIT_FUNC(mod_simple_vhost_init) {
33140         plugin_data *p;
33141 -       
33142 +
33143         p = calloc(1, sizeof(*p));
33144 -       
33145 +
33146         p->doc_root = buffer_init();
33147 -       
33148 +
33149         return p;
33150  }
33151  
33152  FREE_FUNC(mod_simple_vhost_free) {
33153         plugin_data *p = p_d;
33154 -       
33155 +
33156         UNUSED(srv);
33157  
33158         if (!p) return HANDLER_GO_ON;
33159 -       
33160 +
33161         if (p->config_storage) {
33162                 size_t i;
33163                 for (i = 0; i < srv->config_context->used; i++) {
33164                         plugin_config *s = p->config_storage[i];
33165 -                       
33166 +
33167                         buffer_free(s->document_root);
33168                         buffer_free(s->default_host);
33169                         buffer_free(s->server_root);
33170 -                       
33171 +
33172                         buffer_free(s->docroot_cache_key);
33173                         buffer_free(s->docroot_cache_value);
33174                         buffer_free(s->docroot_cache_servername);
33175 -                       
33176 +
33177                         free(s);
33178                 }
33179 -       
33180 +
33181                 free(p->config_storage);
33182         }
33183 -       
33184 +
33185         buffer_free(p->doc_root);
33186 -       
33187 +
33188         free(p);
33189 -       
33190 +
33191         return HANDLER_GO_ON;
33192  }
33193  
33194  SETDEFAULTS_FUNC(mod_simple_vhost_set_defaults) {
33195         plugin_data *p = p_d;
33196         size_t i;
33197 -       
33198 -       config_values_t cv[] = { 
33199 +
33200 +       config_values_t cv[] = {
33201                 { "simple-vhost.server-root",       NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
33202                 { "simple-vhost.default-host",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
33203                 { "simple-vhost.document-root",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
33204                 { "simple-vhost.debug",             NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
33205                 { NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33206         };
33207 -       
33208 +
33209         if (!p) return HANDLER_ERROR;
33210 -       
33211 +
33212         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33213 -       
33214 +
33215         for (i = 0; i < srv->config_context->used; i++) {
33216                 plugin_config *s;
33217 -               
33218 +
33219                 s = calloc(1, sizeof(plugin_config));
33220 -               
33221 +
33222                 s->server_root = buffer_init();
33223                 s->default_host = buffer_init();
33224                 s->document_root = buffer_init();
33225 -               
33226 +
33227                 s->docroot_cache_key = buffer_init();
33228                 s->docroot_cache_value = buffer_init();
33229                 s->docroot_cache_servername = buffer_init();
33230  
33231                 s->debug = 0;
33232 -               
33233 +
33234                 cv[0].destination = s->server_root;
33235                 cv[1].destination = s->default_host;
33236                 cv[2].destination = s->document_root;
33237                 cv[3].destination = &(s->debug);
33238 -               
33239 -               
33240 +
33241 +
33242                 p->config_storage[i] = s;
33243 -               
33244 +
33245                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
33246                         return HANDLER_ERROR;
33247                 }
33248         }
33249 -       
33250 +
33251         return HANDLER_GO_ON;
33252  }
33253  
33254  static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer *out, buffer *host) {
33255         stat_cache_entry *sce = NULL;
33256 -       
33257 +
33258         buffer_prepare_copy(out, 128);
33259  
33260         if (p->conf.server_root->used) {
33261                 buffer_copy_string_buffer(out, p->conf.server_root);
33262 -               
33263 +
33264                 if (host->used) {
33265                         /* a hostname has to start with a alpha-numerical character
33266                          * and must not contain a slash "/"
33267                          */
33268                         char *dp;
33269 -                       
33270 -                       BUFFER_APPEND_SLASH(out);
33271 -                       
33272 +
33273 +                       PATHNAME_APPEND_SLASH(out);
33274 +
33275                         if (NULL == (dp = strchr(host->ptr, ':'))) {
33276                                 buffer_append_string_buffer(out, host);
33277                         } else {
33278                                 buffer_append_string_len(out, host->ptr, dp - host->ptr);
33279                         }
33280                 }
33281 -               BUFFER_APPEND_SLASH(out);
33282 -               
33283 +               PATHNAME_APPEND_SLASH(out);
33284 +
33285                 if (p->conf.document_root->used > 2 && p->conf.document_root->ptr[0] == '/') {
33286                         buffer_append_string_len(out, p->conf.document_root->ptr + 1, p->conf.document_root->used - 2);
33287                 } else {
33288                         buffer_append_string_buffer(out, p->conf.document_root);
33289 -                       BUFFER_APPEND_SLASH(out);
33290 +                       PATHNAME_APPEND_SLASH(out);
33291                 }
33292         } else {
33293                 buffer_copy_string_buffer(out, con->conf.document_root);
33294 -               BUFFER_APPEND_SLASH(out);
33295 +               PATHNAME_APPEND_SLASH(out);
33296         }
33297 -       
33298 +
33299         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, out, &sce)) {
33300                 if (p->conf.debug) {
33301                         log_error_write(srv, __FILE__, __LINE__, "sb",
33302 @@ -169,57 +171,53 @@
33303         } else if (!S_ISDIR(sce->st.st_mode)) {
33304                 return -1;
33305         }
33306 -       
33307 +
33308         return 0;
33309  }
33310  
33311 -
33312 -#define PATCH(x) \
33313 -       p->conf.x = s->x;
33314  static int mod_simple_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
33315         size_t i, j;
33316         plugin_config *s = p->config_storage[0];
33317 -       
33318 -       PATCH(server_root);
33319 -       PATCH(default_host);
33320 -       PATCH(document_root);
33321 -       
33322 -       PATCH(docroot_cache_key);
33323 -       PATCH(docroot_cache_value);
33324 -       PATCH(docroot_cache_servername);
33325  
33326 -       PATCH(debug);
33327 -       
33328 +       PATCH_OPTION(server_root);
33329 +       PATCH_OPTION(default_host);
33330 +       PATCH_OPTION(document_root);
33331 +
33332 +       PATCH_OPTION(docroot_cache_key);
33333 +       PATCH_OPTION(docroot_cache_value);
33334 +       PATCH_OPTION(docroot_cache_servername);
33335 +
33336 +       PATCH_OPTION(debug);
33337 +
33338         /* skip the first, the global context */
33339         for (i = 1; i < srv->config_context->used; i++) {
33340                 data_config *dc = (data_config *)srv->config_context->data[i];
33341                 s = p->config_storage[i];
33342 -               
33343 +
33344                 /* condition didn't match */
33345                 if (!config_check_cond(srv, con, dc)) continue;
33346 -               
33347 +
33348                 /* merge config */
33349                 for (j = 0; j < dc->value->used; j++) {
33350                         data_unset *du = dc->value->data[j];
33351 -                       
33352 +
33353                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.server-root"))) {
33354 -                               PATCH(server_root);
33355 -                               PATCH(docroot_cache_key);
33356 -                               PATCH(docroot_cache_value);
33357 -                               PATCH(docroot_cache_servername);
33358 +                               PATCH_OPTION(server_root);
33359 +                               PATCH_OPTION(docroot_cache_key);
33360 +                               PATCH_OPTION(docroot_cache_value);
33361 +                               PATCH_OPTION(docroot_cache_servername);
33362                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.default-host"))) {
33363 -                               PATCH(default_host);
33364 +                               PATCH_OPTION(default_host);
33365                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.document-root"))) {
33366 -                               PATCH(document_root);
33367 +                               PATCH_OPTION(document_root);
33368                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.debug"))) {
33369 -                               PATCH(debug);
33370 +                               PATCH_OPTION(debug);
33371                         }
33372                 }
33373         }
33374 -       
33375 +
33376         return 0;
33377  }
33378 -#undef PATCH
33379  
33380  static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_data) {
33381         plugin_data *p = p_data;
33382 @@ -227,12 +225,12 @@
33383         /*
33384          * cache the last successfull translation from hostname (authority) to docroot
33385          * - this saves us a stat() call
33386 -        * 
33387 +        *
33388          */
33389 -       
33390 +
33391         mod_simple_vhost_patch_connection(srv, con, p);
33392 -       
33393 -       if (p->conf.docroot_cache_key->used && 
33394 +
33395 +       if (p->conf.docroot_cache_key->used &&
33396             con->uri.authority->used &&
33397             buffer_is_equal(p->conf.docroot_cache_key, con->uri.authority)) {
33398                 /* cache hit */
33399 @@ -243,8 +241,8 @@
33400                 if ((con->uri.authority->used == 0) ||
33401                     build_doc_root(srv, con, p, p->doc_root, con->uri.authority)) {
33402                         /* not found, fallback the default-host */
33403 -                       if (build_doc_root(srv, con, p, 
33404 -                                          p->doc_root, 
33405 +                       if (build_doc_root(srv, con, p,
33406 +                                          p->doc_root,
33407                                            p->conf.default_host)) {
33408                                 return HANDLER_GO_ON;
33409                         } else {
33410 @@ -253,15 +251,15 @@
33411                 } else {
33412                         buffer_copy_string_buffer(con->server_name, con->uri.authority);
33413                 }
33414 -               
33415 +
33416                 /* copy to cache */
33417                 buffer_copy_string_buffer(p->conf.docroot_cache_key,        con->uri.authority);
33418                 buffer_copy_string_buffer(p->conf.docroot_cache_value,      p->doc_root);
33419                 buffer_copy_string_buffer(p->conf.docroot_cache_servername, con->server_name);
33420 -               
33421 +
33422                 buffer_copy_string_buffer(con->physical.doc_root, p->doc_root);
33423         }
33424 -       
33425 +
33426         return HANDLER_GO_ON;
33427  }
33428  
33429 @@ -269,13 +267,13 @@
33430  int mod_simple_vhost_plugin_init(plugin *p) {
33431         p->version     = LIGHTTPD_VERSION_ID;
33432         p->name        = buffer_init_string("simple_vhost");
33433 -       
33434 +
33435         p->init        = mod_simple_vhost_init;
33436         p->set_defaults = mod_simple_vhost_set_defaults;
33437         p->handle_docroot  = mod_simple_vhost_docroot;
33438         p->cleanup     = mod_simple_vhost_free;
33439 -       
33440 +
33441         p->data        = NULL;
33442 -       
33443 +
33444         return 0;
33445  }
33446 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_skeleton.c lighttpd-1.4.12/src/mod_skeleton.c
33447 --- lighttpd-1.4.11/src/mod_skeleton.c  2005-10-02 18:30:51.000000000 +0300
33448 +++ lighttpd-1.4.12/src/mod_skeleton.c  2006-07-11 21:23:40.000000000 +0300
33449 @@ -14,13 +14,13 @@
33450  
33451  /**
33452   * this is a skeleton for a lighttpd plugin
33453 - * 
33454 + *
33455   * just replaces every occurance of 'skeleton' by your plugin name
33456 - * 
33457 + *
33458   * e.g. in vim:
33459 - * 
33460 + *
33461   *   :%s/skeleton/myhandler/
33462 - * 
33463 + *
33464   */
33465  
33466  
33467 @@ -33,12 +33,12 @@
33468  
33469  typedef struct {
33470         PLUGIN_DATA;
33471 -       
33472 +
33473         buffer *match_buf;
33474 -       
33475 +
33476         plugin_config **config_storage;
33477 -       
33478 -       plugin_config conf; 
33479 +
33480 +       plugin_config conf;
33481  } plugin_data;
33482  
33483  typedef struct {
33484 @@ -47,36 +47,36 @@
33485  
33486  static handler_ctx * handler_ctx_init() {
33487         handler_ctx * hctx;
33488 -       
33489 +
33490         hctx = calloc(1, sizeof(*hctx));
33491 -       
33492 +
33493         return hctx;
33494  }
33495  
33496  static void handler_ctx_free(handler_ctx *hctx) {
33497 -       
33498 +
33499         free(hctx);
33500  }
33501  
33502  /* init the plugin data */
33503  INIT_FUNC(mod_skeleton_init) {
33504         plugin_data *p;
33505 -       
33506 +
33507         p = calloc(1, sizeof(*p));
33508 -       
33509 +
33510         p->match_buf = buffer_init();
33511 -       
33512 +
33513         return p;
33514  }
33515  
33516  /* detroy the plugin data */
33517  FREE_FUNC(mod_skeleton_free) {
33518         plugin_data *p = p_d;
33519 -       
33520 +
33521         UNUSED(srv);
33522  
33523         if (!p) return HANDLER_GO_ON;
33524 -       
33525 +
33526         if (p->config_storage) {
33527                 size_t i;
33528  
33529 @@ -84,18 +84,18 @@
33530                         plugin_config *s = p->config_storage[i];
33531  
33532                         if (!s) continue;
33533 -                       
33534 +
33535                         array_free(s->match);
33536 -                       
33537 +
33538                         free(s);
33539                 }
33540                 free(p->config_storage);
33541         }
33542 -       
33543 +
33544         buffer_free(p->match_buf);
33545 -       
33546 +
33547         free(p);
33548 -       
33549 +
33550         return HANDLER_GO_ON;
33551  }
33552  
33553 @@ -104,91 +104,88 @@
33554  SETDEFAULTS_FUNC(mod_skeleton_set_defaults) {
33555         plugin_data *p = p_d;
33556         size_t i = 0;
33557 -       
33558 -       config_values_t cv[] = { 
33559 +
33560 +       config_values_t cv[] = {
33561                 { "skeleton.array",             NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
33562                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33563         };
33564 -       
33565 +
33566         if (!p) return HANDLER_ERROR;
33567 -       
33568 +
33569         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33570 -       
33571 +
33572         for (i = 0; i < srv->config_context->used; i++) {
33573                 plugin_config *s;
33574 -               
33575 +
33576                 s = calloc(1, sizeof(plugin_config));
33577                 s->match    = array_init();
33578 -               
33579 +
33580                 cv[0].destination = s->match;
33581 -               
33582 +
33583                 p->config_storage[i] = s;
33584 -       
33585 +
33586                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
33587                         return HANDLER_ERROR;
33588                 }
33589         }
33590 -       
33591 +
33592         return HANDLER_GO_ON;
33593  }
33594  
33595 -#define PATCH(x) \
33596 -       p->conf.x = s->x;
33597  static int mod_skeleton_patch_connection(server *srv, connection *con, plugin_data *p) {
33598         size_t i, j;
33599         plugin_config *s = p->config_storage[0];
33600 -       
33601 -       PATCH(match);
33602 -       
33603 +
33604 +       PATCH_OPTION(match);
33605 +
33606         /* skip the first, the global context */
33607         for (i = 1; i < srv->config_context->used; i++) {
33608                 data_config *dc = (data_config *)srv->config_context->data[i];
33609                 s = p->config_storage[i];
33610 -               
33611 +
33612                 /* condition didn't match */
33613                 if (!config_check_cond(srv, con, dc)) continue;
33614 -               
33615 +
33616                 /* merge config */
33617                 for (j = 0; j < dc->value->used; j++) {
33618                         data_unset *du = dc->value->data[j];
33619 -                       
33620 +
33621                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("skeleton.array"))) {
33622 -                               PATCH(match);
33623 +                               PATCH_OPTION(match);
33624                         }
33625                 }
33626         }
33627 -       
33628 +
33629         return 0;
33630  }
33631 -#undef PATCH
33632  
33633  URIHANDLER_FUNC(mod_skeleton_uri_handler) {
33634         plugin_data *p = p_d;
33635         int s_len;
33636         size_t k, i;
33637 -       
33638 +
33639         UNUSED(srv);
33640  
33641         if (con->uri.path->used == 0) return HANDLER_GO_ON;
33642 -       
33643 +
33644         mod_skeleton_patch_connection(srv, con, p);
33645  
33646         s_len = con->uri.path->used - 1;
33647 -       
33648 +
33649         for (k = 0; k < p->conf.match->used; k++) {
33650                 data_string *ds = (data_string *)p->conf.match->data[k];
33651                 int ct_len = ds->value->used - 1;
33652 -               
33653 +
33654                 if (ct_len > s_len) continue;
33655                 if (ds->value->used == 0) continue;
33656 -               
33657 +
33658                 if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
33659                         con->http_status = 403;
33660 -       
33661 +
33662                         return HANDLER_FINISHED;
33663                 }
33664         }
33665 -       
33666 +
33667         /* not found */
33668         return HANDLER_GO_ON;
33669  }
33670 @@ -198,13 +195,13 @@
33671  int mod_skeleton_plugin_init(plugin *p) {
33672         p->version     = LIGHTTPD_VERSION_ID;
33673         p->name        = buffer_init_string("skeleton");
33674 -       
33675 +
33676         p->init        = mod_skeleton_init;
33677         p->handle_uri_clean  = mod_skeleton_uri_handler;
33678         p->set_defaults  = mod_skeleton_set_defaults;
33679         p->cleanup     = mod_skeleton_free;
33680 -       
33681 +
33682         p->data        = NULL;
33683 -       
33684 +
33685         return 0;
33686  }
33687 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_sql_vhost_core.c lighttpd-1.4.12/src/mod_sql_vhost_core.c
33688 --- lighttpd-1.4.11/src/mod_sql_vhost_core.c    1970-01-01 03:00:00.000000000 +0300
33689 +++ lighttpd-1.4.12/src/mod_sql_vhost_core.c    2006-07-11 21:23:40.000000000 +0300
33690 @@ -0,0 +1,209 @@
33691 +#include <stdio.h>
33692 +#include <errno.h>
33693 +#include <fcntl.h>
33694 +#include <string.h>
33695 +
33696 +#ifdef HAVE_CONFIG_H
33697 +#include "config.h"
33698 +#endif
33699 +
33700 +#include "plugin.h"
33701 +#include "log.h"
33702 +
33703 +#include "stat_cache.h"
33704 +
33705 +#include "mod_sql_vhost_core.h"
33706 +
33707 +#define plugin_data mod_sql_vhost_core_plugin_data
33708 +#define plugin_config mod_sql_vhost_core_plugin_config
33709 +
33710 +/* init the plugin data */
33711 +INIT_FUNC(mod_sql_vhost_core_init) {
33712 +       plugin_data *p;
33713 +
33714 +       p = calloc(1, sizeof(*p));
33715 +
33716 +       p->docroot = buffer_init();
33717 +       p->host = buffer_init();
33718 +
33719 +       return p;
33720 +}
33721 +
33722 +/* cleanup the plugin data */
33723 +SERVER_FUNC(mod_sql_vhost_core_cleanup) {
33724 +       plugin_data *p = p_d;
33725 +
33726 +       UNUSED(srv);
33727 +
33728 +       if (!p) return HANDLER_GO_ON;
33729 +
33730 +       if (p->config_storage) {
33731 +               size_t i;
33732 +               for (i = 0; i < srv->config_context->used; i++) {
33733 +                       plugin_config *s = p->config_storage[i];
33734 +
33735 +                       if (!s) continue;
33736 +
33737 +                       buffer_free(s->db);
33738 +                       buffer_free(s->user);
33739 +                       buffer_free(s->pass);
33740 +                       buffer_free(s->sock);
33741 +                       buffer_free(s->backend);
33742 +
33743 +                       free(s);
33744 +               }
33745 +               free(p->config_storage);
33746 +       }
33747 +       buffer_free(p->docroot);
33748 +       buffer_free(p->host);
33749 +
33750 +       free(p);
33751 +
33752 +       return HANDLER_GO_ON;
33753 +}
33754 +
33755 +/* set configuration values */
33756 +SERVER_FUNC(mod_sql_vhost_core_set_defaults) {
33757 +       plugin_data *p = p_d;
33758 +
33759 +       size_t i = 0;
33760 +
33761 +       config_values_t cv[] = {
33762 +               { "sql-vhost.db",       NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 0 * e.g. vhost */
33763 +               { "sql-vhost.user",     NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 1 * lighty */
33764 +               { "sql-vhost.pass",     NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 2 * secrect */
33765 +               { "sql-vhost.sock",     NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 3 * /tmp/mysql.sock */
33766 +               { "sql-vhost.select-vhost", NULL, T_CONFIG_STRING,      T_CONFIG_SCOPE_SERVER }, /* 4 * SELECT ... FROM hosts WHERE hostname = ? */
33767 +               { "sql-vhost.hostname", NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 5 * 127.0.0.1 */
33768 +               { "sql-vhost.port",     NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_SERVER }, /* 6 * 3306 */
33769 +               { "sql-vhost.backend",  NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 7 * mysql */
33770 +
33771 +               /* backward compat */
33772 +               { "mysql-vhost.db",     NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 8 == 0 */
33773 +               { "mysql-vhost.user",   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 9 == 1 */
33774 +               { "mysql-vhost.pass",   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 10 == 2 */
33775 +               { "mysql-vhost.sock",   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 11 == 3 */
33776 +               { "mysql-vhost.sql",    NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER }, /* 12 == 4 */
33777 +               { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER }, /* 13 == 5 */
33778 +               { "mysql-vhost.port",   NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_SERVER }, /* 14 == 6 */
33779 +
33780 +                { NULL,                        NULL, T_CONFIG_UNSET,   T_CONFIG_SCOPE_UNSET }
33781 +        };
33782 +
33783 +       p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33784 +
33785 +       for (i = 0; i < srv->config_context->used; i++) {
33786 +               plugin_config *s;
33787 +
33788 +               s = calloc(1, sizeof(plugin_config));
33789 +               s->db = buffer_init();
33790 +               s->user = buffer_init();
33791 +               s->pass = buffer_init();
33792 +               s->sock = buffer_init();
33793 +               s->hostname = buffer_init();
33794 +               s->backend = buffer_init();
33795 +               s->port   = 0;               /* default port for mysql */
33796 +               s->select_vhost = buffer_init();
33797 +               s->backend_data = NULL;
33798 +
33799 +               cv[0].destination = s->db;
33800 +               cv[1].destination = s->user;
33801 +               cv[2].destination = s->pass;
33802 +               cv[3].destination = s->sock;
33803 +               cv[4].destination = s->select_vhost;
33804 +               cv[5].destination = s->hostname;
33805 +               cv[6].destination = &(s->port);
33806 +               cv[7].destination = s->backend;
33807 +
33808 +               /* backend compat */
33809 +               cv[8].destination = cv[0].destination;
33810 +               cv[9].destination = cv[1].destination;
33811 +               cv[10].destination = cv[2].destination;
33812 +               cv[11].destination = cv[3].destination;
33813 +               cv[12].destination = cv[4].destination;
33814 +               cv[13].destination = cv[5].destination;
33815 +               cv[14].destination = cv[6].destination;
33816 +
33817 +               p->config_storage[i] = s;
33818 +
33819 +               if (config_insert_values_global(srv,
33820 +                       ((data_config *)srv->config_context->data[i])->value,
33821 +                       cv)) return HANDLER_ERROR;
33822 +
33823 +               /* we only parse the config, the backend plugin will patch itself into the plugin-struct */
33824 +       }
33825 +
33826 +        return HANDLER_GO_ON;
33827 +}
33828 +
33829 +static int mod_sql_vhost_core_patch_connection(server *srv, connection *con, plugin_data *p) {
33830 +       size_t i;
33831 +       plugin_config *s = p->config_storage[0];
33832 +
33833 +       PATCH_OPTION(backend_data);
33834 +       PATCH_OPTION(get_vhost);
33835 +
33836 +       /* skip the first, the global context */
33837 +       for (i = 1; i < srv->config_context->used; i++) {
33838 +               data_config *dc = (data_config *)srv->config_context->data[i];
33839 +               s = p->config_storage[i];
33840 +
33841 +               /* condition didn't match */
33842 +               if (!config_check_cond(srv, con, dc)) continue;
33843 +
33844 +               if (s->backend_data) {
33845 +                       PATCH_OPTION(backend_data);
33846 +                       PATCH_OPTION(get_vhost);
33847 +               }
33848 +       }
33849 +
33850 +       return 0;
33851 +}
33852 +
33853 +/* handle document root request */
33854 +CONNECTION_FUNC(mod_sql_vhost_core_handle_docroot) {
33855 +       plugin_data *p = p_d;
33856 +       stat_cache_entry *sce;
33857 +
33858 +       /* no host specified? */
33859 +       if (!con->uri.authority->used) return HANDLER_GO_ON;
33860 +
33861 +       mod_sql_vhost_core_patch_connection(srv, con, p);
33862 +
33863 +       /* do we have backend ? */
33864 +       if (!p->conf.get_vhost) return HANDLER_GO_ON;
33865 +
33866 +       /* ask the backend for the data */
33867 +       if (0 != p->conf.get_vhost(srv, con, p->conf.backend_data, p->docroot, p->host)) {
33868 +               return HANDLER_GO_ON;
33869 +       }
33870 +
33871 +       if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->docroot, &sce)) {
33872 +               log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->docroot);
33873 +               return HANDLER_GO_ON;
33874 +       }
33875 +        if (!S_ISDIR(sce->st.st_mode)) {
33876 +               log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->docroot);
33877 +               return HANDLER_GO_ON;
33878 +       }
33879 +
33880 +       buffer_copy_string_buffer(con->server_name, p->host);
33881 +       buffer_copy_string_buffer(con->physical.doc_root, p->docroot);
33882 +
33883 +       return HANDLER_GO_ON;
33884 +}
33885 +
33886 +/* this function is called at dlopen() time and inits the callbacks */
33887 +int mod_sql_vhost_core_plugin_init(plugin *p) {
33888 +       p->version     = LIGHTTPD_VERSION_ID;
33889 +       p->name                         = buffer_init_string("mod_sql_vhost_core");
33890 +
33891 +       p->init                         = mod_sql_vhost_core_init;
33892 +       p->cleanup                      = mod_sql_vhost_core_cleanup;
33893 +
33894 +       p->set_defaults                 = mod_sql_vhost_core_set_defaults;
33895 +       p->handle_docroot               = mod_sql_vhost_core_handle_docroot;
33896 +
33897 +       return 0;
33898 +}
33899 +
33900 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_sql_vhost_core.h lighttpd-1.4.12/src/mod_sql_vhost_core.h
33901 --- lighttpd-1.4.11/src/mod_sql_vhost_core.h    1970-01-01 03:00:00.000000000 +0300
33902 +++ lighttpd-1.4.12/src/mod_sql_vhost_core.h    2006-07-11 21:23:40.000000000 +0300
33903 @@ -0,0 +1,49 @@
33904 +#ifndef _MOD_SQL_VHOST_CORE_H_
33905 +#define _MOD_SQL_VHOST_CORE_H_
33906 +
33907 +#include "buffer.h"
33908 +#include "plugin.h"
33909 +
33910 +#define SQLVHOST_BACKEND_GETVHOST_PARAMS \
33911 +       (server *srv, connection *con, void *p_d, buffer *docroot, buffer *host)
33912 +
33913 +#define SQLVHOST_BACKEND_GETVHOST_RETVAL handler_t
33914 +
33915 +#define SQLVHOST_BACKEND_GETVHOST(name) \
33916 +       SQLVHOST_BACKEND_GETVHOST_RETVAL name SQLVHOST_BACKEND_GETVHOST_PARAMS
33917 +
33918 +#define SQLVHOST_BACKEND_GETVHOST_PTR(name) \
33919 +       SQLVHOST_BACKEND_GETVHOST_RETVAL (* name)SQLVHOST_BACKEND_GETVHOST_PARAMS
33920 +
33921 +typedef struct {
33922 +       buffer  *db;
33923 +       buffer  *user;
33924 +       buffer  *pass;
33925 +       buffer  *sock;
33926 +
33927 +       buffer  *hostname;
33928 +       unsigned short port;
33929 +
33930 +       buffer  *backend;
33931 +       void *backend_data;
33932 +
33933 +       buffer *select_vhost;
33934 +
33935 +       SQLVHOST_BACKEND_GETVHOST_PTR(get_vhost);
33936 +} mod_sql_vhost_core_plugin_config;
33937 +
33938 +/* global plugin data */
33939 +typedef struct {
33940 +       PLUGIN_DATA;
33941 +
33942 +       buffer  *docroot;
33943 +       buffer  *host;
33944 +
33945 +       mod_sql_vhost_core_plugin_config **config_storage;
33946 +
33947 +       mod_sql_vhost_core_plugin_config conf;
33948 +} mod_sql_vhost_core_plugin_data;
33949 +
33950 +
33951 +
33952 +#endif
33953 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_ssi.c lighttpd-1.4.12/src/mod_ssi.c
33954 --- lighttpd-1.4.11/src/mod_ssi.c       2006-03-04 17:09:48.000000000 +0200
33955 +++ lighttpd-1.4.12/src/mod_ssi.c       2006-07-11 21:23:40.000000000 +0300
33956 @@ -6,7 +6,6 @@
33957  #include <string.h>
33958  #include <errno.h>
33959  #include <time.h>
33960 -#include <unistd.h>
33961  
33962  #include "base.h"
33963  #include "log.h"
33964 @@ -23,6 +22,8 @@
33965  #include "inet_ntop_cache.h"
33966  
33967  #include "sys-socket.h"
33968 +#include "sys-strings.h"
33969 +#include "sys-files.h"
33970  
33971  #ifdef HAVE_PWD_H
33972  #include <pwd.h>
33973 @@ -39,15 +40,15 @@
33974  /* init the plugin data */
33975  INIT_FUNC(mod_ssi_init) {
33976         plugin_data *p;
33977 -       
33978 +
33979         p = calloc(1, sizeof(*p));
33980 -       
33981 +
33982         p->timefmt = buffer_init();
33983         p->stat_fn = buffer_init();
33984 -       
33985 +
33986         p->ssi_vars = array_init();
33987         p->ssi_cgi_env = array_init();
33988 -       
33989 +
33990         return p;
33991  }
33992  
33993 @@ -55,21 +56,21 @@
33994  FREE_FUNC(mod_ssi_free) {
33995         plugin_data *p = p_d;
33996         UNUSED(srv);
33997 -       
33998 +
33999         if (!p) return HANDLER_GO_ON;
34000 -       
34001 +
34002         if (p->config_storage) {
34003                 size_t i;
34004                 for (i = 0; i < srv->config_context->used; i++) {
34005                         plugin_config *s = p->config_storage[i];
34006 -                       
34007 +
34008                         array_free(s->ssi_extension);
34009 -                       
34010 +
34011                         free(s);
34012                 }
34013                 free(p->config_storage);
34014         }
34015 -       
34016 +
34017         array_free(p->ssi_vars);
34018         array_free(p->ssi_cgi_env);
34019  #ifdef HAVE_PCRE_H
34020 @@ -77,9 +78,9 @@
34021  #endif
34022         buffer_free(p->timefmt);
34023         buffer_free(p->stat_fn);
34024 -       
34025 +
34026         free(p);
34027 -       
34028 +
34029         return HANDLER_GO_ON;
34030  }
34031  
34032 @@ -92,36 +93,36 @@
34033         const char *errptr;
34034         int erroff;
34035  #endif
34036 -       
34037 -       config_values_t cv[] = { 
34038 +
34039 +       config_values_t cv[] = {
34040                 { "ssi.extension",              NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
34041                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
34042         };
34043 -       
34044 +
34045         if (!p) return HANDLER_ERROR;
34046 -       
34047 +
34048         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
34049 -       
34050 +
34051         for (i = 0; i < srv->config_context->used; i++) {
34052                 plugin_config *s;
34053 -               
34054 +
34055                 s = calloc(1, sizeof(plugin_config));
34056                 s->ssi_extension  = array_init();
34057 -               
34058 +
34059                 cv[0].destination = s->ssi_extension;
34060 -               
34061 +
34062                 p->config_storage[i] = s;
34063 -       
34064 +
34065                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
34066                         return HANDLER_ERROR;
34067                 }
34068         }
34069 -       
34070 +
34071  #ifdef HAVE_PCRE_H
34072         /* allow 2 params */
34073         if (NULL == (p->ssi_regex = pcre_compile("<!--#([a-z]+)\\s+(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?-->", 0, &errptr, &erroff, NULL))) {
34074                 log_error_write(srv, __FILE__, __LINE__, "sds",
34075 -                               "ssi: pcre ", 
34076 +                               "ssi: pcre ",
34077                                 erroff, errptr);
34078                 return HANDLER_ERROR;
34079         }
34080 @@ -130,52 +131,52 @@
34081                         "mod_ssi: pcre support is missing, please recompile with pcre support or remove mod_ssi from the list of modules");
34082         return HANDLER_ERROR;
34083  #endif
34084 -       
34085 +
34086         return HANDLER_GO_ON;
34087  }
34088  
34089  int ssi_env_add(array *env, const char *key, const char *val) {
34090         data_string *ds;
34091 -                       
34092 +
34093         if (NULL == (ds = (data_string *)array_get_unused_element(env, TYPE_STRING))) {
34094                 ds = data_string_init();
34095         }
34096         buffer_copy_string(ds->key,   key);
34097         buffer_copy_string(ds->value, val);
34098 -       
34099 +
34100         array_insert_unique(env, (data_unset *)ds);
34101 -       
34102 +
34103         return 0;
34104  }
34105  
34106  /**
34107   *
34108   *  the next two functions are take from fcgi.c
34109 - * 
34110 + *
34111   */
34112  
34113  static int ssi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
34114         size_t i;
34115 -       
34116 +
34117         for (i = 0; i < con->request.headers->used; i++) {
34118                 data_string *ds;
34119 -               
34120 +
34121                 ds = (data_string *)con->request.headers->data[i];
34122 -               
34123 +
34124                 if (ds->value->used && ds->key->used) {
34125                         size_t j;
34126                         buffer_reset(srv->tmp_buf);
34127 -                       
34128 +
34129                         /* don't forward the Authorization: Header */
34130                         if (0 == strcasecmp(ds->key->ptr, "AUTHORIZATION")) {
34131                                 continue;
34132                         }
34133 -                       
34134 +
34135                         if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
34136                                 buffer_copy_string(srv->tmp_buf, "HTTP_");
34137                                 srv->tmp_buf->used--;
34138                         }
34139 -                       
34140 +
34141                         buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
34142                         for (j = 0; j < ds->key->used - 1; j++) {
34143                                 char c = '_';
34144 @@ -189,33 +190,33 @@
34145                                 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
34146                         }
34147                         srv->tmp_buf->ptr[srv->tmp_buf->used] = '\0';
34148 -                       
34149 +
34150                         ssi_env_add(p->ssi_cgi_env, srv->tmp_buf->ptr, ds->value->ptr);
34151                 }
34152         }
34153 -       
34154 +
34155         return 0;
34156  }
34157  
34158  static int build_ssi_cgi_vars(server *srv, connection *con, plugin_data *p) {
34159         char buf[32];
34160 -       
34161 +
34162         server_socket *srv_sock = con->srv_socket;
34163 -       
34164 +
34165  #ifdef HAVE_IPV6
34166         char b2[INET6_ADDRSTRLEN + 1];
34167  #endif
34168  
34169  #define CONST_STRING(x) \
34170                 x
34171 -       
34172 +
34173         array_reset(p->ssi_cgi_env);
34174 -       
34175 +
34176         ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_SOFTWARE"), PACKAGE_NAME"/"PACKAGE_VERSION);
34177         ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_NAME"),
34178  #ifdef HAVE_IPV6
34179 -                    inet_ntop(srv_sock->addr.plain.sa_family, 
34180 -                              srv_sock->addr.plain.sa_family == AF_INET6 ? 
34181 +                    inet_ntop(srv_sock->addr.plain.sa_family,
34182 +                              srv_sock->addr.plain.sa_family == AF_INET6 ?
34183                                (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
34184                                (const void *) &(srv_sock->addr.ipv4.sin_addr),
34185                                b2, sizeof(b2)-1)
34186 @@ -224,28 +225,28 @@
34187  #endif
34188                      );
34189         ssi_env_add(p->ssi_cgi_env, CONST_STRING("GATEWAY_INTERFACE"), "CGI/1.1");
34190 -               
34191 -       ltostr(buf, 
34192 +
34193 +       ltostr(buf,
34194  #ifdef HAVE_IPV6
34195                ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
34196  #else
34197                ntohs(srv_sock->addr.ipv4.sin_port)
34198  #endif
34199                );
34200 -       
34201 +
34202         ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PORT"), buf);
34203 -       
34204 +
34205         ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_ADDR"),
34206                     inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
34207 -       
34208 +
34209         if (con->authed_user->used) {
34210                 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_USER"),
34211                              con->authed_user->ptr);
34212         }
34213 -       
34214 +
34215         if (con->request.content_length > 0) {
34216                 /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
34217 -               
34218 +
34219                 /* request.content_length < SSIZE_MAX, see request.c */
34220                 ltostr(buf, con->request.content_length);
34221                 ssi_env_add(p->ssi_cgi_env, CONST_STRING("CONTENT_LENGTH"), buf);
34222 @@ -271,30 +272,30 @@
34223         if (con->request.pathinfo->used) {
34224                 ssi_env_add(p->ssi_cgi_env, CONST_STRING("PATH_INFO"), con->request.pathinfo->ptr);
34225         }
34226 -               
34227 +
34228         ssi_env_add(p->ssi_cgi_env, CONST_STRING("SCRIPT_FILENAME"), con->physical.path->ptr);
34229         ssi_env_add(p->ssi_cgi_env, CONST_STRING("DOCUMENT_ROOT"), con->physical.doc_root->ptr);
34230 -       
34231 +
34232         ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_URI"), con->request.uri->ptr);
34233         ssi_env_add(p->ssi_cgi_env, CONST_STRING("QUERY_STRING"), con->uri.query->used ? con->uri.query->ptr : "");
34234         ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_METHOD"), get_http_method_name(con->request.http_method));
34235         ssi_env_add(p->ssi_cgi_env, CONST_STRING("REDIRECT_STATUS"), "200");
34236         ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PROTOCOL"), get_http_version_name(con->request.http_version));
34237 -       
34238 +
34239         ssi_env_add_request_headers(srv, con, p);
34240 -       
34241 +
34242         return 0;
34243  }
34244  
34245 -static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, 
34246 +static int process_ssi_stmt(server *srv, connection *con, plugin_data *p,
34247                             const char **l, size_t n) {
34248         size_t i, ssicmd = 0;
34249         char buf[255];
34250         buffer *b = NULL;
34251 -       
34252 -       struct { 
34253 +
34254 +       struct {
34255                 const char *var;
34256 -               enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD, 
34257 +               enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD,
34258                                 SSI_CONFIG, SSI_PRINTENV, SSI_SET, SSI_IF, SSI_ELIF,
34259                                 SSI_ELSE, SSI_ENDIF, SSI_EXEC } type;
34260         } ssicmds[] = {
34261 @@ -310,27 +311,27 @@
34262                 { "endif",    SSI_ENDIF },
34263                 { "else",     SSI_ELSE },
34264                 { "exec",     SSI_EXEC },
34265 -               
34266 +
34267                 { NULL, SSI_UNSET }
34268         };
34269 -       
34270 +
34271         for (i = 0; ssicmds[i].var; i++) {
34272                 if (0 == strcmp(l[1], ssicmds[i].var)) {
34273                         ssicmd = ssicmds[i].type;
34274                         break;
34275                 }
34276         }
34277 -       
34278 +
34279         switch(ssicmd) {
34280         case SSI_ECHO: {
34281                 /* echo */
34282                 int var = 0, enc = 0;
34283                 const char *var_val = NULL;
34284                 stat_cache_entry *sce = NULL;
34285 -               
34286 -               struct { 
34287 +
34288 +               struct {
34289                         const char *var;
34290 -                       enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI, 
34291 +                       enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI,
34292                                         SSI_ECHO_LAST_MODIFIED, SSI_ECHO_USER_NAME } type;
34293                 } echovars[] = {
34294                         { "DATE_GMT",      SSI_ECHO_DATE_GMT },
34295 @@ -339,27 +340,27 @@
34296                         { "DOCUMENT_URI",  SSI_ECHO_DOCUMENT_URI },
34297                         { "LAST_MODIFIED", SSI_ECHO_LAST_MODIFIED },
34298                         { "USER_NAME",     SSI_ECHO_USER_NAME },
34299 -                       
34300 +
34301                         { NULL, SSI_ECHO_UNSET }
34302                 };
34303 -               
34304 -               struct { 
34305 +
34306 +               struct {
34307                         const char *var;
34308                         enum { SSI_ENC_UNSET, SSI_ENC_URL, SSI_ENC_NONE, SSI_ENC_ENTITY } type;
34309                 } encvars[] = {
34310                         { "url",          SSI_ENC_URL },
34311                         { "none",         SSI_ENC_NONE },
34312                         { "entity",       SSI_ENC_ENTITY },
34313 -                       
34314 +
34315                         { NULL, SSI_ENC_UNSET }
34316                 };
34317 -               
34318 +
34319                 for (i = 2; i < n; i += 2) {
34320                         if (0 == strcmp(l[i], "var")) {
34321                                 int j;
34322 -                               
34323 +
34324                                 var_val = l[i+1];
34325 -                               
34326 +
34327                                 for (j = 0; echovars[j].var; j++) {
34328                                         if (0 == strcmp(l[i+1], echovars[j].var)) {
34329                                                 var = echovars[j].type;
34330 @@ -368,7 +369,7 @@
34331                                 }
34332                         } else if (0 == strcmp(l[i], "encoding")) {
34333                                 int j;
34334 -                               
34335 +
34336                                 for (j = 0; encvars[j].var; j++) {
34337                                         if (0 == strcmp(l[i+1], encvars[j].var)) {
34338                                                 enc = encvars[j].type;
34339 @@ -377,26 +378,26 @@
34340                                 }
34341                         } else {
34342                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34343 -                                               "ssi: unknow attribute for ", 
34344 +                                               "ssi: unknow attribute for ",
34345                                                 l[1], l[i]);
34346                         }
34347                 }
34348 -               
34349 +
34350                 if (p->if_is_false) break;
34351 -               
34352 +
34353                 if (!var_val) {
34354                         log_error_write(srv, __FILE__, __LINE__, "sss",
34355 -                                       "ssi: ", 
34356 +                                       "ssi: ",
34357                                         l[1], "var is missing");
34358                         break;
34359                 }
34360  
34361                 stat_cache_get_entry(srv, con, con->physical.path, &sce);
34362 -               
34363 +
34364                 switch(var) {
34365                 case SSI_ECHO_USER_NAME: {
34366                         struct passwd *pw;
34367 -                       
34368 +
34369                         b = chunkqueue_get_append_buffer(con->write_queue);
34370  #ifdef HAVE_PWD_H
34371                         if (NULL == (pw = getpwuid(sce->st.st_uid))) {
34372 @@ -411,7 +412,7 @@
34373                 }
34374                 case SSI_ECHO_LAST_MODIFIED:    {
34375                         time_t t = sce->st.st_mtime;
34376 -                       
34377 +
34378                         b = chunkqueue_get_append_buffer(con->write_queue);
34379                         if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
34380                                 buffer_copy_string(b, "(none)");
34381 @@ -422,7 +423,7 @@
34382                 }
34383                 case SSI_ECHO_DATE_LOCAL: {
34384                         time_t t = time(NULL);
34385 -                       
34386 +
34387                         b = chunkqueue_get_append_buffer(con->write_queue);
34388                         if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
34389                                 buffer_copy_string(b, "(none)");
34390 @@ -433,7 +434,7 @@
34391                 }
34392                 case SSI_ECHO_DATE_GMT: {
34393                         time_t t = time(NULL);
34394 -                       
34395 +
34396                         b = chunkqueue_get_append_buffer(con->write_queue);
34397                         if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, gmtime(&t))) {
34398                                 buffer_copy_string(b, "(none)");
34399 @@ -444,7 +445,7 @@
34400                 }
34401                 case SSI_ECHO_DOCUMENT_NAME: {
34402                         char *sl;
34403 -                       
34404 +
34405                         b = chunkqueue_get_append_buffer(con->write_queue);
34406                         if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
34407                                 buffer_copy_string_buffer(b, con->physical.path);
34408 @@ -461,15 +462,15 @@
34409                 default: {
34410                         data_string *ds;
34411                         /* check if it is a cgi-var */
34412 -                       
34413 +
34414                         b = chunkqueue_get_append_buffer(con->write_queue);
34415 -                       
34416 +
34417                         if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, var_val))) {
34418                                 buffer_copy_string_buffer(b, ds->value);
34419                         } else {
34420                                 buffer_copy_string(b, "(none)");
34421                         }
34422 -                       
34423 +
34424                         break;
34425                 }
34426                 }
34427 @@ -481,7 +482,7 @@
34428                 const char * file_path = NULL, *virt_path = NULL;
34429                 struct stat st;
34430                 char *sl;
34431 -               
34432 +
34433                 for (i = 2; i < n; i += 2) {
34434                         if (0 == strcmp(l[i], "file")) {
34435                                 file_path = l[i+1];
34436 @@ -489,28 +490,28 @@
34437                                 virt_path = l[i+1];
34438                         } else {
34439                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34440 -                                               "ssi: unknow attribute for ", 
34441 +                                               "ssi: unknow attribute for ",
34442                                                 l[1], l[i]);
34443                         }
34444                 }
34445 -               
34446 +
34447                 if (!file_path && !virt_path) {
34448                         log_error_write(srv, __FILE__, __LINE__, "sss",
34449 -                                       "ssi: ", 
34450 +                                       "ssi: ",
34451                                         l[1], "file or virtual are missing");
34452                         break;
34453                 }
34454 -               
34455 +
34456                 if (file_path && virt_path) {
34457                         log_error_write(srv, __FILE__, __LINE__, "sss",
34458 -                                       "ssi: ", 
34459 +                                       "ssi: ",
34460                                         l[1], "only one of file and virtual is allowed here");
34461                         break;
34462                 }
34463 -               
34464 -               
34465 +
34466 +
34467                 if (p->if_is_false) break;
34468 -               
34469 +
34470                 if (file_path) {
34471                         /* current doc-root */
34472                         if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
34473 @@ -519,46 +520,46 @@
34474                                 buffer_copy_string_len(p->stat_fn, con->physical.path->ptr, sl - con->physical.path->ptr + 1);
34475                         }
34476  
34477 -                       buffer_copy_string(srv->tmp_buf, file_path); 
34478 +                       buffer_copy_string(srv->tmp_buf, file_path);
34479                         buffer_urldecode_path(srv->tmp_buf);
34480 -                       buffer_path_simplify(srv->tmp_buf, srv->tmp_buf); 
34481 -                       buffer_append_string_buffer(p->stat_fn, srv->tmp_buf); 
34482 +                       buffer_path_simplify(srv->tmp_buf, srv->tmp_buf);
34483 +                       buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
34484                 } else {
34485                         /* virtual */
34486 -                       
34487 +
34488                         if (virt_path[0] == '/') {
34489                                 buffer_copy_string(p->stat_fn, virt_path);
34490                         } else {
34491                                 /* there is always a / */
34492                                 sl = strrchr(con->uri.path->ptr, '/');
34493 -                               
34494 +
34495                                 buffer_copy_string_len(p->stat_fn, con->uri.path->ptr, sl - con->uri.path->ptr + 1);
34496                                 buffer_append_string(p->stat_fn, virt_path);
34497                         }
34498 -                       
34499 +
34500                         buffer_urldecode_path(p->stat_fn);
34501                         buffer_path_simplify(srv->tmp_buf, p->stat_fn);
34502 -                       
34503 +
34504                         /* we have an uri */
34505 -                       
34506 +
34507                         buffer_copy_string_buffer(p->stat_fn, con->physical.doc_root);
34508                         buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
34509                 }
34510 -               
34511 +
34512                 if (0 == stat(p->stat_fn->ptr, &st)) {
34513                         time_t t = st.st_mtime;
34514 -                       
34515 +
34516                         switch (ssicmd) {
34517                         case SSI_FSIZE:
34518                                 b = chunkqueue_get_append_buffer(con->write_queue);
34519                                 if (p->sizefmt) {
34520                                         int j = 0;
34521                                         const char *abr[] = { " B", " kB", " MB", " GB", " TB", NULL };
34522 -                                       
34523 +
34524                                         off_t s = st.st_size;
34525 -                                       
34526 +
34527                                         for (j = 0; s > 1024 && abr[j+1]; s /= 1024, j++);
34528 -                                       
34529 +
34530                                         buffer_copy_off_t(b, s);
34531                                         buffer_append_string(b, abr[j]);
34532                                 } else {
34533 @@ -579,7 +580,7 @@
34534                         }
34535                 } else {
34536                         log_error_write(srv, __FILE__, __LINE__, "sbs",
34537 -                                       "ssi: stating failed ", 
34538 +                                       "ssi: stating failed ",
34539                                         p->stat_fn, strerror(errno));
34540                 }
34541                 break;
34542 @@ -593,33 +594,33 @@
34543                                 val = l[i+1];
34544                         } else {
34545                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34546 -                                               "ssi: unknow attribute for ", 
34547 +                                               "ssi: unknow attribute for ",
34548                                                 l[1], l[i]);
34549                         }
34550                 }
34551 -               
34552 +
34553                 if (p->if_is_false) break;
34554 -               
34555 +
34556                 if (key && val) {
34557                         data_string *ds;
34558 -                       
34559 +
34560                         if (NULL == (ds = (data_string *)array_get_unused_element(p->ssi_vars, TYPE_STRING))) {
34561                                 ds = data_string_init();
34562                         }
34563                         buffer_copy_string(ds->key,   key);
34564                         buffer_copy_string(ds->value, val);
34565 -                       
34566 +
34567                         array_insert_unique(p->ssi_vars, (data_unset *)ds);
34568                 } else {
34569                         log_error_write(srv, __FILE__, __LINE__, "sss",
34570 -                                       "ssi: var and value have to be set in", 
34571 +                                       "ssi: var and value have to be set in",
34572                                         l[0], l[1]);
34573                 }
34574                 break;
34575         }
34576 -       case SSI_CONFIG: 
34577 +       case SSI_CONFIG:
34578                 if (p->if_is_false) break;
34579 -               
34580 +
34581                 for (i = 2; i < n; i += 2) {
34582                         if (0 == strcmp(l[i], "timefmt")) {
34583                                 buffer_copy_string(p->timefmt, l[i+1]);
34584 @@ -632,63 +633,65 @@
34585                                         log_error_write(srv, __FILE__, __LINE__, "sssss",
34586                                                         "ssi: unknow value for attribute '",
34587                                                         l[i],
34588 -                                                       "' for ", 
34589 +                                                       "' for ",
34590                                                         l[1], l[i+1]);
34591                                 }
34592                         } else {
34593                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34594 -                                               "ssi: unknow attribute for ", 
34595 +                                               "ssi: unknow attribute for ",
34596                                                 l[1], l[i]);
34597                         }
34598                 }
34599                 break;
34600         case SSI_PRINTENV:
34601                 if (p->if_is_false) break;
34602 -               
34603 +
34604                 b = chunkqueue_get_append_buffer(con->write_queue);
34605                 buffer_copy_string(b, "<pre>");
34606                 for (i = 0; i < p->ssi_vars->used; i++) {
34607                         data_string *ds = (data_string *)p->ssi_vars->data[p->ssi_vars->sorted[i]];
34608 -                       
34609 +
34610                         buffer_append_string_buffer(b, ds->key);
34611                         buffer_append_string(b, ": ");
34612                         buffer_append_string_buffer(b, ds->value);
34613                         buffer_append_string(b, "<br />");
34614 -                                       
34615 +
34616                 }
34617                 buffer_append_string(b, "</pre>");
34618 -               
34619 +
34620                 break;
34621         case SSI_EXEC: {
34622 +#ifndef _WIN32
34623 +
34624                 const char *cmd = NULL;
34625                 pid_t pid;
34626                 int from_exec_fds[2];
34627 -               
34628 +
34629                 for (i = 2; i < n; i += 2) {
34630                         if (0 == strcmp(l[i], "cmd")) {
34631                                 cmd = l[i+1];
34632                         } else {
34633                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34634 -                                               "ssi: unknow attribute for ", 
34635 +                                               "ssi: unknow attribute for ",
34636                                                 l[1], l[i]);
34637                         }
34638                 }
34639 -               
34640 +
34641                 if (p->if_is_false) break;
34642 -               
34643 +
34644                 /* create a return pipe and send output to the html-page
34645 -                * 
34646 -                * as exec is assumed evil it is implemented synchronously 
34647 +                *
34648 +                * as exec is assumed evil it is implemented synchronously
34649                  */
34650 -               
34651 +
34652                 if (!cmd) break;
34653 -#ifdef HAVE_FORK       
34654 +
34655                 if (pipe(from_exec_fds)) {
34656 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
34657 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
34658                                         "pipe failed: ", strerror(errno));
34659                         return -1;
34660                 }
34661 -       
34662 +
34663                 /* fork, execve */
34664                 switch (pid = fork()) {
34665                 case 0: {
34666 @@ -698,14 +701,14 @@
34667                         close(from_exec_fds[1]);
34668                         /* not needed */
34669                         close(from_exec_fds[0]);
34670 -                       
34671 +
34672                         /* close stdin */
34673                         close(STDIN_FILENO);
34674 -               
34675 +
34676                         execl("/bin/sh", "sh", "-c", cmd, NULL);
34677 -                       
34678 +
34679                         log_error_write(srv, __FILE__, __LINE__, "sss", "spawing exec failed:", strerror(errno), cmd);
34680 -               
34681 +
34682                         /* */
34683                         SEGFAULT();
34684                         break;
34685 @@ -718,9 +721,9 @@
34686                         /* father */
34687                         int status;
34688                         ssize_t r;
34689 -                       
34690 +
34691                         close(from_exec_fds[1]);
34692 -                       
34693 +
34694                         /* wait for the client to end */
34695                         if (-1 == waitpid(pid, &status, 0)) {
34696                                 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed:", strerror(errno));
34697 @@ -730,7 +733,7 @@
34698  
34699                                 while(1) {
34700                                         if (ioctl(from_exec_fds[0], FIONREAD, &toread)) {
34701 -                                               log_error_write(srv, __FILE__, __LINE__, "s", 
34702 +                                               log_error_write(srv, __FILE__, __LINE__, "s",
34703                                                         "unexpected end-of-file (perhaps the ssi-exec process died)");
34704                                                 return -1;
34705                                         }
34706 @@ -738,10 +741,10 @@
34707                                         if (toread > 0) {
34708                                                 b = chunkqueue_get_append_buffer(con->write_queue);
34709  
34710 -                                               buffer_prepare_copy(b, toread + 1); 
34711 +                                               buffer_prepare_copy(b, toread + 1);
34712  
34713                                                 if ((r = read(from_exec_fds[0], b->ptr, b->size - 1)) < 0) {
34714 -                                                       /* read failed */ 
34715 +                                                       /* read failed */
34716                                                         break;
34717                                                 } else {
34718                                                         b->used = r;
34719 @@ -755,59 +758,58 @@
34720                                 log_error_write(srv, __FILE__, __LINE__, "s", "process exited abnormally");
34721                         }
34722                         close(from_exec_fds[0]);
34723 -                       
34724 +
34725                         break;
34726                 }
34727                 }
34728  #else
34729 -
34730                 return -1;
34731  #endif
34732 -               
34733 +
34734                 break;
34735         }
34736         case SSI_IF: {
34737                 const char *expr = NULL;
34738 -               
34739 +
34740                 for (i = 2; i < n; i += 2) {
34741                         if (0 == strcmp(l[i], "expr")) {
34742                                 expr = l[i+1];
34743                         } else {
34744                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34745 -                                               "ssi: unknow attribute for ", 
34746 +                                               "ssi: unknow attribute for ",
34747                                                 l[1], l[i]);
34748                         }
34749                 }
34750 -               
34751 +
34752                 if (!expr) {
34753                         log_error_write(srv, __FILE__, __LINE__, "sss",
34754 -                                       "ssi: ", 
34755 +                                       "ssi: ",
34756                                         l[1], "expr missing");
34757                         break;
34758                 }
34759 -               
34760 +
34761                 if ((!p->if_is_false) &&
34762 -                   ((p->if_is_false_level == 0) || 
34763 +                   ((p->if_is_false_level == 0) ||
34764                      (p->if_level < p->if_is_false_level))) {
34765                         switch (ssi_eval_expr(srv, con, p, expr)) {
34766                         case -1:
34767 -                       case 0: 
34768 -                               p->if_is_false = 1; 
34769 +                       case 0:
34770 +                               p->if_is_false = 1;
34771                                 p->if_is_false_level = p->if_level;
34772                                 break;
34773 -                       case 1: 
34774 -                               p->if_is_false = 0; 
34775 +                       case 1:
34776 +                               p->if_is_false = 0;
34777                                 break;
34778                         }
34779                 }
34780 -               
34781 +
34782                 p->if_level++;
34783 -               
34784 +
34785                 break;
34786         }
34787         case SSI_ELSE:
34788                 p->if_level--;
34789 -               
34790 +
34791                 if (p->if_is_false) {
34792                         if ((p->if_level == p->if_is_false_level) &&
34793                             (p->if_is_false_endif == 0)) {
34794 @@ -815,11 +817,11 @@
34795                         }
34796                 } else {
34797                         p->if_is_false = 1;
34798 -                       
34799 +
34800                         p->if_is_false_level = p->if_level;
34801                 }
34802                 p->if_level++;
34803 -               
34804 +
34805                 break;
34806         case SSI_ELIF: {
34807                 const char *expr = NULL;
34808 @@ -828,52 +830,52 @@
34809                                 expr = l[i+1];
34810                         } else {
34811                                 log_error_write(srv, __FILE__, __LINE__, "sss",
34812 -                                               "ssi: unknow attribute for ", 
34813 +                                               "ssi: unknow attribute for ",
34814                                                 l[1], l[i]);
34815                         }
34816                 }
34817 -               
34818 +
34819                 if (!expr) {
34820                         log_error_write(srv, __FILE__, __LINE__, "sss",
34821 -                                       "ssi: ", 
34822 +                                       "ssi: ",
34823                                         l[1], "expr missing");
34824                         break;
34825                 }
34826 -               
34827 +
34828                 p->if_level--;
34829 -               
34830 +
34831                 if (p->if_level == p->if_is_false_level) {
34832                         if ((p->if_is_false) &&
34833                             (p->if_is_false_endif == 0)) {
34834                                 switch (ssi_eval_expr(srv, con, p, expr)) {
34835                                 case -1:
34836 -                               case 0: 
34837 -                                       p->if_is_false = 1; 
34838 +                               case 0:
34839 +                                       p->if_is_false = 1;
34840                                         p->if_is_false_level = p->if_level;
34841                                         break;
34842 -                               case 1: 
34843 -                                       p->if_is_false = 0; 
34844 +                               case 1:
34845 +                                       p->if_is_false = 0;
34846                                         break;
34847                                 }
34848                         } else {
34849 -                               p->if_is_false = 1; 
34850 +                               p->if_is_false = 1;
34851                                 p->if_is_false_level = p->if_level;
34852                                 p->if_is_false_endif = 1;
34853                         }
34854                 }
34855 -               
34856 +
34857                 p->if_level++;
34858 -               
34859 +
34860                 break;
34861         }
34862         case SSI_ENDIF:
34863                 p->if_level--;
34864 -               
34865 +
34866                 if (p->if_level == p->if_is_false_level) {
34867                         p->if_is_false = 0;
34868                         p->if_is_false_endif = 0;
34869                 }
34870 -                       
34871 +
34872                 break;
34873         default:
34874                 log_error_write(srv, __FILE__, __LINE__, "ss",
34875 @@ -881,41 +883,41 @@
34876                                 l[1]);
34877                 break;
34878         }
34879 -       
34880 +
34881         return 0;
34882 -       
34883 +
34884  }
34885  
34886  static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p) {
34887         stream s;
34888  #ifdef  HAVE_PCRE_H
34889         int i, n;
34890 -       
34891 +
34892  #define N 10
34893         int ovec[N * 3];
34894  #endif
34895 -       
34896 +
34897         /* get a stream to the file */
34898 -       
34899 +
34900         array_reset(p->ssi_vars);
34901         array_reset(p->ssi_cgi_env);
34902         buffer_copy_string(p->timefmt, "%a, %d %b %Y %H:%M:%S %Z");
34903         p->sizefmt = 0;
34904         build_ssi_cgi_vars(srv, con, p);
34905         p->if_is_false = 0;
34906 -       
34907 +
34908         if (-1 == stream_open(&s, con->physical.path)) {
34909                 log_error_write(srv, __FILE__, __LINE__, "sb",
34910                                 "stream-open: ", con->physical.path);
34911                 return -1;
34912         }
34913 -       
34914 -       
34915 +
34916 +
34917         /**
34918 -        * <!--#element attribute=value attribute=value ... --> 
34919 -        * 
34920 +        * <!--#element attribute=value attribute=value ... -->
34921 +        *
34922          * config       DONE
34923 -        *   errmsg     -- missing 
34924 +        *   errmsg     -- missing
34925          *   sizefmt    DONE
34926          *   timefmt    DONE
34927          * echo         DONE
34928 @@ -937,13 +939,13 @@
34929          * set          DONE
34930          *   var        DONE
34931          *   value      DONE
34932 -        * 
34933 +        *
34934          * if           DONE
34935          * elif         DONE
34936          * else         DONE
34937          * endif        DONE
34938 -        * 
34939 -        * 
34940 +        *
34941 +        *
34942          * expressions
34943          * AND, OR      DONE
34944          * comp         DONE
34945 @@ -951,118 +953,115 @@
34946          * $...         DONE
34947          * '...'        DONE
34948          * ( ... )      DONE
34949 -        * 
34950 -        * 
34951 -        * 
34952 +        *
34953 +        *
34954 +        *
34955          * ** all DONE **
34956 -        * DATE_GMT 
34957 -        *   The current date in Greenwich Mean Time. 
34958 -        * DATE_LOCAL 
34959 -        *   The current date in the local time zone. 
34960 -        * DOCUMENT_NAME 
34961 -        *   The filename (excluding directories) of the document requested by the user. 
34962 -        * DOCUMENT_URI 
34963 -        *   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. 
34964 -        * LAST_MODIFIED 
34965 -        *   The last modification date of the document requested by the user. 
34966 -        * USER_NAME 
34967 +        * DATE_GMT
34968 +        *   The current date in Greenwich Mean Time.
34969 +        * DATE_LOCAL
34970 +        *   The current date in the local time zone.
34971 +        * DOCUMENT_NAME
34972 +        *   The filename (excluding directories) of the document requested by the user.
34973 +        * DOCUMENT_URI
34974 +        *   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.
34975 +        * LAST_MODIFIED
34976 +        *   The last modification date of the document requested by the user.
34977 +        * USER_NAME
34978          *   Contains the owner of the file which included it.
34979 -        * 
34980 +        *
34981          */
34982 -#ifdef HAVE_PCRE_H     
34983 +#ifdef HAVE_PCRE_H
34984         for (i = 0; (n = pcre_exec(p->ssi_regex, NULL, s.start, s.size, i, 0, ovec, N * 3)) > 0; i = ovec[1]) {
34985                 const char **l;
34986                 /* take everything from last offset to current match pos */
34987 -               
34988 +
34989                 if (!p->if_is_false) chunkqueue_append_file(con->write_queue, con->physical.path, i, ovec[0] - i);
34990 -               
34991 +
34992                 pcre_get_substring_list(s.start, ovec, n, &l);
34993                 process_ssi_stmt(srv, con, p, l, n);
34994                 pcre_free_substring_list(l);
34995         }
34996 -       
34997 +
34998         switch(n) {
34999         case PCRE_ERROR_NOMATCH:
35000                 /* copy everything/the rest */
35001                 chunkqueue_append_file(con->write_queue, con->physical.path, i, s.size - i);
35002 -               
35003 +
35004                 break;
35005         default:
35006                 log_error_write(srv, __FILE__, __LINE__, "sd",
35007                                 "execution error while matching: ", n);
35008                 break;
35009         }
35010 -#endif 
35011 -       
35012 -       
35013 +#endif
35014 +
35015 +
35016         stream_close(&s);
35017 -       
35018 +
35019         con->file_started  = 1;
35020         con->file_finished = 1;
35021 -       
35022 +
35023         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
35024 -       
35025 +
35026         /* reset physical.path */
35027         buffer_reset(con->physical.path);
35028 -       
35029 +
35030         return 0;
35031  }
35032  
35033 -#define PATCH(x) \
35034 -       p->conf.x = s->x;
35035  static int mod_ssi_patch_connection(server *srv, connection *con, plugin_data *p) {
35036         size_t i, j;
35037         plugin_config *s = p->config_storage[0];
35038 -       
35039 -       PATCH(ssi_extension);
35040 -       
35041 +
35042 +       PATCH_OPTION(ssi_extension);
35043 +
35044         /* skip the first, the global context */
35045         for (i = 1; i < srv->config_context->used; i++) {
35046                 data_config *dc = (data_config *)srv->config_context->data[i];
35047                 s = p->config_storage[i];
35048 -               
35049 +
35050                 /* condition didn't match */
35051                 if (!config_check_cond(srv, con, dc)) continue;
35052 -               
35053 +
35054                 /* merge config */
35055                 for (j = 0; j < dc->value->used; j++) {
35056                         data_unset *du = dc->value->data[j];
35057 -                       
35058 +
35059                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssi.extension"))) {
35060 -                               PATCH(ssi_extension);
35061 +                               PATCH_OPTION(ssi_extension);
35062                         }
35063                 }
35064         }
35065 -       
35066 +
35067         return 0;
35068  }
35069 -#undef PATCH
35070  
35071  URIHANDLER_FUNC(mod_ssi_physical_path) {
35072         plugin_data *p = p_d;
35073         size_t k;
35074 -       
35075 +
35076         if (con->physical.path->used == 0) return HANDLER_GO_ON;
35077 -       
35078 +
35079         mod_ssi_patch_connection(srv, con, p);
35080 -       
35081 +
35082         for (k = 0; k < p->conf.ssi_extension->used; k++) {
35083                 data_string *ds = (data_string *)p->conf.ssi_extension->data[k];
35084 -               
35085 +
35086                 if (ds->value->used == 0) continue;
35087 -               
35088 +
35089                 if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
35090                         /* handle ssi-request */
35091 -                       
35092 +
35093                         if (mod_ssi_handle_request(srv, con, p)) {
35094                                 /* on error */
35095                                 con->http_status = 500;
35096                         }
35097 -                       
35098 +
35099                         return HANDLER_FINISHED;
35100                 }
35101         }
35102 -       
35103 +
35104         /* not found */
35105         return HANDLER_GO_ON;
35106  }
35107 @@ -1072,13 +1071,13 @@
35108  int mod_ssi_plugin_init(plugin *p) {
35109         p->version     = LIGHTTPD_VERSION_ID;
35110         p->name        = buffer_init_string("ssi");
35111 -       
35112 +
35113         p->init        = mod_ssi_init;
35114         p->handle_subrequest_start = mod_ssi_physical_path;
35115         p->set_defaults  = mod_ssi_set_defaults;
35116         p->cleanup     = mod_ssi_free;
35117 -       
35118 +
35119         p->data        = NULL;
35120 -       
35121 +
35122         return 0;
35123  }
35124 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_ssi.h lighttpd-1.4.12/src/mod_ssi.h
35125 --- lighttpd-1.4.11/src/mod_ssi.h       2005-08-11 01:26:39.000000000 +0300
35126 +++ lighttpd-1.4.12/src/mod_ssi.h       2006-07-11 21:23:40.000000000 +0300
35127 @@ -19,23 +19,23 @@
35128  
35129  typedef struct {
35130         PLUGIN_DATA;
35131 -       
35132 -#ifdef HAVE_PCRE_H     
35133 +
35134 +#ifdef HAVE_PCRE_H
35135         pcre *ssi_regex;
35136 -#endif 
35137 +#endif
35138         buffer *timefmt;
35139         int sizefmt;
35140 -       
35141 +
35142         buffer *stat_fn;
35143 -       
35144 +
35145         array *ssi_vars;
35146         array *ssi_cgi_env;
35147 -       
35148 +
35149         int if_level, if_is_false_level, if_is_false, if_is_false_endif;
35150 -       
35151 +
35152         plugin_config **config_storage;
35153 -       
35154 -       plugin_config conf; 
35155 +
35156 +       plugin_config conf;
35157  } plugin_data;
35158  
35159  int ssi_eval_expr(server *srv, connection *con, plugin_data *p, const char *expr);
35160 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_ssi_expr.c lighttpd-1.4.12/src/mod_ssi_expr.c
35161 --- lighttpd-1.4.11/src/mod_ssi_expr.c  2005-08-11 01:26:48.000000000 +0300
35162 +++ lighttpd-1.4.12/src/mod_ssi_expr.c  2006-07-11 21:23:40.000000000 +0300
35163 @@ -11,9 +11,9 @@
35164         const char *input;
35165         size_t offset;
35166         size_t size;
35167 -       
35168 +
35169         int line_pos;
35170 -       
35171 +
35172         int in_key;
35173         int in_brace;
35174         int in_cond;
35175 @@ -21,15 +21,15 @@
35176  
35177  ssi_val_t *ssi_val_init() {
35178         ssi_val_t *s;
35179 -       
35180 +
35181         s = calloc(1, sizeof(*s));
35182 -       
35183 +
35184         return s;
35185  }
35186  
35187  void ssi_val_free(ssi_val_t *s) {
35188         if (s->str) buffer_free(s->str);
35189 -       
35190 +
35191         free(s);
35192  }
35193  
35194 @@ -45,175 +45,175 @@
35195                               ssi_tokenizer_t *t, int *token_id, buffer *token) {
35196         int tid = 0;
35197         size_t i;
35198 -       
35199 +
35200         UNUSED(con);
35201  
35202         for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
35203                 char c = t->input[t->offset];
35204                 data_string *ds;
35205 -               
35206 +
35207                 switch (c) {
35208 -               case '=': 
35209 +               case '=':
35210                         tid = TK_EQ;
35211 -                       
35212 +
35213                         t->offset++;
35214                         t->line_pos++;
35215 -                       
35216 +
35217                         buffer_copy_string(token, "(=)");
35218 -                       
35219 +
35220                         break;
35221                 case '>':
35222                         if (t->input[t->offset + 1] == '=') {
35223                                 t->offset += 2;
35224                                 t->line_pos += 2;
35225 -                               
35226 +
35227                                 tid = TK_GE;
35228 -                               
35229 +
35230                                 buffer_copy_string(token, "(>=)");
35231                         } else {
35232                                 t->offset += 1;
35233                                 t->line_pos += 1;
35234 -                               
35235 +
35236                                 tid = TK_GT;
35237 -                               
35238 +
35239                                 buffer_copy_string(token, "(>)");
35240                         }
35241 -                       
35242 +
35243                         break;
35244                 case '<':
35245                         if (t->input[t->offset + 1] == '=') {
35246                                 t->offset += 2;
35247                                 t->line_pos += 2;
35248 -                               
35249 +
35250                                 tid = TK_LE;
35251 -                               
35252 +
35253                                 buffer_copy_string(token, "(<=)");
35254                         } else {
35255                                 t->offset += 1;
35256                                 t->line_pos += 1;
35257 -                               
35258 +
35259                                 tid = TK_LT;
35260 -                               
35261 +
35262                                 buffer_copy_string(token, "(<)");
35263                         }
35264 -                       
35265 +
35266                         break;
35267 -                       
35268 +
35269                 case '!':
35270                         if (t->input[t->offset + 1] == '=') {
35271                                 t->offset += 2;
35272                                 t->line_pos += 2;
35273 -                               
35274 +
35275                                 tid = TK_NE;
35276 -                               
35277 +
35278                                 buffer_copy_string(token, "(!=)");
35279                         } else {
35280                                 t->offset += 1;
35281                                 t->line_pos += 1;
35282 -                               
35283 +
35284                                 tid = TK_NOT;
35285 -                               
35286 +
35287                                 buffer_copy_string(token, "(!)");
35288                         }
35289 -                       
35290 +
35291                         break;
35292                 case '&':
35293                         if (t->input[t->offset + 1] == '&') {
35294                                 t->offset += 2;
35295                                 t->line_pos += 2;
35296 -                               
35297 +
35298                                 tid = TK_AND;
35299 -                               
35300 +
35301                                 buffer_copy_string(token, "(&&)");
35302                         } else {
35303 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
35304 -                                               "pos:", t->line_pos, 
35305 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
35306 +                                               "pos:", t->line_pos,
35307                                                 "missing second &");
35308                                 return -1;
35309                         }
35310 -                       
35311 +
35312                         break;
35313                 case '|':
35314                         if (t->input[t->offset + 1] == '|') {
35315                                 t->offset += 2;
35316                                 t->line_pos += 2;
35317 -                               
35318 +
35319                                 tid = TK_OR;
35320 -                               
35321 +
35322                                 buffer_copy_string(token, "(||)");
35323                         } else {
35324 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
35325 -                                               "pos:", t->line_pos, 
35326 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
35327 +                                               "pos:", t->line_pos,
35328                                                 "missing second |");
35329                                 return -1;
35330                         }
35331 -                       
35332 +
35333                         break;
35334                 case '\t':
35335                 case ' ':
35336                         t->offset++;
35337                         t->line_pos++;
35338                         break;
35339 -                       
35340 +
35341                 case '\'':
35342                         /* search for the terminating " */
35343                         for (i = 1; t->input[t->offset + i] && t->input[t->offset + i] != '\'';  i++);
35344 -                       
35345 +
35346                         if (t->input[t->offset + i]) {
35347                                 tid = TK_VALUE;
35348 -                               
35349 +
35350                                 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
35351 -                               
35352 +
35353                                 t->offset += i + 1;
35354                                 t->line_pos += i + 1;
35355                         } else {
35356                                 /* ERROR */
35357 -                               
35358 -                               log_error_write(srv, __FILE__, __LINE__, "sds", 
35359 -                                               "pos:", t->line_pos, 
35360 +
35361 +                               log_error_write(srv, __FILE__, __LINE__, "sds",
35362 +                                               "pos:", t->line_pos,
35363                                                 "missing closing quote");
35364 -                               
35365 +
35366                                 return -1;
35367                         }
35368 -                       
35369 +
35370                         break;
35371                 case '(':
35372                         t->offset++;
35373                         t->in_brace++;
35374 -                               
35375 +
35376                         tid = TK_LPARAN;
35377 -                               
35378 +
35379                         buffer_copy_string(token, "(");
35380                         break;
35381                 case ')':
35382                         t->offset++;
35383                         t->in_brace--;
35384 -                               
35385 +
35386                         tid = TK_RPARAN;
35387 -                               
35388 +
35389                         buffer_copy_string(token, ")");
35390                         break;
35391                 case '$':
35392                         if (t->input[t->offset + 1] == '{') {
35393                                 for (i = 2; t->input[t->offset + i] && t->input[t->offset + i] != '}';  i++);
35394 -                               
35395 +
35396                                 if (t->input[t->offset + i] != '}') {
35397 -                                       log_error_write(srv, __FILE__, __LINE__, "sds", 
35398 -                                                       "pos:", t->line_pos, 
35399 +                                       log_error_write(srv, __FILE__, __LINE__, "sds",
35400 +                                                       "pos:", t->line_pos,
35401                                                         "missing closing quote");
35402 -                                       
35403 +
35404                                         return -1;
35405                                 }
35406 -                               
35407 +
35408                                 buffer_copy_string_len(token, t->input + t->offset + 2, i-3);
35409                         } else {
35410                                 for (i = 1; isalpha(t->input[t->offset + i]) || t->input[t->offset + i] == '_';  i++);
35411 -                               
35412 +
35413                                 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
35414                         }
35415 -                       
35416 +
35417                         tid = TK_VALUE;
35418 -                       
35419 +
35420                         if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, token->ptr))) {
35421                                 buffer_copy_string_buffer(token, ds->value);
35422                         } else if (NULL != (ds = (data_string *)array_get_element(p->ssi_vars, token->ptr))) {
35423 @@ -221,16 +221,16 @@
35424                         } else {
35425                                 buffer_copy_string(token, "");
35426                         }
35427 -                               
35428 +
35429                         t->offset += i;
35430                         t->line_pos += i;
35431 -                       
35432 +
35433                         break;
35434                 default:
35435                         for (i = 0; isgraph(t->input[t->offset + i]);  i++) {
35436                                 char d = t->input[t->offset + i];
35437                                 switch(d) {
35438 -                               case ' ': 
35439 +                               case ' ':
35440                                 case '\t':
35441                                 case ')':
35442                                 case '(':
35443 @@ -244,25 +244,25 @@
35444                                         break;
35445                                 }
35446                         }
35447 -                       
35448 +
35449                         tid = TK_VALUE;
35450 -                               
35451 +
35452                         buffer_copy_string_len(token, t->input + t->offset, i);
35453 -                               
35454 +
35455                         t->offset += i;
35456                         t->line_pos += i;
35457 -                       
35458 +
35459                         break;
35460                 }
35461         }
35462 -                       
35463 +
35464         if (tid) {
35465                 *token_id = tid;
35466 -               
35467 +
35468                 return 1;
35469         } else if (t->offset < t->size) {
35470 -               log_error_write(srv, __FILE__, __LINE__, "sds", 
35471 -                               "pos:", t->line_pos, 
35472 +               log_error_write(srv, __FILE__, __LINE__, "sds",
35473 +                               "pos:", t->line_pos,
35474                                 "foobar");
35475         }
35476         return 0;
35477 @@ -275,50 +275,50 @@
35478         buffer *token;
35479         ssi_ctx_t context;
35480         int ret;
35481 -       
35482 +
35483         t.input = expr;
35484         t.offset = 0;
35485         t.size = strlen(expr);
35486         t.line_pos = 1;
35487 -       
35488 +
35489         t.in_key = 1;
35490         t.in_brace = 0;
35491         t.in_cond = 0;
35492 -       
35493 +
35494         context.ok = 1;
35495         context.srv = srv;
35496 -       
35497 +
35498         /* default context */
35499 -       
35500 +
35501         pParser = ssiexprparserAlloc( malloc );
35502         token = buffer_init();
35503         while((1 == (ret = ssi_expr_tokenizer(srv, con, p, &t, &token_id, token))) && context.ok) {
35504                 ssiexprparser(pParser, token_id, token, &context);
35505 -               
35506 +
35507                 token = buffer_init();
35508         }
35509         ssiexprparser(pParser, 0, token, &context);
35510         ssiexprparserFree(pParser, free );
35511 -       
35512 +
35513         buffer_free(token);
35514 -       
35515 +
35516         if (ret == -1) {
35517 -               log_error_write(srv, __FILE__, __LINE__, "s", 
35518 +               log_error_write(srv, __FILE__, __LINE__, "s",
35519                                 "expr parser failed");
35520                 return -1;
35521         }
35522 -       
35523 +
35524         if (context.ok == 0) {
35525 -               log_error_write(srv, __FILE__, __LINE__, "sds", 
35526 -                               "pos:", t.line_pos, 
35527 +               log_error_write(srv, __FILE__, __LINE__, "sds",
35528 +                               "pos:", t.line_pos,
35529                                 "parser failed somehow near here");
35530                 return -1;
35531         }
35532  #if 0
35533 -       log_error_write(srv, __FILE__, __LINE__, "ssd", 
35534 +       log_error_write(srv, __FILE__, __LINE__, "ssd",
35535                         "expr: ",
35536                         expr,
35537                         context.val.bo);
35538 -#endif 
35539 +#endif
35540         return context.val.bo;
35541  }
35542 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_ssi_expr.h lighttpd-1.4.12/src/mod_ssi_expr.h
35543 --- lighttpd-1.4.11/src/mod_ssi_expr.h  2005-08-11 01:26:48.000000000 +0300
35544 +++ lighttpd-1.4.12/src/mod_ssi_expr.h  2006-07-11 21:23:40.000000000 +0300
35545 @@ -5,16 +5,16 @@
35546  
35547  typedef struct {
35548         enum { SSI_TYPE_UNSET, SSI_TYPE_BOOL, SSI_TYPE_STRING } type;
35549 -       
35550 +
35551         buffer *str;
35552         int     bo;
35553  } ssi_val_t;
35554  
35555  typedef struct {
35556         int     ok;
35557 -       
35558 +
35559         ssi_val_t val;
35560 -       
35561 +
35562         void   *srv;
35563  } ssi_ctx_t;
35564  
35565 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_ssi_exprparser.c lighttpd-1.4.12/src/mod_ssi_exprparser.c
35566 --- lighttpd-1.4.11/src/mod_ssi_exprparser.c    2005-10-03 00:40:25.000000000 +0300
35567 +++ lighttpd-1.4.12/src/mod_ssi_exprparser.c    2006-07-11 21:49:18.000000000 +0300
35568 @@ -18,10 +18,10 @@
35569  /* Next is all token values, in a form suitable for use by makeheaders.
35570  ** This section will be null unless lemon is run with the -m switch.
35571  */
35572 -/* 
35573 +/*
35574  ** These constants (all generated automatically by the parser generator)
35575  ** specify the various kinds of tokens (terminals) that the parser
35576 -** understands. 
35577 +** understands.
35578  **
35579  ** Each symbol here is a terminal symbol in the grammar.
35580  */
35581 @@ -38,7 +38,7 @@
35582  **                       and nonterminals.  "int" is used otherwise.
35583  **    YYNOCODE           is a number of type YYCODETYPE which corresponds
35584  **                       to no legal terminal or nonterminal number.  This
35585 -**                       number is used to fill in empty slots of the hash 
35586 +**                       number is used to fill in empty slots of the hash
35587  **                       table.
35588  **    YYFALLBACK         If defined, this indicates that one or more tokens
35589  **                       have fall-back values which should be used if the
35590 @@ -47,7 +47,7 @@
35591  **                       and nonterminal numbers.  "unsigned char" is
35592  **                       used if there are fewer than 250 rules and
35593  **                       states combined.  "int" is used otherwise.
35594 -**    ssiexprparserTOKENTYPE     is the data type used for minor tokens given 
35595 +**    ssiexprparserTOKENTYPE     is the data type used for minor tokens given
35596  **                       directly to the parser from the tokenizer.
35597  **    YYMINORTYPE        is the data type used for all minor tokens.
35598  **                       This is typically a union of many types, one of
35599 @@ -91,7 +91,7 @@
35600  /* Next are that tables used to determine what action to take based on the
35601  ** current state and lookahead token.  These tables are used to implement
35602  ** functions that take a state number and lookahead value and return an
35603 -** action integer.  
35604 +** action integer.
35605  **
35606  ** Suppose the action integer is N.  Then the action is determined as
35607  ** follows
35608 @@ -116,7 +116,7 @@
35609  ** If the index value yy_shift_ofst[S]+X is out of range or if the value
35610  ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
35611  ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
35612 -** and that yy_default[S] should be used instead.  
35613 +** and that yy_default[S] should be used instead.
35614  **
35615  ** The formula above is for computing the action when the lookahead is
35616  ** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
35617 @@ -168,7 +168,7 @@
35618  
35619  /* The next table maps tokens into fallback tokens.  If a construct
35620  ** like the following:
35621 -** 
35622 +**
35623  **      %fallback ID X Y Z.
35624  **
35625  ** appears in the grammer, then ID becomes a fallback token for X, Y,
35626 @@ -219,10 +219,10 @@
35627  #endif /* NDEBUG */
35628  
35629  #ifndef NDEBUG
35630 -/* 
35631 +/*
35632  ** Turn parser tracing on by giving a stream to which to write the trace
35633  ** and a prompt to preface each trace message.  Tracing is turned off
35634 -** by making either argument NULL 
35635 +** by making either argument NULL
35636  **
35637  ** Inputs:
35638  ** <ul>
35639 @@ -247,7 +247,7 @@
35640  #ifndef NDEBUG
35641  /* For tracing shifts, the names of all terminals and nonterminals
35642  ** are required.  The following table supplies these names */
35643 -static const char *yyTokenName[] = { 
35644 +static const char *yyTokenName[] = {
35645    "$",             "AND",           "OR",            "EQ",          
35646    "NE",            "GT",            "GE",            "LT",          
35647    "LE",            "NOT",           "LPARAN",        "RPARAN",      
35648 @@ -295,7 +295,7 @@
35649  #endif
35650  }
35651  
35652 -/* 
35653 +/*
35654  ** This function allocates a new parser.
35655  ** The only argument is a pointer to a function which works like
35656  ** malloc.
35657 @@ -326,7 +326,7 @@
35658      /* Here is inserted the actions which take place when a
35659      ** terminal or non-terminal is destroyed.  This can happen
35660      ** when the symbol is popped from the stack during a
35661 -    ** reduce or during error processing or when a parser is 
35662 +    ** reduce or during error processing or when a parser is
35663      ** being destroyed before it is finished parsing.
35664      **
35665      ** Note: during a reduce, the only symbols destroyed are those
35666 @@ -379,7 +379,7 @@
35667    return yymajor;
35668  }
35669  
35670 -/* 
35671 +/*
35672  ** Deallocate and destroy a parser.  Destructors are all called for
35673  ** all stack elements before shutting the parser down.
35674  **
35675 @@ -415,7 +415,7 @@
35676  ){
35677    int i;
35678    int stateno = pParser->yystack[pParser->yyidx].stateno;
35679
35680 +
35681    /* if( pParser->yyidx<0 ) return YY_NO_ACTION;  */
35682    i = yy_shift_ofst[stateno];
35683    if( i==YY_SHIFT_USE_DFLT ){
35684 @@ -459,7 +459,7 @@
35685  ){
35686    int i;
35687    int stateno = pParser->yystack[pParser->yyidx].stateno;
35688
35689 +
35690    i = yy_reduce_ofst[stateno];
35691    if( i==YY_REDUCE_USE_DFLT ){
35692      return yy_default[stateno];
35693 @@ -559,7 +559,7 @@
35694    ssiexprparserARG_FETCH;
35695    yymsp = &yypParser->yystack[yypParser->yyidx];
35696  #ifndef NDEBUG
35697 -  if( yyTraceFILE && yyruleno>=0 
35698 +  if( yyTraceFILE && yyruleno>=0
35699          && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
35700      fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
35701        yyRuleName[yyruleno]);
35702 @@ -872,7 +872,7 @@
35703  #ifdef YYERRORSYMBOL
35704        /* A syntax error has occurred.
35705        ** The response to an error depends upon whether or not the
35706 -      ** grammar defines an error token "ERROR".  
35707 +      ** grammar defines an error token "ERROR".
35708        **
35709        ** This is what we do if the grammar does define ERROR:
35710        **
35711 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_staticfile.c lighttpd-1.4.12/src/mod_staticfile.c
35712 --- lighttpd-1.4.11/src/mod_staticfile.c        2006-02-15 14:31:14.000000000 +0200
35713 +++ lighttpd-1.4.12/src/mod_staticfile.c        2006-07-11 21:23:39.000000000 +0300
35714 @@ -14,9 +14,11 @@
35715  #include "http_chunk.h"
35716  #include "response.h"
35717  
35718 +#include "sys-files.h"
35719 +#include "sys-strings.h"
35720  /**
35721   * this is a staticfile for a lighttpd plugin
35722 - * 
35723 + *
35724   */
35725  
35726  
35727 @@ -29,48 +31,48 @@
35728  
35729  typedef struct {
35730         PLUGIN_DATA;
35731 -       
35732 +
35733         buffer *range_buf;
35734 -       
35735 +
35736         plugin_config **config_storage;
35737 -       
35738 -       plugin_config conf; 
35739 +
35740 +       plugin_config conf;
35741  } plugin_data;
35742  
35743  /* init the plugin data */
35744  INIT_FUNC(mod_staticfile_init) {
35745         plugin_data *p;
35746 -       
35747 +
35748         p = calloc(1, sizeof(*p));
35749 -       
35750 +
35751         p->range_buf = buffer_init();
35752 -       
35753 +
35754         return p;
35755  }
35756  
35757 -/* detroy the plugin data */
35758 +/* destroy the plugin data */
35759  FREE_FUNC(mod_staticfile_free) {
35760         plugin_data *p = p_d;
35761 -       
35762 +
35763         UNUSED(srv);
35764  
35765         if (!p) return HANDLER_GO_ON;
35766 -       
35767 +
35768         if (p->config_storage) {
35769                 size_t i;
35770                 for (i = 0; i < srv->config_context->used; i++) {
35771                         plugin_config *s = p->config_storage[i];
35772 -                       
35773 +
35774                         array_free(s->exclude_ext);
35775 -                       
35776 +
35777                         free(s);
35778                 }
35779                 free(p->config_storage);
35780         }
35781         buffer_free(p->range_buf);
35782 -       
35783 +
35784         free(p);
35785 -       
35786 +
35787         return HANDLER_GO_ON;
35788  }
35789  
35790 @@ -79,63 +81,60 @@
35791  SETDEFAULTS_FUNC(mod_staticfile_set_defaults) {
35792         plugin_data *p = p_d;
35793         size_t i = 0;
35794 -       
35795 -       config_values_t cv[] = { 
35796 +
35797 +       config_values_t cv[] = {
35798                 { "static-file.exclude-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
35799                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
35800         };
35801 -       
35802 +
35803         if (!p) return HANDLER_ERROR;
35804 -       
35805 +
35806         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
35807 -       
35808 +
35809         for (i = 0; i < srv->config_context->used; i++) {
35810                 plugin_config *s;
35811 -               
35812 +
35813                 s = calloc(1, sizeof(plugin_config));
35814                 s->exclude_ext    = array_init();
35815 -               
35816 +
35817                 cv[0].destination = s->exclude_ext;
35818 -               
35819 +
35820                 p->config_storage[i] = s;
35821 -       
35822 +
35823                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
35824                         return HANDLER_ERROR;
35825                 }
35826         }
35827 -       
35828 +
35829         return HANDLER_GO_ON;
35830  }
35831  
35832 -#define PATCH(x) \
35833 -       p->conf.x = s->x;
35834  static int mod_staticfile_patch_connection(server *srv, connection *con, plugin_data *p) {
35835         size_t i, j;
35836         plugin_config *s = p->config_storage[0];
35837 -       
35838 -       PATCH(exclude_ext);
35839 -       
35840 +
35841 +       PATCH_OPTION(exclude_ext);
35842 +
35843         /* skip the first, the global context */
35844         for (i = 1; i < srv->config_context->used; i++) {
35845                 data_config *dc = (data_config *)srv->config_context->data[i];
35846                 s = p->config_storage[i];
35847 -               
35848 +
35849                 /* condition didn't match */
35850                 if (!config_check_cond(srv, con, dc)) continue;
35851 -               
35852 +
35853                 /* merge config */
35854                 for (j = 0; j < dc->value->used; j++) {
35855                         data_unset *du = dc->value->data[j];
35856 -                       
35857 +
35858                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("static-file.exclude-extensions"))) {
35859 -                               PATCH(exclude_ext);
35860 +                               PATCH_OPTION(exclude_ext);
35861                         }
35862                 }
35863         }
35864 -       
35865 +
35866         return 0;
35867  }
35868 -#undef PATCH
35869  
35870  static int http_response_parse_range(server *srv, connection *con, plugin_data *p) {
35871         int multipart = 0;
35872 @@ -146,69 +145,69 @@
35873         data_string *ds;
35874         stat_cache_entry *sce = NULL;
35875         buffer *content_type = NULL;
35876 -       
35877 +
35878         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
35879                 SEGFAULT();
35880         }
35881 -       
35882 +
35883         start = 0;
35884         end = sce->st.st_size - 1;
35885 -       
35886 +
35887         con->response.content_length = 0;
35888 -       
35889 +
35890         if (NULL != (ds = (data_string *)array_get_element(con->response.headers, "Content-Type"))) {
35891                 content_type = ds->value;
35892         }
35893 -       
35894 +
35895         for (s = con->request.http_range, error = 0;
35896              !error && *s && NULL != (minus = strchr(s, '-')); ) {
35897                 char *err;
35898                 off_t la, le;
35899 -               
35900 +
35901                 if (s == minus) {
35902                         /* -<stop> */
35903 -                       
35904 +
35905                         le = strtoll(s, &err, 10);
35906 -                       
35907 +
35908                         if (le == 0) {
35909                                 /* RFC 2616 - 14.35.1 */
35910 -                               
35911 +
35912                                 con->http_status = 416;
35913                                 error = 1;
35914                         } else if (*err == '\0') {
35915                                 /* end */
35916                                 s = err;
35917 -                               
35918 +
35919                                 end = sce->st.st_size - 1;
35920                                 start = sce->st.st_size + le;
35921                         } else if (*err == ',') {
35922                                 multipart = 1;
35923                                 s = err + 1;
35924 -                               
35925 +
35926                                 end = sce->st.st_size - 1;
35927                                 start = sce->st.st_size + le;
35928                         } else {
35929                                 error = 1;
35930                         }
35931 -                       
35932 +
35933                 } else if (*(minus+1) == '\0' || *(minus+1) == ',') {
35934                         /* <start>- */
35935 -                       
35936 +
35937                         la = strtoll(s, &err, 10);
35938 -                       
35939 +
35940                         if (err == minus) {
35941                                 /* ok */
35942 -                               
35943 +
35944                                 if (*(err + 1) == '\0') {
35945                                         s = err + 1;
35946 -                                       
35947 +
35948                                         end = sce->st.st_size - 1;
35949                                         start = la;
35950 -                                       
35951 +
35952                                 } else if (*(err + 1) == ',') {
35953                                         multipart = 1;
35954                                         s = err + 2;
35955 -                                       
35956 +
35957                                         end = sce->st.st_size - 1;
35958                                         start = la;
35959                                 } else {
35960 @@ -220,64 +219,64 @@
35961                         }
35962                 } else {
35963                         /* <start>-<stop> */
35964 -                       
35965 +
35966                         la = strtoll(s, &err, 10);
35967 -                       
35968 +
35969                         if (err == minus) {
35970                                 le = strtoll(minus+1, &err, 10);
35971 -                               
35972 +
35973                                 /* RFC 2616 - 14.35.1 */
35974                                 if (la > le) {
35975                                         error = 1;
35976                                 }
35977 -                                       
35978 +
35979                                 if (*err == '\0') {
35980                                         /* ok, end*/
35981                                         s = err;
35982 -                                       
35983 +
35984                                         end = le;
35985                                         start = la;
35986                                 } else if (*err == ',') {
35987                                         multipart = 1;
35988                                         s = err + 1;
35989 -                                       
35990 +
35991                                         end = le;
35992                                         start = la;
35993                                 } else {
35994                                         /* error */
35995 -                                       
35996 +
35997                                         error = 1;
35998                                 }
35999                         } else {
36000                                 /* error */
36001 -                               
36002 +
36003                                 error = 1;
36004                         }
36005                 }
36006 -               
36007 +
36008                 if (!error) {
36009                         if (start < 0) start = 0;
36010 -                       
36011 +
36012                         /* RFC 2616 - 14.35.1 */
36013                         if (end > sce->st.st_size - 1) end = sce->st.st_size - 1;
36014 -                       
36015 +
36016                         if (start > sce->st.st_size - 1) {
36017                                 error = 1;
36018 -                               
36019 +
36020                                 con->http_status = 416;
36021                         }
36022                 }
36023 -               
36024 +
36025                 if (!error) {
36026                         if (multipart) {
36027                                 /* write boundary-header */
36028                                 buffer *b;
36029 -                               
36030 +
36031                                 b = chunkqueue_get_append_buffer(con->write_queue);
36032 -                               
36033 +
36034                                 buffer_copy_string(b, "\r\n--");
36035                                 buffer_append_string(b, boundary);
36036 -                               
36037 +
36038                                 /* write Content-Range */
36039                                 buffer_append_string(b, "\r\nContent-Range: bytes ");
36040                                 buffer_append_off_t(b, start);
36041 @@ -285,54 +284,54 @@
36042                                 buffer_append_off_t(b, end);
36043                                 buffer_append_string(b, "/");
36044                                 buffer_append_off_t(b, sce->st.st_size);
36045 -                               
36046 +
36047                                 buffer_append_string(b, "\r\nContent-Type: ");
36048                                 buffer_append_string_buffer(b, content_type);
36049 -                               
36050 +
36051                                 /* write END-OF-HEADER */
36052                                 buffer_append_string(b, "\r\n\r\n");
36053 -                               
36054 +
36055                                 con->response.content_length += b->used - 1;
36056 -                               
36057 +
36058                         }
36059 -                       
36060 +
36061                         chunkqueue_append_file(con->write_queue, con->physical.path, start, end - start + 1);
36062                         con->response.content_length += end - start + 1;
36063                 }
36064         }
36065 -       
36066 +
36067         /* something went wrong */
36068         if (error) return -1;
36069 -       
36070 +
36071         if (multipart) {
36072                 /* add boundary end */
36073                 buffer *b;
36074 -               
36075 +
36076                 b = chunkqueue_get_append_buffer(con->write_queue);
36077 -               
36078 +
36079                 buffer_copy_string_len(b, "\r\n--", 4);
36080                 buffer_append_string(b, boundary);
36081                 buffer_append_string_len(b, "--\r\n", 4);
36082 -               
36083 +
36084                 con->response.content_length += b->used - 1;
36085 -               
36086 +
36087                 /* set header-fields */
36088 -               
36089 +
36090                 buffer_copy_string(p->range_buf, "multipart/byteranges; boundary=");
36091                 buffer_append_string(p->range_buf, boundary);
36092 -               
36093 +
36094                 /* overwrite content-type */
36095                 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(p->range_buf));
36096         } else {
36097                 /* add Content-Range-header */
36098 -               
36099 +
36100                 buffer_copy_string(p->range_buf, "bytes ");
36101                 buffer_append_off_t(p->range_buf, start);
36102                 buffer_append_string(p->range_buf, "-");
36103                 buffer_append_off_t(p->range_buf, end);
36104                 buffer_append_string(p->range_buf, "/");
36105                 buffer_append_off_t(p->range_buf, sce->st.st_size);
36106 -               
36107 +
36108                 response_header_insert(srv, con, CONST_STR_LEN("Content-Range"), CONST_BUF_LEN(p->range_buf));
36109         }
36110  
36111 @@ -347,12 +346,12 @@
36112         stat_cache_entry *sce = NULL;
36113         buffer *mtime;
36114         data_string *ds;
36115 -       
36116 +
36117         /* someone else has done a decision for us */
36118         if (con->http_status != 0) return HANDLER_GO_ON;
36119         if (con->uri.path->used == 0) return HANDLER_GO_ON;
36120         if (con->physical.path->used == 0) return HANDLER_GO_ON;
36121 -       
36122 +
36123         /* someone else has handled this request */
36124         if (con->mode != DIRECT) return HANDLER_GO_ON;
36125  
36126 @@ -365,52 +364,52 @@
36127         default:
36128                 return HANDLER_GO_ON;
36129         }
36130 -       
36131 +
36132         mod_staticfile_patch_connection(srv, con, p);
36133 -       
36134 +
36135         s_len = con->uri.path->used - 1;
36136 -       
36137 +
36138         /* ignore certain extensions */
36139         for (k = 0; k < p->conf.exclude_ext->used; k++) {
36140 -               ds = (data_string *)p->conf.exclude_ext->data[k]; 
36141 -               
36142 +               ds = (data_string *)p->conf.exclude_ext->data[k];
36143 +
36144                 if (ds->value->used == 0) continue;
36145  
36146                 if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
36147                         return HANDLER_GO_ON;
36148                 }
36149         }
36150 -       
36151 +
36152  
36153         if (con->conf.log_request_handling) {
36154                 log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling file as static file");
36155         }
36156 -       
36157 +
36158         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
36159                 con->http_status = 403;
36160 -               
36161 +
36162                 log_error_write(srv, __FILE__, __LINE__, "sbsb",
36163                                 "not a regular file:", con->uri.path,
36164                                 "->", con->physical.path);
36165 -               
36166 +
36167                 return HANDLER_FINISHED;
36168         }
36169 -       
36170 -       /* we only handline regular files */
36171 +
36172 +       /* we only handle regular files */
36173         if (!S_ISREG(sce->st.st_mode)) {
36174                 con->http_status = 404;
36175 -               
36176 +
36177                 if (con->conf.log_file_not_found) {
36178                         log_error_write(srv, __FILE__, __LINE__, "sbsb",
36179                                         "not a regular file:", con->uri.path,
36180                                         "->", sce->name);
36181                 }
36182 -               
36183 +
36184                 return HANDLER_FINISHED;
36185         }
36186  
36187 -       /* mod_compress might set several data directly, don't overwrite them */
36188 -       
36189 +       /* mod_compress might set several parameters directly; don't overwrite them */
36190 +
36191         /* set response content-type, if not set already */
36192  
36193         if (NULL == array_get_element(con->response.headers, "Content-Type")) {
36194 @@ -420,15 +419,15 @@
36195                         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
36196                 }
36197         }
36198 -       
36199 +
36200         if (NULL == array_get_element(con->response.headers, "ETag")) {
36201                 /* generate e-tag */
36202                 etag_mutate(con->physical.etag, sce->etag);
36203 -       
36204 +
36205                 response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
36206         }
36207         response_header_overwrite(srv, con, CONST_STR_LEN("Accept-Ranges"), CONST_STR_LEN("bytes"));
36208 -       
36209 +
36210         /* prepare header */
36211         if (NULL == (ds = (data_string *)array_get_element(con->response.headers, "Last-Modified"))) {
36212                 mtime = strftime_cache_get(srv, sce->st.st_mtime);
36213 @@ -444,34 +443,34 @@
36214                 /* check if we have a conditional GET */
36215  
36216                 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If-Range"))) {
36217 -                       /* if the value is the same as our ETag, we do a Range-request, 
36218 +                       /* if the value is the same as our ETag, we do a Range-request,
36219                          * otherwise a full 200 */
36220  
36221                         if (!buffer_is_equal(ds->value, con->physical.etag)) {
36222                                 do_range_request = 0;
36223                         }
36224                 }
36225 -       
36226 +
36227                 if (do_range_request) {
36228                         /* content prepared, I'm done */
36229                         con->file_finished = 1;
36230 -               
36231 +
36232                         if (0 == http_response_parse_range(srv, con, p)) {
36233                                 con->http_status = 206;
36234                         }
36235                         return HANDLER_FINISHED;
36236                 }
36237         }
36238 -       
36239 +
36240         /* if we are still here, prepare body */
36241 -       
36242 -       /* we add it here for all requests 
36243 -        * the HEAD request will drop it afterwards again 
36244 +
36245 +       /* we add it here for all requests
36246 +        * the HEAD request will drop it afterwards again
36247          */
36248         http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
36249 -       
36250 +
36251         con->file_finished = 1;
36252 -       
36253 +
36254         return HANDLER_FINISHED;
36255  }
36256  
36257 @@ -480,13 +479,13 @@
36258  int mod_staticfile_plugin_init(plugin *p) {
36259         p->version     = LIGHTTPD_VERSION_ID;
36260         p->name        = buffer_init_string("staticfile");
36261 -       
36262 +
36263         p->init        = mod_staticfile_init;
36264         p->handle_subrequest_start = mod_staticfile_subrequest;
36265         p->set_defaults  = mod_staticfile_set_defaults;
36266         p->cleanup     = mod_staticfile_free;
36267 -       
36268 +
36269         p->data        = NULL;
36270 -       
36271 +
36272         return 0;
36273  }
36274 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_status.c lighttpd-1.4.12/src/mod_status.c
36275 --- lighttpd-1.4.11/src/mod_status.c    2006-01-10 21:45:32.000000000 +0200
36276 +++ lighttpd-1.4.12/src/mod_status.c    2006-07-11 21:23:40.000000000 +0300
36277 @@ -4,7 +4,6 @@
36278  #include <fcntl.h>
36279  #include <stdlib.h>
36280  #include <string.h>
36281 -#include <unistd.h>
36282  #include <errno.h>
36283  #include <time.h>
36284  #include <stdio.h>
36285 @@ -29,114 +28,114 @@
36286  
36287  typedef struct {
36288         PLUGIN_DATA;
36289 -       
36290 +
36291         double traffic_out;
36292         double requests;
36293 -       
36294 +
36295         double mod_5s_traffic_out[5];
36296         double mod_5s_requests[5];
36297         size_t mod_5s_ndx;
36298 -       
36299 +
36300         double rel_traffic_out;
36301         double rel_requests;
36302 -       
36303 +
36304         double abs_traffic_out;
36305         double abs_requests;
36306 -       
36307 +
36308         double bytes_written;
36309 -       
36310 +
36311         buffer *module_list;
36312 -       
36313 +
36314         plugin_config **config_storage;
36315 -       
36316 -       plugin_config conf; 
36317 +
36318 +       plugin_config conf;
36319  } plugin_data;
36320  
36321  INIT_FUNC(mod_status_init) {
36322         plugin_data *p;
36323         size_t i;
36324 -       
36325 +
36326         p = calloc(1, sizeof(*p));
36327 -       
36328 +
36329         p->traffic_out = p->requests = 0;
36330         p->rel_traffic_out = p->rel_requests = 0;
36331         p->abs_traffic_out = p->abs_requests = 0;
36332         p->bytes_written = 0;
36333         p->module_list = buffer_init();
36334 -       
36335 +
36336         for (i = 0; i < 5; i++) {
36337                 p->mod_5s_traffic_out[i] = p->mod_5s_requests[i] = 0;
36338         }
36339 -       
36340 +
36341         return p;
36342  }
36343  
36344  FREE_FUNC(mod_status_free) {
36345         plugin_data *p = p_d;
36346 -       
36347 +
36348         UNUSED(srv);
36349  
36350         if (!p) return HANDLER_GO_ON;
36351 -       
36352 +
36353         buffer_free(p->module_list);
36354 -       
36355 +
36356         if (p->config_storage) {
36357                 size_t i;
36358                 for (i = 0; i < srv->config_context->used; i++) {
36359                         plugin_config *s = p->config_storage[i];
36360 -                       
36361 +
36362                         buffer_free(s->status_url);
36363                         buffer_free(s->statistics_url);
36364                         buffer_free(s->config_url);
36365 -                       
36366 +
36367                         free(s);
36368                 }
36369                 free(p->config_storage);
36370         }
36371 -       
36372 -       
36373 +
36374 +
36375         free(p);
36376 -       
36377 +
36378         return HANDLER_GO_ON;
36379  }
36380  
36381  SETDEFAULTS_FUNC(mod_status_set_defaults) {
36382         plugin_data *p = p_d;
36383         size_t i;
36384 -       
36385 -       config_values_t cv[] = { 
36386 +
36387 +       config_values_t cv[] = {
36388                 { "status.status-url",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
36389                 { "status.config-url",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
36390                 { "status.enable-sort",          NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
36391                 { "status.statistics-url",       NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
36392                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
36393         };
36394 -       
36395 +
36396         if (!p) return HANDLER_ERROR;
36397 -       
36398 +
36399         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
36400 -       
36401 +
36402         for (i = 0; i < srv->config_context->used; i++) {
36403                 plugin_config *s;
36404 -               
36405 +
36406                 s = calloc(1, sizeof(plugin_config));
36407                 s->config_url    = buffer_init();
36408                 s->status_url    = buffer_init();
36409                 s->sort          = 1;
36410                 s->statistics_url    = buffer_init();
36411 -               
36412 +
36413                 cv[0].destination = s->status_url;
36414                 cv[1].destination = s->config_url;
36415                 cv[2].destination = &(s->sort);
36416                 cv[3].destination = s->statistics_url;
36417 -               
36418 +
36419                 p->config_storage[i] = s;
36420 -       
36421 +
36422                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
36423                         return HANDLER_ERROR;
36424                 }
36425         }
36426 -       
36427 +
36428         return HANDLER_GO_ON;
36429  }
36430  
36431 @@ -151,7 +150,7 @@
36432         buffer_append_string(b, value);
36433         BUFFER_APPEND_STRING_CONST(b, "</td>\n");
36434         BUFFER_APPEND_STRING_CONST(b, "   </tr>\n");
36435 -       
36436 +
36437         return 0;
36438  }
36439  
36440 @@ -161,13 +160,13 @@
36441         buffer_append_string(b, key);
36442         BUFFER_APPEND_STRING_CONST(b, "</th>\n");
36443         BUFFER_APPEND_STRING_CONST(b, "   </tr>\n");
36444 -       
36445 +
36446         return 0;
36447  }
36448  
36449  static int mod_status_header_append_sort(buffer *b, void *p_d, const char* key) {
36450         plugin_data *p = p_d;
36451 -       
36452 +
36453         if (p->conf.sort) {
36454                 BUFFER_APPEND_STRING_CONST(b, "<th class=\"status\"><a href=\"#\" class=\"sortheader\" onclick=\"resort(this);return false;\">");
36455                 buffer_append_string(b, key);
36456 @@ -177,13 +176,13 @@
36457                 buffer_append_string(b, key);
36458                 BUFFER_APPEND_STRING_CONST(b, "</th>\n");
36459         }
36460 -       
36461 +
36462         return 0;
36463  }
36464  
36465  static int mod_status_get_multiplier(double *avg, char *multiplier, int size) {
36466         *multiplier = ' ';
36467 -       
36468 +
36469         if (*avg > size) { *avg /= size; *multiplier = 'k'; }
36470         if (*avg > size) { *avg /= size; *multiplier = 'M'; }
36471         if (*avg > size) { *avg /= size; *multiplier = 'G'; }
36472 @@ -202,21 +201,21 @@
36473         size_t j;
36474         double avg;
36475         char multiplier = '\0';
36476 -       char buf[32];
36477 +       char buf[128];
36478         time_t ts;
36479 -       
36480 +
36481         int days, hours, mins, seconds;
36482 -       
36483 +
36484         b = chunkqueue_get_append_buffer(con->write_queue);
36485  
36486 -       BUFFER_COPY_STRING_CONST(b, 
36487 +       BUFFER_COPY_STRING_CONST(b,
36488                                  "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
36489                                  "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
36490                                  "         \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
36491                                  "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
36492                                  " <head>\n"
36493                                  "  <title>Status</title>\n");
36494 -       
36495 +
36496         BUFFER_APPEND_STRING_CONST(b,
36497                                    "  <style type=\"text/css\">\n"
36498                                    "    table.status { border: black solid thin; }\n"
36499 @@ -226,14 +225,14 @@
36500                                    "    a.sortheader { background-color: black; color: white; font-weight: bold; text-decoration: none; display: block; }\n"
36501                                    "    span.sortarrow { color: white; text-decoration: none; }\n"
36502                                    "  </style>\n");
36503 -       
36504 +
36505         if (p->conf.sort) {
36506                 BUFFER_APPEND_STRING_CONST(b,
36507                                            "<script type=\"text/javascript\">\n"
36508                                            "// <!--\n"
36509                                            "var sort_column;\n"
36510                                            "var prev_span = null;\n");
36511 -               
36512 +
36513                 BUFFER_APPEND_STRING_CONST(b,
36514                                            "function get_inner_text(el) {\n"
36515                                            " if((typeof el == 'string')||(typeof el == 'undefined'))\n"
36516 @@ -251,7 +250,7 @@
36517                                            " }\n"
36518                                            " return str;\n"
36519                                            "}\n");
36520 -               
36521 +
36522                 BUFFER_APPEND_STRING_CONST(b,
36523                                            "function sortfn(a,b) {\n"
36524                                            " var at = get_inner_text(a.cells[sort_column]);\n"
36525 @@ -266,7 +265,7 @@
36526                                            "  else return 1;\n"
36527                                            " }\n"
36528                                            "}\n");
36529 -               
36530 +
36531                 BUFFER_APPEND_STRING_CONST(b,
36532                                            "function resort(lnk) {\n"
36533                                            " var span = lnk.childNodes[1];\n"
36534 @@ -276,7 +275,7 @@
36535                                            "  rows[j-1] = table.rows[j];\n"
36536                                            " sort_column = lnk.parentNode.cellIndex;\n"
36537                                            " rows.sort(sortfn);\n");
36538 -               
36539 +
36540                 BUFFER_APPEND_STRING_CONST(b,
36541                                            " if (prev_span != null) prev_span.innerHTML = '';\n"
36542                                            " if (span.getAttribute('sortdir')=='down') {\n"
36543 @@ -294,175 +293,175 @@
36544                                            "// -->\n"
36545                                            "</script>\n");
36546         }
36547 -       
36548 -       BUFFER_APPEND_STRING_CONST(b, 
36549 +
36550 +       BUFFER_APPEND_STRING_CONST(b,
36551                                  " </head>\n"
36552                                  " <body>\n");
36553 -       
36554 -       
36555 -       
36556 +
36557 +
36558 +
36559         /* connection listing */
36560         BUFFER_APPEND_STRING_CONST(b, "<h1>Server-Status</h1>");
36561 -       
36562 -       BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">");
36563 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\">");
36564 +
36565 +       BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" id=\"status\" summary=\"Server Status\">");
36566 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\"><span id=\"host_addr\">");
36567         buffer_append_string_buffer(b, con->uri.authority);
36568 -       BUFFER_APPEND_STRING_CONST(b, " (");
36569 +       BUFFER_APPEND_STRING_CONST(b, "</span> (<span id=\"host_name\">");
36570         buffer_append_string_buffer(b, con->server_name);
36571 -       BUFFER_APPEND_STRING_CONST(b, ")</td></tr>\n");
36572 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\">");
36573 -       
36574 +       BUFFER_APPEND_STRING_CONST(b, "</span>)</td></tr>\n");
36575 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\" id=\"uptime\">");
36576 +
36577         ts = srv->cur_ts - srv->startup_ts;
36578 -       
36579 +
36580         days = ts / (60 * 60 * 24);
36581         ts %= (60 * 60 * 24);
36582 -       
36583 +
36584         hours = ts / (60 * 60);
36585         ts %= (60 * 60);
36586 -       
36587 +
36588         mins = ts / (60);
36589         ts %= (60);
36590 -       
36591 +
36592         seconds = ts;
36593 -       
36594 +
36595         if (days) {
36596                 buffer_append_long(b, days);
36597                 BUFFER_APPEND_STRING_CONST(b, " days ");
36598         }
36599 -       
36600 +
36601         if (hours) {
36602                 buffer_append_long(b, hours);
36603                 BUFFER_APPEND_STRING_CONST(b, " hours ");
36604         }
36605 -       
36606 +
36607         if (mins) {
36608                 buffer_append_long(b, mins);
36609                 BUFFER_APPEND_STRING_CONST(b, " min ");
36610         }
36611 -       
36612 +
36613         buffer_append_long(b, seconds);
36614         BUFFER_APPEND_STRING_CONST(b, " s");
36615 -       
36616 +
36617         BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36618         BUFFER_APPEND_STRING_CONST(b, "<tr><td>Started at</td><td class=\"string\">");
36619 -       
36620 +
36621         ts = srv->startup_ts;
36622 -       
36623 -       strftime(buf, sizeof(buf) - 1, "%Y-%m-%d %H:%M:%S", localtime(&ts));
36624 +
36625 +       strftime(buf, sizeof(buf) - 1, "<span id=\"start_date\">%Y-%m-%d</span> <span id=\"start_time\">%H:%M:%S</span>", localtime(&ts));
36626         buffer_append_string(b, buf);
36627         BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36628 -       
36629 -       
36630 +
36631 +
36632         BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">absolute (since start)</th></tr>\n");
36633 -       
36634 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36635 +
36636 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\" ><span id=\"requests\">");
36637         avg = p->abs_requests;
36638  
36639         mod_status_get_multiplier(&avg, &multiplier, 1000);
36640 -       
36641 +
36642         buffer_append_long(b, avg);
36643 -       BUFFER_APPEND_STRING_CONST(b, " ");
36644 +       BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_mult\">");
36645         if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36646 -       BUFFER_APPEND_STRING_CONST(b, "req</td></tr>\n");
36647 -       
36648 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36649 +       BUFFER_APPEND_STRING_CONST(b, "</span>req</td></tr>\n");
36650 +
36651 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic\">");
36652         avg = p->abs_traffic_out;
36653  
36654         mod_status_get_multiplier(&avg, &multiplier, 1024);
36655  
36656         sprintf(buf, "%.2f", avg);
36657         buffer_append_string(b, buf);
36658 -       BUFFER_APPEND_STRING_CONST(b, " ");
36659 +       BUFFER_APPEND_STRING_CONST(b, "</span>  <span id=\"traffic_mult\">");
36660         if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36661 -       BUFFER_APPEND_STRING_CONST(b, "byte</td></tr>\n");
36662 +       BUFFER_APPEND_STRING_CONST(b, "</span>byte</td></tr>\n");
36663  
36664  
36665  
36666         BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (since start)</th></tr>\n");
36667 -       
36668 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36669 +
36670 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_avg\">");
36671         avg = p->abs_requests / (srv->cur_ts - srv->startup_ts);
36672  
36673         mod_status_get_multiplier(&avg, &multiplier, 1000);
36674  
36675         buffer_append_long(b, avg);
36676 -       BUFFER_APPEND_STRING_CONST(b, " ");
36677 +       BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_avg_mult\">");
36678         if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36679 -       BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
36680 -       
36681 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36682 +       BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
36683 +
36684 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic_avg\">");
36685         avg = p->abs_traffic_out / (srv->cur_ts - srv->startup_ts);
36686  
36687         mod_status_get_multiplier(&avg, &multiplier, 1024);
36688  
36689         sprintf(buf, "%.2f", avg);
36690         buffer_append_string(b, buf);
36691 -       BUFFER_APPEND_STRING_CONST(b, " ");
36692 +       BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"traffic_avg_mult\">");
36693         if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36694 -       BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
36695 +       BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
36696 +
36697 +
36698  
36699 -       
36700 -       
36701         BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (5s sliding average)</th></tr>\n");
36702         for (j = 0, avg = 0; j < 5; j++) {
36703                 avg += p->mod_5s_requests[j];
36704         }
36705 -       
36706 +
36707         avg /= 5;
36708 -       
36709 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
36710 +
36711 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_sliding_avg\">");
36712  
36713         mod_status_get_multiplier(&avg, &multiplier, 1000);
36714  
36715         buffer_append_long(b, avg);
36716 -       BUFFER_APPEND_STRING_CONST(b, " ");
36717 +       BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_avg_mult\">");
36718         if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36719 -       
36720 -       BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
36721 -       
36722 +
36723 +       BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
36724 +
36725         for (j = 0, avg = 0; j < 5; j++) {
36726                 avg += p->mod_5s_traffic_out[j];
36727         }
36728 -       
36729 +
36730         avg /= 5;
36731 -       
36732 -       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
36733 +
36734 +       BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"requests_sliding_traffic\">");
36735  
36736         mod_status_get_multiplier(&avg, &multiplier, 1024);
36737  
36738         sprintf(buf, "%.2f", avg);
36739         buffer_append_string(b, buf);
36740 -       BUFFER_APPEND_STRING_CONST(b, " ");
36741 +       BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_traffic_mult\">");
36742         if (multiplier) buffer_append_string_len(b, &multiplier, 1);
36743 -       BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
36744 -       
36745 +       BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
36746 +
36747         BUFFER_APPEND_STRING_CONST(b, "</table>\n");
36748 -       
36749 -       
36750 +
36751 +
36752         BUFFER_APPEND_STRING_CONST(b, "<hr />\n<pre><b>legend</b>\n");
36753         BUFFER_APPEND_STRING_CONST(b, ". = connect, C = close, E = hard error\n");
36754         BUFFER_APPEND_STRING_CONST(b, "r = read, R = read-POST, W = write, h = handle-request\n");
36755         BUFFER_APPEND_STRING_CONST(b, "q = request-start,  Q = request-end\n");
36756         BUFFER_APPEND_STRING_CONST(b, "s = response-start, S = response-end\n");
36757 -       
36758 -       BUFFER_APPEND_STRING_CONST(b, "<b>");
36759 +
36760 +       BUFFER_APPEND_STRING_CONST(b, "<strong><span id=\"connections\">");
36761         buffer_append_long(b, srv->conns->used);
36762 -       BUFFER_APPEND_STRING_CONST(b, " connections</b>\n");
36763 -       
36764 +       BUFFER_APPEND_STRING_CONST(b, "</span> connections</strong>\n");
36765 +
36766         for (j = 0; j < srv->conns->used; j++) {
36767                 connection *c = srv->conns->ptr[j];
36768                 const char *state = connection_get_short_state(c->state);
36769 -               
36770 +
36771                 buffer_append_string_len(b, state, 1);
36772 -               
36773 +
36774                 if (((j + 1) % 50) == 0) {
36775                         BUFFER_APPEND_STRING_CONST(b, "\n");
36776                 }
36777         }
36778 -       
36779 +
36780         BUFFER_APPEND_STRING_CONST(b, "\n</pre><hr />\n<h2>Connections</h2>\n");
36781 -       
36782 -       BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">\n");
36783 +
36784 +       BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" summary=\"Current connections\" id=\"clients\">\n");
36785         BUFFER_APPEND_STRING_CONST(b, "<tr>");
36786         mod_status_header_append_sort(b, p_d, "Client IP");
36787         mod_status_header_append_sort(b, p_d, "Read");
36788 @@ -473,16 +472,16 @@
36789         mod_status_header_append_sort(b, p_d, "URI");
36790         mod_status_header_append_sort(b, p_d, "File");
36791         BUFFER_APPEND_STRING_CONST(b, "</tr>\n");
36792 -       
36793 +
36794         for (j = 0; j < srv->conns->used; j++) {
36795                 connection *c = srv->conns->ptr[j];
36796 -               
36797 -               BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string\">");
36798 -               
36799 +
36800 +               BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string ip\">");
36801 +
36802                 buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(c->dst_addr)));
36803 -               
36804 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36805 -               
36806 +
36807 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_read\">");
36808 +
36809                 if (con->request.content_length) {
36810                         buffer_append_long(b, c->request_content_queue->bytes_in);
36811                         BUFFER_APPEND_STRING_CONST(b, "/");
36812 @@ -490,55 +489,55 @@
36813                 } else {
36814                         BUFFER_APPEND_STRING_CONST(b, "0/0");
36815                 }
36816 -       
36817 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36818 -               
36819 +
36820 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_written\">");
36821 +
36822                 buffer_append_off_t(b, chunkqueue_written(c->write_queue));
36823                 BUFFER_APPEND_STRING_CONST(b, "/");
36824                 buffer_append_off_t(b, chunkqueue_length(c->write_queue));
36825 -               
36826 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36827 -               
36828 +
36829 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string state\">");
36830 +
36831                 buffer_append_string(b, connection_get_state(c->state));
36832 -               
36833 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
36834 -               
36835 +
36836 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int time\">");
36837 +
36838                 buffer_append_long(b, srv->cur_ts - c->request_start);
36839 -               
36840 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36841 -               
36842 +
36843 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string host\">");
36844 +
36845                 if (buffer_is_empty(c->server_name)) {
36846                         buffer_append_string_buffer(b, c->uri.authority);
36847                 }
36848                 else {
36849                         buffer_append_string_buffer(b, c->server_name);
36850                 }
36851 -               
36852 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36853 -               
36854 +
36855 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string uri\">");
36856 +
36857                 if (!buffer_is_empty(c->uri.path)) {
36858                         buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.path), ENCODING_HTML);
36859                 }
36860 -               
36861 -               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
36862 -               
36863 +
36864 +               BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string file\">");
36865 +
36866                 buffer_append_string_buffer(b, c->physical.path);
36867 -               
36868 +
36869                 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
36870         }
36871 -       
36872 -       
36873 -       BUFFER_APPEND_STRING_CONST(b, 
36874 +
36875 +
36876 +       BUFFER_APPEND_STRING_CONST(b,
36877                       "</table>\n");
36878 -       
36879 -       
36880 -       BUFFER_APPEND_STRING_CONST(b, 
36881 +
36882 +
36883 +       BUFFER_APPEND_STRING_CONST(b,
36884                       " </body>\n"
36885                       "</html>\n"
36886                       );
36887 -       
36888 +
36889         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
36890 -       
36891 +
36892         return 0;
36893  }
36894  
36895 @@ -548,7 +547,7 @@
36896         buffer *b;
36897         double avg;
36898         time_t ts;
36899 -       
36900 +
36901         b = chunkqueue_get_append_buffer(con->write_queue);
36902  
36903         /* output total number of requests */
36904 @@ -556,19 +555,19 @@
36905         avg = p->abs_requests;
36906         buffer_append_long(b, avg);
36907         BUFFER_APPEND_STRING_CONST(b, "\n");
36908 -       
36909 +
36910         /* output total traffic out in kbytes */
36911         BUFFER_APPEND_STRING_CONST(b, "Total kBytes: ");
36912         avg = p->abs_traffic_out / 1024;
36913         buffer_append_long(b, avg);
36914         BUFFER_APPEND_STRING_CONST(b, "\n");
36915 -       
36916 +
36917         /* output uptime */
36918         BUFFER_APPEND_STRING_CONST(b, "Uptime: ");
36919         ts = srv->cur_ts - srv->startup_ts;
36920         buffer_append_long(b, ts);
36921         BUFFER_APPEND_STRING_CONST(b, "\n");
36922 -       
36923 +
36924         /* output busy servers */
36925         BUFFER_APPEND_STRING_CONST(b, "BusyServers: ");
36926         buffer_append_long(b, srv->conns->used);
36927 @@ -577,7 +576,7 @@
36928         /* set text/plain output */
36929  
36930         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
36931 -       
36932 +
36933         return 0;
36934  }
36935  
36936 @@ -591,10 +590,10 @@
36937                 /* we have nothing to send */
36938                 con->http_status = 204;
36939                 con->file_finished = 1;
36940 -       
36941 +
36942                 return HANDLER_FINISHED;
36943         }
36944 -       
36945 +
36946         b = chunkqueue_get_append_buffer(con->write_queue);
36947  
36948         for (i = 0; i < st->used; i++) {
36949 @@ -605,27 +604,27 @@
36950                 buffer_append_long(b, ((data_integer *)(st->data[ndx]))->value);
36951                 buffer_append_string(b, "\n");
36952         }
36953 -       
36954 +
36955         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
36956 -       
36957 +
36958         con->http_status = 200;
36959         con->file_finished = 1;
36960 -       
36961 +
36962         return HANDLER_FINISHED;
36963  }
36964  
36965  
36966  static handler_t mod_status_handle_server_status(server *srv, connection *con, void *p_d) {
36967 -       
36968 +
36969         if (buffer_is_equal_string(con->uri.query, CONST_STR_LEN("auto"))) {
36970                 mod_status_handle_server_status_text(srv, con, p_d);
36971         } else {
36972                 mod_status_handle_server_status_html(srv, con, p_d);
36973         }
36974 -       
36975 +
36976         con->http_status = 200;
36977         con->file_finished = 1;
36978 -       
36979 +
36980         return HANDLER_FINISHED;
36981  }
36982  
36983 @@ -634,9 +633,9 @@
36984         plugin_data *p = p_d;
36985         buffer *b, *m = p->module_list;
36986         size_t i;
36987 -       
36988 -       struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] = 
36989 -       { 
36990 +
36991 +       struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
36992 +       {
36993                 /* - poll is most reliable
36994                  * - select works everywhere
36995                  * - linux-* are experimental
36996 @@ -661,10 +660,10 @@
36997  #endif
36998                 { FDEVENT_HANDLER_UNSET,          NULL }
36999         };
37000 -       
37001 +
37002         b = chunkqueue_get_append_buffer(con->write_queue);
37003 -       
37004 -       BUFFER_COPY_STRING_CONST(b, 
37005 +
37006 +       BUFFER_COPY_STRING_CONST(b,
37007                            "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
37008                            "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
37009                            "         \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
37010 @@ -675,7 +674,7 @@
37011                            " <body>\n"
37012                            "  <h1>" PACKAGE_NAME " " PACKAGE_VERSION "</h1>\n"
37013                            "  <table border=\"1\">\n");
37014 -       
37015 +
37016         mod_status_header_append(b, "Server-Features");
37017  #ifdef HAVE_PCRE_H
37018         mod_status_row_append(b, "RegEx Conditionals", "enabled");
37019 @@ -683,21 +682,21 @@
37020         mod_status_row_append(b, "RegEx Conditionals", "disabled - pcre missing");
37021  #endif
37022         mod_status_header_append(b, "Network Engine");
37023 -       
37024 +
37025         for (i = 0; event_handlers[i].name; i++) {
37026                 if (event_handlers[i].et == srv->event_handler) {
37027                         mod_status_row_append(b, "fd-Event-Handler", event_handlers[i].name);
37028                         break;
37029                 }
37030         }
37031 -       
37032 +
37033         mod_status_header_append(b, "Config-File-Settings");
37034 -       
37035 +
37036         for (i = 0; i < srv->plugins.used; i++) {
37037                 plugin **ps = srv->plugins.ptr;
37038 -               
37039 +
37040                 plugin *pl = ps[i];
37041 -       
37042 +
37043                 if (i == 0) {
37044                         buffer_copy_string_buffer(m, pl->name);
37045                 } else {
37046 @@ -705,137 +704,135 @@
37047                         buffer_append_string_buffer(m, pl->name);
37048                 }
37049         }
37050 -       
37051 +
37052         mod_status_row_append(b, "Loaded Modules", m->ptr);
37053 -       
37054 +
37055         BUFFER_APPEND_STRING_CONST(b, "  </table>\n");
37056 -       
37057 -       BUFFER_APPEND_STRING_CONST(b, 
37058 +
37059 +       BUFFER_APPEND_STRING_CONST(b,
37060                       " </body>\n"
37061                       "</html>\n"
37062                       );
37063 -       
37064 +
37065         response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
37066 -       
37067 +
37068         con->http_status = 200;
37069         con->file_finished = 1;
37070 -       
37071 +
37072         return HANDLER_FINISHED;
37073  }
37074  
37075 -#define PATCH(x) \
37076 -       p->conf.x = s->x;
37077  static int mod_status_patch_connection(server *srv, connection *con, plugin_data *p) {
37078         size_t i, j;
37079         plugin_config *s = p->config_storage[0];
37080 -       
37081 -       PATCH(status_url);
37082 -       PATCH(config_url);
37083 -       PATCH(sort);
37084 -       PATCH(statistics_url);
37085 -       
37086 +
37087 +       PATCH_OPTION(status_url);
37088 +       PATCH_OPTION(config_url);
37089 +       PATCH_OPTION(sort);
37090 +       PATCH_OPTION(statistics_url);
37091 +
37092         /* skip the first, the global context */
37093         for (i = 1; i < srv->config_context->used; i++) {
37094                 data_config *dc = (data_config *)srv->config_context->data[i];
37095                 s = p->config_storage[i];
37096 -               
37097 +
37098                 /* condition didn't match */
37099                 if (!config_check_cond(srv, con, dc)) continue;
37100 -               
37101 +
37102                 /* merge config */
37103                 for (j = 0; j < dc->value->used; j++) {
37104                         data_unset *du = dc->value->data[j];
37105 -                       
37106 +
37107                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.status-url"))) {
37108 -                               PATCH(status_url);
37109 +                               PATCH_OPTION(status_url);
37110                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.config-url"))) {
37111 -                               PATCH(config_url);
37112 +                               PATCH_OPTION(config_url);
37113                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.enable-sort"))) {
37114 -                               PATCH(sort);
37115 +                               PATCH_OPTION(sort);
37116                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.statistics-url"))) {
37117 -                               PATCH(statistics_url);
37118 -                       } 
37119 +                               PATCH_OPTION(statistics_url);
37120 +                       }
37121                 }
37122         }
37123 -       
37124 +
37125         return 0;
37126  }
37127  
37128  static handler_t mod_status_handler(server *srv, connection *con, void *p_d) {
37129         plugin_data *p = p_d;
37130 -       
37131 +
37132         mod_status_patch_connection(srv, con, p);
37133 -       
37134 -       if (!buffer_is_empty(p->conf.status_url) && 
37135 +
37136 +       if (!buffer_is_empty(p->conf.status_url) &&
37137             buffer_is_equal(p->conf.status_url, con->uri.path)) {
37138                 return mod_status_handle_server_status(srv, con, p_d);
37139 -       } else if (!buffer_is_empty(p->conf.config_url) && 
37140 +       } else if (!buffer_is_empty(p->conf.config_url) &&
37141             buffer_is_equal(p->conf.config_url, con->uri.path)) {
37142                 return mod_status_handle_server_config(srv, con, p_d);
37143 -       } else if (!buffer_is_empty(p->conf.statistics_url) && 
37144 +       } else if (!buffer_is_empty(p->conf.statistics_url) &&
37145             buffer_is_equal(p->conf.statistics_url, con->uri.path)) {
37146                 return mod_status_handle_server_statistics(srv, con, p_d);
37147         }
37148 -       
37149 +
37150         return HANDLER_GO_ON;
37151  }
37152  
37153  TRIGGER_FUNC(mod_status_trigger) {
37154         plugin_data *p = p_d;
37155         size_t i;
37156 -       
37157 +
37158         /* check all connections */
37159         for (i = 0; i < srv->conns->used; i++) {
37160                 connection *c = srv->conns->ptr[i];
37161 -               
37162 +
37163                 p->bytes_written += c->bytes_written_cur_second;
37164         }
37165 -       
37166 +
37167         /* a sliding average */
37168         p->mod_5s_traffic_out[p->mod_5s_ndx] = p->bytes_written;
37169         p->mod_5s_requests   [p->mod_5s_ndx] = p->requests;
37170 -       
37171 +
37172         p->mod_5s_ndx = (p->mod_5s_ndx+1) % 5;
37173 -       
37174 +
37175         p->abs_traffic_out += p->bytes_written;
37176         p->rel_traffic_out += p->bytes_written;
37177 -       
37178 +
37179         p->bytes_written = 0;
37180 -       
37181 +
37182         /* reset storage - second */
37183         p->traffic_out = 0;
37184         p->requests    = 0;
37185 -       
37186 +
37187         return HANDLER_GO_ON;
37188  }
37189  
37190  REQUESTDONE_FUNC(mod_status_account) {
37191         plugin_data *p = p_d;
37192 -       
37193 +
37194         UNUSED(srv);
37195  
37196         p->requests++;
37197         p->rel_requests++;
37198         p->abs_requests++;
37199 -       
37200 +
37201         p->bytes_written += con->bytes_written_cur_second;
37202 -       
37203 +
37204         return HANDLER_GO_ON;
37205  }
37206  
37207  int mod_status_plugin_init(plugin *p) {
37208         p->version     = LIGHTTPD_VERSION_ID;
37209         p->name        = buffer_init_string("status");
37210 -       
37211 +
37212         p->init        = mod_status_init;
37213         p->cleanup     = mod_status_free;
37214         p->set_defaults= mod_status_set_defaults;
37215 -       
37216 +
37217         p->handle_uri_clean    = mod_status_handler;
37218         p->handle_trigger      = mod_status_trigger;
37219         p->handle_request_done = mod_status_account;
37220 -       
37221 +
37222         p->data        = NULL;
37223 -       
37224 +
37225         return 0;
37226  }
37227 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_trigger_b4_dl.c lighttpd-1.4.12/src/mod_trigger_b4_dl.c
37228 --- lighttpd-1.4.11/src/mod_trigger_b4_dl.c     2005-09-23 22:53:55.000000000 +0300
37229 +++ lighttpd-1.4.12/src/mod_trigger_b4_dl.c     2006-07-11 21:23:39.000000000 +0300
37230 @@ -24,18 +24,18 @@
37231  
37232  /**
37233   * this is a trigger_b4_dl for a lighttpd plugin
37234 - * 
37235 + *
37236   */
37237  
37238  /* plugin config for all request/connections */
37239  
37240  typedef struct {
37241         buffer *db_filename;
37242 -       
37243 +
37244         buffer *trigger_url;
37245         buffer *download_url;
37246         buffer *deny_url;
37247 -       
37248 +
37249         array  *mc_hosts;
37250         buffer *mc_namespace;
37251  #if defined(HAVE_PCRE_H)
37252 @@ -46,58 +46,58 @@
37253         GDBM_FILE db;
37254  #endif
37255  
37256 -#if defined(HAVE_MEMCACHE_H) 
37257 +#if defined(HAVE_MEMCACHE_H)
37258         struct memcache *mc;
37259  #endif
37260 -       
37261 +
37262         unsigned short trigger_timeout;
37263         unsigned short debug;
37264  } plugin_config;
37265  
37266  typedef struct {
37267         PLUGIN_DATA;
37268 -       
37269 +
37270         buffer *tmp_buf;
37271 -       
37272 +
37273         plugin_config **config_storage;
37274 -       
37275 -       plugin_config conf; 
37276 +
37277 +       plugin_config conf;
37278  } plugin_data;
37279  
37280  /* init the plugin data */
37281  INIT_FUNC(mod_trigger_b4_dl_init) {
37282         plugin_data *p;
37283 -       
37284 +
37285         p = calloc(1, sizeof(*p));
37286 -       
37287 +
37288         p->tmp_buf = buffer_init();
37289 -       
37290 +
37291         return p;
37292  }
37293  
37294  /* detroy the plugin data */
37295  FREE_FUNC(mod_trigger_b4_dl_free) {
37296         plugin_data *p = p_d;
37297 -       
37298 +
37299         UNUSED(srv);
37300  
37301         if (!p) return HANDLER_GO_ON;
37302 -       
37303 +
37304         if (p->config_storage) {
37305                 size_t i;
37306                 for (i = 0; i < srv->config_context->used; i++) {
37307                         plugin_config *s = p->config_storage[i];
37308  
37309                         if (!s) continue;
37310 -                       
37311 +
37312                         buffer_free(s->db_filename);
37313                         buffer_free(s->download_url);
37314                         buffer_free(s->trigger_url);
37315                         buffer_free(s->deny_url);
37316 -                       
37317 +
37318                         buffer_free(s->mc_namespace);
37319                         array_free(s->mc_hosts);
37320 -                       
37321 +
37322  #if defined(HAVE_PCRE_H)
37323                         if (s->trigger_regex) pcre_free(s->trigger_regex);
37324                         if (s->download_regex) pcre_free(s->download_regex);
37325 @@ -108,16 +108,16 @@
37326  #if defined(HAVE_MEMCACHE_H)
37327                         if (s->mc) mc_free(s->mc);
37328  #endif
37329 -                       
37330 +
37331                         free(s);
37332                 }
37333                 free(p->config_storage);
37334         }
37335 -       
37336 +
37337         buffer_free(p->tmp_buf);
37338 -       
37339 +
37340         free(p);
37341 -       
37342 +
37343         return HANDLER_GO_ON;
37344  }
37345  
37346 @@ -126,9 +126,9 @@
37347  SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) {
37348         plugin_data *p = p_d;
37349         size_t i = 0;
37350 -       
37351 -       
37352 -       config_values_t cv[] = { 
37353 +
37354 +
37355 +       config_values_t cv[] = {
37356                 { "trigger-before-download.gdbm-filename",   NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
37357                 { "trigger-before-download.trigger-url",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
37358                 { "trigger-before-download.download-url",    NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
37359 @@ -139,18 +139,18 @@
37360                 { "trigger-before-download.debug",           NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },      /* 7 */
37361                 { NULL,                        NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
37362         };
37363 -       
37364 +
37365         if (!p) return HANDLER_ERROR;
37366 -       
37367 +
37368         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
37369 -       
37370 +
37371         for (i = 0; i < srv->config_context->used; i++) {
37372                 plugin_config *s;
37373  #if defined(HAVE_PCRE_H)
37374                 const char *errptr;
37375                 int erroff;
37376  #endif
37377 -               
37378 +
37379                 s = calloc(1, sizeof(plugin_config));
37380                 s->db_filename    = buffer_init();
37381                 s->download_url   = buffer_init();
37382 @@ -158,7 +158,7 @@
37383                 s->deny_url       = buffer_init();
37384                 s->mc_hosts       = array_init();
37385                 s->mc_namespace   = buffer_init();
37386 -               
37387 +
37388                 cv[0].destination = s->db_filename;
37389                 cv[1].destination = s->trigger_url;
37390                 cv[2].destination = s->download_url;
37391 @@ -167,41 +167,41 @@
37392                 cv[5].destination = s->mc_hosts;
37393                 cv[6].destination = s->mc_namespace;
37394                 cv[7].destination = &(s->debug);
37395 -               
37396 +
37397                 p->config_storage[i] = s;
37398 -       
37399 +
37400                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
37401                         return HANDLER_ERROR;
37402                 }
37403  #if defined(HAVE_GDBM_H)
37404                 if (!buffer_is_empty(s->db_filename)) {
37405                         if (NULL == (s->db = gdbm_open(s->db_filename->ptr, 4096, GDBM_WRCREAT | GDBM_NOLOCK, S_IRUSR | S_IWUSR, 0))) {
37406 -                               log_error_write(srv, __FILE__, __LINE__, "s", 
37407 +                               log_error_write(srv, __FILE__, __LINE__, "s",
37408                                                 "gdbm-open failed");
37409                                 return HANDLER_ERROR;
37410                         }
37411                 }
37412  #endif
37413 -#if defined(HAVE_PCRE_H)               
37414 +#if defined(HAVE_PCRE_H)
37415                 if (!buffer_is_empty(s->download_url)) {
37416                         if (NULL == (s->download_regex = pcre_compile(s->download_url->ptr,
37417                                                                       0, &errptr, &erroff, NULL))) {
37418 -                               
37419 -                               log_error_write(srv, __FILE__, __LINE__, "sbss", 
37420 -                                               "compiling regex for download-url failed:", 
37421 +
37422 +                               log_error_write(srv, __FILE__, __LINE__, "sbss",
37423 +                                               "compiling regex for download-url failed:",
37424                                                 s->download_url, "pos:", erroff);
37425                                 return HANDLER_ERROR;
37426                         }
37427                 }
37428 -               
37429 +
37430                 if (!buffer_is_empty(s->trigger_url)) {
37431                         if (NULL == (s->trigger_regex = pcre_compile(s->trigger_url->ptr,
37432                                                                      0, &errptr, &erroff, NULL))) {
37433 -                               
37434 -                               log_error_write(srv, __FILE__, __LINE__, "sbss", 
37435 -                                               "compiling regex for trigger-url failed:", 
37436 +
37437 +                               log_error_write(srv, __FILE__, __LINE__, "sbss",
37438 +                                               "compiling regex for trigger-url failed:",
37439                                                 s->trigger_url, "pos:", erroff);
37440 -                               
37441 +
37442                                 return HANDLER_ERROR;
37443                         }
37444                 }
37445 @@ -211,100 +211,97 @@
37446  #if defined(HAVE_MEMCACHE_H)
37447                         size_t k;
37448                         s->mc = mc_new();
37449 -               
37450 +
37451                         for (k = 0; k < s->mc_hosts->used; k++) {
37452                                 data_string *ds = (data_string *)s->mc_hosts->data[k];
37453 -                               
37454 +
37455                                 if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
37456 -                                       log_error_write(srv, __FILE__, __LINE__, "sb", 
37457 -                                                       "connection to host failed:", 
37458 +                                       log_error_write(srv, __FILE__, __LINE__, "sb",
37459 +                                                       "connection to host failed:",
37460                                                         ds->value);
37461 -                                       
37462 +
37463                                         return HANDLER_ERROR;
37464                                 }
37465                         }
37466  #else
37467 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
37468 +                       log_error_write(srv, __FILE__, __LINE__, "s",
37469                                         "memcache support is not compiled in but trigger-before-download.memcache-hosts is set, aborting");
37470                         return HANDLER_ERROR;
37471  #endif
37472                 }
37473 -               
37474 +
37475  
37476  #if (!defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)) || !defined(HAVE_PCRE_H)
37477 -               log_error_write(srv, __FILE__, __LINE__, "s", 
37478 +               log_error_write(srv, __FILE__, __LINE__, "s",
37479                                 "(either gdbm or libmemcache) and pcre are require, but were not found, aborting");
37480                 return HANDLER_ERROR;
37481  #endif
37482         }
37483 -       
37484 +
37485         return HANDLER_GO_ON;
37486  }
37487  
37488 -#define PATCH(x) \
37489 -       p->conf.x = s->x;
37490  static int mod_trigger_b4_dl_patch_connection(server *srv, connection *con, plugin_data *p) {
37491         size_t i, j;
37492         plugin_config *s = p->config_storage[0];
37493 -       
37494 +
37495  #if defined(HAVE_GDBM)
37496 -       PATCH(db);
37497 -#endif 
37498 +       PATCH_OPTION(db);
37499 +#endif
37500  #if defined(HAVE_PCRE_H)
37501 -       PATCH(download_regex);
37502 -       PATCH(trigger_regex);
37503 -#endif 
37504 -       PATCH(trigger_timeout);
37505 -       PATCH(deny_url);
37506 -       PATCH(mc_namespace);
37507 -       PATCH(debug);
37508 +       PATCH_OPTION(download_regex);
37509 +       PATCH_OPTION(trigger_regex);
37510 +#endif
37511 +       PATCH_OPTION(trigger_timeout);
37512 +       PATCH_OPTION(deny_url);
37513 +       PATCH_OPTION(mc_namespace);
37514 +       PATCH_OPTION(debug);
37515  #if defined(HAVE_MEMCACHE_H)
37516 -       PATCH(mc);
37517 +       PATCH_OPTION(mc);
37518  #endif
37519 -       
37520 +
37521         /* skip the first, the global context */
37522         for (i = 1; i < srv->config_context->used; i++) {
37523                 data_config *dc = (data_config *)srv->config_context->data[i];
37524                 s = p->config_storage[i];
37525 -               
37526 +
37527                 /* condition didn't match */
37528                 if (!config_check_cond(srv, con, dc)) continue;
37529 -               
37530 +
37531                 /* merge config */
37532                 for (j = 0; j < dc->value->used; j++) {
37533                         data_unset *du = dc->value->data[j];
37534  
37535                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.download-url"))) {
37536  #if defined(HAVE_PCRE_H)
37537 -                               PATCH(download_regex);
37538 +                               PATCH_OPTION(download_regex);
37539  #endif
37540                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-url"))) {
37541  # if defined(HAVE_PCRE_H)
37542 -                               PATCH(trigger_regex);
37543 +                               PATCH_OPTION(trigger_regex);
37544  # endif
37545                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.gdbm-filename"))) {
37546  #if defined(HAVE_GDBM_H)
37547 -                               PATCH(db);
37548 +                               PATCH_OPTION(db);
37549  #endif
37550                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-timeout"))) {
37551 -                               PATCH(trigger_timeout);
37552 +                               PATCH_OPTION(trigger_timeout);
37553                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.debug"))) {
37554 -                               PATCH(debug);
37555 +                               PATCH_OPTION(debug);
37556                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.deny-url"))) {
37557 -                               PATCH(deny_url);
37558 +                               PATCH_OPTION(deny_url);
37559                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-namespace"))) {
37560 -                               PATCH(mc_namespace);
37561 +                               PATCH_OPTION(mc_namespace);
37562                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-hosts"))) {
37563  #if defined(HAVE_MEMCACHE_H)
37564 -                               PATCH(mc);
37565 +                               PATCH_OPTION(mc);
37566  #endif
37567                         }
37568                 }
37569         }
37570 -       
37571 +
37572         return 0;
37573  }
37574 -#undef PATCH
37575  
37576  URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) {
37577         plugin_data *p = p_d;
37578 @@ -315,20 +312,20 @@
37579         int n;
37580  # define N 10
37581         int ovec[N * 3];
37582 -       
37583 +
37584         if (con->uri.path->used == 0) return HANDLER_GO_ON;
37585 -       
37586 +
37587         mod_trigger_b4_dl_patch_connection(srv, con, p);
37588 -       
37589 +
37590         if (!p->conf.trigger_regex || !p->conf.download_regex) return HANDLER_GO_ON;
37591 -       
37592 +
37593  # if !defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)
37594         return HANDLER_GO_ON;
37595  # elif defined(HAVE_GDBM_H) && defined(HAVE_MEMCACHE_H)
37596         if (!p->conf.db && !p->conf.mc) return HANDLER_GO_ON;
37597         if (p->conf.db && p->conf.mc) {
37598                 /* can't decide which one */
37599 -               
37600 +
37601                 return HANDLER_GO_ON;
37602         }
37603  # elif defined(HAVE_GDBM_H)
37604 @@ -336,12 +333,12 @@
37605  # else
37606         if (!p->conf.mc) return HANDLER_GO_ON;
37607  # endif
37608 -       
37609 +
37610         if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "X-Forwarded-For"))) {
37611                 /* X-Forwarded-For contains the ip behind the proxy */
37612 -               
37613 +
37614                 remote_ip = ds->value->ptr;
37615 -               
37616 +
37617                 /* memcache can't handle spaces */
37618         } else {
37619                 remote_ip = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
37620 @@ -350,13 +347,13 @@
37621         if (p->conf.debug) {
37622                 log_error_write(srv, __FILE__, __LINE__, "ss", "(debug) remote-ip:", remote_ip);
37623         }
37624 -               
37625 +
37626         /* check if URL is a trigger -> insert IP into DB */
37627         if ((n = pcre_exec(p->conf.trigger_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
37628                 if (n != PCRE_ERROR_NOMATCH) {
37629                         log_error_write(srv, __FILE__, __LINE__, "sd",
37630                                         "execution error while matching:", n);
37631 -                       
37632 +
37633                         return HANDLER_ERROR;
37634                 }
37635         } else {
37636 @@ -364,34 +361,34 @@
37637                 if (p->conf.db) {
37638                         /* the trigger matched */
37639                         datum key, val;
37640 -                       
37641 +
37642                         key.dptr = (char *)remote_ip;
37643                         key.dsize = strlen(remote_ip);
37644 -                       
37645 +
37646                         val.dptr = (char *)&(srv->cur_ts);
37647                         val.dsize = sizeof(srv->cur_ts);
37648 -                       
37649 +
37650                         if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
37651                                 log_error_write(srv, __FILE__, __LINE__, "s",
37652                                                 "insert failed");
37653                         }
37654                 }
37655  # endif
37656 -# if defined(HAVE_MEMCACHE_H)          
37657 +# if defined(HAVE_MEMCACHE_H)
37658                 if (p->conf.mc) {
37659                         size_t i;
37660                         buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
37661                         buffer_append_string(p->tmp_buf, remote_ip);
37662 -                       
37663 +
37664                         for (i = 0; i < p->tmp_buf->used - 1; i++) {
37665                                 if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
37666                         }
37667 -                       
37668 +
37669                         if (p->conf.debug) {
37670                                 log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) triggered IP:", p->tmp_buf);
37671                         }
37672  
37673 -                       if (0 != mc_set(p->conf.mc, 
37674 +                       if (0 != mc_set(p->conf.mc,
37675                                         CONST_BUF_LEN(p->tmp_buf),
37676                                         (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
37677                                         p->conf.trigger_timeout, 0)) {
37678 @@ -401,7 +398,7 @@
37679                 }
37680  # endif
37681         }
37682 -               
37683 +
37684         /* check if URL is a download -> check IP in DB, update timestamp */
37685         if ((n = pcre_exec(p->conf.download_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
37686                 if (n != PCRE_ERROR_NOMATCH) {
37687 @@ -411,93 +408,93 @@
37688                 }
37689         } else {
37690                 /* the download uri matched */
37691 -# if defined(HAVE_GDBM_H)              
37692 +# if defined(HAVE_GDBM_H)
37693                 if (p->conf.db) {
37694                         datum key, val;
37695                         time_t last_hit;
37696 -               
37697 +
37698                         key.dptr = (char *)remote_ip;
37699                         key.dsize = strlen(remote_ip);
37700 -                       
37701 +
37702                         val = gdbm_fetch(p->conf.db, key);
37703 -               
37704 +
37705                         if (val.dptr == NULL) {
37706                                 /* not found, redirect */
37707 -                               
37708 +
37709                                 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37710 -                               
37711 +
37712                                 con->http_status = 307;
37713 -                               
37714 +
37715                                 return HANDLER_FINISHED;
37716                         }
37717 -                       
37718 +
37719                         last_hit = *(time_t *)(val.dptr);
37720 -                       
37721 +
37722                         free(val.dptr);
37723 -                       
37724 +
37725                         if (srv->cur_ts - last_hit > p->conf.trigger_timeout) {
37726                                 /* found, but timeout, redirect */
37727 -                               
37728 +
37729                                 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37730                                 con->http_status = 307;
37731 -                               
37732 +
37733                                 if (p->conf.db) {
37734                                         if (0 != gdbm_delete(p->conf.db, key)) {
37735                                                 log_error_write(srv, __FILE__, __LINE__, "s",
37736                                                                 "delete failed");
37737                                         }
37738                                 }
37739 -                               
37740 +
37741                                 return HANDLER_FINISHED;
37742                         }
37743 -                       
37744 +
37745                         val.dptr = (char *)&(srv->cur_ts);
37746                         val.dsize = sizeof(srv->cur_ts);
37747 -                       
37748 +
37749                         if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
37750                                 log_error_write(srv, __FILE__, __LINE__, "s",
37751                                                 "insert failed");
37752                         }
37753                 }
37754  # endif
37755 -               
37756 -# if defined(HAVE_MEMCACHE_H)          
37757 +
37758 +# if defined(HAVE_MEMCACHE_H)
37759                 if (p->conf.mc) {
37760                         void *r;
37761                         size_t i;
37762 -                       
37763 +
37764                         buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
37765                         buffer_append_string(p->tmp_buf, remote_ip);
37766 -                       
37767 +
37768                         for (i = 0; i < p->tmp_buf->used - 1; i++) {
37769                                 if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
37770                         }
37771 -                       
37772 +
37773                         if (p->conf.debug) {
37774                                 log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) checking IP:", p->tmp_buf);
37775                         }
37776  
37777                         /**
37778 -                        * 
37779 +                        *
37780                          * memcached is do expiration for us, as long as we can fetch it every thing is ok
37781 -                        * and the timestamp is updated 
37782 -                        * 
37783 +                        * and the timestamp is updated
37784 +                        *
37785                          */
37786 -                       if (NULL == (r = mc_aget(p->conf.mc, 
37787 +                       if (NULL == (r = mc_aget(p->conf.mc,
37788                                                  CONST_BUF_LEN(p->tmp_buf)
37789                                                  ))) {
37790 -                               
37791 +
37792                                 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
37793 -                               
37794 +
37795                                 con->http_status = 307;
37796 -                               
37797 +
37798                                 return HANDLER_FINISHED;
37799                         }
37800 -                       
37801 +
37802                         free(r);
37803 -                       
37804 +
37805                         /* set a new timeout */
37806 -                       if (0 != mc_set(p->conf.mc, 
37807 +                       if (0 != mc_set(p->conf.mc,
37808                                         CONST_BUF_LEN(p->tmp_buf),
37809                                         (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
37810                                         p->conf.trigger_timeout, 0)) {
37811 @@ -507,13 +504,13 @@
37812                 }
37813  # endif
37814         }
37815 -       
37816 +
37817  #else
37818         UNUSED(srv);
37819         UNUSED(con);
37820         UNUSED(p_d);
37821  #endif
37822 -       
37823 +
37824         return HANDLER_GO_ON;
37825  }
37826  
37827 @@ -521,21 +518,21 @@
37828  TRIGGER_FUNC(mod_trigger_b4_dl_handle_trigger) {
37829         plugin_data *p = p_d;
37830         size_t i;
37831 -       
37832 +
37833         /* check DB each minute */
37834         if (srv->cur_ts % 60 != 0) return HANDLER_GO_ON;
37835 -       
37836 +
37837         /* cleanup */
37838         for (i = 0; i < srv->config_context->used; i++) {
37839                 plugin_config *s = p->config_storage[i];
37840                 datum key, val, okey;
37841 -               
37842 +
37843                 if (!s->db) continue;
37844 -               
37845 +
37846                 okey.dptr = NULL;
37847 -               
37848 -               /* according to the manual this loop + delete does delete all entries on its way 
37849 -                * 
37850 +
37851 +               /* according to the manual this loop + delete does delete all entries on its way
37852 +                *
37853                  * we don't care as the next round will remove them. We don't have to perfect here.
37854                  */
37855                 for (key = gdbm_firstkey(s->db); key.dptr; key = gdbm_nextkey(s->db, okey)) {
37856 @@ -544,21 +541,21 @@
37857                                 free(okey.dptr);
37858                                 okey.dptr = NULL;
37859                         }
37860 -                       
37861 +
37862                         val = gdbm_fetch(s->db, key);
37863 -                       
37864 +
37865                         last_hit = *(time_t *)(val.dptr);
37866 -                       
37867 +
37868                         free(val.dptr);
37869 -                       
37870 +
37871                         if (srv->cur_ts - last_hit > s->trigger_timeout) {
37872                                 gdbm_delete(s->db, key);
37873                         }
37874 -                       
37875 +
37876                         okey = key;
37877                 }
37878                 if (okey.dptr) free(okey.dptr);
37879 -               
37880 +
37881                 /* reorg once a day */
37882                 if ((srv->cur_ts % (60 * 60 * 24) != 0)) gdbm_reorganize(s->db);
37883         }
37884 @@ -571,7 +568,7 @@
37885  int mod_trigger_b4_dl_plugin_init(plugin *p) {
37886         p->version     = LIGHTTPD_VERSION_ID;
37887         p->name        = buffer_init_string("trigger_b4_dl");
37888 -       
37889 +
37890         p->init        = mod_trigger_b4_dl_init;
37891         p->handle_uri_clean  = mod_trigger_b4_dl_uri_handler;
37892         p->set_defaults  = mod_trigger_b4_dl_set_defaults;
37893 @@ -579,8 +576,8 @@
37894         p->handle_trigger  = mod_trigger_b4_dl_handle_trigger;
37895  #endif
37896         p->cleanup     = mod_trigger_b4_dl_free;
37897 -       
37898 +
37899         p->data        = NULL;
37900 -       
37901 +
37902         return 0;
37903  }
37904 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_userdir.c lighttpd-1.4.12/src/mod_userdir.c
37905 --- lighttpd-1.4.11/src/mod_userdir.c   2005-10-28 16:48:28.000000000 +0300
37906 +++ lighttpd-1.4.12/src/mod_userdir.c   2006-07-11 21:23:40.000000000 +0300
37907 @@ -10,6 +10,7 @@
37908  #include "response.h"
37909  
37910  #include "plugin.h"
37911 +#include "sys-files.h"
37912  
37913  #ifdef HAVE_PWD_H
37914  #include <pwd.h>
37915 @@ -25,54 +26,54 @@
37916  
37917  typedef struct {
37918         PLUGIN_DATA;
37919 -       
37920 +
37921         buffer *username;
37922         buffer *temp_path;
37923 -       
37924 +
37925         plugin_config **config_storage;
37926 -       
37927 -       plugin_config conf; 
37928 +
37929 +       plugin_config conf;
37930  } plugin_data;
37931  
37932  /* init the plugin data */
37933  INIT_FUNC(mod_userdir_init) {
37934         plugin_data *p;
37935 -       
37936 +
37937         p = calloc(1, sizeof(*p));
37938 -       
37939 +
37940         p->username = buffer_init();
37941         p->temp_path = buffer_init();
37942 -       
37943 +
37944         return p;
37945  }
37946  
37947  /* detroy the plugin data */
37948  FREE_FUNC(mod_userdir_free) {
37949         plugin_data *p = p_d;
37950 -       
37951 +
37952         if (!p) return HANDLER_GO_ON;
37953 -       
37954 +
37955         if (p->config_storage) {
37956                 size_t i;
37957 -               
37958 +
37959                 for (i = 0; i < srv->config_context->used; i++) {
37960                         plugin_config *s = p->config_storage[i];
37961 -                       
37962 +
37963                         array_free(s->include_user);
37964                         array_free(s->exclude_user);
37965                         buffer_free(s->path);
37966                         buffer_free(s->basepath);
37967 -                       
37968 +
37969                         free(s);
37970                 }
37971                 free(p->config_storage);
37972         }
37973 -       
37974 +
37975         buffer_free(p->username);
37976         buffer_free(p->temp_path);
37977 -       
37978 +
37979         free(p);
37980 -       
37981 +
37982         return HANDLER_GO_ON;
37983  }
37984  
37985 @@ -81,81 +82,78 @@
37986  SETDEFAULTS_FUNC(mod_userdir_set_defaults) {
37987         plugin_data *p = p_d;
37988         size_t i;
37989 -       
37990 -       config_values_t cv[] = { 
37991 +
37992 +       config_values_t cv[] = {
37993                 { "userdir.path",               NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
37994                 { "userdir.exclude-user",       NULL, T_CONFIG_ARRAY,  T_CONFIG_SCOPE_CONNECTION },       /* 1 */
37995                 { "userdir.include-user",       NULL, T_CONFIG_ARRAY,  T_CONFIG_SCOPE_CONNECTION },       /* 2 */
37996                 { "userdir.basepath",           NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 3 */
37997                 { NULL,                         NULL, T_CONFIG_UNSET,  T_CONFIG_SCOPE_UNSET }
37998         };
37999 -       
38000 +
38001         if (!p) return HANDLER_ERROR;
38002 -       
38003 +
38004         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
38005 -       
38006 +
38007         for (i = 0; i < srv->config_context->used; i++) {
38008                 plugin_config *s;
38009 -               
38010 +
38011                 s = calloc(1, sizeof(plugin_config));
38012                 s->exclude_user = array_init();
38013                 s->include_user = array_init();
38014                 s->path = buffer_init();
38015                 s->basepath = buffer_init();
38016 -       
38017 +
38018                 cv[0].destination = s->path;
38019                 cv[1].destination = s->exclude_user;
38020                 cv[2].destination = s->include_user;
38021                 cv[3].destination = s->basepath;
38022 -               
38023 +
38024                 p->config_storage[i] = s;
38025 -       
38026 +
38027                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
38028                         return HANDLER_ERROR;
38029                 }
38030         }
38031 -       
38032 +
38033         return HANDLER_GO_ON;
38034  }
38035  
38036 -#define PATCH(x) \
38037 -       p->conf.x = s->x;
38038  static int mod_userdir_patch_connection(server *srv, connection *con, plugin_data *p) {
38039         size_t i, j;
38040         plugin_config *s = p->config_storage[0];
38041 -       
38042 -       PATCH(path);
38043 -       PATCH(exclude_user);
38044 -       PATCH(include_user);
38045 -       PATCH(basepath);
38046 -       
38047 +
38048 +       PATCH_OPTION(path);
38049 +       PATCH_OPTION(exclude_user);
38050 +       PATCH_OPTION(include_user);
38051 +       PATCH_OPTION(basepath);
38052 +
38053         /* skip the first, the global context */
38054         for (i = 1; i < srv->config_context->used; i++) {
38055                 data_config *dc = (data_config *)srv->config_context->data[i];
38056                 s = p->config_storage[i];
38057 -               
38058 +
38059                 /* condition didn't match */
38060                 if (!config_check_cond(srv, con, dc)) continue;
38061 -               
38062 +
38063                 /* merge config */
38064                 for (j = 0; j < dc->value->used; j++) {
38065                         data_unset *du = dc->value->data[j];
38066 -                       
38067 +
38068                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.path"))) {
38069 -                               PATCH(path);
38070 +                               PATCH_OPTION(path);
38071                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.exclude-user"))) {
38072 -                               PATCH(exclude_user);
38073 +                               PATCH_OPTION(exclude_user);
38074                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.include-user"))) {
38075 -                               PATCH(include_user);
38076 +                               PATCH_OPTION(include_user);
38077                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.basepath"))) {
38078 -                               PATCH(basepath);
38079 +                               PATCH_OPTION(basepath);
38080                         }
38081                 }
38082         }
38083 -       
38084 +
38085         return 0;
38086  }
38087 -#undef PATCH
38088  
38089  URIHANDLER_FUNC(mod_userdir_docroot_handler) {
38090         plugin_data *p = p_d;
38091 @@ -169,18 +167,18 @@
38092         if (con->uri.path->used == 0) return HANDLER_GO_ON;
38093  
38094         mod_userdir_patch_connection(srv, con, p);
38095 -       
38096 +
38097         uri_len = con->uri.path->used - 1;
38098 -       
38099 +
38100         /* /~user/foo.html -> /home/user/public_html/foo.html */
38101 -       
38102 +
38103         if (con->uri.path->ptr[0] != '/' ||
38104             con->uri.path->ptr[1] != '~') return HANDLER_GO_ON;
38105 -       
38106 +
38107         if (NULL == (rel_url = strchr(con->uri.path->ptr + 2, '/'))) {
38108                 /* / is missing -> redirect to .../ as we are a user - DIRECTORY ! :) */
38109                 http_response_redirect_to_directory(srv, con);
38110 -               
38111 +
38112                 return HANDLER_FINISHED;
38113         }
38114  
38115 @@ -188,10 +186,10 @@
38116         if (0 == rel_url - (con->uri.path->ptr + 2)) {
38117                 return HANDLER_GO_ON;
38118         }
38119 -       
38120 +
38121         buffer_copy_string_len(p->username, con->uri.path->ptr + 2, rel_url - (con->uri.path->ptr + 2));
38122 -       
38123 -       if (buffer_is_empty(p->conf.basepath) 
38124 +
38125 +       if (buffer_is_empty(p->conf.basepath)
38126  #ifdef HAVE_PWD_H
38127             && NULL == (pwd = getpwnam(p->username->ptr))
38128  #endif
38129 @@ -200,31 +198,31 @@
38130                 return HANDLER_GO_ON;
38131         }
38132  
38133 -       
38134 +
38135         for (k = 0; k < p->conf.exclude_user->used; k++) {
38136                 data_string *ds = (data_string *)p->conf.exclude_user->data[k];
38137 -               
38138 +
38139                 if (buffer_is_equal(ds->value, p->username)) {
38140                         /* user in exclude list */
38141                         return HANDLER_GO_ON;
38142                 }
38143         }
38144 -       
38145 +
38146         if (p->conf.include_user->used) {
38147                 int found_user = 0;
38148                 for (k = 0; k < p->conf.include_user->used; k++) {
38149                         data_string *ds = (data_string *)p->conf.include_user->data[k];
38150 -                       
38151 +
38152                         if (buffer_is_equal(ds->value, p->username)) {
38153                                 /* user in include list */
38154                                 found_user = 1;
38155                                 break;
38156                         }
38157                 }
38158 -               
38159 +
38160                 if (!found_user) return HANDLER_GO_ON;
38161         }
38162 -       
38163 +
38164         /* we build the physical path */
38165  
38166         if (buffer_is_empty(p->conf.basepath)) {
38167 @@ -252,23 +250,23 @@
38168                 }
38169  
38170                 buffer_copy_string_buffer(p->temp_path, p->conf.basepath);
38171 -               BUFFER_APPEND_SLASH(p->temp_path);
38172 +               PATHNAME_APPEND_SLASH(p->temp_path);
38173                 buffer_append_string_buffer(p->temp_path, p->username);
38174         }
38175 -       BUFFER_APPEND_SLASH(p->temp_path);
38176 -       buffer_append_string_buffer(p->temp_path, p->conf.path); 
38177 +       PATHNAME_APPEND_SLASH(p->temp_path);
38178 +       buffer_append_string_buffer(p->temp_path, p->conf.path);
38179  
38180         if (buffer_is_empty(p->conf.basepath)) {
38181                 struct stat st;
38182                 int ret;
38183 -               
38184 +
38185                 ret = stat(p->temp_path->ptr, &st);
38186                 if (ret < 0 || S_ISDIR(st.st_mode) != 1) {
38187                         return HANDLER_GO_ON;
38188 -               } 
38189 +               }
38190         }
38191  
38192 -       BUFFER_APPEND_SLASH(p->temp_path);
38193 +       PATHNAME_APPEND_SLASH(p->temp_path);
38194         buffer_append_string(p->temp_path, rel_url + 1); /* skip the / */
38195         buffer_copy_string_buffer(con->physical.path, p->temp_path);
38196  
38197 @@ -282,13 +280,13 @@
38198  int mod_userdir_plugin_init(plugin *p) {
38199         p->version     = LIGHTTPD_VERSION_ID;
38200         p->name        = buffer_init_string("userdir");
38201 -       
38202 +
38203         p->init           = mod_userdir_init;
38204         p->handle_physical = mod_userdir_docroot_handler;
38205         p->set_defaults   = mod_userdir_set_defaults;
38206         p->cleanup        = mod_userdir_free;
38207 -       
38208 +
38209         p->data        = NULL;
38210 -       
38211 +
38212         return 0;
38213  }
38214 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_usertrack.c lighttpd-1.4.12/src/mod_usertrack.c
38215 --- lighttpd-1.4.11/src/mod_usertrack.c 2006-01-31 15:01:20.000000000 +0200
38216 +++ lighttpd-1.4.12/src/mod_usertrack.c 2006-07-11 21:23:40.000000000 +0300
38217 @@ -24,44 +24,44 @@
38218  
38219  typedef struct {
38220         PLUGIN_DATA;
38221 -       
38222 +
38223         plugin_config **config_storage;
38224 -       
38225 -       plugin_config conf; 
38226 +
38227 +       plugin_config conf;
38228  } plugin_data;
38229  
38230  /* init the plugin data */
38231  INIT_FUNC(mod_usertrack_init) {
38232         plugin_data *p;
38233 -       
38234 +
38235         p = calloc(1, sizeof(*p));
38236 -       
38237 +
38238         return p;
38239  }
38240  
38241  /* detroy the plugin data */
38242  FREE_FUNC(mod_usertrack_free) {
38243         plugin_data *p = p_d;
38244 -       
38245 +
38246         UNUSED(srv);
38247 -       
38248 +
38249         if (!p) return HANDLER_GO_ON;
38250 -       
38251 +
38252         if (p->config_storage) {
38253                 size_t i;
38254                 for (i = 0; i < srv->config_context->used; i++) {
38255                         plugin_config *s = p->config_storage[i];
38256 -                       
38257 +
38258                         buffer_free(s->cookie_name);
38259                         buffer_free(s->cookie_domain);
38260 -                       
38261 +
38262                         free(s);
38263                 }
38264                 free(p->config_storage);
38265         }
38266 -       
38267 +
38268         free(p);
38269 -       
38270 +
38271         return HANDLER_GO_ON;
38272  }
38273  
38274 @@ -70,38 +70,38 @@
38275  SETDEFAULTS_FUNC(mod_usertrack_set_defaults) {
38276         plugin_data *p = p_d;
38277         size_t i = 0;
38278 -       
38279 -       config_values_t cv[] = { 
38280 +
38281 +       config_values_t cv[] = {
38282                 { "usertrack.cookie-name",       NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
38283                 { "usertrack.cookie-max-age",    NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 1 */
38284                 { "usertrack.cookie-domain",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
38285 -               
38286 -               { "usertrack.cookiename",        NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },   
38287 +
38288 +               { "usertrack.cookiename",        NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
38289                 { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
38290         };
38291 -       
38292 +
38293         if (!p) return HANDLER_ERROR;
38294 -       
38295 +
38296         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
38297 -       
38298 +
38299         for (i = 0; i < srv->config_context->used; i++) {
38300                 plugin_config *s;
38301 -               
38302 +
38303                 s = calloc(1, sizeof(plugin_config));
38304                 s->cookie_name    = buffer_init();
38305                 s->cookie_domain  = buffer_init();
38306                 s->cookie_max_age = 0;
38307 -               
38308 +
38309                 cv[0].destination = s->cookie_name;
38310                 cv[1].destination = &(s->cookie_max_age);
38311                 cv[2].destination = s->cookie_domain;
38312 -               
38313 +
38314                 p->config_storage[i] = s;
38315 -       
38316 +
38317                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
38318                         return HANDLER_ERROR;
38319                 }
38320 -       
38321 +
38322                 if (buffer_is_empty(s->cookie_name)) {
38323                         buffer_copy_string(s->cookie_name, "TRACKID");
38324                 } else {
38325 @@ -109,68 +109,65 @@
38326                         for (j = 0; j < s->cookie_name->used - 1; j++) {
38327                                 char c = s->cookie_name->ptr[j] | 32;
38328                                 if (c < 'a' || c > 'z') {
38329 -                                       log_error_write(srv, __FILE__, __LINE__, "sb", 
38330 -                                                       "invalid character in usertrack.cookie-name:", 
38331 +                                       log_error_write(srv, __FILE__, __LINE__, "sb",
38332 +                                                       "invalid character in usertrack.cookie-name:",
38333                                                         s->cookie_name);
38334 -                                       
38335 +
38336                                         return HANDLER_ERROR;
38337                                 }
38338                         }
38339                 }
38340 -               
38341 +
38342                 if (!buffer_is_empty(s->cookie_domain)) {
38343                         size_t j;
38344                         for (j = 0; j < s->cookie_domain->used - 1; j++) {
38345                                 char c = s->cookie_domain->ptr[j];
38346                                 if (c <= 32 || c >= 127 || c == '"' || c == '\\') {
38347 -                                       log_error_write(srv, __FILE__, __LINE__, "sb", 
38348 -                                                       "invalid character in usertrack.cookie-domain:", 
38349 +                                       log_error_write(srv, __FILE__, __LINE__, "sb",
38350 +                                                       "invalid character in usertrack.cookie-domain:",
38351                                                         s->cookie_domain);
38352 -                                       
38353 +
38354                                         return HANDLER_ERROR;
38355                                 }
38356                         }
38357                 }
38358         }
38359 -               
38360 +
38361         return HANDLER_GO_ON;
38362  }
38363  
38364 -#define PATCH(x) \
38365 -       p->conf.x = s->x;
38366  static int mod_usertrack_patch_connection(server *srv, connection *con, plugin_data *p) {
38367         size_t i, j;
38368         plugin_config *s = p->config_storage[0];
38369 -       
38370 -       PATCH(cookie_name);
38371 -       PATCH(cookie_domain);
38372 -       PATCH(cookie_max_age);
38373 -       
38374 +
38375 +       PATCH_OPTION(cookie_name);
38376 +       PATCH_OPTION(cookie_domain);
38377 +       PATCH_OPTION(cookie_max_age);
38378 +
38379         /* skip the first, the global context */
38380         for (i = 1; i < srv->config_context->used; i++) {
38381                 data_config *dc = (data_config *)srv->config_context->data[i];
38382                 s = p->config_storage[i];
38383 -               
38384 +
38385                 /* condition didn't match */
38386                 if (!config_check_cond(srv, con, dc)) continue;
38387 -               
38388 +
38389                 /* merge config */
38390                 for (j = 0; j < dc->value->used; j++) {
38391                         data_unset *du = dc->value->data[j];
38392 -                       
38393 +
38394                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-name"))) {
38395 -                               PATCH(cookie_name);
38396 +                               PATCH_OPTION(cookie_name);
38397                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-max-age"))) {
38398 -                               PATCH(cookie_max_age);
38399 +                               PATCH_OPTION(cookie_max_age);
38400                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-domain"))) {
38401 -                               PATCH(cookie_domain);
38402 +                               PATCH_OPTION(cookie_domain);
38403                         }
38404                 }
38405         }
38406 -       
38407 +
38408         return 0;
38409  }
38410 -#undef PATCH
38411  
38412  URIHANDLER_FUNC(mod_usertrack_uri_handler) {
38413         plugin_data *p = p_d;
38414 @@ -178,38 +175,38 @@
38415         unsigned char h[16];
38416         MD5_CTX Md5Ctx;
38417         char hh[32];
38418 -       
38419 +
38420         if (con->uri.path->used == 0) return HANDLER_GO_ON;
38421 -       
38422 +
38423         mod_usertrack_patch_connection(srv, con, p);
38424 -       
38425 +
38426         if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) {
38427                 char *g;
38428                 /* we have a cookie, does it contain a valid name ? */
38429 -               
38430 -               /* parse the cookie 
38431 -                * 
38432 +
38433 +               /* parse the cookie
38434 +                *
38435                  * check for cookiename + (WS | '=')
38436 -                * 
38437 +                *
38438                  */
38439 -               
38440 +
38441                 if (NULL != (g = strstr(ds->value->ptr, p->conf.cookie_name->ptr))) {
38442                         char *nc;
38443 -                       
38444 +
38445                         /* skip WS */
38446                         for (nc = g + p->conf.cookie_name->used-1; *nc == ' ' || *nc == '\t'; nc++);
38447 -                       
38448 +
38449                         if (*nc == '=') {
38450                                 /* ok, found the key of our own cookie */
38451 -                               
38452 +
38453                                 if (strlen(nc) > 32) {
38454                                         /* i'm lazy */
38455                                         return HANDLER_GO_ON;
38456                                 }
38457                         }
38458                 }
38459 -       } 
38460 -       
38461 +       }
38462 +
38463         /* set a cookie */
38464         if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
38465                 ds = data_response_init();
38466 @@ -217,39 +214,39 @@
38467         buffer_copy_string(ds->key, "Set-Cookie");
38468         buffer_copy_string_buffer(ds->value, p->conf.cookie_name);
38469         buffer_append_string(ds->value, "=");
38470 -       
38471 +
38472  
38473         /* taken from mod_auth.c */
38474 -       
38475 +
38476         /* generate shared-secret */
38477         MD5_Init(&Md5Ctx);
38478         MD5_Update(&Md5Ctx, (unsigned char *)con->uri.path->ptr, con->uri.path->used - 1);
38479         MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
38480 -       
38481 +
38482         /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
38483         ltostr(hh, srv->cur_ts);
38484         MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
38485         ltostr(hh, rand());
38486         MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
38487 -       
38488 +
38489         MD5_Final(h, &Md5Ctx);
38490 -       
38491 +
38492         buffer_append_string_encoded(ds->value, (char *)h, 16, ENCODING_HEX);
38493         buffer_append_string(ds->value, "; Path=/");
38494         buffer_append_string(ds->value, "; Version=1");
38495 -       
38496 +
38497         if (!buffer_is_empty(p->conf.cookie_domain)) {
38498                 buffer_append_string(ds->value, "; Domain=");
38499                 buffer_append_string_encoded(ds->value, CONST_BUF_LEN(p->conf.cookie_domain), ENCODING_REL_URI);
38500         }
38501 -       
38502 +
38503         if (p->conf.cookie_max_age) {
38504                 buffer_append_string(ds->value, "; max-age=");
38505                 buffer_append_long(ds->value, p->conf.cookie_max_age);
38506         }
38507 -       
38508 +
38509         array_insert_unique(con->response.headers, (data_unset *)ds);
38510 -       
38511 +
38512         return HANDLER_GO_ON;
38513  }
38514  
38515 @@ -258,13 +255,13 @@
38516  int mod_usertrack_plugin_init(plugin *p) {
38517         p->version     = LIGHTTPD_VERSION_ID;
38518         p->name        = buffer_init_string("usertrack");
38519 -       
38520 +
38521         p->init        = mod_usertrack_init;
38522         p->handle_uri_clean  = mod_usertrack_uri_handler;
38523         p->set_defaults  = mod_usertrack_set_defaults;
38524         p->cleanup     = mod_usertrack_free;
38525 -       
38526 +
38527         p->data        = NULL;
38528 -       
38529 +
38530         return 0;
38531  }
38532 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/mod_webdav.c lighttpd-1.4.12/src/mod_webdav.c
38533 --- lighttpd-1.4.11/src/mod_webdav.c    2006-03-03 01:28:58.000000000 +0200
38534 +++ lighttpd-1.4.12/src/mod_webdav.c    2006-07-11 21:23:40.000000000 +0300
38535 @@ -3,13 +3,10 @@
38536  #include <ctype.h>
38537  #include <stdlib.h>
38538  #include <string.h>
38539 -#include <dirent.h>
38540  #include <errno.h>
38541 -#include <unistd.h>
38542  #include <fcntl.h>
38543  #include <stdio.h>
38544  #include <assert.h>
38545 -#include <sys/mman.h>
38546  
38547  #ifdef HAVE_CONFIG_H
38548  #include "config.h"
38549 @@ -23,6 +20,11 @@
38550  #include <sqlite3.h>
38551  #endif
38552  
38553 +#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H) && defined(HAVE_UUID_H)
38554 +#define USE_LOCKS
38555 +#include <uuid/uuid.h>
38556 +#endif
38557 +
38558  #include "base.h"
38559  #include "log.h"
38560  #include "buffer.h"
38561 @@ -33,13 +35,16 @@
38562  #include "stream.h"
38563  #include "stat_cache.h"
38564  
38565 +#include "sys-files.h"
38566 +#include "sys-mmap.h"
38567 +#include "sys-strings.h"
38568  
38569  /**
38570   * this is a webdav for a lighttpd plugin
38571   *
38572 - * at least a very basic one. 
38573 + * at least a very basic one.
38574   * - for now it is read-only and we only support PROPFIND
38575 - * 
38576 + *
38577   */
38578  
38579  
38580 @@ -58,64 +63,70 @@
38581         sqlite3_stmt *stmt_delete_prop;
38582         sqlite3_stmt *stmt_select_prop;
38583         sqlite3_stmt *stmt_select_propnames;
38584 -       
38585 +
38586         sqlite3_stmt *stmt_delete_uri;
38587         sqlite3_stmt *stmt_move_uri;
38588         sqlite3_stmt *stmt_copy_uri;
38589 +
38590 +       sqlite3_stmt *stmt_remove_lock;
38591 +       sqlite3_stmt *stmt_create_lock;
38592 +       sqlite3_stmt *stmt_read_lock;
38593 +       sqlite3_stmt *stmt_read_lock_by_uri;
38594 +       sqlite3_stmt *stmt_refresh_lock;
38595  #endif
38596  } plugin_config;
38597  
38598  typedef struct {
38599         PLUGIN_DATA;
38600 -       
38601 +
38602         buffer *tmp_buf;
38603         request_uri uri;
38604         physical physical;
38605  
38606         plugin_config **config_storage;
38607 -       
38608 -       plugin_config conf; 
38609 +
38610 +       plugin_config conf;
38611  } plugin_data;
38612  
38613  /* init the plugin data */
38614  INIT_FUNC(mod_webdav_init) {
38615         plugin_data *p;
38616 -       
38617 +
38618         p = calloc(1, sizeof(*p));
38619 -       
38620 +
38621         p->tmp_buf = buffer_init();
38622  
38623         p->uri.scheme = buffer_init();
38624         p->uri.path_raw = buffer_init();
38625         p->uri.path = buffer_init();
38626         p->uri.authority = buffer_init();
38627 -       
38628 +
38629         p->physical.path = buffer_init();
38630         p->physical.rel_path = buffer_init();
38631         p->physical.doc_root = buffer_init();
38632         p->physical.basedir = buffer_init();
38633 -       
38634 +
38635         return p;
38636  }
38637  
38638  /* detroy the plugin data */
38639  FREE_FUNC(mod_webdav_free) {
38640         plugin_data *p = p_d;
38641 -       
38642 +
38643         UNUSED(srv);
38644  
38645         if (!p) return HANDLER_GO_ON;
38646 -       
38647 +
38648         if (p->config_storage) {
38649                 size_t i;
38650                 for (i = 0; i < srv->config_context->used; i++) {
38651                         plugin_config *s = p->config_storage[i];
38652  
38653                         if (!s) continue;
38654 -       
38655 +
38656                         buffer_free(s->sqlite_db_name);
38657  #ifdef USE_PROPPATCH
38658 -                       if (s->sql) {   
38659 +                       if (s->sql) {
38660                                 sqlite3_finalize(s->stmt_delete_prop);
38661                                 sqlite3_finalize(s->stmt_delete_uri);
38662                                 sqlite3_finalize(s->stmt_copy_uri);
38663 @@ -123,9 +134,15 @@
38664                                 sqlite3_finalize(s->stmt_update_prop);
38665                                 sqlite3_finalize(s->stmt_select_prop);
38666                                 sqlite3_finalize(s->stmt_select_propnames);
38667 +
38668 +                               sqlite3_finalize(s->stmt_read_lock);
38669 +                               sqlite3_finalize(s->stmt_read_lock_by_uri);
38670 +                               sqlite3_finalize(s->stmt_create_lock);
38671 +                               sqlite3_finalize(s->stmt_remove_lock);
38672 +                               sqlite3_finalize(s->stmt_refresh_lock);
38673                                 sqlite3_close(s->sql);
38674                         }
38675 -#endif 
38676 +#endif
38677                         free(s);
38678                 }
38679                 free(p->config_storage);
38680 @@ -135,16 +152,16 @@
38681         buffer_free(p->uri.path_raw);
38682         buffer_free(p->uri.path);
38683         buffer_free(p->uri.authority);
38684 -       
38685 +
38686         buffer_free(p->physical.path);
38687         buffer_free(p->physical.rel_path);
38688         buffer_free(p->physical.doc_root);
38689         buffer_free(p->physical.basedir);
38690 -       
38691 +
38692         buffer_free(p->tmp_buf);
38693 -       
38694 +
38695         free(p);
38696 -       
38697 +
38698         return HANDLER_GO_ON;
38699  }
38700  
38701 @@ -153,32 +170,32 @@
38702  SETDEFAULTS_FUNC(mod_webdav_set_defaults) {
38703         plugin_data *p = p_d;
38704         size_t i = 0;
38705 -       
38706 -       config_values_t cv[] = { 
38707 +
38708 +       config_values_t cv[] = {
38709                 { "webdav.activate",            NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
38710                 { "webdav.is-readonly",         NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
38711                 { "webdav.sqlite-db-name",      NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_CONNECTION },       /* 2 */
38712                 { "webdav.log-xml",             NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },       /* 3 */
38713                 { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
38714         };
38715 -       
38716 +
38717         if (!p) return HANDLER_ERROR;
38718 -       
38719 +
38720         p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
38721 -       
38722 +
38723         for (i = 0; i < srv->config_context->used; i++) {
38724                 plugin_config *s;
38725 -               
38726 +
38727                 s = calloc(1, sizeof(plugin_config));
38728                 s->sqlite_db_name = buffer_init();
38729 -               
38730 +
38731                 cv[0].destination = &(s->enabled);
38732                 cv[1].destination = &(s->is_readonly);
38733                 cv[2].destination = s->sqlite_db_name;
38734                 cv[3].destination = &(s->log_xml);
38735 -               
38736 +
38737                 p->config_storage[i] = s;
38738 -       
38739 +
38740                 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
38741                         return HANDLER_ERROR;
38742                 }
38743 @@ -193,8 +210,26 @@
38744                                 return HANDLER_ERROR;
38745                         }
38746  
38747 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38748 -                               CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"), 
38749 +                       if (SQLITE_OK != sqlite3_exec(s->sql,
38750 +                                       "CREATE TABLE properties ("
38751 +                                       "  resource TEXT NOT NULL,"
38752 +                                       "  prop TEXT NOT NULL,"
38753 +                                       "  ns TEXT NOT NULL,"
38754 +                                       "  value TEXT NOT NULL,"
38755 +                                       "  PRIMARY KEY(resource, prop, ns))",
38756 +                                       NULL, NULL, &err)) {
38757 +
38758 +                               if (0 != strcmp(err, "table properties already exists")) {
38759 +                                       log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
38760 +                                       sqlite3_free(err);
38761 +
38762 +                                       return HANDLER_ERROR;
38763 +                               }
38764 +                               sqlite3_free(err);
38765 +                       }
38766 +
38767 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38768 +                               CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
38769                                 &(s->stmt_select_prop), &next_stmt)) {
38770                                 /* prepare failed */
38771  
38772 @@ -202,8 +237,8 @@
38773                                 return HANDLER_ERROR;
38774                         }
38775  
38776 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38777 -                               CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"), 
38778 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38779 +                               CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"),
38780                                 &(s->stmt_select_propnames), &next_stmt)) {
38781                                 /* prepare failed */
38782  
38783 @@ -211,16 +246,67 @@
38784                                 return HANDLER_ERROR;
38785                         }
38786  
38787 -                       if (SQLITE_OK != sqlite3_exec(s->sql, 
38788 -                                       "CREATE TABLE properties ("
38789 +
38790 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38791 +                               CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"),
38792 +                               &(s->stmt_update_prop), &next_stmt)) {
38793 +                               /* prepare failed */
38794 +
38795 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
38796 +                               return HANDLER_ERROR;
38797 +                       }
38798 +
38799 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38800 +                               CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
38801 +                               &(s->stmt_delete_prop), &next_stmt)) {
38802 +                               /* prepare failed */
38803 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38804 +
38805 +                               return HANDLER_ERROR;
38806 +                       }
38807 +
38808 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38809 +                               CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"),
38810 +                               &(s->stmt_delete_uri), &next_stmt)) {
38811 +                               /* prepare failed */
38812 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38813 +
38814 +                               return HANDLER_ERROR;
38815 +                       }
38816 +
38817 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38818 +                               CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"),
38819 +                               &(s->stmt_copy_uri), &next_stmt)) {
38820 +                               /* prepare failed */
38821 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38822 +
38823 +                               return HANDLER_ERROR;
38824 +                       }
38825 +
38826 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38827 +                               CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"),
38828 +                               &(s->stmt_move_uri), &next_stmt)) {
38829 +                               /* prepare failed */
38830 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38831 +
38832 +                               return HANDLER_ERROR;
38833 +                       }
38834 +
38835 +                       /* LOCKS */
38836 +
38837 +                       if (SQLITE_OK != sqlite3_exec(s->sql,
38838 +                                       "CREATE TABLE locks ("
38839 +                                       "  locktoken TEXT NOT NULL,"
38840                                         "  resource TEXT NOT NULL,"
38841 -                                       "  prop TEXT NOT NULL,"
38842 -                                       "  ns TEXT NOT NULL,"
38843 -                                       "  value TEXT NOT NULL,"
38844 -                                       "  PRIMARY KEY(resource, prop, ns))",
38845 +                                       "  lockscope TEXT NOT NULL,"
38846 +                                       "  locktype TEXT NOT NULL,"
38847 +                                       "  owner TEXT NOT NULL,"
38848 +                                       "  depth INT NOT NULL,"
38849 +                                       "  timeout TIMESTAMP NOT NULL,"
38850 +                                       "  PRIMARY KEY(locktoken))",
38851                                         NULL, NULL, &err)) {
38852  
38853 -                               if (0 != strcmp(err, "table properties already exists")) {
38854 +                               if (0 != strcmp(err, "table locks already exists")) {
38855                                         log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
38856                                         sqlite3_free(err);
38857  
38858 @@ -228,127 +314,138 @@
38859                                 }
38860                                 sqlite3_free(err);
38861                         }
38862 -       
38863 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38864 -                               CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"), 
38865 -                               &(s->stmt_update_prop), &next_stmt)) {
38866 +
38867 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38868 +                               CONST_STR_LEN("INSERT INTO locks (locktoken, resource, lockscope, locktype, owner, depth, timeout) VALUES (?,?,?,?,?,?, CURRENT_TIME + 600)"),
38869 +                               &(s->stmt_create_lock), &next_stmt)) {
38870                                 /* prepare failed */
38871 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38872  
38873 -                               log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
38874                                 return HANDLER_ERROR;
38875                         }
38876  
38877 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38878 -                               CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"), 
38879 -                               &(s->stmt_delete_prop), &next_stmt)) {
38880 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38881 +                               CONST_STR_LEN("DELETE FROM locks WHERE locktoken = ?"),
38882 +                               &(s->stmt_remove_lock), &next_stmt)) {
38883                                 /* prepare failed */
38884                                 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38885  
38886                                 return HANDLER_ERROR;
38887                         }
38888  
38889 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38890 -                               CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"), 
38891 -                               &(s->stmt_delete_uri), &next_stmt)) {
38892 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38893 +                               CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE locktoken = ?"),
38894 +                               &(s->stmt_read_lock), &next_stmt)) {
38895                                 /* prepare failed */
38896                                 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38897  
38898                                 return HANDLER_ERROR;
38899                         }
38900  
38901 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38902 -                               CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"), 
38903 -                               &(s->stmt_copy_uri), &next_stmt)) {
38904 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38905 +                               CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE resource = ?"),
38906 +                               &(s->stmt_read_lock_by_uri), &next_stmt)) {
38907                                 /* prepare failed */
38908                                 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38909  
38910                                 return HANDLER_ERROR;
38911                         }
38912  
38913 -                       if (SQLITE_OK != sqlite3_prepare(s->sql, 
38914 -                               CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"), 
38915 -                               &(s->stmt_move_uri), &next_stmt)) {
38916 +                       if (SQLITE_OK != sqlite3_prepare(s->sql,
38917 +                               CONST_STR_LEN("UPDATE locks SET timeout = CURRENT_TIME + 600 WHERE locktoken = ?"),
38918 +                               &(s->stmt_refresh_lock), &next_stmt)) {
38919                                 /* prepare failed */
38920                                 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
38921  
38922                                 return HANDLER_ERROR;
38923                         }
38924 +
38925 +
38926  #else
38927                         log_error_write(srv, __FILE__, __LINE__, "s", "Sorry, no sqlite3 and libxml2 support include, compile with --with-webdav-props");
38928                         return HANDLER_ERROR;
38929  #endif
38930                 }
38931         }
38932 -       
38933 +
38934         return HANDLER_GO_ON;
38935  }
38936  
38937 -#define PATCH(x) \
38938 -       p->conf.x = s->x;
38939  static int mod_webdav_patch_connection(server *srv, connection *con, plugin_data *p) {
38940         size_t i, j;
38941         plugin_config *s = p->config_storage[0];
38942 -       
38943 -       PATCH(enabled);
38944 -       PATCH(is_readonly);
38945 -       PATCH(log_xml);
38946 -       
38947 +
38948 +       PATCH_OPTION(enabled);
38949 +       PATCH_OPTION(is_readonly);
38950 +       PATCH_OPTION(log_xml);
38951 +
38952  #ifdef USE_PROPPATCH
38953 -       PATCH(sql);
38954 -       PATCH(stmt_update_prop);
38955 -       PATCH(stmt_delete_prop);
38956 -       PATCH(stmt_select_prop);
38957 -       PATCH(stmt_select_propnames);
38958 -
38959 -       PATCH(stmt_delete_uri);
38960 -       PATCH(stmt_move_uri);
38961 -       PATCH(stmt_copy_uri);
38962 +       PATCH_OPTION(sql);
38963 +       PATCH_OPTION(stmt_update_prop);
38964 +       PATCH_OPTION(stmt_delete_prop);
38965 +       PATCH_OPTION(stmt_select_prop);
38966 +       PATCH_OPTION(stmt_select_propnames);
38967 +
38968 +       PATCH_OPTION(stmt_delete_uri);
38969 +       PATCH_OPTION(stmt_move_uri);
38970 +       PATCH_OPTION(stmt_copy_uri);
38971 +
38972 +       PATCH_OPTION(stmt_remove_lock);
38973 +       PATCH_OPTION(stmt_refresh_lock);
38974 +       PATCH_OPTION(stmt_create_lock);
38975 +       PATCH_OPTION(stmt_read_lock);
38976 +       PATCH_OPTION(stmt_read_lock_by_uri);
38977  #endif
38978         /* skip the first, the global context */
38979         for (i = 1; i < srv->config_context->used; i++) {
38980                 data_config *dc = (data_config *)srv->config_context->data[i];
38981                 s = p->config_storage[i];
38982 -               
38983 +
38984                 /* condition didn't match */
38985                 if (!config_check_cond(srv, con, dc)) continue;
38986 -               
38987 +
38988                 /* merge config */
38989                 for (j = 0; j < dc->value->used; j++) {
38990                         data_unset *du = dc->value->data[j];
38991 -                       
38992 +
38993                         if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.activate"))) {
38994 -                               PATCH(enabled);
38995 +                               PATCH_OPTION(enabled);
38996                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.is-readonly"))) {
38997 -                               PATCH(is_readonly);
38998 +                               PATCH_OPTION(is_readonly);
38999                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.log-xml"))) {
39000 -                               PATCH(log_xml);
39001 +                               PATCH_OPTION(log_xml);
39002                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.sqlite-db-name"))) {
39003  #ifdef USE_PROPPATCH
39004 -                               PATCH(sql);
39005 -                               PATCH(stmt_update_prop);
39006 -                               PATCH(stmt_delete_prop);
39007 -                               PATCH(stmt_select_prop);
39008 -                               PATCH(stmt_select_propnames);
39009 -                               
39010 -                               PATCH(stmt_delete_uri);
39011 -                               PATCH(stmt_move_uri);
39012 -                               PATCH(stmt_copy_uri);
39013 +                               PATCH_OPTION(sql);
39014 +                               PATCH_OPTION(stmt_update_prop);
39015 +                               PATCH_OPTION(stmt_delete_prop);
39016 +                               PATCH_OPTION(stmt_select_prop);
39017 +                               PATCH_OPTION(stmt_select_propnames);
39018 +
39019 +                               PATCH_OPTION(stmt_delete_uri);
39020 +                               PATCH_OPTION(stmt_move_uri);
39021 +                               PATCH_OPTION(stmt_copy_uri);
39022 +
39023 +                               PATCH_OPTION(stmt_remove_lock);
39024 +                               PATCH_OPTION(stmt_refresh_lock);
39025 +                               PATCH_OPTION(stmt_create_lock);
39026 +                               PATCH_OPTION(stmt_read_lock);
39027 +                               PATCH_OPTION(stmt_read_lock_by_uri);
39028  #endif
39029                         }
39030                 }
39031         }
39032 -       
39033 +
39034         return 0;
39035  }
39036 -#undef PATCH
39037  
39038  URIHANDLER_FUNC(mod_webdav_uri_handler) {
39039         plugin_data *p = p_d;
39040 -       
39041 +
39042         UNUSED(srv);
39043  
39044         if (con->uri.path->used == 0) return HANDLER_GO_ON;
39045 -       
39046 +
39047         mod_webdav_patch_connection(srv, con, p);
39048  
39049         if (!p->conf.enabled) return HANDLER_GO_ON;
39050 @@ -362,20 +459,20 @@
39051                 if (p->conf.is_readonly) {
39052                         response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND"));
39053                 } else {
39054 -                       response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH"));
39055 +                       response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH, LOCK, UNLOCK"));
39056                 }
39057                 break;
39058         default:
39059                 break;
39060         }
39061 -       
39062 +
39063         /* not found */
39064         return HANDLER_GO_ON;
39065  }
39066 -static int webdav_gen_prop_tag(server *srv, connection *con, 
39067 -               char *prop_name, 
39068 -               char *prop_ns, 
39069 -               char *value, 
39070 +static int webdav_gen_prop_tag(server *srv, connection *con,
39071 +               char *prop_name,
39072 +               char *prop_ns,
39073 +               char *value,
39074                 buffer *b) {
39075  
39076         UNUSED(srv);
39077 @@ -414,7 +511,7 @@
39078         buffer_append_string_buffer(b, dst->rel_path);
39079         buffer_append_string(b,"</D:href>\n");
39080         buffer_append_string(b,"<D:status>\n");
39081 -       
39082 +
39083         if (con->request.http_version == HTTP_VERSION_1_1) {
39084                 BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
39085         } else {
39086 @@ -458,11 +555,11 @@
39087  
39088                         /* bind the values to the insert */
39089  
39090 -                       sqlite3_bind_text(stmt, 1, 
39091 -                                         dst->rel_path->ptr, 
39092 +                       sqlite3_bind_text(stmt, 1,
39093 +                                         dst->rel_path->ptr,
39094                                           dst->rel_path->used - 1,
39095                                           SQLITE_TRANSIENT);
39096 -                                                                       
39097 +
39098                         if (SQLITE_DONE != sqlite3_step(stmt)) {
39099                                 /* */
39100                                 WP();
39101 @@ -493,14 +590,14 @@
39102                             (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
39103                                 continue;
39104                                 /* ignore the parent dir */
39105 -                       } 
39106 +                       }
39107  
39108                         buffer_copy_string_buffer(d.path, dst->path);
39109 -                       BUFFER_APPEND_SLASH(d.path);
39110 +                       PATHNAME_APPEND_SLASH(d.path);
39111                         buffer_append_string(d.path, de->d_name);
39112 -                       
39113 +
39114                         buffer_copy_string_buffer(d.rel_path, dst->rel_path);
39115 -                       BUFFER_APPEND_SLASH(d.rel_path);
39116 +                       PATHNAME_APPEND_SLASH(d.rel_path);
39117                         buffer_append_string(d.rel_path, de->d_name);
39118  
39119                         /* stat and unlink afterwards */
39120 @@ -508,7 +605,7 @@
39121                                 /* don't about it yet, rmdir will fail too */
39122                         } else if (S_ISDIR(st.st_mode)) {
39123                                 have_multi_status = webdav_delete_dir(srv, con, p, &d, b);
39124 -                                       
39125 +
39126                                 /* try to unlink it */
39127                                 if (-1 == rmdir(d.path->ptr)) {
39128                                         switch(errno) {
39129 @@ -535,11 +632,11 @@
39130  
39131                                                 /* bind the values to the insert */
39132  
39133 -                                               sqlite3_bind_text(stmt, 1, 
39134 -                                                                 d.rel_path->ptr, 
39135 +                                               sqlite3_bind_text(stmt, 1,
39136 +                                                                 d.rel_path->ptr,
39137                                                                   d.rel_path->used - 1,
39138                                                                   SQLITE_TRANSIENT);
39139 -                                                                                                       
39140 +
39141                                                 if (SQLITE_DONE != sqlite3_step(stmt)) {
39142                                                         /* */
39143                                                         WP();
39144 @@ -569,7 +666,7 @@
39145         if (stream_open(&s, src->path)) {
39146                 return 403;
39147         }
39148 -                       
39149 +
39150         if (-1 == (ofd = open(dst->path->ptr, O_WRONLY|O_TRUNC|O_CREAT|(overwrite ? 0 : O_EXCL), 0600))) {
39151                 /* opening the destination failed for some reason */
39152                 switch(errno) {
39153 @@ -601,7 +698,7 @@
39154                         break;
39155                 }
39156         }
39157 -       
39158 +
39159         stream_close(&s);
39160         close(ofd);
39161  
39162 @@ -614,16 +711,16 @@
39163                         sqlite3_reset(stmt);
39164  
39165                         /* bind the values to the insert */
39166 -                       sqlite3_bind_text(stmt, 1, 
39167 -                                         dst->rel_path->ptr, 
39168 +                       sqlite3_bind_text(stmt, 1,
39169 +                                         dst->rel_path->ptr,
39170                                           dst->rel_path->used - 1,
39171                                           SQLITE_TRANSIENT);
39172  
39173 -                       sqlite3_bind_text(stmt, 2, 
39174 -                                         src->rel_path->ptr, 
39175 +                       sqlite3_bind_text(stmt, 2,
39176 +                                         src->rel_path->ptr,
39177                                           src->rel_path->used - 1,
39178                                           SQLITE_TRANSIENT);
39179 -                                                                                                       
39180 +
39181                         if (SQLITE_DONE != sqlite3_step(stmt)) {
39182                                 /* */
39183                                 WP();
39184 @@ -655,21 +752,21 @@
39185                             (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
39186                                 continue;
39187                         }
39188 -                       
39189 +
39190                         buffer_copy_string_buffer(s.path, src->path);
39191 -                       BUFFER_APPEND_SLASH(s.path);
39192 +                       PATHNAME_APPEND_SLASH(s.path);
39193                         buffer_append_string(s.path, de->d_name);
39194  
39195                         buffer_copy_string_buffer(d.path, dst->path);
39196 -                       BUFFER_APPEND_SLASH(d.path);
39197 +                       PATHNAME_APPEND_SLASH(d.path);
39198                         buffer_append_string(d.path, de->d_name);
39199  
39200                         buffer_copy_string_buffer(s.rel_path, src->rel_path);
39201 -                       BUFFER_APPEND_SLASH(s.rel_path);
39202 +                       PATHNAME_APPEND_SLASH(s.rel_path);
39203                         buffer_append_string(s.rel_path, de->d_name);
39204  
39205                         buffer_copy_string_buffer(d.rel_path, dst->rel_path);
39206 -                       BUFFER_APPEND_SLASH(d.rel_path);
39207 +                       PATHNAME_APPEND_SLASH(d.rel_path);
39208                         buffer_append_string(d.rel_path, de->d_name);
39209  
39210                         if (-1 == stat(s.path->ptr, &st)) {
39211 @@ -692,16 +789,16 @@
39212                                                 sqlite3_reset(stmt);
39213  
39214                                                 /* bind the values to the insert */
39215 -                                               sqlite3_bind_text(stmt, 1, 
39216 -                                                         dst->rel_path->ptr, 
39217 +                                               sqlite3_bind_text(stmt, 1,
39218 +                                                         dst->rel_path->ptr,
39219                                                           dst->rel_path->used - 1,
39220                                                           SQLITE_TRANSIENT);
39221  
39222 -                                               sqlite3_bind_text(stmt, 2, 
39223 -                                                         src->rel_path->ptr, 
39224 +                                               sqlite3_bind_text(stmt, 2,
39225 +                                                         src->rel_path->ptr,
39226                                                           src->rel_path->used - 1,
39227                                                           SQLITE_TRANSIENT);
39228 -                                                                                                       
39229 +
39230                                                 if (SQLITE_DONE != sqlite3_step(stmt)) {
39231                                                         /* */
39232                                                         WP();
39233 @@ -721,7 +818,7 @@
39234                 buffer_free(s.rel_path);
39235                 buffer_free(d.path);
39236                 buffer_free(d.rel_path);
39237 -               
39238 +
39239                 closedir(srcdir);
39240         }
39241  
39242 @@ -748,12 +845,12 @@
39243                         if (S_ISDIR(sce->st.st_mode)) {
39244                                 buffer_append_string(b, "<D:getcontenttype>httpd/unix-directory</D:getcontenttype>");
39245                                 found = 1;
39246 -                       } else if(S_ISREG(sce->st.st_mode)) { 
39247 +                       } else if(S_ISREG(sce->st.st_mode)) {
39248                                 for (k = 0; k < con->conf.mimetypes->used; k++) {
39249                                         data_string *ds = (data_string *)con->conf.mimetypes->data[k];
39250 -               
39251 +
39252                                         if (ds->key->used == 0) continue;
39253 -                               
39254 +
39255                                         if (buffer_is_equal_right_len(dst->path, ds->key, ds->key->used - 1)) {
39256                                                 buffer_append_string(b,"<D:getcontenttype>");
39257                                                 buffer_append_string_buffer(b, ds->value);
39258 @@ -807,23 +904,23 @@
39259  
39260                         /* bind the values to the insert */
39261  
39262 -                       sqlite3_bind_text(stmt, 1, 
39263 -                                         dst->rel_path->ptr, 
39264 +                       sqlite3_bind_text(stmt, 1,
39265 +                                         dst->rel_path->ptr,
39266                                           dst->rel_path->used - 1,
39267                                           SQLITE_TRANSIENT);
39268 -                       sqlite3_bind_text(stmt, 2, 
39269 +                       sqlite3_bind_text(stmt, 2,
39270                                           prop_name,
39271                                           strlen(prop_name),
39272                                           SQLITE_TRANSIENT);
39273 -                       sqlite3_bind_text(stmt, 3, 
39274 +                       sqlite3_bind_text(stmt, 3,
39275                                           prop_ns,
39276                                           strlen(prop_ns),
39277                                           SQLITE_TRANSIENT);
39278  
39279                         /* it is the PK */
39280 -                       while (SQLITE_ROW == sqlite3_step(p->conf.stmt_select_prop)) {
39281 +                       while (SQLITE_ROW == sqlite3_step(stmt)) {
39282                                 /* there is a row for us, we only expect a single col 'value' */
39283 -                               webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(p->conf.stmt_select_prop, 0), b);
39284 +                               webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(stmt, 0), b);
39285                                 found = 1;
39286                         }
39287                 }
39288 @@ -840,7 +937,7 @@
39289         char *prop;
39290  } webdav_property;
39291  
39292 -webdav_property live_properties[] = { 
39293 +webdav_property live_properties[] = {
39294         { "DAV:", "creationdate" },
39295         { "DAV:", "displayname" },
39296         { "DAV:", "getcontentlanguage" },
39297 @@ -871,8 +968,8 @@
39298                         webdav_property *prop;
39299  
39300                         prop = props->ptr[i];
39301 -                       
39302 -                       if (0 != webdav_get_property(srv, con, p, 
39303 +
39304 +                       if (0 != webdav_get_property(srv, con, p,
39305                                 dst, prop->prop, prop->ns, b_200)) {
39306                                 webdav_gen_prop_tag(srv, con, prop->prop, prop->ns, NULL, b_404);
39307                         }
39308 @@ -916,12 +1013,12 @@
39309                                 if (-1 == c->file.fd &&  /* open the file if not already open */
39310                                     -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
39311                                         log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
39312 -               
39313 +
39314                                         return -1;
39315                                 }
39316 -       
39317 +
39318                                 if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
39319 -                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ", 
39320 +                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
39321                                                         strerror(errno), c->file.name,  c->file.fd);
39322  
39323                                         return -1;
39324 @@ -938,7 +1035,7 @@
39325                         if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->file.mmap.start + c->offset, weHave, 0))) {
39326                                 log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err);
39327                         }
39328 -                       
39329 +
39330                         c->offset += weHave;
39331                         cq->bytes_out += weHave;
39332  
39333 @@ -956,7 +1053,7 @@
39334                         if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->mem->ptr + c->offset, weHave, 0))) {
39335                                 log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err);
39336                         }
39337 -                       
39338 +
39339                         c->offset += weHave;
39340                         cq->bytes_out += weHave;
39341  
39342 @@ -991,6 +1088,113 @@
39343  }
39344  #endif
39345  
39346 +int webdav_lockdiscovery(server *srv, connection *con,
39347 +               buffer *locktoken, const char *lockscope, const char *locktype, int depth) {
39348 +
39349 +       buffer *b;
39350 +
39351 +       response_header_overwrite(srv, con, CONST_STR_LEN("Lock-Token"), CONST_BUF_LEN(locktoken));
39352 +
39353 +       response_header_overwrite(srv, con,
39354 +               CONST_STR_LEN("Content-Type"),
39355 +               CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39356 +
39357 +       b = chunkqueue_get_append_buffer(con->write_queue);
39358 +
39359 +       buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
39360 +
39361 +       buffer_append_string(b,"<D:prop xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
39362 +       buffer_append_string(b,"<D:lockdiscovery>\n");
39363 +       buffer_append_string(b,"<D:activelock>\n");
39364 +
39365 +       buffer_append_string(b,"<D:lockscope>");
39366 +       buffer_append_string(b,"<D:");
39367 +       buffer_append_string(b, lockscope);
39368 +       buffer_append_string(b, "/>");
39369 +       buffer_append_string(b,"</D:lockscope>\n");
39370 +
39371 +       buffer_append_string(b,"<D:locktype>");
39372 +       buffer_append_string(b,"<D:");
39373 +       buffer_append_string(b, locktype);
39374 +       buffer_append_string(b, "/>");
39375 +       buffer_append_string(b,"</D:locktype>\n");
39376 +
39377 +       buffer_append_string(b,"<D:depth>");
39378 +       buffer_append_string(b, depth == 0 ? "0" : "infinity");
39379 +       buffer_append_string(b,"</D:depth>\n");
39380 +
39381 +       buffer_append_string(b,"<D:timeout>");
39382 +       buffer_append_string(b, "Second-600");
39383 +       buffer_append_string(b,"</D:timeout>\n");
39384 +
39385 +       buffer_append_string(b,"<D:owner>");
39386 +       buffer_append_string(b,"</D:owner>\n");
39387 +
39388 +       buffer_append_string(b,"<D:locktoken>");
39389 +       buffer_append_string(b, "<D:href>");
39390 +       buffer_append_string_buffer(b, locktoken);
39391 +       buffer_append_string(b, "</D:href>");
39392 +       buffer_append_string(b,"</D:locktoken>\n");
39393 +
39394 +       buffer_append_string(b,"</D:activelock>\n");
39395 +       buffer_append_string(b,"</D:lockdiscovery>\n");
39396 +       buffer_append_string(b,"</D:prop>\n");
39397 +
39398 +       return 0;
39399 +}
39400 +/**
39401 + * check if resource is having the right locks to access to resource
39402 + *
39403 + *
39404 + *
39405 + */
39406 +int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer *uri) {
39407 +       int has_lock = 1;
39408 +
39409 +#ifdef USE_LOCKS
39410 +       data_string *ds;
39411 +
39412 +       /**
39413 +        * If can have
39414 +        * - <lock-token>
39415 +        * - [etag]
39416 +        *
39417 +        * there is NOT, AND and OR
39418 +        * and a list can be tagged
39419 +        *
39420 +        * (<lock-token>) is untagged
39421 +        * <tag> (<lock-token>) is tagged
39422 +        *
39423 +        * as long as we don't handle collections it is simple. :)
39424 +        *
39425 +        * X-Litmus: locks: 11 (owner_modify)
39426 +        * If: <http://127.0.0.1:1025/dav/litmus/lockme> (<opaquelocktoken:2165478d-0611-49c4-be92-e790d68a38f1>)
39427 +        *
39428 +        * X-Litmus: locks: 16 (fail_cond_put)
39429 +        * If: (<DAV:no-lock> ["-1622396671"])
39430 +        */
39431 +       if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
39432 +       } else {
39433 +               /* we didn't provided a lock-token -> */
39434 +               /* if the resource is locked -> 423 */
39435 +
39436 +               sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
39437 +
39438 +               sqlite3_reset(stmt);
39439 +
39440 +               sqlite3_bind_text(stmt, 1,
39441 +                         CONST_BUF_LEN(uri),
39442 +                         SQLITE_TRANSIENT);
39443 +
39444 +               while (SQLITE_ROW == sqlite3_step(stmt)) {
39445 +                       has_lock = 0;
39446 +               }
39447 +       }
39448 +#endif
39449 +
39450 +       return has_lock;
39451 +}
39452 +
39453  URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
39454         plugin_data *p = p_d;
39455         buffer *b;
39456 @@ -1001,7 +1205,8 @@
39457         buffer *prop_200;
39458         buffer *prop_404;
39459         webdav_properties *req_props;
39460 -       
39461 +       stat_cache_entry *sce = NULL;
39462 +
39463         UNUSED(srv);
39464  
39465         if (!p->conf.enabled) return HANDLER_GO_ON;
39466 @@ -1019,7 +1224,19 @@
39467                 req_props = NULL;
39468  
39469                 /* is there a content-body ? */
39470 -       
39471 +
39472 +               switch (stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
39473 +               case HANDLER_ERROR:
39474 +                       if (errno == ENOENT) {
39475 +                               con->http_status = 404;
39476 +                               return HANDLER_FINISHED;
39477 +                       }
39478 +                       break;
39479 +               default:
39480 +                       break;
39481 +               }
39482 +
39483 +
39484  #ifdef USE_PROPPATCH
39485                 /* any special requests or just allprop ? */
39486                 if (con->request.content_length) {
39487 @@ -1087,12 +1304,12 @@
39488                                                                 /* get all property names (EMPTY) */
39489                                                                 sqlite3_reset(stmt);
39490                                                                 /* bind the values to the insert */
39491 -       
39492 -                                                               sqlite3_bind_text(stmt, 1, 
39493 -                                                                                 con->uri.path->ptr, 
39494 +
39495 +                                                               sqlite3_bind_text(stmt, 1,
39496 +                                                                                 con->uri.path->ptr,
39497                                                                                   con->uri.path->used - 1,
39498                                                                                   SQLITE_TRANSIENT);
39499 -                                               
39500 +
39501                                                                 if (SQLITE_DONE != sqlite3_step(stmt)) {
39502                                                                         WP();
39503                                                                 }
39504 @@ -1115,13 +1332,13 @@
39505                 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39506  
39507                 b = chunkqueue_get_append_buffer(con->write_queue);
39508 -                               
39509 +
39510                 buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
39511  
39512                 buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
39513  
39514                 /* allprop */
39515 -               
39516 +
39517                 prop_200 = buffer_init();
39518                 prop_404 = buffer_init();
39519  
39520 @@ -1129,7 +1346,7 @@
39521                 case 0:
39522                         /* Depth: 0 */
39523                         webdav_get_props(srv, con, p, &(con->physical), req_props, prop_200, prop_404);
39524 -       
39525 +
39526                         buffer_append_string(b,"<D:response>\n");
39527                         buffer_append_string(b,"<D:href>");
39528                         buffer_append_string_buffer(b, con->uri.scheme);
39529 @@ -1145,9 +1362,9 @@
39530                                 buffer_append_string_buffer(b, prop_200);
39531  
39532                                 buffer_append_string(b,"</D:prop>\n");
39533 -       
39534 +
39535                                 buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
39536 -       
39537 +
39538                                 buffer_append_string(b,"</D:propstat>\n");
39539                         }
39540                         if (!buffer_is_empty(prop_404)) {
39541 @@ -1157,16 +1374,16 @@
39542                                 buffer_append_string_buffer(b, prop_404);
39543  
39544                                 buffer_append_string(b,"</D:prop>\n");
39545 -       
39546 +
39547                                 buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
39548 -       
39549 +
39550                                 buffer_append_string(b,"</D:propstat>\n");
39551                         }
39552  
39553                         buffer_append_string(b,"</D:response>\n");
39554  
39555                         break;
39556 -               case 1: 
39557 +               case 1:
39558                         if (NULL != (dir = opendir(con->physical.path->ptr))) {
39559                                 struct dirent *de;
39560                                 physical d;
39561 @@ -1179,16 +1396,16 @@
39562                                         if (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') {
39563                                                 continue;
39564                                                 /* ignore the parent dir */
39565 -                                       } 
39566 +                                       }
39567  
39568                                         buffer_copy_string_buffer(d.path, dst->path);
39569 -                                       BUFFER_APPEND_SLASH(d.path);
39570 +                                       PATHNAME_APPEND_SLASH(d.path);
39571  
39572                                         buffer_copy_string_buffer(d.rel_path, dst->rel_path);
39573 -                                       BUFFER_APPEND_SLASH(d.rel_path);
39574 +                                       PATHNAME_APPEND_SLASH(d.rel_path);
39575  
39576                                         if (de->d_name[0] == '.' && de->d_name[1] == '\0') {
39577 -                                               /* don't append the . */ 
39578 +                                               /* don't append the . */
39579                                         } else {
39580                                                 buffer_append_string(d.path, de->d_name);
39581                                                 buffer_append_string(d.rel_path, de->d_name);
39582 @@ -1198,7 +1415,7 @@
39583                                         buffer_reset(prop_404);
39584  
39585                                         webdav_get_props(srv, con, p, &d, req_props, prop_200, prop_404);
39586 -                                       
39587 +
39588                                         buffer_append_string(b,"<D:response>\n");
39589                                         buffer_append_string(b,"<D:href>");
39590                                         buffer_append_string_buffer(b, con->uri.scheme);
39591 @@ -1214,9 +1431,9 @@
39592                                                 buffer_append_string_buffer(b, prop_200);
39593  
39594                                                 buffer_append_string(b,"</D:prop>\n");
39595 -                       
39596 +
39597                                                 buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
39598 -                       
39599 +
39600                                                 buffer_append_string(b,"</D:propstat>\n");
39601                                         }
39602                                         if (!buffer_is_empty(prop_404)) {
39603 @@ -1226,9 +1443,9 @@
39604                                                 buffer_append_string_buffer(b, prop_404);
39605  
39606                                                 buffer_append_string(b,"</D:prop>\n");
39607 -       
39608 +
39609                                                 buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
39610 -       
39611 +
39612                                                 buffer_append_string(b,"</D:propstat>\n");
39613                                         }
39614  
39615 @@ -1275,7 +1492,7 @@
39616  
39617                         return HANDLER_FINISHED;
39618                 }
39619 -       
39620 +
39621                 /* let's create the directory */
39622  
39623                 if (-1 == mkdir(con->physical.path->ptr, 0700)) {
39624 @@ -1303,7 +1520,13 @@
39625                         con->http_status = 403;
39626                         return HANDLER_FINISHED;
39627                 }
39628 -               
39629 +
39630 +               /* does the client have a lock for this connection ? */
39631 +               if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39632 +                       con->http_status = 423;
39633 +                       return HANDLER_FINISHED;
39634 +               }
39635 +
39636                 /* stat and unlink afterwards */
39637                 if (-1 == stat(con->physical.path->ptr, &st)) {
39638                         /* don't about it yet, unlink will fail too */
39639 @@ -1323,7 +1546,7 @@
39640                                 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
39641  
39642                                 b = chunkqueue_get_append_buffer(con->write_queue);
39643 -                       
39644 +
39645                                 buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
39646  
39647                                 buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\">\n");
39648 @@ -1331,7 +1554,7 @@
39649                                 buffer_append_string_buffer(b, multi_status_resp);
39650  
39651                                 buffer_append_string(b,"</D:multistatus>\n");
39652 -                       
39653 +
39654                                 if (p->conf.log_xml) {
39655                                         log_error_write(srv, __FILE__, __LINE__, "sb", "XML-response-body:", b);
39656                                 }
39657 @@ -1340,7 +1563,7 @@
39658                                 con->file_finished = 1;
39659                         } else {
39660                                 /* everything went fine, remove the directory */
39661 -       
39662 +
39663                                 if (-1 == rmdir(con->physical.path->ptr)) {
39664                                         switch(errno) {
39665                                         case ENOENT:
39666 @@ -1375,97 +1598,174 @@
39667         case HTTP_METHOD_PUT: {
39668                 int fd;
39669                 chunkqueue *cq = con->request_content_queue;
39670 +               chunk *c;
39671 +               data_string *ds_range;
39672  
39673                 if (p->conf.is_readonly) {
39674                         con->http_status = 403;
39675                         return HANDLER_FINISHED;
39676                 }
39677  
39678 +               /* is a exclusive lock set on the source */
39679 +               if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39680 +                       con->http_status = 423;
39681 +                       return HANDLER_FINISHED;
39682 +               }
39683 +
39684 +
39685                 assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
39686  
39687 -               /* taken what we have in the request-body and write it to a file */
39688 -               if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC, 0600))) {
39689 -                       /* we can't open the file */
39690 -                       con->http_status = 403;
39691 -               } else {
39692 -                       chunk *c;
39693 +               /* RFC2616 Section 9.6 PUT requires us to send 501 on all Content-* we don't support
39694 +                * - most important Content-Range
39695 +                *
39696 +                *
39697 +                * Example: Content-Range: bytes 100-1037/1038 */
39698  
39699 -                       con->http_status = 201; /* created */
39700 -                       con->file_finished = 1;
39701 +               if (NULL != (ds_range = (data_string *)array_get_element(con->request.headers, "Content-Range"))) {
39702 +                       const char *num = ds_range->value->ptr;
39703 +                       off_t offset;
39704 +                       char *err = NULL;
39705  
39706 -                       for (c = cq->first; c; c = cq->first) {
39707 -                               int r = 0; 
39708 +                       if (0 != strncmp(num, "bytes ", 6)) {
39709 +                               con->http_status = 501; /* not implemented */
39710  
39711 -                               /* copy all chunks */
39712 -                               switch(c->type) {
39713 -                               case FILE_CHUNK:
39714 -
39715 -                                       if (c->file.mmap.start == MAP_FAILED) {
39716 -                                               if (-1 == c->file.fd &&  /* open the file if not already open */
39717 -                                                   -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
39718 -                                                       log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
39719 -                                       
39720 -                                                       return -1;
39721 -                                               }
39722 -                               
39723 -                                               if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
39724 -                                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ", 
39725 -                                                                       strerror(errno), c->file.name,  c->file.fd);
39726 +                               return HANDLER_FINISHED;
39727 +                       }
39728  
39729 -                                                       return -1;
39730 -                                               }
39731 +                       /* we only support <num>- ... */
39732  
39733 -                                               c->file.mmap.length = c->file.length;
39734 +                       num += 6;
39735  
39736 -                                               close(c->file.fd);
39737 -                                               c->file.fd = -1;
39738 -       
39739 -                                               /* chunk_reset() or chunk_free() will cleanup for us */
39740 -                                       }
39741 -
39742 -                                       if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
39743 -                                               switch(errno) {
39744 -                                               case ENOSPC:
39745 -                                                       con->http_status = 507;
39746 -               
39747 -                                                       break;
39748 -                                               default:
39749 -                                                       con->http_status = 403;
39750 -                                                       break;
39751 -                                               }
39752 -                                       }
39753 -                                       break;
39754 -                               case MEM_CHUNK:
39755 -                                       if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
39756 -                                               switch(errno) {
39757 -                                               case ENOSPC:
39758 -                                                       con->http_status = 507;
39759 -               
39760 -                                                       break;
39761 -                                               default:
39762 -                                                       con->http_status = 403;
39763 -                                                       break;
39764 -                                               }
39765 -                                       }
39766 +                       /* skip WS */
39767 +                       while (*num == ' ' || *num == '\t') num++;
39768 +
39769 +                       if (*num == '\0') {
39770 +                               con->http_status = 501; /* not implemented */
39771 +
39772 +                               return HANDLER_FINISHED;
39773 +                       }
39774 +
39775 +                       offset = strtoll(num, &err, 10);
39776 +
39777 +                       if (*err != '-' || offset < 0) {
39778 +                               con->http_status = 501; /* not implemented */
39779 +
39780 +                               return HANDLER_FINISHED;
39781 +                       }
39782 +
39783 +                       if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY, 0600))) {
39784 +                               switch (errno) {
39785 +                               case ENOENT:
39786 +                                       con->http_status = 404; /* not found */
39787                                         break;
39788 -                               case UNUSED_CHUNK:
39789 +                               default:
39790 +                                       con->http_status = 403; /* not found */
39791                                         break;
39792                                 }
39793 +                               return HANDLER_FINISHED;
39794 +                       }
39795 +
39796 +                       if (-1 == lseek(fd, offset, SEEK_SET)) {
39797 +                               con->http_status = 501; /* not implemented */
39798 +
39799 +                               close(fd);
39800 +
39801 +                               return HANDLER_FINISHED;
39802 +                       }
39803 +                       con->http_status = 200; /* modified */
39804 +               } else {
39805 +                       /* take what we have in the request-body and write it to a file */
39806 +
39807 +                       /* if the file doesn't exist, create it */
39808 +                       if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_TRUNC, 0600))) {
39809 +                               if (errno == ENOENT &&
39810 +                                   -1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0600))) {
39811 +                                       /* we can't open the file */
39812 +                                       con->http_status = 403;
39813  
39814 -                               if (r > 0) {
39815 -                                       c->offset += r;
39816 -                                       cq->bytes_out += r;
39817 +                                       return HANDLER_FINISHED;
39818                                 } else {
39819 -                                       break;
39820 +                                       con->http_status = 201; /* created */
39821 +                               }
39822 +                       } else {
39823 +                               con->http_status = 200; /* modified */
39824 +                       }
39825 +               }
39826 +
39827 +               con->file_finished = 1;
39828 +
39829 +               for (c = cq->first; c; c = cq->first) {
39830 +                       int r = 0;
39831 +
39832 +                       /* copy all chunks */
39833 +                       switch(c->type) {
39834 +                       case FILE_CHUNK:
39835 +
39836 +                               if (c->file.mmap.start == MAP_FAILED) {
39837 +                                       if (-1 == c->file.fd &&  /* open the file if not already open */
39838 +                                           -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
39839 +                                               log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
39840 +
39841 +                                               return -1;
39842 +                                       }
39843 +
39844 +                                       if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
39845 +                                               log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
39846 +                                                               strerror(errno), c->file.name,  c->file.fd);
39847 +
39848 +                                               return -1;
39849 +                                       }
39850 +
39851 +                                       c->file.mmap.length = c->file.length;
39852 +
39853 +                                       close(c->file.fd);
39854 +                                       c->file.fd = -1;
39855 +
39856 +                                       /* chunk_reset() or chunk_free() will cleanup for us */
39857 +                               }
39858 +
39859 +                               if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
39860 +                                       switch(errno) {
39861 +                                       case ENOSPC:
39862 +                                               con->http_status = 507;
39863 +
39864 +                                               break;
39865 +                                       default:
39866 +                                               con->http_status = 403;
39867 +                                               break;
39868 +                                       }
39869                                 }
39870 -                               chunkqueue_remove_finished_chunks(cq);
39871 +                               break;
39872 +                       case MEM_CHUNK:
39873 +                               if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
39874 +                                       switch(errno) {
39875 +                                       case ENOSPC:
39876 +                                               con->http_status = 507;
39877 +
39878 +                                               break;
39879 +                                       default:
39880 +                                               con->http_status = 403;
39881 +                                               break;
39882 +                                       }
39883 +                               }
39884 +                               break;
39885 +                       case UNUSED_CHUNK:
39886 +                               break;
39887                         }
39888 -                       close(fd);
39889  
39890 +                       if (r > 0) {
39891 +                               c->offset += r;
39892 +                               cq->bytes_out += r;
39893 +                       } else {
39894 +                               break;
39895 +                       }
39896 +                       chunkqueue_remove_finished_chunks(cq);
39897                 }
39898 +               close(fd);
39899 +
39900                 return HANDLER_FINISHED;
39901         }
39902 -       case HTTP_METHOD_MOVE: 
39903 +       case HTTP_METHOD_MOVE:
39904         case HTTP_METHOD_COPY: {
39905                 buffer *destination = NULL;
39906                 char *sep, *start;
39907 @@ -1475,7 +1775,15 @@
39908                         con->http_status = 403;
39909                         return HANDLER_FINISHED;
39910                 }
39911 -               
39912 +
39913 +               /* is a exclusive lock set on the source */
39914 +               if (con->request.http_method == HTTP_METHOD_MOVE) {
39915 +                       if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39916 +                               con->http_status = 423;
39917 +                               return HANDLER_FINISHED;
39918 +                       }
39919 +               }
39920 +
39921                 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Destination"))) {
39922                         destination = ds->value;
39923                 } else {
39924 @@ -1549,10 +1857,10 @@
39925                 }
39926  
39927                 buffer_copy_string_buffer(p->physical.path, p->physical.doc_root);
39928 -               BUFFER_APPEND_SLASH(p->physical.path);
39929 +               PATHNAME_APPEND_SLASH(p->physical.path);
39930                 buffer_copy_string_buffer(p->physical.basedir, p->physical.path);
39931  
39932 -               /* don't add a second / */ 
39933 +               /* don't add a second / */
39934                 if (p->physical.rel_path->ptr[0] == '/') {
39935                         buffer_append_string_len(p->physical.path, p->physical.rel_path->ptr + 1, p->physical.rel_path->used - 2);
39936                 } else {
39937 @@ -1613,6 +1921,12 @@
39938                         /* it is just a file, good */
39939                         int r;
39940  
39941 +                       /* does the client have a lock for this connection ? */
39942 +                       if (!webdav_has_lock(srv, con, p, p->uri.path)) {
39943 +                               con->http_status = 423;
39944 +                               return HANDLER_FINISHED;
39945 +                       }
39946 +
39947                         /* destination exists */
39948                         if (0 == (r = stat(p->physical.path->ptr, &st))) {
39949                                 if (S_ISDIR(st.st_mode)) {
39950 @@ -1636,7 +1950,7 @@
39951                                         return HANDLER_FINISHED;
39952                                 }
39953                         } else if (overwrite == 0) {
39954 -                               /* destination exists, but overwrite is not set */ 
39955 +                               /* destination exists, but overwrite is not set */
39956                                 con->http_status = 412;
39957                                 return HANDLER_FINISHED;
39958                         } else {
39959 @@ -1655,16 +1969,16 @@
39960                                                 sqlite3_reset(stmt);
39961  
39962                                                 /* bind the values to the insert */
39963 -                                               sqlite3_bind_text(stmt, 1, 
39964 -                                                                 p->uri.path->ptr, 
39965 +                                               sqlite3_bind_text(stmt, 1,
39966 +                                                                 p->uri.path->ptr,
39967                                                                   p->uri.path->used - 1,
39968                                                                   SQLITE_TRANSIENT);
39969  
39970 -                                               sqlite3_bind_text(stmt, 2, 
39971 -                                                                 con->uri.path->ptr, 
39972 +                                               sqlite3_bind_text(stmt, 2,
39973 +                                                                 con->uri.path->ptr,
39974                                                                   con->uri.path->used - 1,
39975                                                                   SQLITE_TRANSIENT);
39976 -                                               
39977 +
39978                                                 if (SQLITE_DONE != sqlite3_step(stmt)) {
39979                                                         log_error_write(srv, __FILE__, __LINE__, "ss", "sql-move failed:", sqlite3_errmsg(p->conf.sql));
39980                                                 }
39981 @@ -1691,12 +2005,17 @@
39982  
39983                 return HANDLER_FINISHED;
39984         }
39985 -       case HTTP_METHOD_PROPPATCH: {
39986 +       case HTTP_METHOD_PROPPATCH:
39987                 if (p->conf.is_readonly) {
39988                         con->http_status = 403;
39989                         return HANDLER_FINISHED;
39990                 }
39991  
39992 +               if (!webdav_has_lock(srv, con, p, con->uri.path)) {
39993 +                       con->http_status = 423;
39994 +                       return HANDLER_FINISHED;
39995 +               }
39996 +
39997                 /* check if destination exists */
39998                 if (-1 == stat(con->physical.path->ptr, &st)) {
39999                         switch(errno) {
40000 @@ -1737,7 +2056,7 @@
40001  
40002                                                         sqlite3_stmt *stmt;
40003  
40004 -                                                       stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ? 
40005 +                                                       stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ?
40006                                                                 p->conf.stmt_delete_prop : p->conf.stmt_update_prop;
40007  
40008                                                         for (props = cmd->children; props; props = props->next) {
40009 @@ -1762,34 +2081,35 @@
40010  
40011                                                                         /* bind the values to the insert */
40012  
40013 -                                                                       sqlite3_bind_text(stmt, 1, 
40014 -                                                                                         con->uri.path->ptr, 
40015 +                                                                       sqlite3_bind_text(stmt, 1,
40016 +                                                                                         con->uri.path->ptr,
40017                                                                                           con->uri.path->used - 1,
40018                                                                                           SQLITE_TRANSIENT);
40019 -                                                                       sqlite3_bind_text(stmt, 2, 
40020 +                                                                       sqlite3_bind_text(stmt, 2,
40021                                                                                           (char *)prop->name,
40022                                                                                           strlen((char *)prop->name),
40023                                                                                           SQLITE_TRANSIENT);
40024                                                                         if (prop->ns) {
40025 -                                                                               sqlite3_bind_text(stmt, 3, 
40026 +                                                                               sqlite3_bind_text(stmt, 3,
40027                                                                                                   (char *)prop->ns->href,
40028                                                                                                   strlen((char *)prop->ns->href),
40029                                                                                                   SQLITE_TRANSIENT);
40030                                                                         } else {
40031 -                                                                               sqlite3_bind_text(stmt, 3, 
40032 +                                                                               sqlite3_bind_text(stmt, 3,
40033                                                                                                   "",
40034                                                                                                   0,
40035                                                                                                   SQLITE_TRANSIENT);
40036                                                                         }
40037                                                                         if (stmt == p->conf.stmt_update_prop) {
40038 -                                                                               sqlite3_bind_text(stmt, 4, 
40039 +                                                                               sqlite3_bind_text(stmt, 4,
40040                                                                                           (char *)xmlNodeGetContent(prop),
40041                                                                                           strlen((char *)xmlNodeGetContent(prop)),
40042                                                                                           SQLITE_TRANSIENT);
40043                                                                         }
40044 -                                                               
40045 +
40046                                                                         if (SQLITE_DONE != (r = sqlite3_step(stmt))) {
40047 -                                                                               log_error_write(srv, __FILE__, __LINE__, "ss", "sql-set failed:", sqlite3_errmsg(p->conf.sql));
40048 +                                                                               log_error_write(srv, __FILE__, __LINE__, "ss",
40049 +                                                                                               "sql-set failed:", sqlite3_errmsg(p->conf.sql));
40050                                                                         }
40051                                                                 }
40052                                                         }
40053 @@ -1804,7 +2124,7 @@
40054  
40055                                                         goto propmatch_cleanup;
40056                                                 }
40057 -       
40058 +
40059                                                 con->http_status = 400;
40060                                         } else {
40061                                                 if (SQLITE_OK != sqlite3_exec(p->conf.sql, "COMMIT", NULL, NULL, &err)) {
40062 @@ -1821,6 +2141,7 @@
40063                                 }
40064  
40065  propmatch_cleanup:
40066 +
40067                                 xmlFreeDoc(xml);
40068                         } else {
40069                                 con->http_status = 400;
40070 @@ -1830,11 +2151,307 @@
40071  #endif
40072                 con->http_status = 501;
40073                 return HANDLER_FINISHED;
40074 -       }
40075 +       case HTTP_METHOD_LOCK:
40076 +               /**
40077 +                * a mac wants to write
40078 +                *
40079 +                * LOCK /dav/expire.txt HTTP/1.1\r\n
40080 +                * User-Agent: WebDAVFS/1.3 (01308000) Darwin/8.1.0 (Power Macintosh)\r\n
40081 +                * Accept: * / *\r\n
40082 +                * Depth: 0\r\n
40083 +                * Timeout: Second-600\r\n
40084 +                * Content-Type: text/xml; charset=\"utf-8\"\r\n
40085 +                * Content-Length: 229\r\n
40086 +                * Connection: keep-alive\r\n
40087 +                * Host: 192.168.178.23:1025\r\n
40088 +                * \r\n
40089 +                * <?xml version=\"1.0\" encoding=\"utf-8\"?>\n
40090 +                * <D:lockinfo xmlns:D=\"DAV:\">\n
40091 +                *  <D:lockscope><D:exclusive/></D:lockscope>\n
40092 +                *  <D:locktype><D:write/></D:locktype>\n
40093 +                *  <D:owner>\n
40094 +                *   <D:href>http://www.apple.com/webdav_fs/</D:href>\n
40095 +                *  </D:owner>\n
40096 +                * </D:lockinfo>\n
40097 +                */
40098 +
40099 +               if (depth != 0 && depth != -1) {
40100 +                       con->http_status = 400;
40101 +
40102 +                       return HANDLER_FINISHED;
40103 +               }
40104 +
40105 +#ifdef USE_LOCKS
40106 +               if (con->request.content_length) {
40107 +                       xmlDocPtr xml;
40108 +                       buffer *hdr_if = NULL;
40109 +
40110 +                       if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
40111 +                               hdr_if = ds->value;
40112 +                       }
40113 +
40114 +                       /* we don't support Depth: Infinity on locks */
40115 +                       if (hdr_if == NULL && depth == -1) {
40116 +                               con->http_status = 409; /* Conflict */
40117 +
40118 +                               return HANDLER_FINISHED;
40119 +                       }
40120 +
40121 +                       if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) {
40122 +                               xmlNode *rootnode = xmlDocGetRootElement(xml);
40123 +
40124 +                               assert(rootnode);
40125 +
40126 +                               if (0 == xmlStrcmp(rootnode->name, BAD_CAST "lockinfo")) {
40127 +                                       xmlNode *lockinfo;
40128 +                                       const xmlChar *lockscope = NULL, *locktype = NULL, *owner = NULL;
40129 +
40130 +                                       for (lockinfo = rootnode->children; lockinfo; lockinfo = lockinfo->next) {
40131 +                                               if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "lockscope")) {
40132 +                                                       xmlNode *value;
40133 +                                                       for (value = lockinfo->children; value; value = value->next) {
40134 +                                                               if ((0 == xmlStrcmp(value->name, BAD_CAST "exclusive")) ||
40135 +                                                                   (0 == xmlStrcmp(value->name, BAD_CAST "shared"))) {
40136 +                                                                       lockscope = value->name;
40137 +                                                               } else {
40138 +                                                                       con->http_status = 400;
40139 +
40140 +                                                                       xmlFreeDoc(xml);
40141 +                                                                       return HANDLER_FINISHED;
40142 +                                                               }
40143 +                                                       }
40144 +                                               } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "locktype")) {
40145 +                                                       xmlNode *value;
40146 +                                                       for (value = lockinfo->children; value; value = value->next) {
40147 +                                                               if ((0 == xmlStrcmp(value->name, BAD_CAST "write"))) {
40148 +                                                                       locktype = value->name;
40149 +                                                               } else {
40150 +                                                                       con->http_status = 400;
40151 +
40152 +                                                                       xmlFreeDoc(xml);
40153 +                                                                       return HANDLER_FINISHED;
40154 +                                                               }
40155 +                                                       }
40156 +
40157 +                                               } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "owner")) {
40158 +                                               }
40159 +                                       }
40160 +
40161 +                                       if (lockscope && locktype) {
40162 +                                               sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
40163 +
40164 +                                               /* is this resourse already locked ? */
40165 +
40166 +                                               /* SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout
40167 +                                                *   FROM locks
40168 +                                                *  WHERE resource = ? */
40169 +
40170 +                                               if (stmt) {
40171 +
40172 +                                                       sqlite3_reset(stmt);
40173 +
40174 +                                                       sqlite3_bind_text(stmt, 1,
40175 +                                                                         p->uri.path->ptr,
40176 +                                                                         p->uri.path->used - 1,
40177 +                                                                         SQLITE_TRANSIENT);
40178 +
40179 +                                                       /* it is the PK */
40180 +                                                       while (SQLITE_ROW == sqlite3_step(stmt)) {
40181 +                                                               /* we found a lock
40182 +                                                                * 1. is it compatible ?
40183 +                                                                * 2. is it ours */
40184 +                                                               char *sql_lockscope = (char *)sqlite3_column_text(stmt, 2);
40185 +
40186 +                                                               if (strcmp(sql_lockscope, "exclusive")) {
40187 +                                                                       con->http_status = 423;
40188 +                                                               } else if (0 == xmlStrcmp(lockscope, BAD_CAST "exclusive")) {
40189 +                                                                       /* resourse is locked with a shared lock
40190 +                                                                        * client wants exclusive */
40191 +                                                                       con->http_status = 423;
40192 +                                                               }
40193 +                                                       }
40194 +                                                       if (con->http_status == 423) {
40195 +                                                               xmlFreeDoc(xml);
40196 +                                                               return HANDLER_FINISHED;
40197 +                                                       }
40198 +                                               }
40199 +
40200 +                                               stmt = p->conf.stmt_create_lock;
40201 +                                               if (stmt) {
40202 +                                                       /* create a lock-token */
40203 +                                                       uuid_t id;
40204 +                                                       char uuid[37] /* 36 + \0 */;
40205 +
40206 +                                                       uuid_generate(id);
40207 +                                                       uuid_unparse(id, uuid);
40208 +
40209 +                                                       buffer_copy_string(p->tmp_buf, "opaquelocktoken:");
40210 +                                                       buffer_append_string(p->tmp_buf, uuid);
40211 +
40212 +                                                       /* "CREATE TABLE locks ("
40213 +                                                        * "  locktoken TEXT NOT NULL,"
40214 +                                                        * "  resource TEXT NOT NULL,"
40215 +                                                        * "  lockscope TEXT NOT NULL,"
40216 +                                                        * "  locktype TEXT NOT NULL,"
40217 +                                                        * "  owner TEXT NOT NULL,"
40218 +                                                        * "  depth INT NOT NULL,"
40219 +                                                        */
40220 +
40221 +                                                       sqlite3_reset(stmt);
40222 +
40223 +                                                       sqlite3_bind_text(stmt, 1,
40224 +                                                                         CONST_BUF_LEN(p->tmp_buf),
40225 +                                                                         SQLITE_TRANSIENT);
40226 +
40227 +                                                       sqlite3_bind_text(stmt, 2,
40228 +                                                                         CONST_BUF_LEN(con->uri.path),
40229 +                                                                         SQLITE_TRANSIENT);
40230 +
40231 +                                                       sqlite3_bind_text(stmt, 3,
40232 +                                                                         lockscope,
40233 +                                                                         xmlStrlen(lockscope),
40234 +                                                                         SQLITE_TRANSIENT);
40235 +
40236 +                                                       sqlite3_bind_text(stmt, 4,
40237 +                                                                         locktype,
40238 +                                                                         xmlStrlen(locktype),
40239 +                                                                         SQLITE_TRANSIENT);
40240 +
40241 +                                                       /* owner */
40242 +                                                       sqlite3_bind_text(stmt, 5,
40243 +                                                                         "",
40244 +                                                                         0,
40245 +                                                                         SQLITE_TRANSIENT);
40246 +
40247 +                                                       /* depth */
40248 +                                                       sqlite3_bind_int(stmt, 6,
40249 +                                                                        depth);
40250 +
40251 +
40252 +                                                       if (SQLITE_DONE != sqlite3_step(stmt)) {
40253 +                                                               log_error_write(srv, __FILE__, __LINE__, "ss",
40254 +                                                                               "create lock:", sqlite3_errmsg(p->conf.sql));
40255 +                                                       }
40256 +
40257 +                                                       /* looks like we survived */
40258 +                                                       webdav_lockdiscovery(srv, con, p->tmp_buf, lockscope, locktype, depth);
40259 +
40260 +                                                       con->http_status = 201;
40261 +                                                       con->file_finished = 1;
40262 +                                               }
40263 +                                       }
40264 +                               }
40265 +
40266 +                               xmlFreeDoc(xml);
40267 +                               return HANDLER_FINISHED;
40268 +                       } else {
40269 +                               con->http_status = 400;
40270 +                               return HANDLER_FINISHED;
40271 +                       }
40272 +               } else {
40273 +
40274 +                       if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
40275 +                               buffer *locktoken = ds->value;
40276 +                               sqlite3_stmt *stmt = p->conf.stmt_refresh_lock;
40277 +
40278 +                               /* remove the < > around the token */
40279 +                               if (locktoken->used < 6) {
40280 +                                       con->http_status = 400;
40281 +
40282 +                                       return HANDLER_FINISHED;
40283 +                               }
40284 +
40285 +                               buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 2, locktoken->used - 5);
40286 +
40287 +                               sqlite3_reset(stmt);
40288 +
40289 +                               sqlite3_bind_text(stmt, 1,
40290 +                                         CONST_BUF_LEN(p->tmp_buf),
40291 +                                         SQLITE_TRANSIENT);
40292 +
40293 +                               if (SQLITE_DONE != sqlite3_step(stmt)) {
40294 +                                       log_error_write(srv, __FILE__, __LINE__, "ss",
40295 +                                               "refresh lock:", sqlite3_errmsg(p->conf.sql));
40296 +                               }
40297 +
40298 +                               webdav_lockdiscovery(srv, con, p->tmp_buf, "exclusive", "write", 0);
40299 +
40300 +                               con->http_status = 200;
40301 +                               con->file_finished = 1;
40302 +                               return HANDLER_FINISHED;
40303 +                       } else {
40304 +                               /* we need a lock-token to refresh */
40305 +                               con->http_status = 400;
40306 +
40307 +                               return HANDLER_FINISHED;
40308 +                       }
40309 +               }
40310 +               break;
40311 +#else
40312 +               con->http_status = 501;
40313 +               return HANDLER_FINISHED;
40314 +#endif
40315 +       case HTTP_METHOD_UNLOCK:
40316 +#ifdef USE_LOCKS
40317 +               if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Lock-Token"))) {
40318 +                       buffer *locktoken = ds->value;
40319 +                       sqlite3_stmt *stmt = p->conf.stmt_remove_lock;
40320 +
40321 +                       /* remove the < > around the token */
40322 +                       if (locktoken->used < 4) {
40323 +                               con->http_status = 400;
40324 +
40325 +                               return HANDLER_FINISHED;
40326 +                       }
40327 +
40328 +                       /**
40329 +                        * FIXME:
40330 +                        *
40331 +                        * if the resourse is locked:
40332 +                        * - by us: unlock
40333 +                        * - by someone else: 401
40334 +                        * if the resource is not locked:
40335 +                        * - 412
40336 +                        *  */
40337 +
40338 +                       buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 1, locktoken->used - 3);
40339 +
40340 +                       sqlite3_reset(stmt);
40341 +
40342 +                       sqlite3_bind_text(stmt, 1,
40343 +                                 CONST_BUF_LEN(p->tmp_buf),
40344 +                                 SQLITE_TRANSIENT);
40345 +
40346 +                       sqlite3_bind_text(stmt, 2,
40347 +                                 CONST_BUF_LEN(con->uri.path),
40348 +                                 SQLITE_TRANSIENT);
40349 +
40350 +                       if (SQLITE_DONE != sqlite3_step(stmt)) {
40351 +                               log_error_write(srv, __FILE__, __LINE__, "ss",
40352 +                                       "remove lock:", sqlite3_errmsg(p->conf.sql));
40353 +                       }
40354 +
40355 +                       if (0 == sqlite3_changes(p->conf.sql)) {
40356 +                               con->http_status = 401;
40357 +                       } else {
40358 +                               con->http_status = 204;
40359 +                       }
40360 +                       return HANDLER_FINISHED;
40361 +               } else {
40362 +                       /* we need a lock-token to unlock */
40363 +                       con->http_status = 400;
40364 +
40365 +                       return HANDLER_FINISHED;
40366 +               }
40367 +               break;
40368 +#else
40369 +               con->http_status = 501;
40370 +               return HANDLER_FINISHED;
40371 +#endif
40372         default:
40373                 break;
40374         }
40375 -       
40376 +
40377         /* not found */
40378         return HANDLER_GO_ON;
40379  }
40380 @@ -1845,14 +2462,14 @@
40381  int mod_webdav_plugin_init(plugin *p) {
40382         p->version     = LIGHTTPD_VERSION_ID;
40383         p->name        = buffer_init_string("webdav");
40384 -       
40385 +
40386         p->init        = mod_webdav_init;
40387         p->handle_uri_clean  = mod_webdav_uri_handler;
40388         p->handle_physical   = mod_webdav_subrequest_handler;
40389         p->set_defaults  = mod_webdav_set_defaults;
40390         p->cleanup     = mod_webdav_free;
40391 -       
40392 +
40393         p->data        = NULL;
40394 -       
40395 +
40396         return 0;
40397  }
40398 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/network.c lighttpd-1.4.12/src/network.c
40399 --- lighttpd-1.4.11/src/network.c       2006-03-04 16:45:46.000000000 +0200
40400 +++ lighttpd-1.4.12/src/network.c       2006-07-11 21:23:39.000000000 +0300
40401 @@ -1,14 +1,14 @@
40402  #include <sys/types.h>
40403  #include <sys/stat.h>
40404 -#include <sys/time.h>
40405  
40406  #include <errno.h>
40407  #include <fcntl.h>
40408 -#include <unistd.h>
40409  #include <string.h>
40410  #include <stdlib.h>
40411  #include <assert.h>
40412  
40413 +#include <stdio.h>
40414 +
40415  #include "network.h"
40416  #include "fdevent.h"
40417  #include "log.h"
40418 @@ -19,11 +19,12 @@
40419  #include "network_backends.h"
40420  #include "sys-mmap.h"
40421  #include "sys-socket.h"
40422 +#include "sys-files.h"
40423  
40424  #ifdef USE_OPENSSL
40425 -# include <openssl/ssl.h> 
40426 -# include <openssl/err.h> 
40427 -# include <openssl/rand.h> 
40428 +# include <openssl/ssl.h>
40429 +# include <openssl/err.h>
40430 +# include <openssl/rand.h>
40431  #endif
40432  
40433  handler_t network_server_handle_fdevent(void *s, void *context, int revents) {
40434 @@ -31,11 +32,11 @@
40435         server_socket *srv_socket = (server_socket *)context;
40436         connection *con;
40437         int loops = 0;
40438 -       
40439 +
40440         UNUSED(context);
40441 -       
40442 +
40443         if (revents != FDEVENT_IN) {
40444 -               log_error_write(srv, __FILE__, __LINE__, "sdd", 
40445 +               log_error_write(srv, __FILE__, __LINE__, "sdd",
40446                                 "strange event for server socket",
40447                                 srv_socket->fd,
40448                                 revents);
40449 @@ -44,12 +45,12 @@
40450  
40451         /* accept()s at most 100 connections directly
40452          *
40453 -        * we jump out after 100 to give the waiting connections a chance */    
40454 +        * we jump out after 100 to give the waiting connections a chance */
40455         for (loops = 0; loops < 100 && NULL != (con = connection_accept(srv, srv_socket)); loops++) {
40456                 handler_t r;
40457 -               
40458 +
40459                 connection_state_machine(srv, con);
40460 -               
40461 +
40462                 switch(r = plugins_call_handle_joblist(srv, con)) {
40463                 case HANDLER_FINISHED:
40464                 case HANDLER_GO_ON:
40465 @@ -72,18 +73,18 @@
40466         buffer *b;
40467         int is_unix_domain_socket = 0;
40468         int fd;
40469 -       
40470 +
40471  #ifdef SO_ACCEPTFILTER
40472         struct accept_filter_arg afa;
40473  #endif
40474  
40475 -#ifdef __WIN32
40476 +#ifdef _WIN32
40477         WORD wVersionRequested;
40478         WSADATA wsaData;
40479         int err;
40480 -        
40481 +
40482         wVersionRequested = MAKEWORD( 2, 2 );
40483 -        
40484 +
40485         err = WSAStartup( wVersionRequested, &wsaData );
40486         if ( err != 0 ) {
40487                     /* Tell the user that we could not find a usable */
40488 @@ -91,37 +92,37 @@
40489                     return -1;
40490         }
40491  #endif
40492 -       
40493 +
40494         srv_socket = calloc(1, sizeof(*srv_socket));
40495         srv_socket->fd = -1;
40496 -       
40497 +
40498         srv_socket->srv_token = buffer_init();
40499         buffer_copy_string_buffer(srv_socket->srv_token, host_token);
40500 -       
40501 +
40502         b = buffer_init();
40503         buffer_copy_string_buffer(b, host_token);
40504 -       
40505 -       /* ipv4:port 
40506 +
40507 +       /* ipv4:port
40508          * [ipv6]:port
40509          */
40510         if (NULL == (sp = strrchr(b->ptr, ':'))) {
40511                 log_error_write(srv, __FILE__, __LINE__, "sb", "value of $SERVER[\"socket\"] has to be \"ip:port\".", b);
40512 -               
40513 +
40514                 return -1;
40515         }
40516 -       
40517 +
40518         host = b->ptr;
40519 -       
40520 +
40521         /* check for [ and ] */
40522         if (b->ptr[0] == '[' && *(sp-1) == ']') {
40523                 *(sp-1) = '\0';
40524                 host++;
40525 -               
40526 +
40527                 s->use_ipv6 = 1;
40528         }
40529 -       
40530 +
40531         *(sp++) = '\0';
40532 -       
40533 +
40534         port = strtol(sp, NULL, 10);
40535  
40536         if (host[0] == '/') {
40537 @@ -129,17 +130,17 @@
40538                 is_unix_domain_socket = 1;
40539         } else if (port == 0 || port > 65535) {
40540                 log_error_write(srv, __FILE__, __LINE__, "sd", "port out of range:", port);
40541 -       
40542 +
40543                 return -1;
40544         }
40545 -       
40546 +
40547         if (*host == '\0') host = NULL;
40548  
40549         if (is_unix_domain_socket) {
40550  #ifdef HAVE_SYS_UN_H
40551  
40552                 srv_socket->addr.plain.sa_family = AF_UNIX;
40553 -               
40554 +
40555                 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) {
40556                         log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
40557                         return -1;
40558 @@ -154,7 +155,7 @@
40559  #ifdef HAVE_IPV6
40560         if (s->use_ipv6) {
40561                 srv_socket->addr.plain.sa_family = AF_INET6;
40562 -               
40563 +
40564                 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
40565                         log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
40566                         return -1;
40567 @@ -162,7 +163,7 @@
40568                 srv_socket->use_ipv6 = 1;
40569         }
40570  #endif
40571 -                               
40572 +
40573         if (srv_socket->fd == -1) {
40574                 srv_socket->addr.plain.sa_family = AF_INET;
40575                 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
40576 @@ -170,16 +171,16 @@
40577                         return -1;
40578                 }
40579         }
40580 -       
40581 +
40582         /* */
40583         srv->cur_fds = srv_socket->fd;
40584 -       
40585 +
40586         val = 1;
40587         if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
40588                 log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt failed:", strerror(errno));
40589                 return -1;
40590         }
40591 -       
40592 +
40593         switch(srv_socket->addr.plain.sa_family) {
40594  #ifdef HAVE_IPV6
40595         case AF_INET6:
40596 @@ -190,23 +191,23 @@
40597                 } else {
40598                         struct addrinfo hints, *res;
40599                         int r;
40600 -                       
40601 +
40602                         memset(&hints, 0, sizeof(hints));
40603 -                       
40604 +
40605                         hints.ai_family   = AF_INET6;
40606                         hints.ai_socktype = SOCK_STREAM;
40607                         hints.ai_protocol = IPPROTO_TCP;
40608 -                       
40609 +
40610                         if (0 != (r = getaddrinfo(host, NULL, &hints, &res))) {
40611 -                               log_error_write(srv, __FILE__, __LINE__, 
40612 -                                               "sssss", "getaddrinfo failed: ", 
40613 +                               log_error_write(srv, __FILE__, __LINE__,
40614 +                                               "sssss", "getaddrinfo failed: ",
40615                                                 gai_strerror(r), "'", host, "'");
40616 -                               
40617 +
40618                                 return -1;
40619                         }
40620 -                       
40621 +
40622                         memcpy(&(srv_socket->addr), res->ai_addr, res->ai_addrlen);
40623 -                       
40624 +
40625                         freeaddrinfo(res);
40626                 }
40627                 srv_socket->addr.ipv6.sin6_port = htons(port);
40628 @@ -221,33 +222,34 @@
40629                 } else {
40630                         struct hostent *he;
40631                         if (NULL == (he = gethostbyname(host))) {
40632 -                               log_error_write(srv, __FILE__, __LINE__, 
40633 -                                               "sds", "gethostbyname failed: ", 
40634 +                               log_error_write(srv, __FILE__, __LINE__,
40635 +                                               "sds", "gethostbyname failed: ",
40636                                                 h_errno, host);
40637                                 return -1;
40638                         }
40639 -                       
40640 +
40641                         if (he->h_addrtype != AF_INET) {
40642                                 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
40643                                 return -1;
40644                         }
40645 -                       
40646 +
40647                         if (he->h_length != sizeof(struct in_addr)) {
40648                                 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
40649                                 return -1;
40650                         }
40651 -                       
40652 +
40653                         memcpy(&(srv_socket->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
40654                 }
40655                 srv_socket->addr.ipv4.sin_port = htons(port);
40656 -               
40657 +
40658                 addr_len = sizeof(struct sockaddr_in);
40659 -               
40660 +
40661                 break;
40662 +#ifndef _WIN32
40663         case AF_UNIX:
40664                 srv_socket->addr.un.sun_family = AF_UNIX;
40665                 strcpy(srv_socket->addr.un.sun_path, host);
40666 -               
40667 +
40668  #ifdef SUN_LEN
40669                 addr_len = SUN_LEN(&srv_socket->addr.un);
40670  #else
40671 @@ -259,8 +261,8 @@
40672                 if (-1 != (fd = connect(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) {
40673                         close(fd);
40674  
40675 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
40676 -                               "server socket is still in use:", 
40677 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
40678 +                               "server socket is still in use:",
40679                                 host);
40680  
40681  
40682 @@ -275,88 +277,89 @@
40683                 case ENOENT:
40684                         break;
40685                 default:
40686 -                       log_error_write(srv, __FILE__, __LINE__, "sds", 
40687 -                               "testing socket failed:", 
40688 +                       log_error_write(srv, __FILE__, __LINE__, "sds",
40689 +                               "testing socket failed:",
40690                                 host, strerror(errno));
40691  
40692                         return -1;
40693                 }
40694  
40695                 break;
40696 +#endif
40697         default:
40698                 addr_len = 0;
40699 -               
40700 +
40701                 return -1;
40702         }
40703 -       
40704 +
40705         if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
40706                 switch(srv_socket->addr.plain.sa_family) {
40707                 case AF_UNIX:
40708 -                       log_error_write(srv, __FILE__, __LINE__, "sds", 
40709 -                                       "can't bind to socket:", 
40710 +                       log_error_write(srv, __FILE__, __LINE__, "sds",
40711 +                                       "can't bind to socket:",
40712                                         host, strerror(errno));
40713                         break;
40714                 default:
40715 -                       log_error_write(srv, __FILE__, __LINE__, "ssds", 
40716 -                                       "can't bind to port:", 
40717 +                       log_error_write(srv, __FILE__, __LINE__, "ssds",
40718 +                                       "can't bind to port:",
40719                                         host, port, strerror(errno));
40720                         break;
40721                 }
40722                 return -1;
40723         }
40724 -       
40725 +
40726         if (-1 == listen(srv_socket->fd, 128 * 8)) {
40727                 log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno));
40728                 return -1;
40729         }
40730 -       
40731 +
40732         if (s->is_ssl) {
40733  #ifdef USE_OPENSSL
40734                 if (srv->ssl_is_init == 0) {
40735                         SSL_load_error_strings();
40736                         SSL_library_init();
40737                         srv->ssl_is_init = 1;
40738 -                       
40739 +
40740                         if (0 == RAND_status()) {
40741 -                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", 
40742 +                               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40743                                                 "not enough entropy in the pool");
40744                                 return -1;
40745                         }
40746                 }
40747 -               
40748 +
40749                 if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
40750 -                       log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", 
40751 +                       log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40752                                         ERR_error_string(ERR_get_error(), NULL));
40753                         return -1;
40754                 }
40755 -               
40756 +
40757                 if (buffer_is_empty(s->ssl_pemfile)) {
40758                         log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set");
40759                         return -1;
40760                 }
40761 -               
40762 +
40763                 if (!buffer_is_empty(s->ssl_ca_file)) {
40764                         if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) {
40765 -                               log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", 
40766 +                               log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40767                                                 ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
40768                                 return -1;
40769                         }
40770                 }
40771 -               
40772 +
40773                 if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
40774 -                       log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", 
40775 +                       log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40776                                         ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
40777                         return -1;
40778                 }
40779 -               
40780 +
40781                 if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
40782 -                       log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", 
40783 +                       log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
40784                                         ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
40785                         return -1;
40786                 }
40787 -               
40788 +
40789                 if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
40790 -                       log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:", 
40791 +                       log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
40792                                         "Private key does not match the certificate public key, reason:",
40793                                         ERR_error_string(ERR_get_error(), NULL),
40794                                         s->ssl_pemfile);
40795 @@ -364,15 +367,15 @@
40796                 }
40797                 srv_socket->ssl_ctx = s->ssl_ctx;
40798  #else
40799 -               
40800 +
40801                 buffer_free(srv_socket->srv_token);
40802                 free(srv_socket);
40803 -               
40804 +
40805                 buffer_free(b);
40806 -               
40807 -               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", 
40808 +
40809 +               log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
40810                                 "ssl requested but openssl support is not compiled in");
40811 -               
40812 +
40813                 return -1;
40814  #endif
40815         } else {
40816 @@ -390,10 +393,10 @@
40817                 }
40818  #endif
40819         }
40820 -       
40821 +
40822         srv_socket->is_ssl = s->is_ssl;
40823         srv_socket->fde_ndx = -1;
40824 -       
40825 +
40826         if (srv->srv_sockets.size == 0) {
40827                 srv->srv_sockets.size = 4;
40828                 srv->srv_sockets.used = 0;
40829 @@ -402,11 +405,10 @@
40830                 srv->srv_sockets.size += 4;
40831                 srv->srv_sockets.ptr = realloc(srv->srv_sockets.ptr, srv->srv_sockets.size * sizeof(server_socket));
40832         }
40833 -       
40834 +
40835         srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket;
40836 -       
40837         buffer_free(b);
40838 -       
40839 +
40840         return 0;
40841  }
40842  
40843 @@ -414,45 +416,58 @@
40844         size_t i;
40845         for (i = 0; i < srv->srv_sockets.used; i++) {
40846                 server_socket *srv_socket = srv->srv_sockets.ptr[i];
40847 -               
40848 +
40849                 if (srv_socket->fd != -1) {
40850                         /* check if server fd are already registered */
40851                         if (srv_socket->fde_ndx != -1) {
40852                                 fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
40853                                 fdevent_unregister(srv->ev, srv_socket->fd);
40854                         }
40855 -               
40856 +
40857                         close(srv_socket->fd);
40858                 }
40859 -               
40860 +
40861 +               if (srv_socket->is_ssl) {
40862 +#ifdef USE_OPENSSL
40863 +                       SSL_CTX_free(srv_socket->ssl_ctx);
40864 +#endif
40865 +               }
40866 +
40867                 buffer_free(srv_socket->srv_token);
40868 -               
40869 +
40870                 free(srv_socket);
40871         }
40872 -       
40873 +
40874 +#ifdef USE_OPENSSL
40875 +       ERR_free_strings();
40876 +#endif
40877         free(srv->srv_sockets.ptr);
40878 -       
40879 +
40880         return 0;
40881  }
40882  
40883  typedef enum {
40884         NETWORK_BACKEND_UNSET,
40885 +
40886         NETWORK_BACKEND_WRITE,
40887         NETWORK_BACKEND_WRITEV,
40888         NETWORK_BACKEND_LINUX_SENDFILE,
40889         NETWORK_BACKEND_FREEBSD_SENDFILE,
40890 -       NETWORK_BACKEND_SOLARIS_SENDFILEV
40891 +       NETWORK_BACKEND_SOLARIS_SENDFILEV,
40892 +
40893 +    NETWORK_BACKEND_WIN32_SEND,
40894 +    NETWORK_BACKEND_WIN32_TRANSMITFILE,
40895  } network_backend_t;
40896  
40897  int network_init(server *srv) {
40898         buffer *b;
40899         size_t i;
40900         network_backend_t backend;
40901 -       
40902 -       struct nb_map { 
40903 -               network_backend_t nb; 
40904 -               const char *name; 
40905 -       } network_backends[] = { 
40906 +
40907 +       struct nb_map {
40908 +               network_backend_t nb;
40909 +               const char *name;
40910 +       } network_backends[] = {
40911                 /* lowest id wins */
40912  #if defined USE_LINUX_SENDFILE
40913                 { NETWORK_BACKEND_LINUX_SENDFILE,       "linux-sendfile" },
40914 @@ -466,21 +481,30 @@
40915  #if defined USE_WRITEV
40916                 { NETWORK_BACKEND_WRITEV,               "writev" },
40917  #endif
40918 +#if defined USE_WRITE
40919                 { NETWORK_BACKEND_WRITE,                "write" },
40920 +#endif
40921 +#if defined USE_WIN32_TRANSMITFILE
40922 +               { NETWORK_BACKEND_WIN32_TRANSMITFILE,   "win32-transmitfile" },
40923 +#endif
40924 +#if defined USE_WIN32_SEND
40925 +               { NETWORK_BACKEND_WIN32_SEND,           "win32-send" },
40926 +#endif
40927 +
40928                 { NETWORK_BACKEND_UNSET,                NULL }
40929         };
40930 -       
40931 +
40932         b = buffer_init();
40933 -               
40934 +
40935         buffer_copy_string_buffer(b, srv->srvconf.bindhost);
40936         buffer_append_string(b, ":");
40937         buffer_append_long(b, srv->srvconf.port);
40938 -       
40939 +
40940         if (0 != network_server_init(srv, b, srv->config_storage[0])) {
40941                 return -1;
40942         }
40943         buffer_free(b);
40944 -               
40945 +
40946  #ifdef USE_OPENSSL
40947         srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
40948  #endif
40949 @@ -500,54 +524,80 @@
40950                 if (NULL == network_backends[i].name) {
40951                         /* we don't know it */
40952  
40953 -                       log_error_write(srv, __FILE__, __LINE__, "sb", 
40954 -                                       "server.network-backend has a unknown value:", 
40955 +                       log_error_write(srv, __FILE__, __LINE__, "sb",
40956 +                                       "server.network-backend has a unknown value:",
40957                                         srv->srvconf.network_backend);
40958  
40959                         return -1;
40960                 }
40961         }
40962  
40963 +#define SET_NETWORK_BACKEND(read, write) \
40964 +    srv->network_backend_write = network_write_chunkqueue_##write;\
40965 +    srv->network_backend_read = network_read_chunkqueue_##read
40966 +
40967 +#define SET_NETWORK_BACKEND_SSL(read, write) \
40968 +    srv->network_ssl_backend_write = network_write_chunkqueue_##write;\
40969 +    srv->network_ssl_backend_read = network_read_chunkqueue_##read
40970 +
40971         switch(backend) {
40972 +
40973 +#ifdef USE_WIN32_SEND
40974 +       case NETWORK_BACKEND_WIN32_SEND:
40975 +        SET_NETWORK_BACKEND(win32recv, win32send);
40976 +               break;
40977 +#ifdef USE_WIN32_TRANSMITFILE
40978 +       case NETWORK_BACKEND_WIN32_TRANSMITFILE:
40979 +        SET_NETWORK_BACKEND(win32recv, win32transmitfile);
40980 +               break;
40981 +#endif
40982 +#endif
40983 +
40984 +#ifdef USE_WRITE
40985         case NETWORK_BACKEND_WRITE:
40986 -               srv->network_backend_write = network_write_chunkqueue_write;
40987 +        SET_NETWORK_BACKEND(read, write);
40988                 break;
40989 +
40990  #ifdef USE_WRITEV
40991         case NETWORK_BACKEND_WRITEV:
40992 -               srv->network_backend_write = network_write_chunkqueue_writev;
40993 +        SET_NETWORK_BACKEND(read, writev);
40994                 break;
40995  #endif
40996  #ifdef USE_LINUX_SENDFILE
40997         case NETWORK_BACKEND_LINUX_SENDFILE:
40998 -               srv->network_backend_write = network_write_chunkqueue_linuxsendfile; 
40999 +        SET_NETWORK_BACKEND(read, linuxsendfile);
41000                 break;
41001  #endif
41002  #ifdef USE_FREEBSD_SENDFILE
41003         case NETWORK_BACKEND_FREEBSD_SENDFILE:
41004 -               srv->network_backend_write = network_write_chunkqueue_freebsdsendfile; 
41005 +        SET_NETWORK_BACKEND(read, freebsdsendfile);
41006                 break;
41007  #endif
41008  #ifdef USE_SOLARIS_SENDFILEV
41009         case NETWORK_BACKEND_SOLARIS_SENDFILEV:
41010 -               srv->network_backend_write = network_write_chunkqueue_solarissendfilev; 
41011 +        SET_NETWORK_BACKEND(read, solarissendfilev);
41012                 break;
41013  #endif
41014 +#endif
41015         default:
41016                 return -1;
41017         }
41018 +#ifdef USE_OPENSSL
41019 +        SET_NETWORK_BACKEND_SSL(openssl, openssl);
41020 +#endif
41021  
41022         /* check for $SERVER["socket"] */
41023         for (i = 1; i < srv->config_context->used; i++) {
41024                 data_config *dc = (data_config *)srv->config_context->data[i];
41025                 specific_config *s = srv->config_storage[i];
41026                 size_t j;
41027 -               
41028 +
41029                 /* not our stage */
41030                 if (COMP_SERVER_SOCKET != dc->comp) continue;
41031 -               
41032 +
41033                 if (dc->cond != CONFIG_COND_EQ) {
41034                         log_error_write(srv, __FILE__, __LINE__, "s", "only == is allowed for $SERVER[\"socket\"].");
41035 -                       
41036 +
41037                         return -1;
41038                 }
41039  
41040 @@ -558,36 +608,47 @@
41041                                 break;
41042                         }
41043                 }
41044 -               
41045 +
41046                 if (j == srv->srv_sockets.used) {
41047                         if (0 != network_server_init(srv, dc->string, s)) return -1;
41048                 }
41049         }
41050 -       
41051 +
41052         return 0;
41053  }
41054  
41055  int network_register_fdevents(server *srv) {
41056         size_t i;
41057 -       
41058         if (-1 == fdevent_reset(srv->ev)) {
41059                 return -1;
41060         }
41061 -       
41062         /* register fdevents after reset */
41063         for (i = 0; i < srv->srv_sockets.used; i++) {
41064                 server_socket *srv_socket = srv->srv_sockets.ptr[i];
41065 -               
41066                 fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket);
41067                 fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
41068         }
41069         return 0;
41070  }
41071  
41072 -int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
41073 -       int ret = -1;
41074 +network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
41075 +    server_socket *srv_socket = con->srv_socket;
41076 +
41077 +       if (srv_socket->is_ssl) {
41078 +#ifdef USE_OPENSSL
41079 +               return srv->network_ssl_backend_read(srv, con, con->ssl, cq);
41080 +#else
41081 +               return NETWORK_STATUS_FATAL_ERROR;
41082 +#endif
41083 +       } else {
41084 +               return srv->network_backend_read(srv, con, con->fd, cq);
41085 +       }
41086 +}
41087 +
41088 +network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
41089 +       network_status_t ret = NETWORK_STATUS_UNSET;
41090         off_t written = 0;
41091 -#ifdef TCP_CORK        
41092 +#ifdef TCP_CORK
41093         int corked = 0;
41094  #endif
41095         server_socket *srv_socket = con->srv_socket;
41096 @@ -600,11 +661,11 @@
41097                 joblist_append(srv, con);
41098  
41099                 return 1;
41100 -       }  
41101 +       }
41102  
41103         written = cq->bytes_out;
41104  
41105 -#ifdef TCP_CORK        
41106 +#ifdef TCP_CORK
41107         /* Linux: put a cork into the socket as we want to combine the write() calls
41108          * but only if we really have multiple chunks
41109          */
41110 @@ -613,7 +674,7 @@
41111                 setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
41112         }
41113  #endif
41114 -       
41115 +
41116         if (srv_socket->is_ssl) {
41117  #ifdef USE_OPENSSL
41118                 ret = srv->network_ssl_backend_write(srv, con, con->ssl, cq);
41119 @@ -621,12 +682,17 @@
41120         } else {
41121                 ret = srv->network_backend_write(srv, con, con->fd, cq);
41122         }
41123 -       
41124 -       if (ret >= 0) {
41125 +
41126 +    switch (ret) {
41127 +    case NETWORK_STATUS_WAIT_FOR_EVENT:
41128 +    case NETWORK_STATUS_SUCCESS:
41129                 chunkqueue_remove_finished_chunks(cq);
41130 -               ret = chunkqueue_is_empty(cq) ? 0 : 1;
41131 +
41132 +        break;
41133 +    default:
41134 +        break;
41135         }
41136 -       
41137 +
41138  #ifdef TCP_CORK
41139         if (corked) {
41140                 corked = 0;
41141 @@ -639,13 +705,13 @@
41142         con->bytes_written_cur_second += written;
41143  
41144         *(con->conf.global_bytes_per_second_cnt_ptr) += written;
41145 -       
41146 +
41147         if (con->conf.kbytes_per_second &&
41148             (con->bytes_written_cur_second > con->conf.kbytes_per_second * 1024)) {
41149                 /* we reached the traffic limit */
41150  
41151                 con->traffic_limit_reached = 1;
41152                 joblist_append(srv, con);
41153 -       }  
41154 +       }
41155         return ret;
41156  }
41157 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/network.h lighttpd-1.4.12/src/network.h
41158 --- lighttpd-1.4.11/src/network.h       2005-08-11 01:26:42.000000000 +0300
41159 +++ lighttpd-1.4.12/src/network.h       2006-07-11 21:23:39.000000000 +0300
41160 @@ -3,7 +3,8 @@
41161  
41162  #include "server.h"
41163  
41164 -int network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
41165 +network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
41166 +network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *c);
41167  
41168  int network_init(server *srv);
41169  int network_close(server *srv);
41170 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/network_backends.h lighttpd-1.4.12/src/network_backends.h
41171 --- lighttpd-1.4.11/src/network_backends.h      2005-10-24 15:13:51.000000000 +0300
41172 +++ lighttpd-1.4.12/src/network_backends.h      2006-07-11 21:23:40.000000000 +0300
41173 @@ -43,16 +43,52 @@
41174  # define USE_AIX_SENDFILE
41175  #endif
41176  
41177 +/**
41178 +* unix can use read/write or recv/send on sockets
41179 +* win32 only recv/send
41180 +*/
41181 +#ifdef _WIN32
41182 +# define USE_WIN32_SEND
41183 +/* wait for async-io support
41184 +# define USE_WIN32_TRANSMITFILE
41185 +*/
41186 +#else
41187 +# define USE_WRITE
41188 +#endif
41189 +
41190  #include "base.h"
41191 +#include "network.h"
41192 +
41193 +#define NETWORK_BACKEND_WRITE_CHUNK(x) \
41194 +    network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq, chunk *c)
41195 +
41196 +#define NETWORK_BACKEND_WRITE(x) \
41197 +    network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq)
41198 +#define NETWORK_BACKEND_READ(x) \
41199 +    network_status_t network_read_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq)
41200  
41201 +NETWORK_BACKEND_WRITE_CHUNK(writev_mem);
41202 +
41203 +NETWORK_BACKEND_WRITE(write);
41204 +NETWORK_BACKEND_WRITE(writev);
41205 +NETWORK_BACKEND_WRITE(linuxsendfile);
41206 +NETWORK_BACKEND_WRITE(freebsdsendfile);
41207 +NETWORK_BACKEND_WRITE(solarissendfilev);
41208 +
41209 +NETWORK_BACKEND_WRITE(win32transmitfile);
41210 +NETWORK_BACKEND_WRITE(win32send);
41211 +
41212 +NETWORK_BACKEND_READ(read);
41213 +NETWORK_BACKEND_READ(win32recv);
41214  
41215 -int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq);
41216 -int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq);
41217 -int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
41218 -int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
41219 -int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq);
41220  #ifdef USE_OPENSSL
41221 -int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq);
41222 +#define NETWORK_BACKEND_WRITE_SSL(x) \
41223 +    network_status_t network_write_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq)
41224 +#define NETWORK_BACKEND_READ_SSL(x) \
41225 +    network_status_t network_read_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq)
41226 +
41227 +NETWORK_BACKEND_WRITE_SSL(openssl);
41228 +NETWORK_BACKEND_READ_SSL(openssl);
41229  #endif
41230  
41231  #endif
41232 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/network_freebsd_sendfile.c lighttpd-1.4.12/src/network_freebsd_sendfile.c
41233 --- lighttpd-1.4.11/src/network_freebsd_sendfile.c      2005-10-22 12:28:18.000000000 +0300
41234 +++ lighttpd-1.4.12/src/network_freebsd_sendfile.c      2006-07-11 21:23:40.000000000 +0300
41235 @@ -26,142 +26,61 @@
41236  
41237  #ifndef UIO_MAXIOV
41238  # ifdef __FreeBSD__
41239 -/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */ 
41240 +/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */
41241  #  define UIO_MAXIOV 1024
41242  # endif
41243  #endif
41244  
41245 -int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
41246 +NETWORK_BACKEND_WRITE(freebsdsendfile) {
41247         chunk *c;
41248         size_t chunks_written = 0;
41249 -       
41250 +
41251         for(c = cq->first; c; c = c->next, chunks_written++) {
41252                 int chunk_finished = 0;
41253 -               
41254 +               network_status_t ret;
41255 +
41256                 switch(c->type) {
41257 -               case MEM_CHUNK: {
41258 -                       char * offset;
41259 -                       size_t toSend;
41260 -                       ssize_t r;
41261 -                       
41262 -                       size_t num_chunks, i;
41263 -                       struct iovec chunks[UIO_MAXIOV];
41264 -                       chunk *tc;
41265 -                       size_t num_bytes = 0;
41266 -                       
41267 -                       /* we can't send more then SSIZE_MAX bytes in one chunk */
41268 -                       
41269 -                       /* build writev list 
41270 -                        * 
41271 -                        * 1. limit: num_chunks < UIO_MAXIOV
41272 -                        * 2. limit: num_bytes < SSIZE_MAX
41273 -                        */
41274 -                       for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
41275 -                       
41276 -                       for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
41277 -                               if (tc->mem->used == 0) {
41278 -                                       chunks[i].iov_base = tc->mem->ptr;
41279 -                                       chunks[i].iov_len  = 0;
41280 -                               } else {
41281 -                                       offset = tc->mem->ptr + tc->offset;
41282 -                                       toSend = tc->mem->used - 1 - tc->offset;
41283 -                                       
41284 -                                       chunks[i].iov_base = offset;
41285 -                                       
41286 -                                       /* protect the return value of writev() */
41287 -                                       if (toSend > SSIZE_MAX ||
41288 -                                           num_bytes + toSend > SSIZE_MAX) {
41289 -                                               chunks[i].iov_len = SSIZE_MAX - num_bytes;
41290 -                                               
41291 -                                               num_chunks = i + 1;
41292 -                                               break;
41293 -                                       } else {
41294 -                                               chunks[i].iov_len = toSend;
41295 -                                       }
41296 -                                
41297 -                                       num_bytes += toSend;
41298 -                               }
41299 -                       }
41300 -                       
41301 -                       if ((r = writev(fd, chunks, num_chunks)) < 0) {
41302 -                               switch (errno) {
41303 -                               case EAGAIN:
41304 -                               case EINTR:
41305 -                                       r = 0;
41306 -                                       break;
41307 -                               case EPIPE:
41308 -                               case ECONNRESET:
41309 -                                       return -2;
41310 -                               default:
41311 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
41312 -                                                       "writev failed:", strerror(errno), fd);
41313 -                                       
41314 -                                       return -1;
41315 -                               }
41316 +               case MEM_CHUNK:
41317 +                       ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
41318  
41319 -                               r = 0;
41320 -                       }
41321 -                       
41322 -                       /* check which chunks have been written */
41323 -                       cq->bytes_out += r;
41324 -                       
41325 -                       for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41326 -                               if (r >= (ssize_t)chunks[i].iov_len) {
41327 -                                       /* written */
41328 -                                       r -= chunks[i].iov_len;
41329 -                                       tc->offset += chunks[i].iov_len;
41330 -                                       
41331 -                                       if (chunk_finished) {
41332 -                                               /* skip the chunks from further touches */
41333 -                                               chunks_written++;
41334 -                                               c = c->next;
41335 -                                       } else {
41336 -                                               /* chunks_written + c = c->next is done in the for()*/
41337 -                                               chunk_finished++;
41338 -                                       }
41339 -                               } else {
41340 -                                       /* partially written */
41341 -                                       
41342 -                                       tc->offset += r;
41343 -                                       chunk_finished = 0;
41344 -                                       
41345 -                                       break;
41346 -                               }
41347 +                       if (ret != NETWORK_STATUS_SUCCESS) {
41348 +                               return ret;
41349                         }
41350 -                       
41351 +
41352 +                       chunk_finished = 1;
41353 +
41354                         break;
41355 -               }
41356                 case FILE_CHUNK: {
41357                         off_t offset, r;
41358                         size_t toSend;
41359                         stat_cache_entry *sce = NULL;
41360                         int ifd;
41361 -                       
41362 +
41363                         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41364                                 log_error_write(srv, __FILE__, __LINE__, "sb",
41365                                                 strerror(errno), c->file.name);
41366 -                               return -1;
41367 +                               return NETWORK_STATUS_FATAL_ERROR;
41368                         }
41369 -                       
41370 +
41371                         offset = c->file.start + c->offset;
41372                         /* limit the toSend to 2^31-1 bytes in a chunk */
41373 -                       toSend = c->file.length - c->offset > ((1 << 30) - 1) ? 
41374 +                       toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
41375                                 ((1 << 30) - 1) : c->file.length - c->offset;
41376 -                               
41377 +
41378                         if (offset > sce->st.st_size) {
41379                                 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
41380 -                               
41381 -                               return -1;
41382 +
41383 +                               return NETWORK_STATUS_FATAL_ERROR;
41384                         }
41385 -                       
41386 +
41387                         if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
41388                                 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
41389 -                               
41390 -                               return -1;
41391 +
41392 +                               return NETWORK_STATUS_FATAL_ERROR;
41393                         }
41394 -                       
41395 +
41396                         r = 0;
41397 -                       
41398 +
41399                         /* FreeBSD sendfile() */
41400                         if (-1 == sendfile(ifd, fd, offset, toSend, NULL, &r, 0)) {
41401                                 switch(errno) {
41402 @@ -169,39 +88,39 @@
41403                                         break;
41404                                 case ENOTCONN:
41405                                         close(ifd);
41406 -                                       return -2;
41407 +                                       return NETWORK_STATUS_CONNECTION_CLOSE;
41408                                 default:
41409                                         log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
41410                                         close(ifd);
41411 -                                       return -1;
41412 +                                       return NETWORK_STATUS_FATAL_ERROR;
41413                                 }
41414                         }
41415                         close(ifd);
41416 -                       
41417 +
41418                         c->offset += r;
41419                         cq->bytes_out += r;
41420 -                       
41421 +
41422                         if (c->offset == c->file.length) {
41423                                 chunk_finished = 1;
41424                         }
41425 -                       
41426 +
41427                         break;
41428                 }
41429                 default:
41430 -                       
41431 +
41432                         log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
41433 -                       
41434 +
41435                         return -1;
41436                 }
41437 -               
41438 +
41439                 if (!chunk_finished) {
41440                         /* not finished yet */
41441 -                       
41442 +
41443                         break;
41444                 }
41445         }
41446  
41447 -       return chunks_written;
41448 +       return NETWORK_STATUS_SUCCESS;
41449  }
41450  
41451  #endif
41452 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/network_linux_sendfile.c lighttpd-1.4.12/src/network_linux_sendfile.c
41453 --- lighttpd-1.4.11/src/network_linux_sendfile.c        2006-02-15 20:02:36.000000000 +0200
41454 +++ lighttpd-1.4.12/src/network_linux_sendfile.c        2006-07-11 21:23:40.000000000 +0300
41455 @@ -26,122 +26,54 @@
41456  /* on linux 2.4.29 + debian/ubuntu we have crashes if this is enabled */
41457  #undef HAVE_POSIX_FADVISE
41458  
41459 -int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
41460 -       chunk *c;
41461 +NETWORK_BACKEND_WRITE(linuxsendfile) {
41462 +       chunk *c, *tc;
41463         size_t chunks_written = 0;
41464 -       
41465 +
41466         for(c = cq->first; c; c = c->next, chunks_written++) {
41467                 int chunk_finished = 0;
41468 -               
41469 +               network_status_t ret;
41470 +
41471                 switch(c->type) {
41472 -               case MEM_CHUNK: {
41473 -                       char * offset;
41474 -                       size_t toSend;
41475 -                       ssize_t r;
41476 -                       
41477 -                       size_t num_chunks, i;
41478 -                       struct iovec chunks[UIO_MAXIOV];
41479 -                       chunk *tc;
41480 -                       size_t num_bytes = 0;
41481 -                       
41482 -                       /* we can't send more then SSIZE_MAX bytes in one chunk */
41483 -                       
41484 -                       /* build writev list 
41485 -                        * 
41486 -                        * 1. limit: num_chunks < UIO_MAXIOV
41487 -                        * 2. limit: num_bytes < SSIZE_MAX
41488 -                        */
41489 -                       for (num_chunks = 0, tc = c; 
41490 -                            tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; 
41491 -                            tc = tc->next, num_chunks++);
41492 -                       
41493 -                       for (tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
41494 -                               if (tc->mem->used == 0) {
41495 -                                       chunks[i].iov_base = tc->mem->ptr;
41496 -                                       chunks[i].iov_len  = 0;
41497 -                               } else {
41498 -                                       offset = tc->mem->ptr + tc->offset;
41499 -                                       toSend = tc->mem->used - 1 - tc->offset;
41500 -                               
41501 -                                       chunks[i].iov_base = offset;
41502 -                                       
41503 -                                       /* protect the return value of writev() */
41504 -                                       if (toSend > SSIZE_MAX ||
41505 -                                           num_bytes + toSend > SSIZE_MAX) {
41506 -                                               chunks[i].iov_len = SSIZE_MAX - num_bytes;
41507 -                                               
41508 -                                               num_chunks = i + 1;
41509 -                                               break;
41510 -                                       } else {
41511 -                                               chunks[i].iov_len = toSend;
41512 -                                       }
41513 -                                
41514 -                                       num_bytes += toSend;
41515 -                               }
41516 -                       }
41517 -                       
41518 -                       if ((r = writev(fd, chunks, num_chunks)) < 0) {
41519 -                               switch (errno) {
41520 -                               case EAGAIN:
41521 -                               case EINTR:
41522 -                                       r = 0;
41523 -                                       break;
41524 -                               case EPIPE:
41525 -                               case ECONNRESET:
41526 -                                       return -2;
41527 -                               default:
41528 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
41529 -                                                       "writev failed:", strerror(errno), fd);
41530 -                               
41531 -                                       return -1;
41532 -                               }
41533 -                       }
41534 -                       
41535 -                       /* check which chunks have been written */
41536 -                       cq->bytes_out += r;
41537 +               case MEM_CHUNK:
41538 +                       ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
41539  
41540 -                       for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
41541 -                               if (r >= (ssize_t)chunks[i].iov_len) {
41542 -                                       /* written */
41543 -                                       r -= chunks[i].iov_len;
41544 -                                       tc->offset += chunks[i].iov_len;
41545 -                                       
41546 +                       /* check which chunks are finished now */
41547 +                       for (tc = c; tc; tc = tc->next) {
41548 +                               /* finished the chunk */
41549 +                               if (tc->offset == tc->mem->used - 1) {
41550 +                                       /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
41551                                         if (chunk_finished) {
41552 -                                               /* skip the chunks from further touches */
41553 -                                               chunks_written++;
41554                                                 c = c->next;
41555                                         } else {
41556 -                                               /* chunks_written + c = c->next is done in the for()*/
41557 -                                               chunk_finished++;
41558 +                                               chunk_finished = 1;
41559                                         }
41560                                 } else {
41561 -                                       /* partially written */
41562 -                                       
41563 -                                       tc->offset += r;
41564 -                                       chunk_finished = 0;
41565 -                                       
41566                                         break;
41567                                 }
41568                         }
41569 -                       
41570 +
41571 +                       if (ret != NETWORK_STATUS_SUCCESS) {
41572 +                               return ret;
41573 +                       }
41574 +
41575                         break;
41576 -               }
41577                 case FILE_CHUNK: {
41578                         ssize_t r;
41579                         off_t offset;
41580                         size_t toSend;
41581                         stat_cache_entry *sce = NULL;
41582 -                       
41583 +
41584                         offset = c->file.start + c->offset;
41585                         /* limit the toSend to 2^31-1 bytes in a chunk */
41586 -                       toSend = c->file.length - c->offset > ((1 << 30) - 1) ? 
41587 +                       toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
41588                                 ((1 << 30) - 1) : c->file.length - c->offset;
41589 -                               
41590 -                       /* open file if not already opened */   
41591 +
41592 +                       /* open file if not already opened */
41593                         if (-1 == c->file.fd) {
41594                                 if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
41595                                         log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
41596 -                               
41597 +
41598                                         return -1;
41599                                 }
41600  #ifdef FD_CLOEXEC
41601 @@ -151,7 +83,7 @@
41602                                 /* tell the kernel that we want to stream the file */
41603                                 if (-1 == posix_fadvise(c->file.fd, 0, 0, POSIX_FADV_SEQUENTIAL)) {
41604                                         if (ENOSYS != errno) {
41605 -                                               log_error_write(srv, __FILE__, __LINE__, "ssd", 
41606 +                                               log_error_write(srv, __FILE__, __LINE__, "ssd",
41607                                                         "posix_fadvise failed:", strerror(errno), c->file.fd);
41608                                         }
41609                                 }
41610 @@ -168,7 +100,7 @@
41611                                 case ECONNRESET:
41612                                         return -2;
41613                                 default:
41614 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
41615 +                                       log_error_write(srv, __FILE__, __LINE__, "ssd",
41616                                                         "sendfile failed:", strerror(errno), fd);
41617                                         return -1;
41618                                 }
41619 @@ -179,7 +111,7 @@
41620                                  *
41621                                  * - the file shrinked -> error
41622                                  * - the remote side closed inbetween -> remote-close */
41623 -       
41624 +
41625                                 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41626                                         /* file is gone ? */
41627                                         return -1;
41628 @@ -196,22 +128,22 @@
41629  #ifdef HAVE_POSIX_FADVISE
41630  #if 0
41631  #define K * 1024
41632 -#define M * 1024 K     
41633 +#define M * 1024 K
41634  #define READ_AHEAD 4 M
41635                         /* check if we need a new chunk */
41636                         if ((c->offset & ~(READ_AHEAD - 1)) != ((c->offset + r) & ~(READ_AHEAD - 1))) {
41637                                 /* tell the kernel that we want to stream the file */
41638                                 if (-1 == posix_fadvise(c->file.fd, (c->offset + r) & ~(READ_AHEAD - 1), READ_AHEAD, POSIX_FADV_NOREUSE)) {
41639 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
41640 +                                       log_error_write(srv, __FILE__, __LINE__, "ssd",
41641                                                 "posix_fadvise failed:", strerror(errno), c->file.fd);
41642                                 }
41643                         }
41644  #endif
41645  #endif
41646 -                       
41647 +
41648                         c->offset += r;
41649                         cq->bytes_out += r;
41650 -                       
41651 +
41652                         if (c->offset == c->file.length) {
41653                                 chunk_finished = 1;
41654  
41655 @@ -222,19 +154,19 @@
41656                                         c->file.fd = -1;
41657                                 }
41658                         }
41659 -                       
41660 +
41661                         break;
41662                 }
41663                 default:
41664 -                       
41665 +
41666                         log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
41667 -                       
41668 +
41669                         return -1;
41670                 }
41671 -               
41672 +
41673                 if (!chunk_finished) {
41674                         /* not finished yet */
41675 -                       
41676 +
41677                         break;
41678                 }
41679         }
41680 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/network_openssl.c lighttpd-1.4.12/src/network_openssl.c
41681 --- lighttpd-1.4.11/src/network_openssl.c       2005-11-17 14:53:29.000000000 +0200
41682 +++ lighttpd-1.4.12/src/network_openssl.c       2006-07-11 21:23:40.000000000 +0300
41683 @@ -23,17 +23,87 @@
41684  #include "log.h"
41685  #include "stat_cache.h"
41686  
41687 -# include <openssl/ssl.h> 
41688 -# include <openssl/err.h> 
41689 +# include <openssl/ssl.h>
41690 +# include <openssl/err.h>
41691  
41692 -int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq) {
41693 +NETWORK_BACKEND_READ_SSL(openssl) {
41694 +       buffer *b;
41695 +       off_t len;
41696 +
41697 +       b = chunkqueue_get_append_buffer(cq);
41698 +       buffer_prepare_copy(b, 8192);
41699 +       len = SSL_read(ssl, b->ptr, b->size - 1);
41700 +
41701 +       log_error_write(srv, __FILE__, __LINE__, "so", "SSL:", len);
41702 +
41703 +       if (len < 0) {
41704 +               int r, ssl_err;
41705 +
41706 +               switch ((r = SSL_get_error(con->ssl, len))) {
41707 +               case SSL_ERROR_WANT_READ:
41708 +                       return NETWORK_STATUS_WAIT_FOR_EVENT;
41709 +               case SSL_ERROR_SYSCALL:
41710 +                       /**
41711 +                        * man SSL_get_error()
41712 +                        *
41713 +                        * SSL_ERROR_SYSCALL
41714 +                        *   Some I/O error occurred.  The OpenSSL error queue may contain more
41715 +                        *   information on the error.  If the error queue is empty (i.e.
41716 +                        *   ERR_get_error() returns 0), ret can be used to find out more about
41717 +                        *   the error: If ret == 0, an EOF was observed that violates the
41718 +                        *   protocol.  If ret == -1, the underlying BIO reported an I/O error
41719 +                        *   (for socket I/O on Unix systems, consult errno for details).
41720 +                        *
41721 +                        */
41722 +                       while((ssl_err = ERR_get_error())) {
41723 +                               /* get all errors from the error-queue */
41724 +                               log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
41725 +                                               r, ERR_error_string(ssl_err, NULL));
41726 +                       }
41727 +
41728 +                       switch(errno) {
41729 +                       default:
41730 +                               log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41731 +                                               len, r, errno,
41732 +                                               strerror(errno));
41733 +                               break;
41734 +                       }
41735 +
41736 +                       break;
41737 +               case SSL_ERROR_ZERO_RETURN:
41738 +                       /* clean shutdown on the remote side */
41739 +
41740 +                       if (r == 0) {
41741 +                               /* FIXME: later */
41742 +                       }
41743 +
41744 +                       /* fall thourgh */
41745 +               default:
41746 +                       while((ssl_err = ERR_get_error())) {
41747 +                               /* get all errors from the error-queue */
41748 +                               log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
41749 +                                               r, ERR_error_string(ssl_err, NULL));
41750 +                       }
41751 +                       break;
41752 +               }
41753 +       }
41754 +
41755 +       assert(len > 0);
41756 +       b->used += len;
41757 +       b->ptr[b->used - 1] = '\0';
41758 +
41759 +       return NETWORK_STATUS_SUCCESS;
41760 +}
41761 +
41762 +
41763 +NETWORK_BACKEND_WRITE_SSL(openssl) {
41764         int ssl_r;
41765         chunk *c;
41766         size_t chunks_written = 0;
41767  
41768         /* this is a 64k sendbuffer
41769          *
41770 -        * it has to stay at the same location all the time to satisfy the needs 
41771 +        * it has to stay at the same location all the time to satisfy the needs
41772          * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE
41773          *
41774          * the buffer is allocated once, is NOT realloced and is NOT freed at shutdown
41775 @@ -43,14 +113,14 @@
41776          * In reality we would like to use mmap() but we don't have a guarantee that
41777          * we get the same mmap() address for each call. On openbsd the mmap() address
41778          * even randomized.
41779 -        *   That means either we keep the mmap() open or we do a read() into a 
41780 -        * constant buffer 
41781 +        *   That means either we keep the mmap() open or we do a read() into a
41782 +        * constant buffer
41783          * */
41784  #define LOCAL_SEND_BUFSIZE (64 * 1024)
41785         static char *local_send_buffer = NULL;
41786  
41787         /* the remote side closed the connection before without shutdown request
41788 -        * - IE 
41789 +        * - IE
41790          * - wget
41791          * if keep-alive is disabled */
41792  
41793 @@ -60,32 +130,34 @@
41794  
41795         for(c = cq->first; c; c = c->next) {
41796                 int chunk_finished = 0;
41797 -               
41798 +
41799                 switch(c->type) {
41800                 case MEM_CHUNK: {
41801                         char * offset;
41802                         size_t toSend;
41803 -                       ssize_t r;
41804 -                       
41805 +                       ssize_t r = 0;
41806 +
41807                         if (c->mem->used == 0) {
41808                                 chunk_finished = 1;
41809                                 break;
41810                         }
41811 -                       
41812 +
41813                         offset = c->mem->ptr + c->offset;
41814                         toSend = c->mem->used - 1 - c->offset;
41815 -                       
41816 +
41817                         /**
41818                          * SSL_write man-page
41819 -                        * 
41820 +                        *
41821                          * WARNING
41822                          *        When an SSL_write() operation has to be repeated because of
41823                          *        SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be
41824                          *        repeated with the same arguments.
41825 -                        * 
41826 +                        *
41827 +                        * SSL_write(..., 0) return 0 which is handle as an error (Success)
41828 +                        * checking toSend and not calling SSL_write() is simpler
41829                          */
41830 -                       
41831 -                       if ((r = SSL_write(ssl, offset, toSend)) <= 0) {
41832 +
41833 +                       if (toSend != 0 && (r = SSL_write(ssl, offset, toSend)) <= 0) {
41834                                 unsigned long err;
41835  
41836                                 switch ((ssl_r = SSL_get_error(ssl, r))) {
41837 @@ -95,7 +167,7 @@
41838                                         /* perhaps we have error waiting in our error-queue */
41839                                         if (0 != (err = ERR_get_error())) {
41840                                                 do {
41841 -                                                       log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", 
41842 +                                                       log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41843                                                                         ssl_r, r,
41844                                                                         ERR_error_string(err, NULL));
41845                                                 } while((err = ERR_get_error()));
41846 @@ -105,43 +177,43 @@
41847                                                 case EPIPE:
41848                                                         return -2;
41849                                                 default:
41850 -                                                       log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:", 
41851 +                                                       log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41852                                                                         ssl_r, r, errno,
41853                                                                         strerror(errno));
41854                                                         break;
41855                                                 }
41856                                         } else {
41857                                                 /* neither error-queue nor errno ? */
41858 -                                               log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):", 
41859 +                                               log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
41860                                                                 ssl_r, r, errno,
41861                                                                 strerror(errno));
41862                                         }
41863 -                                       
41864 +
41865                                         return  -1;
41866                                 case SSL_ERROR_ZERO_RETURN:
41867                                         /* clean shutdown on the remote side */
41868 -                                       
41869 +
41870                                         if (r == 0) return -2;
41871 -                                       
41872 +
41873                                         /* fall through */
41874                                 default:
41875                                         while((err = ERR_get_error())) {
41876 -                                               log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", 
41877 +                                               log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41878                                                                 ssl_r, r,
41879                                                                 ERR_error_string(err, NULL));
41880                                         }
41881 -                                       
41882 +
41883                                         return  -1;
41884                                 }
41885                         } else {
41886                                 c->offset += r;
41887                                 cq->bytes_out += r;
41888                         }
41889 -                       
41890 +
41891                         if (c->offset == (off_t)c->mem->used - 1) {
41892                                 chunk_finished = 1;
41893                         }
41894 -                       
41895 +
41896                         break;
41897                 }
41898                 case FILE_CHUNK: {
41899 @@ -150,7 +222,7 @@
41900                         stat_cache_entry *sce = NULL;
41901                         int ifd;
41902                         int write_wait = 0;
41903 -                       
41904 +
41905                         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
41906                                 log_error_write(srv, __FILE__, __LINE__, "sb",
41907                                                 strerror(errno), c->file.name);
41908 @@ -164,13 +236,13 @@
41909  
41910                         do {
41911                                 off_t offset = c->file.start + c->offset;
41912 -                               off_t toSend = c->file.length - c->offset; 
41913 +                               off_t toSend = c->file.length - c->offset;
41914  
41915                                 if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE;
41916 -                       
41917 +
41918                                 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
41919                                         log_error_write(srv, __FILE__, __LINE__, "ss", "open failed:", strerror(errno));
41920 -                               
41921 +
41922                                         return -1;
41923                                 }
41924  
41925 @@ -183,9 +255,9 @@
41926                                 }
41927  
41928                                 s = local_send_buffer;
41929 -                       
41930 +
41931                                 close(ifd);
41932 -                       
41933 +
41934                                 if ((r = SSL_write(ssl, s, toSend)) <= 0) {
41935                                         unsigned long err;
41936  
41937 @@ -197,7 +269,7 @@
41938                                                 /* perhaps we have error waiting in our error-queue */
41939                                                 if (0 != (err = ERR_get_error())) {
41940                                                         do {
41941 -                                                               log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", 
41942 +                                                               log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41943                                                                                 ssl_r, r,
41944                                                                                 ERR_error_string(err, NULL));
41945                                                         } while((err = ERR_get_error()));
41946 @@ -207,58 +279,58 @@
41947                                                         case EPIPE:
41948                                                                 return -2;
41949                                                         default:
41950 -                                                               log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:", 
41951 +                                                               log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
41952                                                                                 ssl_r, r, errno,
41953                                                                                 strerror(errno));
41954                                                                 break;
41955                                                         }
41956                                                 } else {
41957                                                         /* neither error-queue nor errno ? */
41958 -                                                       log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):", 
41959 +                                                       log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
41960                                                                         ssl_r, r, errno,
41961                                                                         strerror(errno));
41962                                                 }
41963 -                                       
41964 +
41965                                                 return  -1;
41966                                         case SSL_ERROR_ZERO_RETURN:
41967                                                 /* clean shutdown on the remote side */
41968 -                                       
41969 +
41970                                                 if (r == 0)  return -2;
41971 -                                       
41972 +
41973                                                 /* fall thourgh */
41974                                         default:
41975                                                 while((err = ERR_get_error())) {
41976 -                                                       log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", 
41977 +                                                       log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
41978                                                                         ssl_r, r,
41979                                                                         ERR_error_string(err, NULL));
41980                                                 }
41981 -                                       
41982 +
41983                                                 return -1;
41984                                         }
41985                                 } else {
41986                                         c->offset += r;
41987                                         cq->bytes_out += r;
41988                                 }
41989 -                       
41990 +
41991                                 if (c->offset == c->file.length) {
41992                                         chunk_finished = 1;
41993                                 }
41994                         } while(!chunk_finished && !write_wait);
41995 -                       
41996 +
41997                         break;
41998                 }
41999                 default:
42000                         log_error_write(srv, __FILE__, __LINE__, "s", "type not known");
42001 -                       
42002 +
42003                         return -1;
42004                 }
42005 -                       
42006 +
42007                 if (!chunk_finished) {
42008                         /* not finished yet */
42009 -                       
42010 +
42011                         break;
42012                 }
42013 -                       
42014 +
42015                 chunks_written++;
42016         }
42017  
42018 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/network_solaris_sendfilev.c lighttpd-1.4.12/src/network_solaris_sendfilev.c
42019 --- lighttpd-1.4.11/src/network_solaris_sendfilev.c     2005-10-22 12:28:27.000000000 +0300
42020 +++ lighttpd-1.4.12/src/network_solaris_sendfilev.c     2006-07-11 21:23:40.000000000 +0300
42021 @@ -29,114 +29,34 @@
42022  #endif
42023  
42024  /**
42025 - * a very simple sendfilev() interface for solaris which can be optimised a lot more 
42026 + * a very simple sendfilev() interface for solaris which can be optimised a lot more
42027   * as solaris sendfilev() supports 'sending everythin in one syscall()'
42028 - * 
42029 - * If you want such an interface and need the performance, just give me an account on 
42030 - * a solaris box. 
42031 + *
42032 + * If you want such an interface and need the performance, just give me an account on
42033 + * a solaris box.
42034   *   - jan@kneschke.de
42035   */
42036  
42037  
42038 -int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq) {
42039 +NETWORK_BACKEND_WRITE(solarissendfilev) {
42040         chunk *c;
42041         size_t chunks_written = 0;
42042 -       
42043 +
42044         for(c = cq->first; c; c = c->next, chunks_written++) {
42045                 int chunk_finished = 0;
42046 -               
42047 +               network_status_t ret;
42048 +
42049                 switch(c->type) {
42050 -               case MEM_CHUNK: {
42051 -                       char * offset;
42052 -                       size_t toSend;
42053 -                       ssize_t r;
42054 -                       
42055 -                       size_t num_chunks, i;
42056 -                       struct iovec chunks[UIO_MAXIOV];
42057 -                       chunk *tc;
42058 -                       
42059 -                       size_t num_bytes = 0;
42060 -                       
42061 -                       /* we can't send more then SSIZE_MAX bytes in one chunk */
42062 -                       
42063 -                       /* build writev list 
42064 -                        * 
42065 -                        * 1. limit: num_chunks < UIO_MAXIOV
42066 -                        * 2. limit: num_bytes < SSIZE_MAX
42067 -                        */
42068 -                       for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
42069 -                       
42070 -                       for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
42071 -                               if (tc->mem->used == 0) {
42072 -                                       chunks[i].iov_base = tc->mem->ptr;
42073 -                                       chunks[i].iov_len  = 0;
42074 -                               } else {
42075 -                                       offset = tc->mem->ptr + tc->offset;
42076 -                                       toSend = tc->mem->used - 1 - tc->offset;
42077 -                               
42078 -                                       chunks[i].iov_base = offset;
42079 -                                       
42080 -                                       /* protect the return value of writev() */
42081 -                                       if (toSend > SSIZE_MAX ||
42082 -                                           num_bytes + toSend > SSIZE_MAX) {
42083 -                                               chunks[i].iov_len = SSIZE_MAX - num_bytes;
42084 -                                               
42085 -                                               num_chunks = i + 1;
42086 -                                               break;
42087 -                                       } else {
42088 -                                               chunks[i].iov_len = toSend;
42089 -                                       }
42090 -                                       
42091 -                                       num_bytes += toSend;
42092 -                               }
42093 -                       }
42094 -                       
42095 -                       if ((r = writev(fd, chunks, num_chunks)) < 0) {
42096 -                               switch (errno) {
42097 -                               case EAGAIN:
42098 -                               case EINTR:
42099 -                                       r = 0;
42100 -                                       break;
42101 -                               case EPIPE:
42102 -                               case ECONNRESET:
42103 -                                       return -2;
42104 -                               default:
42105 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
42106 -                                                       "writev failed:", strerror(errno), fd);
42107 -                               
42108 -                                       return -1;
42109 -                               }
42110 -                       }
42111 -                       
42112 -                       /* check which chunks have been written */
42113 -                       cq->bytes_out += r;
42114 -                       
42115 -                       for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
42116 -                               if (r >= (ssize_t)chunks[i].iov_len) {
42117 -                                       /* written */
42118 -                                       r -= chunks[i].iov_len;
42119 -                                       tc->offset += chunks[i].iov_len;
42120 -                                       
42121 -                                       if (chunk_finished) {
42122 -                                               /* skip the chunks from further touches */
42123 -                                               chunks_written++;
42124 -                                               c = c->next;
42125 -                                       } else {
42126 -                                               /* chunks_written + c = c->next is done in the for()*/
42127 -                                               chunk_finished++;
42128 -                                       }
42129 -                               } else {
42130 -                                       /* partially written */
42131 -                                       
42132 -                                       tc->offset += r;
42133 -                                       chunk_finished = 0;
42134 -                                       
42135 -                                       break;
42136 -                               }
42137 +               case MEM_CHUNK:
42138 +                       ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
42139 +
42140 +                       if (ret != NETWORK_STATUS_SUCCESS) {
42141 +                               return ret;
42142                         }
42143 -                       
42144 +
42145 +                       chunk_finished = 1;
42146 +
42147                         break;
42148 -               }
42149                 case FILE_CHUNK: {
42150                         ssize_t r;
42151                         off_t offset;
42152 @@ -144,25 +64,25 @@
42153                         sendfilevec_t fvec;
42154                         stat_cache_entry *sce = NULL;
42155                         int ifd;
42156 -                       
42157 +
42158                         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
42159                                 log_error_write(srv, __FILE__, __LINE__, "sb",
42160                                                 strerror(errno), c->file.name);
42161                                 return -1;
42162                         }
42163 -                                       
42164 +
42165                         offset = c->file.start + c->offset;
42166                         toSend = c->file.length - c->offset;
42167 -                       
42168 +
42169                         if (offset > sce->st.st_size) {
42170                                 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
42171 -                               
42172 +
42173                                 return -1;
42174                         }
42175  
42176                         if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
42177                                 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
42178 -                               
42179 +
42180                                 return -1;
42181                         }
42182  
42183 @@ -170,44 +90,43 @@
42184                         fvec.sfv_flag = 0;
42185                         fvec.sfv_off = offset;
42186                         fvec.sfv_len = toSend;
42187 -                       
42188 +
42189                         /* Solaris sendfilev() */
42190                         if (-1 == (r = sendfilev(fd, &fvec, 1, &written))) {
42191                                 if (errno != EAGAIN) {
42192                                         log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
42193 -                                       
42194 +
42195                                         close(ifd);
42196 -                                       return -1;
42197 +                                       return NETWORK_STATUS_FATAL_ERROR;
42198                                 }
42199 -                               
42200 +
42201                                 r = 0;
42202                         }
42203 -                       
42204 +
42205                         close(ifd);
42206                         c->offset += written;
42207                         cq->bytes_out += written;
42208 -                       
42209 +
42210                         if (c->offset == c->file.length) {
42211                                 chunk_finished = 1;
42212                         }
42213 -                       
42214 +
42215                         break;
42216                 }
42217                 default:
42218 -                       
42219                         log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
42220 -                       
42221 -                       return -1;
42222 +
42223 +                       return NETWORK_STATUS_FATAL_ERROR;
42224                 }
42225 -               
42226 +
42227                 if (!chunk_finished) {
42228                         /* not finished yet */
42229 -                       
42230 +
42231                         break;
42232                 }
42233         }
42234  
42235 -       return chunks_written;
42236 +       return NETWORK_STATUS_SUCCESS;
42237  }
42238  
42239  #endif
42240 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/network_write.c lighttpd-1.4.12/src/network_write.c
42241 --- lighttpd-1.4.11/src/network_write.c 2005-10-22 12:27:56.000000000 +0300
42242 +++ lighttpd-1.4.12/src/network_write.c 2006-07-11 21:23:39.000000000 +0300
42243 @@ -1,11 +1,11 @@
42244  #include <sys/types.h>
42245  #include <sys/stat.h>
42246 -#include <sys/time.h>
42247 +
42248  #include <errno.h>
42249  #include <fcntl.h>
42250 -#include <unistd.h>
42251  #include <string.h>
42252  #include <stdlib.h>
42253 +#include <assert.h>
42254  
42255  #include "network.h"
42256  #include "fdevent.h"
42257 @@ -13,9 +13,12 @@
42258  #include "stat_cache.h"
42259  
42260  #include "sys-socket.h"
42261 +#include "sys-files.h"
42262  
42263  #include "network_backends.h"
42264  
42265 +#ifdef USE_WRITE
42266 +
42267  #ifdef HAVE_SYS_FILIO_H
42268  # include <sys/filio.h>
42269  #endif
42270 @@ -24,47 +27,86 @@
42271  #include <sys/resource.h>
42272  #endif
42273  
42274 -int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq) {
42275 +/**
42276 +* fill the chunkqueue will all the data that we can get
42277 +*
42278 +* this might be optimized into a readv() which uses the chunks
42279 +* as vectors
42280 +*/
42281 +NETWORK_BACKEND_READ(read) {
42282 +    int toread;
42283 +    buffer *b;
42284 +    off_t r;
42285 +
42286 +       /* check how much we have to read */
42287 +       if (ioctl(fd, FIONREAD, &toread)) {
42288 +               log_error_write(srv, __FILE__, __LINE__, "sd",
42289 +                               "ioctl failed: ",
42290 +                               fd);
42291 +               return NETWORK_STATUS_FATAL_ERROR;
42292 +       }
42293 +
42294 +       if (toread == 0) return NETWORK_STATUS_WAIT_FOR_EVENT;
42295 +
42296 +    /*
42297 +    * our chunk queue is quiet large already
42298 +    *
42299 +    * let's buffer it to disk
42300 +    */
42301 +
42302 +    b = chunkqueue_get_append_buffer(cq);
42303 +
42304 +    buffer_prepare_copy(b, toread);
42305 +
42306 +    if (-1 == (r = read(fd, b->ptr, toread))) {
42307 +               log_error_write(srv, __FILE__, __LINE__, "sds",
42308 +                               "unexpected end-of-file (perhaps the proxy process died):",
42309 +                               fd, strerror(errno));
42310 +               return NETWORK_STATUS_FATAL_ERROR;
42311 +       }
42312 +
42313 +       /* this should be catched by the b > 0 above */
42314 +       assert(r);
42315 +       b->used += r + 1;
42316 +       b->ptr[b->used - 1] = '\0';
42317 +
42318 +    return NETWORK_STATUS_SUCCESS;
42319 +}
42320 +
42321 +NETWORK_BACKEND_WRITE(write) {
42322         chunk *c;
42323         size_t chunks_written = 0;
42324 -       
42325 +
42326         for(c = cq->first; c; c = c->next) {
42327                 int chunk_finished = 0;
42328 -               
42329 +
42330                 switch(c->type) {
42331                 case MEM_CHUNK: {
42332                         char * offset;
42333                         size_t toSend;
42334                         ssize_t r;
42335 -                       
42336 +
42337                         if (c->mem->used == 0) {
42338                                 chunk_finished = 1;
42339                                 break;
42340                         }
42341 -                       
42342 +
42343                         offset = c->mem->ptr + c->offset;
42344                         toSend = c->mem->used - 1 - c->offset;
42345 -#ifdef __WIN32 
42346 -                       if ((r = send(fd, offset, toSend, 0)) < 0) {
42347 -                               log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
42348 -                               
42349 -                               return -1;
42350 -                       }
42351 -#else
42352 +
42353                         if ((r = write(fd, offset, toSend)) < 0) {
42354                                 log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
42355 -                               
42356 -                               return -1;
42357 +
42358 +                               return NETWORK_STATUS_FATAL_ERROR;
42359                         }
42360 -#endif
42361 -                       
42362 +
42363                         c->offset += r;
42364                         cq->bytes_out += r;
42365 -                       
42366 +
42367                         if (c->offset == (off_t)c->mem->used - 1) {
42368                                 chunk_finished = 1;
42369                         }
42370 -                       
42371 +
42372                         break;
42373                 }
42374                 case FILE_CHUNK: {
42375 @@ -76,93 +118,89 @@
42376                         size_t toSend;
42377                         stat_cache_entry *sce = NULL;
42378                         int ifd;
42379 -                       
42380 +
42381                         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
42382                                 log_error_write(srv, __FILE__, __LINE__, "sb",
42383                                                 strerror(errno), c->file.name);
42384 -                               return -1;
42385 +                               return NETWORK_STATUS_FATAL_ERROR;
42386                         }
42387 -                       
42388 +
42389                         offset = c->file.start + c->offset;
42390                         toSend = c->file.length - c->offset;
42391 -                       
42392 +
42393                         if (offset > sce->st.st_size) {
42394                                 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
42395 -                               
42396 -                               return -1;
42397 +
42398 +                               return NETWORK_STATUS_FATAL_ERROR;
42399                         }
42400  
42401                         if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
42402                                 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
42403 -                               
42404 -                               return -1;
42405 +
42406 +                               return NETWORK_STATUS_FATAL_ERROR;
42407                         }
42408 -                       
42409 +
42410  #if defined USE_MMAP
42411                         if (MAP_FAILED == (p = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
42412                                 log_error_write(srv, __FILE__, __LINE__, "ss", "mmap failed: ", strerror(errno));
42413  
42414                                 close(ifd);
42415 -                               
42416 -                               return -1;
42417 +
42418 +                               return NETWORK_STATUS_FATAL_ERROR;
42419                         }
42420                         close(ifd);
42421  
42422                         if ((r = write(fd, p + offset, toSend)) <= 0) {
42423                                 log_error_write(srv, __FILE__, __LINE__, "ss", "write failed: ", strerror(errno));
42424                                 munmap(p, sce->st.st_size);
42425 -                               return -1;
42426 +                               return NETWORK_STATUS_FATAL_ERROR;
42427                         }
42428 -                       
42429 +
42430                         munmap(p, sce->st.st_size);
42431  #else
42432                         buffer_prepare_copy(srv->tmp_buf, toSend);
42433 -                       
42434 +
42435                         lseek(ifd, offset, SEEK_SET);
42436                         if (-1 == (toSend = read(ifd, srv->tmp_buf->ptr, toSend))) {
42437                                 log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno));
42438                                 close(ifd);
42439 -                               
42440 -                               return -1;
42441 +
42442 +                               return NETWORK_STATUS_FATAL_ERROR;
42443                         }
42444                         close(ifd);
42445  
42446                         if (-1 == (r = send(fd, srv->tmp_buf->ptr, toSend, 0))) {
42447                                 log_error_write(srv, __FILE__, __LINE__, "ss", "write: ", strerror(errno));
42448 -                               
42449 -                               return -1;
42450 +
42451 +                               return NETWORK_STATUS_FATAL_ERROR;
42452                         }
42453  #endif
42454                         c->offset += r;
42455                         cq->bytes_out += r;
42456 -                       
42457 +
42458                         if (c->offset == c->file.length) {
42459                                 chunk_finished = 1;
42460                         }
42461 -                       
42462 +
42463                         break;
42464                 }
42465                 default:
42466 -                       
42467 +
42468                         log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
42469 -                       
42470 -                       return -1;
42471 +
42472 +                       return NETWORK_STATUS_FATAL_ERROR;
42473                 }
42474 -               
42475 +
42476                 if (!chunk_finished) {
42477                         /* not finished yet */
42478 -                       
42479 +
42480                         break;
42481                 }
42482 -               
42483 +
42484                 chunks_written++;
42485         }
42486  
42487 -       return chunks_written;
42488 +       return NETWORK_STATUS_SUCCESS;
42489  }
42490  
42491 -#if 0
42492 -network_write_init(void) {
42493 -       p->write = network_write_write_chunkset;
42494 -}
42495  #endif
42496 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/network_writev.c lighttpd-1.4.12/src/network_writev.c
42497 --- lighttpd-1.4.11/src/network_writev.c        2006-02-15 01:02:36.000000000 +0200
42498 +++ lighttpd-1.4.12/src/network_writev.c        2006-07-11 21:23:40.000000000 +0300
42499 @@ -28,10 +28,10 @@
42500  
42501  #ifndef UIO_MAXIOV
42502  # if defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__)
42503 -/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */ 
42504 +/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */
42505  #  define UIO_MAXIOV 1024
42506  # elif defined(__sgi)
42507 -/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */ 
42508 +/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */
42509  #  define UIO_MAXIOV 512
42510  # elif defined(__sun)
42511  /* Solaris (and SunOS?) defines IOV_MAX instead */
42512 @@ -51,105 +51,119 @@
42513  #define LOCAL_BUFFERING 1
42514  #endif
42515  
42516 -int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq) {
42517 -       chunk *c;
42518 +NETWORK_BACKEND_WRITE_CHUNK(writev_mem) {
42519 +       char * offset;
42520 +       size_t toSend;
42521 +       ssize_t r;
42522 +
42523 +       size_t num_chunks, i;
42524 +       struct iovec chunks[UIO_MAXIOV];
42525 +       chunk *tc; /* transfer chunks */
42526 +       size_t num_bytes = 0;
42527 +
42528 +       /* we can't send more then SSIZE_MAX bytes in one chunk */
42529 +
42530 +       /* build writev list
42531 +        *
42532 +        * 1. limit: num_chunks < UIO_MAXIOV
42533 +        * 2. limit: num_bytes < SSIZE_MAX
42534 +        */
42535 +       for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
42536 +
42537 +       for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
42538 +               if (tc->mem->used == 0) {
42539 +                       chunks[i].iov_base = tc->mem->ptr;
42540 +                       chunks[i].iov_len  = 0;
42541 +               } else {
42542 +                       offset = tc->mem->ptr + tc->offset;
42543 +                       toSend = tc->mem->used - 1 - tc->offset;
42544 +
42545 +                       chunks[i].iov_base = offset;
42546 +
42547 +                       /* protect the return value of writev() */
42548 +                       if (toSend > SSIZE_MAX ||
42549 +                           num_bytes + toSend > SSIZE_MAX) {
42550 +                               chunks[i].iov_len = SSIZE_MAX - num_bytes;
42551 +
42552 +                               num_chunks = i + 1;
42553 +                               break;
42554 +                       } else {
42555 +                               chunks[i].iov_len = toSend;
42556 +                       }
42557 +
42558 +                       num_bytes += toSend;
42559 +               }
42560 +       }
42561 +
42562 +       if ((r = writev(fd, chunks, num_chunks)) < 0) {
42563 +               switch (errno) {
42564 +               case EAGAIN:
42565 +               case EINTR:
42566 +                       r = 0;
42567 +                       break;
42568 +               case EPIPE:
42569 +               case ECONNRESET:
42570 +                       return NETWORK_STATUS_CONNECTION_CLOSE;
42571 +               default:
42572 +                       log_error_write(srv, __FILE__, __LINE__, "ssd",
42573 +                                       "writev failed:", strerror(errno), fd);
42574 +
42575 +                       return NETWORK_STATUS_FATAL_ERROR;
42576 +               }
42577 +       }
42578 +
42579 +       cq->bytes_out += r;
42580 +
42581 +       /* check which chunks have been written */
42582 +
42583 +       for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
42584 +               if (r >= (ssize_t)chunks[i].iov_len) {
42585 +                       /* written */
42586 +                       r -= chunks[i].iov_len;
42587 +                       tc->offset += chunks[i].iov_len;
42588 +               } else {
42589 +                       /* partially written */
42590 +
42591 +                       tc->offset += r;
42592 +                       break;
42593 +               }
42594 +       }
42595 +
42596 +       return NETWORK_STATUS_SUCCESS;
42597 +}
42598 +
42599 +NETWORK_BACKEND_WRITE(writev) {
42600 +       chunk *c, *tc;
42601         size_t chunks_written = 0;
42602 -       
42603 +
42604         for(c = cq->first; c; c = c->next) {
42605                 int chunk_finished = 0;
42606 -               
42607 +               network_status_t ret;
42608 +
42609                 switch(c->type) {
42610 -               case MEM_CHUNK: {
42611 -                       char * offset;
42612 -                       size_t toSend;
42613 -                       ssize_t r;
42614 -                       
42615 -                       size_t num_chunks, i;
42616 -                       struct iovec chunks[UIO_MAXIOV];
42617 -                       chunk *tc;
42618 -                       size_t num_bytes = 0;
42619 -                       
42620 -                       /* we can't send more then SSIZE_MAX bytes in one chunk */
42621 -                       
42622 -                       /* build writev list 
42623 -                        * 
42624 -                        * 1. limit: num_chunks < UIO_MAXIOV
42625 -                        * 2. limit: num_bytes < SSIZE_MAX
42626 -                        */
42627 -                       for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
42628 -                       
42629 -                       for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
42630 -                               if (tc->mem->used == 0) {
42631 -                                       chunks[i].iov_base = tc->mem->ptr;
42632 -                                       chunks[i].iov_len  = 0;
42633 -                               } else {
42634 -                                       offset = tc->mem->ptr + tc->offset;
42635 -                                       toSend = tc->mem->used - 1 - tc->offset;
42636 -                               
42637 -                                       chunks[i].iov_base = offset;
42638 -                                       
42639 -                                       /* protect the return value of writev() */
42640 -                                       if (toSend > SSIZE_MAX ||
42641 -                                           num_bytes + toSend > SSIZE_MAX) {
42642 -                                               chunks[i].iov_len = SSIZE_MAX - num_bytes;
42643 -                                               
42644 -                                               num_chunks = i + 1;
42645 -                                               break;
42646 -                                       } else {
42647 -                                               chunks[i].iov_len = toSend;
42648 -                                       }
42649 -                                       
42650 -                                       num_bytes += toSend;
42651 -                               }
42652 -                       }
42653 -                       
42654 -                       if ((r = writev(fd, chunks, num_chunks)) < 0) {
42655 -                               switch (errno) {
42656 -                               case EAGAIN:
42657 -                               case EINTR:
42658 -                                       r = 0;
42659 -                                       break;
42660 -                               case EPIPE:
42661 -                               case ECONNRESET:
42662 -                                       return -2;
42663 -                               default:
42664 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
42665 -                                                       "writev failed:", strerror(errno), fd);
42666 -                               
42667 -                                       return -1;
42668 -                               }
42669 -                       }
42670 -                       
42671 -                       cq->bytes_out += r;
42672 +               case MEM_CHUNK:
42673 +                       ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
42674  
42675 -                       /* check which chunks have been written */
42676 -                       
42677 -                       for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
42678 -                               if (r >= (ssize_t)chunks[i].iov_len) {
42679 -                                       /* written */
42680 -                                       r -= chunks[i].iov_len;
42681 -                                       tc->offset += chunks[i].iov_len;
42682 -                                       
42683 +                       /* check which chunks are finished now */
42684 +                       for (tc = c; tc; tc = tc->next) {
42685 +                               /* finished the chunk */
42686 +                               if (tc->offset == tc->mem->used - 1) {
42687 +                                       /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
42688                                         if (chunk_finished) {
42689 -                                               /* skip the chunks from further touches */
42690 -                                               chunks_written++;
42691                                                 c = c->next;
42692                                         } else {
42693 -                                               /* chunks_written + c = c->next is done in the for()*/
42694 -                                               chunk_finished++;
42695 +                                               chunk_finished = 1;
42696                                         }
42697                                 } else {
42698 -                                       /* partially written */
42699 -                                       
42700 -                                       tc->offset += r;
42701 -                                       chunk_finished = 0;
42702 -
42703                                         break;
42704                                 }
42705                         }
42706 -                       
42707 +
42708 +                       if (ret != NETWORK_STATUS_SUCCESS) {
42709 +                               return ret;
42710 +                       }
42711 +
42712                         break;
42713 -               }
42714                 case FILE_CHUNK: {
42715                         ssize_t r;
42716                         off_t abs_offset;
42717 @@ -159,26 +173,26 @@
42718  #define KByte * 1024
42719  #define MByte * 1024 KByte
42720  #define GByte * 1024 MByte
42721 -                       const off_t we_want_to_mmap = 512 KByte; 
42722 +                       const off_t we_want_to_mmap = 512 KByte;
42723                         char *start = NULL;
42724  
42725                         if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
42726                                 log_error_write(srv, __FILE__, __LINE__, "sb",
42727                                                 strerror(errno), c->file.name);
42728 -                               return -1;
42729 +                               return NETWORK_STATUS_FATAL_ERROR;
42730                         }
42731  
42732                         abs_offset = c->file.start + c->offset;
42733 -                       
42734 +
42735                         if (abs_offset > sce->st.st_size) {
42736 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
42737 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
42738                                                 "file was shrinked:", c->file.name);
42739 -                               
42740 -                               return -1;
42741 +
42742 +                               return NETWORK_STATUS_FATAL_ERROR;
42743                         }
42744  
42745 -                       /* mmap the buffer 
42746 -                        * - first mmap 
42747 +                       /* mmap the buffer
42748 +                        * - first mmap
42749                          * - new mmap as the we are at the end of the last one */
42750                         if (c->file.mmap.start == MAP_FAILED ||
42751                             abs_offset == (off_t)(c->file.mmap.offset + c->file.mmap.length)) {
42752 @@ -188,7 +202,7 @@
42753                                  * adaptive mem-mapping
42754                                  *   the problem:
42755                                  *     we mmap() the whole file. If someone has alot large files and 32bit
42756 -                                *     machine the virtual address area will be unrun and we will have a failing 
42757 +                                *     machine the virtual address area will be unrun and we will have a failing
42758                                  *     mmap() call.
42759                                  *   solution:
42760                                  *     only mmap 16M in one chunk and move the window as soon as we have finished
42761 @@ -234,8 +248,8 @@
42762                                 if (-1 == c->file.fd) {  /* open the file if not already open */
42763                                         if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
42764                                                 log_error_write(srv, __FILE__, __LINE__, "sbs", "open failed for:", c->file.name, strerror(errno));
42765 -                               
42766 -                                               return -1;
42767 +
42768 +                                               return NETWORK_STATUS_FATAL_ERROR;
42769                                         }
42770  #ifdef FD_CLOEXEC
42771                                         fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
42772 @@ -245,10 +259,10 @@
42773                                 if (MAP_FAILED == (c->file.mmap.start = mmap(0, to_mmap, PROT_READ, MAP_SHARED, c->file.fd, c->file.mmap.offset))) {
42774                                         /* close it here, otherwise we'd have to set FD_CLOEXEC */
42775  
42776 -                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:", 
42777 +                                       log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:",
42778                                                         strerror(errno), c->file.name, c->file.fd);
42779  
42780 -                                       return -1;
42781 +                                       return NETWORK_STATUS_FATAL_ERROR;
42782                                 }
42783  
42784                                 c->file.mmap.length = to_mmap;
42785 @@ -258,7 +272,7 @@
42786  #ifdef HAVE_MADVISE
42787                                 /* don't advise files < 64Kb */
42788                                 if (c->file.mmap.length > (64 KByte)) {
42789 -                                       /* darwin 7 is returning EINVAL all the time and I don't know how to 
42790 +                                       /* darwin 7 is returning EINVAL all the time and I don't know how to
42791                                          * detect this at runtime.i
42792                                          *
42793                                          * ignore the return value for now */
42794 @@ -274,12 +288,12 @@
42795                         toSend = (c->file.mmap.offset + c->file.mmap.length) - (abs_offset);
42796  
42797                         if (toSend < 0) {
42798 -                               log_error_write(srv, __FILE__, __LINE__, "soooo", 
42799 +                               log_error_write(srv, __FILE__, __LINE__, "soooo",
42800                                                 "toSend is negative:",
42801                                                 toSend,
42802                                                 c->file.mmap.length,
42803                                                 abs_offset,
42804 -                                               c->file.mmap.offset); 
42805 +                                               c->file.mmap.offset);
42806                                 assert(toSend < 0);
42807                         }
42808  
42809 @@ -297,18 +311,18 @@
42810                                         break;
42811                                 case EPIPE:
42812                                 case ECONNRESET:
42813 -                                       return -2;
42814 +                                       return NETWORK_STATUS_CONNECTION_CLOSE;
42815                                 default:
42816 -                                       log_error_write(srv, __FILE__, __LINE__, "ssd", 
42817 +                                       log_error_write(srv, __FILE__, __LINE__, "ssd",
42818                                                         "write failed:", strerror(errno), fd);
42819 -                                       
42820 -                                       return -1;
42821 +
42822 +                                       return NETWORK_STATUS_FATAL_ERROR;
42823                                 }
42824                         }
42825 -                       
42826 +
42827                         c->offset += r;
42828                         cq->bytes_out += r;
42829 -                       
42830 +
42831                         if (c->offset == c->file.length) {
42832                                 chunk_finished = 1;
42833  
42834 @@ -318,26 +332,26 @@
42835                                         c->file.mmap.start = MAP_FAILED;
42836                                 }
42837                         }
42838 -                       
42839 +
42840                         break;
42841                 }
42842                 default:
42843 -                       
42844 +
42845                         log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
42846 -                       
42847 -                       return -1;
42848 +
42849 +                       return NETWORK_STATUS_FATAL_ERROR;
42850                 }
42851 -               
42852 +
42853                 if (!chunk_finished) {
42854                         /* not finished yet */
42855 -                       
42856 +
42857                         break;
42858                 }
42859 -               
42860 +
42861                 chunks_written++;
42862         }
42863  
42864 -       return chunks_written;
42865 +       return NETWORK_STATUS_SUCCESS;
42866  }
42867  
42868  #endif
42869 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/plugin.c lighttpd-1.4.12/src/plugin.c
42870 --- lighttpd-1.4.11/src/plugin.c        2006-02-08 14:00:54.000000000 +0200
42871 +++ lighttpd-1.4.12/src/plugin.c        2006-07-11 21:23:40.000000000 +0300
42872 @@ -13,27 +13,27 @@
42873  #include <valgrind/valgrind.h>
42874  #endif
42875  
42876 -#ifndef __WIN32
42877 +#ifndef _WIN32
42878  #include <dlfcn.h>
42879  #endif
42880  /*
42881 - * 
42882 + *
42883   * if you change this enum to add a new callback, be sure
42884   * - that PLUGIN_FUNC_SIZEOF is the last entry
42885   * - that you add PLUGIN_TO_SLOT twice:
42886 - *   1. as callback-dispatcher 
42887 + *   1. as callback-dispatcher
42888   *   2. in plugins_call_init()
42889 - * 
42890 + *
42891   */
42892  
42893  typedef struct {
42894         PLUGIN_DATA;
42895  } plugin_data;
42896  
42897 -typedef enum { 
42898 +typedef enum {
42899         PLUGIN_FUNC_UNSET,
42900 -               PLUGIN_FUNC_HANDLE_URI_CLEAN, 
42901 -               PLUGIN_FUNC_HANDLE_URI_RAW, 
42902 +               PLUGIN_FUNC_HANDLE_URI_CLEAN,
42903 +               PLUGIN_FUNC_HANDLE_URI_RAW,
42904                 PLUGIN_FUNC_HANDLE_REQUEST_DONE,
42905                 PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE,
42906                 PLUGIN_FUNC_HANDLE_TRIGGER,
42907 @@ -44,38 +44,42 @@
42908                 PLUGIN_FUNC_HANDLE_DOCROOT,
42909                 PLUGIN_FUNC_HANDLE_PHYSICAL,
42910                 PLUGIN_FUNC_CONNECTION_RESET,
42911 -               PLUGIN_FUNC_INIT, 
42912 +               PLUGIN_FUNC_INIT,
42913                 PLUGIN_FUNC_CLEANUP,
42914                 PLUGIN_FUNC_SET_DEFAULTS,
42915 -               
42916 +
42917                 PLUGIN_FUNC_SIZEOF
42918  } plugin_t;
42919  
42920  static plugin *plugin_init(void) {
42921         plugin *p;
42922 -       
42923 +
42924         p = calloc(1, sizeof(*p));
42925 -       
42926 +
42927 +       p->required_plugins = array_init();
42928 +
42929         return p;
42930  }
42931  
42932  static void plugin_free(plugin *p) {
42933         int use_dlclose = 1;
42934         if (p->name) buffer_free(p->name);
42935 +
42936 +       array_free(p->required_plugins);
42937  #ifdef HAVE_VALGRIND_VALGRIND_H
42938         /*if (RUNNING_ON_VALGRIND) use_dlclose = 0;*/
42939  #endif
42940  
42941  #ifndef LIGHTTPD_STATIC
42942 -       if (use_dlclose && p->lib) {    
42943 -#ifdef __WIN32
42944 +       if (use_dlclose && p->lib) {
42945 +#ifdef _WIN32
42946                 FreeLibrary(p->lib);
42947  #else
42948                 dlclose(p->lib);
42949  #endif
42950         }
42951  #endif
42952 -               
42953 +
42954         free(p);
42955  }
42956  
42957 @@ -89,17 +93,17 @@
42958                 srv->plugins.size += 4;
42959                 srv->plugins.ptr   = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps));
42960         }
42961 -       
42962 +
42963         ps = srv->plugins.ptr;
42964         ps[srv->plugins.used++] = p;
42965 -       
42966 +
42967         return 0;
42968  }
42969  
42970  /**
42971 - * 
42972 - * 
42973 - * 
42974 + *
42975 + *
42976 + *
42977   */
42978  
42979  #ifdef LIGHTTPD_STATIC
42980 @@ -121,30 +125,35 @@
42981  #else
42982  int plugins_load(server *srv) {
42983         plugin *p;
42984 +#ifdef _WIN32
42985 +    FARPROC init;
42986 +#else
42987         int (*init)(plugin *pl);
42988 +#endif
42989 +
42990         const char *error;
42991 -       size_t i;
42992 -       
42993 +       size_t i, j, k;
42994 +
42995         for (i = 0; i < srv->srvconf.modules->used; i++) {
42996                 data_string *d = (data_string *)srv->srvconf.modules->data[i];
42997                 char *modules = d->value->ptr;
42998 -       
42999 +
43000                 buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.modules_dir);
43001  
43002                 buffer_append_string(srv->tmp_buf, "/");
43003                 buffer_append_string(srv->tmp_buf, modules);
43004 -#if defined(__WIN32) || defined(__CYGWIN__)
43005 +#if defined(_WIN32) || defined(__CYGWIN__)
43006                 buffer_append_string(srv->tmp_buf, ".dll");
43007  #else
43008                 buffer_append_string(srv->tmp_buf, ".so");
43009  #endif
43010 -       
43011 +
43012                 p = plugin_init();
43013 -#ifdef __WIN32
43014 +#ifdef _WIN32
43015                 if (NULL == (p->lib = LoadLibrary(srv->tmp_buf->ptr))) {
43016                         LPVOID lpMsgBuf;
43017                         FormatMessage(
43018 -                               FORMAT_MESSAGE_ALLOCATE_BUFFER | 
43019 +                               FORMAT_MESSAGE_ALLOCATE_BUFFER |
43020                                 FORMAT_MESSAGE_FROM_SYSTEM,
43021                                 NULL,
43022                                 GetLastError(),
43023 @@ -152,36 +161,36 @@
43024                                 (LPTSTR) &lpMsgBuf,
43025                                 0, NULL );
43026  
43027 -                       log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed", 
43028 +                       log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
43029                                         lpMsgBuf, srv->tmp_buf);
43030 -                       
43031 +
43032                         plugin_free(p);
43033 -                       
43034 +
43035                         return -1;
43036  
43037                 }
43038 -#else  
43039 +#else
43040                 if (NULL == (p->lib = dlopen(srv->tmp_buf->ptr, RTLD_LAZY))) {
43041 -                       log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:", 
43042 +                       log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
43043                                         srv->tmp_buf, dlerror());
43044 -                       
43045 +
43046                         plugin_free(p);
43047 -                       
43048 +
43049                         return -1;
43050                 }
43051 -               
43052 +
43053  #endif
43054                 buffer_reset(srv->tmp_buf);
43055                 buffer_copy_string(srv->tmp_buf, modules);
43056                 buffer_append_string(srv->tmp_buf, "_plugin_init");
43057  
43058 -#ifdef __WIN32
43059 +#ifdef _WIN32
43060                 init = GetProcAddress(p->lib, srv->tmp_buf->ptr);
43061  
43062                 if (init == NULL)  {
43063                         LPVOID lpMsgBuf;
43064                         FormatMessage(
43065 -                               FORMAT_MESSAGE_ALLOCATE_BUFFER | 
43066 +                               FORMAT_MESSAGE_ALLOCATE_BUFFER |
43067                                 FORMAT_MESSAGE_FROM_SYSTEM,
43068                                 NULL,
43069                                 GetLastError(),
43070 @@ -190,7 +199,7 @@
43071                                 0, NULL );
43072  
43073                         log_error_write(srv, __FILE__, __LINE__, "sbs", "getprocaddress failed:", srv->tmp_buf, lpMsgBuf);
43074 -                       
43075 +
43076                         plugin_free(p);
43077                         return -1;
43078                 }
43079 @@ -203,24 +212,43 @@
43080  #endif
43081                 if ((error = dlerror()) != NULL)  {
43082                         log_error_write(srv, __FILE__, __LINE__, "s", error);
43083 -                       
43084 +
43085                         plugin_free(p);
43086                         return -1;
43087                 }
43088 -       
43089 +
43090  #endif
43091                 if ((*init)(p)) {
43092                         log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin init failed" );
43093 -                       
43094 +
43095                         plugin_free(p);
43096                         return -1;
43097                 }
43098  #if 0
43099                 log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin loaded" );
43100  #endif
43101 +               /* check if the required plugin is loaded */
43102 +               for (k = 0; k < p->required_plugins->used; k++) {
43103 +                       data_string *req = (data_string *)p->required_plugins->data[k];
43104 +
43105 +                       for (j = 0; j < i; j++) {
43106 +                               data_string *mod = (data_string *)srv->srvconf.modules->data[j];
43107 +
43108 +                               if (buffer_is_equal(req->value, mod->value)) break;
43109 +                       }
43110 +
43111 +                       if (j == i) {
43112 +                               /* not found */
43113 +                               log_error_write(srv, __FILE__, __LINE__, "ssbs", modules, "failed to load. required plugin", req->value, "was not loaded" );
43114 +
43115 +                               plugin_free(p);
43116 +                       
43117 +                               return -1;
43118 +                       }
43119 +               }
43120                 plugins_register(srv, p);
43121         }
43122 -       
43123 +
43124         return 0;
43125  }
43126  #endif
43127 @@ -253,8 +281,8 @@
43128         }
43129  
43130  /**
43131 - * plugins that use 
43132 - * 
43133 + * plugins that use
43134 + *
43135   * - server *srv
43136   * - connection *con
43137   * - void *p_d (plugin_data *)
43138 @@ -301,12 +329,12 @@
43139         }
43140  
43141  /**
43142 - * plugins that use 
43143 - * 
43144 + * plugins that use
43145 + *
43146   * - server *srv
43147   * - void *p_d (plugin_data *)
43148   */
43149 -                                                                       
43150 +
43151  PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger)
43152  PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup)
43153  PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup)
43154 @@ -314,18 +342,18 @@
43155  
43156  #undef PLUGIN_TO_SLOT
43157  
43158 -#if 0                                                                  
43159 +#if 0
43160  /**
43161 - * 
43162 + *
43163   * special handler
43164 - * 
43165 + *
43166   */
43167  handler_t plugins_call_handle_fdevent(server *srv, const fd_conn *fdc) {
43168         size_t i;
43169         plugin **ps;
43170 -       
43171 +
43172         ps = srv->plugins.ptr;
43173 -       
43174 +
43175         for (i = 0; i < srv->plugins.used; i++) {
43176                 plugin *p = ps[i];
43177                 if (p->handle_fdevent) {
43178 @@ -344,34 +372,34 @@
43179                         }
43180                 }
43181         }
43182 -       
43183 +
43184         return HANDLER_GO_ON;
43185  }
43186  #endif
43187  /**
43188 - * 
43189 + *
43190   * - call init function of all plugins to init the plugin-internals
43191   * - added each plugin that supports has callback to the corresponding slot
43192 - * 
43193 + *
43194   * - is only called once.
43195   */
43196  
43197  handler_t plugins_call_init(server *srv) {
43198         size_t i;
43199         plugin **ps;
43200 -       
43201 +
43202         ps = srv->plugins.ptr;
43203 -       
43204 +
43205         /* fill slots */
43206 -       
43207 +
43208         srv->plugin_slots = calloc(PLUGIN_FUNC_SIZEOF, sizeof(ps));
43209 -       
43210 +
43211         for (i = 0; i < srv->plugins.used; i++) {
43212                 size_t j;
43213                 /* check which calls are supported */
43214 -               
43215 +
43216                 plugin *p = ps[i];
43217 -               
43218 +
43219  #define PLUGIN_TO_SLOT(x, y) \
43220         if (p->y) { \
43221                 plugin **slot = ((plugin ***)(srv->plugin_slots))[x]; \
43222 @@ -384,11 +412,11 @@
43223                         slot[j] = p;\
43224                         break;\
43225                 }\
43226 -       } 
43227 -               
43228 -               
43229 -               PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean); 
43230 -               PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw); 
43231 +       }
43232 +
43233 +
43234 +               PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
43235 +               PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
43236                 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle_request_done);
43237                 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close);
43238                 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger);
43239 @@ -402,19 +430,19 @@
43240                 PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup);
43241                 PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults);
43242  #undef PLUGIN_TO_SLOT
43243 -               
43244 +
43245                 if (p->init) {
43246                         if (NULL == (p->data = p->init())) {
43247 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
43248 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
43249                                                 "plugin-init failed for module", p->name);
43250                                 return HANDLER_ERROR;
43251                         }
43252 -                       
43253 +
43254                         /* used for con->mode, DIRECT == 0, plugins above that */
43255                         ((plugin_data *)(p->data))->id = i + 1;
43256 -                       
43257 +
43258                         if (p->version != LIGHTTPD_VERSION_ID) {
43259 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
43260 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
43261                                                 "plugin-version doesn't match lighttpd-version for", p->name);
43262                                 return HANDLER_ERROR;
43263                         }
43264 @@ -422,29 +450,46 @@
43265                         p->data = NULL;
43266                 }
43267         }
43268 -       
43269 +
43270         return HANDLER_GO_ON;
43271  }
43272  
43273 +/**
43274 + * get the config-storage of the named plugin 
43275 + */
43276 +void *plugin_get_config(server *srv, const char *name) {
43277 +       size_t i;
43278 +
43279 +       for (i = 0; i < srv->plugins.used; i++) {
43280 +               plugin *p = ((plugin **)srv->plugins.ptr)[i];
43281 +
43282 +               if (buffer_is_equal_string(p->name, name, strlen(name))) {
43283 +                       return p->data;
43284 +               }
43285 +       }
43286 +
43287 +       return NULL;
43288 +}
43289 +
43290  void plugins_free(server *srv) {
43291         size_t i;
43292         plugins_call_cleanup(srv);
43293 -       
43294 +
43295         for (i = 0; i < srv->plugins.used; i++) {
43296                 plugin *p = ((plugin **)srv->plugins.ptr)[i];
43297 -               
43298 +
43299                 plugin_free(p);
43300         }
43301 -       
43302 +
43303         for (i = 0; srv->plugin_slots && i < PLUGIN_FUNC_SIZEOF; i++) {
43304                 plugin **slot = ((plugin ***)(srv->plugin_slots))[i];
43305 -               
43306 +
43307                 if (slot) free(slot);
43308         }
43309 -       
43310 +
43311         free(srv->plugin_slots);
43312         srv->plugin_slots = NULL;
43313 -       
43314 +
43315         free(srv->plugins.ptr);
43316         srv->plugins.ptr = NULL;
43317         srv->plugins.used = 0;
43318 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/plugin.h lighttpd-1.4.12/src/plugin.h
43319 --- lighttpd-1.4.11/src/plugin.h        2005-08-15 12:28:56.000000000 +0300
43320 +++ lighttpd-1.4.12/src/plugin.h        2006-07-11 21:23:40.000000000 +0300
43321 @@ -12,6 +12,12 @@
43322  
43323  #define INIT_FUNC(x) \
43324                 static void *x()
43325 +/*
43326 + * The PATCH_OPTION() macro is used in the patch_connection() functions
43327 + * of the modules to update the config object for the current request.
43328 + */
43329 +#define PATCH_OPTION(x) \
43330 +               p->conf.x = s->x
43331  
43332  #define FREE_FUNC          SERVER_FUNC
43333  #define TRIGGER_FUNC       SERVER_FUNC
43334 @@ -25,19 +31,19 @@
43335  #define URIHANDLER_FUNC    CONNECTION_FUNC
43336  
43337  #define PLUGIN_DATA        size_t id
43338 -                                                                                                                                               
43339 +
43340  typedef struct {
43341         size_t version;
43342 -       
43343 +
43344         buffer *name; /* name of the plugin */
43345 -       
43346 +
43347         void *(* init)                       ();
43348         handler_t (* set_defaults)           (server *srv, void *p_d);
43349         handler_t (* cleanup)                (server *srv, void *p_d);
43350                                                                                            /* is called ... */
43351         handler_t (* handle_trigger)         (server *srv, void *p_d);                     /* once a second */
43352         handler_t (* handle_sighup)          (server *srv, void *p_d);                     /* at a signup */
43353 -       
43354 +
43355         handler_t (* handle_uri_raw)         (server *srv, connection *con, void *p_d);    /* after uri_raw is set */
43356         handler_t (* handle_uri_clean)       (server *srv, connection *con, void *p_d);    /* after uri is set */
43357         handler_t (* handle_docroot)         (server *srv, connection *con, void *p_d);    /* getting the document-root */
43358 @@ -45,20 +51,22 @@
43359         handler_t (* handle_request_done)    (server *srv, connection *con, void *p_d);    /* at the end of a request */
43360         handler_t (* handle_connection_close)(server *srv, connection *con, void *p_d);    /* at the end of a connection */
43361         handler_t (* handle_joblist)         (server *srv, connection *con, void *p_d);    /* after all events are handled */
43362 -       
43363 -       
43364 -       
43365 -       handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);   
43366 -       
43367 -                                                                                          /* when a handler for the request 
43368 +
43369 +
43370 +
43371 +       handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);
43372 +
43373 +                                                                                          /* when a handler for the request
43374                                                                                             * has to be found
43375                                                                                             */
43376         handler_t (* handle_subrequest)      (server *srv, connection *con, void *p_d);    /* */
43377         handler_t (* connection_reset)       (server *srv, connection *con, void *p_d);    /* */
43378         void *data;
43379 -       
43380 +
43381         /* dlopen handle */
43382         void *lib;
43383 +
43384 +       array *required_plugins;
43385  } plugin;
43386  
43387  int plugins_load(server *srv);
43388 @@ -88,5 +96,8 @@
43389  int config_patch_connection(server *srv, connection *con, comp_key_t comp);
43390  int config_check_cond(server *srv, connection *con, data_config *dc);
43391  int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n);
43392 +int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result);
43393 +
43394 +void *plugin_get_config(server *srv, const char *name);
43395  
43396  #endif
43397 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/proc_open.c lighttpd-1.4.12/src/proc_open.c
43398 --- lighttpd-1.4.11/src/proc_open.c     2005-08-11 01:26:39.000000000 +0300
43399 +++ lighttpd-1.4.12/src/proc_open.c     2006-07-11 21:23:40.000000000 +0300
43400 @@ -13,13 +13,13 @@
43401  #endif
43402  
43403  
43404 -#ifdef WIN32
43405 +#ifdef _WIN32
43406  /* {{{ win32 stuff */
43407  # define SHELLENV "ComSpec"
43408  # define SECURITY_DC , SECURITY_ATTRIBUTES *security
43409  # define SECURITY_CC , security
43410  # define pipe(pair) (CreatePipe(&pair[0], &pair[1], security, 2048L) ? 0 : -1)
43411 -static inline HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
43412 +static HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
43413  {
43414         HANDLE copy, self = GetCurrentProcess();
43415  
43416 @@ -148,11 +148,14 @@
43417         STARTUPINFO si;
43418         BOOL procok;
43419         SECURITY_ATTRIBUTES security;
43420 -       const char *shell;
43421 +       const char *shell = NULL;
43422 +       const char *windir = NULL;
43423         buffer *cmdline;
43424  
43425 -       if (NULL == (shell = getenv(SHELLENV))) {
43426 -               fprintf(stderr, "env %s is required", SHELLENV);
43427 +       if (NULL == (shell = getenv(SHELLENV)) &&
43428 +                       NULL == (windir = getenv("SystemRoot")) &&
43429 +                       NULL == (windir = getenv("windir"))) {
43430 +               fprintf(stderr, "One of %s,%%SystemRoot,%%windir is required", SHELLENV);
43431                 return -1;
43432         }
43433  
43434 @@ -177,17 +180,23 @@
43435         memset(&pi, 0, sizeof(pi));
43436  
43437         cmdline = buffer_init();
43438 -       buffer_append_string(cmdline, shell);
43439 +       if (shell) {
43440 +               buffer_append_string(cmdline, shell);
43441 +       } else {
43442 +               buffer_append_string(cmdline, windir);
43443 +               buffer_append_string(cmdline, "\\system32\\cmd.exe");
43444 +       }
43445         buffer_append_string_len(cmdline, CONST_STR_LEN(" /c "));
43446         buffer_append_string(cmdline, command);
43447         procok = CreateProcess(NULL, cmdline->ptr, &security, &security, TRUE,
43448                         NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
43449 -       buffer_free(cmdline);
43450  
43451         if (FALSE == procok) {
43452 -               fprintf(stderr, "failed to CreateProcess");
43453 +               fprintf(stderr, "failed to CreateProcess: %s", cmdline->ptr);
43454 +               buffer_free(cmdline);
43455                 return -1;
43456         }
43457 +       buffer_free(cmdline);
43458  
43459         proc->child = pi.hProcess;
43460         CloseHandle(pi.hThread);
43461 @@ -226,8 +235,7 @@
43462         const char *shell;
43463  
43464         if (NULL == (shell = getenv(SHELLENV))) {
43465 -               fprintf(stderr, "env %s is required", SHELLENV);
43466 -               return -1;
43467 +               shell = "/bin/sh";
43468         }
43469  
43470         if (proc_open_pipes(proc) != 0) {
43471 @@ -262,11 +270,11 @@
43472         }
43473  }
43474  /* }}} */
43475 -#endif /* WIN32 */
43476 +#endif /* _WIN32 */
43477  
43478  /* {{{ proc_read_fd_to_buffer */
43479  static void proc_read_fd_to_buffer(int fd, buffer *b) {
43480 -       ssize_t s;
43481 +       int s; /* win32 has not ssize_t */
43482  
43483         for (;;) {
43484                 buffer_prepare_append(b, 512);
43485 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/proc_open.h lighttpd-1.4.12/src/proc_open.h
43486 --- lighttpd-1.4.11/src/proc_open.h     2005-08-11 01:26:39.000000000 +0300
43487 +++ lighttpd-1.4.12/src/proc_open.h     2006-07-11 21:23:40.000000000 +0300
43488 @@ -1,7 +1,7 @@
43489  
43490  #include "buffer.h"
43491  
43492 -#ifdef WIN32
43493 +#ifdef _WIN32
43494  #include <windows.h>
43495  typedef HANDLE descriptor_t;
43496  typedef HANDLE proc_pid_t;
43497 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/request.c lighttpd-1.4.12/src/request.c
43498 --- lighttpd-1.4.11/src/request.c       2006-03-05 11:58:09.000000000 +0200
43499 +++ lighttpd-1.4.12/src/request.c       2006-07-11 21:23:40.000000000 +0300
43500 @@ -10,15 +10,17 @@
43501  #include "keyvalue.h"
43502  #include "log.h"
43503  
43504 +#include "sys-strings.h"
43505 +
43506  static int request_check_hostname(server *srv, connection *con, buffer *host) {
43507         enum { DOMAINLABEL, TOPLABEL } stage = TOPLABEL;
43508         size_t i;
43509         int label_len = 0;
43510         size_t host_len;
43511         char *colon;
43512 -       int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */ 
43513 +       int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */
43514         int level = 0;
43515 -       
43516 +
43517         UNUSED(srv);
43518         UNUSED(con);
43519  
43520 @@ -32,17 +34,17 @@
43521          *       IPv6address   = "[" ... "]"
43522          *       port          = *digit
43523          */
43524 -       
43525 +
43526         /* no Host: */
43527         if (!host || host->used == 0) return 0;
43528 -       
43529 +
43530         host_len = host->used - 1;
43531 -       
43532 +
43533         /* IPv6 adress */
43534         if (host->ptr[0] == '[') {
43535                 char *c = host->ptr + 1;
43536                 int colon_cnt = 0;
43537 -               
43538 +
43539                 /* check portnumber */
43540                 for (; *c && *c != ']'; c++) {
43541                         if (*c == ':') {
43542 @@ -53,12 +55,12 @@
43543                                 return -1;
43544                         }
43545                 }
43546 -               
43547 +
43548                 /* missing ] */
43549                 if (!*c) {
43550                         return -1;
43551                 }
43552 -               
43553 +
43554                 /* check port */
43555                 if (*(c+1) == ':') {
43556                         for (c += 2; *c; c++) {
43557 @@ -69,39 +71,39 @@
43558                 }
43559                 return 0;
43560         }
43561 -       
43562 +
43563         if (NULL != (colon = memchr(host->ptr, ':', host_len))) {
43564                 char *c = colon + 1;
43565 -               
43566 +
43567                 /* check portnumber */
43568                 for (; *c; c++) {
43569                         if (!light_isdigit(*c)) return -1;
43570                 }
43571 -               
43572 +
43573                 /* remove the port from the host-len */
43574                 host_len = colon - host->ptr;
43575         }
43576 -       
43577 +
43578         /* Host is empty */
43579         if (host_len == 0) return -1;
43580 -       
43581 +
43582         /* scan from the right and skip the \0 */
43583         for (i = host_len - 1; i + 1 > 0; i--) {
43584                 const char c = host->ptr[i];
43585  
43586                 switch (stage) {
43587 -               case TOPLABEL: 
43588 +               case TOPLABEL:
43589                         if (c == '.') {
43590                                 /* only switch stage, if this is not the last character */
43591                                 if (i != host_len - 1) {
43592                                         if (label_len == 0) {
43593                                                 return -1;
43594                                         }
43595 -                                       
43596 +
43597                                         /* check the first character at right of the dot */
43598                                         if (is_ip == 0) {
43599                                                 if (!light_isalpha(host->ptr[i+1])) {
43600 -                                                       return -1; 
43601 +                                                       return -1;
43602                                                 }
43603                                         } else if (!light_isdigit(host->ptr[i+1])) {
43604                                                 is_ip = 0;
43605 @@ -111,9 +113,9 @@
43606                                                 /* just digits */
43607                                                 is_ip = 1;
43608                                         }
43609 -                                               
43610 +
43611                                         stage = DOMAINLABEL;
43612 -                                       
43613 +
43614                                         label_len = 0;
43615                                         level++;
43616                                 } else if (i == 0) {
43617 @@ -135,7 +137,7 @@
43618                                 }
43619                                 label_len++;
43620                         }
43621 -                       
43622 +
43623                         break;
43624                 case DOMAINLABEL:
43625                         if (is_ip == 1) {
43626 @@ -143,7 +145,7 @@
43627                                         if (label_len == 0) {
43628                                                 return -1;
43629                                         }
43630 -                                       
43631 +
43632                                         label_len = 0;
43633                                         level++;
43634                                 } else if (!light_isdigit(c)) {
43635 @@ -156,12 +158,12 @@
43636                                         if (label_len == 0) {
43637                                                 return -1;
43638                                         }
43639 -                                       
43640 +
43641                                         /* c is either - or alphanum here */
43642                                         if ('-' == host->ptr[i+1]) {
43643                                                 return -1;
43644                                         }
43645 -                                       
43646 +
43647                                         label_len = 0;
43648                                         level++;
43649                                 } else if (i == 0) {
43650 @@ -176,20 +178,20 @@
43651                                         label_len++;
43652                                 }
43653                         }
43654 -                       
43655 +
43656                         break;
43657                 }
43658         }
43659 -       
43660 +
43661         /* a IP has to consist of 4 parts */
43662         if (is_ip == 1 && level != 3) {
43663                 return -1;
43664         }
43665 -       
43666 +
43667         if (label_len == 0) {
43668                 return -1;
43669         }
43670 -       
43671 +
43672         return 0;
43673  }
43674  
43675 @@ -201,53 +203,53 @@
43676         char *s;
43677         size_t i;
43678         int state = 0;
43679 -       /*  
43680 -        * parse 
43681 -        * 
43682 +       /*
43683 +        * parse
43684 +        *
43685          * val1, val2, val3, val4
43686 -        * 
43687 +        *
43688          * into a array (more or less a explode() incl. striping of whitespaces
43689          */
43690 -       
43691 +
43692         if (b->used == 0) return 0;
43693 -       
43694 +
43695         s = b->ptr;
43696 -       
43697 +
43698         for (i =0; i < b->used - 1; ) {
43699                 char *start = NULL, *end = NULL;
43700                 data_string *ds;
43701 -               
43702 +
43703                 switch (state) {
43704                 case 0: /* ws */
43705 -                       
43706 +
43707                         /* skip ws */
43708                         for (; (*s == ' ' || *s == '\t') && i < b->used - 1; i++, s++);
43709 -                       
43710 -                       
43711 +
43712 +
43713                         state = 1;
43714                         break;
43715                 case 1: /* value */
43716                         start = s;
43717 -                       
43718 +
43719                         for (; *s != ',' && i < b->used - 1; i++, s++);
43720                         end = s - 1;
43721 -                       
43722 +
43723                         for (; (*end == ' ' || *end == '\t') && end > start; end--);
43724 -                       
43725 +
43726                         if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
43727                                 ds = data_string_init();
43728                         }
43729  
43730                         buffer_copy_string_len(ds->value, start, end-start+1);
43731                         array_insert_unique(vals, (data_unset *)ds);
43732 -                       
43733 +
43734                         if (*s == ',') {
43735                                 state = 0;
43736                                 i++;
43737                                 s++;
43738                         } else {
43739                                 /* end of string */
43740 -                               
43741 +
43742                                 state = 2;
43743                         }
43744                         break;
43745 @@ -263,7 +265,7 @@
43746         if (c <= 32) return 0;
43747         if (c == 127) return 0;
43748         if (c == 255) return 0;
43749 -       
43750 +
43751         return 1;
43752  }
43753  
43754 @@ -271,28 +273,28 @@
43755         char *uri = NULL, *proto = NULL, *method = NULL, con_length_set;
43756         int is_key = 1, key_len = 0, is_ws_after_key = 0, in_folding;
43757         char *value = NULL, *key = NULL;
43758 -       
43759 +
43760         enum { HTTP_CONNECTION_UNSET, HTTP_CONNECTION_KEEPALIVE, HTTP_CONNECTION_CLOSE } keep_alive_set = HTTP_CONNECTION_UNSET;
43761 -       
43762 +
43763         int line = 0;
43764 -       
43765 +
43766         int request_line_stage = 0;
43767         size_t i, first;
43768 -       
43769 +
43770         int done = 0;
43771 -       
43772 +
43773         data_string *ds = NULL;
43774 -       
43775 -       /* 
43776 -        * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$" 
43777 -        * Option : "^([-a-zA-Z]+): (.+)$"                    
43778 +
43779 +       /*
43780 +        * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
43781 +        * Option : "^([-a-zA-Z]+): (.+)$"
43782          * End    : "^$"
43783          */
43784  
43785         if (con->conf.log_request_header) {
43786 -               log_error_write(srv, __FILE__, __LINE__, "sdsdSb", 
43787 -                               "fd:", con->fd, 
43788 -                               "request-len:", con->request.request->used, 
43789 +               log_error_write(srv, __FILE__, __LINE__, "sdsdSb",
43790 +                               "fd:", con->fd,
43791 +                               "request-len:", con->request.request->used,
43792                                 "\n", con->request.request);
43793         }
43794  
43795 @@ -300,13 +302,13 @@
43796             con->request.request->ptr[0] == '\r' &&
43797             con->request.request->ptr[1] == '\n') {
43798                 /* we are in keep-alive and might get \r\n after a previous POST request.*/
43799 -               
43800 +
43801                 buffer_copy_string_len(con->parse_request, con->request.request->ptr + 2, con->request.request->used - 1 - 2);
43802         } else {
43803                 /* fill the local request buffer */
43804                 buffer_copy_string_buffer(con->parse_request, con->request.request);
43805         }
43806 -       
43807 +
43808         keep_alive_set = 0;
43809         con_length_set = 0;
43810  
43811 @@ -318,25 +320,25 @@
43812          * */
43813         for (i = 0, first = 0; i < con->parse_request->used && line == 0; i++) {
43814                 char *cur = con->parse_request->ptr + i;
43815 -               
43816 +
43817                 switch(*cur) {
43818 -               case '\r': 
43819 +               case '\r':
43820                         if (con->parse_request->ptr[i+1] == '\n') {
43821                                 http_method_t r;
43822                                 char *nuri = NULL;
43823                                 size_t j;
43824 -                               
43825 +
43826                                 /* \r\n -> \0\0 */
43827                                 con->parse_request->ptr[i] = '\0';
43828                                 con->parse_request->ptr[i+1] = '\0';
43829 -                               
43830 +
43831                                 buffer_copy_string_len(con->request.request_line, con->parse_request->ptr, i);
43832 -                               
43833 +
43834                                 if (request_line_stage != 2) {
43835                                         con->http_status = 400;
43836                                         con->response.keep_alive = 0;
43837                                         con->keep_alive = 0;
43838 -                                       
43839 +
43840                                         if (srv->srvconf.log_request_header_on_error) {
43841                                                 log_error_write(srv, __FILE__, __LINE__, "s", "incomplete request line -> 400");
43842                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
43843 @@ -345,36 +347,36 @@
43844                                         }
43845                                         return 0;
43846                                 }
43847 -                               
43848 +
43849                                 proto = con->parse_request->ptr + first;
43850 -                               
43851 +
43852                                 *(uri - 1) = '\0';
43853                                 *(proto - 1) = '\0';
43854 -                               
43855 +
43856                                 /* we got the first one :) */
43857                                 if (-1 == (r = get_http_method_key(method))) {
43858                                         con->http_status = 501;
43859                                         con->response.keep_alive = 0;
43860                                         con->keep_alive = 0;
43861 -                                       
43862 +
43863                                         if (srv->srvconf.log_request_header_on_error) {
43864                                                 log_error_write(srv, __FILE__, __LINE__, "s", "unknown http-method -> 501");
43865                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
43866                                                                 "request-header:\n",
43867                                                                 con->request.request);
43868                                         }
43869 -                               
43870 +
43871                                         return 0;
43872                                 }
43873 -                               
43874 +
43875                                 con->request.http_method = r;
43876 -                       
43877 -                               /* 
43878 +
43879 +                               /*
43880                                  * RFC2616 says:
43881                                  *
43882                                  * HTTP-Version   = "HTTP" "/" 1*DIGIT "." 1*DIGIT
43883                                  *
43884 -                                * */   
43885 +                                * */
43886                                 if (0 == strncmp(proto, "HTTP/", sizeof("HTTP/") - 1)) {
43887                                         char * major = proto + sizeof("HTTP/") - 1;
43888                                         char * minor = strchr(major, '.');
43889 @@ -413,10 +415,10 @@
43890                                         }
43891  
43892                                         if (major_num == 1 && minor_num == 1) {
43893 -                                               con->request.http_version = con->conf.allow_http11 ? HTTP_VERSION_1_1 : HTTP_VERSION_1_0;
43894 +                                               con->request.http_version = HTTP_VERSION_1_1;
43895                                         } else if (major_num == 1 && minor_num == 0) {
43896                                                 con->request.http_version = HTTP_VERSION_1_0;
43897 -                                       } else { 
43898 +                                       } else {
43899                                                 con->http_status = 505;
43900  
43901                                                 if (srv->srvconf.log_request_header_on_error) {
43902 @@ -439,30 +441,30 @@
43903                                         }
43904                                         return 0;
43905                                 }
43906 -                               
43907 +
43908                                 if (0 == strncmp(uri, "http://", 7) &&
43909                                     NULL != (nuri = strchr(uri + 7, '/'))) {
43910                                         /* ignore the host-part */
43911 -                                       
43912 +
43913                                         buffer_copy_string_len(con->request.uri, nuri, proto - nuri - 1);
43914                                 } else {
43915                                         /* everything looks good so far */
43916                                         buffer_copy_string_len(con->request.uri, uri, proto - uri - 1);
43917                                 }
43918 -                               
43919 +
43920                                 /* check uri for invalid characters */
43921                                 for (j = 0; j < con->request.uri->used - 1; j++) {
43922                                         if (!request_uri_is_valid_char(con->request.uri->ptr[j])) {
43923                                                 unsigned char buf[2];
43924                                                 con->http_status = 400;
43925                                                 con->keep_alive = 0;
43926 -                                               
43927 +
43928                                                 if (srv->srvconf.log_request_header_on_error) {
43929                                                         buf[0] = con->request.uri->ptr[j];
43930                                                         buf[1] = '\0';
43931 -                                       
43932 +
43933                                                         if (con->request.uri->ptr[j] > 32 &&
43934 -                                                           con->request.uri->ptr[j] != 127) {  
43935 +                                                           con->request.uri->ptr[j] != 127) {
43936                                                                 /* the character is printable -> print it */
43937                                                                 log_error_write(srv, __FILE__, __LINE__, "ss",
43938                                                                                 "invalid character in URI -> 400",
43939 @@ -473,20 +475,20 @@
43940                                                                                 "invalid character in URI -> 400",
43941                                                                                 con->request.uri->ptr[j]);
43942                                                         }
43943 -                                               
43944 +
43945                                                         log_error_write(srv, __FILE__, __LINE__, "Sb",
43946                                                                         "request-header:\n",
43947                                                                         con->request.request);
43948                                                 }
43949 -                                               
43950 +
43951                                                 return 0;
43952                                         }
43953                                 }
43954 -                               
43955 +
43956                                 buffer_copy_string_buffer(con->request.orig_uri, con->request.uri);
43957 -                               
43958 +
43959                                 con->http_status = 0;
43960 -                               
43961 +
43962                                 i++;
43963                                 line++;
43964                                 first = i+1;
43965 @@ -494,14 +496,14 @@
43966                         break;
43967                 case ' ':
43968                         switch(request_line_stage) {
43969 -                       case 0: 
43970 +                       case 0:
43971                                 /* GET|POST|... */
43972 -                               method = con->parse_request->ptr + first; 
43973 +                               method = con->parse_request->ptr + first;
43974                                 first = i + 1;
43975                                 break;
43976                         case 1:
43977                                 /* /foobar/... */
43978 -                               uri = con->parse_request->ptr + first; 
43979 +                               uri = con->parse_request->ptr + first;
43980                                 first = i + 1;
43981                                 break;
43982                         default:
43983 @@ -509,7 +511,7 @@
43984                                 con->http_status = 400;
43985                                 con->response.keep_alive = 0;
43986                                 con->keep_alive = 0;
43987 -                               
43988 +
43989                                 if (srv->srvconf.log_request_header_on_error) {
43990                                         log_error_write(srv, __FILE__, __LINE__, "s", "overlong request line -> 400");
43991                                         log_error_write(srv, __FILE__, __LINE__, "Sb",
43992 @@ -518,12 +520,12 @@
43993                                 }
43994                                 return 0;
43995                         }
43996 -                       
43997 +
43998                         request_line_stage++;
43999                         break;
44000                 }
44001         }
44002 -       
44003 +
44004         in_folding = 0;
44005  
44006         if (con->request.uri->used == 1) {
44007 @@ -540,30 +542,30 @@
44008                 return 0;
44009         }
44010  
44011 -       
44012 +
44013         for (; i < con->parse_request->used && !done; i++) {
44014                 char *cur = con->parse_request->ptr + i;
44015 -               
44016 +
44017                 if (is_key) {
44018                         size_t j;
44019                         int got_colon = 0;
44020 -                       
44021 +
44022                         /**
44023                          * 1*<any CHAR except CTLs or separators>
44024                          * CTLs == 0-31 + 127
44025 -                        * 
44026 +                        *
44027                          */
44028                         switch(*cur) {
44029                         case ':':
44030                                 is_key = 0;
44031 -                               
44032 +
44033                                 value = cur + 1;
44034 -                               
44035 +
44036                                 if (is_ws_after_key == 0) {
44037                                         key_len = i - first;
44038                                 }
44039                                 is_ws_after_key = 0;
44040 -                                       
44041 +
44042                                 break;
44043                         case '(':
44044                         case ')':
44045 @@ -584,8 +586,8 @@
44046                                 con->http_status = 400;
44047                                 con->keep_alive = 0;
44048                                 con->response.keep_alive = 0;
44049 -                               
44050 -                               log_error_write(srv, __FILE__, __LINE__, "sbsds", 
44051 +
44052 +                               log_error_write(srv, __FILE__, __LINE__, "sbsds",
44053                                                 "invalid character in key", con->request.request, cur, *cur, "-> 400");
44054                                 return 0;
44055                         case ' ':
44056 @@ -594,13 +596,13 @@
44057                                         is_key = 0;
44058                                         in_folding = 1;
44059                                         value = cur;
44060 -                                       
44061 +
44062                                         break;
44063                                 }
44064 -                               
44065 -                               
44066 +
44067 +
44068                                 key_len = i - first;
44069 -                               
44070 +
44071                                 /* skip every thing up to the : */
44072                                 for (j = 1; !got_colon; j++) {
44073                                         switch(con->parse_request->ptr[j + i]) {
44074 @@ -610,40 +612,40 @@
44075                                                 continue;
44076                                         case ':':
44077                                                 /* ok, done */
44078 -                                               
44079 +
44080                                                 i += j - 1;
44081                                                 got_colon = 1;
44082 -                                               
44083 +
44084                                                 break;
44085                                         default:
44086                                                 /* error */
44087 -                                               
44088 +
44089                                                 if (srv->srvconf.log_request_header_on_error) {
44090                                                         log_error_write(srv, __FILE__, __LINE__, "s", "WS character in key -> 400");
44091                                                         log_error_write(srv, __FILE__, __LINE__, "Sb",
44092                                                                 "request-header:\n",
44093                                                                 con->request.request);
44094                                                 }
44095 -                                       
44096 +
44097                                                 con->http_status = 400;
44098                                                 con->response.keep_alive = 0;
44099                                                 con->keep_alive = 0;
44100 -                                               
44101 +
44102                                                 return 0;
44103                                         }
44104                                 }
44105 -                               
44106 +
44107                                 break;
44108                         case '\r':
44109                                 if (con->parse_request->ptr[i+1] == '\n' && i == first) {
44110                                         /* End of Header */
44111                                         con->parse_request->ptr[i] = '\0';
44112                                         con->parse_request->ptr[i+1] = '\0';
44113 -                                       
44114 +
44115                                         i++;
44116 -                                       
44117 +
44118                                         done = 1;
44119 -                                       
44120 +
44121                                         break;
44122                                 } else {
44123                                         if (srv->srvconf.log_request_header_on_error) {
44124 @@ -652,7 +654,7 @@
44125                                                         "request-header:\n",
44126                                                         con->request.request);
44127                                         }
44128 -                                       
44129 +
44130                                         con->http_status = 400;
44131                                         con->keep_alive = 0;
44132                                         con->response.keep_alive = 0;
44133 @@ -693,16 +695,16 @@
44134                                 con->http_status = 400;
44135                                 con->keep_alive = 0;
44136                                 con->response.keep_alive = 0;
44137 -                               
44138 +
44139                                 if (srv->srvconf.log_request_header_on_error) {
44140 -                                       log_error_write(srv, __FILE__, __LINE__, "sbsds", 
44141 +                                       log_error_write(srv, __FILE__, __LINE__, "sbsds",
44142                                                 "CTL character in key", con->request.request, cur, *cur, "-> 400");
44143  
44144                                         log_error_write(srv, __FILE__, __LINE__, "Sb",
44145                                                 "request-header:\n",
44146                                                 con->request.request);
44147                                 }
44148 -                               
44149 +
44150                                 return 0;
44151                         default:
44152                                 /* ok */
44153 @@ -710,25 +712,25 @@
44154                         }
44155                 } else {
44156                         switch(*cur) {
44157 -                       case '\r': 
44158 +                       case '\r':
44159                                 if (con->parse_request->ptr[i+1] == '\n') {
44160                                         /* End of Headerline */
44161                                         con->parse_request->ptr[i] = '\0';
44162                                         con->parse_request->ptr[i+1] = '\0';
44163 -                                       
44164 +
44165                                         if (in_folding) {
44166                                                 if (!ds) {
44167                                                         /* 400 */
44168 -                                       
44169 +
44170                                                         if (srv->srvconf.log_request_header_on_error) {
44171                                                                 log_error_write(srv, __FILE__, __LINE__, "s", "WS at the start of first line -> 400");
44172 -                                                       
44173 +
44174                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44175                                                                         "request-header:\n",
44176                                                                         con->request.request);
44177                                                         }
44178  
44179 -                                       
44180 +
44181                                                         con->http_status = 400;
44182                                                         con->keep_alive = 0;
44183                                                         con->response.keep_alive = 0;
44184 @@ -738,9 +740,9 @@
44185                                         } else {
44186                                                 int s_len;
44187                                                 key = con->parse_request->ptr + first;
44188 -                                       
44189 +
44190                                                 s_len = cur - value;
44191 -                                               
44192 +
44193                                                 if (s_len > 0) {
44194                                                         int cmp = 0;
44195                                                         if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
44196 @@ -748,86 +750,87 @@
44197                                                         }
44198                                                         buffer_copy_string_len(ds->key, key, key_len);
44199                                                         buffer_copy_string_len(ds->value, value, s_len);
44200 -                                                       
44201 -                                                       /* retreive values 
44202 -                                                        * 
44203 -                                                        * 
44204 +
44205 +                                                       /* retreive values
44206 +                                                        *
44207 +                                                        *
44208                                                          * the list of options is sorted to simplify the search
44209                                                          */
44210 -                                                       
44211 +
44212                                                         if (0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Connection")))) {
44213                                                                 array *vals;
44214                                                                 size_t vi;
44215 -                                                               
44216 +
44217                                                                 /* split on , */
44218 -                                                               
44219 +
44220                                                                 vals = srv->split_vals;
44221  
44222                                                                 array_reset(vals);
44223 -                                                               
44224 +
44225                                                                 http_request_split_value(vals, ds->value);
44226 -                                                               
44227 +
44228                                                                 for (vi = 0; vi < vals->used; vi++) {
44229                                                                         data_string *dsv = (data_string *)vals->data[vi];
44230 -                                                                       
44231 +
44232                                                                         if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("keep-alive"))) {
44233                                                                                 keep_alive_set = HTTP_CONNECTION_KEEPALIVE;
44234 -                                                                               
44235 +
44236                                                                                 break;
44237                                                                         } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("close"))) {
44238                                                                                 keep_alive_set = HTTP_CONNECTION_CLOSE;
44239 -                                                                               
44240 +
44241                                                                                 break;
44242                                                                         }
44243                                                                 }
44244 -                                                               
44245 +
44246                                                         } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Length")))) {
44247                                                                 char *err;
44248                                                                 unsigned long int r;
44249                                                                 size_t j;
44250 -                                                               
44251 +
44252                                                                 if (con_length_set) {
44253                                                                         con->http_status = 400;
44254                                                                         con->keep_alive = 0;
44255 -                                                                       
44256 +
44257                                                                         if (srv->srvconf.log_request_header_on_error) {
44258 -                                                                               log_error_write(srv, __FILE__, __LINE__, "s", 
44259 +                                                                               log_error_write(srv, __FILE__, __LINE__, "s",
44260                                                                                                 "duplicate Content-Length-header -> 400");
44261                                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44262                                                                                                 "request-header:\n",
44263                                                                                                 con->request.request);
44264                                                                         }
44265 +                                                                       ds->free((data_unset *) ds);
44266                                                                         return 0;
44267                                                                 }
44268 -                                                               
44269 +
44270                                                                 if (ds->value->used == 0) SEGFAULT();
44271 -                                                               
44272 +
44273                                                                 for (j = 0; j < ds->value->used - 1; j++) {
44274                                                                         char c = ds->value->ptr[j];
44275                                                                         if (!isdigit((unsigned char)c)) {
44276 -                                                                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
44277 +                                                                               log_error_write(srv, __FILE__, __LINE__, "sbs",
44278                                                                                                 "content-length broken:", ds->value, "-> 400");
44279 -                                                                               
44280 +
44281                                                                                 con->http_status = 400;
44282                                                                                 con->keep_alive = 0;
44283 -                                                                               
44284 +
44285                                                                                 array_insert_unique(con->request.headers, (data_unset *)ds);
44286                                                                                 return 0;
44287                                                                         }
44288                                                                 }
44289 -                                                               
44290 +
44291                                                                 r = strtoul(ds->value->ptr, &err, 10);
44292 -                                                               
44293 +
44294                                                                 if (*err == '\0') {
44295                                                                         con_length_set = 1;
44296                                                                         con->request.content_length = r;
44297                                                                 } else {
44298 -                                                                       log_error_write(srv, __FILE__, __LINE__, "sbs", 
44299 +                                                                       log_error_write(srv, __FILE__, __LINE__, "sbs",
44300                                                                                         "content-length broken:", ds->value, "-> 400");
44301 -                                                                       
44302 +
44303                                                                         con->http_status = 400;
44304                                                                         con->keep_alive = 0;
44305 -                                                                       
44306 +
44307                                                                         array_insert_unique(con->request.headers, (data_unset *)ds);
44308                                                                         return 0;
44309                                                                 }
44310 @@ -838,23 +841,24 @@
44311                                                                 } else {
44312                                                                         con->http_status = 400;
44313                                                                         con->keep_alive = 0;
44314 -                                                                       
44315 +
44316                                                                         if (srv->srvconf.log_request_header_on_error) {
44317 -                                                                               log_error_write(srv, __FILE__, __LINE__, "s", 
44318 +                                                                               log_error_write(srv, __FILE__, __LINE__, "s",
44319                                                                                                 "duplicate Content-Type-header -> 400");
44320                                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44321                                                                                                 "request-header:\n",
44322                                                                                                 con->request.request);
44323                                                                         }
44324 +                                                                       ds->free((data_unset *) ds);
44325                                                                         return 0;
44326                                                                 }
44327                                                         } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Expect")))) {
44328 -                                                               /* HTTP 2616 8.2.3 
44329 +                                                               /* HTTP 2616 8.2.3
44330                                                                  * Expect: 100-continue
44331 -                                                                * 
44332 +                                                                *
44333                                                                  *   -> (10.1.1)  100 (read content, process request, send final status-code)
44334                                                                  *   -> (10.4.18) 417 (close)
44335 -                                                                * 
44336 +                                                                *
44337                                                                  * (not handled at all yet, we always send 417 here)
44338                                                                  *
44339                                                                  * What has to be added ?
44340 @@ -863,10 +867,10 @@
44341                                                                  *    header
44342                                                                  *
44343                                                                  */
44344 -                                                               
44345 +
44346                                                                 con->http_status = 417;
44347                                                                 con->keep_alive = 0;
44348 -                                                               
44349 +
44350                                                                 array_insert_unique(con->request.headers, (data_unset *)ds);
44351                                                                 return 0;
44352                                                         } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Host")))) {
44353 @@ -875,14 +879,15 @@
44354                                                                 } else {
44355                                                                         con->http_status = 400;
44356                                                                         con->keep_alive = 0;
44357 -                                                                       
44358 +
44359                                                                         if (srv->srvconf.log_request_header_on_error) {
44360 -                                                                               log_error_write(srv, __FILE__, __LINE__, "s", 
44361 +                                                                               log_error_write(srv, __FILE__, __LINE__, "s",
44362                                                                                                 "duplicate Host-header -> 400");
44363                                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44364                                                                                                 "request-header:\n",
44365                                                                                                 con->request.request);
44366                                                                         }
44367 +                                                                       ds->free((data_unset *) ds);
44368                                                                         return 0;
44369                                                                 }
44370                                                         } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-Modified-Since")))) {
44371 @@ -897,14 +902,15 @@
44372                                                                 } else {
44373                                                                         con->http_status = 400;
44374                                                                         con->keep_alive = 0;
44375 -                                                                       
44376 +
44377                                                                         if (srv->srvconf.log_request_header_on_error) {
44378 -                                                                               log_error_write(srv, __FILE__, __LINE__, "s", 
44379 +                                                                               log_error_write(srv, __FILE__, __LINE__, "s",
44380                                                                                                 "duplicate If-Modified-Since header -> 400");
44381                                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44382                                                                                                 "request-header:\n",
44383                                                                                                 con->request.request);
44384                                                                         }
44385 +                                                                       ds->free((data_unset *) ds);
44386                                                                         return 0;
44387                                                                 }
44388                                                         } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-None-Match")))) {
44389 @@ -914,47 +920,49 @@
44390                                                                 } else {
44391                                                                         con->http_status = 400;
44392                                                                         con->keep_alive = 0;
44393 -                                                                       
44394 +
44395                                                                         if (srv->srvconf.log_request_header_on_error) {
44396 -                                                                               log_error_write(srv, __FILE__, __LINE__, "s", 
44397 +                                                                               log_error_write(srv, __FILE__, __LINE__, "s",
44398                                                                                                 "duplicate If-None-Match-header -> 400");
44399                                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44400                                                                                                 "request-header:\n",
44401                                                                                                 con->request.request);
44402                                                                         }
44403 +                                                                       ds->free((data_unset *) ds);
44404                                                                         return 0;
44405                                                                 }
44406                                                         } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Range")))) {
44407                                                                 if (!con->request.http_range) {
44408                                                                         /* bytes=.*-.* */
44409 -                                                               
44410 +
44411                                                                         if (0 == strncasecmp(ds->value->ptr, "bytes=", 6) &&
44412                                                                             NULL != strchr(ds->value->ptr+6, '-')) {
44413 -                                                                               
44414 +
44415                                                                                 /* if dup, only the first one will survive */
44416                                                                                 con->request.http_range = ds->value->ptr + 6;
44417                                                                         }
44418                                                                 } else {
44419                                                                         con->http_status = 400;
44420                                                                         con->keep_alive = 0;
44421 -                                                                       
44422 +
44423                                                                         if (srv->srvconf.log_request_header_on_error) {
44424 -                                                                               log_error_write(srv, __FILE__, __LINE__, "s", 
44425 +                                                                               log_error_write(srv, __FILE__, __LINE__, "s",
44426                                                                                                 "duplicate Range-header -> 400");
44427                                                                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44428                                                                                                 "request-header:\n",
44429                                                                                                 con->request.request);
44430                                                                         }
44431 +                                                                       ds->free((data_unset *) ds);
44432                                                                         return 0;
44433                                                                 }
44434                                                         }
44435 -                                                       
44436 +
44437                                                         array_insert_unique(con->request.headers, (data_unset *)ds);
44438                                                 } else {
44439                                                         /* empty header-fields are not allowed by HTTP-RFC, we just ignore them */
44440                                                 }
44441                                         }
44442 -                                       
44443 +
44444                                         i++;
44445                                         first = i+1;
44446                                         is_key = 1;
44447 @@ -963,10 +971,10 @@
44448                                         in_folding = 0;
44449                                 } else {
44450                                         if (srv->srvconf.log_request_header_on_error) {
44451 -                                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
44452 +                                               log_error_write(srv, __FILE__, __LINE__, "sbs",
44453                                                                 "CR without LF", con->request.request, "-> 400");
44454                                         }
44455 -                                       
44456 +
44457                                         con->http_status = 400;
44458                                         con->keep_alive = 0;
44459                                         con->response.keep_alive = 0;
44460 @@ -982,28 +990,28 @@
44461                         }
44462                 }
44463         }
44464 -       
44465 +
44466         con->header_len = i;
44467 -       
44468 +
44469         /* do some post-processing */
44470  
44471         if (con->request.http_version == HTTP_VERSION_1_1) {
44472                 if (keep_alive_set != HTTP_CONNECTION_CLOSE) {
44473                         /* no Connection-Header sent */
44474 -                       
44475 +
44476                         /* HTTP/1.1 -> keep-alive default TRUE */
44477                         con->keep_alive = 1;
44478                 } else {
44479                         con->keep_alive = 0;
44480                 }
44481 -               
44482 +
44483                 /* RFC 2616, 14.23 */
44484                 if (con->request.http_host == NULL ||
44485                     buffer_is_empty(con->request.http_host)) {
44486                         con->http_status = 400;
44487                         con->response.keep_alive = 0;
44488                         con->keep_alive = 0;
44489 -                       
44490 +
44491                         if (srv->srvconf.log_request_header_on_error) {
44492                                 log_error_write(srv, __FILE__, __LINE__, "s", "HTTP/1.1 but Host missing -> 400");
44493                                 log_error_write(srv, __FILE__, __LINE__, "Sb",
44494 @@ -1015,18 +1023,18 @@
44495         } else {
44496                 if (keep_alive_set == HTTP_CONNECTION_KEEPALIVE) {
44497                         /* no Connection-Header sent */
44498 -                       
44499 +
44500                         /* HTTP/1.0 -> keep-alive default FALSE  */
44501                         con->keep_alive = 1;
44502                 } else {
44503                         con->keep_alive = 0;
44504                 }
44505         }
44506 -       
44507 +
44508         /* check hostname field if it is set */
44509         if (NULL != con->request.http_host &&
44510             0 != request_check_hostname(srv, con, con->request.http_host)) {
44511 -               
44512 +
44513                 if (srv->srvconf.log_request_header_on_error) {
44514                         log_error_write(srv, __FILE__, __LINE__, "s",
44515                                         "Invalid Hostname -> 400");
44516 @@ -1038,7 +1046,7 @@
44517                 con->http_status = 400;
44518                 con->response.keep_alive = 0;
44519                 con->keep_alive = 0;
44520 -               
44521 +
44522                 return 0;
44523         }
44524  
44525 @@ -1048,7 +1056,7 @@
44526                 /* content-length is forbidden for those */
44527                 if (con_length_set && con->request.content_length != 0) {
44528                         /* content-length is missing */
44529 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
44530 +                       log_error_write(srv, __FILE__, __LINE__, "s",
44531                                         "GET/HEAD with content-length -> 400");
44532  
44533                         con->keep_alive = 0;
44534 @@ -1060,7 +1068,7 @@
44535                 /* content-length is required for them */
44536                 if (!con_length_set) {
44537                         /* content-length is missing */
44538 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
44539 +                       log_error_write(srv, __FILE__, __LINE__, "s",
44540                                         "POST-request, but content-length missing -> 411");
44541  
44542                         con->keep_alive = 0;
44543 @@ -1073,16 +1081,16 @@
44544                 /* the may have a content-length */
44545                 break;
44546         }
44547 -                       
44548 -       
44549 +
44550 +
44551         /* check if we have read post data */
44552         if (con_length_set) {
44553                 /* don't handle more the SSIZE_MAX bytes in content-length */
44554                 if (con->request.content_length > SSIZE_MAX) {
44555 -                       con->http_status = 413; 
44556 +                       con->http_status = 413;
44557                         con->keep_alive = 0;
44558  
44559 -                       log_error_write(srv, __FILE__, __LINE__, "sds", 
44560 +                       log_error_write(srv, __FILE__, __LINE__, "sds",
44561                                         "request-size too long:", con->request.content_length, "-> 413");
44562                         return 0;
44563                 }
44564 @@ -1090,25 +1098,25 @@
44565                 /* divide by 1024 as srvconf.max_request_size is in kBytes */
44566                 if (srv->srvconf.max_request_size != 0 &&
44567                     (con->request.content_length >> 10) > srv->srvconf.max_request_size) {
44568 -                       /* the request body itself is larger then 
44569 +                       /* the request body itself is larger then
44570                          * our our max_request_size
44571                          */
44572 -               
44573 +
44574                         con->http_status = 413;
44575                         con->keep_alive = 0;
44576 -               
44577 -                       log_error_write(srv, __FILE__, __LINE__, "sds", 
44578 +
44579 +                       log_error_write(srv, __FILE__, __LINE__, "sds",
44580                                         "request-size too long:", con->request.content_length, "-> 413");
44581                         return 0;
44582                 }
44583 -               
44584 -               
44585 +
44586 +
44587                 /* we have content */
44588                 if (con->request.content_length != 0) {
44589                         return 1;
44590                 }
44591         }
44592 -       
44593 +
44594         return 0;
44595  }
44596  
44597 @@ -1116,9 +1124,9 @@
44598         UNUSED(srv);
44599  
44600         if (con->request.request->used < 5) return 0;
44601 -       
44602 +
44603         if (0 == memcmp(con->request.request->ptr + con->request.request->used - 5, "\r\n\r\n", 4)) return 1;
44604         if (NULL != strstr(con->request.request->ptr, "\r\n\r\n")) return 1;
44605 -       
44606 +
44607         return 0;
44608  }
44609 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/response.c lighttpd-1.4.12/src/response.c
44610 --- lighttpd-1.4.11/src/response.c      2006-03-04 16:41:39.000000000 +0200
44611 +++ lighttpd-1.4.12/src/response.c      2006-07-11 21:23:40.000000000 +0300
44612 @@ -7,7 +7,6 @@
44613  #include <stdlib.h>
44614  #include <string.h>
44615  #include <time.h>
44616 -#include <unistd.h>
44617  #include <ctype.h>
44618  #include <assert.h>
44619  
44620 @@ -24,15 +23,17 @@
44621  #include "plugin.h"
44622  
44623  #include "sys-socket.h"
44624 +#include "sys-files.h"
44625 +#include "sys-strings.h"
44626  
44627  int http_response_write_header(server *srv, connection *con) {
44628         buffer *b;
44629         size_t i;
44630         int have_date = 0;
44631         int have_server = 0;
44632 -       
44633 +
44634         b = chunkqueue_get_prepend_buffer(con->write_queue);
44635 -       
44636 +
44637         if (con->request.http_version == HTTP_VERSION_1_1) {
44638                 BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
44639         } else {
44640 @@ -41,25 +42,26 @@
44641         buffer_append_long(b, con->http_status);
44642         BUFFER_APPEND_STRING_CONST(b, " ");
44643         buffer_append_string(b, get_http_status_name(con->http_status));
44644 -       
44645 +
44646         if (con->request.http_version != HTTP_VERSION_1_1 || con->keep_alive == 0) {
44647                 BUFFER_APPEND_STRING_CONST(b, "\r\nConnection: ");
44648                 buffer_append_string(b, con->keep_alive ? "keep-alive" : "close");
44649         }
44650 -       
44651 +
44652         if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
44653                 BUFFER_APPEND_STRING_CONST(b, "\r\nTransfer-Encoding: chunked");
44654         }
44655 -       
44656 -       
44657 +
44658 +
44659         /* add all headers */
44660         for (i = 0; i < con->response.headers->used; i++) {
44661                 data_string *ds;
44662 -               
44663 +
44664                 ds = (data_string *)con->response.headers->data[i];
44665 -               
44666 +
44667                 if (ds->value->used && ds->key->used &&
44668 -                   0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1)) {
44669 +                   0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1) &&
44670 +                   0 != strcasecmp(ds->key->ptr, "X-Sendfile")) {
44671                         if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Date"))) have_date = 1;
44672                         if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Server"))) have_server = 1;
44673  
44674 @@ -68,28 +70,28 @@
44675                         BUFFER_APPEND_STRING_CONST(b, ": ");
44676                         buffer_append_string_buffer(b, ds->value);
44677  #if 0
44678 -                       log_error_write(srv, __FILE__, __LINE__, "bb", 
44679 +                       log_error_write(srv, __FILE__, __LINE__, "bb",
44680                                         ds->key, ds->value);
44681  #endif
44682                 }
44683         }
44684 -       
44685 +
44686         if (!have_date) {
44687                 /* HTTP/1.1 requires a Date: header */
44688                 BUFFER_APPEND_STRING_CONST(b, "\r\nDate: ");
44689 -       
44690 +
44691                 /* cache the generated timestamp */
44692                 if (srv->cur_ts != srv->last_generated_date_ts) {
44693                         buffer_prepare_copy(srv->ts_date_str, 255);
44694 -               
44695 -                       strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1, 
44696 +
44697 +                       strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1,
44698                                  "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(srv->cur_ts)));
44699 -                        
44700 +
44701                         srv->ts_date_str->used = strlen(srv->ts_date_str->ptr) + 1;
44702 -               
44703 +
44704                         srv->last_generated_date_ts = srv->cur_ts;
44705                 }
44706 -       
44707 +
44708                 buffer_append_string_buffer(b, srv->ts_date_str);
44709         }
44710  
44711 @@ -101,16 +103,16 @@
44712                         buffer_append_string_buffer(b, con->conf.server_tag);
44713                 }
44714         }
44715 -       
44716 +
44717         BUFFER_APPEND_STRING_CONST(b, "\r\n\r\n");
44718 -       
44719 -       
44720 +
44721 +
44722         con->bytes_header = b->used - 1;
44723 -       
44724 +
44725         if (con->conf.log_response_header) {
44726                 log_error_write(srv, __FILE__, __LINE__, "sSb", "Response-Header:", "\n", b);
44727         }
44728 -       
44729 +
44730         return 0;
44731  }
44732  
44733 @@ -118,71 +120,71 @@
44734  
44735  handler_t http_response_prepare(server *srv, connection *con) {
44736         handler_t r;
44737 -       
44738 -       /* looks like someone has already done a decision */
44739 -       if (con->mode == DIRECT && 
44740 +
44741 +       /* looks like someone has already made a decision */
44742 +       if (con->mode == DIRECT &&
44743             (con->http_status != 0 && con->http_status != 200)) {
44744                 /* remove a packets in the queue */
44745                 if (con->file_finished == 0) {
44746                         chunkqueue_reset(con->write_queue);
44747                 }
44748 -               
44749 +
44750                 return HANDLER_FINISHED;
44751         }
44752 -       
44753 +
44754         /* no decision yet, build conf->filename */
44755         if (con->mode == DIRECT && con->physical.path->used == 0) {
44756                 char *qstr;
44757  
44758 -               /* we only come here when we have the parse the full request again
44759 -                * 
44760 -                * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a 
44761 +               /* we only come here when we have to parse the full request again
44762 +                *
44763 +                * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
44764                  * problem here as mod_setenv might get called multiple times
44765                  *
44766                  * fastcgi-auth might lead to a COMEBACK too
44767                  * fastcgi again dead server too
44768                  *
44769                  * mod_compress might add headers twice too
44770 -                * 
44771 +                *
44772                  *  */
44773 -               
44774 +
44775                 if (con->conf.log_condition_handling) {
44776                         log_error_write(srv, __FILE__, __LINE__,  "s",  "run condition");
44777                 }
44778                 config_patch_connection(srv, con, COMP_SERVER_SOCKET); /* SERVERsocket */
44779 -               
44780 +
44781                 /**
44782                  * prepare strings
44783 -                * 
44784 -                * - uri.path_raw 
44785 +                *
44786 +                * - uri.path_raw
44787                  * - uri.path (secure)
44788                  * - uri.query
44789 -                * 
44790 +                *
44791                  */
44792 -               
44793 -               /** 
44794 +
44795 +               /**
44796                  * Name according to RFC 2396
44797 -                * 
44798 +                *
44799                  * - scheme
44800                  * - authority
44801                  * - path
44802                  * - query
44803 -                * 
44804 +                *
44805                  * (scheme)://(authority)(path)?(query)
44806 -                * 
44807 -                * 
44808 +                *
44809 +                *
44810                  */
44811 -       
44812 +
44813                 buffer_copy_string(con->uri.scheme, con->conf.is_ssl ? "https" : "http");
44814                 buffer_copy_string_buffer(con->uri.authority, con->request.http_host);
44815                 buffer_to_lower(con->uri.authority);
44816 -               
44817 +
44818                 config_patch_connection(srv, con, COMP_HTTP_HOST);      /* Host:        */
44819                 config_patch_connection(srv, con, COMP_HTTP_REMOTEIP);  /* Client-IP */
44820                 config_patch_connection(srv, con, COMP_HTTP_REFERER);   /* Referer:     */
44821                 config_patch_connection(srv, con, COMP_HTTP_USERAGENT); /* User-Agent:  */
44822                 config_patch_connection(srv, con, COMP_HTTP_COOKIE);    /* Cookie:  */
44823 -               
44824 +
44825                 /** extract query string from request.uri */
44826                 if (NULL != (qstr = strchr(con->request.uri->ptr, '?'))) {
44827                         buffer_copy_string    (con->uri.query, qstr + 1);
44828 @@ -200,22 +202,22 @@
44829                         log_error_write(srv, __FILE__, __LINE__,  "sb", "URI-path     : ", con->uri.path_raw);
44830                         log_error_write(srv, __FILE__, __LINE__,  "sb", "URI-query    : ", con->uri.query);
44831                 }
44832 -               
44833 +
44834                 /* disable keep-alive if requested */
44835 -               
44836 +
44837                 if (con->request_count > con->conf.max_keep_alive_requests) {
44838                         con->keep_alive = 0;
44839                 }
44840 -               
44841 -               
44842 +
44843 +
44844                 /**
44845 -                *  
44846 -                * call plugins 
44847 -                * 
44848 +                *
44849 +                * call plugins
44850 +                *
44851                  * - based on the raw URL
44852 -                * 
44853 +                *
44854                  */
44855 -               
44856 +
44857                 switch(r = plugins_call_handle_uri_raw(srv, con)) {
44858                 case HANDLER_GO_ON:
44859                         break;
44860 @@ -229,14 +231,14 @@
44861                         break;
44862                 }
44863  
44864 -               /* build filename 
44865 +               /* build filename
44866                  *
44867                  * - decode url-encodings  (e.g. %20 -> ' ')
44868                  * - remove path-modifiers (e.g. /../)
44869                  */
44870 -               
44871 -               
44872 -               
44873 +
44874 +
44875 +
44876                 if (con->request.http_method == HTTP_METHOD_OPTIONS &&
44877                     con->uri.path_raw->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
44878                         /* OPTIONS * ... */
44879 @@ -253,15 +255,20 @@
44880                 }
44881  
44882                 /**
44883 -                *  
44884 -                * call plugins 
44885 -                * 
44886 +                *
44887 +                * call plugins
44888 +                *
44889                  * - based on the clean URL
44890 -                * 
44891 +                *
44892                  */
44893 -               
44894 +
44895                 config_patch_connection(srv, con, COMP_HTTP_URL); /* HTTPurl */
44896 -               
44897 +
44898 +               /* do we have to downgrade to 1.0 ? */
44899 +               if (!con->conf.allow_http11) {
44900 +                       con->request.http_version = HTTP_VERSION_1_0;
44901 +               }
44902 +
44903                 switch(r = plugins_call_handle_uri_clean(srv, con)) {
44904                 case HANDLER_GO_ON:
44905                         break;
44906 @@ -274,11 +281,11 @@
44907                         log_error_write(srv, __FILE__, __LINE__, "");
44908                         break;
44909                 }
44910 -               
44911 +
44912                 if (con->request.http_method == HTTP_METHOD_OPTIONS &&
44913                     con->uri.path->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
44914 -                       /* option requests are handled directly without checking of the path */
44915 -               
44916 +                       /* option requests are handled directly without checking the path */
44917 +
44918                         response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
44919  
44920                         con->http_status = 200;
44921 @@ -288,46 +295,47 @@
44922                 }
44923  
44924                 /***
44925 -                * 
44926 -                * border 
44927 -                * 
44928 +                *
44929 +                * border
44930 +                *
44931                  * logical filename (URI) becomes a physical filename here
44932 -                * 
44933 -                * 
44934 -                * 
44935 +                *
44936 +                *
44937 +                *
44938                  */
44939 -               
44940 -               
44941 -               
44942 -               
44943 +
44944 +
44945 +
44946 +
44947                 /* 1. stat()
44948                  * ... ISREG() -> ok, go on
44949                  * ... ISDIR() -> index-file -> redirect
44950 -                * 
44951 -                * 2. pathinfo() 
44952 +                *
44953 +                * 2. pathinfo()
44954                  * ... ISREG()
44955 -                * 
44956 +                *
44957                  * 3. -> 404
44958 -                * 
44959 +                *
44960                  */
44961 -               
44962 +
44963                 /*
44964                  * SEARCH DOCUMENT ROOT
44965                  */
44966 -               
44967 +
44968                 /* set a default */
44969 -               
44970 +
44971                 buffer_copy_string_buffer(con->physical.doc_root, con->conf.document_root);
44972                 buffer_copy_string_buffer(con->physical.rel_path, con->uri.path);
44973 -               
44974 -#if defined(__WIN32) || defined(__CYGWIN__)
44975 -               /* strip dots from the end and spaces
44976 +
44977 +               filename_unix2local(con->physical.rel_path);
44978 +#if defined(_WIN32) || defined(__CYGWIN__)
44979 +               /* strip dots and spaces from the end
44980                  *
44981                  * windows/dos handle those filenames as the same file
44982                  *
44983                  * foo == foo. == foo..... == "foo...   " == "foo..  ./"
44984                  *
44985 -                * This will affect in some cases PATHINFO
44986 +                * This will affect PATHINFO in some cases
44987                  *
44988                  * on native windows we could prepend the filename with \\?\ to circumvent
44989                  * this behaviour. I have no idea how to push this through cygwin
44990 @@ -377,36 +385,41 @@
44991                         log_error_write(srv, __FILE__, __LINE__, "");
44992                         break;
44993                 }
44994 -               
44995 -               /* MacOS X and Windows can't distiguish between upper and lower-case 
44996 -                * 
44997 -                * convert to lower-case
44998 +
44999 +               /* The default Mac OS X and Windows filesystems can't distiguish between
45000 +                * upper- and lowercase, so convert to lowercase
45001                  */
45002                 if (con->conf.force_lowercase_filenames) {
45003                         buffer_to_lower(con->physical.rel_path);
45004                 }
45005  
45006 -               /* the docroot plugins might set the servername, if they don't we take http-host */
45007 +               /* the docroot plugins might set the servername; if they don't we take http-host */
45008                 if (buffer_is_empty(con->server_name)) {
45009                         buffer_copy_string_buffer(con->server_name, con->uri.authority);
45010                 }
45011 -               
45012 -               /** 
45013 -                * create physical filename 
45014 +
45015 +               /**
45016 +                * create physical filename
45017                  * -> physical.path = docroot + rel_path
45018 -                * 
45019 +                *
45020                  */
45021 -               
45022 +
45023                 buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
45024 -               BUFFER_APPEND_SLASH(con->physical.path);
45025 +               PATHNAME_APPEND_SLASH(con->physical.path);
45026                 buffer_copy_string_buffer(con->physical.basedir, con->physical.path);
45027                 if (con->physical.rel_path->used &&
45028 -                   con->physical.rel_path->ptr[0] == '/') {
45029 +                   con->physical.rel_path->ptr[0] == DIR_SEPERATOR) {
45030                         buffer_append_string_len(con->physical.path, con->physical.rel_path->ptr + 1, con->physical.rel_path->used - 2);
45031                 } else {
45032                         buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
45033                 }
45034  
45035 +        /* win32: directories can't have a trailing slash */
45036 +        if (con->physical.path->ptr[con->physical.path->used - 2] == DIR_SEPERATOR) {
45037 +            con->physical.path->ptr[con->physical.path->used - 2] = '\0';
45038 +            con->physical.path->used--;
45039 +        }
45040 +
45041                 if (con->conf.log_request_handling) {
45042                         log_error_write(srv, __FILE__, __LINE__,  "s",  "-- after doc_root");
45043                         log_error_write(srv, __FILE__, __LINE__,  "sb", "Doc-Root     :", con->physical.doc_root);
45044 @@ -426,7 +439,7 @@
45045                         log_error_write(srv, __FILE__, __LINE__, "");
45046                         break;
45047                 }
45048 -               
45049 +
45050                 if (con->conf.log_request_handling) {
45051                         log_error_write(srv, __FILE__, __LINE__,  "s",  "-- logical -> physical");
45052                         log_error_write(srv, __FILE__, __LINE__,  "sb", "Doc-Root     :", con->physical.doc_root);
45053 @@ -434,38 +447,38 @@
45054                         log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
45055                 }
45056         }
45057 -       
45058 -       /* 
45059 -        * Noone catched away the file from normal path of execution yet (like mod_access)
45060 -        * 
45061 +
45062 +       /*
45063 +        * No one took the file away from the normal path of execution yet (like mod_access)
45064 +        *
45065          * Go on and check of the file exists at all
45066          */
45067 -       
45068 +
45069         if (con->mode == DIRECT) {
45070                 char *slash = NULL;
45071                 char *pathinfo = NULL;
45072                 int found = 0;
45073                 stat_cache_entry *sce = NULL;
45074 -               
45075 +
45076                 if (con->conf.log_request_handling) {
45077                         log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling physical path");
45078                         log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
45079                 }
45080 -               
45081 +
45082                 if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
45083                         /* file exists */
45084 -                       
45085 +
45086                         if (con->conf.log_request_handling) {
45087                                 log_error_write(srv, __FILE__, __LINE__,  "s",  "-- file found");
45088                                 log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
45089                         }
45090 -                       
45091 +
45092                         if (S_ISDIR(sce->st.st_mode)) {
45093 -                               if (con->physical.path->ptr[con->physical.path->used - 2] != '/') {
45094 +                               if (con->uri.path->ptr[con->uri.path->used - 2] != '/') {
45095                                         /* redirect to .../ */
45096 -                                       
45097 +
45098                                         http_response_redirect_to_directory(srv, con);
45099 -                                       
45100 +
45101                                         return HANDLER_FINISHED;
45102                                 }
45103                         } else if (!S_ISREG(sce->st.st_mode)) {
45104 @@ -477,12 +490,12 @@
45105                         switch (errno) {
45106                         case EACCES:
45107                                 con->http_status = 403;
45108 -       
45109 +
45110                                 if (con->conf.log_request_handling) {
45111                                         log_error_write(srv, __FILE__, __LINE__,  "s",  "-- access denied");
45112                                         log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
45113                                 }
45114 -                       
45115 +
45116                                 buffer_reset(con->physical.path);
45117                                 return HANDLER_FINISHED;
45118                         case ENOENT:
45119 @@ -499,77 +512,77 @@
45120                                 /* PATH_INFO ! :) */
45121                                 break;
45122                         default:
45123 -                               /* we have no idea what happend. let's tell the user so. */
45124 +                               /* we have no idea what happened, so tell the user. */
45125                                 con->http_status = 500;
45126                                 buffer_reset(con->physical.path);
45127 -                               
45128 +
45129                                 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
45130                                                 "file not found ... or so: ", strerror(errno),
45131                                                 con->uri.path,
45132                                                 "->", con->physical.path);
45133 -                               
45134 +
45135                                 return HANDLER_FINISHED;
45136                         }
45137 -                       
45138 +
45139                         /* not found, perhaps PATHINFO */
45140 -                       
45141 +
45142                         buffer_copy_string_buffer(srv->tmp_buf, con->physical.path);
45143 -                       
45144 +
45145                         do {
45146                                 struct stat st;
45147 -                               
45148 +
45149                                 if (slash) {
45150                                         buffer_copy_string_len(con->physical.path, srv->tmp_buf->ptr, slash - srv->tmp_buf->ptr);
45151                                 } else {
45152                                         buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
45153                                 }
45154 -                               
45155 +
45156                                 if (0 == stat(con->physical.path->ptr, &(st)) &&
45157                                     S_ISREG(st.st_mode)) {
45158                                         found = 1;
45159                                         break;
45160                                 }
45161 -                               
45162 +
45163                                 if (pathinfo != NULL) {
45164                                         *pathinfo = '\0';
45165                                 }
45166                                 slash = strrchr(srv->tmp_buf->ptr, '/');
45167 -                               
45168 +
45169                                 if (pathinfo != NULL) {
45170                                         /* restore '/' */
45171                                         *pathinfo = '/';
45172                                 }
45173 -                               
45174 +
45175                                 if (slash) pathinfo = slash;
45176                         } while ((found == 0) && (slash != NULL) && (slash - srv->tmp_buf->ptr > con->physical.basedir->used - 2));
45177 -                       
45178 +
45179                         if (found == 0) {
45180 -                               /* no it really doesn't exists */
45181 +                               /* no, it really doesn't exists */
45182                                 con->http_status = 404;
45183 -                               
45184 +
45185                                 if (con->conf.log_file_not_found) {
45186                                         log_error_write(srv, __FILE__, __LINE__, "sbsb",
45187                                                         "file not found:", con->uri.path,
45188                                                         "->", con->physical.path);
45189                                 }
45190 -                               
45191 +
45192                                 buffer_reset(con->physical.path);
45193 -                               
45194 +
45195                                 return HANDLER_FINISHED;
45196                         }
45197 -                       
45198 +
45199                         /* we have a PATHINFO */
45200                         if (pathinfo) {
45201                                 buffer_copy_string(con->request.pathinfo, pathinfo);
45202 -                               
45203 +
45204                                 /*
45205                                  * shorten uri.path
45206                                  */
45207 -                               
45208 +
45209                                 con->uri.path->used -= strlen(pathinfo);
45210                                 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
45211                         }
45212 -                       
45213 +
45214                         if (con->conf.log_request_handling) {
45215                                 log_error_write(srv, __FILE__, __LINE__,  "s",  "-- after pathinfo check");
45216                                 log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
45217 @@ -577,12 +590,12 @@
45218                                 log_error_write(srv, __FILE__, __LINE__,  "sb", "Pathinfo     :", con->request.pathinfo);
45219                         }
45220                 }
45221 -               
45222 +
45223                 if (con->conf.log_request_handling) {
45224                         log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling subrequest");
45225                         log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
45226                 }
45227 -               
45228 +
45229                 /* call the handlers */
45230                 switch(r = plugins_call_handle_subrequest_start(srv, con)) {
45231                 case HANDLER_GO_ON:
45232 @@ -593,32 +606,32 @@
45233                         if (con->conf.log_request_handling) {
45234                                 log_error_write(srv, __FILE__, __LINE__,  "s",  "-- subrequest finished");
45235                         }
45236 -                       
45237 -                       /* something strange happend */
45238 +
45239 +                       /* something strange happened */
45240                         return r;
45241                 }
45242 -               
45243 -               /* if we are still here, no one wanted the file, status 403 is ok I think */
45244 -               
45245 +
45246 +               /* if we are still here, no one wanted the file; status 403 is ok I think */
45247 +
45248                 if (con->mode == DIRECT) {
45249                         con->http_status = 403;
45250 -                       
45251 +
45252                         return HANDLER_FINISHED;
45253                 }
45254 -               
45255 +
45256         }
45257 -       
45258 +
45259         switch(r = plugins_call_handle_subrequest(srv, con)) {
45260         case HANDLER_GO_ON:
45261 -               /* request was not handled, looks like we are done */
45262 +               /* request was not handled; looks like we are done */
45263                 return HANDLER_FINISHED;
45264         case HANDLER_FINISHED:
45265                 /* request is finished */
45266         default:
45267 -               /* something strange happend */
45268 +               /* something strange happened */
45269                 return r;
45270         }
45271 -       
45272 +
45273         /* can't happen */
45274         return HANDLER_COMEBACK;
45275  }
45276 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/server.c lighttpd-1.4.12/src/server.c
45277 --- lighttpd-1.4.11/src/server.c        2006-03-04 19:12:17.000000000 +0200
45278 +++ lighttpd-1.4.12/src/server.c        2006-07-11 21:23:40.000000000 +0300
45279 @@ -1,11 +1,9 @@
45280  #include <sys/types.h>
45281 -#include <sys/time.h>
45282  #include <sys/stat.h>
45283  
45284  #include <string.h>
45285  #include <errno.h>
45286  #include <fcntl.h>
45287 -#include <unistd.h>
45288  #include <stdlib.h>
45289  #include <time.h>
45290  #include <signal.h>
45291 @@ -29,9 +27,14 @@
45292  #include "plugin.h"
45293  #include "joblist.h"
45294  #include "network_backends.h"
45295 -
45296 +#ifdef _WIN32
45297 +/* use local getopt implementation */
45298 +# undef HAVE_GETOPT_H
45299 +#endif
45300  #ifdef HAVE_GETOPT_H
45301  #include <getopt.h>
45302 +#else
45303 +#include "getopt.h"
45304  #endif
45305  
45306  #ifdef HAVE_VALGRIND_VALGRIND_H
45307 @@ -60,8 +63,16 @@
45308  /* #define USE_ALARM */
45309  #endif
45310  
45311 +#ifdef _WIN32
45312 +#undef HAVE_SIGNAL
45313 +#endif
45314 +
45315 +#include "sys-files.h"
45316 +#include "sys-process.h"
45317 +
45318  static volatile sig_atomic_t srv_shutdown = 0;
45319  static volatile sig_atomic_t graceful_shutdown = 0;
45320 +static volatile sig_atomic_t graceful_restart = 0;
45321  static volatile sig_atomic_t handle_sig_alarm = 1;
45322  static volatile sig_atomic_t handle_sig_hup = 0;
45323  
45324 @@ -72,9 +83,9 @@
45325  
45326         switch (sig) {
45327         case SIGTERM: srv_shutdown = 1; break;
45328 -       case SIGINT: 
45329 +       case SIGINT:
45330              if (graceful_shutdown) srv_shutdown = 1;
45331 -            else graceful_shutdown = 1; 
45332 +            else graceful_shutdown = 1;
45333  
45334              break;
45335         case SIGALRM: handle_sig_alarm = 1; break;
45336 @@ -86,9 +97,9 @@
45337  static void signal_handler(int sig) {
45338         switch (sig) {
45339         case SIGTERM: srv_shutdown = 1; break;
45340 -       case SIGINT: 
45341 +       case SIGINT:
45342              if (graceful_shutdown) srv_shutdown = 1;
45343 -            else graceful_shutdown = 1; 
45344 +            else graceful_shutdown = 1;
45345  
45346              break;
45347         case SIGALRM: handle_sig_alarm = 1; break;
45348 @@ -110,25 +121,26 @@
45349         signal(SIGTSTP, SIG_IGN);
45350  #endif
45351         if (0 != fork()) exit(0);
45352 -       
45353 +
45354         if (-1 == setsid()) exit(0);
45355  
45356         signal(SIGHUP, SIG_IGN);
45357  
45358         if (0 != fork()) exit(0);
45359 -       
45360 +
45361         if (0 != chdir("/")) exit(0);
45362  }
45363  #endif
45364  
45365  static server *server_init(void) {
45366         int i;
45367 -       
45368 +
45369         server *srv = calloc(1, sizeof(*srv));
45370         assert(srv);
45371 +    srv->max_fds = 1024;
45372  #define CLEAN(x) \
45373         srv->x = buffer_init();
45374 -       
45375 +
45376         CLEAN(response_header);
45377         CLEAN(parse_full_path);
45378         CLEAN(ts_debug_str);
45379 @@ -138,7 +150,7 @@
45380         CLEAN(tmp_buf);
45381         srv->empty_string = buffer_init_string("");
45382         CLEAN(cond_check_buf);
45383 -       
45384 +
45385         CLEAN(srvconf.errorlog_file);
45386         CLEAN(srvconf.groupname);
45387         CLEAN(srvconf.username);
45388 @@ -146,58 +158,58 @@
45389         CLEAN(srvconf.bindhost);
45390         CLEAN(srvconf.event_handler);
45391         CLEAN(srvconf.pid_file);
45392 -       
45393 +
45394         CLEAN(tmp_chunk_len);
45395  #undef CLEAN
45396 -       
45397 +
45398  #define CLEAN(x) \
45399         srv->x = array_init();
45400 -       
45401 +
45402         CLEAN(config_context);
45403         CLEAN(config_touched);
45404         CLEAN(status);
45405  #undef CLEAN
45406 -       
45407 +
45408         for (i = 0; i < FILE_CACHE_MAX; i++) {
45409                 srv->mtime_cache[i].str = buffer_init();
45410         }
45411 -       
45412 +
45413         srv->cur_ts = time(NULL);
45414         srv->startup_ts = srv->cur_ts;
45415 -       
45416 +
45417         srv->conns = calloc(1, sizeof(*srv->conns));
45418         assert(srv->conns);
45419 -       
45420 +
45421         srv->joblist = calloc(1, sizeof(*srv->joblist));
45422         assert(srv->joblist);
45423 -       
45424 +
45425         srv->fdwaitqueue = calloc(1, sizeof(*srv->fdwaitqueue));
45426         assert(srv->fdwaitqueue);
45427 -       
45428 +
45429         srv->srvconf.modules = array_init();
45430         srv->srvconf.modules_dir = buffer_init_string(LIBRARY_DIR);
45431         srv->srvconf.network_backend = buffer_init();
45432         srv->srvconf.upload_tempdirs = array_init();
45433 -       
45434 +
45435         /* use syslog */
45436         srv->errorlog_fd = -1;
45437         srv->errorlog_mode = ERRORLOG_STDERR;
45438  
45439         srv->split_vals = array_init();
45440 -       
45441 +
45442         return srv;
45443  }
45444  
45445  static void server_free(server *srv) {
45446         size_t i;
45447 -       
45448 +
45449         for (i = 0; i < FILE_CACHE_MAX; i++) {
45450                 buffer_free(srv->mtime_cache[i].str);
45451         }
45452 -       
45453 +
45454  #define CLEAN(x) \
45455         buffer_free(srv->x);
45456 -       
45457 +
45458         CLEAN(response_header);
45459         CLEAN(parse_full_path);
45460         CLEAN(ts_debug_str);
45461 @@ -207,7 +219,7 @@
45462         CLEAN(tmp_buf);
45463         CLEAN(empty_string);
45464         CLEAN(cond_check_buf);
45465 -       
45466 +
45467         CLEAN(srvconf.errorlog_file);
45468         CLEAN(srvconf.groupname);
45469         CLEAN(srvconf.username);
45470 @@ -217,7 +229,7 @@
45471         CLEAN(srvconf.pid_file);
45472         CLEAN(srvconf.modules_dir);
45473         CLEAN(srvconf.network_backend);
45474 -       
45475 +
45476         CLEAN(tmp_chunk_len);
45477  #undef CLEAN
45478  
45479 @@ -225,15 +237,15 @@
45480         fdevent_unregister(srv->ev, srv->fd);
45481  #endif
45482         fdevent_free(srv->ev);
45483 -       
45484 +
45485         free(srv->conns);
45486 -       
45487 +
45488         if (srv->config_storage) {
45489                 for (i = 0; i < srv->config_context->used; i++) {
45490                         specific_config *s = srv->config_storage[i];
45491  
45492                         if (!s) continue;
45493 -                       
45494 +
45495                         buffer_free(s->document_root);
45496                         buffer_free(s->server_name);
45497                         buffer_free(s->server_tag);
45498 @@ -242,32 +254,32 @@
45499                         buffer_free(s->error_handler);
45500                         buffer_free(s->errorfile_prefix);
45501                         array_free(s->mimetypes);
45502 -                       
45503 +
45504                         free(s);
45505                 }
45506                 free(srv->config_storage);
45507                 srv->config_storage = NULL;
45508         }
45509 -       
45510 +
45511  #define CLEAN(x) \
45512         array_free(srv->x);
45513 -       
45514 +
45515         CLEAN(config_context);
45516         CLEAN(config_touched);
45517         CLEAN(status);
45518         CLEAN(srvconf.upload_tempdirs);
45519  #undef CLEAN
45520 -       
45521 +
45522         joblist_free(srv, srv->joblist);
45523         fdwaitqueue_free(srv, srv->fdwaitqueue);
45524 -       
45525 +
45526         if (srv->stat_cache) {
45527                 stat_cache_free(srv->stat_cache);
45528         }
45529  
45530         array_free(srv->srvconf.modules);
45531         array_free(srv->split_vals);
45532 -       
45533 +
45534         free(srv);
45535  }
45536  
45537 @@ -281,14 +293,12 @@
45538  " - a light and fast webserver\n" \
45539  "Build-Date: " __DATE__ " " __TIME__ "\n";
45540  ;
45541 -#undef TEXT_SSL        
45542 +#undef TEXT_SSL
45543         write(STDOUT_FILENO, b, strlen(b));
45544  }
45545  
45546  static void show_features (void) {
45547 -  show_version();
45548 -  printf("\nEvent Handlers:\n\n%s",
45549 -
45550 +  const char *s = ""
45551  #ifdef USE_SELECT
45552        "\t+ select (generic)\n"
45553  #else
45554 @@ -355,11 +365,6 @@
45555  #else
45556        "\t- crypt support\n"
45557  #endif
45558 -#ifdef USE_PAM
45559 -      "\t+ PAM support\n"
45560 -#else
45561 -      "\t- PAM support\n"
45562 -#endif
45563  #ifdef USE_OPENSSL
45564        "\t+ SSL Support\n"
45565  #else
45566 @@ -371,9 +376,9 @@
45567        "\t- PCRE support\n"
45568  #endif
45569  #ifdef HAVE_MYSQL
45570 -      "\t+ mySQL support\n"
45571 +      "\t+ MySQL support\n"
45572  #else
45573 -      "\t- mySQL support\n"
45574 +      "\t- MySQL support\n"
45575  #endif
45576  #if defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER)
45577        "\t+ LDAP support\n"
45578 @@ -410,8 +415,11 @@
45579  #else
45580        "\t- GDBM support\n"
45581  #endif
45582 -      "\n"
45583 -      );
45584 +      "\n";
45585 +
45586 +  show_version();
45587 +
45588 +  printf("\nEvent Handlers:\n\n%s", s);
45589  }
45590  
45591  static void show_help (void) {
45592 @@ -433,12 +441,12 @@
45593  " -h         show this help\n" \
45594  "\n"
45595  ;
45596 -#undef TEXT_SSL        
45597 +#undef TEXT_SSL
45598  #undef TEXT_IPV6
45599         write(STDOUT_FILENO, b, strlen(b));
45600  }
45601  
45602 -int main (int argc, char **argv) {
45603 +int main (int argc, char **argv, char **envp) {
45604         server *srv = NULL;
45605         int print_config = 0;
45606         int test_config = 0;
45607 @@ -447,33 +455,37 @@
45608         int num_childs = 0;
45609         int pid_fd = -1, fd;
45610         size_t i;
45611 +#ifdef _WIN32
45612 +       char *optarg = NULL;
45613 +#endif
45614 +
45615  #ifdef HAVE_SIGACTION
45616         struct sigaction act;
45617  #endif
45618  #ifdef HAVE_GETRLIMIT
45619         struct rlimit rlim;
45620  #endif
45621 -       
45622 +
45623  #ifdef USE_ALARM
45624         struct itimerval interval;
45625 -       
45626 +
45627         interval.it_interval.tv_sec = 1;
45628         interval.it_interval.tv_usec = 0;
45629         interval.it_value.tv_sec = 1;
45630         interval.it_value.tv_usec = 0;
45631  #endif
45632 -       
45633 -       
45634 +
45635 +
45636         /* for nice %b handling in strfime() */
45637         setlocale(LC_TIME, "C");
45638 -       
45639 +
45640         if (NULL == (srv = server_init())) {
45641                 fprintf(stderr, "did this really happen?\n");
45642                 return -1;
45643         }
45644 -       
45645 +
45646         /* init structs done */
45647 -       
45648 +
45649         srv->srvconf.port = 0;
45650  #ifdef HAVE_GETUID
45651         i_am_root = (getuid() == 0);
45652 @@ -481,14 +493,19 @@
45653         i_am_root = 0;
45654  #endif
45655         srv->srvconf.dont_daemonize = 0;
45656 -       
45657 +
45658         while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) {
45659                 switch(o) {
45660 -               case 'f': 
45661 -                       if (config_read(srv, optarg)) { 
45662 +               case 'f':
45663 +#ifdef _WIN32
45664 +                       /* evil HACK for windows, optarg is not set */
45665 +                       optarg = argv[optind-1];
45666 +#endif
45667 +                       if (config_read(srv, optarg)) {
45668                                 server_free(srv);
45669                                 return -1;
45670                         }
45671 +
45672                         break;
45673                 case 'm':
45674                         buffer_copy_string(srv->srvconf.modules_dir, optarg);
45675 @@ -497,23 +514,23 @@
45676                 case 't': test_config = 1; break;
45677                 case 'D': srv->srvconf.dont_daemonize = 1; break;
45678                 case 'v': show_version(); return 0;
45679 -               case 'V': show_features(); return 0;          
45680 +               case 'V': show_features(); return 0;
45681                 case 'h': show_help(); return 0;
45682 -               default: 
45683 +               default:
45684                         show_help();
45685                         server_free(srv);
45686                         return -1;
45687                 }
45688         }
45689 -       
45690 +
45691         if (!srv->config_storage) {
45692                 log_error_write(srv, __FILE__, __LINE__, "s",
45693                                 "No configuration available. Try using -f option.");
45694 -               
45695 +
45696                 server_free(srv);
45697                 return -1;
45698         }
45699 -       
45700 +
45701         if (print_config) {
45702                 data_unset *dc = srv->config_context->data[0];
45703                 if (dc) {
45704 @@ -533,7 +550,7 @@
45705                 server_free(srv);
45706                 return 0;
45707         }
45708 -       
45709 +
45710         /* close stdin and stdout, as they are not needed */
45711         /* move stdin to /dev/null */
45712         if (-1 != (fd = open("/dev/null", O_RDONLY))) {
45713 @@ -541,54 +558,55 @@
45714                 dup2(fd, STDIN_FILENO);
45715                 close(fd);
45716         }
45717 -       
45718 +
45719         /* move stdout to /dev/null */
45720         if (-1 != (fd = open("/dev/null", O_WRONLY))) {
45721                 close(STDOUT_FILENO);
45722                 dup2(fd, STDOUT_FILENO);
45723                 close(fd);
45724         }
45725 -       
45726 +
45727         if (0 != config_set_defaults(srv)) {
45728 -               log_error_write(srv, __FILE__, __LINE__, "s", 
45729 +               log_error_write(srv, __FILE__, __LINE__, "s",
45730                                 "setting default values failed");
45731                 server_free(srv);
45732                 return -1;
45733         }
45734 -       
45735 +
45736         /* UID handling */
45737  #ifdef HAVE_GETUID
45738         if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
45739                 /* we are setuid-root */
45740 -               
45741 -               log_error_write(srv, __FILE__, __LINE__, "s", 
45742 +
45743 +               log_error_write(srv, __FILE__, __LINE__, "s",
45744                                 "Are you nuts ? Don't apply a SUID bit to this binary");
45745 -               
45746 +
45747                 server_free(srv);
45748                 return -1;
45749         }
45750  #endif
45751 -       
45752 +
45753         /* check document-root */
45754         if (srv->config_storage[0]->document_root->used <= 1) {
45755 -               log_error_write(srv, __FILE__, __LINE__, "s", 
45756 +               log_error_write(srv, __FILE__, __LINE__, "s",
45757                                 "document-root is not set\n");
45758 -               
45759 +
45760                 server_free(srv);
45761 -               
45762 +
45763                 return -1;
45764         }
45765 -       
45766 +
45767         if (plugins_load(srv)) {
45768                 log_error_write(srv, __FILE__, __LINE__, "s",
45769                                 "loading plugins finally failed");
45770 -               
45771 +
45772                 plugins_free(srv);
45773                 server_free(srv);
45774 -               
45775 +
45776                 return -1;
45777         }
45778 -       
45779 +
45780 +#ifndef _WIN32
45781         /* open pid file BEFORE chroot */
45782         if (srv->srvconf.pid_file->used) {
45783                 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))) {
45784 @@ -598,18 +616,18 @@
45785                                         "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
45786                                 return -1;
45787                         }
45788 -                       
45789 +
45790                         if (0 != stat(srv->srvconf.pid_file->ptr, &st)) {
45791                                 log_error_write(srv, __FILE__, __LINE__, "sbs",
45792                                                 "stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno));
45793                         }
45794 -                       
45795 +
45796                         if (!S_ISREG(st.st_mode)) {
45797                                 log_error_write(srv, __FILE__, __LINE__, "sb",
45798                                                 "pid-file exists and isn't regular file:", srv->srvconf.pid_file);
45799                                 return -1;
45800                         }
45801 -                       
45802 +
45803                         if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
45804                                 log_error_write(srv, __FILE__, __LINE__, "sbs",
45805                                                 "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
45806 @@ -617,13 +635,14 @@
45807                         }
45808                 }
45809         }
45810 -
45811 +#endif
45812         if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45813                 /* select limits itself
45814                  *
45815                  * as it is a hard limit and will lead to a segfault we add some safety
45816                  * */
45817 -               srv->max_fds = FD_SETSIZE - 200;
45818 +        fprintf(stderr, "%s.%d: max parallel connections: %d\r\n", __FILE__, __LINE__, FD_SETSIZE);
45819 +               srv->max_fds = FD_SETSIZE - 4;
45820         } else {
45821                 srv->max_fds = 4096;
45822         }
45823 @@ -636,7 +655,7 @@
45824  #ifdef HAVE_VALGRIND_VALGRIND_H
45825                 if (RUNNING_ON_VALGRIND) use_rlimit = 0;
45826  #endif
45827 -               
45828 +
45829  #ifdef HAVE_GETRLIMIT
45830                 if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
45831                         log_error_write(srv, __FILE__, __LINE__,
45832 @@ -644,13 +663,13 @@
45833                                         strerror(errno));
45834                         return -1;
45835                 }
45836 -               
45837 +
45838                 if (use_rlimit && srv->srvconf.max_fds) {
45839                         /* set rlimits */
45840 -                       
45841 +
45842                         rlim.rlim_cur = srv->srvconf.max_fds;
45843                         rlim.rlim_max = srv->srvconf.max_fds;
45844 -                       
45845 +
45846                         if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
45847                                 log_error_write(srv, __FILE__, __LINE__,
45848                                                 "ss", "couldn't set 'max filedescriptors'",
45849 @@ -659,7 +678,7 @@
45850                         }
45851                 }
45852  
45853 -               /* #372: solaris need some fds extra for devpoll */     
45854 +               /* #372: solaris need some fds extra for devpoll */
45855                 if (rlim.rlim_cur > 10) rlim.rlim_cur -= 10;
45856  
45857                 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45858 @@ -677,33 +696,33 @@
45859                 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45860                         /* don't raise the limit above FD_SET_SIZE */
45861                         if (srv->max_fds > FD_SETSIZE - 200) {
45862 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
45863 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
45864                                                 "can't raise max filedescriptors above",  FD_SETSIZE - 200,
45865                                                 "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
45866                                 return -1;
45867                         }
45868                 }
45869  
45870 -               
45871 +
45872  #ifdef HAVE_PWD_H
45873                 /* set user and group */
45874                 if (srv->srvconf.username->used) {
45875                         if (NULL == (pwd = getpwnam(srv->srvconf.username->ptr))) {
45876 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
45877 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
45878                                                 "can't find username", srv->srvconf.username);
45879                                 return -1;
45880                         }
45881 -                       
45882 +
45883                         if (pwd->pw_uid == 0) {
45884                                 log_error_write(srv, __FILE__, __LINE__, "s",
45885                                                 "I will not set uid to 0\n");
45886                                 return -1;
45887                         }
45888                 }
45889 -               
45890 +
45891                 if (srv->srvconf.groupname->used) {
45892                         if (NULL == (grp = getgrnam(srv->srvconf.groupname->ptr))) {
45893 -                               log_error_write(srv, __FILE__, __LINE__, "sb", 
45894 +                               log_error_write(srv, __FILE__, __LINE__, "sb",
45895                                         "can't find groupname", srv->srvconf.groupname);
45896                                 return -1;
45897                         }
45898 @@ -713,15 +732,15 @@
45899                                 return -1;
45900                         }
45901                 }
45902 -#endif         
45903 +#endif
45904                 /* we need root-perms for port < 1024 */
45905                 if (0 != network_init(srv)) {
45906                         plugins_free(srv);
45907                         server_free(srv);
45908 -                       
45909 +
45910                         return -1;
45911                 }
45912 -#ifdef HAVE_CHROOT     
45913 +#ifdef HAVE_CHROOT
45914                 if (srv->srvconf.changeroot->used) {
45915                         tzset();
45916  
45917 @@ -761,7 +780,7 @@
45918                 }
45919  
45920                 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45921 -                       srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
45922 +                       srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 4 ? rlim.rlim_cur : FD_SETSIZE - 4;
45923                 } else {
45924                         srv->max_fds = rlim.rlim_cur;
45925                 }
45926 @@ -775,18 +794,18 @@
45927  #endif
45928                 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
45929                         /* don't raise the limit above FD_SET_SIZE */
45930 -                       if (srv->max_fds > FD_SETSIZE - 200) {
45931 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
45932 -                                               "can't raise max filedescriptors above",  FD_SETSIZE - 200,
45933 +                       if (srv->max_fds > FD_SETSIZE - 4) {
45934 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
45935 +                                               "can't raise max filedescriptors above",  FD_SETSIZE - 4,
45936                                                 "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
45937                                 return -1;
45938                         }
45939                 }
45940 -               
45941 +
45942                 if (0 != network_init(srv)) {
45943                         plugins_free(srv);
45944                         server_free(srv);
45945 -                       
45946 +
45947                         return -1;
45948                 }
45949         }
45950 @@ -802,25 +821,27 @@
45951                 /* or use the default */
45952                 srv->max_conns = srv->max_fds;
45953         }
45954 -       
45955 +
45956         if (HANDLER_GO_ON != plugins_call_init(srv)) {
45957                 log_error_write(srv, __FILE__, __LINE__, "s", "Initialization of plugins failed. Going down.");
45958 -               
45959 +
45960                 plugins_free(srv);
45961                 network_close(srv);
45962                 server_free(srv);
45963 -               
45964 +
45965                 return -1;
45966         }
45967  
45968 -#ifdef HAVE_FORK       
45969 +#ifdef HAVE_FORK
45970         /* network is up, let's deamonize ourself */
45971         if (srv->srvconf.dont_daemonize == 0) daemonize();
45972  #endif
45973  
45974 +#ifdef HAVE_PWD_H
45975         srv->gid = getgid();
45976         srv->uid = getuid();
45977 -       
45978 +#endif
45979 +
45980         /* write pid file */
45981         if (pid_fd != -1) {
45982                 buffer_copy_long(srv->tmp_buf, getpid());
45983 @@ -829,17 +850,17 @@
45984                 close(pid_fd);
45985                 pid_fd = -1;
45986         }
45987 -       
45988 +
45989         if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) {
45990                 log_error_write(srv, __FILE__, __LINE__, "s", "Configuration of plugins failed. Going down.");
45991 -               
45992 +
45993                 plugins_free(srv);
45994                 network_close(srv);
45995                 server_free(srv);
45996 -               
45997 +
45998                 return -1;
45999         }
46000 -       
46001 +
46002         /* dump unused config-keys */
46003         for (i = 0; i < srv->config_context->used; i++) {
46004                 array *config = ((data_config *)srv->config_context->data[i])->value;
46005 @@ -847,43 +868,42 @@
46006  
46007                 for (j = 0; config && j < config->used; j++) {
46008                         data_unset *du = config->data[j];
46009 -                       
46010 +
46011                         /* all var.* is known as user defined variable */
46012                         if (strncmp(du->key->ptr, "var.", sizeof("var.") - 1) == 0) {
46013                                 continue;
46014                         }
46015  
46016                         if (NULL == array_get_element(srv->config_touched, du->key->ptr)) {
46017 -                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
46018 +                               log_error_write(srv, __FILE__, __LINE__, "sbs",
46019                                                 "WARNING: unknown config-key:",
46020                                                 du->key,
46021                                                 "(ignored)");
46022                         }
46023                 }
46024         }
46025 -       
46026 +
46027         if (srv->config_deprecated) {
46028 -               log_error_write(srv, __FILE__, __LINE__, "s", 
46029 +               log_error_write(srv, __FILE__, __LINE__, "s",
46030                                 "Configuration contains deprecated keys. Going down.");
46031 -               
46032 +
46033                 plugins_free(srv);
46034                 network_close(srv);
46035                 server_free(srv);
46036 -               
46037 +
46038                 return -1;
46039         }
46040 -       
46041 +
46042         if (-1 == log_error_open(srv)) {
46043 -               log_error_write(srv, __FILE__, __LINE__, "s", 
46044 +               log_error_write(srv, __FILE__, __LINE__, "s",
46045                                 "opening errorlog failed, dying");
46046 -               
46047 +
46048                 plugins_free(srv);
46049                 network_close(srv);
46050                 server_free(srv);
46051                 return -1;
46052         }
46053 -       
46054 -       
46055 +
46056  #ifdef HAVE_SIGACTION
46057         memset(&act, 0, sizeof(act));
46058         act.sa_handler = SIG_IGN;
46059 @@ -903,7 +923,7 @@
46060         sigaction(SIGHUP,  &act, NULL);
46061         sigaction(SIGALRM, &act, NULL);
46062         sigaction(SIGCHLD, &act, NULL);
46063 -       
46064 +
46065  #elif defined(HAVE_SIGNAL)
46066         /* ignore the SIGPIPE from sendfile() */
46067         signal(SIGPIPE, SIG_IGN);
46068 @@ -914,20 +934,20 @@
46069         signal(SIGCHLD,  signal_handler);
46070         signal(SIGINT,  signal_handler);
46071  #endif
46072 -       
46073 +
46074  #ifdef USE_ALARM
46075         signal(SIGALRM, signal_handler);
46076 -       
46077 +
46078         /* setup periodic timer (1 second) */
46079         if (setitimer(ITIMER_REAL, &interval, NULL)) {
46080                 log_error_write(srv, __FILE__, __LINE__, "s", "setting timer failed");
46081                 return -1;
46082         }
46083 -       
46084 +
46085         getitimer(ITIMER_REAL, &interval);
46086  #endif
46087  
46088 -#ifdef HAVE_FORK       
46089 +#ifdef HAVE_FORK
46090         /* start watcher and workers */
46091         num_childs = srv->srvconf.max_worker;
46092         if (num_childs > 0) {
46093 @@ -957,13 +977,13 @@
46094         }
46095  #endif
46096  
46097 -       if (NULL == (srv->ev = fdevent_init(srv->max_fds + 1, srv->event_handler))) {
46098 +       if (NULL == (srv->ev = fdevent_init(/*srv->max_fds + 1*/ 4096, srv->event_handler))) {
46099                 log_error_write(srv, __FILE__, __LINE__,
46100                                 "s", "fdevent_init failed");
46101                 return -1;
46102         }
46103 -       /* 
46104 -        * kqueue() is called here, select resets its internals, 
46105 +       /*
46106 +        * kqueue() is called here, select resets its internals,
46107          * all server sockets get their handlers
46108          *
46109          * */
46110 @@ -971,7 +991,7 @@
46111                 plugins_free(srv);
46112                 network_close(srv);
46113                 server_free(srv);
46114 -               
46115 +
46116                 return -1;
46117         }
46118  
46119 @@ -986,7 +1006,7 @@
46120         /* setup FAM */
46121         if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) {
46122                 if (0 != FAMOpen2(srv->stat_cache->fam, "lighttpd")) {
46123 -                       log_error_write(srv, __FILE__, __LINE__, "s", 
46124 +                       log_error_write(srv, __FILE__, __LINE__, "s",
46125                                          "could not open a fam connection, dieing.");
46126                         return -1;
46127                 }
46128 @@ -1018,16 +1038,40 @@
46129                 int n;
46130                 size_t ndx;
46131                 time_t min_ts;
46132 -               
46133 +
46134                 if (handle_sig_hup) {
46135                         handler_t r;
46136 -                       
46137 +
46138                         /* reset notification */
46139                         handle_sig_hup = 0;
46140 -                       
46141 -                       
46142 +
46143 +#if 0
46144 +                               pid_t pid;
46145 +
46146 +                       /* send the old process into a graceful-shutdown and start a
46147 +                        * new process right away
46148 +                        *
46149 +                        * BUGS:
46150 +                        * - if webserver is running on port < 1024 (e.g. 80, 433)
46151 +                        *   we don't have the permissions to bind to that port anymore
46152 +                        *
46153 +                        *
46154 +                        *  */
46155 +                       if (0 == (pid = fork())) {
46156 +                               execve(argv[0], argv, envp);
46157 +
46158 +                               exit(-1);
46159 +                       } else if (pid == -1) {
46160 +
46161 +                       } else {
46162 +                               /* parent */
46163 +
46164 +                               graceful_shutdown = 1; /* shutdown without killing running connections */
46165 +                               graceful_restart = 1;  /* don't delete pid file */
46166 +                       }
46167 +#else
46168                         /* cycle logfiles */
46169 -                       
46170 +
46171                         switch(r = plugins_call_handle_sighup(srv)) {
46172                         case HANDLER_GO_ON:
46173                                 break;
46174 @@ -1035,30 +1079,31 @@
46175                                 log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r);
46176                                 break;
46177                         }
46178 -                       
46179 +
46180                         if (-1 == log_error_cycle(srv)) {
46181                                 log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying");
46182 -                               
46183 +
46184                                 return -1;
46185                         }
46186 +#endif
46187                 }
46188 -               
46189 +
46190                 if (handle_sig_alarm) {
46191                         /* a new second */
46192 -                       
46193 +
46194  #ifdef USE_ALARM
46195                         /* reset notification */
46196                         handle_sig_alarm = 0;
46197  #endif
46198 -                       
46199 +
46200                         /* get current time */
46201                         min_ts = time(NULL);
46202 -                       
46203 +
46204                         if (min_ts != srv->cur_ts) {
46205                                 int cs = 0;
46206                                 connections *conns = srv->conns;
46207                                 handler_t r;
46208 -                               
46209 +
46210                                 switch(r = plugins_call_handle_trigger(srv)) {
46211                                 case HANDLER_GO_ON:
46212                                         break;
46213 @@ -1069,21 +1114,21 @@
46214                                         log_error_write(srv, __FILE__, __LINE__, "d", r);
46215                                         break;
46216                                 }
46217 -                               
46218 +
46219                                 /* trigger waitpid */
46220                                 srv->cur_ts = min_ts;
46221 -                       
46222 -                               /* cleanup stat-cache */        
46223 +
46224 +                               /* cleanup stat-cache */
46225                                 stat_cache_trigger_cleanup(srv);
46226                                 /**
46227 -                                * check all connections for timeouts 
46228 -                                * 
46229 +                                * check all connections for timeouts
46230 +                                *
46231                                  */
46232                                 for (ndx = 0; ndx < conns->used; ndx++) {
46233                                         int changed = 0;
46234                                         connection *con;
46235                                         int t_diff;
46236 -                                       
46237 +
46238                                         con = conns->ptr[ndx];
46239  
46240                                         if (con->state == CON_STATE_READ ||
46241 @@ -1092,7 +1137,7 @@
46242                                                         if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {
46243                                                                 /* time - out */
46244  #if 0
46245 -                                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
46246 +                                                               log_error_write(srv, __FILE__, __LINE__, "sd",
46247                                                                                 "connection closed - read-timeout:", con->fd);
46248  #endif
46249                                                                 connection_set_state(srv, con, CON_STATE_ERROR);
46250 @@ -1102,7 +1147,7 @@
46251                                                         if (srv->cur_ts - con->read_idle_ts > con->conf.max_keep_alive_idle) {
46252                                                                 /* time - out */
46253  #if 0
46254 -                                                               log_error_write(srv, __FILE__, __LINE__, "sd", 
46255 +                                                               log_error_write(srv, __FILE__, __LINE__, "sd",
46256                                                                                 "connection closed - read-timeout:", con->fd);
46257  #endif
46258                                                                 connection_set_state(srv, con, CON_STATE_ERROR);
46259 @@ -1110,20 +1155,20 @@
46260                                                         }
46261                                                 }
46262                                         }
46263 -                                       
46264 +
46265                                         if ((con->state == CON_STATE_WRITE) &&
46266 -                                           (con->write_request_ts != 0)) { 
46267 +                                           (con->write_request_ts != 0)) {
46268  #if 0
46269                                                 if (srv->cur_ts - con->write_request_ts > 60) {
46270 -                                                       log_error_write(srv, __FILE__, __LINE__, "sdd", 
46271 +                                                       log_error_write(srv, __FILE__, __LINE__, "sdd",
46272                                                                         "connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts);
46273                                                 }
46274  #endif
46275 -                                               
46276 +
46277                                                 if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {
46278                                                         /* time - out */
46279  #if 1
46280 -                                                       log_error_write(srv, __FILE__, __LINE__, "sbsosds", 
46281 +                                                       log_error_write(srv, __FILE__, __LINE__, "sbsosds",
46282                                                                         "NOTE: a request for",
46283                                                                         con->request.uri,
46284                                                                         "timed out after writing",
46285 @@ -1138,35 +1183,35 @@
46286                                         }
46287                                         /* we don't like div by zero */
46288                                         if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1;
46289 -       
46290 -                                       if (con->traffic_limit_reached && 
46291 -                                           (con->conf.kbytes_per_second == 0 || 
46292 +
46293 +                                       if (con->traffic_limit_reached &&
46294 +                                           (con->conf.kbytes_per_second == 0 ||
46295                                              ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) {
46296                                                 /* enable connection again */
46297                                                 con->traffic_limit_reached = 0;
46298 -                                               
46299 +
46300                                                 changed = 1;
46301                                         }
46302 -                                       
46303 +
46304                                         if (changed) {
46305                                                 connection_state_machine(srv, con);
46306                                         }
46307                                         con->bytes_written_cur_second = 0;
46308                                         *(con->conf.global_bytes_per_second_cnt_ptr) = 0;
46309 -                                       
46310 +
46311  #if 0
46312                                         if (cs == 0) {
46313                                                 fprintf(stderr, "connection-state: ");
46314                                                 cs = 1;
46315                                         }
46316 -                                       
46317 +
46318                                         fprintf(stderr, "c[%d,%d]: %s ",
46319                                                 con->fd,
46320                                                 con->fcgi.fd,
46321                                                 connection_get_state(con->state));
46322  #endif
46323                                 }
46324 -                               
46325 +
46326                                 if (cs == 1) fprintf(stderr, "\n");
46327                         }
46328                 }
46329 @@ -1181,18 +1226,18 @@
46330                                         server_socket *srv_socket = srv->srv_sockets.ptr[i];
46331                                         fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
46332                                 }
46333 -                       
46334 +
46335                                 log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again");
46336 -                       
46337 +
46338                                 srv->sockets_disabled = 0;
46339                         }
46340                 } else {
46341                         if ((srv->cur_fds + srv->want_fds > srv->max_fds * 0.9) || /* out of fds */
46342                             (srv->conns->used > srv->max_conns) || /* out of connections */
46343 -                           (graceful_shutdown)) { /* graceful_shutdown */ 
46344 +                           (graceful_shutdown)) { /* graceful_shutdown */
46345  
46346                                 /* disable server-fds */
46347 -                       
46348 +
46349                                 for (i = 0; i < srv->srv_sockets.used; i++) {
46350                                         server_socket *srv_socket = srv->srv_sockets.ptr[i];
46351                                         fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
46352 @@ -1211,7 +1256,7 @@
46353                                                 /* network_close() will cleanup after us */
46354                                         }
46355                                 }
46356 -               
46357 +
46358                                 if (graceful_shutdown) {
46359                                         log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started");
46360                                 } else if (srv->conns->used > srv->max_conns) {
46361 @@ -1219,7 +1264,7 @@
46362                                 } else {
46363                                         log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds");
46364                                 }
46365 -                       
46366 +
46367                                 srv->sockets_disabled = 1;
46368                         }
46369                 }
46370 @@ -1229,16 +1274,16 @@
46371                          * we are ready to terminate without harming anyone */
46372                         srv_shutdown = 1;
46373                 }
46374 -               
46375 +
46376                 /* we still have some fds to share */
46377 -               if (srv->want_fds) { 
46378 +               if (srv->want_fds) {
46379                         /* check the fdwaitqueue for waiting fds */
46380                         int free_fds = srv->max_fds - srv->cur_fds - 16;
46381                         connection *con;
46382 -                       
46383 +
46384                         for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) {
46385                                 connection_state_machine(srv, con);
46386 -                               
46387 +
46388                                 srv->want_fds--;
46389                         }
46390                 }
46391 @@ -1249,27 +1294,27 @@
46392                         int fd_ndx;
46393  #if 0
46394                         if (n > 0) {
46395 -                               log_error_write(srv, __FILE__, __LINE__, "sd", 
46396 +                               log_error_write(srv, __FILE__, __LINE__, "sd",
46397                                                 "polls:", n);
46398                         }
46399 -#endif                 
46400 +#endif
46401                         fd_ndx = -1;
46402                         do {
46403                                 fdevent_handler handler;
46404                                 void *context;
46405                                 handler_t r;
46406 -                               
46407 +
46408                                 fd_ndx  = fdevent_event_next_fdndx (srv->ev, fd_ndx);
46409                                 revents = fdevent_event_get_revent (srv->ev, fd_ndx);
46410                                 fd      = fdevent_event_get_fd     (srv->ev, fd_ndx);
46411                                 handler = fdevent_get_handler(srv->ev, fd);
46412                                 context = fdevent_get_context(srv->ev, fd);
46413 -                               
46414 +
46415                                 /* connection_handle_fdevent needs a joblist_append */
46416  #if 0
46417 -                               log_error_write(srv, __FILE__, __LINE__, "sdd", 
46418 +                               log_error_write(srv, __FILE__, __LINE__, "sdd",
46419                                                 "event for", fd, revents);
46420 -#endif                         
46421 +#endif
46422                                 switch (r = (*handler)(srv, context, revents)) {
46423                                 case HANDLER_FINISHED:
46424                                 case HANDLER_GO_ON:
46425 @@ -1286,17 +1331,17 @@
46426                                 }
46427                         } while (--n > 0);
46428                 } else if (n < 0 && errno != EINTR) {
46429 -                       log_error_write(srv, __FILE__, __LINE__, "ss", 
46430 -                                       "fdevent_poll failed:", 
46431 +                       log_error_write(srv, __FILE__, __LINE__, "ss",
46432 +                                       "fdevent_poll failed:",
46433                                         strerror(errno));
46434                 }
46435 -               
46436 +
46437                 for (ndx = 0; ndx < srv->joblist->used; ndx++) {
46438                         connection *con = srv->joblist->ptr[ndx];
46439                         handler_t r;
46440 -                       
46441 +
46442                         connection_state_machine(srv, con);
46443 -                       
46444 +
46445                         switch(r = plugins_call_handle_joblist(srv, con)) {
46446                         case HANDLER_FINISHED:
46447                         case HANDLER_GO_ON:
46448 @@ -1305,32 +1350,33 @@
46449                                 log_error_write(srv, __FILE__, __LINE__, "d", r);
46450                                 break;
46451                         }
46452 -                       
46453 +
46454                         con->in_joblist = 0;
46455                 }
46456 -               
46457 +
46458                 srv->joblist->used = 0;
46459         }
46460 -       
46461 -       if (srv->srvconf.pid_file->used &&
46462 +
46463 +       if (0 == graceful_restart &&
46464 +           srv->srvconf.pid_file->used &&
46465             srv->srvconf.changeroot->used == 0) {
46466                 if (0 != unlink(srv->srvconf.pid_file->ptr)) {
46467                         if (errno != EACCES && errno != EPERM) {
46468 -                               log_error_write(srv, __FILE__, __LINE__, "sbds", 
46469 -                                               "unlink failed for:", 
46470 +                               log_error_write(srv, __FILE__, __LINE__, "sbds",
46471 +                                               "unlink failed for:",
46472                                                 srv->srvconf.pid_file,
46473                                                 errno,
46474                                                 strerror(errno));
46475                         }
46476                 }
46477         }
46478 -       
46479 +
46480         /* clean-up */
46481         log_error_close(srv);
46482         network_close(srv);
46483         connections_free(srv);
46484         plugins_free(srv);
46485         server_free(srv);
46486 -       
46487 +
46488         return 0;
46489  }
46490 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/settings.h lighttpd-1.4.12/src/settings.h
46491 --- lighttpd-1.4.11/src/settings.h      2005-08-11 01:26:41.000000000 +0300
46492 +++ lighttpd-1.4.12/src/settings.h      2006-07-11 21:23:40.000000000 +0300
46493 @@ -9,24 +9,24 @@
46494  /**
46495   * max size of a buffer which will just be reset
46496   * to ->used = 0 instead of really freeing the buffer
46497 - * 
46498 + *
46499   * 64kB (no real reason, just a guess)
46500   */
46501  #define BUFFER_MAX_REUSE_SIZE  (4 * 1024)
46502  
46503  /**
46504   * max size of the HTTP request header
46505 - * 
46506 + *
46507   * 32k should be enough for everything (just a guess)
46508 - * 
46509 + *
46510   */
46511  #define MAX_HTTP_REQUEST_HEADER  (32 * 1024)
46512  
46513 -typedef enum { HANDLER_UNSET, 
46514 -               HANDLER_GO_ON, 
46515 +typedef enum { HANDLER_UNSET,
46516 +               HANDLER_GO_ON,
46517                 HANDLER_FINISHED,
46518 -               HANDLER_COMEBACK, 
46519 -               HANDLER_WAIT_FOR_EVENT, 
46520 +               HANDLER_COMEBACK,
46521 +               HANDLER_WAIT_FOR_EVENT,
46522                 HANDLER_ERROR,
46523                 HANDLER_WAIT_FOR_FD
46524  } handler_t;
46525 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/spawn-fcgi.c lighttpd-1.4.12/src/spawn-fcgi.c
46526 --- lighttpd-1.4.11/src/spawn-fcgi.c    2006-03-07 14:18:10.000000000 +0200
46527 +++ lighttpd-1.4.12/src/spawn-fcgi.c    2006-07-11 21:23:40.000000000 +0300
46528 @@ -1,19 +1,16 @@
46529  #include <sys/types.h>
46530 -#include <sys/time.h>
46531  #include <sys/stat.h>
46532  
46533  #include <stdlib.h>
46534  #include <string.h>
46535  #include <errno.h>
46536  #include <stdio.h>
46537 -#include <unistd.h>
46538  #include <fcntl.h>
46539 -
46540 +#include <time.h>
46541  #ifdef HAVE_CONFIG_H
46542  #include "config.h"
46543  #endif
46544  
46545 -
46546  #ifdef HAVE_PWD_H
46547  #include <grp.h>
46548  #include <pwd.h>
46549 @@ -30,6 +27,7 @@
46550  #endif
46551  
46552  #include "sys-socket.h"
46553 +#include "sys-files.h"
46554  
46555  #ifdef HAVE_SYS_WAIT_H
46556  #include <sys/wait.h>
46557 @@ -45,28 +43,28 @@
46558         int fcgi_fd;
46559         int socket_type, status;
46560         struct timeval tv = { 0, 100 * 1000 };
46561 -       
46562 +
46563         struct sockaddr_un fcgi_addr_un;
46564         struct sockaddr_in fcgi_addr_in;
46565         struct sockaddr *fcgi_addr;
46566 -       
46567 +
46568         socklen_t servlen;
46569 -       
46570 +
46571         if (child_count < 2) {
46572                 child_count = 5;
46573         }
46574 -       
46575 +
46576         if (child_count > 256) {
46577                 child_count = 256;
46578         }
46579 -       
46580 -       
46581 +
46582 +
46583         if (unixsocket) {
46584                 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
46585 -               
46586 +
46587                 fcgi_addr_un.sun_family = AF_UNIX;
46588                 strcpy(fcgi_addr_un.sun_path, unixsocket);
46589 -               
46590 +
46591  #ifdef SUN_LEN
46592                 servlen = SUN_LEN(&fcgi_addr_un);
46593  #else
46594 @@ -84,50 +82,50 @@
46595                  }
46596                 fcgi_addr_in.sin_port = htons(port);
46597                 servlen = sizeof(fcgi_addr_in);
46598 -               
46599 +
46600                 socket_type = AF_INET;
46601                 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
46602         }
46603 -       
46604 +
46605         if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
46606 -               fprintf(stderr, "%s.%d\n", 
46607 +               fprintf(stderr, "%s.%d\n",
46608                         __FILE__, __LINE__);
46609                 return -1;
46610         }
46611 -       
46612 +
46613         if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
46614                 /* server is not up, spawn in  */
46615                 pid_t child;
46616                 int val;
46617 -               
46618 +
46619                 if (unixsocket) unlink(unixsocket);
46620 -               
46621 +
46622                 close(fcgi_fd);
46623 -               
46624 +
46625                 /* reopen socket */
46626                 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
46627 -                       fprintf(stderr, "%s.%d\n", 
46628 +                       fprintf(stderr, "%s.%d\n",
46629                                 __FILE__, __LINE__);
46630                         return -1;
46631                 }
46632  
46633                 val = 1;
46634                 if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
46635 -                       fprintf(stderr, "%s.%d\n", 
46636 +                       fprintf(stderr, "%s.%d\n",
46637                                 __FILE__, __LINE__);
46638                         return -1;
46639                 }
46640  
46641                 /* create socket */
46642                 if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
46643 -                       fprintf(stderr, "%s.%d: bind failed: %s\n", 
46644 +                       fprintf(stderr, "%s.%d: bind failed: %s\n",
46645                                 __FILE__, __LINE__,
46646                                 strerror(errno));
46647                         return -1;
46648                 }
46649 -               
46650 +
46651                 if (-1 == listen(fcgi_fd, 1024)) {
46652 -                       fprintf(stderr, "%s.%d: fd = -1\n", 
46653 +                       fprintf(stderr, "%s.%d: fd = -1\n",
46654                                 __FILE__, __LINE__);
46655                         return -1;
46656                 }
46657 @@ -137,42 +135,45 @@
46658                 } else {
46659                         child = 0;
46660                 }
46661 -               
46662 +
46663                 switch (child) {
46664                 case 0: {
46665                         char cgi_childs[64];
46666                         char *b;
46667 -                       
46668 +
46669                         int i = 0;
46670 -                       
46671 +
46672 +                       /* loose control terminal */
46673 +                       setsid();
46674 +
46675                         /* is save as we limit to 256 childs */
46676                         sprintf(cgi_childs, "PHP_FCGI_CHILDREN=%d", child_count);
46677 -                       
46678 +
46679                         if(fcgi_fd != FCGI_LISTENSOCK_FILENO) {
46680                                 close(FCGI_LISTENSOCK_FILENO);
46681                                 dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
46682                                 close(fcgi_fd);
46683                         }
46684 -                       
46685 +
46686                         /* we don't need the client socket */
46687                         for (i = 3; i < 256; i++) {
46688                                 close(i);
46689                         }
46690 -                       
46691 +
46692                         /* create environment */
46693 -                       
46694 +
46695                         putenv(cgi_childs);
46696 -                       
46697 +
46698                         /* fork and replace shell */
46699                         b = malloc(strlen("exec ") + strlen(appPath) + 1);
46700                         strcpy(b, "exec ");
46701                         strcat(b, appPath);
46702 -                       
46703 +
46704                         /* exec the cgi */
46705                         execl("/bin/sh", "sh", "-c", b, NULL);
46706 -                       
46707 +
46708                         exit(errno);
46709 -                       
46710 +
46711                         break;
46712                 }
46713                 case -1:
46714 @@ -180,47 +181,47 @@
46715                         break;
46716                 default:
46717                         /* father */
46718 -                       
46719 +
46720                         /* wait */
46721                         select(0, NULL, NULL, NULL, &tv);
46722 -                       
46723 +
46724                         switch (waitpid(child, &status, WNOHANG)) {
46725                         case 0:
46726 -                               fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n", 
46727 +                               fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n",
46728                                         __FILE__, __LINE__,
46729                                         child);
46730 -                               
46731 +
46732                                 /* write pid file */
46733                                 if (pid_fd != -1) {
46734                                         /* assume a 32bit pid_t */
46735                                         char pidbuf[12];
46736 -                                       
46737 +
46738                                         snprintf(pidbuf, sizeof(pidbuf) - 1, "%d", child);
46739 -                                       
46740 +
46741                                         write(pid_fd, pidbuf, strlen(pidbuf));
46742                                         close(pid_fd);
46743                                         pid_fd = -1;
46744                                 }
46745 -                               
46746 +
46747                                 break;
46748                         case -1:
46749                                 break;
46750                         default:
46751                                 if (WIFEXITED(status)) {
46752 -                                       fprintf(stderr, "%s.%d: child exited with: %d, %s\n", 
46753 +                                       fprintf(stderr, "%s.%d: child exited with: %d, %s\n",
46754                                                 __FILE__, __LINE__,
46755                                                 WEXITSTATUS(status), strerror(WEXITSTATUS(status)));
46756                                 } else if (WIFSIGNALED(status)) {
46757 -                                       fprintf(stderr, "%s.%d: child signaled: %d\n", 
46758 +                                       fprintf(stderr, "%s.%d: child signaled: %d\n",
46759                                                 __FILE__, __LINE__,
46760                                                 WTERMSIG(status));
46761                                 } else {
46762 -                                       fprintf(stderr, "%s.%d: child died somehow: %d\n", 
46763 +                                       fprintf(stderr, "%s.%d: child died somehow: %d\n",
46764                                                 __FILE__, __LINE__,
46765                                                 status);
46766                                 }
46767                         }
46768 -                               
46769 +
46770                         break;
46771                 }
46772         } else {
46773 @@ -228,16 +229,16 @@
46774                         __FILE__, __LINE__);
46775                 return -1;
46776         }
46777 -       
46778 +
46779         close(fcgi_fd);
46780 -       
46781 +
46782         return 0;
46783  }
46784  
46785  
46786  void show_version () {
46787         char *b = "spawn-fcgi" "-" PACKAGE_VERSION \
46788 -" - spawns fastcgi processes\n" 
46789 +" - spawns fastcgi processes\n"
46790  ;
46791         write(1, b, strlen(b));
46792  }
46793 @@ -265,7 +266,7 @@
46794  
46795  
46796  int main(int argc, char **argv) {
46797 -       char *fcgi_app = NULL, *changeroot = NULL, *username = NULL, 
46798 +       char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
46799                 *groupname = NULL, *unixsocket = NULL, *pid_file = NULL,
46800                  *addr = NULL;
46801         unsigned short port = 0;
46802 @@ -273,9 +274,9 @@
46803         int i_am_root, o;
46804         int pid_fd = -1;
46805         int nofork = 0;
46806 -       
46807 +
46808         i_am_root = (getuid() == 0);
46809 -       
46810 +
46811         while(-1 != (o = getopt(argc, argv, "c:f:g:hna:p:u:vC:s:P:"))) {
46812                 switch(o) {
46813                 case 'f': fcgi_app = optarg; break;
46814 @@ -290,137 +291,137 @@
46815                 case 'P': pid_file = optarg; /* PID file */ break;
46816                 case 'v': show_version(); return 0;
46817                 case 'h': show_help(); return 0;
46818 -               default: 
46819 +               default:
46820                         show_help();
46821                         return -1;
46822                 }
46823         }
46824 -       
46825 +
46826         if (fcgi_app == NULL || (port == 0 && unixsocket == NULL)) {
46827                 show_help();
46828                 return -1;
46829         }
46830 -           
46831 +
46832         if (unixsocket && port) {
46833 -               fprintf(stderr, "%s.%d: %s\n", 
46834 +               fprintf(stderr, "%s.%d: %s\n",
46835                         __FILE__, __LINE__,
46836                         "either a unix domain socket or a tcp-port, but not both\n");
46837 -               
46838 +
46839                 return -1;
46840         }
46841 -       
46842 +
46843         if (unixsocket && strlen(unixsocket) > UNIX_PATH_MAX - 1) {
46844 -               fprintf(stderr, "%s.%d: %s\n", 
46845 +               fprintf(stderr, "%s.%d: %s\n",
46846                         __FILE__, __LINE__,
46847                         "path of the unix socket is too long\n");
46848 -               
46849 +
46850                 return -1;
46851         }
46852  
46853         /* UID handling */
46854         if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
46855                 /* we are setuid-root */
46856 -               
46857 -               fprintf(stderr, "%s.%d: %s\n", 
46858 +
46859 +               fprintf(stderr, "%s.%d: %s\n",
46860                         __FILE__, __LINE__,
46861                         "Are you nuts ? Don't apply a SUID bit to this binary\n");
46862 -               
46863 +
46864                 return -1;
46865         }
46866 -       
46867 -       if (pid_file && 
46868 +
46869 +       if (pid_file &&
46870             (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)))) {
46871                 struct stat st;
46872                 if (errno != EEXIST) {
46873 -                       fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n", 
46874 +                       fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
46875                                 __FILE__, __LINE__,
46876                                 pid_file, strerror(errno));
46877 -                       
46878 +
46879                         return -1;
46880                 }
46881 -               
46882 +
46883                 /* ok, file exists */
46884 -               
46885 +
46886                 if (0 != stat(pid_file, &st)) {
46887 -                       fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n", 
46888 +                       fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n",
46889                                 __FILE__, __LINE__,
46890                                 pid_file, strerror(errno));
46891 -                       
46892 +
46893                         return -1;
46894                 }
46895 -               
46896 +
46897                 /* is it a regular file ? */
46898 -               
46899 +
46900                 if (!S_ISREG(st.st_mode)) {
46901 -                       fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n", 
46902 +                       fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n",
46903                                 __FILE__, __LINE__,
46904                                 pid_file);
46905 -                       
46906 +
46907                         return -1;
46908                 }
46909 -               
46910 +
46911                 if (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
46912 -                       fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n", 
46913 +                       fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
46914                                 __FILE__, __LINE__,
46915                                 pid_file, strerror(errno));
46916 -                       
46917 +
46918                         return -1;
46919                 }
46920         }
46921 -       
46922 +
46923         if (i_am_root) {
46924                 struct group *grp = NULL;
46925                 struct passwd *pwd = NULL;
46926 -               
46927 +
46928                 /* set user and group */
46929 -               
46930 +
46931                 if (username) {
46932                         if (NULL == (pwd = getpwnam(username))) {
46933 -                               fprintf(stderr, "%s.%d: %s, %s\n", 
46934 +                               fprintf(stderr, "%s.%d: %s, %s\n",
46935                                         __FILE__, __LINE__,
46936                                         "can't find username", username);
46937                                 return -1;
46938                         }
46939 -                       
46940 +
46941                         if (pwd->pw_uid == 0) {
46942 -                               fprintf(stderr, "%s.%d: %s\n", 
46943 +                               fprintf(stderr, "%s.%d: %s\n",
46944                                         __FILE__, __LINE__,
46945                                         "I will not set uid to 0\n");
46946                                 return -1;
46947                         }
46948                 }
46949 -               
46950 +
46951                 if (groupname) {
46952                         if (NULL == (grp = getgrnam(groupname))) {
46953 -                               fprintf(stderr, "%s.%d: %s %s\n", 
46954 +                               fprintf(stderr, "%s.%d: %s %s\n",
46955                                         __FILE__, __LINE__,
46956 -                                       "can't find groupname", 
46957 +                                       "can't find groupname",
46958                                         groupname);
46959                                 return -1;
46960                         }
46961                         if (grp->gr_gid == 0) {
46962 -                               fprintf(stderr, "%s.%d: %s\n", 
46963 +                               fprintf(stderr, "%s.%d: %s\n",
46964                                         __FILE__, __LINE__,
46965                                         "I will not set gid to 0\n");
46966                                 return -1;
46967                         }
46968                 }
46969 -               
46970 +
46971                 if (changeroot) {
46972                         if (-1 == chroot(changeroot)) {
46973 -                               fprintf(stderr, "%s.%d: %s %s\n", 
46974 +                               fprintf(stderr, "%s.%d: %s %s\n",
46975                                         __FILE__, __LINE__,
46976                                         "chroot failed: ", strerror(errno));
46977                                 return -1;
46978                         }
46979                         if (-1 == chdir("/")) {
46980 -                               fprintf(stderr, "%s.%d: %s %s\n", 
46981 +                               fprintf(stderr, "%s.%d: %s %s\n",
46982                                         __FILE__, __LINE__,
46983                                         "chdir failed: ", strerror(errno));
46984                                 return -1;
46985                         }
46986                 }
46987 -               
46988 +
46989                 /* drop root privs */
46990                 if (groupname) {
46991                         setgid(grp->gr_gid);
46992 @@ -428,7 +429,7 @@
46993                 }
46994                 if (username) setuid(pwd->pw_uid);
46995         }
46996 -       
46997 +
46998         return fcgi_spawn_connection(fcgi_app, addr, port, unixsocket, child_count, pid_fd, nofork);
46999  }
47000  #else
47001 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/splaytree.c lighttpd-1.4.12/src/splaytree.c
47002 --- lighttpd-1.4.11/src/splaytree.c     2005-09-12 21:51:28.000000000 +0300
47003 +++ lighttpd-1.4.12/src/splaytree.c     2006-07-11 21:23:39.000000000 +0300
47004 @@ -56,19 +56,19 @@
47005  
47006  #define node_size splaytree_size
47007  
47008 -/* Splay using the key i (which may or may not be in the tree.) 
47009 - * The starting root is t, and the tree used is defined by rat 
47010 +/* Splay using the key i (which may or may not be in the tree.)
47011 + * The starting root is t, and the tree used is defined by rat
47012   * size fields are maintained */
47013  splay_tree * splaytree_splay (splay_tree *t, int i) {
47014      splay_tree N, *l, *r, *y;
47015      int comp, root_size, l_size, r_size;
47016 -    
47017 +
47018      if (t == NULL) return t;
47019      N.left = N.right = NULL;
47020      l = r = &N;
47021      root_size = node_size(t);
47022      l_size = r_size = 0;
47023
47024 +
47025      for (;;) {
47026          comp = compare(i, t->key);
47027          if (comp < 0) {
47028 @@ -120,7 +120,7 @@
47029          y->size = r_size;
47030          r_size -= 1+node_size(y->right);
47031      }
47032
47033 +
47034      l->right = t->left;                                /* assemble */
47035      r->left = t->right;
47036      t->left = N.right;
47037 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/splaytree.h lighttpd-1.4.12/src/splaytree.h
47038 --- lighttpd-1.4.11/src/splaytree.h     2005-09-12 21:51:13.000000000 +0300
47039 +++ lighttpd-1.4.12/src/splaytree.h     2006-07-11 21:23:40.000000000 +0300
47040 @@ -19,6 +19,6 @@
47041  /* This macro returns the size of a node.  Unlike "x->size",     */
47042  /* it works even if x=NULL.  The test could be avoided by using  */
47043  /* a special version of NULL which was a real node with size 0.  */
47044
47045 +
47046  
47047  #endif
47048 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/stat_cache.c lighttpd-1.4.12/src/stat_cache.c
47049 --- lighttpd-1.4.11/src/stat_cache.c    2005-11-22 15:23:51.000000000 +0200
47050 +++ lighttpd-1.4.12/src/stat_cache.c    2006-07-11 21:23:40.000000000 +0300
47051 @@ -6,7 +6,6 @@
47052  #include <stdlib.h>
47053  #include <string.h>
47054  #include <errno.h>
47055 -#include <unistd.h>
47056  #include <stdio.h>
47057  #include <fcntl.h>
47058  #include <assert.h>
47059 @@ -25,19 +24,8 @@
47060  #endif
47061  
47062  #include "sys-mmap.h"
47063 -
47064 -/* NetBSD 1.3.x needs it */
47065 -#ifndef MAP_FAILED
47066 -# define MAP_FAILED -1
47067 -#endif
47068 -
47069 -#ifndef O_LARGEFILE
47070 -# define O_LARGEFILE 0
47071 -#endif
47072 -
47073 -#ifndef HAVE_LSTAT
47074 -#define lstat stat
47075 -#endif
47076 +#include "sys-files.h"
47077 +#include "sys-strings.h"
47078  
47079  #if 0
47080  /* enables debug code for testing if all nodes in the stat-cache as accessable */
47081 @@ -52,8 +40,8 @@
47082   *
47083   * if we get a change-event from FAM, we increment the version in the FAM->dir mapping
47084   *
47085 - * if the stat()-cache is queried we check if the version id for the directory is the 
47086 - * same and return immediatly. 
47087 + * if the stat()-cache is queried we check if the version id for the directory is the
47088 + * same and return immediatly.
47089   *
47090   *
47091   * What we need:
47092 @@ -62,17 +50,17 @@
47093   * - for each FAMRequest we have to find the version in the directory cache (index as userdata)
47094   *
47095   * stat <<-> directory <-> FAMRequest
47096 - * 
47097 - * if file is deleted, directory is dirty, file is rechecked ... 
47098 + *
47099 + * if file is deleted, directory is dirty, file is rechecked ...
47100   * if directory is deleted, directory mapping is removed
47101 - *  
47102 + *
47103   * */
47104  
47105  #ifdef HAVE_FAM_H
47106  typedef struct {
47107         FAMRequest *req;
47108         FAMConnection *fc;
47109 -       
47110 +
47111         buffer *name;
47112  
47113         int version;
47114 @@ -83,16 +71,16 @@
47115   * - we need a hash
47116   * - the hash-key is used as sorting criteria for a tree
47117   * - a splay-tree is used as we can use the caching effect of it
47118 - */ 
47119 + */
47120  
47121  /* we want to cleanup the stat-cache every few seconds, let's say 10
47122   *
47123   * - remove entries which are outdated since 30s
47124   * - remove entries which are fresh but havn't been used since 60s
47125   * - if we don't have a stat-cache entry for a directory, release it from the monitor
47126 - */ 
47127 + */
47128  
47129 -#ifdef DEBUG_STAT_CACHE        
47130 +#ifdef DEBUG_STAT_CACHE
47131  typedef struct {
47132         int *ptr;
47133  
47134 @@ -105,15 +93,15 @@
47135  
47136  stat_cache *stat_cache_init(void) {
47137         stat_cache *fc = NULL;
47138 -       
47139 +
47140         fc = calloc(1, sizeof(*fc));
47141 -       
47142 +
47143         fc->dir_name = buffer_init();
47144  #ifdef HAVE_FAM_H
47145         fc->fam = calloc(1, sizeof(*fc->fam));
47146  #endif
47147  
47148 -#ifdef DEBUG_STAT_CACHE        
47149 +#ifdef DEBUG_STAT_CACHE
47150         ctrl.size = 0;
47151  #endif
47152  
47153 @@ -122,24 +110,24 @@
47154  
47155  static stat_cache_entry * stat_cache_entry_init(void) {
47156         stat_cache_entry *sce = NULL;
47157 -       
47158 +
47159         sce = calloc(1, sizeof(*sce));
47160 -       
47161 +
47162         sce->name = buffer_init();
47163         sce->etag = buffer_init();
47164         sce->content_type = buffer_init();
47165 -       
47166 +
47167         return sce;
47168  }
47169  
47170  static void stat_cache_entry_free(void *data) {
47171         stat_cache_entry *sce = data;
47172         if (!sce) return;
47173 -       
47174 +
47175         buffer_free(sce->etag);
47176         buffer_free(sce->name);
47177         buffer_free(sce->content_type);
47178 -       
47179 +
47180         free(sce);
47181  }
47182  
47183 @@ -148,22 +136,22 @@
47184         fam_dir_entry *fam_dir = NULL;
47185  
47186         fam_dir = calloc(1, sizeof(*fam_dir));
47187 -       
47188 +
47189         fam_dir->name = buffer_init();
47190 -       
47191 +
47192         return fam_dir;
47193  }
47194  
47195  static void fam_dir_entry_free(void *data) {
47196         fam_dir_entry *fam_dir = data;
47197 -       
47198 +
47199         if (!fam_dir) return;
47200 -       
47201 +
47202         FAMCancelMonitor(fam_dir->fc, fam_dir->req);
47203 -       
47204 +
47205         buffer_free(fam_dir->name);
47206         free(fam_dir->req);
47207 -       
47208 +
47209         free(fam_dir);
47210  }
47211  #endif
47212 @@ -174,7 +162,7 @@
47213                 splay_tree *node = sc->files;
47214  
47215                 osize = sc->files->size;
47216 -                       
47217 +
47218                 stat_cache_entry_free(node->data);
47219                 sc->files = splaytree_delete(sc->files, node->key);
47220  
47221 @@ -187,12 +175,12 @@
47222         while (sc->dirs) {
47223                 int osize;
47224                 splay_tree *node = sc->dirs;
47225 -               
47226 +
47227                 osize = sc->dirs->size;
47228  
47229                 fam_dir_entry_free(node->data);
47230                 sc->dirs = splaytree_delete(sc->dirs, node->key);
47231 -               
47232 +
47233                 if (osize == 1) {
47234                         assert(NULL == sc->dirs);
47235                 } else {
47236 @@ -212,7 +200,7 @@
47237  static int stat_cache_attr_get(buffer *buf, char *name) {
47238         int attrlen;
47239         int ret;
47240 -       
47241 +
47242         attrlen = 1024;
47243         buffer_prepare_copy(buf, attrlen);
47244         attrlen--;
47245 @@ -251,15 +239,15 @@
47246             sc->fam) {
47247  
47248                 events = FAMPending(sc->fam);
47249 -       
47250 +
47251                 for (i = 0; i < events; i++) {
47252                         FAMEvent fe;
47253                         fam_dir_entry *fam_dir;
47254                         splay_tree *node;
47255                         int ndx;
47256 -               
47257 +
47258                         FAMNextEvent(sc->fam, &fe);
47259 -       
47260 +
47261                         /* handle event */
47262  
47263                         switch(fe.code) {
47264 @@ -280,7 +268,7 @@
47265  
47266                                 sc->dirs = splaytree_splay(sc->dirs, ndx);
47267                                 node = sc->dirs;
47268 -                       
47269 +
47270                                 if (node && (node->key == ndx)) {
47271                                         int osize = splaytree_size(sc->dirs);
47272  
47273 @@ -308,7 +296,7 @@
47274  
47275                 sc->fam = NULL;
47276         }
47277 -       
47278 +
47279         return HANDLER_GO_ON;
47280  }
47281  
47282 @@ -332,7 +320,7 @@
47283   *
47284   *
47285   *
47286 - * returns: 
47287 + * returns:
47288   *  - HANDLER_FINISHED on cache-miss (don't forget to reopen the file)
47289   *  - HANDLER_ERROR on stat() failed -> see errno for problem
47290   */
47291 @@ -348,16 +336,16 @@
47292         struct stat st;
47293         size_t k;
47294         int fd;
47295 -#ifdef DEBUG_STAT_CACHE        
47296 +#ifdef DEBUG_STAT_CACHE
47297         size_t i;
47298  #endif
47299  
47300         int file_ndx;
47301         splay_tree *file_node = NULL;
47302  
47303 -       *ret_sce = NULL; 
47304 +       *ret_sce = NULL;
47305  
47306 -       /* 
47307 +       /*
47308          * check if the directory for this file has changed
47309          */
47310  
47311 @@ -366,23 +354,23 @@
47312         file_ndx = hashme(name);
47313         sc->files = splaytree_splay(sc->files, file_ndx);
47314  
47315 -#ifdef DEBUG_STAT_CACHE        
47316 +#ifdef DEBUG_STAT_CACHE
47317         for (i = 0; i < ctrl.used; i++) {
47318                 if (ctrl.ptr[i] == file_ndx) break;
47319         }
47320  #endif
47321  
47322         if (sc->files && (sc->files->key == file_ndx)) {
47323 -#ifdef DEBUG_STAT_CACHE        
47324 +#ifdef DEBUG_STAT_CACHE
47325                 /* it was in the cache */
47326                 assert(i < ctrl.used);
47327  #endif
47328 -               
47329 -               /* we have seen this file already and 
47330 +
47331 +               /* we have seen this file already and
47332                  * don't stat() it again in the same second */
47333  
47334                 file_node = sc->files;
47335 -               
47336 +
47337                 sce = file_node->data;
47338  
47339                 /* check if the name is the same, we might have a collision */
47340 @@ -390,7 +378,7 @@
47341                 if (buffer_is_equal(name, sce->name)) {
47342                         if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_SIMPLE) {
47343                                 if (sce->stat_ts == srv->cur_ts) {
47344 -                                       *ret_sce = sce; 
47345 +                                       *ret_sce = sce;
47346                                         return HANDLER_GO_ON;
47347                                 }
47348                         }
47349 @@ -400,15 +388,15 @@
47350                          * file_node is used by the FAM check below to see if we know this file
47351                          * and if we can save a stat().
47352                          *
47353 -                        * BUT, the sce is not reset here as the entry into the cache is ok, we 
47354 +                        * BUT, the sce is not reset here as the entry into the cache is ok, we
47355                          * it is just not pointing to our requested file.
47356 -                        * 
47357 +                        *
47358                          *  */
47359  
47360                         file_node = NULL;
47361                 }
47362         } else {
47363 -#ifdef DEBUG_STAT_CACHE        
47364 +#ifdef DEBUG_STAT_CACHE
47365                 if (i != ctrl.used) {
47366                         fprintf(stderr, "%s.%d: %08x was already inserted but not found in cache, %s\n", __FILE__, __LINE__, file_ndx, name->ptr);
47367                 }
47368 @@ -424,23 +412,23 @@
47369                 }
47370  
47371                 dir_ndx = hashme(sc->dir_name);
47372 -               
47373 +
47374                 sc->dirs = splaytree_splay(sc->dirs, dir_ndx);
47375 -               
47376 +
47377                 if (sc->dirs && (sc->dirs->key == dir_ndx)) {
47378                         dir_node = sc->dirs;
47379                 }
47380 -               
47381 +
47382                 if (dir_node && file_node) {
47383                         /* we found a file */
47384 -                       
47385 +
47386                         sce = file_node->data;
47387                         fam_dir = dir_node->data;
47388 -                       
47389 +
47390                         if (fam_dir->version == sce->dir_version) {
47391                                 /* the stat()-cache entry is still ok */
47392 -                               
47393 -                               *ret_sce = sce; 
47394 +
47395 +                               *ret_sce = sce;
47396                                 return HANDLER_GO_ON;
47397                         }
47398                 }
47399 @@ -448,7 +436,7 @@
47400  #endif
47401  
47402         /*
47403 -        * *lol* 
47404 +        * *lol*
47405          * - open() + fstat() on a named-pipe results in a (intended) hang.
47406          * - stat() if regualar file + open() to see if we can read from it is better
47407          *
47408 @@ -469,16 +457,16 @@
47409  
47410         if (NULL == sce) {
47411                 int osize = 0;
47412 -                      
47413 +
47414                 if (sc->files) {
47415                         osize = sc->files->size;
47416                 }
47417  
47418                 sce = stat_cache_entry_init();
47419                 buffer_copy_string_buffer(sce->name, name);
47420 -               
47421 -               sc->files = splaytree_insert(sc->files, file_ndx, sce); 
47422 -#ifdef DEBUG_STAT_CACHE        
47423 +
47424 +               sc->files = splaytree_insert(sc->files, file_ndx, sce);
47425 +#ifdef DEBUG_STAT_CACHE
47426                 if (ctrl.size == 0) {
47427                         ctrl.size = 16;
47428                         ctrl.used = 0;
47429 @@ -499,29 +487,29 @@
47430         sce->st = st;
47431         sce->stat_ts = srv->cur_ts;
47432  
47433 -       /* catch the obvious symlinks 
47434 +       /* catch the obvious symlinks
47435          *
47436          * this is not a secure check as we still have a race-condition between
47437 -        * the stat() and the open. We can only solve this by 
47438 +        * the stat() and the open. We can only solve this by
47439          * 1. open() the file
47440          * 2. fstat() the fd
47441          *
47442          * and keeping the file open for the rest of the time. But this can
47443          * only be done at network level.
47444 -        * 
47445 +        *
47446          * */
47447         if (S_ISLNK(st.st_mode) && !con->conf.follow_symlink) {
47448                 return HANDLER_ERROR;
47449         }
47450  
47451 -       if (S_ISREG(st.st_mode)) {      
47452 +       if (S_ISREG(st.st_mode)) {
47453                 /* determine mimetype */
47454                 buffer_reset(sce->content_type);
47455 -               
47456 +
47457                 for (k = 0; k < con->conf.mimetypes->used; k++) {
47458                         data_string *ds = (data_string *)con->conf.mimetypes->data[k];
47459                         buffer *type = ds->key;
47460 -               
47461 +
47462                         if (type->used == 0) continue;
47463  
47464                         /* check if the right side is the same */
47465 @@ -539,7 +527,7 @@
47466                 }
47467  #endif
47468         }
47469 -               
47470 +
47471  #ifdef HAVE_FAM_H
47472         if (sc->fam &&
47473             (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM)) {
47474 @@ -549,19 +537,19 @@
47475                         fam_dir->fc = sc->fam;
47476  
47477                         buffer_copy_string_buffer(fam_dir->name, sc->dir_name);
47478 -                       
47479 +
47480                         fam_dir->version = 1;
47481 -                       
47482 +
47483                         fam_dir->req = calloc(1, sizeof(FAMRequest));
47484 -                       
47485 -                       if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr, 
47486 +
47487 +                       if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr,
47488                                                      fam_dir->req, fam_dir)) {
47489 -                               
47490 -                               log_error_write(srv, __FILE__, __LINE__, "sbs", 
47491 -                                               "monitoring dir failed:", 
47492 -                                               fam_dir->name, 
47493 +
47494 +                               log_error_write(srv, __FILE__, __LINE__, "sbs",
47495 +                                               "monitoring dir failed:",
47496 +                                               fam_dir->name,
47497                                                 FamErrlist[FAMErrno]);
47498 -                               
47499 +
47500                                 fam_dir_entry_free(fam_dir);
47501                         } else {
47502                                 int osize = 0;
47503 @@ -570,7 +558,7 @@
47504                                         osize = sc->dirs->size;
47505                                 }
47506  
47507 -                               sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir); 
47508 +                               sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir);
47509                                 assert(sc->dirs);
47510                                 assert(sc->dirs->data == fam_dir);
47511                                 assert(osize == (sc->dirs->size - 1));
47512 @@ -578,9 +566,9 @@
47513                 } else {
47514                         fam_dir = dir_node->data;
47515                 }
47516 -               
47517 +
47518                 /* bind the fam_fc to the stat() cache entry */
47519 -                       
47520 +
47521                 if (fam_dir) {
47522                         sce->dir_version = fam_dir->version;
47523                         sce->dir_ndx     = dir_ndx;
47524 @@ -594,11 +582,11 @@
47525  }
47526  
47527  /**
47528 - * remove stat() from cache which havn't been stat()ed for 
47529 + * remove stat() from cache which havn't been stat()ed for
47530   * more than 10 seconds
47531 - * 
47532   *
47533 - * walk though the stat-cache, collect the ids which are too old 
47534 + *
47535 + * walk though the stat-cache, collect the ids which are too old
47536   * and remove them in a second loop
47537   */
47538  
47539 @@ -639,9 +627,9 @@
47540                 sc->files = splaytree_splay(sc->files, ndx);
47541  
47542                 node = sc->files;
47543 -               
47544 +
47545                 if (node && (node->key == ndx)) {
47546 -#ifdef DEBUG_STAT_CACHE        
47547 +#ifdef DEBUG_STAT_CACHE
47548                         size_t j;
47549                         int osize = splaytree_size(sc->files);
47550                         stat_cache_entry *sce = node->data;
47551 @@ -649,7 +637,7 @@
47552                         stat_cache_entry_free(node->data);
47553                         sc->files = splaytree_delete(sc->files, ndx);
47554  
47555 -#ifdef DEBUG_STAT_CACHE        
47556 +#ifdef DEBUG_STAT_CACHE
47557                         for (j = 0; j < ctrl.used; j++) {
47558                                 if (ctrl.ptr[j] == ndx) {
47559                                         ctrl.ptr[j] = ctrl.ptr[--ctrl.used];
47560 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/stream.c lighttpd-1.4.12/src/stream.c
47561 --- lighttpd-1.4.11/src/stream.c        2005-09-23 21:50:15.000000000 +0300
47562 +++ lighttpd-1.4.12/src/stream.c        2006-07-11 21:23:40.000000000 +0300
47563 @@ -1,7 +1,6 @@
47564  #include <sys/types.h>
47565  #include <sys/stat.h>
47566  
47567 -#include <unistd.h> 
47568  #include <fcntl.h>
47569  
47570  #include "stream.h"
47571 @@ -10,6 +9,7 @@
47572  #endif
47573  
47574  #include "sys-mmap.h"
47575 +#include "sys-files.h"
47576  
47577  #ifndef O_BINARY
47578  # define O_BINARY 0
47579 @@ -19,39 +19,39 @@
47580         struct stat st;
47581  #ifdef HAVE_MMAP
47582         int fd;
47583 -#elif defined __WIN32
47584 +#elif defined _WIN32
47585         HANDLE *fh, *mh;
47586         void *p;
47587  #endif
47588  
47589         f->start = NULL;
47590 -       
47591 +
47592         if (-1 == stat(fn->ptr, &st)) {
47593                 return -1;
47594         }
47595 -       
47596 +
47597         f->size = st.st_size;
47598  
47599  #ifdef HAVE_MMAP
47600         if (-1 == (fd = open(fn->ptr, O_RDONLY | O_BINARY))) {
47601                 return -1;
47602         }
47603 -       
47604 +
47605         f->start = mmap(0, f->size, PROT_READ, MAP_SHARED, fd, 0);
47606 -       
47607 +
47608         close(fd);
47609 -       
47610 +
47611         if (MAP_FAILED == f->start) {
47612                 return -1;
47613         }
47614  
47615 -#elif defined __WIN32
47616 -       fh = CreateFile(fn->ptr, 
47617 -                       GENERIC_READ, 
47618 -                       FILE_SHARE_READ, 
47619 -                       NULL, 
47620 -                       OPEN_EXISTING, 
47621 -                       FILE_ATTRIBUTE_READONLY, 
47622 +#elif defined _WIN32
47623 +       fh = CreateFile(fn->ptr,
47624 +                       GENERIC_READ,
47625 +                       FILE_SHARE_READ,
47626 +                       NULL,
47627 +                       OPEN_EXISTING,
47628 +                       FILE_ATTRIBUTE_READONLY,
47629                         NULL);
47630  
47631         if (!fh) return -1;
47632 @@ -66,7 +66,7 @@
47633         if (!mh) {
47634                 LPVOID lpMsgBuf;
47635                 FormatMessage(
47636 -                       FORMAT_MESSAGE_ALLOCATE_BUFFER | 
47637 +                       FORMAT_MESSAGE_ALLOCATE_BUFFER |
47638                         FORMAT_MESSAGE_FROM_SYSTEM,
47639                         NULL,
47640                         GetLastError(),
47641 @@ -76,7 +76,7 @@
47642  
47643                 return -1;
47644         }
47645 -       
47646 +
47647         p = MapViewOfFile(mh,
47648                         FILE_MAP_READ,
47649                         0,
47650 @@ -87,9 +87,9 @@
47651  
47652         f->start = p;
47653  #else
47654 -# error no mmap found  
47655 +# error no mmap found
47656  #endif
47657 -       
47658 +
47659         return 0;
47660  }
47661  
47662 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/sys-mmap.h lighttpd-1.4.12/src/sys-mmap.h
47663 --- lighttpd-1.4.11/src/sys-mmap.h      2005-08-11 01:26:34.000000000 +0300
47664 +++ lighttpd-1.4.12/src/sys-mmap.h      2006-07-11 21:23:40.000000000 +0300
47665 @@ -1,7 +1,7 @@
47666  #ifndef WIN32_MMAP_H
47667  #define WIN32_MMAP_H
47668  
47669 -#ifdef __WIN32
47670 +#ifdef _WIN32
47671  
47672  #define MAP_FAILED -1
47673  #define PROT_SHARED 0
47674 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/src/sys-socket.h lighttpd-1.4.12/src/sys-socket.h
47675 --- lighttpd-1.4.11/src/sys-socket.h    2005-08-11 01:26:39.000000000 +0300
47676 +++ lighttpd-1.4.12/src/sys-socket.h    2006-07-11 21:23:40.000000000 +0300
47677 @@ -1,15 +1,26 @@
47678  #ifndef WIN32_SOCKET_H
47679  #define WIN32_SOCKET_H
47680  
47681 -#ifdef __WIN32
47682 +#ifdef _WIN32
47683  
47684  #include <winsock2.h>
47685  
47686  #define ECONNRESET WSAECONNRESET
47687  #define EINPROGRESS WSAEINPROGRESS
47688  #define EALREADY WSAEALREADY
47689 +#define ENOTCONN WSAENOTCONN
47690 +#define EWOULDBLOCK WSAEWOULDBLOCK
47691  #define ioctl ioctlsocket
47692  #define hstrerror(x) ""
47693 +#define STDIN_FILENO 0
47694 +#define STDOUT_FILENO 1
47695 +#define STDERR_FILENO 2
47696 +#define ssize_t int
47697 +
47698 +int inet_aton(const char *cp, struct in_addr *inp);
47699 +#define HAVE_INET_ADDR
47700 +#undef HAVE_INET_ATON
47701 +
47702  #else
47703  #include <sys/socket.h>
47704  #include <sys/ioctl.h>
47705 @@ -18,6 +29,11 @@
47706  #include <sys/un.h>
47707  #include <arpa/inet.h>
47708  
47709 +#ifndef SUN_LEN
47710 +#define SUN_LEN(su) \
47711 +        (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
47712 +#endif
47713 +
47714  #include <netdb.h>
47715  #endif
47716  
47717 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/LightyTest.pm lighttpd-1.4.12/tests/LightyTest.pm
47718 --- lighttpd-1.4.11/tests/LightyTest.pm 2006-01-14 20:32:31.000000000 +0200
47719 +++ lighttpd-1.4.12/tests/LightyTest.pm 2006-07-11 21:23:42.000000000 +0300
47720 @@ -87,14 +87,14 @@
47721         # pre-process configfile if necessary
47722         #
47723  
47724 -       unlink($self->{TESTDIR}."/tmp/cfg.file");
47725 -       system("cat ".$self->{SRCDIR}."/".$self->{CONFIGFILE}.' | perl -pe "s#\@SRCDIR\@#'.$self->{BASEDIR}.'/tests/#" > '.$self->{TESTDIR}.'/tmp/cfg.file');
47726 +       $ENV{'SRCDIR'} = $self->{BASEDIR}.'/tests';
47727 +       $ENV{'PORT'} = $self->{PORT};
47728  
47729         unlink($self->{LIGHTTPD_PIDFILE});
47730         if (1) {
47731 -               system($self->{LIGHTTPD_PATH}." -f ".$self->{TESTDIR}."/tmp/cfg.file -m ".$self->{MODULES_PATH});
47732 +               system($self->{LIGHTTPD_PATH}." -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH});
47733         } else {
47734 -               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}." &");
47735 +               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}." &");
47736         }
47737  
47738         select(undef, undef, undef, 0.1);
47739 @@ -184,7 +184,7 @@
47740                                         (my $h = $1) =~ tr/[A-Z]/[a-z]/;
47741  
47742                                         if (defined $resp_hdr{$h}) {
47743 -                                               diag(sprintf("header %s is duplicated: %s and %s\n",
47744 +                                               diag(sprintf("header '%s' is duplicated: '%s' and '%s'\n",
47745                                                              $h, $resp_hdr{$h}, $2));
47746                                         } else {
47747                                                 $resp_hdr{$h} = $2;
47748 @@ -196,6 +196,9 @@
47749                         }
47750                 }
47751  
47752 +               $t->{etag} = $resp_hdr{'etag'};
47753 +               $t->{date} = $resp_hdr{'date'};
47754 +
47755                 # check length
47756                 if (defined $resp_hdr{"content-length"}) {
47757                         $resp_body = substr($lines, 0, $resp_hdr{"content-length"});
47758 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/Makefile.am lighttpd-1.4.12/tests/Makefile.am
47759 --- lighttpd-1.4.11/tests/Makefile.am   2005-09-16 15:48:40.000000000 +0300
47760 +++ lighttpd-1.4.12/tests/Makefile.am   2006-07-11 21:23:42.000000000 +0300
47761 @@ -39,10 +39,15 @@
47762        mod-redirect.t \
47763        mod-userdir.t \
47764        mod-rewrite.t \
47765 +      mod-proxy.t \
47766        request.t \
47767        mod-ssi.t \
47768        LightyTest.pm \
47769 -      mod-setenv.t 
47770 +      mod-setenv.t \
47771 +      lowercase.t \
47772 +      lowercase.conf \
47773 +      proxy.conf \
47774 +      cachable.t
47775  
47776  
47777  TESTS_ENVIRONMENT=$(srcdir)/wrapper.sh $(srcdir) $(top_builddir) 
47778 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/Makefile.in lighttpd-1.4.12/tests/Makefile.in
47779 --- lighttpd-1.4.11/tests/Makefile.in   2006-03-07 14:21:03.000000000 +0200
47780 +++ lighttpd-1.4.12/tests/Makefile.in   2006-07-11 21:48:14.000000000 +0300
47781 @@ -1,4 +1,4 @@
47782 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
47783 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
47784  # @configure_input@
47785  
47786  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
47787 @@ -13,8 +13,6 @@
47788  # PARTICULAR PURPOSE.
47789  
47790  @SET_MAKE@
47791 -SOURCES = $(fcgi_auth_SOURCES) $(fcgi_responder_SOURCES)
47792 -
47793  srcdir = @srcdir@
47794  top_srcdir = @top_srcdir@
47795  VPATH = @srcdir@
47796 @@ -46,7 +44,7 @@
47797  am__aclocal_m4_deps = $(top_srcdir)/configure.in
47798  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
47799         $(ACLOCAL_M4)
47800 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
47801 +mkinstalldirs = $(install_sh) -d
47802  CONFIG_HEADER = $(top_builddir)/config.h
47803  CONFIG_CLEAN_FILES =
47804  am__fcgi_auth_SOURCES_DIST = fcgi-auth.c
47805 @@ -67,8 +65,8 @@
47806         $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
47807         $(AM_CFLAGS) $(CFLAGS)
47808  CCLD = $(CC)
47809 -LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
47810 -       $(AM_LDFLAGS) $(LDFLAGS) -o $@
47811 +LINK = $(LIBTOOL) --tag=CC --mode=link "$(CCLD)" $(AM_CFLAGS) \
47812 +       $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
47813  SOURCES = $(fcgi_auth_SOURCES) $(fcgi_responder_SOURCES)
47814  DIST_SOURCES = $(am__fcgi_auth_SOURCES_DIST) \
47815         $(am__fcgi_responder_SOURCES_DIST)
47816 @@ -134,7 +132,6 @@
47817  LIBTOOL = @LIBTOOL@
47818  LN_S = @LN_S@
47819  LTLIBOBJS = @LTLIBOBJS@
47820 -LUACONFIG = @LUACONFIG@
47821  LUA_CFLAGS = @LUA_CFLAGS@
47822  LUA_LIBS = @LUA_LIBS@
47823  MAINT = @MAINT@
47824 @@ -177,6 +174,7 @@
47825  ac_ct_F77 = @ac_ct_F77@
47826  ac_ct_RANLIB = @ac_ct_RANLIB@
47827  ac_ct_STRIP = @ac_ct_STRIP@
47828 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
47829  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
47830  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
47831  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
47832 @@ -253,10 +251,15 @@
47833        mod-redirect.t \
47834        mod-userdir.t \
47835        mod-rewrite.t \
47836 +      mod-proxy.t \
47837        request.t \
47838        mod-ssi.t \
47839        LightyTest.pm \
47840 -      mod-setenv.t 
47841 +      mod-setenv.t \
47842 +      lowercase.t \
47843 +      lowercase.conf \
47844 +      proxy.conf \
47845 +      cachable.t
47846  
47847  TESTS_ENVIRONMENT = $(srcdir)/wrapper.sh $(srcdir) $(top_builddir) 
47848  EXTRA_DIST = wrapper.sh lighttpd.conf \
47849 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/bug-06.conf lighttpd-1.4.12/tests/bug-06.conf
47850 --- lighttpd-1.4.11/tests/bug-06.conf   2005-08-27 17:44:19.000000000 +0300
47851 +++ lighttpd-1.4.12/tests/bug-06.conf   2006-07-11 21:23:41.000000000 +0300
47852 @@ -1,5 +1,5 @@
47853 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47854 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47855 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47856 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47857  
47858  ## bind to port (default: 80)
47859  server.port                 = 2048
47860 @@ -8,7 +8,7 @@
47861  
47862  ## bind to localhost (default: all interfaces)
47863  server.bind                = "localhost"
47864 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47865 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47866  server.name                = "www.example.org"
47867  server.tag                 = "Apache 1.3.29"
47868  
47869 @@ -59,7 +59,7 @@
47870  ######################## MODULE CONFIG ############################
47871  
47872  
47873 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47874 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47875  
47876  mimetype.assign             = ( ".png"  => "image/png", 
47877                                  ".jpg"  => "image/jpeg",
47878 @@ -77,7 +77,7 @@
47879                                 ".c"    => "text/plain",
47880                                 ".conf" => "text/plain" )
47881  
47882 -compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
47883 +compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
47884  compress.filetype           = ("text/plain", "text/html")
47885  
47886  setenv.add-environment      = ( "TRAC_ENV" => "foo")
47887 @@ -90,7 +90,7 @@
47888                                     "host" => "127.0.0.1",
47889                                     "port" => 1026,
47890  #                                  "mode" => "authorizer",
47891 -#                                  "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
47892 +#                                  "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
47893                                   )
47894                                 )
47895                               )
47896 @@ -106,7 +106,7 @@
47897  ssl.pemfile                 = "server.pem"
47898  
47899  auth.backend                = "plain"
47900 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
47901 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
47902  auth.backend.plain.groupfile = "lighttpd.group"
47903  
47904  auth.backend.ldap.hostname  = "localhost"
47905 @@ -149,15 +149,15 @@
47906  status.config-url           = "/server-config"
47907  
47908  simple-vhost.document-root  = "pages"
47909 -simple-vhost.server-root    = "@SRCDIR@/tmp/lighttpd/servers/"
47910 +simple-vhost.server-root    = env.SRCDIR + "/tmp/lighttpd/servers/"
47911  simple-vhost.default-host   = "www.example.org"
47912  
47913  $HTTP["host"] == "vvv.example.org" {
47914 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47915 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47916  }
47917  
47918  $HTTP["host"] == "zzz.example.org" {
47919 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47920 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47921    server.name = "zzz.example.org"
47922  }
47923  
47924 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/bug-12.conf lighttpd-1.4.12/tests/bug-12.conf
47925 --- lighttpd-1.4.11/tests/bug-12.conf   2005-08-27 17:44:19.000000000 +0300
47926 +++ lighttpd-1.4.12/tests/bug-12.conf   2006-07-11 21:23:41.000000000 +0300
47927 @@ -1,5 +1,5 @@
47928 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47929 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47930 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47931 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47932  
47933  ## bind to port (default: 80)
47934  server.port                 = 2048
47935 @@ -8,7 +8,7 @@
47936  
47937  ## bind to localhost (default: all interfaces)
47938  server.bind                = "localhost"
47939 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47940 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47941  server.name                = "www.example.org"
47942  server.tag                 = "Apache 1.3.29"
47943  
47944 @@ -61,7 +61,7 @@
47945  ######################## MODULE CONFIG ############################
47946  
47947  
47948 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47949 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47950  
47951  mimetype.assign             = ( ".png"  => "image/png", 
47952                                  ".jpg"  => "image/jpeg",
47953 @@ -79,7 +79,7 @@
47954                                 ".c"    => "text/plain",
47955                                 ".conf" => "text/plain" )
47956  
47957 -compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
47958 +compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
47959  compress.filetype           = ("text/plain", "text/html")
47960  
47961  setenv.add-environment      = ( "TRAC_ENV" => "foo")
47962 @@ -92,7 +92,7 @@
47963                                     "host" => "127.0.0.1",
47964                                     "port" => 1026,
47965  #                                  "mode" => "authorizer",
47966 -#                                  "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
47967 +#                                  "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
47968                                   )
47969                                 )
47970                               )
47971 @@ -108,7 +108,7 @@
47972  ssl.pemfile                 = "server.pem"
47973  
47974  auth.backend                = "plain"
47975 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
47976 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
47977  auth.backend.plain.groupfile = "lighttpd.group"
47978  
47979  auth.backend.ldap.hostname  = "localhost"
47980 @@ -151,15 +151,15 @@
47981  status.config-url           = "/server-config"
47982  
47983  simple-vhost.document-root  = "pages"
47984 -simple-vhost.server-root    = "@SRCDIR@/tmp/lighttpd/servers/"
47985 +simple-vhost.server-root    = env.SRCDIR + "/tmp/lighttpd/servers/"
47986  simple-vhost.default-host   = "www.example.org"
47987  
47988  $HTTP["host"] == "vvv.example.org" {
47989 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47990 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47991  }
47992  
47993  $HTTP["host"] == "zzz.example.org" {
47994 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47995 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47996    server.name = "zzz.example.org"
47997  }
47998  
47999 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/cachable.t lighttpd-1.4.12/tests/cachable.t
48000 --- lighttpd-1.4.11/tests/cachable.t    1970-01-01 03:00:00.000000000 +0300
48001 +++ lighttpd-1.4.12/tests/cachable.t    2006-07-11 21:23:41.000000000 +0300
48002 @@ -0,0 +1,112 @@
48003 +#!/usr/bin/env perl
48004 +BEGIN {
48005 +    # add current source dir to the include-path
48006 +    # we need this for make distcheck
48007 +   (my $srcdir = $0) =~ s#/[^/]+$#/#;
48008 +   unshift @INC, $srcdir;
48009 +}
48010 +
48011 +use strict;
48012 +use IO::Socket;
48013 +use Test::More tests => 12;
48014 +use LightyTest;
48015 +
48016 +my $tf = LightyTest->new();
48017 +my $t;
48018 +
48019 +$tf->{CONFIGFILE} = 'lighttpd.conf';
48020 +    
48021 +ok($tf->start_proc == 0, "Starting lighttpd") or die();
48022 +
48023 +## check if If-Modified-Since, If-None-Match works
48024 +
48025 +$t->{REQUEST}  = ( <<EOF
48026 +GET / HTTP/1.0
48027 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT
48028 +EOF
48029 + );
48030 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48031 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since');
48032 +
48033 +$t->{REQUEST}  = ( <<EOF
48034 +GET / HTTP/1.0
48035 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
48036 +EOF
48037 + );
48038 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48039 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since, comment');
48040 +
48041 +my $now = $t->{date};
48042 +
48043 +$t->{REQUEST}  = ( <<EOF
48044 +GET / HTTP/1.0
48045 +If-Modified-Since: $now
48046 +EOF
48047 + );
48048 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
48049 +ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since');
48050 +
48051 +$t->{REQUEST}  = ( <<EOF
48052 +GET / HTTP/1.0
48053 +If-Modified-Since: $now; foo
48054 +EOF
48055 + );
48056 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
48057 +ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since, comment');
48058 +
48059 +$t->{REQUEST}  = ( <<EOF
48060 +GET / HTTP/1.0
48061 +If-None-Match: foo
48062 +EOF
48063 + );
48064 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48065 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
48066 +
48067 +my $etag = $t->{etag};
48068 +
48069 +$t->{REQUEST}  = ( <<EOF
48070 +GET / HTTP/1.0
48071 +If-None-Match: $etag
48072 +EOF
48073 + );
48074 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
48075 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
48076 +
48077 +$t->{REQUEST}  = ( <<EOF
48078 +GET / HTTP/1.0
48079 +If-None-Match: $etag
48080 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
48081 +EOF
48082 + );
48083 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48084 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + old Last-Modified');
48085 +
48086 +$t->{REQUEST}  = ( <<EOF
48087 +GET / HTTP/1.0
48088 +If-None-Match: $etag
48089 +If-Modified-Since: $now; foo
48090 +EOF
48091 + );
48092 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
48093 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag, Last-Modified + comment');
48094 +
48095 +$t->{REQUEST}  = ( <<EOF
48096 +GET / HTTP/1.0
48097 +If-None-Match: Foo
48098 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
48099 +EOF
48100 + );
48101 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48102 +ok($tf->handle_http($t) == 0, 'Conditional GET - old ETAG + old Last-Modified');
48103 +
48104 +$t->{REQUEST}  = ( <<EOF
48105 +GET / HTTP/1.0
48106 +If-None-Match: $etag
48107 +If-Modified-Since: $now foo
48108 +EOF
48109 + );
48110 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 412 } ];
48111 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + Last-Modified + overlong timestamp');
48112 +
48113 +ok($tf->stop_proc == 0, "Stopping lighttpd");
48114 +
48115 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/condition.conf lighttpd-1.4.12/tests/condition.conf
48116 --- lighttpd-1.4.11/tests/condition.conf        2005-08-27 17:44:19.000000000 +0300
48117 +++ lighttpd-1.4.12/tests/condition.conf        2006-07-11 21:23:41.000000000 +0300
48118 @@ -2,15 +2,15 @@
48119  debug.log-request-handling = "enable"
48120  debug.log-condition-handling = "enable"
48121  
48122 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48123 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48124 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48125 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48126  
48127  ## bind to port (default: 80)
48128  server.port                 = 2048
48129  
48130  ## bind to localhost (default: all interfaces)
48131  server.bind                = "localhost"
48132 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48133 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48134  server.name                = "www.example.org"
48135  server.tag                 = "Apache 1.3.29"
48136  
48137 @@ -22,25 +22,25 @@
48138  ######################## MODULE CONFIG ############################
48139  
48140  
48141 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48142 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48143  
48144  mimetype.assign             = ( ".html" => "text/html" )
48145  
48146  url.redirect = ("^" => "/default")
48147  
48148  $HTTP["host"] == "www.example.org" {
48149 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48150 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48151    server.name = "www.example.org"
48152    url.redirect = ("^" => "/match_1")
48153  }
48154  else $HTTP["host"] == "test1.example.org" {
48155 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48156 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48157    server.name = "test1.example.org"
48158    url.redirect = ("^" => "/match_2")
48159  }
48160  # comments
48161  else $HTTP["host"] == "test2.example.org" {
48162 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48163 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48164    server.name = "test2.example.org"
48165    url.redirect = ("^" => "/match_3")
48166  }
48167 @@ -48,7 +48,7 @@
48168          # comments
48169  
48170  else $HTTP["host"] == "test3.example.org" {
48171 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48172 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48173    server.name = "test3.example.org"
48174    url.redirect = ("^" => "/match_4")
48175  
48176 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/core-keepalive.t lighttpd-1.4.12/tests/core-keepalive.t
48177 --- lighttpd-1.4.11/tests/core-keepalive.t      2005-11-17 15:54:19.000000000 +0200
48178 +++ lighttpd-1.4.12/tests/core-keepalive.t      2006-07-11 21:23:41.000000000 +0300
48179 @@ -40,7 +40,7 @@
48180  
48181  GET /12345.txt HTTP/1.0
48182  Host: 123.example.org
48183 -Connection: keep-alive
48184 +Connection: close
48185  EOF
48186   );
48187  $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48188 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/docroot/123/Makefile.in lighttpd-1.4.12/tests/docroot/123/Makefile.in
48189 --- lighttpd-1.4.11/tests/docroot/123/Makefile.in       2006-03-07 14:21:03.000000000 +0200
48190 +++ lighttpd-1.4.12/tests/docroot/123/Makefile.in       2006-07-11 21:48:15.000000000 +0300
48191 @@ -1,4 +1,4 @@
48192 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
48193 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
48194  # @configure_input@
48195  
48196  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
48197 @@ -42,7 +42,7 @@
48198  am__aclocal_m4_deps = $(top_srcdir)/configure.in
48199  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
48200         $(ACLOCAL_M4)
48201 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
48202 +mkinstalldirs = $(install_sh) -d
48203  CONFIG_HEADER = $(top_builddir)/config.h
48204  CONFIG_CLEAN_FILES =
48205  SOURCES =
48206 @@ -100,7 +100,6 @@
48207  LIBTOOL = @LIBTOOL@
48208  LN_S = @LN_S@
48209  LTLIBOBJS = @LTLIBOBJS@
48210 -LUACONFIG = @LUACONFIG@
48211  LUA_CFLAGS = @LUA_CFLAGS@
48212  LUA_LIBS = @LUA_LIBS@
48213  MAINT = @MAINT@
48214 @@ -143,6 +142,7 @@
48215  ac_ct_F77 = @ac_ct_F77@
48216  ac_ct_RANLIB = @ac_ct_RANLIB@
48217  ac_ct_STRIP = @ac_ct_STRIP@
48218 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
48219  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
48220  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
48221  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
48222 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/docroot/Makefile.in lighttpd-1.4.12/tests/docroot/Makefile.in
48223 --- lighttpd-1.4.11/tests/docroot/Makefile.in   2006-03-07 14:21:04.000000000 +0200
48224 +++ lighttpd-1.4.12/tests/docroot/Makefile.in   2006-07-11 21:48:15.000000000 +0300
48225 @@ -1,4 +1,4 @@
48226 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
48227 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
48228  # @configure_input@
48229  
48230  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
48231 @@ -42,7 +42,7 @@
48232  am__aclocal_m4_deps = $(top_srcdir)/configure.in
48233  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
48234         $(ACLOCAL_M4)
48235 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
48236 +mkinstalldirs = $(install_sh) -d
48237  CONFIG_HEADER = $(top_builddir)/config.h
48238  CONFIG_CLEAN_FILES =
48239  SOURCES =
48240 @@ -109,7 +109,6 @@
48241  LIBTOOL = @LIBTOOL@
48242  LN_S = @LN_S@
48243  LTLIBOBJS = @LTLIBOBJS@
48244 -LUACONFIG = @LUACONFIG@
48245  LUA_CFLAGS = @LUA_CFLAGS@
48246  LUA_LIBS = @LUA_LIBS@
48247  MAINT = @MAINT@
48248 @@ -152,6 +151,7 @@
48249  ac_ct_F77 = @ac_ct_F77@
48250  ac_ct_RANLIB = @ac_ct_RANLIB@
48251  ac_ct_STRIP = @ac_ct_STRIP@
48252 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
48253  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
48254  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
48255  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
48256 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/docroot/www/Makefile.in lighttpd-1.4.12/tests/docroot/www/Makefile.in
48257 --- lighttpd-1.4.11/tests/docroot/www/Makefile.in       2006-03-07 14:21:05.000000000 +0200
48258 +++ lighttpd-1.4.12/tests/docroot/www/Makefile.in       2006-07-11 21:48:15.000000000 +0300
48259 @@ -1,4 +1,4 @@
48260 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
48261 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
48262  # @configure_input@
48263  
48264  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
48265 @@ -42,7 +42,7 @@
48266  am__aclocal_m4_deps = $(top_srcdir)/configure.in
48267  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
48268         $(ACLOCAL_M4)
48269 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
48270 +mkinstalldirs = $(install_sh) -d
48271  CONFIG_HEADER = $(top_builddir)/config.h
48272  CONFIG_CLEAN_FILES =
48273  SOURCES =
48274 @@ -109,7 +109,6 @@
48275  LIBTOOL = @LIBTOOL@
48276  LN_S = @LN_S@
48277  LTLIBOBJS = @LTLIBOBJS@
48278 -LUACONFIG = @LUACONFIG@
48279  LUA_CFLAGS = @LUA_CFLAGS@
48280  LUA_LIBS = @LUA_LIBS@
48281  MAINT = @MAINT@
48282 @@ -152,6 +151,7 @@
48283  ac_ct_F77 = @ac_ct_F77@
48284  ac_ct_RANLIB = @ac_ct_RANLIB@
48285  ac_ct_STRIP = @ac_ct_STRIP@
48286 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
48287  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
48288  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
48289  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
48290 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/docroot/www/dummydir/.svn/entries lighttpd-1.4.12/tests/docroot/www/dummydir/.svn/entries
48291 --- lighttpd-1.4.11/tests/docroot/www/dummydir/.svn/entries     2006-03-09 19:21:49.000000000 +0200
48292 +++ lighttpd-1.4.12/tests/docroot/www/dummydir/.svn/entries     2006-07-11 21:23:41.000000000 +0300
48293 @@ -9,5 +9,6 @@
48294     last-author="jan"
48295     kind="dir"
48296     uuid="152afb58-edef-0310-8abb-c4023f1b3aa9"
48297 -   revision="1040"/>
48298 +   repos="svn://svn.lighttpd.net/lighttpd"
48299 +   revision="1159"/>
48300  </wc-entries>
48301 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/docroot/www/expire/Makefile.in lighttpd-1.4.12/tests/docroot/www/expire/Makefile.in
48302 --- lighttpd-1.4.11/tests/docroot/www/expire/Makefile.in        2006-03-07 14:21:05.000000000 +0200
48303 +++ lighttpd-1.4.12/tests/docroot/www/expire/Makefile.in        2006-07-11 21:48:15.000000000 +0300
48304 @@ -1,4 +1,4 @@
48305 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
48306 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
48307  # @configure_input@
48308  
48309  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
48310 @@ -42,7 +42,7 @@
48311  am__aclocal_m4_deps = $(top_srcdir)/configure.in
48312  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
48313         $(ACLOCAL_M4)
48314 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
48315 +mkinstalldirs = $(install_sh) -d
48316  CONFIG_HEADER = $(top_builddir)/config.h
48317  CONFIG_CLEAN_FILES =
48318  SOURCES =
48319 @@ -100,7 +100,6 @@
48320  LIBTOOL = @LIBTOOL@
48321  LN_S = @LN_S@
48322  LTLIBOBJS = @LTLIBOBJS@
48323 -LUACONFIG = @LUACONFIG@
48324  LUA_CFLAGS = @LUA_CFLAGS@
48325  LUA_LIBS = @LUA_LIBS@
48326  MAINT = @MAINT@
48327 @@ -143,6 +142,7 @@
48328  ac_ct_F77 = @ac_ct_F77@
48329  ac_ct_RANLIB = @ac_ct_RANLIB@
48330  ac_ct_STRIP = @ac_ct_STRIP@
48331 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
48332  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
48333  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
48334  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
48335 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/docroot/www/go/Makefile.in lighttpd-1.4.12/tests/docroot/www/go/Makefile.in
48336 --- lighttpd-1.4.11/tests/docroot/www/go/Makefile.in    2006-03-07 14:21:06.000000000 +0200
48337 +++ lighttpd-1.4.12/tests/docroot/www/go/Makefile.in    2006-07-11 21:48:16.000000000 +0300
48338 @@ -1,4 +1,4 @@
48339 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
48340 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
48341  # @configure_input@
48342  
48343  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
48344 @@ -42,7 +42,7 @@
48345  am__aclocal_m4_deps = $(top_srcdir)/configure.in
48346  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
48347         $(ACLOCAL_M4)
48348 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
48349 +mkinstalldirs = $(install_sh) -d
48350  CONFIG_HEADER = $(top_builddir)/config.h
48351  CONFIG_CLEAN_FILES =
48352  SOURCES =
48353 @@ -100,7 +100,6 @@
48354  LIBTOOL = @LIBTOOL@
48355  LN_S = @LN_S@
48356  LTLIBOBJS = @LTLIBOBJS@
48357 -LUACONFIG = @LUACONFIG@
48358  LUA_CFLAGS = @LUA_CFLAGS@
48359  LUA_LIBS = @LUA_LIBS@
48360  MAINT = @MAINT@
48361 @@ -143,6 +142,7 @@
48362  ac_ct_F77 = @ac_ct_F77@
48363  ac_ct_RANLIB = @ac_ct_RANLIB@
48364  ac_ct_STRIP = @ac_ct_STRIP@
48365 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
48366  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
48367  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
48368  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
48369 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/docroot/www/indexfile/Makefile.in lighttpd-1.4.12/tests/docroot/www/indexfile/Makefile.in
48370 --- lighttpd-1.4.11/tests/docroot/www/indexfile/Makefile.in     2006-03-07 14:21:07.000000000 +0200
48371 +++ lighttpd-1.4.12/tests/docroot/www/indexfile/Makefile.in     2006-07-11 21:48:16.000000000 +0300
48372 @@ -1,4 +1,4 @@
48373 -# Makefile.in generated by automake 1.9.5 from Makefile.am.
48374 +# Makefile.in generated by automake 1.9.6 from Makefile.am.
48375  # @configure_input@
48376  
48377  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
48378 @@ -42,7 +42,7 @@
48379  am__aclocal_m4_deps = $(top_srcdir)/configure.in
48380  am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
48381         $(ACLOCAL_M4)
48382 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
48383 +mkinstalldirs = $(install_sh) -d
48384  CONFIG_HEADER = $(top_builddir)/config.h
48385  CONFIG_CLEAN_FILES =
48386  SOURCES =
48387 @@ -100,7 +100,6 @@
48388  LIBTOOL = @LIBTOOL@
48389  LN_S = @LN_S@
48390  LTLIBOBJS = @LTLIBOBJS@
48391 -LUACONFIG = @LUACONFIG@
48392  LUA_CFLAGS = @LUA_CFLAGS@
48393  LUA_LIBS = @LUA_LIBS@
48394  MAINT = @MAINT@
48395 @@ -143,6 +142,7 @@
48396  ac_ct_F77 = @ac_ct_F77@
48397  ac_ct_RANLIB = @ac_ct_RANLIB@
48398  ac_ct_STRIP = @ac_ct_STRIP@
48399 +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
48400  am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
48401  am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
48402  am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
48403 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/fastcgi-10.conf lighttpd-1.4.12/tests/fastcgi-10.conf
48404 --- lighttpd-1.4.11/tests/fastcgi-10.conf       2005-08-31 23:36:34.000000000 +0300
48405 +++ lighttpd-1.4.12/tests/fastcgi-10.conf       2006-07-11 21:23:41.000000000 +0300
48406 @@ -1,12 +1,12 @@
48407 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48408 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48409 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48410 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48411  
48412  ## bind to port (default: 80)
48413  server.port                 = 2048
48414  
48415  ## bind to localhost (default: all interfaces)
48416  server.bind                = "localhost"
48417 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48418 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48419  server.name                = "www.example.org"
48420  server.tag                 = "Apache 1.3.29"
48421  
48422 @@ -44,7 +44,7 @@
48423  ######################## MODULE CONFIG ############################
48424  
48425  
48426 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48427 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48428  
48429  mimetype.assign             = ( ".png"  => "image/png", 
48430                                  ".jpg"  => "image/jpeg",
48431 @@ -62,7 +62,7 @@
48432                                 ".c"    => "text/plain",
48433                                 ".conf" => "text/plain" )
48434  
48435 -compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48436 +compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48437  compress.filetype           = ("text/plain", "text/html")
48438  
48439  fastcgi.debug               = 0
48440 @@ -85,7 +85,7 @@
48441  ssl.pemfile                 = "server.pem"
48442  
48443  auth.backend                = "plain"
48444 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48445 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48446  auth.backend.plain.groupfile = "lighttpd.group"
48447  
48448  auth.backend.ldap.hostname  = "localhost"
48449 @@ -128,11 +128,11 @@
48450  status.config-url           = "/server-config"
48451  
48452  $HTTP["host"] == "vvv.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  }
48456  
48457  $HTTP["host"] == "zzz.example.org" {
48458 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48459 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48460    server.name = "zzz.example.org"
48461  }
48462  
48463 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/fastcgi-13.conf lighttpd-1.4.12/tests/fastcgi-13.conf
48464 --- lighttpd-1.4.11/tests/fastcgi-13.conf       2006-01-03 12:38:17.000000000 +0200
48465 +++ lighttpd-1.4.12/tests/fastcgi-13.conf       2006-07-11 21:23:41.000000000 +0300
48466 @@ -1,5 +1,5 @@
48467 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48468 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48469 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48470 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48471  
48472  debug.log-request-header   = "enable"
48473  debug.log-response-header  = "enable"
48474 @@ -10,7 +10,7 @@
48475  
48476  ## bind to localhost (default: all interfaces)
48477  server.bind                = "localhost"
48478 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48479 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48480  server.name                = "www.example.org"
48481  server.tag                 = "Apache 1.3.29"
48482  
48483 @@ -59,7 +59,7 @@
48484  ######################## MODULE CONFIG ############################
48485  
48486  
48487 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48488 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48489  
48490  mimetype.assign             = ( ".png"  => "image/png", 
48491                                  ".jpg"  => "image/jpeg",
48492 @@ -77,7 +77,7 @@
48493                                 ".c"    => "text/plain",
48494                                 ".conf" => "text/plain" )
48495  
48496 -compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48497 +compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48498  compress.filetype           = ("text/plain", "text/html")
48499  
48500  fastcgi.debug               = 0
48501 @@ -102,7 +102,7 @@
48502  ssl.pemfile                 = "server.pem"
48503  
48504  auth.backend                = "plain"
48505 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48506 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48507  auth.backend.plain.groupfile = "lighttpd.group"
48508  
48509  auth.backend.ldap.hostname  = "localhost"
48510 @@ -145,11 +145,11 @@
48511  status.config-url           = "/server-config"
48512  
48513  $HTTP["host"] == "vvv.example.org" {
48514 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48515 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48516  }
48517  
48518  $HTTP["host"] == "zzz.example.org" {
48519 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48520 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48521    server.name = "zzz.example.org"
48522  }
48523  
48524 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/fastcgi-auth.conf lighttpd-1.4.12/tests/fastcgi-auth.conf
48525 --- lighttpd-1.4.11/tests/fastcgi-auth.conf     2005-08-27 17:44:19.000000000 +0300
48526 +++ lighttpd-1.4.12/tests/fastcgi-auth.conf     2006-07-11 21:23:42.000000000 +0300
48527 @@ -1,5 +1,5 @@
48528 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48529 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48530 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48531 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48532  
48533  debug.log-request-header   = "enable"
48534  debug.log-response-header  = "enable"
48535 @@ -12,7 +12,7 @@
48536  
48537  ## bind to localhost (default: all interfaces)
48538  server.bind                = "localhost"
48539 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48540 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48541  server.name                = "www.example.org"
48542  server.tag                 = "Apache 1.3.29"
48543  
48544 @@ -61,7 +61,7 @@
48545  ######################## MODULE CONFIG ############################
48546  
48547  
48548 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48549 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48550  
48551  mimetype.assign             = ( ".png"  => "image/png", 
48552                                  ".jpg"  => "image/jpeg",
48553 @@ -79,7 +79,7 @@
48554                                 ".c"    => "text/plain",
48555                                 ".conf" => "text/plain" )
48556  
48557 -compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48558 +compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48559  compress.filetype           = ("text/plain", "text/html")
48560  
48561  fastcgi.debug               = 0
48562 @@ -87,9 +87,9 @@
48563                                    "grisu" => ( 
48564                                     "host" => "127.0.0.1",
48565                                     "port" => 20000,
48566 -                                   "bin-path" => "@SRCDIR@/fcgi-auth",
48567 +                                   "bin-path" => env.SRCDIR + "/fcgi-auth",
48568                                      "mode" => "authorizer",
48569 -                                    "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
48570 +                                    "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
48571                                     
48572                                   )
48573                                 )
48574 @@ -106,7 +106,7 @@
48575  ssl.pemfile                 = "server.pem"
48576  
48577  auth.backend                = "plain"
48578 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48579 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48580  auth.backend.plain.groupfile = "lighttpd.group"
48581  
48582  auth.backend.ldap.hostname  = "localhost"
48583 @@ -149,11 +149,11 @@
48584  status.config-url           = "/server-config"
48585  
48586  $HTTP["host"] == "vvv.example.org" {
48587 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48588 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48589  }
48590  
48591  $HTTP["host"] == "zzz.example.org" {
48592 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48593 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48594    server.name = "zzz.example.org"
48595  }
48596  
48597 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/fastcgi-responder.conf lighttpd-1.4.12/tests/fastcgi-responder.conf
48598 --- lighttpd-1.4.11/tests/fastcgi-responder.conf        2005-08-27 17:44:19.000000000 +0300
48599 +++ lighttpd-1.4.12/tests/fastcgi-responder.conf        2006-07-11 21:23:41.000000000 +0300
48600 @@ -1,5 +1,5 @@
48601 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48602 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48603 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48604 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48605  
48606  #debug.log-request-header   = "enable"
48607  #debug.log-response-header  = "enable"
48608 @@ -15,7 +15,7 @@
48609  
48610  ## bind to localhost (default: all interfaces)
48611  server.bind                = "localhost"
48612 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48613 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48614  server.name                = "www.example.org"
48615  server.tag                 = "Apache 1.3.29"
48616  
48617 @@ -64,7 +64,7 @@
48618  ######################## MODULE CONFIG ############################
48619  
48620  
48621 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48622 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48623  
48624  mimetype.assign             = ( ".png"  => "image/png", 
48625                                  ".jpg"  => "image/jpeg",
48626 @@ -82,7 +82,7 @@
48627                                 ".c"    => "text/plain",
48628                                 ".conf" => "text/plain" )
48629  
48630 -compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48631 +compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48632  compress.filetype           = ("text/plain", "text/html")
48633  
48634  fastcgi.debug               = 0
48635 @@ -90,10 +90,11 @@
48636                                    "grisu" => ( 
48637                                     "host" => "127.0.0.1",
48638                                     "port" => 10000,
48639 -                                   "bin-path" => "@SRCDIR@/fcgi-responder",
48640 +                                   "bin-path" => env.SRCDIR + "/fcgi-responder",
48641                                     "check-local" => "disable",
48642                                     "max-procs" => 1,
48643 -                                   "min-procs" => 1
48644 +                                   "min-procs" => 1,
48645 +                                   "allow-x-send-file" => "enable",
48646                                   )
48647                                 )
48648                               )
48649 @@ -109,7 +110,7 @@
48650  ssl.pemfile                 = "server.pem"
48651  
48652  auth.backend                = "plain"
48653 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48654 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48655  auth.backend.plain.groupfile = "lighttpd.group"
48656  
48657  auth.backend.ldap.hostname  = "localhost"
48658 @@ -152,11 +153,11 @@
48659  status.config-url           = "/server-config"
48660  
48661  $HTTP["host"] == "vvv.example.org" {
48662 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48663 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48664  }
48665  
48666  $HTTP["host"] == "zzz.example.org" {
48667 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48668 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48669    server.name = "zzz.example.org"
48670  }
48671  
48672 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/fcgi-responder.c lighttpd-1.4.12/tests/fcgi-responder.c
48673 --- lighttpd-1.4.11/tests/fcgi-responder.c      2005-08-11 01:26:55.000000000 +0300
48674 +++ lighttpd-1.4.12/tests/fcgi-responder.c      2006-07-11 21:23:41.000000000 +0300
48675 @@ -6,11 +6,17 @@
48676  int main () {
48677         int num_requests = 2;
48678         
48679 -       while (num_requests > 0 &&
48680 -              FCGI_Accept() >= 0) {
48681 -               char* p;
48682 -               
48683 -               if (NULL != (p = getenv("QUERY_STRING"))) {
48684 +       while (num_requests > 0 && FCGI_Accept() >= 0) {
48685 +               char* p = NULL;
48686 +               char* doc_root = NULL;
48687 +               char fname[4096];
48688 +               char* pfname = (char *)fname;
48689 +
48690 +               doc_root = getenv("DOCUMENT_ROOT");
48691 +               p = getenv("QUERY_STRING");
48692 +
48693 +               if (NULL != p && NULL != doc_root) {
48694 +                       snprintf(pfname, sizeof(fname), "%s/phpinfo.php", doc_root);
48695                         if (0 == strcmp(p, "lf")) {
48696                                 printf("Status: 200 OK\n\n");
48697                         } else if (0 == strcmp(p, "crlf")) {
48698 @@ -23,6 +29,18 @@
48699                                 printf("Status: 200 OK\r\n");
48700                                 fflush(stdout);
48701                                 printf("\r\n");
48702 +                       } else if (0 == strcmp(p,"x-lighttpd-send-file")) {
48703 +                               printf("Status: 200 OK\r\n");
48704 +                               printf("X-LIGHTTPD-send-file: %s\r\n", pfname);
48705 +                               printf("\r\n");
48706 +                       } else if (0 == strcmp(p,"xsendfile")) {
48707 +                               printf("Status: 200 OK\r\n");
48708 +                               printf("X-Sendfile: %s\r\n", pfname);
48709 +                               printf("\r\n");
48710 +                       } else if (0 == strcmp(p,"xsendfile-mixed-case")) {
48711 +                               printf("Status: 200 OK\r\n");
48712 +                               printf("X-SeNdFiLe: %s\r\n", pfname);
48713 +                               printf("\r\n");
48714                         } else if (0 == strcmp(p, "die-at-end")) {
48715                                 printf("Status: 200 OK\r\n\r\n");
48716                                 num_requests--;
48717 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/lighttpd.conf lighttpd-1.4.12/tests/lighttpd.conf
48718 --- lighttpd-1.4.11/tests/lighttpd.conf 2006-03-09 15:26:58.000000000 +0200
48719 +++ lighttpd-1.4.12/tests/lighttpd.conf 2006-07-11 21:23:41.000000000 +0300
48720 @@ -1,80 +1,18 @@
48721 -debug.log-request-handling = "enable"
48722 -debug.log-condition-handling = "enable"
48723 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48724 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48725 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48726 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48727 +server.tag = "Apache 1.3.29"
48728  
48729  ## 64 Mbyte ... nice limit
48730  server.max-request-size = 65000
48731  
48732 -## bind to port (default: 80)
48733 -server.port                 = 2048
48734 +include "default.conf"
48735  
48736 -## bind to localhost (default: all interfaces)
48737 -server.bind                = "localhost"
48738 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48739 -server.name                = "www.example.org"
48740 -server.tag                 = "Apache 1.3.29"
48741 -
48742 -server.dir-listing          = "enable"
48743 -
48744 -#server.event-handler        = "linux-sysepoll"
48745 -#server.event-handler        = "linux-rtsig"
48746 -
48747 -#server.modules.path         = ""
48748 -server.modules              = ( 
48749 -                               "mod_rewrite",
48750 -                               "mod_setenv",
48751 -                               "mod_secdownload",
48752 -                               "mod_access", 
48753 -                               "mod_auth",
48754 -#                              "mod_httptls",
48755 -                               "mod_status", 
48756 -                               "mod_expire",
48757 -                               "mod_simple_vhost",
48758 -                               "mod_redirect", 
48759 -#                              "mod_evhost",
48760 -#                              "mod_localizer",
48761 -                               "mod_fastcgi",
48762 -                               "mod_cgi",
48763 -                               "mod_compress",
48764 -                               "mod_userdir",
48765 -                               "mod_ssi",
48766 -                               "mod_accesslog" ) 
48767 -
48768 -server.indexfiles           = ( "index.php", "index.html", 
48769 -                                "index.htm", "default.htm" )
48770 -
48771 -
48772 -######################## MODULE CONFIG ############################
48773 -
48774 -ssi.extension = ( ".shtml" )
48775 -
48776 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48777 -
48778 -mimetype.assign             = ( ".png"  => "image/png", 
48779 -                                ".jpg"  => "image/jpeg",
48780 -                                ".jpeg" => "image/jpeg",
48781 -                                ".gif"  => "image/gif",
48782 -                                ".html" => "text/html",
48783 -                                ".htm"  => "text/html",
48784 -                                ".pdf"  => "application/pdf",
48785 -                                ".swf"  => "application/x-shockwave-flash",
48786 -                                ".spl"  => "application/futuresplash",
48787 -                                ".txt"  => "text/plain",
48788 -                                ".tar.gz" =>   "application/x-tgz",
48789 -                                ".tgz"  => "application/x-tgz",
48790 -                                ".gz"   => "application/x-gzip",
48791 -                               ".c"    => "text/plain",
48792 -                               ".conf" => "text/plain" )
48793 +setenv.add-request-header   = ( "FOO" => "foo")
48794 +setenv.add-response-header  = ( "BAR" => "foo")
48795  
48796  $HTTP["host"] == "cache.example.org" {
48797 -  compress.cache-dir          = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48798 +  compress.cache-dir          = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48799  }
48800 -compress.filetype           = ("text/plain", "text/html")
48801 -
48802 -setenv.add-environment      = ( "TRAC_ENV" => "tracenv", "SETENV" => "setenv")
48803 -setenv.add-request-header   = ( "FOO" => "foo")
48804 -setenv.add-response-header  = ( "BAR" => "foo")
48805  
48806  $HTTP["url"] =~ "\.pdf$" {
48807    server.range-requests = "disable"
48808 @@ -85,76 +23,31 @@
48809                                 "/prefix.fcgi" => ( ( "host" => "127.0.0.1", "port" => 1026, "check-local" => "disable", "broken-scriptfilename" => "enable" ) )
48810                               )
48811                 
48812 -
48813 -cgi.assign                  = ( ".pl"  => "/usr/bin/perl",
48814 -                                ".cgi" => "/usr/bin/perl",
48815 -                               ".py"  => "/usr/bin/python" )
48816 -                       
48817 -userdir.include-user = ( "jan" )
48818 -userdir.path = "/"
48819 -
48820 -ssl.engine                  = "disable"
48821 -ssl.pemfile                 = "server.pem"
48822 -
48823  $HTTP["host"] == "auth-htpasswd.example.org" {
48824         auth.backend                = "htpasswd"
48825  }
48826  
48827 -auth.backend                = "plain"
48828 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48829 -
48830 -auth.backend.htpasswd.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.htpasswd"
48831 -
48832 -
48833 -auth.require                = ( "/server-status" => 
48834 -                                ( 
48835 -                                 "method"  => "digest",
48836 -                                 "realm"   => "download archiv",
48837 -                                 "require" => "group=www|user=jan|host=192.168.2.10"
48838 -                               ),
48839 -                               "/server-config" => 
48840 -                                ( 
48841 -                                 "method"  => "basic",
48842 -                                 "realm"   => "download archiv",
48843 -                                 "require" => "valid-user"
48844 -                               )
48845 -                              )
48846 -
48847 -url.access-deny             = ( "~", ".inc")
48848 -
48849 -url.rewrite                = ( "^/rewrite/foo($|\?.+)" => "/indexfile/rewrite.php$1",
48850 -                               "^/rewrite/bar(?:$|\?(.+))" => "/indexfile/rewrite.php?bar&$1" )
48851 -
48852 -expire.url                  = ( "/expire/access" => "access 2 hours", 
48853 -                               "/expire/modification" => "access plus 1 seconds 2 minutes")
48854 -
48855 -#cache.cache-dir             = "/home/weigon/wwwroot/cache/"
48856 -
48857 -#### status module
48858 -status.status-url           = "/server-status"
48859 -status.config-url           = "/server-config"
48860 -
48861  $HTTP["host"] == "vvv.example.org" {
48862 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48863 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48864    secdownload.secret          = "verysecret"
48865 -  secdownload.document-root   = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48866 +  secdownload.document-root   = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48867    secdownload.uri-prefix      = "/sec/"
48868    secdownload.timeout         = 120
48869  }
48870  
48871  $HTTP["host"] == "zzz.example.org" {
48872 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48873 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48874    server.name = "zzz.example.org"
48875  }
48876  
48877  $HTTP["host"] == "no-simple.example.org" {
48878 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/123.example.org/pages/"
48879 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/123.example.org/pages/"
48880    server.name = "zzz.example.org"
48881  }
48882  
48883  $HTTP["host"] !~ "(no-simple\.example\.org)" {
48884    simple-vhost.document-root  = "pages"
48885 -  simple-vhost.server-root    = "@SRCDIR@/tmp/lighttpd/servers/"
48886 +  simple-vhost.server-root    = env.SRCDIR + "/tmp/lighttpd/servers/"
48887    simple-vhost.default-host   = "www.example.org"
48888  }
48889  
48890 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/lowercase.conf lighttpd-1.4.12/tests/lowercase.conf
48891 --- lighttpd-1.4.11/tests/lowercase.conf        1970-01-01 03:00:00.000000000 +0300
48892 +++ lighttpd-1.4.12/tests/lowercase.conf        2006-07-11 21:23:41.000000000 +0300
48893 @@ -0,0 +1,80 @@
48894 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48895 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48896 +
48897 +## bind to port (default: 80)
48898 +server.port                 = 2048
48899 +
48900 +## bind to localhost (default: all interfaces)
48901 +server.bind                = "localhost"
48902 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48903 +
48904 +server.force-lowercase-filenames = "enable"
48905 +
48906 +server.dir-listing          = "enable"
48907 +
48908 +server.modules              = ( 
48909 +                               "mod_rewrite",
48910 +                               "mod_setenv",
48911 +                               "mod_secdownload",
48912 +                               "mod_access", 
48913 +                               "mod_auth",
48914 +                               "mod_status", 
48915 +                               "mod_expire",
48916 +                               "mod_redirect", 
48917 +                               "mod_fastcgi",
48918 +                               "mod_cgi" ) 
48919 +
48920 +server.indexfiles           = ( "index.php", "index.html", 
48921 +                                "index.htm", "default.htm" )
48922 +
48923 +
48924 +######################## MODULE CONFIG ############################
48925 +
48926 +mimetype.assign             = ( ".png"  => "image/png", 
48927 +                                ".jpg"  => "image/jpeg",
48928 +                                ".jpeg" => "image/jpeg",
48929 +                                ".gif"  => "image/gif",
48930 +                                ".html" => "text/html",
48931 +                                ".htm"  => "text/html",
48932 +                                ".pdf"  => "application/pdf",
48933 +                                ".swf"  => "application/x-shockwave-flash",
48934 +                                ".spl"  => "application/futuresplash",
48935 +                                ".txt"  => "text/plain",
48936 +                                ".tar.gz" =>   "application/x-tgz",
48937 +                                ".tgz"  => "application/x-tgz",
48938 +                                ".gz"   => "application/x-gzip",
48939 +                               ".c"    => "text/plain",
48940 +                               ".conf" => "text/plain" )
48941 +
48942 +fastcgi.debug               = 0
48943 +fastcgi.server              = ( ".php" =>        ( ( "host" => "127.0.0.1", "port" => 1026, "broken-scriptfilename" => "enable" ) ),
48944 +                               "/prefix.fcgi" => ( ( "host" => "127.0.0.1", "port" => 1026, "check-local" => "disable", "broken-scriptfilename" => "enable" ) )
48945 +                             )
48946 +               
48947 +
48948 +cgi.assign                  = ( ".pl"  => "/usr/bin/perl",
48949 +                                ".cgi" => "/usr/bin/perl",
48950 +                               ".py"  => "/usr/bin/python" )
48951 +                       
48952 +auth.backend                = "plain"
48953 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48954 +
48955 +auth.backend.htpasswd.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.htpasswd"
48956 +
48957 +$HTTP["host"] == "lowercase-auth" {
48958 +  auth.require             = ( "/image.jpg" => 
48959 +                                ( 
48960 +                                 "method"  => "digest",
48961 +                                 "realm"   => "download archiv",
48962 +                                 "require" => "valid-user"
48963 +                               )
48964 +                              )
48965 +}
48966 +
48967 +$HTTP["host"] == "lowercase-deny" {
48968 +  url.access-deny             = ( ".jpg")
48969 +}
48970 +
48971 +$HTTP["host"] == "lowercase-exclude" {
48972 +  static-file.exclude-extensions = ( ".jpg" )
48973 +}
48974 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/lowercase.t lighttpd-1.4.12/tests/lowercase.t
48975 --- lighttpd-1.4.11/tests/lowercase.t   1970-01-01 03:00:00.000000000 +0300
48976 +++ lighttpd-1.4.12/tests/lowercase.t   2006-07-11 21:23:41.000000000 +0300
48977 @@ -0,0 +1,94 @@
48978 +#!/usr/bin/env perl
48979 +BEGIN {
48980 +    # add current source dir to the include-path
48981 +    # we need this for make distcheck
48982 +   (my $srcdir = $0) =~ s#/[^/]+$#/#;
48983 +   unshift @INC, $srcdir;
48984 +}
48985 +
48986 +use strict;
48987 +use IO::Socket;
48988 +use Test::More tests => 10;
48989 +use LightyTest;
48990 +
48991 +my $tf = LightyTest->new();
48992 +my $t;
48993 +
48994 +$tf->{CONFIGFILE} = 'lowercase.conf';
48995 +    
48996 +ok($tf->start_proc == 0, "Starting lighttpd") or die();
48997 +
48998 +## check if lower-casing works
48999 +
49000 +$t->{REQUEST}  = ( <<EOF
49001 +GET /image.JPG HTTP/1.0
49002 +EOF
49003 + );
49004 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
49005 +ok($tf->handle_http($t) == 0, 'uppercase access');
49006 +
49007 +$t->{REQUEST}  = ( <<EOF
49008 +GET /image.jpg HTTP/1.0
49009 +EOF
49010 + );
49011 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
49012 +ok($tf->handle_http($t) == 0, 'lowercase access');
49013 +
49014 +## check that mod-auth works
49015 +
49016 +$t->{REQUEST}  = ( <<EOF
49017 +GET /image.JPG HTTP/1.0
49018 +Host: lowercase-auth
49019 +EOF
49020 + );
49021 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
49022 +ok($tf->handle_http($t) == 0, 'uppercase access');
49023 +
49024 +$t->{REQUEST}  = ( <<EOF
49025 +GET /image.jpg HTTP/1.0
49026 +Host: lowercase-auth
49027 +EOF
49028 + );
49029 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
49030 +ok($tf->handle_http($t) == 0, 'lowercase access');
49031 +
49032 +
49033 +## check that mod-staticfile exclude works
49034 +$t->{REQUEST}  = ( <<EOF
49035 +GET /image.JPG HTTP/1.0
49036 +Host: lowercase-exclude
49037 +EOF
49038 + );
49039 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
49040 +ok($tf->handle_http($t) == 0, 'upper case access to staticfile.exclude-extension');
49041 +
49042 +$t->{REQUEST}  = ( <<EOF
49043 +GET /image.jpg HTTP/1.0
49044 +Host: lowercase-exclude
49045 +EOF
49046 + );
49047 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
49048 +ok($tf->handle_http($t) == 0, 'lowercase access');
49049 +
49050 +
49051 +## check that mod-access exclude works
49052 +$t->{REQUEST}  = ( <<EOF
49053 +GET /image.JPG HTTP/1.0
49054 +Host: lowercase-deny
49055 +EOF
49056 + );
49057 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
49058 +ok($tf->handle_http($t) == 0, 'uppercase access to url.access-deny protected location');
49059 +
49060 +$t->{REQUEST}  = ( <<EOF
49061 +GET /image.jpg HTTP/1.0
49062 +Host: lowercase-deny
49063 +EOF
49064 + );
49065 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
49066 +ok($tf->handle_http($t) == 0, 'lowercase access');
49067 +
49068 +
49069 +
49070 +ok($tf->stop_proc == 0, "Stopping lighttpd");
49071 +
49072 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/mod-fastcgi.t lighttpd-1.4.12/tests/mod-fastcgi.t
49073 --- lighttpd-1.4.11/tests/mod-fastcgi.t 2006-03-09 15:30:45.000000000 +0200
49074 +++ lighttpd-1.4.12/tests/mod-fastcgi.t 2006-07-11 21:23:41.000000000 +0300
49075 @@ -7,7 +7,7 @@
49076  }
49077  
49078  use strict;
49079 -use Test::More tests => 47;
49080 +use Test::More tests => 49;
49081  use LightyTest;
49082  
49083  my $tf = LightyTest->new();
49084 @@ -15,7 +15,7 @@
49085  my $t;
49086  
49087  SKIP: {
49088 -       skip "no PHP running on port 1026", 30 unless $tf->listening_on(1026);
49089 +       skip "no PHP running on port 1026", 29 unless $tf->listening_on(1026);
49090  
49091         ok($tf->start_proc == 0, "Starting lighttpd") or die();
49092  
49093 @@ -223,7 +223,7 @@
49094  }
49095  
49096  SKIP: {
49097 -       skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php"; 
49098 +       skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php";
49099         $tf->{CONFIGFILE} = 'fastcgi-13.conf';
49100         ok($tf->start_proc == 0, "Starting lighttpd with $tf->{CONFIGFILE}") or die();
49101         $t->{REQUEST}  = ( <<EOF
49102 @@ -285,6 +285,34 @@
49103         $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'test123' } ];
49104         ok($tf->handle_http($t) == 0, 'line-ending \r\n + \r\n');
49105  
49106 +    # X-LIGHTTPD-send-file
49107 +       $t->{REQUEST}  = ( <<EOF
49108 +GET /index.fcgi?x-lighttpd-send-file HTTP/1.0
49109 +Host: www.example.org
49110 +EOF
49111 + );
49112 +       $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
49113 +' } ];
49114 +       ok($tf->handle_http($t) == 0, 'X-LIGHTTPD-send-file');
49115 +    # X-Sendfile
49116 +       $t->{REQUEST}  = ( <<EOF
49117 +GET /index.fcgi?xsendfile HTTP/1.0
49118 +Host: www.example.org
49119 +EOF
49120 + );
49121 +       $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
49122 +' } ];
49123 +       ok($tf->handle_http($t) == 0, 'X-Sendfile');
49124 +
49125 +       $t->{REQUEST}  = ( <<EOF
49126 +GET /index.fcgi?xsendfile-mixed-case HTTP/1.0
49127 +Host: www.example.org
49128 +EOF
49129 + );
49130 +       $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
49131 +' } ];
49132 +       ok($tf->handle_http($t) == 0, 'X-SeNdFiLe in mixed case');
49133 +
49134         $t->{REQUEST}  = ( <<EOF
49135  GET /index.fcgi?die-at-end HTTP/1.0
49136  Host: www.example.org
49137 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/mod-proxy.t lighttpd-1.4.12/tests/mod-proxy.t
49138 --- lighttpd-1.4.11/tests/mod-proxy.t   1970-01-01 03:00:00.000000000 +0300
49139 +++ lighttpd-1.4.12/tests/mod-proxy.t   2006-07-11 21:23:41.000000000 +0300
49140 @@ -0,0 +1,173 @@
49141 +#!/usr/bin/env perl
49142 +BEGIN {
49143 +    # add current source dir to the include-path
49144 +    # we need this for make distcheck
49145 +   (my $srcdir = $0) =~ s#/[^/]+$#/#;
49146 +   unshift @INC, $srcdir;
49147 +}
49148 +
49149 +use strict;
49150 +use IO::Socket;
49151 +use Test::More tests => 21;
49152 +use LightyTest;
49153 +
49154 +my $tf_proxy = LightyTest->new();
49155 +my $tf_backend1 = LightyTest->new();
49156 +my $tf_backend2 = LightyTest->new();
49157 +
49158 +my $t;
49159 +
49160 +## we need two procs
49161 +## 1. the real webserver
49162 +## 2. the proxy server
49163 +
49164 +$tf_proxy->{PORT} = 2048;
49165 +$tf_proxy->{CONFIGFILE} = 'proxy.conf';
49166 +$tf_proxy->{LIGHTTPD_PIDFILE} = $tf_proxy->{SRCDIR}.'/tmp/lighttpd/lighttpd-proxy.pid';
49167 +
49168 +$tf_backend1->{PORT} = 2050;
49169 +$tf_backend1->{CONFIGFILE} = 'proxy-backend-1.conf';
49170 +$tf_backend1->{LIGHTTPD_PIDFILE} = $tf_backend1->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-1.pid';
49171 +
49172 +$tf_backend2->{PORT} = 2051;
49173 +$tf_backend2->{CONFIGFILE} = 'proxy-backend-2.conf';
49174 +$tf_backend2->{LIGHTTPD_PIDFILE} = $tf_backend2->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-2.pid';
49175 +
49176 +
49177 +ok($tf_backend1->start_proc == 0, "Starting lighttpd") or die();
49178 +
49179 +ok($tf_proxy->start_proc == 0, "Starting lighttpd as proxy") or die();
49180 +
49181 +sleep(1);
49182 +
49183 +$t->{REQUEST}  = ( <<EOF
49184 +GET /index.html HTTP/1.0
49185 +Host: www.example.org
49186 +EOF
49187 + );
49188 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
49189 +ok($tf_proxy->handle_http($t) == 0, 'valid request');
49190 +
49191 +$t->{REQUEST}  = ( <<EOF
49192 +GET /index.html HTTP/1.0
49193 +Host: www.example.org
49194 +EOF
49195 + );
49196 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Server' => 'proxy-backend-1' } ];
49197 +ok($tf_proxy->handle_http($t) == 0, 'drop Server from real server');
49198 +
49199 +$t->{REQUEST}  = ( <<EOF
49200 +GET /balance-rr/foo HTTP/1.0
49201 +Host: www.example.org
49202 +EOF
49203 + );
49204 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
49205 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - one backend');
49206 +
49207 +$t->{REQUEST}  = ( <<EOF
49208 +GET /balance-rr/foo HTTP/1.0
49209 +Host: www.example.org
49210 +EOF
49211 + );
49212 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
49213 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - one host down, failover');
49214 +
49215 +$t->{REQUEST}  = ( <<EOF
49216 +GET /balance-fair/foo HTTP/1.0
49217 +Host: www.example.org
49218 +EOF
49219 + );
49220 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
49221 +ok($tf_proxy->handle_http($t) == 0, 'balance fair - one backend');
49222 +
49223 +## backend 2 starting 
49224 +ok($tf_backend2->start_proc == 0, "Starting second proxy backend") or die();
49225 +
49226 +$t->{REQUEST}  = ( <<EOF
49227 +GET /balance-rr/foo HTTP/1.0
49228 +Host: www.example.org
49229 +EOF
49230 + );
49231 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49232 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 1');
49233 +
49234 +$t->{REQUEST}  = ( <<EOF
49235 +GET /balance-rr/foo HTTP/1.0
49236 +Host: www.example.org
49237 +EOF
49238 + );
49239 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
49240 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 2');
49241 +
49242 +$t->{REQUEST}  = ( <<EOF
49243 +GET /balance-hash/foo HTTP/1.0
49244 +Host: www.example.org
49245 +EOF
49246 + );
49247 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
49248 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1');
49249 +
49250 +$t->{REQUEST}  = ( <<EOF
49251 +GET /balance-hash/foo HTTP/1.0
49252 +Host: www.example.org
49253 +EOF
49254 + );
49255 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
49256 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1 - same URL');
49257 +
49258 +$t->{REQUEST}  = ( <<EOF
49259 +GET /balance-hash/bar HTTP/1.0
49260 +Host: www.example.org
49261 +EOF
49262 + );
49263 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49264 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2');
49265 +
49266 +$t->{REQUEST}  = ( <<EOF
49267 +GET /balance-hash/bar HTTP/1.0
49268 +Host: www.example.org
49269 +EOF
49270 + );
49271 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49272 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2 - same URL');
49273 +
49274 +## backend 1 stopping, failover 
49275 +ok($tf_backend1->stop_proc == 0, "Stopping backend 1");
49276 +
49277 +$t->{REQUEST}  = ( <<EOF
49278 +GET /balance-hash/foo HTTP/1.0
49279 +Host: www.example.org
49280 +EOF
49281 + );
49282 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49283 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2');
49284 +
49285 +$t->{REQUEST}  = ( <<EOF
49286 +GET /balance-hash/bar HTTP/1.0
49287 +Host: www.example.org
49288 +EOF
49289 + );
49290 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49291 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2 - same URL');
49292 +
49293 +$t->{REQUEST}  = ( <<EOF
49294 +GET /balance-rr/foo HTTP/1.0
49295 +Host: www.example.org
49296 +EOF
49297 + );
49298 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49299 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - failover to backend 2');
49300 +
49301 +$t->{REQUEST}  = ( <<EOF
49302 +GET /balance-fair/foo HTTP/1.0
49303 +Host: www.example.org
49304 +EOF
49305 + );
49306 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
49307 +ok($tf_proxy->handle_http($t) == 0, 'balance fair - failover to backend 2');
49308 +
49309 +
49310 +ok($tf_backend2->stop_proc == 0, "Stopping lighttpd");
49311 +
49312 +ok($tf_proxy->stop_proc == 0, "Stopping lighttpd proxy");
49313 +
49314 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/proxy.conf lighttpd-1.4.12/tests/proxy.conf
49315 --- lighttpd-1.4.11/tests/proxy.conf    1970-01-01 03:00:00.000000000 +0300
49316 +++ lighttpd-1.4.12/tests/proxy.conf    2006-07-11 21:23:42.000000000 +0300
49317 @@ -0,0 +1,26 @@
49318 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
49319 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd-proxy.pid"
49320 +server.tag = "proxy"
49321 +
49322 +include "default.conf"
49323 +
49324 +## 127.0.0.1 and 127.0.0.2 are the same host
49325 +proxy.server              = ( 
49326 +  "" => (( "host" => "127.0.0.1",
49327 +          "port" => 2050 ),
49328 +         ( "host" => "127.0.0.2",
49329 +           "port" => 2051 )
49330 +  ))
49331 +               
49332 +$HTTP["url"] =~ "^/balance-rr/" {
49333 +  proxy.balance = "round-robin"
49334 +}
49335 +
49336 +$HTTP["url"] =~ "^/balance-hash/" {
49337 +  proxy.balance = "hash"
49338 +}
49339 +
49340 +$HTTP["url"] =~ "^/balance-fair/" {
49341 +  proxy.balance = "fair"
49342 +}
49343 +
49344 diff -ur -x '*.m4' -x compile -x 'config.*' -x configure -x depcomp -N -x missing -x 'ltmain*' -x install-sh -x mkinstalldirs lighttpd-1.4.11/tests/var-include.conf lighttpd-1.4.12/tests/var-include.conf
49345 --- lighttpd-1.4.11/tests/var-include.conf      2005-08-27 17:44:19.000000000 +0300
49346 +++ lighttpd-1.4.12/tests/var-include.conf      2006-07-11 21:23:41.000000000 +0300
49347 @@ -2,15 +2,15 @@
49348  debug.log-request-handling = "enable"
49349  debug.log-condition-handling = "enable"
49350  
49351 -server.document-root         = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
49352 -server.pid-file              = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
49353 +server.document-root         = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
49354 +server.pid-file              = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
49355  
49356  ## bind to port (default: 80)
49357  server.port                 = 2048
49358  
49359  ## bind to localhost (default: all interfaces)
49360  server.bind                = "localhost"
49361 -server.errorlog            = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
49362 +server.errorlog            = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
49363  server.name                = "www.example.org"
49364  server.tag                 = "Apache 1.3.29"
49365  
49366 @@ -21,19 +21,19 @@
49367  ######################## MODULE CONFIG ############################
49368  
49369  
49370 -accesslog.filename          = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
49371 +accesslog.filename          = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
49372  
49373  mimetype.assign             = ( ".html" => "text/html" )
49374  
49375  url.redirect = ("^" => "/default")
49376  
49377  $HTTP["host"] == "www.example.org" {
49378 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
49379 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
49380    server.name = "www.example.org"
49381    url.redirect = ("^" => "/redirect")
49382  }
49383  $HTTP["host"] == "test.example.org" {
49384 -  server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
49385 +  server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
49386    server.name = "test.example.org"
49387    var.myvar = "good"
49388    var.one = 1
This page took 4.531902 seconds and 4 git commands to generate.